From 17d9ddc72fb8bba0d4f67868c9c612e472a594a9 Mon Sep 17 00:00:00 2001 From: "Pallipadi, Venkatesh" Date: Wed, 10 Feb 2010 15:23:44 -0800 Subject: rbtree: Add support for augmented rbtrees Add support for augmented rbtrees in core rbtree code. This will be used in subsequent patches, in x86 PAT code, which needs interval trees to efficiently keep track of PAT ranges. Signed-off-by: Venkatesh Pallipadi LKML-Reference: <20100210232343.GA11465@linux-os.sc.intel.com> Signed-off-by: Suresh Siddha Signed-off-by: H. Peter Anvin diff --git a/Documentation/rbtree.txt b/Documentation/rbtree.txt index aae8355..221f38b 100644 --- a/Documentation/rbtree.txt +++ b/Documentation/rbtree.txt @@ -190,3 +190,61 @@ Example: for (node = rb_first(&mytree); node; node = rb_next(node)) printk("key=%s\n", rb_entry(node, struct mytype, node)->keystring); +Support for Augmented rbtrees +----------------------------- + +Augmented rbtree is an rbtree with "some" additional data stored in each node. +This data can be used to augment some new functionality to rbtree. +Augmented rbtree is an optional feature built on top of basic rbtree +infrastructure. rbtree user who wants this feature will have an augment +callback function in rb_root initialized. + +This callback function will be called from rbtree core routines whenever +a node has a change in one or both of its children. It is the responsibility +of the callback function to recalculate the additional data that is in the +rb node using new children information. Note that if this new additional +data affects the parent node's additional data, then callback function has +to handle it and do the recursive updates. + + +Interval tree is an example of augmented rb tree. Reference - +"Introduction to Algorithms" by Cormen, Leiserson, Rivest and Stein. +More details about interval trees: + +Classical rbtree has a single key and it cannot be directly used to store +interval ranges like [lo:hi] and do a quick lookup for any overlap with a new +lo:hi or to find whether there is an exact match for a new lo:hi. + +However, rbtree can be augmented to store such interval ranges in a structured +way making it possible to do efficient lookup and exact match. + +This "extra information" stored in each node is the maximum hi +(max_hi) value among all the nodes that are its descendents. This +information can be maintained at each node just be looking at the node +and its immediate children. And this will be used in O(log n) lookup +for lowest match (lowest start address among all possible matches) +with something like: + +find_lowest_match(lo, hi, node) +{ + lowest_match = NULL; + while (node) { + if (max_hi(node->left) > lo) { + // Lowest overlap if any must be on left side + node = node->left; + } else if (overlap(lo, hi, node)) { + lowest_match = node; + break; + } else if (lo > node->lo) { + // Lowest overlap if any must be on right side + node = node->right; + } else { + break; + } + } + return lowest_match; +} + +Finding exact match will be to first find lowest match and then to follow +successor nodes looking for exact match, until the start of a node is beyond +the hi value we are looking for. diff --git a/include/linux/rbtree.h b/include/linux/rbtree.h index 9c29541..8e33a25 100644 --- a/include/linux/rbtree.h +++ b/include/linux/rbtree.h @@ -110,6 +110,7 @@ struct rb_node struct rb_root { struct rb_node *rb_node; + void (*augment_cb)(struct rb_node *node); }; @@ -129,7 +130,9 @@ static inline void rb_set_color(struct rb_node *rb, int color) rb->rb_parent_color = (rb->rb_parent_color & ~1) | color; } -#define RB_ROOT (struct rb_root) { NULL, } +#define RB_ROOT (struct rb_root) { NULL, NULL, } +#define RB_AUGMENT_ROOT(x) (struct rb_root) { NULL, x} + #define rb_entry(ptr, type, member) container_of(ptr, type, member) #define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL) diff --git a/lib/rbtree.c b/lib/rbtree.c index e2aa3be..15e10b1 100644 --- a/lib/rbtree.c +++ b/lib/rbtree.c @@ -44,6 +44,11 @@ static void __rb_rotate_left(struct rb_node *node, struct rb_root *root) else root->rb_node = right; rb_set_parent(node, right); + + if (root->augment_cb) { + root->augment_cb(node); + root->augment_cb(right); + } } static void __rb_rotate_right(struct rb_node *node, struct rb_root *root) @@ -67,12 +72,20 @@ static void __rb_rotate_right(struct rb_node *node, struct rb_root *root) else root->rb_node = left; rb_set_parent(node, left); + + if (root->augment_cb) { + root->augment_cb(node); + root->augment_cb(left); + } } void rb_insert_color(struct rb_node *node, struct rb_root *root) { struct rb_node *parent, *gparent; + if (root->augment_cb) + root->augment_cb(node); + while ((parent = rb_parent(node)) && rb_is_red(parent)) { gparent = rb_parent(parent); @@ -227,12 +240,15 @@ void rb_erase(struct rb_node *node, struct rb_root *root) else { struct rb_node *old = node, *left; + int old_parent_cb = 0; + int successor_parent_cb = 0; node = node->rb_right; while ((left = node->rb_left) != NULL) node = left; if (rb_parent(old)) { + old_parent_cb = 1; if (rb_parent(old)->rb_left == old) rb_parent(old)->rb_left = node; else @@ -247,8 +263,10 @@ void rb_erase(struct rb_node *node, struct rb_root *root) if (parent == old) { parent = node; } else { + successor_parent_cb = 1; if (child) rb_set_parent(child, parent); + parent->rb_left = child; node->rb_right = old->rb_right; @@ -259,6 +277,24 @@ void rb_erase(struct rb_node *node, struct rb_root *root) node->rb_left = old->rb_left; rb_set_parent(old->rb_left, node); + if (root->augment_cb) { + /* + * Here, three different nodes can have new children. + * The parent of the successor node that was selected + * to replace the node to be erased. + * The node that is getting erased and is now replaced + * by its successor. + * The parent of the node getting erased-replaced. + */ + if (successor_parent_cb) + root->augment_cb(parent); + + root->augment_cb(node); + + if (old_parent_cb) + root->augment_cb(rb_parent(old)); + } + goto color; } @@ -267,15 +303,19 @@ void rb_erase(struct rb_node *node, struct rb_root *root) if (child) rb_set_parent(child, parent); - if (parent) - { + + if (parent) { if (parent->rb_left == node) parent->rb_left = child; else parent->rb_right = child; - } - else + + if (root->augment_cb) + root->augment_cb(parent); + + } else { root->rb_node = child; + } color: if (color == RB_BLACK) -- cgit v0.10.2 From be5a0c126ad1dea2128dc5aef12c87083518d1ab Mon Sep 17 00:00:00 2001 From: "venkatesh.pallipadi@intel.com" Date: Wed, 10 Feb 2010 11:57:06 -0800 Subject: 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 LKML-Reference: <20100210195909.792781000@intel.com> Signed-off-by: Suresh Siddha Signed-off-by: H. Peter Anvin diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index ae9648e..628e507 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c @@ -30,6 +30,8 @@ #include #include +#include "pat_internal.h" + #ifdef CONFIG_X86_PAT int __read_mostly pat_enabled = 1; @@ -53,19 +55,15 @@ static inline void pat_disable(const char *reason) #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 { @@ -132,17 +130,6 @@ void pat_init(void) #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 @@ -159,14 +146,6 @@ static char *cattr_name(unsigned long flags) * 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 */ @@ -349,6 +328,64 @@ static int free_ram_pages_type(u64 start, u64 end) 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 @@ -364,9 +401,8 @@ static int free_ram_pages_type(u64 start, u64 end) 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; @@ -423,42 +459,7 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type, 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", @@ -469,13 +470,6 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type, 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", @@ -937,28 +931,40 @@ EXPORT_SYMBOL_GPL(pgprot_writecombine); #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) diff --git a/arch/x86/mm/pat_internal.h b/arch/x86/mm/pat_internal.h new file mode 100644 index 0000000..6c98780 --- /dev/null +++ b/arch/x86/mm/pat_internal.h @@ -0,0 +1,28 @@ +#ifndef __PAT_INTERNAL_H_ +#define __PAT_INTERNAL_H_ + +extern int pat_debug_enable; + +#define dprintk(fmt, arg...) \ + do { if (pat_debug_enable) printk(KERN_INFO fmt, ##arg); } while (0) + +struct memtype { + u64 start; + u64 end; + unsigned long type; + struct list_head nd; + struct rb_node rb; +}; + +static inline 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"; + } +} + +#endif /* __PAT_INTERNAL_H_ */ -- cgit v0.10.2 From 9e41a49aab88a5a6c8f4875bf10a5543bc321f2d Mon Sep 17 00:00:00 2001 From: "Pallipadi, Venkatesh" Date: Wed, 10 Feb 2010 15:26:07 -0800 Subject: x86, pat: Migrate to rbtree only backend for pat memtype management Move pat backend to fully rbtree based implementation from the existing rbtree and linked list hybrid. New rbtree based solution uses interval trees (augmented rbtrees) in order to store the PAT ranges. The new code seprates out the pat backend to pat_rbtree.c file, making is cleaner. The change also makes the PAT lookup, reserve and free operations more optimal, as we don't have to traverse linear linked list of few tens of entries in normal case. Signed-off-by: Venkatesh Pallipadi LKML-Reference: <20100210232607.GB11465@linux-os.sc.intel.com> Signed-off-by: Suresh Siddha Signed-off-by: H. Peter Anvin diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile index 06630d2..a4c7683 100644 --- a/arch/x86/mm/Makefile +++ b/arch/x86/mm/Makefile @@ -6,6 +6,7 @@ nostackp := $(call cc-option, -fno-stack-protector) CFLAGS_physaddr.o := $(nostackp) CFLAGS_setup_nx.o := $(nostackp) +obj-$(CONFIG_X86_PAT) += pat_rbtree.o obj-$(CONFIG_SMP) += tlb.o obj-$(CONFIG_X86_32) += pgtable_32.o iomap_32.o diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index 628e507..9510111 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c @@ -130,65 +130,7 @@ void pat_init(void) #undef PAT -/* - * The global memtype list keeps track of memory type for specific - * physical memory areas. Conflicting memory types in different - * mappings can cause CPU cache corruption. To avoid this we keep track. - * - * The list is sorted based on starting address and can contain multiple - * entries for each address (this allows reference counting for overlapping - * areas). All the aliases have the same cache attributes of course. - * Zero attributes are represented as holes. - * - * The data structure is a list that is also organized as an rbtree - * sorted on the start address of memtype range. - * - * memtype_lock protects both the linear list and rbtree. - */ - -static struct rb_root memtype_rbroot = RB_ROOT; -static LIST_HEAD(memtype_list); -static DEFINE_SPINLOCK(memtype_lock); /* protects memtype list */ - -static struct memtype *memtype_rb_search(struct rb_root *root, u64 start) -{ - struct rb_node *node = root->rb_node; - struct memtype *last_lower = NULL; - - while (node) { - struct memtype *data = container_of(node, struct memtype, rb); - - if (data->start < start) { - last_lower = data; - node = node->rb_right; - } else if (data->start > start) { - node = node->rb_left; - } else - return data; - } - - /* Will return NULL if there is no entry with its start <= start */ - return last_lower; -} - -static void memtype_rb_insert(struct rb_root *root, struct memtype *data) -{ - struct rb_node **new = &(root->rb_node); - struct rb_node *parent = NULL; - - while (*new) { - struct memtype *this = container_of(*new, struct memtype, rb); - - parent = *new; - if (data->start <= this->start) - new = &((*new)->rb_left); - else if (data->start > this->start) - new = &((*new)->rb_right); - } - - rb_link_node(&data->rb, parent, new); - rb_insert_color(&data->rb, root); -} +static DEFINE_SPINLOCK(memtype_lock); /* protects memtype accesses */ /* * Does intersection of PAT memory type and MTRR memory type and returns @@ -216,33 +158,6 @@ static unsigned long pat_x_mtrr_type(u64 start, u64 end, unsigned long req_type) return req_type; } -static int -chk_conflict(struct memtype *new, struct memtype *entry, unsigned long *type) -{ - if (new->type != entry->type) { - if (type) { - new->type = entry->type; - *type = entry->type; - } else - goto conflict; - } - - /* check overlaps with more than one entry in the list */ - list_for_each_entry_continue(entry, &memtype_list, nd) { - if (new->end <= entry->start) - break; - else if (new->type != entry->type) - goto conflict; - } - return 0; - - conflict: - printk(KERN_INFO "%s:%d conflicting memory types " - "%Lx-%Lx %s<->%s\n", current->comm, current->pid, new->start, - new->end, cattr_name(new->type), cattr_name(entry->type)); - return -EBUSY; -} - static int pat_pagerange_is_ram(unsigned long start, unsigned long end) { int ram_page = 0, not_rampage = 0; @@ -328,64 +243,6 @@ static int free_ram_pages_type(u64 start, u64 end) 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 @@ -459,7 +316,7 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type, spin_lock(&memtype_lock); - err = memtype_check_insert(new, new_type); + err = rbt_memtype_check_insert(new, new_type); if (err) { printk(KERN_INFO "reserve_memtype failed 0x%Lx-0x%Lx, " "track %s, req %s\n", @@ -481,7 +338,6 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type, int free_memtype(u64 start, u64 end) { - struct memtype *entry, *saved_entry; int err = -EINVAL; int is_range_ram; @@ -505,46 +361,7 @@ int free_memtype(u64 start, u64 end) } spin_lock(&memtype_lock); - - entry = memtype_rb_search(&memtype_rbroot, start); - if (unlikely(entry == NULL)) - goto unlock_ret; - - /* - * Saved entry points to an entry with start same or less than what - * we searched for. Now go through the list in both directions to look - * for the entry that matches with both start and end, with list stored - * in sorted start address - */ - saved_entry = entry; - list_for_each_entry_from(entry, &memtype_list, nd) { - if (entry->start == start && entry->end == end) { - rb_erase(&entry->rb, &memtype_rbroot); - list_del(&entry->nd); - kfree(entry); - err = 0; - break; - } else if (entry->start > start) { - break; - } - } - - if (!err) - goto unlock_ret; - - entry = saved_entry; - list_for_each_entry_reverse(entry, &memtype_list, nd) { - if (entry->start == start && entry->end == end) { - rb_erase(&entry->rb, &memtype_rbroot); - list_del(&entry->nd); - kfree(entry); - err = 0; - break; - } else if (entry->start < start) { - break; - } - } -unlock_ret: + err = rbt_memtype_erase(start, end); spin_unlock(&memtype_lock); if (err) { @@ -593,7 +410,7 @@ static unsigned long lookup_memtype(u64 paddr) spin_lock(&memtype_lock); - entry = memtype_rb_search(&memtype_rbroot, paddr); + entry = rbt_memtype_lookup(paddr); if (entry != NULL) rettype = entry->type; else @@ -930,22 +747,6 @@ EXPORT_SYMBOL_GPL(pgprot_writecombine); #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_X86_PAT) -/* get Nth element of the linked list */ -static int copy_memtype_nth_element(struct memtype *out, loff_t pos) -{ - struct memtype *list_node; - int i = 1; - - list_for_each_entry(list_node, &memtype_list, nd) { - if (pos == i) { - *out = *list_node; - return 0; - } - ++i; - } - return 1; -} - static struct memtype *memtype_get_idx(loff_t pos) { struct memtype *print_entry; @@ -956,7 +757,7 @@ static struct memtype *memtype_get_idx(loff_t pos) return NULL; spin_lock(&memtype_lock); - ret = copy_memtype_nth_element(print_entry, pos); + ret = rbt_memtype_copy_nth_element(print_entry, pos); spin_unlock(&memtype_lock); if (!ret) { diff --git a/arch/x86/mm/pat_internal.h b/arch/x86/mm/pat_internal.h index 6c98780..4f39eef 100644 --- a/arch/x86/mm/pat_internal.h +++ b/arch/x86/mm/pat_internal.h @@ -9,8 +9,8 @@ extern int pat_debug_enable; struct memtype { u64 start; u64 end; + u64 subtree_max_end; unsigned long type; - struct list_head nd; struct rb_node rb; }; @@ -25,4 +25,22 @@ static inline char *cattr_name(unsigned long flags) } } +#ifdef CONFIG_X86_PAT +extern int rbt_memtype_check_insert(struct memtype *new, + unsigned long *new_type); +extern int rbt_memtype_erase(u64 start, u64 end); +extern struct memtype *rbt_memtype_lookup(u64 addr); +extern int rbt_memtype_copy_nth_element(struct memtype *out, loff_t pos); +#else +static inline int rbt_memtype_check_insert(struct memtype *new, + unsigned long *new_type) +{ return 0; } +static inline int rbt_memtype_erase(u64 start, u64 end) +{ return 0; } +static inline struct memtype *rbt_memtype_lookup(u64 addr) +{ return NULL; } +static inline int rbt_memtype_copy_nth_element(struct memtype *out, loff_t pos) +{ return 0; } +#endif + #endif /* __PAT_INTERNAL_H_ */ diff --git a/arch/x86/mm/pat_rbtree.c b/arch/x86/mm/pat_rbtree.c new file mode 100644 index 0000000..9063f40 --- /dev/null +++ b/arch/x86/mm/pat_rbtree.c @@ -0,0 +1,271 @@ +/* + * Handle caching attributes in page tables (PAT) + * + * Authors: Venkatesh Pallipadi + * Suresh B Siddha + * + * Interval tree (augmented rbtree) used to store the PAT memory type + * reservations. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "pat_internal.h" + +/* + * The memtype tree keeps track of memory type for specific + * physical memory areas. Without proper tracking, conflicting memory + * types in different mappings can cause CPU cache corruption. + * + * The tree is an interval tree (augmented rbtree) with tree ordered + * on starting address. Tree can contain multiple entries for + * different regions which overlap. All the aliases have the same + * cache attributes of course. + * + * memtype_lock protects the rbtree. + */ + +static void memtype_rb_augment_cb(struct rb_node *node); +static struct rb_root memtype_rbroot = RB_AUGMENT_ROOT(&memtype_rb_augment_cb); + +static int is_node_overlap(struct memtype *node, u64 start, u64 end) +{ + if (node->start >= end || node->end <= start) + return 0; + + return 1; +} + +static u64 get_subtree_max_end(struct rb_node *node) +{ + u64 ret = 0; + if (node) { + struct memtype *data = container_of(node, struct memtype, rb); + ret = data->subtree_max_end; + } + return ret; +} + +/* Update 'subtree_max_end' for a node, based on node and its children */ +static void update_node_max_end(struct rb_node *node) +{ + struct memtype *data; + u64 max_end, child_max_end; + + if (!node) + return; + + data = container_of(node, struct memtype, rb); + max_end = data->end; + + child_max_end = get_subtree_max_end(node->rb_right); + if (child_max_end > max_end) + max_end = child_max_end; + + child_max_end = get_subtree_max_end(node->rb_left); + if (child_max_end > max_end) + max_end = child_max_end; + + data->subtree_max_end = max_end; +} + +/* Update 'subtree_max_end' for a node and all its ancestors */ +static void update_path_max_end(struct rb_node *node) +{ + u64 old_max_end, new_max_end; + + while (node) { + struct memtype *data = container_of(node, struct memtype, rb); + + old_max_end = data->subtree_max_end; + update_node_max_end(node); + new_max_end = data->subtree_max_end; + + if (new_max_end == old_max_end) + break; + + node = rb_parent(node); + } +} + +/* Find the first (lowest start addr) overlapping range from rb tree */ +static struct memtype *memtype_rb_lowest_match(struct rb_root *root, + u64 start, u64 end) +{ + struct rb_node *node = root->rb_node; + struct memtype *last_lower = NULL; + + while (node) { + struct memtype *data = container_of(node, struct memtype, rb); + + if (get_subtree_max_end(node->rb_left) > start) { + /* Lowest overlap if any must be on left side */ + node = node->rb_left; + } else if (is_node_overlap(data, start, end)) { + last_lower = data; + break; + } else if (start >= data->start) { + /* Lowest overlap if any must be on right side */ + node = node->rb_right; + } else { + break; + } + } + return last_lower; /* Returns NULL if there is no overlap */ +} + +static struct memtype *memtype_rb_exact_match(struct rb_root *root, + u64 start, u64 end) +{ + struct memtype *match; + + match = memtype_rb_lowest_match(root, start, end); + while (match != NULL && match->start < end) { + struct rb_node *node; + + if (match->start == start && match->end == end) + return match; + + node = rb_next(&match->rb); + if (node) + match = container_of(node, struct memtype, rb); + else + match = NULL; + } + + return NULL; /* Returns NULL if there is no exact match */ +} + +static int memtype_rb_check_conflict(struct rb_root *root, + u64 start, u64 end, + unsigned long reqtype, unsigned long *newtype) +{ + struct rb_node *node; + struct memtype *match; + int found_type = reqtype; + + match = memtype_rb_lowest_match(&memtype_rbroot, start, end); + if (match == NULL) + goto success; + + if (match->type != found_type && newtype == NULL) + goto failure; + + dprintk("Overlap at 0x%Lx-0x%Lx\n", match->start, match->end); + found_type = match->type; + + node = rb_next(&match->rb); + while (node) { + match = container_of(node, struct memtype, rb); + + if (match->start >= end) /* Checked all possible matches */ + goto success; + + if (is_node_overlap(match, start, end) && + match->type != found_type) { + goto failure; + } + + node = rb_next(&match->rb); + } +success: + if (newtype) + *newtype = found_type; + + return 0; + +failure: + printk(KERN_INFO "%s:%d conflicting memory types " + "%Lx-%Lx %s<->%s\n", current->comm, current->pid, start, + end, cattr_name(found_type), cattr_name(match->type)); + return -EBUSY; +} + +static void memtype_rb_augment_cb(struct rb_node *node) +{ + if (node) + update_path_max_end(node); +} + +static void memtype_rb_insert(struct rb_root *root, struct memtype *newdata) +{ + struct rb_node **node = &(root->rb_node); + struct rb_node *parent = NULL; + + while (*node) { + struct memtype *data = container_of(*node, struct memtype, rb); + + parent = *node; + if (newdata->start <= data->start) + node = &((*node)->rb_left); + else if (newdata->start > data->start) + node = &((*node)->rb_right); + } + + rb_link_node(&newdata->rb, parent, node); + rb_insert_color(&newdata->rb, root); +} + +int rbt_memtype_check_insert(struct memtype *new, unsigned long *ret_type) +{ + int err = 0; + + err = memtype_rb_check_conflict(&memtype_rbroot, new->start, new->end, + new->type, ret_type); + + if (!err) { + new->type = *ret_type; + memtype_rb_insert(&memtype_rbroot, new); + } + return err; +} + +int rbt_memtype_erase(u64 start, u64 end) +{ + struct memtype *data; + + data = memtype_rb_exact_match(&memtype_rbroot, start, end); + if (!data) + return -EINVAL; + + rb_erase(&data->rb, &memtype_rbroot); + return 0; +} + +struct memtype *rbt_memtype_lookup(u64 addr) +{ + struct memtype *data; + data = memtype_rb_lowest_match(&memtype_rbroot, addr, addr + PAGE_SIZE); + return data; +} + +#if defined(CONFIG_DEBUG_FS) +int rbt_memtype_copy_nth_element(struct memtype *out, loff_t pos) +{ + struct rb_node *node; + int i = 1; + + node = rb_first(&memtype_rbroot); + while (node && pos != i) { + node = rb_next(node); + i++; + } + + if (node) { /* pos == i */ + struct memtype *this = container_of(node, struct memtype, rb); + *out = *this; + return 0; + } else { + return 1; + } +} +#endif -- cgit v0.10.2 From b3ac891b67bd4b1fc728d1c784cad1212dea433d Mon Sep 17 00:00:00 2001 From: Luca Barbieri Date: Wed, 24 Feb 2010 10:54:22 +0100 Subject: x86: Add support for lock prefix in alternatives The current lock prefix UP/SMP alternative code doesn't allow LOCK_PREFIX to be used in alternatives code. This patch solves the problem by adding a new LOCK_PREFIX_ALTERNATIVE_PATCH macro that only records the lock prefix location but does not emit the prefix. The user of this macro can then start any alternative sequence with "lock" and have it UP/SMP patched. To make this work, the UP/SMP alternative code is changed to do the lock/DS prefix switching only if the byte actually contains a lock or DS prefix. Thus, if an alternative without the "lock" is selected, it will now do nothing instead of clobbering the code. Changes in v2: - Naming change - Change label to not conflict with alternatives Signed-off-by: Luca Barbieri LKML-Reference: <1267005265-27958-2-git-send-email-luca@luca-barbieri.com> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h index 3b5b828..55fee12 100644 --- a/arch/x86/include/asm/alternative.h +++ b/arch/x86/include/asm/alternative.h @@ -28,12 +28,14 @@ */ #ifdef CONFIG_SMP -#define LOCK_PREFIX \ +#define LOCK_PREFIX_HERE \ ".section .smp_locks,\"a\"\n" \ _ASM_ALIGN "\n" \ - _ASM_PTR "661f\n" /* address */ \ + _ASM_PTR "671f\n" /* address */ \ ".previous\n" \ - "661:\n\tlock; " + "671:" + +#define LOCK_PREFIX LOCK_PREFIX_HERE "\n\tlock; " #else /* ! CONFIG_SMP */ #define LOCK_PREFIX "" diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index 2589ea4..80b222e 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -244,7 +244,8 @@ static void alternatives_smp_lock(u8 **start, u8 **end, u8 *text, u8 *text_end) if (*ptr > text_end) continue; /* turn DS segment override prefix into lock prefix */ - text_poke(*ptr, ((unsigned char []){0xf0}), 1); + if (**ptr == 0x3e) + text_poke(*ptr, ((unsigned char []){0xf0}), 1); }; mutex_unlock(&text_mutex); } @@ -263,7 +264,8 @@ static void alternatives_smp_unlock(u8 **start, u8 **end, u8 *text, u8 *text_end if (*ptr > text_end) continue; /* turn lock prefix into DS segment override prefix */ - text_poke(*ptr, ((unsigned char []){0x3E}), 1); + if (**ptr == 0xf0) + text_poke(*ptr, ((unsigned char []){0x3E}), 1); }; mutex_unlock(&text_mutex); } -- cgit v0.10.2 From 9c76b38476b18c45f97098a10b0176b321eba3ea Mon Sep 17 00:00:00 2001 From: Luca Barbieri Date: Wed, 24 Feb 2010 10:54:23 +0100 Subject: x86-32: Allow UP/SMP lock replacement in cmpxchg64 Use the functionality just introduced in the previous patch: mark the lock prefixes in cmpxchg64 alternatives for UP removal. Changes in v2: - Naming change Signed-off-by: Luca Barbieri LKML-Reference: <1267005265-27958-3-git-send-email-luca@luca-barbieri.com> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/include/asm/cmpxchg_32.h b/arch/x86/include/asm/cmpxchg_32.h index ffb9bb6..8859e12 100644 --- a/arch/x86/include/asm/cmpxchg_32.h +++ b/arch/x86/include/asm/cmpxchg_32.h @@ -271,7 +271,8 @@ extern unsigned long long cmpxchg_486_u64(volatile void *, u64, u64); __typeof__(*(ptr)) __ret; \ __typeof__(*(ptr)) __old = (o); \ __typeof__(*(ptr)) __new = (n); \ - alternative_io("call cmpxchg8b_emu", \ + alternative_io(LOCK_PREFIX_HERE \ + "call cmpxchg8b_emu", \ "lock; cmpxchg8b (%%esi)" , \ X86_FEATURE_CX8, \ "=A" (__ret), \ -- cgit v0.10.2 From 86a8938078a8bb518c5376de493e348c7490d506 Mon Sep 17 00:00:00 2001 From: Luca Barbieri Date: Wed, 24 Feb 2010 10:54:24 +0100 Subject: lib: Add self-test for atomic64_t This patch adds self-test on boot code for atomic64_t. This has been used to test the later changes in this patchset. Signed-off-by: Luca Barbieri LKML-Reference: <1267005265-27958-4-git-send-email-luca@luca-barbieri.com> Signed-off-by: H. Peter Anvin diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 25c3ed5..3676c51 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1054,6 +1054,13 @@ config DMA_API_DEBUG This option causes a performance degredation. Use only if you want to debug device drivers. If unsure, say N. +config ATOMIC64_SELFTEST + bool "Perform an atomic64_t self-test at boot" + help + Enable this option to test the atomic64_t functions at boot. + + If unsure, say N. + source "samples/Kconfig" source "lib/Kconfig.kgdb" diff --git a/lib/Makefile b/lib/Makefile index 347ad8d..4af4786 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -99,6 +99,8 @@ obj-$(CONFIG_GENERIC_CSUM) += checksum.o obj-$(CONFIG_GENERIC_ATOMIC64) += atomic64.o +obj-$(CONFIG_ATOMIC64_SELFTEST) += atomic64_test.o + hostprogs-y := gen_crc32table clean-files := crc32table.h diff --git a/lib/atomic64_test.c b/lib/atomic64_test.c new file mode 100644 index 0000000..4ff649e --- /dev/null +++ b/lib/atomic64_test.c @@ -0,0 +1,158 @@ +/* + * Testsuite for atomic64_t functions + * + * Copyright © 2010 Luca Barbieri + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ +#include +#include + +#define INIT(c) do { atomic64_set(&v, c); r = c; } while (0) +static __init int test_atomic64(void) +{ + long long v0 = 0xaaa31337c001d00dLL; + long long v1 = 0xdeadbeefdeafcafeLL; + long long v2 = 0xfaceabadf00df001LL; + long long onestwos = 0x1111111122222222LL; + long long one = 1LL; + + atomic64_t v = ATOMIC64_INIT(v0); + long long r = v0; + BUG_ON(v.counter != r); + + atomic64_set(&v, v1); + r = v1; + BUG_ON(v.counter != r); + BUG_ON(atomic64_read(&v) != r); + + INIT(v0); + atomic64_add(onestwos, &v); + r += onestwos; + BUG_ON(v.counter != r); + + INIT(v0); + atomic64_add(-one, &v); + r += -one; + BUG_ON(v.counter != r); + + INIT(v0); + r += onestwos; + BUG_ON(atomic64_add_return(onestwos, &v) != r); + BUG_ON(v.counter != r); + + INIT(v0); + r += -one; + BUG_ON(atomic64_add_return(-one, &v) != r); + BUG_ON(v.counter != r); + + INIT(v0); + atomic64_sub(onestwos, &v); + r -= onestwos; + BUG_ON(v.counter != r); + + INIT(v0); + atomic64_sub(-one, &v); + r -= -one; + BUG_ON(v.counter != r); + + INIT(v0); + r -= onestwos; + BUG_ON(atomic64_sub_return(onestwos, &v) != r); + BUG_ON(v.counter != r); + + INIT(v0); + r -= -one; + BUG_ON(atomic64_sub_return(-one, &v) != r); + BUG_ON(v.counter != r); + + INIT(v0); + atomic64_inc(&v); + r += one; + BUG_ON(v.counter != r); + + INIT(v0); + r += one; + BUG_ON(atomic64_inc_return(&v) != r); + BUG_ON(v.counter != r); + + INIT(v0); + atomic64_dec(&v); + r -= one; + BUG_ON(v.counter != r); + + INIT(v0); + r -= one; + BUG_ON(atomic64_dec_return(&v) != r); + BUG_ON(v.counter != r); + + INIT(v0); + BUG_ON(atomic64_xchg(&v, v1) != v0); + r = v1; + BUG_ON(v.counter != r); + + INIT(v0); + BUG_ON(atomic64_cmpxchg(&v, v0, v1) != v0); + r = v1; + BUG_ON(v.counter != r); + + INIT(v0); + BUG_ON(atomic64_cmpxchg(&v, v2, v1) != v0); + BUG_ON(v.counter != r); + + INIT(v0); + BUG_ON(!atomic64_add_unless(&v, one, v0)); + BUG_ON(v.counter != r); + + INIT(v0); + BUG_ON(atomic64_add_unless(&v, one, v1)); + r += one; + BUG_ON(v.counter != r); + + INIT(onestwos); + BUG_ON(atomic64_dec_if_positive(&v) != (onestwos - 1)); + r -= one; + BUG_ON(v.counter != r); + + INIT(0); + BUG_ON(atomic64_dec_if_positive(&v) != -one); + BUG_ON(v.counter != r); + + INIT(-one); + BUG_ON(atomic64_dec_if_positive(&v) != (-one - one)); + BUG_ON(v.counter != r); + + INIT(onestwos); + BUG_ON(atomic64_inc_not_zero(&v)); + r += one; + BUG_ON(v.counter != r); + + INIT(0); + BUG_ON(!atomic64_inc_not_zero(&v)); + BUG_ON(v.counter != r); + + INIT(-one); + BUG_ON(atomic64_inc_not_zero(&v)); + r += one; + BUG_ON(v.counter != r); + +#ifdef CONFIG_X86 + printk(KERN_INFO "atomic64 test passed for %s+ platform %s CX8 and %s SSE\n", +#ifdef CONFIG_X86_CMPXCHG64 + "586", +#else + "386", +#endif + boot_cpu_has(X86_FEATURE_CX8) ? "with" : "without", + boot_cpu_has(X86_FEATURE_XMM) ? "with" : "without"); +#else + printk(KERN_INFO "atomic64 test passed\n"); +#endif + + return 0; +} + +core_initcall(test_atomic64); -- cgit v0.10.2 From a7e926abc3adfbd2e5e20d2b46177adb4e313915 Mon Sep 17 00:00:00 2001 From: Luca Barbieri Date: Wed, 24 Feb 2010 10:54:25 +0100 Subject: x86-32: Rewrite 32-bit atomic64 functions in assembly This patch replaces atomic64_32.c with two assembly implementations, one for 386/486 machines using pushf/cli/popf and one for 586+ machines using cmpxchg8b. The cmpxchg8b implementation provides the following advantages over the current one: 1. Implements atomic64_add_unless, atomic64_dec_if_positive and atomic64_inc_not_zero 2. Uses the ZF flag changed by cmpxchg8b instead of doing a comparison 3. Uses custom register calling conventions that reduce or eliminate register moves to suit cmpxchg8b 4. Reads the initial value instead of using cmpxchg8b to do that. Currently we use lock xaddl and movl, which seems the fastest. 5. Does not use the lock prefix for atomic64_set 64-bit writes are already atomic, so we don't need that. We still need it for atomic64_read to avoid restoring a value changed in the meantime. 6. Allocates registers as well or better than gcc The 386 implementation provides support for 386 and 486 machines. 386/486 SMP is not supported (we dropped it), but such support can be added easily if desired. A pure assembly implementation is required due to the custom calling conventions, and desire to use %ebp in atomic64_add_return (we need 7 registers...), as well as the ability to use pushf/popf in the 386 code without an intermediate pop/push. The parameter names are changed to match the convention in atomic_64.h Changes in v3 (due to rebasing to tip/x86/asm): - Patches atomic64_32.h instead of atomic_32.h - Uses the CALL alternative mechanism from commit 1b1d9258181bae199dc940f4bd0298126b9a73d9 Changes in v2: - Merged 386 and cx8 support in the same patch - 386 support now done in assembly, C code no longer used at all - cmpxchg64 is used for atomic64_cmpxchg - stop using macros, use one-line inline functions instead - miscellanous changes and improvements Signed-off-by: Luca Barbieri LKML-Reference: <1267005265-27958-5-git-send-email-luca@luca-barbieri.com> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/include/asm/atomic64_32.h b/arch/x86/include/asm/atomic64_32.h index 03027bf..2a934aa 100644 --- a/arch/x86/include/asm/atomic64_32.h +++ b/arch/x86/include/asm/atomic64_32.h @@ -14,109 +14,193 @@ typedef struct { #define ATOMIC64_INIT(val) { (val) } -extern u64 atomic64_cmpxchg(atomic64_t *ptr, u64 old_val, u64 new_val); +#ifdef CONFIG_X86_CMPXCHG64 +#define ATOMIC64_ALTERNATIVE_(f, g) "call atomic64_" #g "_cx8" +#else +#define ATOMIC64_ALTERNATIVE_(f, g) ALTERNATIVE("call atomic64_" #f "_386", "call atomic64_" #g "_cx8", X86_FEATURE_CX8) +#endif + +#define ATOMIC64_ALTERNATIVE(f) ATOMIC64_ALTERNATIVE_(f, f) + +/** + * atomic64_cmpxchg - cmpxchg atomic64 variable + * @p: pointer to type atomic64_t + * @o: expected value + * @n: new value + * + * Atomically sets @v to @n if it was equal to @o and returns + * the old value. + */ + +static inline long long atomic64_cmpxchg(atomic64_t *v, long long o, long long n) +{ + return cmpxchg64(&v->counter, o, n); +} /** * atomic64_xchg - xchg atomic64 variable - * @ptr: pointer to type atomic64_t - * @new_val: value to assign + * @v: pointer to type atomic64_t + * @n: value to assign * - * Atomically xchgs the value of @ptr to @new_val and returns + * Atomically xchgs the value of @v to @n and returns * the old value. */ -extern u64 atomic64_xchg(atomic64_t *ptr, u64 new_val); +static inline long long atomic64_xchg(atomic64_t *v, long long n) +{ + long long o; + unsigned high = (unsigned)(n >> 32); + unsigned low = (unsigned)n; + asm volatile(ATOMIC64_ALTERNATIVE(xchg) + : "=A" (o), "+b" (low), "+c" (high) + : "S" (v) + : "memory" + ); + return o; +} /** * atomic64_set - set atomic64 variable - * @ptr: pointer to type atomic64_t - * @new_val: value to assign + * @v: pointer to type atomic64_t + * @n: value to assign * - * Atomically sets the value of @ptr to @new_val. + * Atomically sets the value of @v to @n. */ -extern void atomic64_set(atomic64_t *ptr, u64 new_val); +static inline void atomic64_set(atomic64_t *v, long long i) +{ + unsigned high = (unsigned)(i >> 32); + unsigned low = (unsigned)i; + asm volatile(ATOMIC64_ALTERNATIVE(set) + : "+b" (low), "+c" (high) + : "S" (v) + : "eax", "edx", "memory" + ); +} /** * atomic64_read - read atomic64 variable - * @ptr: pointer to type atomic64_t + * @v: pointer to type atomic64_t * - * Atomically reads the value of @ptr and returns it. + * Atomically reads the value of @v and returns it. */ -static inline u64 atomic64_read(atomic64_t *ptr) +static inline long long atomic64_read(atomic64_t *v) { - u64 res; - - /* - * Note, we inline this atomic64_t primitive because - * it only clobbers EAX/EDX and leaves the others - * untouched. We also (somewhat subtly) rely on the - * fact that cmpxchg8b returns the current 64-bit value - * of the memory location we are touching: - */ - asm volatile( - "mov %%ebx, %%eax\n\t" - "mov %%ecx, %%edx\n\t" - LOCK_PREFIX "cmpxchg8b %1\n" - : "=&A" (res) - : "m" (*ptr) - ); - - return res; -} - -extern u64 atomic64_read(atomic64_t *ptr); + long long r; + asm volatile(ATOMIC64_ALTERNATIVE(read) + : "=A" (r), "+c" (v) + : : "memory" + ); + return r; + } /** * atomic64_add_return - add and return - * @delta: integer value to add - * @ptr: pointer to type atomic64_t + * @i: integer value to add + * @v: pointer to type atomic64_t * - * Atomically adds @delta to @ptr and returns @delta + *@ptr + * Atomically adds @i to @v and returns @i + *@v */ -extern u64 atomic64_add_return(u64 delta, atomic64_t *ptr); +static inline long long atomic64_add_return(long long i, atomic64_t *v) +{ + asm volatile(ATOMIC64_ALTERNATIVE(add_return) + : "+A" (i), "+c" (v) + : : "memory" + ); + return i; +} /* * Other variants with different arithmetic operators: */ -extern u64 atomic64_sub_return(u64 delta, atomic64_t *ptr); -extern u64 atomic64_inc_return(atomic64_t *ptr); -extern u64 atomic64_dec_return(atomic64_t *ptr); +static inline long long atomic64_sub_return(long long i, atomic64_t *v) +{ + asm volatile(ATOMIC64_ALTERNATIVE(sub_return) + : "+A" (i), "+c" (v) + : : "memory" + ); + return i; +} + +static inline long long atomic64_inc_return(atomic64_t *v) +{ + long long a; + asm volatile(ATOMIC64_ALTERNATIVE(inc_return) + : "=A" (a) + : "S" (v) + : "memory", "ecx" + ); + return a; +} + +static inline long long atomic64_dec_return(atomic64_t *v) +{ + long long a; + asm volatile(ATOMIC64_ALTERNATIVE(dec_return) + : "=A" (a) + : "S" (v) + : "memory", "ecx" + ); + return a; +} /** * atomic64_add - add integer to atomic64 variable - * @delta: integer value to add - * @ptr: pointer to type atomic64_t + * @i: integer value to add + * @v: pointer to type atomic64_t * - * Atomically adds @delta to @ptr. + * Atomically adds @i to @v. */ -extern void atomic64_add(u64 delta, atomic64_t *ptr); +static inline long long atomic64_add(long long i, atomic64_t *v) +{ + asm volatile(ATOMIC64_ALTERNATIVE_(add, add_return) + : "+A" (i), "+c" (v) + : : "memory" + ); + return i; +} /** * atomic64_sub - subtract the atomic64 variable - * @delta: integer value to subtract - * @ptr: pointer to type atomic64_t + * @i: integer value to subtract + * @v: pointer to type atomic64_t * - * Atomically subtracts @delta from @ptr. + * Atomically subtracts @i from @v. */ -extern void atomic64_sub(u64 delta, atomic64_t *ptr); +static inline long long atomic64_sub(long long i, atomic64_t *v) +{ + asm volatile(ATOMIC64_ALTERNATIVE_(sub, sub_return) + : "+A" (i), "+c" (v) + : : "memory" + ); + return i; +} /** * atomic64_sub_and_test - subtract value from variable and test result - * @delta: integer value to subtract - * @ptr: pointer to type atomic64_t - * - * Atomically subtracts @delta from @ptr and returns + * @i: integer value to subtract + * @v: pointer to type atomic64_t + * + * Atomically subtracts @i from @v and returns * true if the result is zero, or false for all * other cases. */ -extern int atomic64_sub_and_test(u64 delta, atomic64_t *ptr); +static inline int atomic64_sub_and_test(long long i, atomic64_t *v) +{ + return atomic64_sub_return(i, v) == 0; +} /** * atomic64_inc - increment atomic64 variable - * @ptr: pointer to type atomic64_t + * @v: pointer to type atomic64_t * - * Atomically increments @ptr by 1. + * Atomically increments @v by 1. */ -extern void atomic64_inc(atomic64_t *ptr); +static inline void atomic64_inc(atomic64_t *v) +{ + asm volatile(ATOMIC64_ALTERNATIVE_(inc, inc_return) + : : "S" (v) + : "memory", "eax", "ecx", "edx" + ); +} /** * atomic64_dec - decrement atomic64 variable @@ -124,37 +208,97 @@ extern void atomic64_inc(atomic64_t *ptr); * * Atomically decrements @ptr by 1. */ -extern void atomic64_dec(atomic64_t *ptr); +static inline void atomic64_dec(atomic64_t *v) +{ + asm volatile(ATOMIC64_ALTERNATIVE_(dec, dec_return) + : : "S" (v) + : "memory", "eax", "ecx", "edx" + ); +} /** * atomic64_dec_and_test - decrement and test - * @ptr: pointer to type atomic64_t + * @v: pointer to type atomic64_t * - * Atomically decrements @ptr by 1 and + * Atomically decrements @v by 1 and * returns true if the result is 0, or false for all other * cases. */ -extern int atomic64_dec_and_test(atomic64_t *ptr); +static inline int atomic64_dec_and_test(atomic64_t *v) +{ + return atomic64_dec_return(v) == 0; +} /** * atomic64_inc_and_test - increment and test - * @ptr: pointer to type atomic64_t + * @v: pointer to type atomic64_t * - * Atomically increments @ptr by 1 + * Atomically increments @v by 1 * and returns true if the result is zero, or false for all * other cases. */ -extern int atomic64_inc_and_test(atomic64_t *ptr); +static inline int atomic64_inc_and_test(atomic64_t *v) +{ + return atomic64_inc_return(v) == 0; +} /** * atomic64_add_negative - add and test if negative - * @delta: integer value to add - * @ptr: pointer to type atomic64_t + * @i: integer value to add + * @v: pointer to type atomic64_t * - * Atomically adds @delta to @ptr and returns true + * Atomically adds @i to @v and returns true * if the result is negative, or false when * result is greater than or equal to zero. */ -extern int atomic64_add_negative(u64 delta, atomic64_t *ptr); +static inline int atomic64_add_negative(long long i, atomic64_t *v) +{ + return atomic64_add_return(i, v) < 0; +} + +/** + * atomic64_add_unless - add unless the number is a given value + * @v: pointer of type atomic64_t + * @a: the amount to add to v... + * @u: ...unless v is equal to u. + * + * Atomically adds @a to @v, so long as it was not @u. + * Returns non-zero if @v was not @u, and zero otherwise. + */ +static inline int atomic64_add_unless(atomic64_t *v, long long a, long long u) +{ + unsigned low = (unsigned)u; + unsigned high = (unsigned)(u >> 32); + asm volatile(ATOMIC64_ALTERNATIVE(add_unless) "\n\t" + : "+A" (a), "+c" (v), "+S" (low), "+D" (high) + : : "memory"); + return (int)a; +} + + +static inline int atomic64_inc_not_zero(atomic64_t *v) +{ + int r; + asm volatile(ATOMIC64_ALTERNATIVE(inc_not_zero) + : "=a" (r) + : "S" (v) + : "ecx", "edx", "memory" + ); + return r; +} + +static inline long long atomic64_dec_if_positive(atomic64_t *v) +{ + long long r; + asm volatile(ATOMIC64_ALTERNATIVE(dec_if_positive) + : "=A" (r) + : "S" (v) + : "ecx", "memory" + ); + return r; +} + +#undef ATOMIC64_ALTERNATIVE +#undef ATOMIC64_ALTERNATIVE_ #endif /* _ASM_X86_ATOMIC64_32_H */ diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index cffd754f..05d686b 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -26,11 +26,12 @@ obj-y += msr.o msr-reg.o msr-reg-export.o ifeq ($(CONFIG_X86_32),y) obj-y += atomic64_32.o + lib-y += atomic64_cx8_32.o lib-y += checksum_32.o lib-y += strstr_32.o lib-y += semaphore_32.o string_32.o ifneq ($(CONFIG_X86_CMPXCHG64),y) - lib-y += cmpxchg8b_emu.o + lib-y += cmpxchg8b_emu.o atomic64_386_32.o endif lib-$(CONFIG_X86_USE_3DNOW) += mmx_32.o else diff --git a/arch/x86/lib/atomic64_32.c b/arch/x86/lib/atomic64_32.c index 824fa0b..540179e 100644 --- a/arch/x86/lib/atomic64_32.c +++ b/arch/x86/lib/atomic64_32.c @@ -6,225 +6,54 @@ #include #include -static noinline u64 cmpxchg8b(u64 *ptr, u64 old, u64 new) -{ - u32 low = new; - u32 high = new >> 32; - - asm volatile( - LOCK_PREFIX "cmpxchg8b %1\n" - : "+A" (old), "+m" (*ptr) - : "b" (low), "c" (high) - ); - return old; -} - -u64 atomic64_cmpxchg(atomic64_t *ptr, u64 old_val, u64 new_val) -{ - return cmpxchg8b(&ptr->counter, old_val, new_val); -} -EXPORT_SYMBOL(atomic64_cmpxchg); - -/** - * atomic64_xchg - xchg atomic64 variable - * @ptr: pointer to type atomic64_t - * @new_val: value to assign - * - * Atomically xchgs the value of @ptr to @new_val and returns - * the old value. - */ -u64 atomic64_xchg(atomic64_t *ptr, u64 new_val) -{ - /* - * Try first with a (possibly incorrect) assumption about - * what we have there. We'll do two loops most likely, - * but we'll get an ownership MESI transaction straight away - * instead of a read transaction followed by a - * flush-for-ownership transaction: - */ - u64 old_val, real_val = 0; - - do { - old_val = real_val; - - real_val = atomic64_cmpxchg(ptr, old_val, new_val); - - } while (real_val != old_val); - - return old_val; -} -EXPORT_SYMBOL(atomic64_xchg); - -/** - * atomic64_set - set atomic64 variable - * @ptr: pointer to type atomic64_t - * @new_val: value to assign - * - * Atomically sets the value of @ptr to @new_val. - */ -void atomic64_set(atomic64_t *ptr, u64 new_val) -{ - atomic64_xchg(ptr, new_val); -} -EXPORT_SYMBOL(atomic64_set); - -/** -EXPORT_SYMBOL(atomic64_read); - * atomic64_add_return - add and return - * @delta: integer value to add - * @ptr: pointer to type atomic64_t - * - * Atomically adds @delta to @ptr and returns @delta + *@ptr - */ -noinline u64 atomic64_add_return(u64 delta, atomic64_t *ptr) -{ - /* - * Try first with a (possibly incorrect) assumption about - * what we have there. We'll do two loops most likely, - * but we'll get an ownership MESI transaction straight away - * instead of a read transaction followed by a - * flush-for-ownership transaction: - */ - u64 old_val, new_val, real_val = 0; - - do { - old_val = real_val; - new_val = old_val + delta; - - real_val = atomic64_cmpxchg(ptr, old_val, new_val); - - } while (real_val != old_val); - - return new_val; -} -EXPORT_SYMBOL(atomic64_add_return); - -u64 atomic64_sub_return(u64 delta, atomic64_t *ptr) -{ - return atomic64_add_return(-delta, ptr); -} -EXPORT_SYMBOL(atomic64_sub_return); - -u64 atomic64_inc_return(atomic64_t *ptr) -{ - return atomic64_add_return(1, ptr); -} -EXPORT_SYMBOL(atomic64_inc_return); - -u64 atomic64_dec_return(atomic64_t *ptr) -{ - return atomic64_sub_return(1, ptr); -} -EXPORT_SYMBOL(atomic64_dec_return); - -/** - * atomic64_add - add integer to atomic64 variable - * @delta: integer value to add - * @ptr: pointer to type atomic64_t - * - * Atomically adds @delta to @ptr. - */ -void atomic64_add(u64 delta, atomic64_t *ptr) -{ - atomic64_add_return(delta, ptr); -} -EXPORT_SYMBOL(atomic64_add); - -/** - * atomic64_sub - subtract the atomic64 variable - * @delta: integer value to subtract - * @ptr: pointer to type atomic64_t - * - * Atomically subtracts @delta from @ptr. - */ -void atomic64_sub(u64 delta, atomic64_t *ptr) -{ - atomic64_add(-delta, ptr); -} -EXPORT_SYMBOL(atomic64_sub); - -/** - * atomic64_sub_and_test - subtract value from variable and test result - * @delta: integer value to subtract - * @ptr: pointer to type atomic64_t - * - * Atomically subtracts @delta from @ptr and returns - * true if the result is zero, or false for all - * other cases. - */ -int atomic64_sub_and_test(u64 delta, atomic64_t *ptr) -{ - u64 new_val = atomic64_sub_return(delta, ptr); - - return new_val == 0; -} -EXPORT_SYMBOL(atomic64_sub_and_test); - -/** - * atomic64_inc - increment atomic64 variable - * @ptr: pointer to type atomic64_t - * - * Atomically increments @ptr by 1. - */ -void atomic64_inc(atomic64_t *ptr) -{ - atomic64_add(1, ptr); -} -EXPORT_SYMBOL(atomic64_inc); - -/** - * atomic64_dec - decrement atomic64 variable - * @ptr: pointer to type atomic64_t - * - * Atomically decrements @ptr by 1. - */ -void atomic64_dec(atomic64_t *ptr) -{ - atomic64_sub(1, ptr); -} -EXPORT_SYMBOL(atomic64_dec); - -/** - * atomic64_dec_and_test - decrement and test - * @ptr: pointer to type atomic64_t - * - * Atomically decrements @ptr by 1 and - * returns true if the result is 0, or false for all other - * cases. - */ -int atomic64_dec_and_test(atomic64_t *ptr) -{ - return atomic64_sub_and_test(1, ptr); -} -EXPORT_SYMBOL(atomic64_dec_and_test); - -/** - * atomic64_inc_and_test - increment and test - * @ptr: pointer to type atomic64_t - * - * Atomically increments @ptr by 1 - * and returns true if the result is zero, or false for all - * other cases. - */ -int atomic64_inc_and_test(atomic64_t *ptr) -{ - return atomic64_sub_and_test(-1, ptr); -} -EXPORT_SYMBOL(atomic64_inc_and_test); - -/** - * atomic64_add_negative - add and test if negative - * @delta: integer value to add - * @ptr: pointer to type atomic64_t - * - * Atomically adds @delta to @ptr and returns true - * if the result is negative, or false when - * result is greater than or equal to zero. - */ -int atomic64_add_negative(u64 delta, atomic64_t *ptr) -{ - s64 new_val = atomic64_add_return(delta, ptr); - - return new_val < 0; -} -EXPORT_SYMBOL(atomic64_add_negative); +long long atomic64_read_cx8(long long, const atomic64_t *v); +EXPORT_SYMBOL(atomic64_read_cx8); +long long atomic64_set_cx8(long long, const atomic64_t *v); +EXPORT_SYMBOL(atomic64_set_cx8); +long long atomic64_xchg_cx8(long long, unsigned high); +EXPORT_SYMBOL(atomic64_xchg_cx8); +long long atomic64_add_return_cx8(long long a, atomic64_t *v); +EXPORT_SYMBOL(atomic64_add_return_cx8); +long long atomic64_sub_return_cx8(long long a, atomic64_t *v); +EXPORT_SYMBOL(atomic64_sub_return_cx8); +long long atomic64_inc_return_cx8(long long a, atomic64_t *v); +EXPORT_SYMBOL(atomic64_inc_return_cx8); +long long atomic64_dec_return_cx8(long long a, atomic64_t *v); +EXPORT_SYMBOL(atomic64_dec_return_cx8); +long long atomic64_dec_if_positive_cx8(atomic64_t *v); +EXPORT_SYMBOL(atomic64_dec_if_positive_cx8); +int atomic64_inc_not_zero_cx8(atomic64_t *v); +EXPORT_SYMBOL(atomic64_inc_not_zero_cx8); +int atomic64_add_unless_cx8(atomic64_t *v, long long a, long long u); +EXPORT_SYMBOL(atomic64_add_unless_cx8); + +#ifndef CONFIG_X86_CMPXCHG64 +long long atomic64_read_386(long long, const atomic64_t *v); +EXPORT_SYMBOL(atomic64_read_386); +long long atomic64_set_386(long long, const atomic64_t *v); +EXPORT_SYMBOL(atomic64_set_386); +long long atomic64_xchg_386(long long, unsigned high); +EXPORT_SYMBOL(atomic64_xchg_386); +long long atomic64_add_return_386(long long a, atomic64_t *v); +EXPORT_SYMBOL(atomic64_add_return_386); +long long atomic64_sub_return_386(long long a, atomic64_t *v); +EXPORT_SYMBOL(atomic64_sub_return_386); +long long atomic64_inc_return_386(long long a, atomic64_t *v); +EXPORT_SYMBOL(atomic64_inc_return_386); +long long atomic64_dec_return_386(long long a, atomic64_t *v); +EXPORT_SYMBOL(atomic64_dec_return_386); +long long atomic64_add_386(long long a, atomic64_t *v); +EXPORT_SYMBOL(atomic64_add_386); +long long atomic64_sub_386(long long a, atomic64_t *v); +EXPORT_SYMBOL(atomic64_sub_386); +long long atomic64_inc_386(long long a, atomic64_t *v); +EXPORT_SYMBOL(atomic64_inc_386); +long long atomic64_dec_386(long long a, atomic64_t *v); +EXPORT_SYMBOL(atomic64_dec_386); +long long atomic64_dec_if_positive_386(atomic64_t *v); +EXPORT_SYMBOL(atomic64_dec_if_positive_386); +int atomic64_inc_not_zero_386(atomic64_t *v); +EXPORT_SYMBOL(atomic64_inc_not_zero_386); +int atomic64_add_unless_386(atomic64_t *v, long long a, long long u); +EXPORT_SYMBOL(atomic64_add_unless_386); +#endif diff --git a/arch/x86/lib/atomic64_386_32.S b/arch/x86/lib/atomic64_386_32.S new file mode 100644 index 0000000..5db07fe --- /dev/null +++ b/arch/x86/lib/atomic64_386_32.S @@ -0,0 +1,175 @@ +/* + * atomic64_t for 386/486 + * + * Copyright © 2010 Luca Barbieri + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include + +/* if you want SMP support, implement these with real spinlocks */ +.macro LOCK reg + pushfl + CFI_ADJUST_CFA_OFFSET 4 + cli +.endm + +.macro UNLOCK reg + popfl + CFI_ADJUST_CFA_OFFSET -4 +.endm + +.macro BEGIN func reg +$v = \reg + +ENTRY(atomic64_\func\()_386) + CFI_STARTPROC + LOCK $v + +.macro RETURN + UNLOCK $v + ret +.endm + +.macro END_ + CFI_ENDPROC +ENDPROC(atomic64_\func\()_386) +.purgem RETURN +.purgem END_ +.purgem END +.endm + +.macro END +RETURN +END_ +.endm +.endm + +BEGIN read %ecx + movl ($v), %eax + movl 4($v), %edx +END + +BEGIN set %esi + movl %ebx, ($v) + movl %ecx, 4($v) +END + +BEGIN xchg %esi + movl ($v), %eax + movl 4($v), %edx + movl %ebx, ($v) + movl %ecx, 4($v) +END + +BEGIN add %ecx + addl %eax, ($v) + adcl %edx, 4($v) +END + +BEGIN add_return %ecx + addl ($v), %eax + adcl 4($v), %edx + movl %eax, ($v) + movl %edx, 4($v) +END + +BEGIN sub %ecx + subl %eax, ($v) + sbbl %edx, 4($v) +END + +BEGIN sub_return %ecx + negl %edx + negl %eax + sbbl $0, %edx + addl ($v), %eax + adcl 4($v), %edx + movl %eax, ($v) + movl %edx, 4($v) +END + +BEGIN inc %esi + addl $1, ($v) + adcl $0, 4($v) +END + +BEGIN inc_return %esi + movl ($v), %eax + movl 4($v), %edx + addl $1, %eax + adcl $0, %edx + movl %eax, ($v) + movl %edx, 4($v) +END + +BEGIN dec %esi + subl $1, ($v) + sbbl $0, 4($v) +END + +BEGIN dec_return %esi + movl ($v), %eax + movl 4($v), %edx + subl $1, %eax + sbbl $0, %edx + movl %eax, ($v) + movl %edx, 4($v) +END + +BEGIN add_unless %ecx + addl %eax, %esi + adcl %edx, %edi + addl ($v), %eax + adcl 4($v), %edx + cmpl %eax, %esi + je 3f +1: + movl %eax, ($v) + movl %edx, 4($v) + xorl %eax, %eax +2: +RETURN +3: + cmpl %edx, %edi + jne 1b + movl $1, %eax + jmp 2b +END_ + +BEGIN inc_not_zero %esi + movl ($v), %eax + movl 4($v), %edx + testl %eax, %eax + je 3f +1: + addl $1, %eax + adcl $0, %edx + movl %eax, ($v) + movl %edx, 4($v) + xorl %eax, %eax +2: +RETURN +3: + testl %edx, %edx + jne 1b + movl $1, %eax + jmp 2b +END_ + +BEGIN dec_if_positive %esi + movl ($v), %eax + movl 4($v), %edx + subl $1, %eax + sbbl $0, %edx + js 1f + movl %eax, ($v) + movl %edx, 4($v) +1: +END diff --git a/arch/x86/lib/atomic64_cx8_32.S b/arch/x86/lib/atomic64_cx8_32.S new file mode 100644 index 0000000..e49c4eb --- /dev/null +++ b/arch/x86/lib/atomic64_cx8_32.S @@ -0,0 +1,225 @@ +/* + * atomic64_t for 586+ + * + * Copyright © 2010 Luca Barbieri + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include + +.macro SAVE reg + pushl %\reg + CFI_ADJUST_CFA_OFFSET 4 + CFI_REL_OFFSET \reg, 0 +.endm + +.macro RESTORE reg + popl %\reg + CFI_ADJUST_CFA_OFFSET -4 + CFI_RESTORE \reg +.endm + +.macro read64 reg + movl %ebx, %eax + movl %ecx, %edx +/* we need LOCK_PREFIX since otherwise cmpxchg8b always does the write */ + LOCK_PREFIX + cmpxchg8b (\reg) +.endm + +ENTRY(atomic64_read_cx8) + CFI_STARTPROC + + read64 %ecx + ret + CFI_ENDPROC +ENDPROC(atomic64_read_cx8) + +ENTRY(atomic64_set_cx8) + CFI_STARTPROC + +1: +/* we don't need LOCK_PREFIX since aligned 64-bit writes + * are atomic on 586 and newer */ + cmpxchg8b (%esi) + jne 1b + + ret + CFI_ENDPROC +ENDPROC(atomic64_set_cx8) + +ENTRY(atomic64_xchg_cx8) + CFI_STARTPROC + + movl %ebx, %eax + movl %ecx, %edx +1: + LOCK_PREFIX + cmpxchg8b (%esi) + jne 1b + + ret + CFI_ENDPROC +ENDPROC(atomic64_xchg_cx8) + +.macro addsub_return func ins insc +ENTRY(atomic64_\func\()_return_cx8) + CFI_STARTPROC + SAVE ebp + SAVE ebx + SAVE esi + SAVE edi + + movl %eax, %esi + movl %edx, %edi + movl %ecx, %ebp + + read64 %ebp +1: + movl %eax, %ebx + movl %edx, %ecx + \ins\()l %esi, %ebx + \insc\()l %edi, %ecx + LOCK_PREFIX + cmpxchg8b (%ebp) + jne 1b + +10: + movl %ebx, %eax + movl %ecx, %edx + RESTORE edi + RESTORE esi + RESTORE ebx + RESTORE ebp + ret + CFI_ENDPROC +ENDPROC(atomic64_\func\()_return_cx8) +.endm + +addsub_return add add adc +addsub_return sub sub sbb + +.macro incdec_return func ins insc +ENTRY(atomic64_\func\()_return_cx8) + CFI_STARTPROC + SAVE ebx + + read64 %esi +1: + movl %eax, %ebx + movl %edx, %ecx + \ins\()l $1, %ebx + \insc\()l $0, %ecx + LOCK_PREFIX + cmpxchg8b (%esi) + jne 1b + +10: + movl %ebx, %eax + movl %ecx, %edx + RESTORE ebx + ret + CFI_ENDPROC +ENDPROC(atomic64_\func\()_return_cx8) +.endm + +incdec_return inc add adc +incdec_return dec sub sbb + +ENTRY(atomic64_dec_if_positive_cx8) + CFI_STARTPROC + SAVE ebx + + read64 %esi +1: + movl %eax, %ebx + movl %edx, %ecx + subl $1, %ebx + sbb $0, %ecx + js 2f + LOCK_PREFIX + cmpxchg8b (%esi) + jne 1b + +2: + movl %ebx, %eax + movl %ecx, %edx + RESTORE ebx + ret + CFI_ENDPROC +ENDPROC(atomic64_dec_if_positive_cx8) + +ENTRY(atomic64_add_unless_cx8) + CFI_STARTPROC + SAVE ebp + SAVE ebx +/* these just push these two parameters on the stack */ + SAVE edi + SAVE esi + + movl %ecx, %ebp + movl %eax, %esi + movl %edx, %edi + + read64 %ebp +1: + cmpl %eax, 0(%esp) + je 4f +2: + movl %eax, %ebx + movl %edx, %ecx + addl %esi, %ebx + adcl %edi, %ecx + LOCK_PREFIX + cmpxchg8b (%ebp) + jne 1b + + xorl %eax, %eax +3: + addl $8, %esp + CFI_ADJUST_CFA_OFFSET -8 + RESTORE ebx + RESTORE ebp + ret +4: + cmpl %edx, 4(%esp) + jne 2b + movl $1, %eax + jmp 3b + CFI_ENDPROC +ENDPROC(atomic64_add_unless_cx8) + +ENTRY(atomic64_inc_not_zero_cx8) + CFI_STARTPROC + SAVE ebx + + read64 %esi +1: + testl %eax, %eax + je 4f +2: + movl %eax, %ebx + movl %edx, %ecx + addl $1, %ebx + adcl $0, %ecx + LOCK_PREFIX + cmpxchg8b (%esi) + jne 1b + + xorl %eax, %eax +3: + RESTORE ebx + ret +4: + testl %edx, %edx + jne 2b + movl $1, %eax + jmp 3b + CFI_ENDPROC +ENDPROC(atomic64_inc_not_zero_cx8) -- cgit v0.10.2 From 8f4f202b335144bf5be5c9e5b1bc9477ecdae958 Mon Sep 17 00:00:00 2001 From: Luca Barbieri Date: Fri, 26 Feb 2010 12:22:40 +0100 Subject: lib: Only test atomic64_dec_if_positive on archs having it Currently atomic64_dec_if_positive() is only supported by PowerPC, MIPS and x86-32. Signed-off-by: Luca Barbieri LKML-Reference: <1267183361-20775-1-git-send-email-luca@luca-barbieri.com> Signed-off-by: H. Peter Anvin diff --git a/lib/atomic64_test.c b/lib/atomic64_test.c index 4ff649e..0effcac 100644 --- a/lib/atomic64_test.c +++ b/lib/atomic64_test.c @@ -112,6 +112,7 @@ static __init int test_atomic64(void) r += one; BUG_ON(v.counter != r); +#if defined(CONFIG_X86_32) || defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(_ASM_GENERIC_ATOMIC64_H) INIT(onestwos); BUG_ON(atomic64_dec_if_positive(&v) != (onestwos - 1)); r -= one; @@ -124,6 +125,9 @@ static __init int test_atomic64(void) INIT(-one); BUG_ON(atomic64_dec_if_positive(&v) != (-one - one)); BUG_ON(v.counter != r); +#else +#warning Please implement atomic64_dec_if_positive for your architecture, and add it to the IF above +#endif INIT(onestwos); BUG_ON(atomic64_inc_not_zero(&v)); -- cgit v0.10.2 From d7f6de1e9c4a12e11ba7186c70f0f40caa76f590 Mon Sep 17 00:00:00 2001 From: Luca Barbieri Date: Fri, 26 Feb 2010 12:22:41 +0100 Subject: x86: Implement atomic[64]_dec_if_positive() Add support for atomic_dec_if_positive(), and atomic64_dec_if_positive() for x86-64. atomic64_dec_if_positive() for x86-32 was already implemented in a previous patch. Signed-off-by: Luca Barbieri LKML-Reference: <1267183361-20775-2-git-send-email-luca@luca-barbieri.com> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/include/asm/atomic.h b/arch/x86/include/asm/atomic.h index 8f8217b..706c694 100644 --- a/arch/x86/include/asm/atomic.h +++ b/arch/x86/include/asm/atomic.h @@ -246,6 +246,29 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u) #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) +/* + * atomic_dec_if_positive - decrement by 1 if old value positive + * @v: pointer of type atomic_t + * + * The function returns the old value of *v minus 1, even if + * the atomic variable, v, was not decremented. + */ +static inline int atomic_dec_if_positive(atomic_t *v) +{ + int c, old, dec; + c = atomic_read(v); + for (;;) { + dec = c - 1; + if (unlikely(dec < 0)) + break; + old = atomic_cmpxchg((v), c, dec); + if (likely(old == c)) + break; + c = old; + } + return dec; +} + /** * atomic_inc_short - increment of a short integer * @v: pointer to type int diff --git a/arch/x86/include/asm/atomic64_64.h b/arch/x86/include/asm/atomic64_64.h index 51c5b40..4d6e2cd 100644 --- a/arch/x86/include/asm/atomic64_64.h +++ b/arch/x86/include/asm/atomic64_64.h @@ -221,4 +221,27 @@ static inline int atomic64_add_unless(atomic64_t *v, long a, long u) #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0) +/* + * atomic64_dec_if_positive - decrement by 1 if old value positive + * @v: pointer of type atomic_t + * + * The function returns the old value of *v minus 1, even if + * the atomic variable, v, was not decremented. + */ +static inline long atomic64_dec_if_positive(atomic64_t *v) +{ + long c, old, dec; + c = atomic64_read(v); + for (;;) { + dec = c - 1; + if (unlikely(dec < 0)) + break; + old = atomic64_cmpxchg((v), c, dec); + if (likely(old == c)) + break; + c = old; + } + return dec; +} + #endif /* _ASM_X86_ATOMIC64_64_H */ diff --git a/lib/atomic64_test.c b/lib/atomic64_test.c index 0effcac..58efdab 100644 --- a/lib/atomic64_test.c +++ b/lib/atomic64_test.c @@ -112,7 +112,7 @@ static __init int test_atomic64(void) r += one; BUG_ON(v.counter != r); -#if defined(CONFIG_X86_32) || defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(_ASM_GENERIC_ATOMIC64_H) +#if defined(CONFIG_X86) || defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(_ASM_GENERIC_ATOMIC64_H) INIT(onestwos); BUG_ON(atomic64_dec_if_positive(&v) != (onestwos - 1)); r -= one; -- cgit v0.10.2 From 9efbcd590243045111670c171a951923b877b57d Mon Sep 17 00:00:00 2001 From: Luca Barbieri Date: Mon, 1 Mar 2010 19:55:45 +0100 Subject: lib: Fix atomic64_add_unless test atomic64_add_unless must return 1 if it perfomed the add and 0 otherwise. The test assumed the opposite convention. Reported-by: H. Peter Anvin Signed-off-by: Luca Barbieri LKML-Reference: <1267469749-11878-2-git-send-email-luca@luca-barbieri.com> Signed-off-by: H. Peter Anvin diff --git a/lib/atomic64_test.c b/lib/atomic64_test.c index 58efdab..ee8e6de 100644 --- a/lib/atomic64_test.c +++ b/lib/atomic64_test.c @@ -104,11 +104,11 @@ static __init int test_atomic64(void) BUG_ON(v.counter != r); INIT(v0); - BUG_ON(!atomic64_add_unless(&v, one, v0)); + BUG_ON(atomic64_add_unless(&v, one, v0)); BUG_ON(v.counter != r); INIT(v0); - BUG_ON(atomic64_add_unless(&v, one, v1)); + BUG_ON(!atomic64_add_unless(&v, one, v1)); r += one; BUG_ON(v.counter != r); -- cgit v0.10.2 From 6e6104fe085026e6ef82cc5cc303d6c8ceb7e411 Mon Sep 17 00:00:00 2001 From: Luca Barbieri Date: Mon, 1 Mar 2010 19:55:46 +0100 Subject: x86-32: Fix atomic64_add_unless return value convention atomic64_add_unless must return 1 if it perfomed the add and 0 otherwise. The implementation did the opposite thing. Reported-by: H. Peter Anvin Signed-off-by: Luca Barbieri LKML-Reference: <1267469749-11878-3-git-send-email-luca@luca-barbieri.com> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/lib/atomic64_386_32.S b/arch/x86/lib/atomic64_386_32.S index 5db07fe..a2f847c 100644 --- a/arch/x86/lib/atomic64_386_32.S +++ b/arch/x86/lib/atomic64_386_32.S @@ -133,13 +133,13 @@ BEGIN add_unless %ecx 1: movl %eax, ($v) movl %edx, 4($v) - xorl %eax, %eax + movl $1, %eax 2: RETURN 3: cmpl %edx, %edi jne 1b - movl $1, %eax + xorl %eax, %eax jmp 2b END_ diff --git a/arch/x86/lib/atomic64_cx8_32.S b/arch/x86/lib/atomic64_cx8_32.S index e49c4eb..d0e37b1 100644 --- a/arch/x86/lib/atomic64_cx8_32.S +++ b/arch/x86/lib/atomic64_cx8_32.S @@ -180,7 +180,7 @@ ENTRY(atomic64_add_unless_cx8) cmpxchg8b (%ebp) jne 1b - xorl %eax, %eax + movl $1, %eax 3: addl $8, %esp CFI_ADJUST_CFA_OFFSET -8 @@ -190,7 +190,7 @@ ENTRY(atomic64_add_unless_cx8) 4: cmpl %edx, 4(%esp) jne 2b - movl $1, %eax + xorl %eax, %eax jmp 3b CFI_ENDPROC ENDPROC(atomic64_add_unless_cx8) -- cgit v0.10.2 From 97577896f6b9c056fa0a5e9f6a608110cb3dcd33 Mon Sep 17 00:00:00 2001 From: Luca Barbieri Date: Mon, 1 Mar 2010 19:55:47 +0100 Subject: lib: Fix atomic64_add_unless return value convention atomic64_add_unless must return 1 if it perfomed the add and 0 otherwise. The generic implementation did the opposite thing. Reported-by: H. Peter Anvin Confirmed-by: Paul Mackerras Signed-off-by: Luca Barbieri LKML-Reference: <1267469749-11878-4-git-send-email-luca@luca-barbieri.com> Signed-off-by: H. Peter Anvin diff --git a/lib/atomic64.c b/lib/atomic64.c index 8bee16e..a21c12b 100644 --- a/lib/atomic64.c +++ b/lib/atomic64.c @@ -162,12 +162,12 @@ int atomic64_add_unless(atomic64_t *v, long long a, long long u) { unsigned long flags; spinlock_t *lock = lock_addr(v); - int ret = 1; + int ret = 0; spin_lock_irqsave(lock, flags); if (v->counter != u) { v->counter += a; - ret = 0; + ret = 1; } spin_unlock_irqrestore(lock, flags); return ret; -- cgit v0.10.2 From 25a304f277ad70166eeae25a4958d2049005c33a Mon Sep 17 00:00:00 2001 From: Luca Barbieri Date: Mon, 1 Mar 2010 19:55:48 +0100 Subject: lib: Fix atomic64_inc_not_zero test atomic64_inc_not_zero must return 1 if it perfomed the add and 0 otherwise. The test assumed the opposite convention. Signed-off-by: Luca Barbieri LKML-Reference: <1267469749-11878-5-git-send-email-luca@luca-barbieri.com> Signed-off-by: H. Peter Anvin diff --git a/lib/atomic64_test.c b/lib/atomic64_test.c index ee8e6de..f7bb706 100644 --- a/lib/atomic64_test.c +++ b/lib/atomic64_test.c @@ -130,16 +130,16 @@ static __init int test_atomic64(void) #endif INIT(onestwos); - BUG_ON(atomic64_inc_not_zero(&v)); + BUG_ON(!atomic64_inc_not_zero(&v)); r += one; BUG_ON(v.counter != r); INIT(0); - BUG_ON(!atomic64_inc_not_zero(&v)); + BUG_ON(atomic64_inc_not_zero(&v)); BUG_ON(v.counter != r); INIT(-one); - BUG_ON(atomic64_inc_not_zero(&v)); + BUG_ON(!atomic64_inc_not_zero(&v)); r += one; BUG_ON(v.counter != r); -- cgit v0.10.2 From f3e83131469e29032a700217aa394996107b8fc5 Mon Sep 17 00:00:00 2001 From: Luca Barbieri Date: Mon, 1 Mar 2010 19:55:49 +0100 Subject: x86-32: Fix atomic64_inc_not_zero return value convention atomic64_inc_not_zero must return 1 if it perfomed the add and 0 otherwise. It was doing the opposite thing. Signed-off-by: Luca Barbieri LKML-Reference: <1267469749-11878-6-git-send-email-luca@luca-barbieri.com> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/lib/atomic64_386_32.S b/arch/x86/lib/atomic64_386_32.S index a2f847c..4a5979a 100644 --- a/arch/x86/lib/atomic64_386_32.S +++ b/arch/x86/lib/atomic64_386_32.S @@ -153,13 +153,12 @@ BEGIN inc_not_zero %esi adcl $0, %edx movl %eax, ($v) movl %edx, 4($v) - xorl %eax, %eax + movl $1, %eax 2: RETURN 3: testl %edx, %edx jne 1b - movl $1, %eax jmp 2b END_ diff --git a/arch/x86/lib/atomic64_cx8_32.S b/arch/x86/lib/atomic64_cx8_32.S index d0e37b1..71e080d 100644 --- a/arch/x86/lib/atomic64_cx8_32.S +++ b/arch/x86/lib/atomic64_cx8_32.S @@ -212,14 +212,13 @@ ENTRY(atomic64_inc_not_zero_cx8) cmpxchg8b (%esi) jne 1b - xorl %eax, %eax + movl $1, %eax 3: RESTORE ebx ret 4: testl %edx, %edx jne 2b - movl $1, %eax jmp 3b CFI_ENDPROC ENDPROC(atomic64_inc_not_zero_cx8) -- cgit v0.10.2 From a5c9161f27c3e1ae6c0094d262f03a7e98262181 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 1 Mar 2010 11:49:23 -0800 Subject: x86, atomic64: In selftest, distinguish x86-64 from 586+ The x86-64 implementation of the atomics is totally different from the i586+ implementation, which makes it quite confusing to call it "586+". Also fix indentation, and add "i" for "i386" and "i586" as used elsewhere in the kernel. Signed-off-by: H. Peter Anvin Cc: Luca Barbieri LKML-Reference: <1267005265-27958-4-git-send-email-luca@luca-barbieri.com> diff --git a/lib/atomic64_test.c b/lib/atomic64_test.c index f7bb706..65e482c 100644 --- a/lib/atomic64_test.c +++ b/lib/atomic64_test.c @@ -144,14 +144,16 @@ static __init int test_atomic64(void) BUG_ON(v.counter != r); #ifdef CONFIG_X86 - printk(KERN_INFO "atomic64 test passed for %s+ platform %s CX8 and %s SSE\n", -#ifdef CONFIG_X86_CMPXCHG64 - "586", + printk(KERN_INFO "atomic64 test passed for %s platform %s CX8 and %s SSE\n", +#ifdef CONFIG_X86_64 + "x86-64", +#elif defined(CONFIG_X86_CMPXCHG64) + "i586+", #else - "386", + "i386+", #endif - boot_cpu_has(X86_FEATURE_CX8) ? "with" : "without", - boot_cpu_has(X86_FEATURE_XMM) ? "with" : "without"); + boot_cpu_has(X86_FEATURE_CX8) ? "with" : "without", + boot_cpu_has(X86_FEATURE_XMM) ? "with" : "without"); #else printk(KERN_INFO "atomic64 test passed\n"); #endif -- cgit v0.10.2 From 4daa2a8093ecd1148270a1fc64e99f072b8c2901 Mon Sep 17 00:00:00 2001 From: "Pallipadi, Venkatesh" Date: Wed, 24 Feb 2010 13:43:55 -0800 Subject: x86, pat: In rbt_memtype_check_insert(), update new->type only if valid new->type should only change when there is a valid ret_type. Otherwise the requested type and return type should be same. Signed-off-by: Venkatesh Pallipadi LKML-Reference: <20100224214355.GA16431@linux-os.sc.intel.com> Tested-by: Jack Steiner Signed-off-by: H. Peter Anvin diff --git a/arch/x86/mm/pat_rbtree.c b/arch/x86/mm/pat_rbtree.c index 9063f40..07de4cb 100644 --- a/arch/x86/mm/pat_rbtree.c +++ b/arch/x86/mm/pat_rbtree.c @@ -223,7 +223,9 @@ int rbt_memtype_check_insert(struct memtype *new, unsigned long *ret_type) new->type, ret_type); if (!err) { - new->type = *ret_type; + if (ret_type) + new->type = *ret_type; + memtype_rb_insert(&memtype_rbroot, new); } return err; -- cgit v0.10.2 From 372e22ef0a87d5fc10d387791f9f19721115820c Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 1 Mar 2010 22:06:25 -0800 Subject: x86, docbook: Fix errors from x86 headers merger Fix docbook errors for x86 headers that were recently merged: docproc: arch/x86/include/asm/atomic_32.h: No such file or directory docproc: arch/x86/include/asm/io_32.h: No such file or directory Signed-off-by: Randy Dunlap LKML-Reference: <20100301220625.bad46c19.randy.dunlap@oracle.com> Cc: Brian Gerst Signed-off-by: H. Peter Anvin diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl index f9a6e2c..1b2dd4f 100644 --- a/Documentation/DocBook/device-drivers.tmpl +++ b/Documentation/DocBook/device-drivers.tmpl @@ -45,7 +45,7 @@ Atomic and pointer manipulation -!Iarch/x86/include/asm/atomic_32.h +!Iarch/x86/include/asm/atomic.h !Iarch/x86/include/asm/unaligned.h diff --git a/Documentation/DocBook/deviceiobook.tmpl b/Documentation/DocBook/deviceiobook.tmpl index 3ed8812..c1ed6a4 100644 --- a/Documentation/DocBook/deviceiobook.tmpl +++ b/Documentation/DocBook/deviceiobook.tmpl @@ -316,7 +316,7 @@ CPU B: spin_unlock_irqrestore(&dev_lock, flags) Public Functions Provided -!Iarch/x86/include/asm/io_32.h +!Iarch/x86/include/asm/io.h !Elib/iomap.c -- cgit v0.10.2 From ced918eb748ce30b3aace549fd17540e40ffdca0 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 17 Feb 2010 16:47:10 +0000 Subject: i8253: Convert i8253_lock to raw_spinlock i8253_lock needs to be a real spinlock in preempt-rt, i.e. it can not be converted to a sleeping lock. Convert it to raw_spinlock and fix up all users. Signed-off-by: Thomas Gleixner Acked-by: Ralf Baechle Acked-by: Dmitry Torokhov Acked-by: Takashi Iwai Cc: Jens Axboe LKML-Reference: <20100217163751.030764372@linutronix.de> diff --git a/arch/mips/include/asm/i8253.h b/arch/mips/include/asm/i8253.h index 032ca73..48bb823 100644 --- a/arch/mips/include/asm/i8253.h +++ b/arch/mips/include/asm/i8253.h @@ -12,7 +12,7 @@ #define PIT_CH0 0x40 #define PIT_CH2 0x42 -extern spinlock_t i8253_lock; +extern raw_spinlock_t i8253_lock; extern void setup_pit_timer(void); diff --git a/arch/mips/kernel/i8253.c b/arch/mips/kernel/i8253.c index ed5c441..9479406 100644 --- a/arch/mips/kernel/i8253.c +++ b/arch/mips/kernel/i8253.c @@ -15,7 +15,7 @@ #include #include -DEFINE_SPINLOCK(i8253_lock); +DEFINE_RAW_SPINLOCK(i8253_lock); EXPORT_SYMBOL(i8253_lock); /* @@ -26,7 +26,7 @@ EXPORT_SYMBOL(i8253_lock); static void init_pit_timer(enum clock_event_mode mode, struct clock_event_device *evt) { - spin_lock(&i8253_lock); + raw_spin_lock(&i8253_lock); switch(mode) { case CLOCK_EVT_MODE_PERIODIC: @@ -55,7 +55,7 @@ static void init_pit_timer(enum clock_event_mode mode, /* Nothing to do here */ break; } - spin_unlock(&i8253_lock); + raw_spin_unlock(&i8253_lock); } /* @@ -65,10 +65,10 @@ static void init_pit_timer(enum clock_event_mode mode, */ static int pit_next_event(unsigned long delta, struct clock_event_device *evt) { - spin_lock(&i8253_lock); + raw_spin_lock(&i8253_lock); outb_p(delta & 0xff , PIT_CH0); /* LSB */ outb(delta >> 8 , PIT_CH0); /* MSB */ - spin_unlock(&i8253_lock); + raw_spin_unlock(&i8253_lock); return 0; } @@ -137,7 +137,7 @@ static cycle_t pit_read(struct clocksource *cs) static int old_count; static u32 old_jifs; - spin_lock_irqsave(&i8253_lock, flags); + raw_spin_lock_irqsave(&i8253_lock, flags); /* * Although our caller may have the read side of xtime_lock, * this is now a seqlock, and we are cheating in this routine @@ -183,7 +183,7 @@ static cycle_t pit_read(struct clocksource *cs) old_count = count; old_jifs = jifs; - spin_unlock_irqrestore(&i8253_lock, flags); + raw_spin_unlock_irqrestore(&i8253_lock, flags); count = (LATCH - 1) - count; diff --git a/arch/x86/include/asm/i8253.h b/arch/x86/include/asm/i8253.h index 1edbf89..fc1f579 100644 --- a/arch/x86/include/asm/i8253.h +++ b/arch/x86/include/asm/i8253.h @@ -6,7 +6,7 @@ #define PIT_CH0 0x40 #define PIT_CH2 0x42 -extern spinlock_t i8253_lock; +extern raw_spinlock_t i8253_lock; extern struct clock_event_device *global_clock_event; diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c index 031aa88..c4f9182 100644 --- a/arch/x86/kernel/apm_32.c +++ b/arch/x86/kernel/apm_32.c @@ -1224,7 +1224,7 @@ static void reinit_timer(void) #ifdef INIT_TIMER_AFTER_SUSPEND unsigned long flags; - spin_lock_irqsave(&i8253_lock, flags); + raw_spin_lock_irqsave(&i8253_lock, flags); /* set the clock to HZ */ outb_pit(0x34, PIT_MODE); /* binary, mode 2, LSB/MSB, ch 0 */ udelay(10); @@ -1232,7 +1232,7 @@ static void reinit_timer(void) udelay(10); outb_pit(LATCH >> 8, PIT_CH0); /* MSB */ udelay(10); - spin_unlock_irqrestore(&i8253_lock, flags); + raw_spin_unlock_irqrestore(&i8253_lock, flags); #endif } diff --git a/arch/x86/kernel/i8253.c b/arch/x86/kernel/i8253.c index 23c1679..2dfd315 100644 --- a/arch/x86/kernel/i8253.c +++ b/arch/x86/kernel/i8253.c @@ -16,7 +16,7 @@ #include #include -DEFINE_SPINLOCK(i8253_lock); +DEFINE_RAW_SPINLOCK(i8253_lock); EXPORT_SYMBOL(i8253_lock); /* @@ -33,7 +33,7 @@ struct clock_event_device *global_clock_event; static void init_pit_timer(enum clock_event_mode mode, struct clock_event_device *evt) { - spin_lock(&i8253_lock); + raw_spin_lock(&i8253_lock); switch (mode) { case CLOCK_EVT_MODE_PERIODIC: @@ -62,7 +62,7 @@ static void init_pit_timer(enum clock_event_mode mode, /* Nothing to do here */ break; } - spin_unlock(&i8253_lock); + raw_spin_unlock(&i8253_lock); } /* @@ -72,10 +72,10 @@ static void init_pit_timer(enum clock_event_mode mode, */ static int pit_next_event(unsigned long delta, struct clock_event_device *evt) { - spin_lock(&i8253_lock); + raw_spin_lock(&i8253_lock); outb_pit(delta & 0xff , PIT_CH0); /* LSB */ outb_pit(delta >> 8 , PIT_CH0); /* MSB */ - spin_unlock(&i8253_lock); + raw_spin_unlock(&i8253_lock); return 0; } @@ -130,7 +130,7 @@ static cycle_t pit_read(struct clocksource *cs) int count; u32 jifs; - spin_lock_irqsave(&i8253_lock, flags); + raw_spin_lock_irqsave(&i8253_lock, flags); /* * Although our caller may have the read side of xtime_lock, * this is now a seqlock, and we are cheating in this routine @@ -176,7 +176,7 @@ static cycle_t pit_read(struct clocksource *cs) old_count = count; old_jifs = jifs; - spin_unlock_irqrestore(&i8253_lock, flags); + raw_spin_unlock_irqrestore(&i8253_lock, flags); count = (LATCH - 1) - count; diff --git a/drivers/block/hd.c b/drivers/block/hd.c index 5116c65..b9868ad 100644 --- a/drivers/block/hd.c +++ b/drivers/block/hd.c @@ -165,12 +165,12 @@ unsigned long read_timer(void) unsigned long t, flags; int i; - spin_lock_irqsave(&i8253_lock, flags); + raw_spin_lock_irqsave(&i8253_lock, flags); t = jiffies * 11932; outb_p(0, 0x43); i = inb_p(0x40); i |= inb(0x40) << 8; - spin_unlock_irqrestore(&i8253_lock, flags); + raw_spin_unlock_irqrestore(&i8253_lock, flags); return(t - i); } #endif diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index 7e18bcf..46239e4 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c @@ -59,11 +59,11 @@ static unsigned int get_time_pit(void) unsigned long flags; unsigned int count; - spin_lock_irqsave(&i8253_lock, flags); + raw_spin_lock_irqsave(&i8253_lock, flags); outb_p(0x00, 0x43); count = inb_p(0x40); count |= inb_p(0x40) << 8; - spin_unlock_irqrestore(&i8253_lock, flags); + raw_spin_unlock_irqrestore(&i8253_lock, flags); return count; } diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index 1c0b529..4afe0a3 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c @@ -146,11 +146,11 @@ static unsigned int get_time_pit(void) unsigned long flags; unsigned int count; - spin_lock_irqsave(&i8253_lock, flags); + raw_spin_lock_irqsave(&i8253_lock, flags); outb_p(0x00, 0x43); count = inb_p(0x40); count |= inb_p(0x40) << 8; - spin_unlock_irqrestore(&i8253_lock, flags); + raw_spin_unlock_irqrestore(&i8253_lock, flags); return count; } diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c index ea4e1fd..f080dd3 100644 --- a/drivers/input/misc/pcspkr.c +++ b/drivers/input/misc/pcspkr.c @@ -30,7 +30,7 @@ MODULE_ALIAS("platform:pcspkr"); #include #else #include -static DEFINE_SPINLOCK(i8253_lock); +static DEFINE_RAW_SPINLOCK(i8253_lock); #endif static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) @@ -50,7 +50,7 @@ static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int c if (value > 20 && value < 32767) count = PIT_TICK_RATE / value; - spin_lock_irqsave(&i8253_lock, flags); + raw_spin_lock_irqsave(&i8253_lock, flags); if (count) { /* set command for counter 2, 2 byte write */ @@ -65,7 +65,7 @@ static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int c outb(inb_p(0x61) & 0xFC, 0x61); } - spin_unlock_irqrestore(&i8253_lock, flags); + raw_spin_unlock_irqrestore(&i8253_lock, flags); return 0; } diff --git a/sound/drivers/pcsp/pcsp.h b/sound/drivers/pcsp/pcsp.h index 1e12307..4ff6c8c 100644 --- a/sound/drivers/pcsp/pcsp.h +++ b/sound/drivers/pcsp/pcsp.h @@ -16,7 +16,7 @@ #include #else #include -static DEFINE_SPINLOCK(i8253_lock); +static DEFINE_RAW_SPINLOCK(i8253_lock); #endif #define PCSP_SOUND_VERSION 0x400 /* read 4.00 */ diff --git a/sound/drivers/pcsp/pcsp_input.c b/sound/drivers/pcsp/pcsp_input.c index 0444cde..b5e2b54 100644 --- a/sound/drivers/pcsp/pcsp_input.c +++ b/sound/drivers/pcsp/pcsp_input.c @@ -21,7 +21,7 @@ static void pcspkr_do_sound(unsigned int count) { unsigned long flags; - spin_lock_irqsave(&i8253_lock, flags); + raw_spin_lock_irqsave(&i8253_lock, flags); if (count) { /* set command for counter 2, 2 byte write */ @@ -36,7 +36,7 @@ static void pcspkr_do_sound(unsigned int count) outb(inb_p(0x61) & 0xFC, 0x61); } - spin_unlock_irqrestore(&i8253_lock, flags); + raw_spin_unlock_irqrestore(&i8253_lock, flags); } void pcspkr_stop_sound(void) diff --git a/sound/drivers/pcsp/pcsp_lib.c b/sound/drivers/pcsp/pcsp_lib.c index e1145ac..f6a2e72 100644 --- a/sound/drivers/pcsp/pcsp_lib.c +++ b/sound/drivers/pcsp/pcsp_lib.c @@ -65,7 +65,7 @@ static u64 pcsp_timer_update(struct snd_pcsp *chip) timer_cnt = val * CUR_DIV() / 256; if (timer_cnt && chip->enable) { - spin_lock_irqsave(&i8253_lock, flags); + raw_spin_lock_irqsave(&i8253_lock, flags); if (!nforce_wa) { outb_p(chip->val61, 0x61); outb_p(timer_cnt, 0x42); @@ -74,7 +74,7 @@ static u64 pcsp_timer_update(struct snd_pcsp *chip) outb(chip->val61 ^ 2, 0x61); chip->thalf = 1; } - spin_unlock_irqrestore(&i8253_lock, flags); + raw_spin_unlock_irqrestore(&i8253_lock, flags); } chip->ns_rem = PCSP_PERIOD_NS(); @@ -158,10 +158,10 @@ static int pcsp_start_playing(struct snd_pcsp *chip) return -EIO; } - spin_lock(&i8253_lock); + raw_spin_lock(&i8253_lock); chip->val61 = inb(0x61) | 0x03; outb_p(0x92, 0x43); /* binary, mode 1, LSB only, ch 2 */ - spin_unlock(&i8253_lock); + raw_spin_unlock(&i8253_lock); atomic_set(&chip->timer_active, 1); chip->thalf = 0; @@ -178,11 +178,11 @@ static void pcsp_stop_playing(struct snd_pcsp *chip) return; atomic_set(&chip->timer_active, 0); - spin_lock(&i8253_lock); + raw_spin_lock(&i8253_lock); /* restore the timer */ outb_p(0xb6, 0x43); /* binary, mode 3, LSB/MSB, ch 2 */ outb(chip->val61 & 0xFC, 0x61); - spin_unlock(&i8253_lock); + raw_spin_unlock(&i8253_lock); } /* -- cgit v0.10.2 From bc078e4eab65f11bbaeed380593ab8151b30d703 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Tue, 2 Mar 2010 16:01:10 +0100 Subject: oprofile: convert oprofile from timer_hook to hrtimer Oprofile is currently broken on systems running with NOHZ enabled. A maximum of 1 tick is accounted via the timer_hook if a cpu sleeps for a longer period of time. This does bad things to the percentages in the profiler output. To solve this problem convert oprofile to use a restarting hrtimer instead of the timer_hook. Signed-off-by: Martin Schwidefsky Signed-off-by: Robert Richter diff --git a/drivers/oprofile/oprof.c b/drivers/oprofile/oprof.c index dc8a042..b336cd9 100644 --- a/drivers/oprofile/oprof.c +++ b/drivers/oprofile/oprof.c @@ -253,22 +253,26 @@ static int __init oprofile_init(void) int err; err = oprofile_arch_init(&oprofile_ops); - if (err < 0 || timer) { printk(KERN_INFO "oprofile: using timer interrupt.\n"); - oprofile_timer_init(&oprofile_ops); + err = oprofile_timer_init(&oprofile_ops); + if (err) + goto out_arch; } - err = oprofilefs_register(); if (err) - oprofile_arch_exit(); + goto out_arch; + return 0; +out_arch: + oprofile_arch_exit(); return err; } static void __exit oprofile_exit(void) { + oprofile_timer_exit(); oprofilefs_unregister(); oprofile_arch_exit(); } diff --git a/drivers/oprofile/oprof.h b/drivers/oprofile/oprof.h index cb92f5c..47e12cb 100644 --- a/drivers/oprofile/oprof.h +++ b/drivers/oprofile/oprof.h @@ -34,7 +34,8 @@ struct super_block; struct dentry; void oprofile_create_files(struct super_block *sb, struct dentry *root); -void oprofile_timer_init(struct oprofile_operations *ops); +int oprofile_timer_init(struct oprofile_operations *ops); +void oprofile_timer_exit(void); int oprofile_set_backtrace(unsigned long depth); int oprofile_set_timeout(unsigned long time); diff --git a/drivers/oprofile/timer_int.c b/drivers/oprofile/timer_int.c index 333f915..dc0ae4d 100644 --- a/drivers/oprofile/timer_int.c +++ b/drivers/oprofile/timer_int.c @@ -13,34 +13,94 @@ #include #include #include +#include +#include +#include #include #include "oprof.h" -static int timer_notify(struct pt_regs *regs) +static DEFINE_PER_CPU(struct hrtimer, oprofile_hrtimer); + +static enum hrtimer_restart oprofile_hrtimer_notify(struct hrtimer *hrtimer) +{ + oprofile_add_sample(get_irq_regs(), 0); + hrtimer_forward_now(hrtimer, ns_to_ktime(TICK_NSEC)); + return HRTIMER_RESTART; +} + +static void __oprofile_hrtimer_start(void *unused) +{ + struct hrtimer *hrtimer = &__get_cpu_var(oprofile_hrtimer); + + hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + hrtimer->function = oprofile_hrtimer_notify; + + hrtimer_start(hrtimer, ns_to_ktime(TICK_NSEC), + HRTIMER_MODE_REL_PINNED); +} + +static int oprofile_hrtimer_start(void) { - oprofile_add_sample(regs, 0); + on_each_cpu(__oprofile_hrtimer_start, NULL, 1); return 0; } -static int timer_start(void) +static void __oprofile_hrtimer_stop(int cpu) { - return register_timer_hook(timer_notify); + struct hrtimer *hrtimer = &per_cpu(oprofile_hrtimer, cpu); + + hrtimer_cancel(hrtimer); } +static void oprofile_hrtimer_stop(void) +{ + int cpu; + + for_each_online_cpu(cpu) + __oprofile_hrtimer_stop(cpu); +} -static void timer_stop(void) +static int __cpuinit oprofile_cpu_notify(struct notifier_block *self, + unsigned long action, void *hcpu) { - unregister_timer_hook(timer_notify); + long cpu = (long) hcpu; + + switch (action) { + case CPU_ONLINE: + case CPU_ONLINE_FROZEN: + smp_call_function_single(cpu, __oprofile_hrtimer_start, + NULL, 1); + break; + case CPU_DEAD: + case CPU_DEAD_FROZEN: + __oprofile_hrtimer_stop(cpu); + break; + } + return NOTIFY_OK; } +static struct notifier_block __refdata oprofile_cpu_notifier = { + .notifier_call = oprofile_cpu_notify, +}; -void __init oprofile_timer_init(struct oprofile_operations *ops) +int __init oprofile_timer_init(struct oprofile_operations *ops) { + int rc; + + rc = register_hotcpu_notifier(&oprofile_cpu_notifier); + if (rc) + return rc; ops->create_files = NULL; ops->setup = NULL; ops->shutdown = NULL; - ops->start = timer_start; - ops->stop = timer_stop; + ops->start = oprofile_hrtimer_start; + ops->stop = oprofile_hrtimer_stop; ops->cpu_type = "timer"; + return 0; +} + +void __exit oprofile_timer_exit(void) +{ + unregister_hotcpu_notifier(&oprofile_cpu_notifier); } -- cgit v0.10.2 From 4abc14a733f9002c05623db755aaafdd27fa7a91 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 20 Jan 2010 14:52:23 +0100 Subject: iommu-api: Rename ->{un}map function pointers to ->{un}map_range The new function pointer names match better with the top-level functions of the iommu-api which are using them. Main intention of this change is to make the ->{un}map pointer names free for two new mapping functions. Signed-off-by: Joerg Roedel diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index adb0ba0..59cae7c 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -2515,8 +2515,8 @@ static struct iommu_ops amd_iommu_ops = { .domain_destroy = amd_iommu_domain_destroy, .attach_dev = amd_iommu_attach_device, .detach_dev = amd_iommu_detach_device, - .map = amd_iommu_map_range, - .unmap = amd_iommu_unmap_range, + .map_range = amd_iommu_map_range, + .unmap_range = amd_iommu_unmap_range, .iova_to_phys = amd_iommu_iova_to_phys, .domain_has_cap = amd_iommu_domain_has_cap, }; diff --git a/drivers/base/iommu.c b/drivers/base/iommu.c index 8ad4ffe..f4c86c4 100644 --- a/drivers/base/iommu.c +++ b/drivers/base/iommu.c @@ -83,14 +83,14 @@ EXPORT_SYMBOL_GPL(iommu_detach_device); int iommu_map_range(struct iommu_domain *domain, unsigned long iova, phys_addr_t paddr, size_t size, int prot) { - return iommu_ops->map(domain, iova, paddr, size, prot); + return iommu_ops->map_range(domain, iova, paddr, size, prot); } EXPORT_SYMBOL_GPL(iommu_map_range); void iommu_unmap_range(struct iommu_domain *domain, unsigned long iova, size_t size) { - iommu_ops->unmap(domain, iova, size); + iommu_ops->unmap_range(domain, iova, size); } EXPORT_SYMBOL_GPL(iommu_unmap_range); diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 4173125..a714e3d 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -3714,8 +3714,8 @@ static struct iommu_ops intel_iommu_ops = { .domain_destroy = intel_iommu_domain_destroy, .attach_dev = intel_iommu_attach_device, .detach_dev = intel_iommu_detach_device, - .map = intel_iommu_map_range, - .unmap = intel_iommu_unmap_range, + .map_range = intel_iommu_map_range, + .unmap_range = intel_iommu_unmap_range, .iova_to_phys = intel_iommu_iova_to_phys, .domain_has_cap = intel_iommu_domain_has_cap, }; diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 3af4ffd..0f18f37 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -36,10 +36,10 @@ struct iommu_ops { void (*domain_destroy)(struct iommu_domain *domain); int (*attach_dev)(struct iommu_domain *domain, struct device *dev); void (*detach_dev)(struct iommu_domain *domain, struct device *dev); - int (*map)(struct iommu_domain *domain, unsigned long iova, - phys_addr_t paddr, size_t size, int prot); - void (*unmap)(struct iommu_domain *domain, unsigned long iova, - size_t size); + int (*map_range)(struct iommu_domain *domain, unsigned long iova, + phys_addr_t paddr, size_t size, int prot); + void (*unmap_range)(struct iommu_domain *domain, unsigned long iova, + size_t size); phys_addr_t (*iova_to_phys)(struct iommu_domain *domain, unsigned long iova); int (*domain_has_cap)(struct iommu_domain *domain, -- cgit v0.10.2 From cefc53c7f494240d4813c80154c7617452d1904d Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Fri, 8 Jan 2010 13:35:09 +0100 Subject: iommu-api: Add iommu_map and iommu_unmap functions These two functions provide support for mapping and unmapping physical addresses to io virtual addresses. The difference to the iommu_(un)map_range() is that the new functions take a gfp_order parameter instead of a size. This allows the IOMMU backend implementations to detect easier if a given range can be mapped by larger page sizes. These new functions should replace the old ones in the long term. Signed-off-by: Joerg Roedel diff --git a/drivers/base/iommu.c b/drivers/base/iommu.c index f4c86c4..cf7cbec 100644 --- a/drivers/base/iommu.c +++ b/drivers/base/iommu.c @@ -107,3 +107,34 @@ int iommu_domain_has_cap(struct iommu_domain *domain, return iommu_ops->domain_has_cap(domain, cap); } EXPORT_SYMBOL_GPL(iommu_domain_has_cap); + +int iommu_map(struct iommu_domain *domain, unsigned long iova, + phys_addr_t paddr, int gfp_order, int prot) +{ + unsigned long invalid_mask; + size_t size; + + size = 0x1000UL << gfp_order; + invalid_mask = size - 1; + + BUG_ON((iova | paddr) & invalid_mask); + + return iommu_ops->map_range(domain, iova, paddr, size, prot); +} +EXPORT_SYMBOL_GPL(iommu_map); + +int iommu_unmap(struct iommu_domain *domain, unsigned long iova, int gfp_order) +{ + unsigned long invalid_mask; + size_t size; + + size = 0x1000UL << gfp_order; + invalid_mask = size - 1; + + BUG_ON(iova & invalid_mask); + + iommu_ops->unmap_range(domain, iova, size); + + return gfp_order; +} +EXPORT_SYMBOL_GPL(iommu_unmap); diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 0f18f37..6d0035b 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -60,6 +60,10 @@ extern int iommu_map_range(struct iommu_domain *domain, unsigned long iova, phys_addr_t paddr, size_t size, int prot); extern void iommu_unmap_range(struct iommu_domain *domain, unsigned long iova, size_t size); +extern int iommu_map(struct iommu_domain *domain, unsigned long iova, + phys_addr_t paddr, int gfp_order, int prot); +extern int iommu_unmap(struct iommu_domain *domain, unsigned long iova, + int gfp_order); extern phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, unsigned long iova); extern int iommu_domain_has_cap(struct iommu_domain *domain, @@ -108,6 +112,18 @@ static inline void iommu_unmap_range(struct iommu_domain *domain, { } +static inline int iommu_map(struct iommu_domain *domain, unsigned long iova, + phys_addr_t paddr, int gfp_order, int prot) +{ + return -ENODEV; +} + +static inline int iommu_unmap(struct iommu_domain *domain, unsigned long iova, + int gfp_order) +{ + return -ENODEV; +} + static inline phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, unsigned long iova) { -- cgit v0.10.2 From 67651786948c360c3122b8a17cb1e59209d50880 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 21 Jan 2010 16:32:27 +0100 Subject: iommu-api: Add ->{un}map callbacks to iommu_ops This patch adds new callbacks for mapping and unmapping pages to the iommu_ops structure. These callbacks are aware of page sizes which makes them different to the ->{un}map_range callbacks. Signed-off-by: Joerg Roedel diff --git a/drivers/base/iommu.c b/drivers/base/iommu.c index cf7cbec..55d37e4 100644 --- a/drivers/base/iommu.c +++ b/drivers/base/iommu.c @@ -119,6 +119,9 @@ int iommu_map(struct iommu_domain *domain, unsigned long iova, BUG_ON((iova | paddr) & invalid_mask); + if (iommu_ops->map) + return iommu_ops->map(domain, iova, paddr, gfp_order, prot); + return iommu_ops->map_range(domain, iova, paddr, size, prot); } EXPORT_SYMBOL_GPL(iommu_map); @@ -133,6 +136,9 @@ int iommu_unmap(struct iommu_domain *domain, unsigned long iova, int gfp_order) BUG_ON(iova & invalid_mask); + if (iommu_ops->unmap) + return iommu_ops->unmap(domain, iova, gfp_order); + iommu_ops->unmap_range(domain, iova, size); return gfp_order; diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 6d0035b..5a7a3d8 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -36,6 +36,10 @@ struct iommu_ops { void (*domain_destroy)(struct iommu_domain *domain); int (*attach_dev)(struct iommu_domain *domain, struct device *dev); void (*detach_dev)(struct iommu_domain *domain, struct device *dev); + int (*map)(struct iommu_domain *domain, unsigned long iova, + phys_addr_t paddr, int gfp_order, int prot); + int (*unmap)(struct iommu_domain *domain, unsigned long iova, + int gfp_order); int (*map_range)(struct iommu_domain *domain, unsigned long iova, phys_addr_t paddr, size_t size, int prot); void (*unmap_range)(struct iommu_domain *domain, unsigned long iova, -- cgit v0.10.2 From b146a1c9f7f1feeacf840fa1ba197a99593cea15 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 20 Jan 2010 17:17:37 +0100 Subject: VT-d: Change {un}map_range functions to implement {un}map interface This patch changes the iommu-api functions for mapping and unmapping page ranges to use the new page-size based interface. This allows to remove the range based functions later. Signed-off-by: Joerg Roedel diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index a714e3d..371dc56 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -3626,14 +3626,15 @@ static void intel_iommu_detach_device(struct iommu_domain *domain, domain_remove_one_dev_info(dmar_domain, pdev); } -static int intel_iommu_map_range(struct iommu_domain *domain, - unsigned long iova, phys_addr_t hpa, - size_t size, int iommu_prot) +static int intel_iommu_map(struct iommu_domain *domain, + unsigned long iova, phys_addr_t hpa, + int gfp_order, int iommu_prot) { struct dmar_domain *dmar_domain = domain->priv; u64 max_addr; int addr_width; int prot = 0; + size_t size; int ret; if (iommu_prot & IOMMU_READ) @@ -3643,6 +3644,7 @@ static int intel_iommu_map_range(struct iommu_domain *domain, if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping) prot |= DMA_PTE_SNP; + size = PAGE_SIZE << gfp_order; max_addr = iova + size; if (dmar_domain->max_addr < max_addr) { int min_agaw; @@ -3669,19 +3671,19 @@ static int intel_iommu_map_range(struct iommu_domain *domain, return ret; } -static void intel_iommu_unmap_range(struct iommu_domain *domain, - unsigned long iova, size_t size) +static int intel_iommu_unmap(struct iommu_domain *domain, + unsigned long iova, int gfp_order) { struct dmar_domain *dmar_domain = domain->priv; - - if (!size) - return; + size_t size = PAGE_SIZE << gfp_order; dma_pte_clear_range(dmar_domain, iova >> VTD_PAGE_SHIFT, (iova + size - 1) >> VTD_PAGE_SHIFT); if (dmar_domain->max_addr == iova + size) dmar_domain->max_addr = iova; + + return gfp_order; } static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain, @@ -3714,8 +3716,8 @@ static struct iommu_ops intel_iommu_ops = { .domain_destroy = intel_iommu_domain_destroy, .attach_dev = intel_iommu_attach_device, .detach_dev = intel_iommu_detach_device, - .map_range = intel_iommu_map_range, - .unmap_range = intel_iommu_unmap_range, + .map = intel_iommu_map, + .unmap = intel_iommu_unmap, .iova_to_phys = intel_iommu_iova_to_phys, .domain_has_cap = intel_iommu_domain_has_cap, }; -- cgit v0.10.2 From fcd95807fb61e67d602610e7ff7129ed769e9fee Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Mon, 11 Jan 2010 16:38:18 +0100 Subject: kvm: Change kvm_iommu_map_pages to map large pages This patch changes the implementation of of kvm_iommu_map_pages to map the pages with the host page size into the io virtual address space. Signed-off-by: Joerg Roedel Acked-By: Avi Kivity diff --git a/virt/kvm/iommu.c b/virt/kvm/iommu.c index 80fd3ad..11692b9 100644 --- a/virt/kvm/iommu.c +++ b/virt/kvm/iommu.c @@ -32,12 +32,30 @@ static int kvm_iommu_unmap_memslots(struct kvm *kvm); static void kvm_iommu_put_pages(struct kvm *kvm, gfn_t base_gfn, unsigned long npages); +static pfn_t kvm_pin_pages(struct kvm *kvm, struct kvm_memory_slot *slot, + gfn_t gfn, unsigned long size) +{ + gfn_t end_gfn; + pfn_t pfn; + + pfn = gfn_to_pfn_memslot(kvm, slot, gfn); + end_gfn = gfn + (size >> PAGE_SHIFT); + gfn += 1; + + if (is_error_pfn(pfn)) + return pfn; + + while (gfn < end_gfn) + gfn_to_pfn_memslot(kvm, slot, gfn++); + + return pfn; +} + int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot) { - gfn_t gfn = slot->base_gfn; - unsigned long npages = slot->npages; + gfn_t gfn, end_gfn; pfn_t pfn; - int i, r = 0; + int r = 0; struct iommu_domain *domain = kvm->arch.iommu_domain; int flags; @@ -45,31 +63,62 @@ int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot) if (!domain) return 0; + gfn = slot->base_gfn; + end_gfn = gfn + slot->npages; + flags = IOMMU_READ | IOMMU_WRITE; if (kvm->arch.iommu_flags & KVM_IOMMU_CACHE_COHERENCY) flags |= IOMMU_CACHE; - for (i = 0; i < npages; i++) { - /* check if already mapped */ - if (iommu_iova_to_phys(domain, gfn_to_gpa(gfn))) + + while (gfn < end_gfn) { + unsigned long page_size; + + /* Check if already mapped */ + if (iommu_iova_to_phys(domain, gfn_to_gpa(gfn))) { + gfn += 1; + continue; + } + + /* Get the page size we could use to map */ + page_size = kvm_host_page_size(kvm, gfn); + + /* Make sure the page_size does not exceed the memslot */ + while ((gfn + (page_size >> PAGE_SHIFT)) > end_gfn) + page_size >>= 1; + + /* Make sure gfn is aligned to the page size we want to map */ + while ((gfn << PAGE_SHIFT) & (page_size - 1)) + page_size >>= 1; + + /* + * Pin all pages we are about to map in memory. This is + * important because we unmap and unpin in 4kb steps later. + */ + pfn = kvm_pin_pages(kvm, slot, gfn, page_size); + if (is_error_pfn(pfn)) { + gfn += 1; continue; + } - pfn = gfn_to_pfn_memslot(kvm, slot, gfn); - r = iommu_map_range(domain, - gfn_to_gpa(gfn), - pfn_to_hpa(pfn), - PAGE_SIZE, flags); + /* Map into IO address space */ + r = iommu_map(domain, gfn_to_gpa(gfn), pfn_to_hpa(pfn), + get_order(page_size), flags); if (r) { printk(KERN_ERR "kvm_iommu_map_address:" "iommu failed to map pfn=%lx\n", pfn); goto unmap_pages; } - gfn++; + + gfn += page_size >> PAGE_SHIFT; + + } + return 0; unmap_pages: - kvm_iommu_put_pages(kvm, slot->base_gfn, i); + kvm_iommu_put_pages(kvm, slot->base_gfn, gfn); return r; } @@ -189,27 +238,47 @@ out_unmap: return r; } +static void kvm_unpin_pages(struct kvm *kvm, pfn_t pfn, unsigned long npages) +{ + unsigned long i; + + for (i = 0; i < npages; ++i) + kvm_release_pfn_clean(pfn + i); +} + static void kvm_iommu_put_pages(struct kvm *kvm, gfn_t base_gfn, unsigned long npages) { - gfn_t gfn = base_gfn; + struct iommu_domain *domain; + gfn_t end_gfn, gfn; pfn_t pfn; - struct iommu_domain *domain = kvm->arch.iommu_domain; - unsigned long i; u64 phys; + domain = kvm->arch.iommu_domain; + end_gfn = base_gfn + npages; + gfn = base_gfn; + /* check if iommu exists and in use */ if (!domain) return; - for (i = 0; i < npages; i++) { + while (gfn < end_gfn) { + unsigned long unmap_pages; + int order; + + /* Get physical address */ phys = iommu_iova_to_phys(domain, gfn_to_gpa(gfn)); - pfn = phys >> PAGE_SHIFT; - kvm_release_pfn_clean(pfn); - gfn++; - } + pfn = phys >> PAGE_SHIFT; + + /* Unmap address from IO address space */ + order = iommu_unmap(domain, gfn_to_gpa(gfn), PAGE_SIZE); + unmap_pages = 1ULL << order; - iommu_unmap_range(domain, gfn_to_gpa(base_gfn), PAGE_SIZE * npages); + /* Unpin all pages we just unmapped to not leak any memory */ + kvm_unpin_pages(kvm, pfn, unmap_pages); + + gfn += unmap_pages; + } } static int kvm_iommu_unmap_memslots(struct kvm *kvm) -- cgit v0.10.2 From cbb9d729f3433c9c2660b01dc52e6deb89488886 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Fri, 15 Jan 2010 14:41:15 +0100 Subject: x86/amd-iommu: Make iommu_map_page and alloc_pte aware of page sizes This patch changes the old map_size parameter of alloc_pte to a page_size parameter which can be used more easily to alloc a pte for intermediate page sizes. Signed-off-by: Joerg Roedel diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h index ba19ad4..5e8da56 100644 --- a/arch/x86/include/asm/amd_iommu_types.h +++ b/arch/x86/include/asm/amd_iommu_types.h @@ -172,6 +172,34 @@ (~((1ULL << (12 + ((lvl) * 9))) - 1))) #define PM_ALIGNED(lvl, addr) ((PM_MAP_MASK(lvl) & (addr)) == (addr)) +/* + * Returns the page table level to use for a given page size + * Pagesize is expected to be a power-of-two + */ +#define PAGE_SIZE_LEVEL(pagesize) \ + ((__ffs(pagesize) - 12) / 9) +/* + * Returns the number of ptes to use for a given page size + * Pagesize is expected to be a power-of-two + */ +#define PAGE_SIZE_PTE_COUNT(pagesize) \ + (1ULL << ((__ffs(pagesize) - 12) % 9)) + +/* + * Aligns a given io-virtual address to a given page size + * Pagesize is expected to be a power-of-two + */ +#define PAGE_SIZE_ALIGN(address, pagesize) \ + ((address) & ~((pagesize) - 1)) +/* + * Creates an IOMMU PTE for an address an a given pagesize + * The PTE has no permission bits set + * Pagesize is expected to be a power-of-two larger than 4096 + */ +#define PAGE_SIZE_PTE(address, pagesize) \ + (((address) | ((pagesize) - 1)) & \ + (~(pagesize >> 1)) & PM_ADDR_MASK) + #define IOMMU_PTE_P (1ULL << 0) #define IOMMU_PTE_TV (1ULL << 1) #define IOMMU_PTE_U (1ULL << 59) diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 59cae7c..4170031 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -730,18 +730,22 @@ static bool increase_address_space(struct protection_domain *domain, static u64 *alloc_pte(struct protection_domain *domain, unsigned long address, - int end_lvl, + unsigned long page_size, u64 **pte_page, gfp_t gfp) { + int level, end_lvl; u64 *pte, *page; - int level; + + BUG_ON(!is_power_of_2(page_size)); while (address > PM_LEVEL_SIZE(domain->mode)) increase_address_space(domain, gfp); - level = domain->mode - 1; - pte = &domain->pt_root[PM_LEVEL_INDEX(level, address)]; + level = domain->mode - 1; + pte = &domain->pt_root[PM_LEVEL_INDEX(level, address)]; + address = PAGE_SIZE_ALIGN(address, page_size); + end_lvl = PAGE_SIZE_LEVEL(page_size); while (level > end_lvl) { if (!IOMMU_PTE_PRESENT(*pte)) { @@ -751,6 +755,10 @@ static u64 *alloc_pte(struct protection_domain *domain, *pte = PM_LEVEL_PDE(level, virt_to_phys(page)); } + /* No level skipping support yet */ + if (PM_PTE_LEVEL(*pte) != level) + return NULL; + level -= 1; pte = IOMMU_PTE_PAGE(*pte); @@ -806,31 +814,36 @@ static int iommu_map_page(struct protection_domain *dom, unsigned long bus_addr, unsigned long phys_addr, int prot, - int map_size) + unsigned long page_size) { u64 __pte, *pte; - - bus_addr = PAGE_ALIGN(bus_addr); - phys_addr = PAGE_ALIGN(phys_addr); - - BUG_ON(!PM_ALIGNED(map_size, bus_addr)); - BUG_ON(!PM_ALIGNED(map_size, phys_addr)); + int i, count; if (!(prot & IOMMU_PROT_MASK)) return -EINVAL; - pte = alloc_pte(dom, bus_addr, map_size, NULL, GFP_KERNEL); + bus_addr = PAGE_ALIGN(bus_addr); + phys_addr = PAGE_ALIGN(phys_addr); + count = PAGE_SIZE_PTE_COUNT(page_size); + pte = alloc_pte(dom, bus_addr, page_size, NULL, GFP_KERNEL); + + for (i = 0; i < count; ++i) + if (IOMMU_PTE_PRESENT(pte[i])) + return -EBUSY; - if (IOMMU_PTE_PRESENT(*pte)) - return -EBUSY; + if (page_size > PAGE_SIZE) { + __pte = PAGE_SIZE_PTE(phys_addr, page_size); + __pte |= PM_LEVEL_ENC(7) | IOMMU_PTE_P | IOMMU_PTE_FC; + } else + __pte = phys_addr | IOMMU_PTE_P | IOMMU_PTE_FC; - __pte = phys_addr | IOMMU_PTE_P; if (prot & IOMMU_PROT_IR) __pte |= IOMMU_PTE_IR; if (prot & IOMMU_PROT_IW) __pte |= IOMMU_PTE_IW; - *pte = __pte; + for (i = 0; i < count; ++i) + pte[i] = __pte; update_domain(dom); @@ -877,7 +890,7 @@ static int dma_ops_unity_map(struct dma_ops_domain *dma_dom, for (addr = e->address_start; addr < e->address_end; addr += PAGE_SIZE) { ret = iommu_map_page(&dma_dom->domain, addr, addr, e->prot, - PM_MAP_4k); + PAGE_SIZE); if (ret) return ret; /* @@ -1005,7 +1018,7 @@ static int alloc_new_range(struct dma_ops_domain *dma_dom, u64 *pte, *pte_page; for (i = 0; i < num_ptes; ++i) { - pte = alloc_pte(&dma_dom->domain, address, PM_MAP_4k, + pte = alloc_pte(&dma_dom->domain, address, PAGE_SIZE, &pte_page, gfp); if (!pte) goto out_free; @@ -1711,7 +1724,7 @@ static u64* dma_ops_get_pte(struct dma_ops_domain *dom, pte = aperture->pte_pages[APERTURE_PAGE_INDEX(address)]; if (!pte) { - pte = alloc_pte(&dom->domain, address, PM_MAP_4k, &pte_page, + pte = alloc_pte(&dom->domain, address, PAGE_SIZE, &pte_page, GFP_ATOMIC); aperture->pte_pages[APERTURE_PAGE_INDEX(address)] = pte_page; } else @@ -2457,7 +2470,7 @@ static int amd_iommu_map_range(struct iommu_domain *dom, paddr &= PAGE_MASK; for (i = 0; i < npages; ++i) { - ret = iommu_map_page(domain, iova, paddr, prot, PM_MAP_4k); + ret = iommu_map_page(domain, iova, paddr, prot, PAGE_SIZE); if (ret) return ret; -- cgit v0.10.2 From 24cd772315c19e4d9409d0d21367ec1ebab3149f Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Tue, 19 Jan 2010 17:27:39 +0100 Subject: x86/amd-iommu: Make iommu_unmap_page and fetch_pte aware of page sizes This patch extends the functionality of iommu_unmap_page and fetch_pte to support arbitrary page sizes. Signed-off-by: Joerg Roedel diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h index 5e8da56..b150c74 100644 --- a/arch/x86/include/asm/amd_iommu_types.h +++ b/arch/x86/include/asm/amd_iommu_types.h @@ -200,6 +200,12 @@ (((address) | ((pagesize) - 1)) & \ (~(pagesize >> 1)) & PM_ADDR_MASK) +/* + * Takes a PTE value with mode=0x07 and returns the page size it maps + */ +#define PTE_PAGE_SIZE(pte) \ + (1ULL << (1 + ffz(((pte) | 0xfffULL)))) + #define IOMMU_PTE_P (1ULL << 0) #define IOMMU_PTE_TV (1ULL << 1) #define IOMMU_PTE_U (1ULL << 59) diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 4170031..503d312 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -776,28 +776,47 @@ static u64 *alloc_pte(struct protection_domain *domain, * This function checks if there is a PTE for a given dma address. If * there is one, it returns the pointer to it. */ -static u64 *fetch_pte(struct protection_domain *domain, - unsigned long address, int map_size) +static u64 *fetch_pte(struct protection_domain *domain, unsigned long address) { int level; u64 *pte; - level = domain->mode - 1; - pte = &domain->pt_root[PM_LEVEL_INDEX(level, address)]; + if (address > PM_LEVEL_SIZE(domain->mode)) + return NULL; + + level = domain->mode - 1; + pte = &domain->pt_root[PM_LEVEL_INDEX(level, address)]; - while (level > map_size) { + while (level > 0) { + + /* Not Present */ if (!IOMMU_PTE_PRESENT(*pte)) return NULL; + /* Large PTE */ + if (PM_PTE_LEVEL(*pte) == 0x07) { + unsigned long pte_mask, __pte; + + /* + * If we have a series of large PTEs, make + * sure to return a pointer to the first one. + */ + pte_mask = PTE_PAGE_SIZE(*pte); + pte_mask = ~((PAGE_SIZE_PTE_COUNT(pte_mask) << 3) - 1); + __pte = ((unsigned long)pte) & pte_mask; + + return (u64 *)__pte; + } + + /* No level skipping support yet */ + if (PM_PTE_LEVEL(*pte) != level) + return NULL; + level -= 1; + /* Walk to the next level */ pte = IOMMU_PTE_PAGE(*pte); pte = &pte[PM_LEVEL_INDEX(level, address)]; - - if ((PM_PTE_LEVEL(*pte) == 0) && level != map_size) { - pte = NULL; - break; - } } return pte; @@ -850,13 +869,48 @@ static int iommu_map_page(struct protection_domain *dom, return 0; } -static void iommu_unmap_page(struct protection_domain *dom, - unsigned long bus_addr, int map_size) +static unsigned long iommu_unmap_page(struct protection_domain *dom, + unsigned long bus_addr, + unsigned long page_size) { - u64 *pte = fetch_pte(dom, bus_addr, map_size); + unsigned long long unmap_size, unmapped; + u64 *pte; + + BUG_ON(!is_power_of_2(page_size)); + + unmapped = 0; + + while (unmapped < page_size) { + + pte = fetch_pte(dom, bus_addr); + + if (!pte) { + /* + * No PTE for this address + * move forward in 4kb steps + */ + unmap_size = PAGE_SIZE; + } else if (PM_PTE_LEVEL(*pte) == 0) { + /* 4kb PTE found for this address */ + unmap_size = PAGE_SIZE; + *pte = 0ULL; + } else { + int count, i; + + /* Large PTE found which maps this address */ + unmap_size = PTE_PAGE_SIZE(*pte); + count = PAGE_SIZE_PTE_COUNT(unmap_size); + for (i = 0; i < count; i++) + pte[i] = 0ULL; + } + + bus_addr = (bus_addr & ~(unmap_size - 1)) + unmap_size; + unmapped += unmap_size; + } + + BUG_ON(!is_power_of_2(unmapped)); - if (pte) - *pte = 0; + return unmapped; } /* @@ -1054,7 +1108,7 @@ static int alloc_new_range(struct dma_ops_domain *dma_dom, for (i = dma_dom->aperture[index]->offset; i < dma_dom->aperture_size; i += PAGE_SIZE) { - u64 *pte = fetch_pte(&dma_dom->domain, i, PM_MAP_4k); + u64 *pte = fetch_pte(&dma_dom->domain, i); if (!pte || !IOMMU_PTE_PRESENT(*pte)) continue; @@ -2491,7 +2545,7 @@ static void amd_iommu_unmap_range(struct iommu_domain *dom, iova &= PAGE_MASK; for (i = 0; i < npages; ++i) { - iommu_unmap_page(domain, iova, PM_MAP_4k); + iommu_unmap_page(domain, iova, PAGE_SIZE); iova += PAGE_SIZE; } @@ -2506,7 +2560,7 @@ static phys_addr_t amd_iommu_iova_to_phys(struct iommu_domain *dom, phys_addr_t paddr; u64 *pte; - pte = fetch_pte(domain, iova, PM_MAP_4k); + pte = fetch_pte(domain, iova); if (!pte || !IOMMU_PTE_PRESENT(*pte)) return 0; -- cgit v0.10.2 From f03152bb7d0a74f409ad63ed36916444a7493d72 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 21 Jan 2010 16:15:24 +0100 Subject: x86/amd-iommu: Make amd_iommu_iova_to_phys aware of multiple page sizes This patch extends the amd_iommu_iova_to_phys() function to handle different page sizes correctly. It doesn't use fetch_pte() anymore because we don't know (or care about) the page_size used for mapping the given iova. Signed-off-by: Joerg Roedel diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 503d312..52e44af 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -2556,17 +2556,22 @@ static phys_addr_t amd_iommu_iova_to_phys(struct iommu_domain *dom, unsigned long iova) { struct protection_domain *domain = dom->priv; - unsigned long offset = iova & ~PAGE_MASK; + unsigned long offset_mask; phys_addr_t paddr; - u64 *pte; + u64 *pte, __pte; pte = fetch_pte(domain, iova); if (!pte || !IOMMU_PTE_PRESENT(*pte)) return 0; - paddr = *pte & IOMMU_PAGE_MASK; - paddr |= offset; + if (PM_PTE_LEVEL(*pte) == 0) + offset_mask = PAGE_SIZE - 1; + else + offset_mask = PTE_PAGE_SIZE(*pte) - 1; + + __pte = *pte & PM_ADDR_MASK; + paddr = (__pte & ~offset_mask) | (iova & offset_mask); return paddr; } -- cgit v0.10.2 From 468e2366cdb80cf8a691b8bc212260cfbdbd518e Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 21 Jan 2010 16:37:36 +0100 Subject: x86/amd-iommu: Implement ->{un}map callbacks for iommu-api This patch implements the new callbacks for the IOMMU-API with functions that can handle different page sizes in the IOMMU page table. Signed-off-by: Joerg Roedel diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 52e44af..0e068c9 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -2552,6 +2552,33 @@ static void amd_iommu_unmap_range(struct iommu_domain *dom, iommu_flush_tlb_pde(domain); } +static int amd_iommu_map(struct iommu_domain *dom, unsigned long iova, + phys_addr_t paddr, int gfp_order, int iommu_prot) +{ + unsigned long page_size = 0x1000UL << gfp_order; + struct protection_domain *domain = dom->priv; + int prot = 0; + + if (iommu_prot & IOMMU_READ) + prot |= IOMMU_PROT_IR; + if (iommu_prot & IOMMU_WRITE) + prot |= IOMMU_PROT_IW; + + return iommu_map_page(domain, iova, paddr, prot, page_size); +} + +static int amd_iommu_unmap(struct iommu_domain *dom, unsigned long iova, + int gfp_order) +{ + struct protection_domain *domain = dom->priv; + unsigned long page_size, unmap_size; + + page_size = 0x1000UL << gfp_order; + unmap_size = iommu_unmap_page(domain, iova, page_size); + + return get_order(unmap_size); +} + static phys_addr_t amd_iommu_iova_to_phys(struct iommu_domain *dom, unsigned long iova) { @@ -2587,6 +2614,8 @@ static struct iommu_ops amd_iommu_ops = { .domain_destroy = amd_iommu_domain_destroy, .attach_dev = amd_iommu_attach_device, .detach_dev = amd_iommu_detach_device, + .map = amd_iommu_map, + .unmap = amd_iommu_unmap, .map_range = amd_iommu_map_range, .unmap_range = amd_iommu_unmap_range, .iova_to_phys = amd_iommu_iova_to_phys, -- cgit v0.10.2 From 12c7389abe5786349d3ea6da1961cf78d0c1c7cd Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 21 Jan 2010 11:50:28 +0100 Subject: iommu-api: Remove iommu_{un}map_range functions These functions are not longer used and can be removed savely. There functionality is now provided by the iommu_{un}map functions which are also capable of multiple page sizes. Signed-off-by: Joerg Roedel diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 0e068c9..d8da998 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -2506,52 +2506,6 @@ static int amd_iommu_attach_device(struct iommu_domain *dom, return ret; } -static int amd_iommu_map_range(struct iommu_domain *dom, - unsigned long iova, phys_addr_t paddr, - size_t size, int iommu_prot) -{ - struct protection_domain *domain = dom->priv; - unsigned long i, npages = iommu_num_pages(paddr, size, PAGE_SIZE); - int prot = 0; - int ret; - - if (iommu_prot & IOMMU_READ) - prot |= IOMMU_PROT_IR; - if (iommu_prot & IOMMU_WRITE) - prot |= IOMMU_PROT_IW; - - iova &= PAGE_MASK; - paddr &= PAGE_MASK; - - for (i = 0; i < npages; ++i) { - ret = iommu_map_page(domain, iova, paddr, prot, PAGE_SIZE); - if (ret) - return ret; - - iova += PAGE_SIZE; - paddr += PAGE_SIZE; - } - - return 0; -} - -static void amd_iommu_unmap_range(struct iommu_domain *dom, - unsigned long iova, size_t size) -{ - - struct protection_domain *domain = dom->priv; - unsigned long i, npages = iommu_num_pages(iova, size, PAGE_SIZE); - - iova &= PAGE_MASK; - - for (i = 0; i < npages; ++i) { - iommu_unmap_page(domain, iova, PAGE_SIZE); - iova += PAGE_SIZE; - } - - iommu_flush_tlb_pde(domain); -} - static int amd_iommu_map(struct iommu_domain *dom, unsigned long iova, phys_addr_t paddr, int gfp_order, int iommu_prot) { @@ -2616,8 +2570,6 @@ static struct iommu_ops amd_iommu_ops = { .detach_dev = amd_iommu_detach_device, .map = amd_iommu_map, .unmap = amd_iommu_unmap, - .map_range = amd_iommu_map_range, - .unmap_range = amd_iommu_unmap_range, .iova_to_phys = amd_iommu_iova_to_phys, .domain_has_cap = amd_iommu_domain_has_cap, }; diff --git a/drivers/base/iommu.c b/drivers/base/iommu.c index 55d37e4..6e6b6a1 100644 --- a/drivers/base/iommu.c +++ b/drivers/base/iommu.c @@ -80,20 +80,6 @@ void iommu_detach_device(struct iommu_domain *domain, struct device *dev) } EXPORT_SYMBOL_GPL(iommu_detach_device); -int iommu_map_range(struct iommu_domain *domain, unsigned long iova, - phys_addr_t paddr, size_t size, int prot) -{ - return iommu_ops->map_range(domain, iova, paddr, size, prot); -} -EXPORT_SYMBOL_GPL(iommu_map_range); - -void iommu_unmap_range(struct iommu_domain *domain, unsigned long iova, - size_t size) -{ - iommu_ops->unmap_range(domain, iova, size); -} -EXPORT_SYMBOL_GPL(iommu_unmap_range); - phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, unsigned long iova) { @@ -119,10 +105,7 @@ int iommu_map(struct iommu_domain *domain, unsigned long iova, BUG_ON((iova | paddr) & invalid_mask); - if (iommu_ops->map) - return iommu_ops->map(domain, iova, paddr, gfp_order, prot); - - return iommu_ops->map_range(domain, iova, paddr, size, prot); + return iommu_ops->map(domain, iova, paddr, gfp_order, prot); } EXPORT_SYMBOL_GPL(iommu_map); @@ -136,11 +119,6 @@ int iommu_unmap(struct iommu_domain *domain, unsigned long iova, int gfp_order) BUG_ON(iova & invalid_mask); - if (iommu_ops->unmap) - return iommu_ops->unmap(domain, iova, gfp_order); - - iommu_ops->unmap_range(domain, iova, size); - - return gfp_order; + return iommu_ops->unmap(domain, iova, gfp_order); } EXPORT_SYMBOL_GPL(iommu_unmap); diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 5a7a3d8..be22ad8 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -40,10 +40,6 @@ struct iommu_ops { phys_addr_t paddr, int gfp_order, int prot); int (*unmap)(struct iommu_domain *domain, unsigned long iova, int gfp_order); - int (*map_range)(struct iommu_domain *domain, unsigned long iova, - phys_addr_t paddr, size_t size, int prot); - void (*unmap_range)(struct iommu_domain *domain, unsigned long iova, - size_t size); phys_addr_t (*iova_to_phys)(struct iommu_domain *domain, unsigned long iova); int (*domain_has_cap)(struct iommu_domain *domain, @@ -60,10 +56,6 @@ extern int iommu_attach_device(struct iommu_domain *domain, struct device *dev); extern void iommu_detach_device(struct iommu_domain *domain, struct device *dev); -extern int iommu_map_range(struct iommu_domain *domain, unsigned long iova, - phys_addr_t paddr, size_t size, int prot); -extern void iommu_unmap_range(struct iommu_domain *domain, unsigned long iova, - size_t size); extern int iommu_map(struct iommu_domain *domain, unsigned long iova, phys_addr_t paddr, int gfp_order, int prot); extern int iommu_unmap(struct iommu_domain *domain, unsigned long iova, @@ -104,18 +96,6 @@ static inline void iommu_detach_device(struct iommu_domain *domain, { } -static inline int iommu_map_range(struct iommu_domain *domain, - unsigned long iova, phys_addr_t paddr, - size_t size, int prot) -{ - return -ENODEV; -} - -static inline void iommu_unmap_range(struct iommu_domain *domain, - unsigned long iova, size_t size) -{ -} - static inline int iommu_map(struct iommu_domain *domain, unsigned long iova, phys_addr_t paddr, int gfp_order, int prot) { -- cgit v0.10.2 From 51a5006afcd13176276f0935ee57c4cc6f210e83 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 8 Mar 2010 21:45:19 +0900 Subject: sh: Merge clkdev API updates. This rolls in the remainder of the clkdev API bits from the ARM tree. This can more or less be used verbatim, so we just copy it over and nuke our local version. Signed-off-by: Paul Mundt diff --git a/arch/sh/include/asm/clkdev.h b/arch/sh/include/asm/clkdev.h new file mode 100644 index 0000000..5645f35 --- /dev/null +++ b/arch/sh/include/asm/clkdev.h @@ -0,0 +1,35 @@ +/* + * arch/sh/include/asm/clkdev.h + * + * Cloned from arch/arm/include/asm/clkdev.h: + * + * Copyright (C) 2008 Russell King. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Helper for the clk API to assist looking up a struct clk. + */ +#ifndef __ASM_CLKDEV_H +#define __ASM_CLKDEV_H + +struct clk; + +struct clk_lookup { + struct list_head node; + const char *dev_id; + const char *con_id; + struct clk *clk; +}; + +struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id, + const char *dev_fmt, ...); + +void clkdev_add(struct clk_lookup *cl); +void clkdev_drop(struct clk_lookup *cl); + +void clkdev_add_table(struct clk_lookup *, size_t); +int clk_add_alias(const char *, const char *, char *, struct device *); + +#endif diff --git a/arch/sh/include/asm/clock.h b/arch/sh/include/asm/clock.h index 11da4c5..4b19179 100644 --- a/arch/sh/include/asm/clock.h +++ b/arch/sh/include/asm/clock.h @@ -45,13 +45,6 @@ struct clk { struct cpufreq_frequency_table *freq_table; }; -struct clk_lookup { - struct list_head node; - const char *dev_id; - const char *con_id; - struct clk *clk; -}; - #define CLK_ENABLE_ON_INIT (1 << 0) /* Should be defined by processor-specific code */ diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile index 02fd3ae..650b92f 100644 --- a/arch/sh/kernel/Makefile +++ b/arch/sh/kernel/Makefile @@ -11,7 +11,7 @@ endif CFLAGS_REMOVE_return_address.o = -pg -obj-y := debugtraps.o dma-nommu.o dumpstack.o \ +obj-y := clkdev.o debugtraps.o dma-nommu.o dumpstack.o \ idle.o io.o io_generic.o irq.o \ irq_$(BITS).o machvec.o nmi_debug.o process.o \ process_$(BITS).o ptrace_$(BITS).o \ diff --git a/arch/sh/kernel/clkdev.c b/arch/sh/kernel/clkdev.c new file mode 100644 index 0000000..29cd802 --- /dev/null +++ b/arch/sh/kernel/clkdev.c @@ -0,0 +1,162 @@ +/* + * arch/sh/kernel/clkdev.c + * + * Cloned from arch/arm/common/clkdev.c: + * + * Copyright (C) 2008 Russell King. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Helper for the clk API to assist looking up a struct clk. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static LIST_HEAD(clocks); +static DEFINE_MUTEX(clocks_mutex); + +/* + * Find the correct struct clk for the device and connection ID. + * We do slightly fuzzy matching here: + * An entry with a NULL ID is assumed to be a wildcard. + * If an entry has a device ID, it must match + * If an entry has a connection ID, it must match + * Then we take the most specific entry - with the following + * order of precidence: dev+con > dev only > con only. + */ +static struct clk *clk_find(const char *dev_id, const char *con_id) +{ + struct clk_lookup *p; + struct clk *clk = NULL; + int match, best = 0; + + list_for_each_entry(p, &clocks, node) { + match = 0; + if (p->dev_id) { + if (!dev_id || strcmp(p->dev_id, dev_id)) + continue; + match += 2; + } + if (p->con_id) { + if (!con_id || strcmp(p->con_id, con_id)) + continue; + match += 1; + } + if (match == 0) + continue; + + if (match > best) { + clk = p->clk; + best = match; + } + } + return clk; +} + +struct clk *clk_get_sys(const char *dev_id, const char *con_id) +{ + struct clk *clk; + + mutex_lock(&clocks_mutex); + clk = clk_find(dev_id, con_id); + mutex_unlock(&clocks_mutex); + + return clk ? clk : ERR_PTR(-ENOENT); +} +EXPORT_SYMBOL(clk_get_sys); + +void clkdev_add(struct clk_lookup *cl) +{ + mutex_lock(&clocks_mutex); + list_add_tail(&cl->node, &clocks); + mutex_unlock(&clocks_mutex); +} +EXPORT_SYMBOL(clkdev_add); + +void __init clkdev_add_table(struct clk_lookup *cl, size_t num) +{ + mutex_lock(&clocks_mutex); + while (num--) { + list_add_tail(&cl->node, &clocks); + cl++; + } + mutex_unlock(&clocks_mutex); +} + +#define MAX_DEV_ID 20 +#define MAX_CON_ID 16 + +struct clk_lookup_alloc { + struct clk_lookup cl; + char dev_id[MAX_DEV_ID]; + char con_id[MAX_CON_ID]; +}; + +struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id, + const char *dev_fmt, ...) +{ + struct clk_lookup_alloc *cla; + + cla = kzalloc(sizeof(*cla), GFP_KERNEL); + if (!cla) + return NULL; + + cla->cl.clk = clk; + if (con_id) { + strlcpy(cla->con_id, con_id, sizeof(cla->con_id)); + cla->cl.con_id = cla->con_id; + } + + if (dev_fmt) { + va_list ap; + + va_start(ap, dev_fmt); + vscnprintf(cla->dev_id, sizeof(cla->dev_id), dev_fmt, ap); + cla->cl.dev_id = cla->dev_id; + va_end(ap); + } + + return &cla->cl; +} +EXPORT_SYMBOL(clkdev_alloc); + +int clk_add_alias(const char *alias, const char *alias_dev_name, char *id, + struct device *dev) +{ + struct clk *r = clk_get(dev, id); + struct clk_lookup *l; + + if (IS_ERR(r)) + return PTR_ERR(r); + + l = clkdev_alloc(r, alias, alias_dev_name); + clk_put(r); + if (!l) + return -ENODEV; + clkdev_add(l); + return 0; +} +EXPORT_SYMBOL(clk_add_alias); + +/* + * clkdev_drop - remove a clock dynamically allocated + */ +void clkdev_drop(struct clk_lookup *cl) +{ + mutex_lock(&clocks_mutex); + list_del(&cl->node); + mutex_unlock(&clocks_mutex); + kfree(cl); +} +EXPORT_SYMBOL(clkdev_drop); diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c index 83da5de..9ded1bc 100644 --- a/arch/sh/kernel/cpu/clock.c +++ b/arch/sh/kernel/cpu/clock.c @@ -10,10 +10,6 @@ * * Modified for omap shared clock framework by Tony Lindgren * - * With clkdev bits: - * - * Copyright (C) 2008 Russell King. - * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. @@ -30,6 +26,7 @@ #include #include #include +#include #include #include @@ -398,56 +395,6 @@ long clk_round_rate(struct clk *clk, unsigned long rate) EXPORT_SYMBOL_GPL(clk_round_rate); /* - * Find the correct struct clk for the device and connection ID. - * We do slightly fuzzy matching here: - * An entry with a NULL ID is assumed to be a wildcard. - * If an entry has a device ID, it must match - * If an entry has a connection ID, it must match - * Then we take the most specific entry - with the following - * order of precidence: dev+con > dev only > con only. - */ -static struct clk *clk_find(const char *dev_id, const char *con_id) -{ - struct clk_lookup *p; - struct clk *clk = NULL; - int match, best = 0; - - list_for_each_entry(p, &clock_list, node) { - match = 0; - if (p->dev_id) { - if (!dev_id || strcmp(p->dev_id, dev_id)) - continue; - match += 2; - } - if (p->con_id) { - if (!con_id || strcmp(p->con_id, con_id)) - continue; - match += 1; - } - if (match == 0) - continue; - - if (match > best) { - clk = p->clk; - best = match; - } - } - return clk; -} - -struct clk *clk_get_sys(const char *dev_id, const char *con_id) -{ - struct clk *clk; - - mutex_lock(&clock_list_sem); - clk = clk_find(dev_id, con_id); - mutex_unlock(&clock_list_sem); - - return clk ? clk : ERR_PTR(-ENOENT); -} -EXPORT_SYMBOL_GPL(clk_get_sys); - -/* * Returns a clock. Note that we first try to use device id on the bus * and clock name. If this fails, we try to use clock name only. */ -- cgit v0.10.2 From 2e733b3f84fa9c2ae60513c5f7b56d599ed2ae02 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 8 Mar 2010 21:46:37 +0900 Subject: sh: Support early clkdev allocations. early platform devices and the like may need to set up clock aliases, which require an allocation at a time well before the slab allocators are available. The clock framework comes up after bootmem, so using bootmem as a fallback should be sufficient. Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/clkdev.c b/arch/sh/kernel/clkdev.c index 29cd802..defdd6e 100644 --- a/arch/sh/kernel/clkdev.c +++ b/arch/sh/kernel/clkdev.c @@ -20,6 +20,9 @@ #include #include #include +#include +#include +#include #include #include @@ -103,12 +106,16 @@ struct clk_lookup_alloc { char con_id[MAX_CON_ID]; }; -struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id, - const char *dev_fmt, ...) +struct clk_lookup * __init_refok +clkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, ...) { struct clk_lookup_alloc *cla; - cla = kzalloc(sizeof(*cla), GFP_KERNEL); + if (!slab_is_available()) + cla = alloc_bootmem_low_pages(sizeof(*cla)); + else + cla = kzalloc(sizeof(*cla), GFP_KERNEL); + if (!cla) return NULL; -- cgit v0.10.2 From a636ee7fb35b731ba2b331f6294e809bb6be09c8 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 9 Mar 2010 06:57:53 +0000 Subject: driver core: Early dev_name() support. Presently early platform devices suffer from the fact they are unable to use dev_xxx() calls early on due to dev_name() and others being unavailable at the time ->probe() is called. This implements early init_name construction from the matched name/id pair following the semantics of the late device/driver match. As a result, matched IDs (inclusive of requested ones) are preserved when the handoff from the early platform code happens at kobject initialization time. Since we still require kmalloc slabs to be available at this point, using kstrdup() for establishing the init_name works fine. This subsequently needs to be tested from dev_name() prior to the init_name being cleared by the driver core. We don't kfree() since others will already have a handle on the string long before the kobject initialization takes place. This is also needed to permit drivers to use the clock framework early, without having to manually construct their own device IDs from the match id/name pair locally (needed by the early console and timer code on sh and arm). Signed-off-by: Paul Mundt Acked-by: Greg Kroah-Hartman diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 1ba9d617..d2d4926 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -1239,6 +1239,25 @@ static int __init early_platform_driver_probe_id(char *class_str, } if (match) { + /* + * Set up a sensible init_name to enable + * dev_name() and others to be used before the + * rest of the driver core is initialized. + */ + if (!match->dev.init_name) { + char buf[32]; + + if (match->id != -1) + snprintf(buf, sizeof(buf), "%s.%d", + match->name, match->id); + else + snprintf(buf, sizeof(buf), "%s", + match->name); + + match->dev.init_name = kstrdup(buf, GFP_KERNEL); + if (!match->dev.init_name) + return -ENOMEM; + } if (epdrv->pdrv->probe(match)) pr_warning("%s: unable to probe %s early.\n", class_str, match->name); diff --git a/include/linux/device.h b/include/linux/device.h index 1821928..241b96b 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -451,6 +451,10 @@ struct device { static inline const char *dev_name(const struct device *dev) { + /* Use the init name until the kobject becomes available */ + if (dev->init_name) + return dev->init_name; + return kobject_name(&dev->kobj); } -- cgit v0.10.2 From 214a607a4f5bf5a14dab0304ba350cdaf3916795 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 10 Mar 2010 16:26:25 +0900 Subject: clocksource: Use dev_name() universally across the SH drivers. There is no need to copy in the name from the sh timer config now that dev_name() is available early. We prefer the dev_name() variant for consistent naming. Signed-off-by: Paul Mundt diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index 578595c..a1d3811 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -149,13 +149,12 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start) static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate) { - struct sh_timer_config *cfg = p->pdev->dev.platform_data; int ret; /* enable clock */ ret = clk_enable(p->clk); if (ret) { - pr_err("sh_cmt: cannot enable clock \"%s\"\n", cfg->clk); + dev_err(&p->pdev->dev, "cannot enable clock\n"); return ret; } @@ -278,7 +277,7 @@ static void sh_cmt_clock_event_program_verify(struct sh_cmt_priv *p, delay = 1; if (!delay) - pr_warning("sh_cmt: too long delay\n"); + dev_warn(&p->pdev->dev, "too long delay\n"); } while (delay); } @@ -288,7 +287,7 @@ static void sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta) unsigned long flags; if (delta > p->max_match_value) - pr_warning("sh_cmt: delta out of range\n"); + dev_warn(&p->pdev->dev, "delta out of range\n"); spin_lock_irqsave(&p->lock, flags); p->next_match_value = delta; @@ -450,7 +449,7 @@ static int sh_cmt_register_clocksource(struct sh_cmt_priv *p, cs->resume = sh_cmt_clocksource_resume; cs->mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8); cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; - pr_info("sh_cmt: %s used as clock source\n", cs->name); + dev_info(&p->pdev->dev, "used as clock source\n"); clocksource_register(cs); return 0; } @@ -496,13 +495,11 @@ static void sh_cmt_clock_event_mode(enum clock_event_mode mode, switch (mode) { case CLOCK_EVT_MODE_PERIODIC: - pr_info("sh_cmt: %s used for periodic clock events\n", - ced->name); + dev_info(&p->pdev->dev, "used for periodic clock events\n"); sh_cmt_clock_event_start(p, 1); break; case CLOCK_EVT_MODE_ONESHOT: - pr_info("sh_cmt: %s used for oneshot clock events\n", - ced->name); + dev_info(&p->pdev->dev, "used for oneshot clock events\n"); sh_cmt_clock_event_start(p, 0); break; case CLOCK_EVT_MODE_SHUTDOWN: @@ -543,7 +540,7 @@ static void sh_cmt_register_clockevent(struct sh_cmt_priv *p, ced->set_next_event = sh_cmt_clock_event_next; ced->set_mode = sh_cmt_clock_event_mode; - pr_info("sh_cmt: %s used for clock events\n", ced->name); + dev_info(&p->pdev->dev, "used for clock events\n"); clockevents_register_device(ced); } @@ -600,12 +597,12 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) /* map memory, let mapbase point to our channel */ p->mapbase = ioremap_nocache(res->start, resource_size(res)); if (p->mapbase == NULL) { - pr_err("sh_cmt: failed to remap I/O memory\n"); + dev_err(&p->pdev->dev, "failed to remap I/O memory\n"); goto err0; } /* request irq using setup_irq() (too early for request_irq()) */ - p->irqaction.name = cfg->name; + p->irqaction.name = dev_name(&p->pdev->dev); p->irqaction.handler = sh_cmt_interrupt; p->irqaction.dev_id = p; p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL; @@ -613,7 +610,7 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) /* get hold of clock */ p->clk = clk_get(&p->pdev->dev, cfg->clk); if (IS_ERR(p->clk)) { - pr_err("sh_cmt: cannot get clock \"%s\"\n", cfg->clk); + dev_err(&p->pdev->dev, "cannot get clock\n"); ret = PTR_ERR(p->clk); goto err1; } @@ -628,17 +625,17 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) p->clear_bits = ~0xc000; } - ret = sh_cmt_register(p, cfg->name, + ret = sh_cmt_register(p, (char *)dev_name(&p->pdev->dev), cfg->clockevent_rating, cfg->clocksource_rating); if (ret) { - pr_err("sh_cmt: registration failed\n"); + dev_err(&p->pdev->dev, "registration failed\n"); goto err1; } ret = setup_irq(irq, &p->irqaction); if (ret) { - pr_err("sh_cmt: failed to request irq %d\n", irq); + dev_err(&p->pdev->dev, "failed to request irq %d\n", irq); goto err1; } @@ -653,11 +650,10 @@ err0: static int __devinit sh_cmt_probe(struct platform_device *pdev) { struct sh_cmt_priv *p = platform_get_drvdata(pdev); - struct sh_timer_config *cfg = pdev->dev.platform_data; int ret; if (p) { - pr_info("sh_cmt: %s kept as earlytimer\n", cfg->name); + dev_info(&pdev->dev, "kept as earlytimer\n"); return 0; } diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c index 4c8a759..8ce3555 100644 --- a/drivers/clocksource/sh_mtu2.c +++ b/drivers/clocksource/sh_mtu2.c @@ -118,13 +118,12 @@ static void sh_mtu2_start_stop_ch(struct sh_mtu2_priv *p, int start) static int sh_mtu2_enable(struct sh_mtu2_priv *p) { - struct sh_timer_config *cfg = p->pdev->dev.platform_data; int ret; /* enable clock */ ret = clk_enable(p->clk); if (ret) { - pr_err("sh_mtu2: cannot enable clock \"%s\"\n", cfg->clk); + dev_err(&p->pdev->dev, "cannot enable clock\n"); return ret; } @@ -193,8 +192,7 @@ static void sh_mtu2_clock_event_mode(enum clock_event_mode mode, switch (mode) { case CLOCK_EVT_MODE_PERIODIC: - pr_info("sh_mtu2: %s used for periodic clock events\n", - ced->name); + dev_info(&p->pdev->dev, "used for periodic clock events\n"); sh_mtu2_enable(p); break; case CLOCK_EVT_MODE_UNUSED: @@ -221,13 +219,13 @@ static void sh_mtu2_register_clockevent(struct sh_mtu2_priv *p, ced->cpumask = cpumask_of(0); ced->set_mode = sh_mtu2_clock_event_mode; - pr_info("sh_mtu2: %s used for clock events\n", ced->name); + dev_info(&p->pdev->dev, "used for clock events\n"); clockevents_register_device(ced); ret = setup_irq(p->irqaction.irq, &p->irqaction); if (ret) { - pr_err("sh_mtu2: failed to request irq %d\n", - p->irqaction.irq); + dev_err(&p->pdev->dev, "failed to request irq %d\n", + p->irqaction.irq); return; } } @@ -273,12 +271,12 @@ static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev) /* map memory, let mapbase point to our channel */ p->mapbase = ioremap_nocache(res->start, resource_size(res)); if (p->mapbase == NULL) { - pr_err("sh_mtu2: failed to remap I/O memory\n"); + dev_err(&p->pdev->dev, "failed to remap I/O memory\n"); goto err0; } /* setup data for setup_irq() (too early for request_irq()) */ - p->irqaction.name = cfg->name; + p->irqaction.name = dev_name(&p->pdev->dev); p->irqaction.handler = sh_mtu2_interrupt; p->irqaction.dev_id = p; p->irqaction.irq = irq; @@ -287,12 +285,13 @@ static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev) /* get hold of clock */ p->clk = clk_get(&p->pdev->dev, cfg->clk); if (IS_ERR(p->clk)) { - pr_err("sh_mtu2: cannot get clock \"%s\"\n", cfg->clk); + dev_err(&p->pdev->dev, "cannot get clock\n"); ret = PTR_ERR(p->clk); goto err1; } - return sh_mtu2_register(p, cfg->name, cfg->clockevent_rating); + return sh_mtu2_register(p, (char *)dev_name(&p->pdev->dev), + cfg->clockevent_rating); err1: iounmap(p->mapbase); err0: @@ -302,11 +301,10 @@ static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev) static int __devinit sh_mtu2_probe(struct platform_device *pdev) { struct sh_mtu2_priv *p = platform_get_drvdata(pdev); - struct sh_timer_config *cfg = pdev->dev.platform_data; int ret; if (p) { - pr_info("sh_mtu2: %s kept as earlytimer\n", cfg->name); + dev_info(&pdev->dev, "kept as earlytimer\n"); return 0; } diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c index 961f5b5..3423945 100644 --- a/drivers/clocksource/sh_tmu.c +++ b/drivers/clocksource/sh_tmu.c @@ -106,13 +106,12 @@ static void sh_tmu_start_stop_ch(struct sh_tmu_priv *p, int start) static int sh_tmu_enable(struct sh_tmu_priv *p) { - struct sh_timer_config *cfg = p->pdev->dev.platform_data; int ret; /* enable clock */ ret = clk_enable(p->clk); if (ret) { - pr_err("sh_tmu: cannot enable clock \"%s\"\n", cfg->clk); + dev_err(&p->pdev->dev, "cannot enable clock\n"); return ret; } @@ -228,7 +227,7 @@ static int sh_tmu_register_clocksource(struct sh_tmu_priv *p, cs->disable = sh_tmu_clocksource_disable; cs->mask = CLOCKSOURCE_MASK(32); cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; - pr_info("sh_tmu: %s used as clock source\n", cs->name); + dev_info(&p->pdev->dev, "used as clock source\n"); clocksource_register(cs); return 0; } @@ -276,13 +275,11 @@ static void sh_tmu_clock_event_mode(enum clock_event_mode mode, switch (mode) { case CLOCK_EVT_MODE_PERIODIC: - pr_info("sh_tmu: %s used for periodic clock events\n", - ced->name); + dev_info(&p->pdev->dev, "used for periodic clock events\n"); sh_tmu_clock_event_start(p, 1); break; case CLOCK_EVT_MODE_ONESHOT: - pr_info("sh_tmu: %s used for oneshot clock events\n", - ced->name); + dev_info(&p->pdev->dev, "used for oneshot clock events\n"); sh_tmu_clock_event_start(p, 0); break; case CLOCK_EVT_MODE_UNUSED: @@ -323,13 +320,13 @@ static void sh_tmu_register_clockevent(struct sh_tmu_priv *p, ced->set_next_event = sh_tmu_clock_event_next; ced->set_mode = sh_tmu_clock_event_mode; - pr_info("sh_tmu: %s used for clock events\n", ced->name); + dev_info(&p->pdev->dev, "used for clock events\n"); clockevents_register_device(ced); ret = setup_irq(p->irqaction.irq, &p->irqaction); if (ret) { - pr_err("sh_tmu: failed to request irq %d\n", - p->irqaction.irq); + dev_err(&p->pdev->dev, "failed to request irq %d\n", + p->irqaction.irq); return; } } @@ -378,12 +375,12 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev) /* map memory, let mapbase point to our channel */ p->mapbase = ioremap_nocache(res->start, resource_size(res)); if (p->mapbase == NULL) { - pr_err("sh_tmu: failed to remap I/O memory\n"); + dev_err(&p->pdev->dev, "failed to remap I/O memory\n"); goto err0; } /* setup data for setup_irq() (too early for request_irq()) */ - p->irqaction.name = cfg->name; + p->irqaction.name = dev_name(&p->pdev->dev); p->irqaction.handler = sh_tmu_interrupt; p->irqaction.dev_id = p; p->irqaction.irq = irq; @@ -392,12 +389,12 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev) /* get hold of clock */ p->clk = clk_get(&p->pdev->dev, cfg->clk); if (IS_ERR(p->clk)) { - pr_err("sh_tmu: cannot get clock \"%s\"\n", cfg->clk); + dev_err(&p->pdev->dev, "cannot get clock\n"); ret = PTR_ERR(p->clk); goto err1; } - return sh_tmu_register(p, cfg->name, + return sh_tmu_register(p, (char *)dev_name(&p->pdev->dev), cfg->clockevent_rating, cfg->clocksource_rating); err1: @@ -409,11 +406,10 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev) static int __devinit sh_tmu_probe(struct platform_device *pdev) { struct sh_tmu_priv *p = platform_get_drvdata(pdev); - struct sh_timer_config *cfg = pdev->dev.platform_data; int ret; if (p) { - pr_info("sh_tmu: %s kept as earlytimer\n", cfg->name); + dev_info(&pdev->dev, "kept as earlytimer\n"); return 0; } -- cgit v0.10.2 From ec0ffe2ee0e0fb9da4409d86bfd72636450f32df Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 10 Mar 2010 16:28:16 +0900 Subject: sh: Kill off all timer name clobbering. Now that dev_name() can be used early, we no longer require a static string. Kill off all of the superfluous timer names. Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh2/setup-sh7619.c b/arch/sh/kernel/cpu/sh2/setup-sh7619.c index 114c7ce..9b96457 100644 --- a/arch/sh/kernel/cpu/sh2/setup-sh7619.c +++ b/arch/sh/kernel/cpu/sh2/setup-sh7619.c @@ -128,7 +128,6 @@ static struct platform_device eth_device = { }; static struct sh_timer_config cmt0_platform_data = { - .name = "CMT0", .channel_offset = 0x02, .timer_bit = 0, .clk = "peripheral_clk", @@ -138,7 +137,6 @@ static struct sh_timer_config cmt0_platform_data = { static struct resource cmt0_resources[] = { [0] = { - .name = "CMT0", .start = 0xf84a0072, .end = 0xf84a0077, .flags = IORESOURCE_MEM, @@ -160,7 +158,6 @@ static struct platform_device cmt0_device = { }; static struct sh_timer_config cmt1_platform_data = { - .name = "CMT1", .channel_offset = 0x08, .timer_bit = 1, .clk = "peripheral_clk", @@ -170,7 +167,6 @@ static struct sh_timer_config cmt1_platform_data = { static struct resource cmt1_resources[] = { [0] = { - .name = "CMT1", .start = 0xf84a0078, .end = 0xf84a007d, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh2a/setup-mxg.c b/arch/sh/kernel/cpu/sh2a/setup-mxg.c index 8f669dc..5301450 100644 --- a/arch/sh/kernel/cpu/sh2a/setup-mxg.c +++ b/arch/sh/kernel/cpu/sh2a/setup-mxg.c @@ -115,7 +115,6 @@ static DECLARE_INTC_DESC(intc_desc, "mxg", vectors, groups, mask_registers, prio_registers, NULL); static struct sh_timer_config mtu2_0_platform_data = { - .name = "MTU2_0", .channel_offset = -0x80, .timer_bit = 0, .clk = "peripheral_clk", @@ -124,7 +123,6 @@ static struct sh_timer_config mtu2_0_platform_data = { static struct resource mtu2_0_resources[] = { [0] = { - .name = "MTU2_0", .start = 0xff801300, .end = 0xff801326, .flags = IORESOURCE_MEM, @@ -146,7 +144,6 @@ static struct platform_device mtu2_0_device = { }; static struct sh_timer_config mtu2_1_platform_data = { - .name = "MTU2_1", .channel_offset = -0x100, .timer_bit = 1, .clk = "peripheral_clk", @@ -155,7 +152,6 @@ static struct sh_timer_config mtu2_1_platform_data = { static struct resource mtu2_1_resources[] = { [0] = { - .name = "MTU2_1", .start = 0xff801380, .end = 0xff801390, .flags = IORESOURCE_MEM, @@ -177,7 +173,6 @@ static struct platform_device mtu2_1_device = { }; static struct sh_timer_config mtu2_2_platform_data = { - .name = "MTU2_2", .channel_offset = 0x80, .timer_bit = 2, .clk = "peripheral_clk", @@ -186,7 +181,6 @@ static struct sh_timer_config mtu2_2_platform_data = { static struct resource mtu2_2_resources[] = { [0] = { - .name = "MTU2_2", .start = 0xff801000, .end = 0xff80100a, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7201.c b/arch/sh/kernel/cpu/sh2a/setup-sh7201.c index 4ccfeb5..5b07ab5 100644 --- a/arch/sh/kernel/cpu/sh2a/setup-sh7201.c +++ b/arch/sh/kernel/cpu/sh2a/setup-sh7201.c @@ -318,7 +318,6 @@ static struct platform_device rtc_device = { }; static struct sh_timer_config mtu2_0_platform_data = { - .name = "MTU2_0", .channel_offset = -0x80, .timer_bit = 0, .clk = "peripheral_clk", @@ -327,7 +326,6 @@ static struct sh_timer_config mtu2_0_platform_data = { static struct resource mtu2_0_resources[] = { [0] = { - .name = "MTU2_0", .start = 0xfffe4300, .end = 0xfffe4326, .flags = IORESOURCE_MEM, @@ -349,7 +347,6 @@ static struct platform_device mtu2_0_device = { }; static struct sh_timer_config mtu2_1_platform_data = { - .name = "MTU2_1", .channel_offset = -0x100, .timer_bit = 1, .clk = "peripheral_clk", @@ -358,7 +355,6 @@ static struct sh_timer_config mtu2_1_platform_data = { static struct resource mtu2_1_resources[] = { [0] = { - .name = "MTU2_1", .start = 0xfffe4380, .end = 0xfffe4390, .flags = IORESOURCE_MEM, @@ -380,7 +376,6 @@ static struct platform_device mtu2_1_device = { }; static struct sh_timer_config mtu2_2_platform_data = { - .name = "MTU2_2", .channel_offset = 0x80, .timer_bit = 2, .clk = "peripheral_clk", @@ -389,7 +384,6 @@ static struct sh_timer_config mtu2_2_platform_data = { static struct resource mtu2_2_resources[] = { [0] = { - .name = "MTU2_2", .start = 0xfffe4000, .end = 0xfffe400a, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7203.c b/arch/sh/kernel/cpu/sh2a/setup-sh7203.c index 3136966..433ac53 100644 --- a/arch/sh/kernel/cpu/sh2a/setup-sh7203.c +++ b/arch/sh/kernel/cpu/sh2a/setup-sh7203.c @@ -234,7 +234,6 @@ static struct platform_device scif3_device = { }; static struct sh_timer_config cmt0_platform_data = { - .name = "CMT0", .channel_offset = 0x02, .timer_bit = 0, .clk = "peripheral_clk", @@ -244,7 +243,6 @@ static struct sh_timer_config cmt0_platform_data = { static struct resource cmt0_resources[] = { [0] = { - .name = "CMT0", .start = 0xfffec002, .end = 0xfffec007, .flags = IORESOURCE_MEM, @@ -266,7 +264,6 @@ static struct platform_device cmt0_device = { }; static struct sh_timer_config cmt1_platform_data = { - .name = "CMT1", .channel_offset = 0x08, .timer_bit = 1, .clk = "peripheral_clk", @@ -276,7 +273,6 @@ static struct sh_timer_config cmt1_platform_data = { static struct resource cmt1_resources[] = { [0] = { - .name = "CMT1", .start = 0xfffec008, .end = 0xfffec00d, .flags = IORESOURCE_MEM, @@ -298,7 +294,6 @@ static struct platform_device cmt1_device = { }; static struct sh_timer_config mtu2_0_platform_data = { - .name = "MTU2_0", .channel_offset = -0x80, .timer_bit = 0, .clk = "peripheral_clk", @@ -307,7 +302,6 @@ static struct sh_timer_config mtu2_0_platform_data = { static struct resource mtu2_0_resources[] = { [0] = { - .name = "MTU2_0", .start = 0xfffe4300, .end = 0xfffe4326, .flags = IORESOURCE_MEM, @@ -329,7 +323,6 @@ static struct platform_device mtu2_0_device = { }; static struct sh_timer_config mtu2_1_platform_data = { - .name = "MTU2_1", .channel_offset = -0x100, .timer_bit = 1, .clk = "peripheral_clk", @@ -338,7 +331,6 @@ static struct sh_timer_config mtu2_1_platform_data = { static struct resource mtu2_1_resources[] = { [0] = { - .name = "MTU2_1", .start = 0xfffe4380, .end = 0xfffe4390, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c index 0648735..8caecb4 100644 --- a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c +++ b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c @@ -194,7 +194,6 @@ static struct platform_device scif3_device = { }; static struct sh_timer_config cmt0_platform_data = { - .name = "CMT0", .channel_offset = 0x02, .timer_bit = 0, .clk = "peripheral_clk", @@ -204,7 +203,6 @@ static struct sh_timer_config cmt0_platform_data = { static struct resource cmt0_resources[] = { [0] = { - .name = "CMT0", .start = 0xfffec002, .end = 0xfffec007, .flags = IORESOURCE_MEM, @@ -226,7 +224,6 @@ static struct platform_device cmt0_device = { }; static struct sh_timer_config cmt1_platform_data = { - .name = "CMT1", .channel_offset = 0x08, .timer_bit = 1, .clk = "peripheral_clk", @@ -236,7 +233,6 @@ static struct sh_timer_config cmt1_platform_data = { static struct resource cmt1_resources[] = { [0] = { - .name = "CMT1", .start = 0xfffec008, .end = 0xfffec00d, .flags = IORESOURCE_MEM, @@ -258,7 +254,6 @@ static struct platform_device cmt1_device = { }; static struct sh_timer_config mtu2_0_platform_data = { - .name = "MTU2_0", .channel_offset = -0x80, .timer_bit = 0, .clk = "peripheral_clk", @@ -267,7 +262,6 @@ static struct sh_timer_config mtu2_0_platform_data = { static struct resource mtu2_0_resources[] = { [0] = { - .name = "MTU2_0", .start = 0xfffe4300, .end = 0xfffe4326, .flags = IORESOURCE_MEM, @@ -289,7 +283,6 @@ static struct platform_device mtu2_0_device = { }; static struct sh_timer_config mtu2_1_platform_data = { - .name = "MTU2_1", .channel_offset = -0x100, .timer_bit = 1, .clk = "peripheral_clk", @@ -298,7 +291,6 @@ static struct sh_timer_config mtu2_1_platform_data = { static struct resource mtu2_1_resources[] = { [0] = { - .name = "MTU2_1", .start = 0xfffe4380, .end = 0xfffe4390, .flags = IORESOURCE_MEM, @@ -320,7 +312,6 @@ static struct platform_device mtu2_1_device = { }; static struct sh_timer_config mtu2_2_platform_data = { - .name = "MTU2_2", .channel_offset = 0x80, .timer_bit = 2, .clk = "peripheral_clk", @@ -329,7 +320,6 @@ static struct sh_timer_config mtu2_2_platform_data = { static struct resource mtu2_2_resources[] = { [0] = { - .name = "MTU2_2", .start = 0xfffe4000, .end = 0xfffe400a, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7705.c b/arch/sh/kernel/cpu/sh3/setup-sh7705.c index 7b892d6..5e45fb7 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh7705.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh7705.c @@ -124,7 +124,6 @@ static struct platform_device rtc_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x02, .timer_bit = 0, .clk = "peripheral_clk", @@ -133,7 +132,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xfffffe94, .end = 0xfffffe9f, .flags = IORESOURCE_MEM, @@ -155,7 +153,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0xe, .timer_bit = 1, .clk = "peripheral_clk", @@ -164,7 +161,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xfffffea0, .end = 0xfffffeab, .flags = IORESOURCE_MEM, @@ -186,7 +182,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1a, .timer_bit = 2, .clk = "peripheral_clk", @@ -194,7 +189,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xfffffeac, .end = 0xfffffebb, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh3/setup-sh770x.c b/arch/sh/kernel/cpu/sh3/setup-sh770x.c index bc0c4f6..9adb853 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh770x.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh770x.c @@ -157,7 +157,6 @@ static struct platform_device scif2_device = { #endif static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x02, .timer_bit = 0, .clk = "peripheral_clk", @@ -166,7 +165,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xfffffe94, .end = 0xfffffe9f, .flags = IORESOURCE_MEM, @@ -188,7 +186,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0xe, .timer_bit = 1, .clk = "peripheral_clk", @@ -197,7 +194,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xfffffea0, .end = 0xfffffeab, .flags = IORESOURCE_MEM, @@ -219,7 +215,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1a, .timer_bit = 2, .clk = "peripheral_clk", @@ -227,7 +222,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xfffffeac, .end = 0xfffffebb, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7710.c b/arch/sh/kernel/cpu/sh3/setup-sh7710.c index 0845a3a..2e581e3 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh7710.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh7710.c @@ -127,7 +127,6 @@ static struct platform_device scif1_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x02, .timer_bit = 0, .clk = "peripheral_clk", @@ -136,7 +135,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xa412fe94, .end = 0xa412fe9f, .flags = IORESOURCE_MEM, @@ -158,7 +156,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0xe, .timer_bit = 1, .clk = "peripheral_clk", @@ -167,7 +164,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xa412fea0, .end = 0xa412feab, .flags = IORESOURCE_MEM, @@ -189,7 +185,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1a, .timer_bit = 2, .clk = "peripheral_clk", @@ -197,7 +192,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xa412feac, .end = 0xa412feb5, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7720.c b/arch/sh/kernel/cpu/sh3/setup-sh7720.c index a718a62..9a006e1 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh7720.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh7720.c @@ -130,7 +130,6 @@ static struct platform_device usbf_device = { }; static struct sh_timer_config cmt0_platform_data = { - .name = "CMT0", .channel_offset = 0x10, .timer_bit = 0, .clk = "peripheral_clk", @@ -140,7 +139,6 @@ static struct sh_timer_config cmt0_platform_data = { static struct resource cmt0_resources[] = { [0] = { - .name = "CMT0", .start = 0x044a0010, .end = 0x044a001b, .flags = IORESOURCE_MEM, @@ -162,7 +160,6 @@ static struct platform_device cmt0_device = { }; static struct sh_timer_config cmt1_platform_data = { - .name = "CMT1", .channel_offset = 0x20, .timer_bit = 1, .clk = "peripheral_clk", @@ -170,7 +167,6 @@ static struct sh_timer_config cmt1_platform_data = { static struct resource cmt1_resources[] = { [0] = { - .name = "CMT1", .start = 0x044a0020, .end = 0x044a002b, .flags = IORESOURCE_MEM, @@ -192,7 +188,6 @@ static struct platform_device cmt1_device = { }; static struct sh_timer_config cmt2_platform_data = { - .name = "CMT2", .channel_offset = 0x30, .timer_bit = 2, .clk = "peripheral_clk", @@ -200,7 +195,6 @@ static struct sh_timer_config cmt2_platform_data = { static struct resource cmt2_resources[] = { [0] = { - .name = "CMT2", .start = 0x044a0030, .end = 0x044a003b, .flags = IORESOURCE_MEM, @@ -222,7 +216,6 @@ static struct platform_device cmt2_device = { }; static struct sh_timer_config cmt3_platform_data = { - .name = "CMT3", .channel_offset = 0x40, .timer_bit = 3, .clk = "peripheral_clk", @@ -230,7 +223,6 @@ static struct sh_timer_config cmt3_platform_data = { static struct resource cmt3_resources[] = { [0] = { - .name = "CMT3", .start = 0x044a0040, .end = 0x044a004b, .flags = IORESOURCE_MEM, @@ -252,7 +244,6 @@ static struct platform_device cmt3_device = { }; static struct sh_timer_config cmt4_platform_data = { - .name = "CMT4", .channel_offset = 0x50, .timer_bit = 4, .clk = "peripheral_clk", @@ -260,7 +251,6 @@ static struct sh_timer_config cmt4_platform_data = { static struct resource cmt4_resources[] = { [0] = { - .name = "CMT4", .start = 0x044a0050, .end = 0x044a005b, .flags = IORESOURCE_MEM, @@ -282,7 +272,6 @@ static struct platform_device cmt4_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x02, .timer_bit = 0, .clk = "peripheral_clk", @@ -291,7 +280,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xa412fe94, .end = 0xa412fe9f, .flags = IORESOURCE_MEM, @@ -313,7 +301,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0xe, .timer_bit = 1, .clk = "peripheral_clk", @@ -322,7 +309,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xa412fea0, .end = 0xa412feab, .flags = IORESOURCE_MEM, @@ -344,7 +330,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1a, .timer_bit = 2, .clk = "peripheral_clk", @@ -352,7 +337,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xa412feac, .end = 0xa412feb5, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh4/setup-sh4-202.c b/arch/sh/kernel/cpu/sh4/setup-sh4-202.c index b9b7e10..223d066 100644 --- a/arch/sh/kernel/cpu/sh4/setup-sh4-202.c +++ b/arch/sh/kernel/cpu/sh4/setup-sh4-202.c @@ -31,7 +31,6 @@ static struct platform_device scif0_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -40,7 +39,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xffd80008, .end = 0xffd80013, .flags = IORESOURCE_MEM, @@ -62,7 +60,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -71,7 +68,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xffd80014, .end = 0xffd8001f, .flags = IORESOURCE_MEM, @@ -93,7 +89,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1c, .timer_bit = 2, .clk = "peripheral_clk", @@ -101,7 +96,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xffd80020, .end = 0xffd8002f, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7750.c b/arch/sh/kernel/cpu/sh4/setup-sh7750.c index ffd79e5..2f337b1 100644 --- a/arch/sh/kernel/cpu/sh4/setup-sh7750.c +++ b/arch/sh/kernel/cpu/sh4/setup-sh7750.c @@ -66,7 +66,6 @@ static struct platform_device scif1_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -75,7 +74,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xffd80008, .end = 0xffd80013, .flags = IORESOURCE_MEM, @@ -97,7 +95,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -106,7 +103,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xffd80014, .end = 0xffd8001f, .flags = IORESOURCE_MEM, @@ -128,7 +124,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1c, .timer_bit = 2, .clk = "peripheral_clk", @@ -136,7 +131,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xffd80020, .end = 0xffd8002f, .flags = IORESOURCE_MEM, @@ -163,7 +157,6 @@ static struct platform_device tmu2_device = { defined(CONFIG_CPU_SUBTYPE_SH7751R) static struct sh_timer_config tmu3_platform_data = { - .name = "TMU3", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -171,7 +164,6 @@ static struct sh_timer_config tmu3_platform_data = { static struct resource tmu3_resources[] = { [0] = { - .name = "TMU3", .start = 0xfe100008, .end = 0xfe100013, .flags = IORESOURCE_MEM, @@ -193,7 +185,6 @@ static struct platform_device tmu3_device = { }; static struct sh_timer_config tmu4_platform_data = { - .name = "TMU4", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -201,7 +192,6 @@ static struct sh_timer_config tmu4_platform_data = { static struct resource tmu4_resources[] = { [0] = { - .name = "TMU4", .start = 0xfe100014, .end = 0xfe10001f, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7760.c b/arch/sh/kernel/cpu/sh4/setup-sh7760.c index a16eb36..fa43da0 100644 --- a/arch/sh/kernel/cpu/sh4/setup-sh7760.c +++ b/arch/sh/kernel/cpu/sh4/setup-sh7760.c @@ -187,7 +187,6 @@ static struct platform_device scif3_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -196,7 +195,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xffd80008, .end = 0xffd80013, .flags = IORESOURCE_MEM, @@ -218,7 +216,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -227,7 +224,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xffd80014, .end = 0xffd8001f, .flags = IORESOURCE_MEM, @@ -249,7 +245,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1c, .timer_bit = 2, .clk = "peripheral_clk", @@ -257,7 +252,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xffd80020, .end = 0xffd8002f, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c index 45eb1bf..fdbd7d0 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c @@ -207,7 +207,6 @@ static struct platform_device jpu_device = { }; static struct sh_timer_config cmt_platform_data = { - .name = "CMT", .channel_offset = 0x60, .timer_bit = 5, .clk = "cmt0", @@ -217,7 +216,6 @@ static struct sh_timer_config cmt_platform_data = { static struct resource cmt_resources[] = { [0] = { - .name = "CMT", .start = 0x044a0060, .end = 0x044a006b, .flags = IORESOURCE_MEM, @@ -239,7 +237,6 @@ static struct platform_device cmt_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x04, .timer_bit = 0, .clk = "tmu0", @@ -248,7 +245,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xffd80008, .end = 0xffd80013, .flags = IORESOURCE_MEM, @@ -270,7 +266,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0x10, .timer_bit = 1, .clk = "tmu0", @@ -279,7 +274,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xffd80014, .end = 0xffd8001f, .flags = IORESOURCE_MEM, @@ -301,7 +295,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1c, .timer_bit = 2, .clk = "tmu0", @@ -309,7 +302,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xffd80020, .end = 0xffd8002b, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c index c494c19..d90fe0a 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c @@ -169,7 +169,6 @@ static struct platform_device veu1_device = { }; static struct sh_timer_config cmt_platform_data = { - .name = "CMT", .channel_offset = 0x60, .timer_bit = 5, .clk = "cmt0", @@ -179,7 +178,6 @@ static struct sh_timer_config cmt_platform_data = { static struct resource cmt_resources[] = { [0] = { - .name = "CMT", .start = 0x044a0060, .end = 0x044a006b, .flags = IORESOURCE_MEM, @@ -201,7 +199,6 @@ static struct platform_device cmt_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x04, .timer_bit = 0, .clk = "tmu0", @@ -210,7 +207,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xffd80008, .end = 0xffd80013, .flags = IORESOURCE_MEM, @@ -232,7 +228,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0x10, .timer_bit = 1, .clk = "tmu0", @@ -241,7 +236,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xffd80014, .end = 0xffd8001f, .flags = IORESOURCE_MEM, @@ -263,7 +257,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1c, .timer_bit = 2, .clk = "tmu0", @@ -271,7 +264,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xffd80020, .end = 0xffd8002b, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c index fd7e363..83ae9ad 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c @@ -401,7 +401,6 @@ static struct platform_device jpu_device = { }; static struct sh_timer_config cmt_platform_data = { - .name = "CMT", .channel_offset = 0x60, .timer_bit = 5, .clk = "cmt0", @@ -411,7 +410,6 @@ static struct sh_timer_config cmt_platform_data = { static struct resource cmt_resources[] = { [0] = { - .name = "CMT", .start = 0x044a0060, .end = 0x044a006b, .flags = IORESOURCE_MEM, @@ -436,7 +434,6 @@ static struct platform_device cmt_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x04, .timer_bit = 0, .clk = "tmu0", @@ -445,7 +442,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xffd80008, .end = 0xffd80013, .flags = IORESOURCE_MEM, @@ -470,7 +466,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0x10, .timer_bit = 1, .clk = "tmu0", @@ -479,7 +474,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xffd80014, .end = 0xffd8001f, .flags = IORESOURCE_MEM, @@ -504,7 +498,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1c, .timer_bit = 2, .clk = "tmu0", @@ -512,7 +505,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xffd80020, .end = 0xffd8002b, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c index 85c61f6..68446b3f 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c @@ -211,7 +211,6 @@ static struct platform_device veu1_device = { }; static struct sh_timer_config cmt_platform_data = { - .name = "CMT", .channel_offset = 0x60, .timer_bit = 5, .clk = "cmt0", @@ -221,7 +220,6 @@ static struct sh_timer_config cmt_platform_data = { static struct resource cmt_resources[] = { [0] = { - .name = "CMT", .start = 0x044a0060, .end = 0x044a006b, .flags = IORESOURCE_MEM, @@ -246,7 +244,6 @@ static struct platform_device cmt_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x04, .timer_bit = 0, .clk = "tmu0", @@ -255,7 +252,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xffd80008, .end = 0xffd80013, .flags = IORESOURCE_MEM, @@ -280,7 +276,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0x10, .timer_bit = 1, .clk = "tmu0", @@ -289,7 +284,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xffd80014, .end = 0xffd8001f, .flags = IORESOURCE_MEM, @@ -314,7 +308,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1c, .timer_bit = 2, .clk = "tmu0", @@ -322,7 +315,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xffd80020, .end = 0xffd8002b, .flags = IORESOURCE_MEM, @@ -347,7 +339,6 @@ static struct platform_device tmu2_device = { }; static struct sh_timer_config tmu3_platform_data = { - .name = "TMU3", .channel_offset = 0x04, .timer_bit = 0, .clk = "tmu1", @@ -355,7 +346,6 @@ static struct sh_timer_config tmu3_platform_data = { static struct resource tmu3_resources[] = { [0] = { - .name = "TMU3", .start = 0xffd90008, .end = 0xffd90013, .flags = IORESOURCE_MEM, @@ -380,7 +370,6 @@ static struct platform_device tmu3_device = { }; static struct sh_timer_config tmu4_platform_data = { - .name = "TMU4", .channel_offset = 0x10, .timer_bit = 1, .clk = "tmu1", @@ -388,7 +377,6 @@ static struct sh_timer_config tmu4_platform_data = { static struct resource tmu4_resources[] = { [0] = { - .name = "TMU4", .start = 0xffd90014, .end = 0xffd9001f, .flags = IORESOURCE_MEM, @@ -413,7 +401,6 @@ static struct platform_device tmu4_device = { }; static struct sh_timer_config tmu5_platform_data = { - .name = "TMU5", .channel_offset = 0x1c, .timer_bit = 2, .clk = "tmu1", @@ -421,7 +408,6 @@ static struct sh_timer_config tmu5_platform_data = { static struct resource tmu5_resources[] = { [0] = { - .name = "TMU5", .start = 0xffd90020, .end = 0xffd9002b, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c index e7fa2a9..abc98b0 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c @@ -485,7 +485,6 @@ static struct platform_device veu1_device = { }; static struct sh_timer_config cmt_platform_data = { - .name = "CMT", .channel_offset = 0x60, .timer_bit = 5, .clk = "cmt0", @@ -495,7 +494,6 @@ static struct sh_timer_config cmt_platform_data = { static struct resource cmt_resources[] = { [0] = { - .name = "CMT", .start = 0x044a0060, .end = 0x044a006b, .flags = IORESOURCE_MEM, @@ -520,7 +518,6 @@ static struct platform_device cmt_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x04, .timer_bit = 0, .clk = "tmu0", @@ -529,7 +526,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xffd80008, .end = 0xffd80013, .flags = IORESOURCE_MEM, @@ -554,7 +550,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0x10, .timer_bit = 1, .clk = "tmu0", @@ -563,7 +558,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xffd80014, .end = 0xffd8001f, .flags = IORESOURCE_MEM, @@ -588,7 +582,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1c, .timer_bit = 2, .clk = "tmu0", @@ -596,7 +589,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xffd80020, .end = 0xffd8002b, .flags = IORESOURCE_MEM, @@ -622,7 +614,6 @@ static struct platform_device tmu2_device = { static struct sh_timer_config tmu3_platform_data = { - .name = "TMU3", .channel_offset = 0x04, .timer_bit = 0, .clk = "tmu1", @@ -630,7 +621,6 @@ static struct sh_timer_config tmu3_platform_data = { static struct resource tmu3_resources[] = { [0] = { - .name = "TMU3", .start = 0xffd90008, .end = 0xffd90013, .flags = IORESOURCE_MEM, @@ -655,7 +645,6 @@ static struct platform_device tmu3_device = { }; static struct sh_timer_config tmu4_platform_data = { - .name = "TMU4", .channel_offset = 0x10, .timer_bit = 1, .clk = "tmu1", @@ -663,7 +652,6 @@ static struct sh_timer_config tmu4_platform_data = { static struct resource tmu4_resources[] = { [0] = { - .name = "TMU4", .start = 0xffd90014, .end = 0xffd9001f, .flags = IORESOURCE_MEM, @@ -688,7 +676,6 @@ static struct platform_device tmu4_device = { }; static struct sh_timer_config tmu5_platform_data = { - .name = "TMU5", .channel_offset = 0x1c, .timer_bit = 2, .clk = "tmu1", @@ -696,7 +683,6 @@ static struct sh_timer_config tmu5_platform_data = { static struct resource tmu5_resources[] = { [0] = { - .name = "TMU5", .start = 0xffd90020, .end = 0xffd9002b, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c index e75edf5..25eddf2 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c @@ -63,7 +63,6 @@ static struct platform_device scif4_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -72,7 +71,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xfe430008, .end = 0xfe430013, .flags = IORESOURCE_MEM, @@ -94,7 +92,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -103,7 +100,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xfe430014, .end = 0xfe43001f, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7763.c b/arch/sh/kernel/cpu/sh4a/setup-sh7763.c index 7f6b0a5..a91263e 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7763.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7763.c @@ -131,7 +131,6 @@ static struct platform_device usbf_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -140,7 +139,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xffd80008, .end = 0xffd80013, .flags = IORESOURCE_MEM, @@ -162,7 +160,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -171,7 +168,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xffd80014, .end = 0xffd8001f, .flags = IORESOURCE_MEM, @@ -193,7 +189,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1c, .timer_bit = 2, .clk = "peripheral_clk", @@ -201,7 +196,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xffd80020, .end = 0xffd8002f, .flags = IORESOURCE_MEM, @@ -223,7 +217,6 @@ static struct platform_device tmu2_device = { }; static struct sh_timer_config tmu3_platform_data = { - .name = "TMU3", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -231,7 +224,6 @@ static struct sh_timer_config tmu3_platform_data = { static struct resource tmu3_resources[] = { [0] = { - .name = "TMU3", .start = 0xffd88008, .end = 0xffd88013, .flags = IORESOURCE_MEM, @@ -253,7 +245,6 @@ static struct platform_device tmu3_device = { }; static struct sh_timer_config tmu4_platform_data = { - .name = "TMU4", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -261,7 +252,6 @@ static struct sh_timer_config tmu4_platform_data = { static struct resource tmu4_resources[] = { [0] = { - .name = "TMU4", .start = 0xffd88014, .end = 0xffd8801f, .flags = IORESOURCE_MEM, @@ -283,7 +273,6 @@ static struct platform_device tmu4_device = { }; static struct sh_timer_config tmu5_platform_data = { - .name = "TMU5", .channel_offset = 0x1c, .timer_bit = 2, .clk = "peripheral_clk", @@ -291,7 +280,6 @@ static struct sh_timer_config tmu5_platform_data = { static struct resource tmu5_resources[] = { [0] = { - .name = "TMU5", .start = 0xffd88020, .end = 0xffd8802b, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7770.c b/arch/sh/kernel/cpu/sh4a/setup-sh7770.c index 86d681e..83a27b0 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7770.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7770.c @@ -165,7 +165,6 @@ static struct platform_device scif9_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -174,7 +173,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xffd80008, .end = 0xffd80013, .flags = IORESOURCE_MEM, @@ -196,7 +194,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -205,7 +202,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xffd80014, .end = 0xffd8001f, .flags = IORESOURCE_MEM, @@ -227,7 +223,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1c, .timer_bit = 2, .clk = "peripheral_clk", @@ -235,7 +230,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xffd80020, .end = 0xffd8002f, .flags = IORESOURCE_MEM, @@ -257,7 +251,6 @@ static struct platform_device tmu2_device = { }; static struct sh_timer_config tmu3_platform_data = { - .name = "TMU3", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -265,7 +258,6 @@ static struct sh_timer_config tmu3_platform_data = { static struct resource tmu3_resources[] = { [0] = { - .name = "TMU3", .start = 0xffd81008, .end = 0xffd81013, .flags = IORESOURCE_MEM, @@ -287,7 +279,6 @@ static struct platform_device tmu3_device = { }; static struct sh_timer_config tmu4_platform_data = { - .name = "TMU4", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -295,7 +286,6 @@ static struct sh_timer_config tmu4_platform_data = { static struct resource tmu4_resources[] = { [0] = { - .name = "TMU4", .start = 0xffd81014, .end = 0xffd8101f, .flags = IORESOURCE_MEM, @@ -317,7 +307,6 @@ static struct platform_device tmu4_device = { }; static struct sh_timer_config tmu5_platform_data = { - .name = "TMU5", .channel_offset = 0x1c, .timer_bit = 2, .clk = "peripheral_clk", @@ -325,7 +314,6 @@ static struct sh_timer_config tmu5_platform_data = { static struct resource tmu5_resources[] = { [0] = { - .name = "TMU5", .start = 0xffd81020, .end = 0xffd8102f, .flags = IORESOURCE_MEM, @@ -347,7 +335,6 @@ static struct platform_device tmu5_device = { }; static struct sh_timer_config tmu6_platform_data = { - .name = "TMU6", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -355,7 +342,6 @@ static struct sh_timer_config tmu6_platform_data = { static struct resource tmu6_resources[] = { [0] = { - .name = "TMU6", .start = 0xffd82008, .end = 0xffd82013, .flags = IORESOURCE_MEM, @@ -377,7 +363,6 @@ static struct platform_device tmu6_device = { }; static struct sh_timer_config tmu7_platform_data = { - .name = "TMU7", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -385,7 +370,6 @@ static struct sh_timer_config tmu7_platform_data = { static struct resource tmu7_resources[] = { [0] = { - .name = "TMU7", .start = 0xffd82014, .end = 0xffd8201f, .flags = IORESOURCE_MEM, @@ -407,7 +391,6 @@ static struct platform_device tmu7_device = { }; static struct sh_timer_config tmu8_platform_data = { - .name = "TMU8", .channel_offset = 0x1c, .timer_bit = 2, .clk = "peripheral_clk", @@ -415,7 +398,6 @@ static struct sh_timer_config tmu8_platform_data = { static struct resource tmu8_resources[] = { [0] = { - .name = "TMU8", .start = 0xffd82020, .end = 0xffd8202b, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c index 02e792c..f7c48e92 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c @@ -49,7 +49,6 @@ static struct platform_device scif1_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -58,7 +57,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xffd80008, .end = 0xffd80013, .flags = IORESOURCE_MEM, @@ -80,7 +78,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -89,7 +86,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xffd80014, .end = 0xffd8001f, .flags = IORESOURCE_MEM, @@ -111,7 +107,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1c, .timer_bit = 2, .clk = "peripheral_clk", @@ -119,7 +114,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xffd80020, .end = 0xffd8002f, .flags = IORESOURCE_MEM, @@ -141,7 +135,6 @@ static struct platform_device tmu2_device = { }; static struct sh_timer_config tmu3_platform_data = { - .name = "TMU3", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -149,7 +142,6 @@ static struct sh_timer_config tmu3_platform_data = { static struct resource tmu3_resources[] = { [0] = { - .name = "TMU3", .start = 0xffdc0008, .end = 0xffdc0013, .flags = IORESOURCE_MEM, @@ -171,7 +163,6 @@ static struct platform_device tmu3_device = { }; static struct sh_timer_config tmu4_platform_data = { - .name = "TMU4", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -179,7 +170,6 @@ static struct sh_timer_config tmu4_platform_data = { static struct resource tmu4_resources[] = { [0] = { - .name = "TMU4", .start = 0xffdc0014, .end = 0xffdc001f, .flags = IORESOURCE_MEM, @@ -201,7 +191,6 @@ static struct platform_device tmu4_device = { }; static struct sh_timer_config tmu5_platform_data = { - .name = "TMU5", .channel_offset = 0x1c, .timer_bit = 2, .clk = "peripheral_clk", @@ -209,7 +198,6 @@ static struct sh_timer_config tmu5_platform_data = { static struct resource tmu5_resources[] = { [0] = { - .name = "TMU5", .start = 0xffdc0020, .end = 0xffdc002b, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c index 1fcd88b..05e9308 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c @@ -117,7 +117,6 @@ static struct platform_device scif5_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x04, .timer_bit = 0, .clk = "tmu012_fck", @@ -126,7 +125,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xffd80008, .end = 0xffd80013, .flags = IORESOURCE_MEM, @@ -148,7 +146,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0x10, .timer_bit = 1, .clk = "tmu012_fck", @@ -157,7 +154,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xffd80014, .end = 0xffd8001f, .flags = IORESOURCE_MEM, @@ -179,7 +175,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1c, .timer_bit = 2, .clk = "tmu012_fck", @@ -187,7 +182,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xffd80020, .end = 0xffd8002f, .flags = IORESOURCE_MEM, @@ -209,7 +203,6 @@ static struct platform_device tmu2_device = { }; static struct sh_timer_config tmu3_platform_data = { - .name = "TMU3", .channel_offset = 0x04, .timer_bit = 0, .clk = "tmu345_fck", @@ -217,7 +210,6 @@ static struct sh_timer_config tmu3_platform_data = { static struct resource tmu3_resources[] = { [0] = { - .name = "TMU3", .start = 0xffdc0008, .end = 0xffdc0013, .flags = IORESOURCE_MEM, @@ -239,7 +231,6 @@ static struct platform_device tmu3_device = { }; static struct sh_timer_config tmu4_platform_data = { - .name = "TMU4", .channel_offset = 0x10, .timer_bit = 1, .clk = "tmu345_fck", @@ -247,7 +238,6 @@ static struct sh_timer_config tmu4_platform_data = { static struct resource tmu4_resources[] = { [0] = { - .name = "TMU4", .start = 0xffdc0014, .end = 0xffdc001f, .flags = IORESOURCE_MEM, @@ -269,7 +259,6 @@ static struct platform_device tmu4_device = { }; static struct sh_timer_config tmu5_platform_data = { - .name = "TMU5", .channel_offset = 0x1c, .timer_bit = 2, .clk = "tmu345_fck", @@ -277,7 +266,6 @@ static struct sh_timer_config tmu5_platform_data = { static struct resource tmu5_resources[] = { [0] = { - .name = "TMU5", .start = 0xffdc0020, .end = 0xffdc002b, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c index 7e58532..542ced8 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c @@ -117,7 +117,6 @@ static struct platform_device scif5_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -126,7 +125,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xffd80008, .end = 0xffd80013, .flags = IORESOURCE_MEM, @@ -148,7 +146,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -157,7 +154,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xffd80014, .end = 0xffd8001f, .flags = IORESOURCE_MEM, @@ -179,7 +175,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1c, .timer_bit = 2, .clk = "peripheral_clk", @@ -187,7 +182,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xffd80020, .end = 0xffd8002f, .flags = IORESOURCE_MEM, @@ -209,7 +203,6 @@ static struct platform_device tmu2_device = { }; static struct sh_timer_config tmu3_platform_data = { - .name = "TMU3", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -217,7 +210,6 @@ static struct sh_timer_config tmu3_platform_data = { static struct resource tmu3_resources[] = { [0] = { - .name = "TMU3", .start = 0xffda0008, .end = 0xffda0013, .flags = IORESOURCE_MEM, @@ -239,7 +231,6 @@ static struct platform_device tmu3_device = { }; static struct sh_timer_config tmu4_platform_data = { - .name = "TMU4", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -247,7 +238,6 @@ static struct sh_timer_config tmu4_platform_data = { static struct resource tmu4_resources[] = { [0] = { - .name = "TMU4", .start = 0xffda0014, .end = 0xffda001f, .flags = IORESOURCE_MEM, @@ -269,7 +259,6 @@ static struct platform_device tmu4_device = { }; static struct sh_timer_config tmu5_platform_data = { - .name = "TMU5", .channel_offset = 0x1c, .timer_bit = 2, .clk = "peripheral_clk", @@ -277,7 +266,6 @@ static struct sh_timer_config tmu5_platform_data = { static struct resource tmu5_resources[] = { [0] = { - .name = "TMU5", .start = 0xffda0020, .end = 0xffda002b, .flags = IORESOURCE_MEM, @@ -299,7 +287,6 @@ static struct platform_device tmu5_device = { }; static struct sh_timer_config tmu6_platform_data = { - .name = "TMU6", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -307,7 +294,6 @@ static struct sh_timer_config tmu6_platform_data = { static struct resource tmu6_resources[] = { [0] = { - .name = "TMU6", .start = 0xffdc0008, .end = 0xffdc0013, .flags = IORESOURCE_MEM, @@ -329,7 +315,6 @@ static struct platform_device tmu6_device = { }; static struct sh_timer_config tmu7_platform_data = { - .name = "TMU7", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -337,7 +322,6 @@ static struct sh_timer_config tmu7_platform_data = { static struct resource tmu7_resources[] = { [0] = { - .name = "TMU7", .start = 0xffdc0014, .end = 0xffdc001f, .flags = IORESOURCE_MEM, @@ -359,7 +343,6 @@ static struct platform_device tmu7_device = { }; static struct sh_timer_config tmu8_platform_data = { - .name = "TMU8", .channel_offset = 0x1c, .timer_bit = 2, .clk = "peripheral_clk", @@ -367,7 +350,6 @@ static struct sh_timer_config tmu8_platform_data = { static struct resource tmu8_resources[] = { [0] = { - .name = "TMU8", .start = 0xffdc0020, .end = 0xffdc002b, .flags = IORESOURCE_MEM, @@ -389,7 +371,6 @@ static struct platform_device tmu8_device = { }; static struct sh_timer_config tmu9_platform_data = { - .name = "TMU9", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -397,7 +378,6 @@ static struct sh_timer_config tmu9_platform_data = { static struct resource tmu9_resources[] = { [0] = { - .name = "TMU9", .start = 0xffde0008, .end = 0xffde0013, .flags = IORESOURCE_MEM, @@ -419,7 +399,6 @@ static struct platform_device tmu9_device = { }; static struct sh_timer_config tmu10_platform_data = { - .name = "TMU10", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -427,7 +406,6 @@ static struct sh_timer_config tmu10_platform_data = { static struct resource tmu10_resources[] = { [0] = { - .name = "TMU10", .start = 0xffde0014, .end = 0xffde001f, .flags = IORESOURCE_MEM, @@ -449,7 +427,6 @@ static struct platform_device tmu10_device = { }; static struct sh_timer_config tmu11_platform_data = { - .name = "TMU11", .channel_offset = 0x1c, .timer_bit = 2, .clk = "peripheral_clk", @@ -457,7 +434,6 @@ static struct sh_timer_config tmu11_platform_data = { static struct resource tmu11_resources[] = { [0] = { - .name = "TMU11", .start = 0xffde0020, .end = 0xffde002b, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh4a/setup-shx3.c b/arch/sh/kernel/cpu/sh4a/setup-shx3.c index 780ba17..ba545b5 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-shx3.c +++ b/arch/sh/kernel/cpu/sh4a/setup-shx3.c @@ -70,7 +70,6 @@ static struct platform_device scif2_device = { }; static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -79,7 +78,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = 0xffc10008, .end = 0xffc10013, .flags = IORESOURCE_MEM, @@ -101,7 +99,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -110,7 +107,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = 0xffc10014, .end = 0xffc1001f, .flags = IORESOURCE_MEM, @@ -132,7 +128,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1c, .timer_bit = 2, .clk = "peripheral_clk", @@ -140,7 +135,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = 0xffc10020, .end = 0xffc1002f, .flags = IORESOURCE_MEM, @@ -162,7 +156,6 @@ static struct platform_device tmu2_device = { }; static struct sh_timer_config tmu3_platform_data = { - .name = "TMU3", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -170,7 +163,6 @@ static struct sh_timer_config tmu3_platform_data = { static struct resource tmu3_resources[] = { [0] = { - .name = "TMU3", .start = 0xffc20008, .end = 0xffc20013, .flags = IORESOURCE_MEM, @@ -192,7 +184,6 @@ static struct platform_device tmu3_device = { }; static struct sh_timer_config tmu4_platform_data = { - .name = "TMU4", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -200,7 +191,6 @@ static struct sh_timer_config tmu4_platform_data = { static struct resource tmu4_resources[] = { [0] = { - .name = "TMU4", .start = 0xffc20014, .end = 0xffc2001f, .flags = IORESOURCE_MEM, @@ -222,7 +212,6 @@ static struct platform_device tmu4_device = { }; static struct sh_timer_config tmu5_platform_data = { - .name = "TMU5", .channel_offset = 0x1c, .timer_bit = 2, .clk = "peripheral_clk", @@ -230,7 +219,6 @@ static struct sh_timer_config tmu5_platform_data = { static struct resource tmu5_resources[] = { [0] = { - .name = "TMU5", .start = 0xffc20020, .end = 0xffc2002b, .flags = IORESOURCE_MEM, diff --git a/arch/sh/kernel/cpu/sh5/setup-sh5.c b/arch/sh/kernel/cpu/sh5/setup-sh5.c index e7a3c1e..c84ca20 100644 --- a/arch/sh/kernel/cpu/sh5/setup-sh5.c +++ b/arch/sh/kernel/cpu/sh5/setup-sh5.c @@ -68,7 +68,6 @@ static struct platform_device rtc_device = { #define TMU2_BASE (TMU_BASE + 0x8 + (0xc * 0x2)) static struct sh_timer_config tmu0_platform_data = { - .name = "TMU0", .channel_offset = 0x04, .timer_bit = 0, .clk = "peripheral_clk", @@ -77,7 +76,6 @@ static struct sh_timer_config tmu0_platform_data = { static struct resource tmu0_resources[] = { [0] = { - .name = "TMU0", .start = TMU0_BASE, .end = TMU0_BASE + 0xc - 1, .flags = IORESOURCE_MEM, @@ -99,7 +97,6 @@ static struct platform_device tmu0_device = { }; static struct sh_timer_config tmu1_platform_data = { - .name = "TMU1", .channel_offset = 0x10, .timer_bit = 1, .clk = "peripheral_clk", @@ -108,7 +105,6 @@ static struct sh_timer_config tmu1_platform_data = { static struct resource tmu1_resources[] = { [0] = { - .name = "TMU1", .start = TMU1_BASE, .end = TMU1_BASE + 0xc - 1, .flags = IORESOURCE_MEM, @@ -130,7 +126,6 @@ static struct platform_device tmu1_device = { }; static struct sh_timer_config tmu2_platform_data = { - .name = "TMU2", .channel_offset = 0x1c, .timer_bit = 2, .clk = "peripheral_clk", @@ -138,7 +133,6 @@ static struct sh_timer_config tmu2_platform_data = { static struct resource tmu2_resources[] = { [0] = { - .name = "TMU2", .start = TMU2_BASE, .end = TMU2_BASE + 0xc - 1, .flags = IORESOURCE_MEM, -- cgit v0.10.2 From c7ed1ab3f7b2fe0dedebf34cbf40bf12cb5ae48b Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 10 Mar 2010 18:35:14 +0900 Subject: serial: sh-sci: clkdev updates for MSTP gating. This fixes up some of the I/D/F clock ambiguity in the sh-sci driver. The interface clock in most cases just wraps back to the peripheral clock, while the function clock wraps in to the MSTP bits. As the logic was somewhat inverted, this cleans that up, and also enables all CPUs with SCI MSTP bits to match function clocks through clkdev lookup. As a result, this gets rid of the clk string abuse on the sh side, and the clock string will be killed off once the ARM code has had a chance to sync up. This also enables MSTP gating on CPUs like 7786 which had never wired it up before. Impacted CPUs are primarily all SH-Mobiles, SH7785, and SH7786. Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c index 2c16df3..c541301 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c @@ -159,10 +159,10 @@ static struct clk mstp_clks[] = { MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0), MSTP("mfi0", &div4_clks[DIV4_P], MSTPCR0, 11, 0), MSTP("flctl0", &div4_clks[DIV4_P], MSTPCR0, 10, 0), - MSTP("scif0", &div4_clks[DIV4_P], MSTPCR0, 7, 0), - MSTP("scif1", &div4_clks[DIV4_P], MSTPCR0, 6, 0), - MSTP("scif2", &div4_clks[DIV4_P], MSTPCR0, 5, 0), - MSTP("scif3", &div4_clks[DIV4_P], MSTPCR0, 4, 0), + SH_CLK_MSTP32("sci_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 7, 0), + SH_CLK_MSTP32("sci_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 6, 0), + SH_CLK_MSTP32("sci_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 5, 0), + SH_CLK_MSTP32("sci_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 4, 0), MSTP("sio0", &div4_clks[DIV4_P], MSTPCR0, 3, 0), MSTP("siof0", &div4_clks[DIV4_P], MSTPCR0, 2, 0), MSTP("siof1", &div4_clks[DIV4_P], MSTPCR0, 1, 0), diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c index 91588d2..e10c64f 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c @@ -163,9 +163,9 @@ static struct clk mstp_clks[] = { MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0), MSTP("mfi0", &div4_clks[DIV4_P], MSTPCR0, 11, 0), MSTP("flctl0", &div4_clks[DIV4_P], MSTPCR0, 10, 0), - MSTP("scif0", &div4_clks[DIV4_P], MSTPCR0, 7, 0), - MSTP("scif1", &div4_clks[DIV4_P], MSTPCR0, 6, 0), - MSTP("scif2", &div4_clks[DIV4_P], MSTPCR0, 5, 0), + SH_CLK_MSTP32("sci_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 7, 0), + SH_CLK_MSTP32("sci_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 6, 0), + SH_CLK_MSTP32("sci_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 5, 0), MSTP("msiof0", &div4_clks[DIV4_P], MSTPCR0, 2, 0), MSTP("sbr0", &div4_clks[DIV4_P], MSTPCR0, 1, 0), diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c index 15db6d5..0732c8b 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c @@ -164,9 +164,9 @@ static struct clk mstp_clks[] = { SH_HWBLK_CLK("cmt0", -1, R_CLK, HWBLK_CMT, 0), SH_HWBLK_CLK("rwdt0", -1, R_CLK, HWBLK_RWDT, 0), SH_HWBLK_CLK("flctl0", -1, P_CLK, HWBLK_FLCTL, 0), - SH_HWBLK_CLK("scif0", -1, P_CLK, HWBLK_SCIF0, 0), - SH_HWBLK_CLK("scif1", -1, P_CLK, HWBLK_SCIF1, 0), - SH_HWBLK_CLK("scif2", -1, P_CLK, HWBLK_SCIF2, 0), + SH_HWBLK_CLK("sci_fck", 0, P_CLK, HWBLK_SCIF0, 0), + SH_HWBLK_CLK("sci_fck", 1, P_CLK, HWBLK_SCIF1, 0), + SH_HWBLK_CLK("sci_fck", 2, P_CLK, HWBLK_SCIF2, 0), SH_HWBLK_CLK("i2c0", -1, P_CLK, HWBLK_IIC, 0), SH_HWBLK_CLK("rtc0", -1, R_CLK, HWBLK_RTC, 0), diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c index 50babe0..4d4c123 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c @@ -177,12 +177,12 @@ static struct clk mstp_clks[] = { SH_HWBLK_CLK("dmac1", -1, B_CLK, HWBLK_DMAC1, 0), SH_HWBLK_CLK("tmu1", -1, P_CLK, HWBLK_TMU1, 0), SH_HWBLK_CLK("flctl0", -1, P_CLK, HWBLK_FLCTL, 0), - SH_HWBLK_CLK("scif0", -1, P_CLK, HWBLK_SCIF0, 0), - SH_HWBLK_CLK("scif1", -1, P_CLK, HWBLK_SCIF1, 0), - SH_HWBLK_CLK("scif2", -1, P_CLK, HWBLK_SCIF2, 0), - SH_HWBLK_CLK("scif3", -1, B_CLK, HWBLK_SCIF3, 0), - SH_HWBLK_CLK("scif4", -1, B_CLK, HWBLK_SCIF4, 0), - SH_HWBLK_CLK("scif5", -1, B_CLK, HWBLK_SCIF5, 0), + SH_HWBLK_CLK("sci_fck", 0, P_CLK, HWBLK_SCIF0, 0), + SH_HWBLK_CLK("sci_fck", 1, P_CLK, HWBLK_SCIF1, 0), + SH_HWBLK_CLK("sci_fck", 2, P_CLK, HWBLK_SCIF2, 0), + SH_HWBLK_CLK("sci_fck", 3, B_CLK, HWBLK_SCIF3, 0), + SH_HWBLK_CLK("sci_fck", 4, B_CLK, HWBLK_SCIF4, 0), + SH_HWBLK_CLK("sci_fck", 5, B_CLK, HWBLK_SCIF5, 0), SH_HWBLK_CLK("msiof0", -1, B_CLK, HWBLK_MSIOF0, 0), SH_HWBLK_CLK("msiof1", -1, B_CLK, HWBLK_MSIOF1, 0), SH_HWBLK_CLK("meram0", -1, SH_CLK, HWBLK_MERAM, 0), diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c index 6707061..bcf2b97 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c @@ -194,12 +194,12 @@ static struct clk mstp_clks[] = { SH_HWBLK_CLK("rwdt0", -1, R_CLK, HWBLK_RWDT, 0), SH_HWBLK_CLK("dmac1", -1, B_CLK, HWBLK_DMAC1, 0), SH_HWBLK_CLK("tmu1", -1, P_CLK, HWBLK_TMU1, 0), - SH_HWBLK_CLK("scif0", -1, P_CLK, HWBLK_SCIF0, 0), - SH_HWBLK_CLK("scif1", -1, P_CLK, HWBLK_SCIF1, 0), - SH_HWBLK_CLK("scif2", -1, P_CLK, HWBLK_SCIF2, 0), - SH_HWBLK_CLK("scif3", -1, B_CLK, HWBLK_SCIF3, 0), - SH_HWBLK_CLK("scif4", -1, B_CLK, HWBLK_SCIF4, 0), - SH_HWBLK_CLK("scif5", -1, B_CLK, HWBLK_SCIF5, 0), + SH_HWBLK_CLK("sci_fck", 0, P_CLK, HWBLK_SCIF0, 0), + SH_HWBLK_CLK("sci_fck", 1, P_CLK, HWBLK_SCIF1, 0), + SH_HWBLK_CLK("sci_fck", 2, P_CLK, HWBLK_SCIF2, 0), + SH_HWBLK_CLK("sci_fck", 3, B_CLK, HWBLK_SCIF3, 0), + SH_HWBLK_CLK("sci_fck", 4, B_CLK, HWBLK_SCIF4, 0), + SH_HWBLK_CLK("sci_fck", 5, B_CLK, HWBLK_SCIF5, 0), SH_HWBLK_CLK("msiof0", -1, B_CLK, HWBLK_MSIOF0, 0), SH_HWBLK_CLK("msiof1", -1, B_CLK, HWBLK_MSIOF1, 0), diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c index d997f0a..6061c73 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c @@ -88,12 +88,12 @@ struct clk div4_clks[DIV4_NR] = { static struct clk mstp_clks[] = { /* MSTPCR0 */ - SH_CLK_MSTP32("scif_fck", 5, &div4_clks[DIV4_P], MSTPCR0, 29, 0), - SH_CLK_MSTP32("scif_fck", 4, &div4_clks[DIV4_P], MSTPCR0, 28, 0), - SH_CLK_MSTP32("scif_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 27, 0), - SH_CLK_MSTP32("scif_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 26, 0), - SH_CLK_MSTP32("scif_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 25, 0), - SH_CLK_MSTP32("scif_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 24, 0), + SH_CLK_MSTP32("sci_fck", 5, &div4_clks[DIV4_P], MSTPCR0, 29, 0), + SH_CLK_MSTP32("sci_fck", 4, &div4_clks[DIV4_P], MSTPCR0, 28, 0), + SH_CLK_MSTP32("sci_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 27, 0), + SH_CLK_MSTP32("sci_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 26, 0), + SH_CLK_MSTP32("sci_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 25, 0), + SH_CLK_MSTP32("sci_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 24, 0), SH_CLK_MSTP32("ssi_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 21, 0), SH_CLK_MSTP32("ssi_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 20, 0), SH_CLK_MSTP32("hac_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 17, 0), diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c index af69fd4..85e8d57 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c @@ -87,12 +87,12 @@ struct clk div4_clks[DIV4_NR] = { static struct clk mstp_clks[] = { /* MSTPCR0 */ - SH_CLK_MSTP32("scif_fck", 5, &div4_clks[DIV4_P], MSTPCR0, 29, 0), - SH_CLK_MSTP32("scif_fck", 4, &div4_clks[DIV4_P], MSTPCR0, 28, 0), - SH_CLK_MSTP32("scif_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 27, 0), - SH_CLK_MSTP32("scif_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 26, 0), - SH_CLK_MSTP32("scif_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 25, 0), - SH_CLK_MSTP32("scif_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 24, 0), + SH_CLK_MSTP32("sci_fck", 5, &div4_clks[DIV4_P], MSTPCR0, 29, 0), + SH_CLK_MSTP32("sci_fck", 4, &div4_clks[DIV4_P], MSTPCR0, 28, 0), + SH_CLK_MSTP32("sci_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 27, 0), + SH_CLK_MSTP32("sci_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 26, 0), + SH_CLK_MSTP32("sci_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 25, 0), + SH_CLK_MSTP32("sci_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 24, 0), SH_CLK_MSTP32("ssi_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 23, 0), SH_CLK_MSTP32("ssi_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 22, 0), SH_CLK_MSTP32("ssi_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 21, 0), diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c index fdbd7d0..6f83949 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c @@ -21,7 +21,6 @@ static struct plat_sci_port scif0_platform_data = { .flags = UPF_BOOT_AUTOCONF, .type = PORT_SCIF, .irqs = { 80, 80, 80, 80 }, - .clk = "scif0", }; static struct platform_device scif0_device = { @@ -37,7 +36,6 @@ static struct plat_sci_port scif1_platform_data = { .flags = UPF_BOOT_AUTOCONF, .type = PORT_SCIF, .irqs = { 81, 81, 81, 81 }, - .clk = "scif1", }; static struct platform_device scif1_device = { @@ -53,7 +51,6 @@ static struct plat_sci_port scif2_platform_data = { .flags = UPF_BOOT_AUTOCONF, .type = PORT_SCIF, .irqs = { 82, 82, 82, 82 }, - .clk = "scif2", }; static struct platform_device scif2_device = { @@ -69,7 +66,6 @@ static struct plat_sci_port scif3_platform_data = { .flags = UPF_BOOT_AUTOCONF, .type = PORT_SCIF, .irqs = { 83, 83, 83, 83 }, - .clk = "scif3", }; static struct platform_device scif3_device = { diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c index d90fe0a..1d897ed 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c @@ -23,7 +23,6 @@ static struct plat_sci_port scif0_platform_data = { .flags = UPF_BOOT_AUTOCONF, .type = PORT_SCIF, .irqs = { 80, 80, 80, 80 }, - .clk = "scif0", }; static struct platform_device scif0_device = { diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c index 83ae9ad..847a276 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c @@ -174,7 +174,6 @@ static struct plat_sci_port scif0_platform_data = { .flags = UPF_BOOT_AUTOCONF, .type = PORT_SCIF, .irqs = { 80, 80, 80, 80 }, - .clk = "scif0", }; static struct platform_device scif0_device = { @@ -190,7 +189,6 @@ static struct plat_sci_port scif1_platform_data = { .flags = UPF_BOOT_AUTOCONF, .type = PORT_SCIF, .irqs = { 81, 81, 81, 81 }, - .clk = "scif1", }; static struct platform_device scif1_device = { @@ -206,7 +204,6 @@ static struct plat_sci_port scif2_platform_data = { .flags = UPF_BOOT_AUTOCONF, .type = PORT_SCIF, .irqs = { 82, 82, 82, 82 }, - .clk = "scif2", }; static struct platform_device scif2_device = { diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c index 68446b3f..187462b 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c @@ -26,7 +26,6 @@ static struct plat_sci_port scif0_platform_data = { .flags = UPF_BOOT_AUTOCONF, .type = PORT_SCIF, .irqs = { 80, 80, 80, 80 }, - .clk = "scif0", }; static struct platform_device scif0_device = { @@ -42,7 +41,6 @@ static struct plat_sci_port scif1_platform_data = { .flags = UPF_BOOT_AUTOCONF, .type = PORT_SCIF, .irqs = { 81, 81, 81, 81 }, - .clk = "scif1", }; static struct platform_device scif1_device = { @@ -58,7 +56,6 @@ static struct plat_sci_port scif2_platform_data = { .flags = UPF_BOOT_AUTOCONF, .type = PORT_SCIF, .irqs = { 82, 82, 82, 82 }, - .clk = "scif2", }; static struct platform_device scif2_device = { @@ -74,7 +71,6 @@ static struct plat_sci_port scif3_platform_data = { .flags = UPF_BOOT_AUTOCONF, .type = PORT_SCIFA, .irqs = { 56, 56, 56, 56 }, - .clk = "scif3", }; static struct platform_device scif3_device = { @@ -90,7 +86,6 @@ static struct plat_sci_port scif4_platform_data = { .flags = UPF_BOOT_AUTOCONF, .type = PORT_SCIFA, .irqs = { 88, 88, 88, 88 }, - .clk = "scif4", }; static struct platform_device scif4_device = { @@ -106,7 +101,6 @@ static struct plat_sci_port scif5_platform_data = { .flags = UPF_BOOT_AUTOCONF, .type = PORT_SCIFA, .irqs = { 109, 109, 109, 109 }, - .clk = "scif5", }; static struct platform_device scif5_device = { diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c index abc98b0..ee97890 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c @@ -213,7 +213,6 @@ static struct plat_sci_port scif0_platform_data = { .flags = UPF_BOOT_AUTOCONF, .type = PORT_SCIF, .irqs = { 80, 80, 80, 80 }, - .clk = "scif0", }; static struct platform_device scif0_device = { @@ -229,7 +228,6 @@ static struct plat_sci_port scif1_platform_data = { .flags = UPF_BOOT_AUTOCONF, .type = PORT_SCIF, .irqs = { 81, 81, 81, 81 }, - .clk = "scif1", }; static struct platform_device scif1_device = { @@ -245,7 +243,6 @@ static struct plat_sci_port scif2_platform_data = { .flags = UPF_BOOT_AUTOCONF, .type = PORT_SCIF, .irqs = { 82, 82, 82, 82 }, - .clk = "scif2", }; static struct platform_device scif2_device = { @@ -261,7 +258,6 @@ static struct plat_sci_port scif3_platform_data = { .flags = UPF_BOOT_AUTOCONF, .type = PORT_SCIFA, .irqs = { 56, 56, 56, 56 }, - .clk = "scif3", }; static struct platform_device scif3_device = { @@ -277,7 +273,6 @@ static struct plat_sci_port scif4_platform_data = { .flags = UPF_BOOT_AUTOCONF, .type = PORT_SCIFA, .irqs = { 88, 88, 88, 88 }, - .clk = "scif4", }; static struct platform_device scif4_device = { @@ -293,7 +288,6 @@ static struct plat_sci_port scif5_platform_data = { .flags = UPF_BOOT_AUTOCONF, .type = PORT_SCIFA, .irqs = { 109, 109, 109, 109 }, - .clk = "scif5", }; static struct platform_device scif5_device = { diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c index 05e9308..76afe57 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c @@ -25,7 +25,6 @@ static struct plat_sci_port scif0_platform_data = { .flags = UPF_BOOT_AUTOCONF, .type = PORT_SCIF, .irqs = { 40, 40, 40, 40 }, - .clk = "scif_fck", }; static struct platform_device scif0_device = { @@ -41,7 +40,6 @@ static struct plat_sci_port scif1_platform_data = { .flags = UPF_BOOT_AUTOCONF, .type = PORT_SCIF, .irqs = { 44, 44, 44, 44 }, - .clk = "scif_fck", }; static struct platform_device scif1_device = { @@ -57,7 +55,6 @@ static struct plat_sci_port scif2_platform_data = { .flags = UPF_BOOT_AUTOCONF, .type = PORT_SCIF, .irqs = { 60, 60, 60, 60 }, - .clk = "scif_fck", }; static struct platform_device scif2_device = { @@ -73,7 +70,6 @@ static struct plat_sci_port scif3_platform_data = { .flags = UPF_BOOT_AUTOCONF, .type = PORT_SCIF, .irqs = { 61, 61, 61, 61 }, - .clk = "scif_fck", }; static struct platform_device scif3_device = { @@ -89,7 +85,6 @@ static struct plat_sci_port scif4_platform_data = { .flags = UPF_BOOT_AUTOCONF, .type = PORT_SCIF, .irqs = { 62, 62, 62, 62 }, - .clk = "scif_fck", }; static struct platform_device scif4_device = { @@ -105,7 +100,6 @@ static struct plat_sci_port scif5_platform_data = { .flags = UPF_BOOT_AUTOCONF, .type = PORT_SCIF, .irqs = { 63, 63, 63, 63 }, - .clk = "scif_fck", }; static struct platform_device scif5_device = { diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 980f394..054a842 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -83,8 +83,8 @@ struct sci_port { /* Interface clock */ struct clk *iclk; - /* Data clock */ - struct clk *dclk; + /* Function clock */ + struct clk *fclk; struct list_head node; struct dma_chan *chan_tx; @@ -803,7 +803,7 @@ static int sci_notifier(struct notifier_block *self, (phase == CPUFREQ_RESUMECHANGE)) { spin_lock_irqsave(&priv->lock, flags); list_for_each_entry(sci_port, &priv->ports, node) - sci_port->port.uartclk = clk_get_rate(sci_port->dclk); + sci_port->port.uartclk = clk_get_rate(sci_port->iclk); spin_unlock_irqrestore(&priv->lock, flags); } @@ -814,21 +814,17 @@ static void sci_clk_enable(struct uart_port *port) { struct sci_port *sci_port = to_sci_port(port); - clk_enable(sci_port->dclk); - sci_port->port.uartclk = clk_get_rate(sci_port->dclk); - - if (sci_port->iclk) - clk_enable(sci_port->iclk); + clk_enable(sci_port->iclk); + sci_port->port.uartclk = clk_get_rate(sci_port->iclk); + clk_enable(sci_port->fclk); } static void sci_clk_disable(struct uart_port *port) { struct sci_port *sci_port = to_sci_port(port); - if (sci_port->iclk) - clk_disable(sci_port->iclk); - - clk_disable(sci_port->dclk); + clk_disable(sci_port->fclk); + clk_disable(sci_port->iclk); } static int sci_request_irq(struct sci_port *port) @@ -1557,10 +1553,10 @@ static struct uart_ops sci_uart_ops = { #endif }; -static void __devinit sci_init_single(struct platform_device *dev, - struct sci_port *sci_port, - unsigned int index, - struct plat_sci_port *p) +static int __devinit sci_init_single(struct platform_device *dev, + struct sci_port *sci_port, + unsigned int index, + struct plat_sci_port *p) { struct uart_port *port = &sci_port->port; @@ -1581,8 +1577,23 @@ static void __devinit sci_init_single(struct platform_device *dev, } if (dev) { - sci_port->iclk = p->clk ? clk_get(&dev->dev, p->clk) : NULL; - sci_port->dclk = clk_get(&dev->dev, "peripheral_clk"); + sci_port->iclk = clk_get(&dev->dev, "sci_ick"); + if (IS_ERR(sci_port->iclk)) { + sci_port->iclk = clk_get(&dev->dev, "peripheral_clk"); + if (IS_ERR(sci_port->iclk)) { + dev_err(&dev->dev, "can't get iclk\n"); + return PTR_ERR(sci_port->iclk); + } + } + + /* + * The function clock is optional, ignore it if we can't + * find it. + */ + sci_port->fclk = clk_get(&dev->dev, "sci_fck"); + if (IS_ERR(sci_port->fclk)) + sci_port->fclk = NULL; + sci_port->enable = sci_clk_enable; sci_port->disable = sci_clk_disable; port->dev = &dev->dev; @@ -1609,6 +1620,7 @@ static void __devinit sci_init_single(struct platform_device *dev, #endif memcpy(&sci_port->irqs, &p->irqs, sizeof(p->irqs)); + return 0; } #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE @@ -1758,8 +1770,11 @@ static int sci_remove(struct platform_device *dev) cpufreq_unregister_notifier(&priv->clk_nb, CPUFREQ_TRANSITION_NOTIFIER); spin_lock_irqsave(&priv->lock, flags); - list_for_each_entry(p, &priv->ports, node) + list_for_each_entry(p, &priv->ports, node) { uart_remove_one_port(&sci_uart_driver, &p->port); + clk_put(p->iclk); + clk_put(p->fclk); + } spin_unlock_irqrestore(&priv->lock, flags); kfree(priv); @@ -1785,7 +1800,9 @@ static int __devinit sci_probe_single(struct platform_device *dev, return 0; } - sci_init_single(dev, sciport, index, p); + ret = sci_init_single(dev, sciport, index, p); + if (ret) + return ret; ret = uart_add_one_port(&sci_uart_driver, &sciport->port); if (ret) -- cgit v0.10.2 From ca037701a025334e724e5c61b3b1082940c8b981 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 2 Mar 2010 19:52:12 +0100 Subject: perf, x86: Add PEBS infrastructure This patch implements support for Intel Precise Event Based Sampling, which is an alternative counter mode in which the counter triggers a hardware assist to collect information on events. The hardware assist takes a trap like snapshot of a subset of the machine registers. This data is written to the Intel Debug-Store, which can be programmed with a data threshold at which to raise a PMI. With the PEBS hardware assist being trap like, the reported IP is always one instruction after the actual instruction that triggered the event. This implements a simple PEBS model that always takes a single PEBS event at a time. This is done so that the interaction with the rest of the system is as expected (freq adjust, period randomization, lbr, callchains, etc.). It adds an ABI element: perf_event_attr::precise, which indicates that we wish to use this (constrained, but precise) mode. Signed-off-by: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: paulus@samba.org Cc: eranian@google.com Cc: robert.richter@amd.com Cc: fweisbec@gmail.com LKML-Reference: <20100304140100.392111285@chello.nl> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 1d665a0b..0c03d5c 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -31,45 +31,6 @@ static u64 perf_event_mask __read_mostly; -/* The maximal number of PEBS events: */ -#define MAX_PEBS_EVENTS 4 - -/* The size of a BTS record in bytes: */ -#define BTS_RECORD_SIZE 24 - -/* The size of a per-cpu BTS buffer in bytes: */ -#define BTS_BUFFER_SIZE (BTS_RECORD_SIZE * 2048) - -/* The BTS overflow threshold in bytes from the end of the buffer: */ -#define BTS_OVFL_TH (BTS_RECORD_SIZE * 128) - - -/* - * Bits in the debugctlmsr controlling branch tracing. - */ -#define X86_DEBUGCTL_TR (1 << 6) -#define X86_DEBUGCTL_BTS (1 << 7) -#define X86_DEBUGCTL_BTINT (1 << 8) -#define X86_DEBUGCTL_BTS_OFF_OS (1 << 9) -#define X86_DEBUGCTL_BTS_OFF_USR (1 << 10) - -/* - * A debug store configuration. - * - * We only support architectures that use 64bit fields. - */ -struct debug_store { - u64 bts_buffer_base; - u64 bts_index; - u64 bts_absolute_maximum; - u64 bts_interrupt_threshold; - u64 pebs_buffer_base; - u64 pebs_index; - u64 pebs_absolute_maximum; - u64 pebs_interrupt_threshold; - u64 pebs_event_reset[MAX_PEBS_EVENTS]; -}; - struct event_constraint { union { unsigned long idxmsk[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; @@ -88,17 +49,29 @@ struct amd_nb { }; struct cpu_hw_events { + /* + * Generic x86 PMC bits + */ struct perf_event *events[X86_PMC_IDX_MAX]; /* in counter order */ unsigned long active_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; unsigned long interrupts; int enabled; - struct debug_store *ds; int n_events; int n_added; int assign[X86_PMC_IDX_MAX]; /* event to counter assignment */ u64 tags[X86_PMC_IDX_MAX]; struct perf_event *event_list[X86_PMC_IDX_MAX]; /* in enabled order */ + + /* + * Intel DebugStore bits + */ + struct debug_store *ds; + u64 pebs_enabled; + + /* + * AMD specific bits + */ struct amd_nb *amd_nb; }; @@ -112,12 +85,24 @@ struct cpu_hw_events { #define EVENT_CONSTRAINT(c, n, m) \ __EVENT_CONSTRAINT(c, n, m, HWEIGHT(n)) +/* + * Constraint on the Event code. + */ #define INTEL_EVENT_CONSTRAINT(c, n) \ EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVTSEL_MASK) +/* + * Constraint on the Event code + UMask + fixed-mask + */ #define FIXED_EVENT_CONSTRAINT(c, n) \ EVENT_CONSTRAINT(c, (1ULL << (32+n)), INTEL_ARCH_FIXED_MASK) +/* + * Constraint on the Event code + UMask + */ +#define PEBS_EVENT_CONSTRAINT(c, n) \ + EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK) + #define EVENT_CONSTRAINT_END \ EVENT_CONSTRAINT(0, 0, 0) @@ -128,6 +113,9 @@ struct cpu_hw_events { * struct x86_pmu - generic x86 pmu */ struct x86_pmu { + /* + * Generic x86 PMC bits + */ const char *name; int version; int (*handle_irq)(struct pt_regs *); @@ -146,10 +134,6 @@ struct x86_pmu { u64 event_mask; int apic; u64 max_period; - u64 intel_ctrl; - void (*enable_bts)(u64 config); - void (*disable_bts)(void); - struct event_constraint * (*get_event_constraints)(struct cpu_hw_events *cpuc, struct perf_event *event); @@ -162,6 +146,19 @@ struct x86_pmu { void (*cpu_starting)(int cpu); void (*cpu_dying)(int cpu); void (*cpu_dead)(int cpu); + + /* + * Intel Arch Perfmon v2+ + */ + u64 intel_ctrl; + + /* + * Intel DebugStore bits + */ + int bts, pebs; + int pebs_record_size; + void (*drain_pebs)(struct pt_regs *regs); + struct event_constraint *pebs_constraints; }; static struct x86_pmu x86_pmu __read_mostly; @@ -293,110 +290,14 @@ static void release_pmc_hardware(void) #endif } -static inline bool bts_available(void) -{ - return x86_pmu.enable_bts != NULL; -} - -static void init_debug_store_on_cpu(int cpu) -{ - struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds; - - if (!ds) - return; - - wrmsr_on_cpu(cpu, MSR_IA32_DS_AREA, - (u32)((u64)(unsigned long)ds), - (u32)((u64)(unsigned long)ds >> 32)); -} - -static void fini_debug_store_on_cpu(int cpu) -{ - if (!per_cpu(cpu_hw_events, cpu).ds) - return; - - wrmsr_on_cpu(cpu, MSR_IA32_DS_AREA, 0, 0); -} - -static void release_bts_hardware(void) -{ - int cpu; - - if (!bts_available()) - return; - - get_online_cpus(); - - for_each_online_cpu(cpu) - fini_debug_store_on_cpu(cpu); - - for_each_possible_cpu(cpu) { - struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds; - - if (!ds) - continue; - - per_cpu(cpu_hw_events, cpu).ds = NULL; - - kfree((void *)(unsigned long)ds->bts_buffer_base); - kfree(ds); - } - - put_online_cpus(); -} - -static int reserve_bts_hardware(void) -{ - int cpu, err = 0; - - if (!bts_available()) - return 0; - - get_online_cpus(); - - for_each_possible_cpu(cpu) { - struct debug_store *ds; - void *buffer; - - err = -ENOMEM; - buffer = kzalloc(BTS_BUFFER_SIZE, GFP_KERNEL); - if (unlikely(!buffer)) - break; - - ds = kzalloc(sizeof(*ds), GFP_KERNEL); - if (unlikely(!ds)) { - kfree(buffer); - break; - } - - ds->bts_buffer_base = (u64)(unsigned long)buffer; - ds->bts_index = ds->bts_buffer_base; - ds->bts_absolute_maximum = - ds->bts_buffer_base + BTS_BUFFER_SIZE; - ds->bts_interrupt_threshold = - ds->bts_absolute_maximum - BTS_OVFL_TH; - - per_cpu(cpu_hw_events, cpu).ds = ds; - err = 0; - } - - if (err) - release_bts_hardware(); - else { - for_each_online_cpu(cpu) - init_debug_store_on_cpu(cpu); - } - - put_online_cpus(); - - return err; -} +static int reserve_ds_buffers(void); +static void release_ds_buffers(void); static void hw_perf_event_destroy(struct perf_event *event) { if (atomic_dec_and_mutex_lock(&active_events, &pmc_reserve_mutex)) { release_pmc_hardware(); - release_bts_hardware(); + release_ds_buffers(); mutex_unlock(&pmc_reserve_mutex); } } @@ -459,7 +360,7 @@ static int __hw_perf_event_init(struct perf_event *event) if (!reserve_pmc_hardware()) err = -EBUSY; else - err = reserve_bts_hardware(); + err = reserve_ds_buffers(); } if (!err) atomic_inc(&active_events); @@ -537,7 +438,7 @@ static int __hw_perf_event_init(struct perf_event *event) if ((attr->config == PERF_COUNT_HW_BRANCH_INSTRUCTIONS) && (hwc->sample_period == 1)) { /* BTS is not supported by this architecture. */ - if (!bts_available()) + if (!x86_pmu.bts) return -EOPNOTSUPP; /* BTS is currently only allowed for user-mode. */ @@ -995,6 +896,7 @@ static void x86_pmu_unthrottle(struct perf_event *event) void perf_event_print_debug(void) { u64 ctrl, status, overflow, pmc_ctrl, pmc_count, prev_left, fixed; + u64 pebs; struct cpu_hw_events *cpuc; unsigned long flags; int cpu, idx; @@ -1012,12 +914,14 @@ void perf_event_print_debug(void) rdmsrl(MSR_CORE_PERF_GLOBAL_STATUS, status); rdmsrl(MSR_CORE_PERF_GLOBAL_OVF_CTRL, overflow); rdmsrl(MSR_ARCH_PERFMON_FIXED_CTR_CTRL, fixed); + rdmsrl(MSR_IA32_PEBS_ENABLE, pebs); pr_info("\n"); pr_info("CPU#%d: ctrl: %016llx\n", cpu, ctrl); pr_info("CPU#%d: status: %016llx\n", cpu, status); pr_info("CPU#%d: overflow: %016llx\n", cpu, overflow); pr_info("CPU#%d: fixed: %016llx\n", cpu, fixed); + pr_info("CPU#%d: pebs: %016llx\n", cpu, pebs); } pr_info("CPU#%d: active: %016llx\n", cpu, *(u64 *)cpuc->active_mask); @@ -1333,6 +1237,7 @@ undo: #include "perf_event_amd.c" #include "perf_event_p6.c" +#include "perf_event_intel_ds.c" #include "perf_event_intel.c" static int __cpuinit @@ -1465,6 +1370,32 @@ static const struct pmu pmu = { }; /* + * validate that we can schedule this event + */ +static int validate_event(struct perf_event *event) +{ + struct cpu_hw_events *fake_cpuc; + struct event_constraint *c; + int ret = 0; + + fake_cpuc = kmalloc(sizeof(*fake_cpuc), GFP_KERNEL | __GFP_ZERO); + if (!fake_cpuc) + return -ENOMEM; + + c = x86_pmu.get_event_constraints(fake_cpuc, event); + + if (!c || !c->weight) + ret = -ENOSPC; + + if (x86_pmu.put_event_constraints) + x86_pmu.put_event_constraints(fake_cpuc, event); + + kfree(fake_cpuc); + + return ret; +} + +/* * validate a single event group * * validation include: @@ -1529,6 +1460,8 @@ const struct pmu *hw_perf_event_init(struct perf_event *event) if (event->group_leader != event) err = validate_group(event); + else + err = validate_event(event); event->pmu = tmp; } diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 84bfde6..1144641 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -470,42 +470,6 @@ static u64 intel_pmu_raw_event(u64 hw_event) return hw_event & CORE_EVNTSEL_MASK; } -static void intel_pmu_enable_bts(u64 config) -{ - unsigned long debugctlmsr; - - debugctlmsr = get_debugctlmsr(); - - debugctlmsr |= X86_DEBUGCTL_TR; - debugctlmsr |= X86_DEBUGCTL_BTS; - debugctlmsr |= X86_DEBUGCTL_BTINT; - - if (!(config & ARCH_PERFMON_EVENTSEL_OS)) - debugctlmsr |= X86_DEBUGCTL_BTS_OFF_OS; - - if (!(config & ARCH_PERFMON_EVENTSEL_USR)) - debugctlmsr |= X86_DEBUGCTL_BTS_OFF_USR; - - update_debugctlmsr(debugctlmsr); -} - -static void intel_pmu_disable_bts(void) -{ - struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); - unsigned long debugctlmsr; - - if (!cpuc->ds) - return; - - debugctlmsr = get_debugctlmsr(); - - debugctlmsr &= - ~(X86_DEBUGCTL_TR | X86_DEBUGCTL_BTS | X86_DEBUGCTL_BTINT | - X86_DEBUGCTL_BTS_OFF_OS | X86_DEBUGCTL_BTS_OFF_USR); - - update_debugctlmsr(debugctlmsr); -} - static void intel_pmu_disable_all(void) { struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); @@ -514,6 +478,8 @@ static void intel_pmu_disable_all(void) if (test_bit(X86_PMC_IDX_FIXED_BTS, cpuc->active_mask)) intel_pmu_disable_bts(); + + intel_pmu_pebs_disable_all(); } static void intel_pmu_enable_all(void) @@ -531,6 +497,8 @@ static void intel_pmu_enable_all(void) intel_pmu_enable_bts(event->hw.config); } + + intel_pmu_pebs_enable_all(); } static inline u64 intel_pmu_get_status(void) @@ -547,8 +515,7 @@ static inline void intel_pmu_ack_status(u64 ack) wrmsrl(MSR_CORE_PERF_GLOBAL_OVF_CTRL, ack); } -static inline void -intel_pmu_disable_fixed(struct hw_perf_event *hwc) +static void intel_pmu_disable_fixed(struct hw_perf_event *hwc) { int idx = hwc->idx - X86_PMC_IDX_FIXED; u64 ctrl_val, mask; @@ -560,68 +527,7 @@ intel_pmu_disable_fixed(struct hw_perf_event *hwc) (void)checking_wrmsrl(hwc->config_base, ctrl_val); } -static void intel_pmu_drain_bts_buffer(void) -{ - struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); - struct debug_store *ds = cpuc->ds; - struct bts_record { - u64 from; - u64 to; - u64 flags; - }; - struct perf_event *event = cpuc->events[X86_PMC_IDX_FIXED_BTS]; - struct bts_record *at, *top; - struct perf_output_handle handle; - struct perf_event_header header; - struct perf_sample_data data; - struct pt_regs regs; - - if (!event) - return; - - if (!ds) - return; - - at = (struct bts_record *)(unsigned long)ds->bts_buffer_base; - top = (struct bts_record *)(unsigned long)ds->bts_index; - - if (top <= at) - return; - - ds->bts_index = ds->bts_buffer_base; - - perf_sample_data_init(&data, 0); - - data.period = event->hw.last_period; - regs.ip = 0; - - /* - * Prepare a generic sample, i.e. fill in the invariant fields. - * We will overwrite the from and to address before we output - * the sample. - */ - perf_prepare_sample(&header, &data, event, ®s); - - if (perf_output_begin(&handle, event, - header.size * (top - at), 1, 1)) - return; - - for (; at < top; at++) { - data.ip = at->from; - data.addr = at->to; - - perf_output_sample(&handle, &header, &data, event); - } - - perf_output_end(&handle); - - /* There's new data available. */ - event->hw.interrupts++; - event->pending_kill = POLL_IN; -} - -static inline void -intel_pmu_disable_event(struct perf_event *event) +static void intel_pmu_disable_event(struct perf_event *event) { struct hw_perf_event *hwc = &event->hw; @@ -637,10 +543,12 @@ intel_pmu_disable_event(struct perf_event *event) } x86_pmu_disable_event(event); + + if (unlikely(event->attr.precise)) + intel_pmu_pebs_disable(hwc); } -static inline void -intel_pmu_enable_fixed(struct hw_perf_event *hwc) +static void intel_pmu_enable_fixed(struct hw_perf_event *hwc) { int idx = hwc->idx - X86_PMC_IDX_FIXED; u64 ctrl_val, bits, mask; @@ -689,6 +597,9 @@ static void intel_pmu_enable_event(struct perf_event *event) return; } + if (unlikely(event->attr.precise)) + intel_pmu_pebs_enable(hwc); + __x86_pmu_enable_event(hwc); } @@ -762,6 +673,13 @@ again: inc_irq_stat(apic_perf_irqs); ack = status; + + /* + * PEBS overflow sets bit 62 in the global status register + */ + if (__test_and_clear_bit(62, (unsigned long *)&status)) + x86_pmu.drain_pebs(regs); + for_each_set_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) { struct perf_event *event = cpuc->events[bit]; @@ -791,22 +709,18 @@ done: return 1; } -static struct event_constraint bts_constraint = - EVENT_CONSTRAINT(0, 1ULL << X86_PMC_IDX_FIXED_BTS, 0); - static struct event_constraint * -intel_special_constraints(struct perf_event *event) +intel_bts_constraints(struct perf_event *event) { - unsigned int hw_event; - - hw_event = event->hw.config & INTEL_ARCH_EVENT_MASK; + struct hw_perf_event *hwc = &event->hw; + unsigned int hw_event, bts_event; - if (unlikely((hw_event == - x86_pmu.event_map(PERF_COUNT_HW_BRANCH_INSTRUCTIONS)) && - (event->hw.sample_period == 1))) { + hw_event = hwc->config & INTEL_ARCH_EVENT_MASK; + bts_event = x86_pmu.event_map(PERF_COUNT_HW_BRANCH_INSTRUCTIONS); + if (unlikely(hw_event == bts_event && hwc->sample_period == 1)) return &bts_constraint; - } + return NULL; } @@ -815,7 +729,11 @@ intel_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event { struct event_constraint *c; - c = intel_special_constraints(event); + c = intel_bts_constraints(event); + if (c) + return c; + + c = intel_pebs_constraints(event); if (c) return c; @@ -864,8 +782,6 @@ static __initconst struct x86_pmu intel_pmu = { * the generic event period: */ .max_period = (1ULL << 31) - 1, - .enable_bts = intel_pmu_enable_bts, - .disable_bts = intel_pmu_disable_bts, .get_event_constraints = intel_get_event_constraints, .cpu_starting = init_debug_store_on_cpu, @@ -915,6 +831,8 @@ static __init int intel_pmu_init(void) if (version > 1) x86_pmu.num_events_fixed = max((int)edx.split.num_events_fixed, 3); + intel_ds_init(); + /* * Install the hw-cache-events table: */ diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c new file mode 100644 index 0000000..0d994ef --- /dev/null +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -0,0 +1,557 @@ +#ifdef CONFIG_CPU_SUP_INTEL + +/* The maximal number of PEBS events: */ +#define MAX_PEBS_EVENTS 4 + +/* The size of a BTS record in bytes: */ +#define BTS_RECORD_SIZE 24 + +#define BTS_BUFFER_SIZE (PAGE_SIZE << 4) +#define PEBS_BUFFER_SIZE PAGE_SIZE + +/* + * pebs_record_32 for p4 and core not supported + +struct pebs_record_32 { + u32 flags, ip; + u32 ax, bc, cx, dx; + u32 si, di, bp, sp; +}; + + */ + +struct pebs_record_core { + u64 flags, ip; + u64 ax, bx, cx, dx; + u64 si, di, bp, sp; + u64 r8, r9, r10, r11; + u64 r12, r13, r14, r15; +}; + +struct pebs_record_nhm { + u64 flags, ip; + u64 ax, bx, cx, dx; + u64 si, di, bp, sp; + u64 r8, r9, r10, r11; + u64 r12, r13, r14, r15; + u64 status, dla, dse, lat; +}; + +/* + * Bits in the debugctlmsr controlling branch tracing. + */ +#define X86_DEBUGCTL_TR (1 << 6) +#define X86_DEBUGCTL_BTS (1 << 7) +#define X86_DEBUGCTL_BTINT (1 << 8) +#define X86_DEBUGCTL_BTS_OFF_OS (1 << 9) +#define X86_DEBUGCTL_BTS_OFF_USR (1 << 10) + +/* + * A debug store configuration. + * + * We only support architectures that use 64bit fields. + */ +struct debug_store { + u64 bts_buffer_base; + u64 bts_index; + u64 bts_absolute_maximum; + u64 bts_interrupt_threshold; + u64 pebs_buffer_base; + u64 pebs_index; + u64 pebs_absolute_maximum; + u64 pebs_interrupt_threshold; + u64 pebs_event_reset[MAX_PEBS_EVENTS]; +}; + +static void init_debug_store_on_cpu(int cpu) +{ + struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds; + + if (!ds) + return; + + wrmsr_on_cpu(cpu, MSR_IA32_DS_AREA, + (u32)((u64)(unsigned long)ds), + (u32)((u64)(unsigned long)ds >> 32)); +} + +static void fini_debug_store_on_cpu(int cpu) +{ + if (!per_cpu(cpu_hw_events, cpu).ds) + return; + + wrmsr_on_cpu(cpu, MSR_IA32_DS_AREA, 0, 0); +} + +static void release_ds_buffers(void) +{ + int cpu; + + if (!x86_pmu.bts && !x86_pmu.pebs) + return; + + get_online_cpus(); + + for_each_online_cpu(cpu) + fini_debug_store_on_cpu(cpu); + + for_each_possible_cpu(cpu) { + struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds; + + if (!ds) + continue; + + per_cpu(cpu_hw_events, cpu).ds = NULL; + + kfree((void *)(unsigned long)ds->pebs_buffer_base); + kfree((void *)(unsigned long)ds->bts_buffer_base); + kfree(ds); + } + + put_online_cpus(); +} + +static int reserve_ds_buffers(void) +{ + int cpu, err = 0; + + if (!x86_pmu.bts && !x86_pmu.pebs) + return 0; + + get_online_cpus(); + + for_each_possible_cpu(cpu) { + struct debug_store *ds; + void *buffer; + int max, thresh; + + err = -ENOMEM; + ds = kzalloc(sizeof(*ds), GFP_KERNEL); + if (unlikely(!ds)) { + kfree(buffer); + break; + } + per_cpu(cpu_hw_events, cpu).ds = ds; + + if (x86_pmu.bts) { + buffer = kzalloc(BTS_BUFFER_SIZE, GFP_KERNEL); + if (unlikely(!buffer)) + break; + + max = BTS_BUFFER_SIZE / BTS_RECORD_SIZE; + thresh = max / 16; + + ds->bts_buffer_base = (u64)(unsigned long)buffer; + ds->bts_index = ds->bts_buffer_base; + ds->bts_absolute_maximum = ds->bts_buffer_base + + max * BTS_RECORD_SIZE; + ds->bts_interrupt_threshold = ds->bts_absolute_maximum - + thresh * BTS_RECORD_SIZE; + } + + if (x86_pmu.pebs) { + buffer = kzalloc(PEBS_BUFFER_SIZE, GFP_KERNEL); + if (unlikely(!buffer)) + break; + + max = PEBS_BUFFER_SIZE / x86_pmu.pebs_record_size; + + ds->pebs_buffer_base = (u64)(unsigned long)buffer; + ds->pebs_index = ds->pebs_buffer_base; + ds->pebs_absolute_maximum = ds->pebs_buffer_base + + max * x86_pmu.pebs_record_size; + /* + * Always use single record PEBS + */ + ds->pebs_interrupt_threshold = ds->pebs_buffer_base + + x86_pmu.pebs_record_size; + } + + err = 0; + } + + if (err) + release_ds_buffers(); + else { + for_each_online_cpu(cpu) + init_debug_store_on_cpu(cpu); + } + + put_online_cpus(); + + return err; +} + +/* + * BTS + */ + +static struct event_constraint bts_constraint = + EVENT_CONSTRAINT(0, 1ULL << X86_PMC_IDX_FIXED_BTS, 0); + +static void intel_pmu_enable_bts(u64 config) +{ + unsigned long debugctlmsr; + + debugctlmsr = get_debugctlmsr(); + + debugctlmsr |= X86_DEBUGCTL_TR; + debugctlmsr |= X86_DEBUGCTL_BTS; + debugctlmsr |= X86_DEBUGCTL_BTINT; + + if (!(config & ARCH_PERFMON_EVENTSEL_OS)) + debugctlmsr |= X86_DEBUGCTL_BTS_OFF_OS; + + if (!(config & ARCH_PERFMON_EVENTSEL_USR)) + debugctlmsr |= X86_DEBUGCTL_BTS_OFF_USR; + + update_debugctlmsr(debugctlmsr); +} + +static void intel_pmu_disable_bts(void) +{ + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + unsigned long debugctlmsr; + + if (!cpuc->ds) + return; + + debugctlmsr = get_debugctlmsr(); + + debugctlmsr &= + ~(X86_DEBUGCTL_TR | X86_DEBUGCTL_BTS | X86_DEBUGCTL_BTINT | + X86_DEBUGCTL_BTS_OFF_OS | X86_DEBUGCTL_BTS_OFF_USR); + + update_debugctlmsr(debugctlmsr); +} + +static void intel_pmu_drain_bts_buffer(void) +{ + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + struct debug_store *ds = cpuc->ds; + struct bts_record { + u64 from; + u64 to; + u64 flags; + }; + struct perf_event *event = cpuc->events[X86_PMC_IDX_FIXED_BTS]; + struct bts_record *at, *top; + struct perf_output_handle handle; + struct perf_event_header header; + struct perf_sample_data data; + struct pt_regs regs; + + if (!event) + return; + + if (!ds) + return; + + at = (struct bts_record *)(unsigned long)ds->bts_buffer_base; + top = (struct bts_record *)(unsigned long)ds->bts_index; + + if (top <= at) + return; + + ds->bts_index = ds->bts_buffer_base; + + perf_sample_data_init(&data, 0); + data.period = event->hw.last_period; + regs.ip = 0; + + /* + * Prepare a generic sample, i.e. fill in the invariant fields. + * We will overwrite the from and to address before we output + * the sample. + */ + perf_prepare_sample(&header, &data, event, ®s); + + if (perf_output_begin(&handle, event, header.size * (top - at), 1, 1)) + return; + + for (; at < top; at++) { + data.ip = at->from; + data.addr = at->to; + + perf_output_sample(&handle, &header, &data, event); + } + + perf_output_end(&handle); + + /* There's new data available. */ + event->hw.interrupts++; + event->pending_kill = POLL_IN; +} + +/* + * PEBS + */ + +static struct event_constraint intel_core_pebs_events[] = { + PEBS_EVENT_CONSTRAINT(0x00c0, 0x1), /* INSTR_RETIRED.ANY */ + PEBS_EVENT_CONSTRAINT(0xfec1, 0x1), /* X87_OPS_RETIRED.ANY */ + PEBS_EVENT_CONSTRAINT(0x00c5, 0x1), /* BR_INST_RETIRED.MISPRED */ + PEBS_EVENT_CONSTRAINT(0x1fc7, 0x1), /* SIMD_INST_RETURED.ANY */ + PEBS_EVENT_CONSTRAINT(0x01cb, 0x1), /* MEM_LOAD_RETIRED.L1D_MISS */ + PEBS_EVENT_CONSTRAINT(0x02cb, 0x1), /* MEM_LOAD_RETIRED.L1D_LINE_MISS */ + PEBS_EVENT_CONSTRAINT(0x04cb, 0x1), /* MEM_LOAD_RETIRED.L2_MISS */ + PEBS_EVENT_CONSTRAINT(0x08cb, 0x1), /* MEM_LOAD_RETIRED.L2_LINE_MISS */ + PEBS_EVENT_CONSTRAINT(0x10cb, 0x1), /* MEM_LOAD_RETIRED.DTLB_MISS */ + EVENT_CONSTRAINT_END +}; + +static struct event_constraint intel_nehalem_pebs_events[] = { + PEBS_EVENT_CONSTRAINT(0x00c0, 0xf), /* INSTR_RETIRED.ANY */ + PEBS_EVENT_CONSTRAINT(0xfec1, 0xf), /* X87_OPS_RETIRED.ANY */ + PEBS_EVENT_CONSTRAINT(0x00c5, 0xf), /* BR_INST_RETIRED.MISPRED */ + PEBS_EVENT_CONSTRAINT(0x1fc7, 0xf), /* SIMD_INST_RETURED.ANY */ + PEBS_EVENT_CONSTRAINT(0x01cb, 0xf), /* MEM_LOAD_RETIRED.L1D_MISS */ + PEBS_EVENT_CONSTRAINT(0x02cb, 0xf), /* MEM_LOAD_RETIRED.L1D_LINE_MISS */ + PEBS_EVENT_CONSTRAINT(0x04cb, 0xf), /* MEM_LOAD_RETIRED.L2_MISS */ + PEBS_EVENT_CONSTRAINT(0x08cb, 0xf), /* MEM_LOAD_RETIRED.L2_LINE_MISS */ + PEBS_EVENT_CONSTRAINT(0x10cb, 0xf), /* MEM_LOAD_RETIRED.DTLB_MISS */ + EVENT_CONSTRAINT_END +}; + +static struct event_constraint * +intel_pebs_constraints(struct perf_event *event) +{ + struct event_constraint *c; + + if (!event->attr.precise) + return NULL; + + if (x86_pmu.pebs_constraints) { + for_each_event_constraint(c, x86_pmu.pebs_constraints) { + if ((event->hw.config & c->cmask) == c->code) + return c; + } + } + + return &emptyconstraint; +} + +static void intel_pmu_pebs_enable(struct hw_perf_event *hwc) +{ + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + u64 val = cpuc->pebs_enabled; + + hwc->config &= ~ARCH_PERFMON_EVENTSEL_INT; + + val |= 1ULL << hwc->idx; + wrmsrl(MSR_IA32_PEBS_ENABLE, val); +} + +static void intel_pmu_pebs_disable(struct hw_perf_event *hwc) +{ + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + u64 val = cpuc->pebs_enabled; + + val &= ~(1ULL << hwc->idx); + wrmsrl(MSR_IA32_PEBS_ENABLE, val); + + hwc->config |= ARCH_PERFMON_EVENTSEL_INT; +} + +static void intel_pmu_pebs_enable_all(void) +{ + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + + if (cpuc->pebs_enabled) + wrmsrl(MSR_IA32_PEBS_ENABLE, cpuc->pebs_enabled); +} + +static void intel_pmu_pebs_disable_all(void) +{ + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + + if (cpuc->pebs_enabled) + wrmsrl(MSR_IA32_PEBS_ENABLE, 0); +} + +static int intel_pmu_save_and_restart(struct perf_event *event); +static void intel_pmu_disable_event(struct perf_event *event); + +static void intel_pmu_drain_pebs_core(struct pt_regs *iregs) +{ + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + struct debug_store *ds = cpuc->ds; + struct perf_event *event = cpuc->events[0]; /* PMC0 only */ + struct pebs_record_core *at, *top; + struct perf_sample_data data; + struct pt_regs regs; + int n; + + if (!event || !ds || !x86_pmu.pebs) + return; + + intel_pmu_pebs_disable_all(); + + at = (struct pebs_record_core *)(unsigned long)ds->pebs_buffer_base; + top = (struct pebs_record_core *)(unsigned long)ds->pebs_index; + + if (top <= at) + goto out; + + ds->pebs_index = ds->pebs_buffer_base; + + if (!intel_pmu_save_and_restart(event)) + goto out; + + perf_sample_data_init(&data, 0); + data.period = event->hw.last_period; + + n = top - at; + + /* + * Should not happen, we program the threshold at 1 and do not + * set a reset value. + */ + WARN_ON_ONCE(n > 1); + + /* + * We use the interrupt regs as a base because the PEBS record + * does not contain a full regs set, specifically it seems to + * lack segment descriptors, which get used by things like + * user_mode(). + * + * In the simple case fix up only the IP and BP,SP regs, for + * PERF_SAMPLE_IP and PERF_SAMPLE_CALLCHAIN to function properly. + * A possible PERF_SAMPLE_REGS will have to transfer all regs. + */ + regs = *iregs; + regs.ip = at->ip; + regs.bp = at->bp; + regs.sp = at->sp; + + if (perf_event_overflow(event, 1, &data, ®s)) + intel_pmu_disable_event(event); + +out: + intel_pmu_pebs_enable_all(); +} + +static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs) +{ + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + struct debug_store *ds = cpuc->ds; + struct pebs_record_nhm *at, *top; + struct perf_sample_data data; + struct perf_event *event = NULL; + struct pt_regs regs; + int bit, n; + + if (!ds || !x86_pmu.pebs) + return; + + intel_pmu_pebs_disable_all(); + + at = (struct pebs_record_nhm *)(unsigned long)ds->pebs_buffer_base; + top = (struct pebs_record_nhm *)(unsigned long)ds->pebs_index; + + if (top <= at) + goto out; + + ds->pebs_index = ds->pebs_buffer_base; + + n = top - at; + + /* + * Should not happen, we program the threshold at 1 and do not + * set a reset value. + */ + WARN_ON_ONCE(n > MAX_PEBS_EVENTS); + + for ( ; at < top; at++) { + for_each_bit(bit, (unsigned long *)&at->status, MAX_PEBS_EVENTS) { + if (!cpuc->events[bit]->attr.precise) + continue; + + event = cpuc->events[bit]; + } + + if (!event) + continue; + + if (!intel_pmu_save_and_restart(event)) + continue; + + perf_sample_data_init(&data, 0); + data.period = event->hw.last_period; + + /* + * See the comment in intel_pmu_drain_pebs_core() + */ + regs = *iregs; + regs.ip = at->ip; + regs.bp = at->bp; + regs.sp = at->sp; + + if (perf_event_overflow(event, 1, &data, ®s)) + intel_pmu_disable_event(event); + } +out: + intel_pmu_pebs_enable_all(); +} + +/* + * BTS, PEBS probe and setup + */ + +static void intel_ds_init(void) +{ + /* + * No support for 32bit formats + */ + if (!boot_cpu_has(X86_FEATURE_DTES64)) + return; + + x86_pmu.bts = boot_cpu_has(X86_FEATURE_BTS); + x86_pmu.pebs = boot_cpu_has(X86_FEATURE_PEBS); + if (x86_pmu.pebs) { + int format = 0; + + if (x86_pmu.version > 1) { + u64 capabilities; + /* + * v2+ has a PEBS format field + */ + rdmsrl(MSR_IA32_PERF_CAPABILITIES, capabilities); + format = (capabilities >> 8) & 0xf; + } + + switch (format) { + case 0: + printk(KERN_CONT "PEBS v0, "); + x86_pmu.pebs_record_size = sizeof(struct pebs_record_core); + x86_pmu.drain_pebs = intel_pmu_drain_pebs_core; + x86_pmu.pebs_constraints = intel_core_pebs_events; + break; + + case 1: + printk(KERN_CONT "PEBS v1, "); + x86_pmu.pebs_record_size = sizeof(struct pebs_record_nhm); + x86_pmu.drain_pebs = intel_pmu_drain_pebs_nhm; + x86_pmu.pebs_constraints = intel_nehalem_pebs_events; + break; + + default: + printk(KERN_CONT "PEBS unknown format: %d, ", format); + x86_pmu.pebs = 0; + break; + } + } +} + +#else /* CONFIG_CPU_SUP_INTEL */ + +static int reseve_ds_buffers(void) +{ + return 0; +} + +static void release_ds_buffers(void) +{ +} + +#endif /* CONFIG_CPU_SUP_INTEL */ diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 80acbf3..42307b5 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -203,8 +203,9 @@ struct perf_event_attr { enable_on_exec : 1, /* next exec enables */ task : 1, /* trace fork/exit */ watermark : 1, /* wakeup_watermark */ + precise : 1, /* OoO invariant counter */ - __reserved_1 : 49; + __reserved_1 : 48; union { __u32 wakeup_events; /* wakeup every n events */ -- cgit v0.10.2 From 69fef0d2e2c2c049ef4207a52e78b50d527bd85a Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 4 Mar 2010 13:57:24 +0100 Subject: perf: Add attr->precise support to raw event parsing Minimal userspace interface to the new 'precise' events flag. Can be used like "perf top -e r00c0p" which will use PEBS to sample retired instructions. Signed-off-by: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: paulus@samba.org Cc: eranian@google.com Cc: robert.richter@amd.com Cc: fweisbec@gmail.com LKML-Reference: <20100304140100.468665803@chello.nl> Signed-off-by: Ingo Molnar diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 05d0c5c..a201445 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -656,6 +656,10 @@ parse_raw_event(const char **strp, struct perf_event_attr *attr) return EVT_FAILED; n = hex2u64(str + 1, &config); if (n > 0) { + if (str[n+1] == 'p') { + attr->precise = 1; + n++; + } *strp = str + n + 1; attr->type = PERF_TYPE_RAW; attr->config = config; -- cgit v0.10.2 From caff2befffe899e63df5cc760b7ed01cfd902685 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 3 Mar 2010 12:02:30 +0100 Subject: perf, x86: Implement simple LBR support Implement simple suport Intel Last-Branch-Record, it supports all hardware that implements FREEZE_LBRS_ON_PMI, but does not (yet) implement the LBR config register. The Intel LBR is a FIFO of From,To addresses describing the last few branches the hardware took. This patch does not add perf interface to the LBR, but merely provides an interface for internal use. Signed-off-by: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: paulus@samba.org Cc: eranian@google.com Cc: robert.richter@amd.com Cc: fweisbec@gmail.com LKML-Reference: <20100304140100.544191154@chello.nl> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 0c03d5c..1badff6 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -48,6 +48,8 @@ struct amd_nb { struct event_constraint event_constraints[X86_PMC_IDX_MAX]; }; +#define MAX_LBR_ENTRIES 16 + struct cpu_hw_events { /* * Generic x86 PMC bits @@ -70,6 +72,14 @@ struct cpu_hw_events { u64 pebs_enabled; /* + * Intel LBR bits + */ + int lbr_users; + void *lbr_context; + struct perf_branch_stack lbr_stack; + struct perf_branch_entry lbr_entries[MAX_LBR_ENTRIES]; + + /* * AMD specific bits */ struct amd_nb *amd_nb; @@ -159,6 +169,13 @@ struct x86_pmu { int pebs_record_size; void (*drain_pebs)(struct pt_regs *regs); struct event_constraint *pebs_constraints; + + /* + * Intel LBR + */ + unsigned long lbr_tos, lbr_from, lbr_to; /* MSR base regs */ + int lbr_nr; /* hardware stack size */ + int lbr_format; /* hardware format */ }; static struct x86_pmu x86_pmu __read_mostly; @@ -1237,6 +1254,7 @@ undo: #include "perf_event_amd.c" #include "perf_event_p6.c" +#include "perf_event_intel_lbr.c" #include "perf_event_intel_ds.c" #include "perf_event_intel.c" diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 1144641..44f6ed4 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -480,6 +480,7 @@ static void intel_pmu_disable_all(void) intel_pmu_disable_bts(); intel_pmu_pebs_disable_all(); + intel_pmu_lbr_disable_all(); } static void intel_pmu_enable_all(void) @@ -499,6 +500,7 @@ static void intel_pmu_enable_all(void) } intel_pmu_pebs_enable_all(); + intel_pmu_lbr_enable_all(); } static inline u64 intel_pmu_get_status(void) @@ -674,6 +676,8 @@ again: inc_irq_stat(apic_perf_irqs); ack = status; + intel_pmu_lbr_read(); + /* * PEBS overflow sets bit 62 in the global status register */ @@ -848,6 +852,8 @@ static __init int intel_pmu_init(void) memcpy(hw_cache_event_ids, core2_hw_cache_event_ids, sizeof(hw_cache_event_ids)); + intel_pmu_lbr_init_core(); + x86_pmu.event_constraints = intel_core2_event_constraints; pr_cont("Core2 events, "); break; @@ -857,13 +863,18 @@ static __init int intel_pmu_init(void) memcpy(hw_cache_event_ids, nehalem_hw_cache_event_ids, sizeof(hw_cache_event_ids)); + intel_pmu_lbr_init_nhm(); + x86_pmu.event_constraints = intel_nehalem_event_constraints; pr_cont("Nehalem/Corei7 events, "); break; + case 28: /* Atom */ memcpy(hw_cache_event_ids, atom_hw_cache_event_ids, sizeof(hw_cache_event_ids)); + intel_pmu_lbr_init_atom(); + x86_pmu.event_constraints = intel_gen_event_constraints; pr_cont("Atom events, "); break; @@ -873,6 +884,8 @@ static __init int intel_pmu_init(void) memcpy(hw_cache_event_ids, westmere_hw_cache_event_ids, sizeof(hw_cache_event_ids)); + intel_pmu_lbr_init_nhm(); + x86_pmu.event_constraints = intel_westmere_event_constraints; pr_cont("Westmere events, "); break; diff --git a/arch/x86/kernel/cpu/perf_event_intel_lbr.c b/arch/x86/kernel/cpu/perf_event_intel_lbr.c new file mode 100644 index 0000000..ea3e99e --- /dev/null +++ b/arch/x86/kernel/cpu/perf_event_intel_lbr.c @@ -0,0 +1,228 @@ +#ifdef CONFIG_CPU_SUP_INTEL + +enum { + LBR_FORMAT_32 = 0x00, + LBR_FORMAT_LIP = 0x01, + LBR_FORMAT_EIP = 0x02, + LBR_FORMAT_EIP_FLAGS = 0x03, +}; + +/* + * We only support LBR implementations that have FREEZE_LBRS_ON_PMI + * otherwise it becomes near impossible to get a reliable stack. + */ + +#define X86_DEBUGCTL_LBR (1 << 0) +#define X86_DEBUGCTL_FREEZE_LBRS_ON_PMI (1 << 11) + +static void __intel_pmu_lbr_enable(void) +{ + u64 debugctl; + + rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl); + debugctl |= (X86_DEBUGCTL_LBR | X86_DEBUGCTL_FREEZE_LBRS_ON_PMI); + wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctl); +} + +static void __intel_pmu_lbr_disable(void) +{ + u64 debugctl; + + rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl); + debugctl &= ~(X86_DEBUGCTL_LBR | X86_DEBUGCTL_FREEZE_LBRS_ON_PMI); + wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctl); +} + +static void intel_pmu_lbr_reset_32(void) +{ + int i; + + for (i = 0; i < x86_pmu.lbr_nr; i++) + wrmsrl(x86_pmu.lbr_from + i, 0); +} + +static void intel_pmu_lbr_reset_64(void) +{ + int i; + + for (i = 0; i < x86_pmu.lbr_nr; i++) { + wrmsrl(x86_pmu.lbr_from + i, 0); + wrmsrl(x86_pmu.lbr_to + i, 0); + } +} + +static void intel_pmu_lbr_reset(void) +{ + if (x86_pmu.lbr_format == LBR_FORMAT_32) + intel_pmu_lbr_reset_32(); + else + intel_pmu_lbr_reset_64(); +} + +static void intel_pmu_lbr_enable(struct perf_event *event) +{ + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + + if (!x86_pmu.lbr_nr) + return; + + WARN_ON(cpuc->enabled); + + /* + * Reset the LBR stack if this is the first LBR user or + * we changed task context so as to avoid data leaks. + */ + + if (!cpuc->lbr_users || + (event->ctx->task && cpuc->lbr_context != event->ctx)) { + intel_pmu_lbr_reset(); + cpuc->lbr_context = event->ctx; + } + + cpuc->lbr_users++; +} + +static void intel_pmu_lbr_disable(struct perf_event *event) +{ + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + + if (!x86_pmu.lbr_nr) + return; + + cpuc->lbr_users--; + + BUG_ON(cpuc->lbr_users < 0); + WARN_ON(cpuc->enabled); +} + +static void intel_pmu_lbr_enable_all(void) +{ + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + + if (cpuc->lbr_users) + __intel_pmu_lbr_enable(); +} + +static void intel_pmu_lbr_disable_all(void) +{ + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + + if (cpuc->lbr_users) + __intel_pmu_lbr_disable(); +} + +static inline u64 intel_pmu_lbr_tos(void) +{ + u64 tos; + + rdmsrl(x86_pmu.lbr_tos, tos); + + return tos; +} + +static void intel_pmu_lbr_read_32(struct cpu_hw_events *cpuc) +{ + unsigned long mask = x86_pmu.lbr_nr - 1; + u64 tos = intel_pmu_lbr_tos(); + int i; + + for (i = 0; i < x86_pmu.lbr_nr; i++, tos--) { + unsigned long lbr_idx = (tos - i) & mask; + union { + struct { + u32 from; + u32 to; + }; + u64 lbr; + } msr_lastbranch; + + rdmsrl(x86_pmu.lbr_from + lbr_idx, msr_lastbranch.lbr); + + cpuc->lbr_entries[i].from = msr_lastbranch.from; + cpuc->lbr_entries[i].to = msr_lastbranch.to; + cpuc->lbr_entries[i].flags = 0; + } + cpuc->lbr_stack.nr = i; +} + +#define LBR_FROM_FLAG_MISPRED (1ULL << 63) + +/* + * Due to lack of segmentation in Linux the effective address (offset) + * is the same as the linear address, allowing us to merge the LIP and EIP + * LBR formats. + */ +static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc) +{ + unsigned long mask = x86_pmu.lbr_nr - 1; + u64 tos = intel_pmu_lbr_tos(); + int i; + + for (i = 0; i < x86_pmu.lbr_nr; i++, tos--) { + unsigned long lbr_idx = (tos - i) & mask; + u64 from, to, flags = 0; + + rdmsrl(x86_pmu.lbr_from + lbr_idx, from); + rdmsrl(x86_pmu.lbr_to + lbr_idx, to); + + if (x86_pmu.lbr_format == LBR_FORMAT_EIP_FLAGS) { + flags = !!(from & LBR_FROM_FLAG_MISPRED); + from = (u64)((((s64)from) << 1) >> 1); + } + + cpuc->lbr_entries[i].from = from; + cpuc->lbr_entries[i].to = to; + cpuc->lbr_entries[i].flags = flags; + } + cpuc->lbr_stack.nr = i; +} + +static void intel_pmu_lbr_read(void) +{ + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + + if (!cpuc->lbr_users) + return; + + if (x86_pmu.lbr_format == LBR_FORMAT_32) + intel_pmu_lbr_read_32(cpuc); + else + intel_pmu_lbr_read_64(cpuc); +} + +static int intel_pmu_lbr_format(void) +{ + u64 capabilities; + + rdmsrl(MSR_IA32_PERF_CAPABILITIES, capabilities); + return capabilities & 0x1f; +} + +static void intel_pmu_lbr_init_core(void) +{ + x86_pmu.lbr_format = intel_pmu_lbr_format(); + x86_pmu.lbr_nr = 4; + x86_pmu.lbr_tos = 0x01c9; + x86_pmu.lbr_from = 0x40; + x86_pmu.lbr_to = 0x60; +} + +static void intel_pmu_lbr_init_nhm(void) +{ + x86_pmu.lbr_format = intel_pmu_lbr_format(); + x86_pmu.lbr_nr = 16; + x86_pmu.lbr_tos = 0x01c9; + x86_pmu.lbr_from = 0x680; + x86_pmu.lbr_to = 0x6c0; +} + +static void intel_pmu_lbr_init_atom(void) +{ + x86_pmu.lbr_format = intel_pmu_lbr_format(); + x86_pmu.lbr_nr = 8; + x86_pmu.lbr_tos = 0x01c9; + x86_pmu.lbr_from = 0x40; + x86_pmu.lbr_to = 0x60; +} + +#endif /* CONFIG_CPU_SUP_INTEL */ diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 42307b5..ab4fd9e 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -467,6 +467,17 @@ struct perf_raw_record { void *data; }; +struct perf_branch_entry { + __u64 from; + __u64 to; + __u64 flags; +}; + +struct perf_branch_stack { + __u64 nr; + struct perf_branch_entry entries[0]; +}; + struct task_struct; /** -- cgit v0.10.2 From ef21f683a045a79b6aa86ad81e5fdfc0d5ddd250 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 3 Mar 2010 13:12:23 +0100 Subject: perf, x86: use LBR for PEBS IP+1 fixup Use the LBR to fix up the PEBS IP+1 issue. As said, PEBS reports the next instruction, here we use the LBR to find the last branch and from that construct the actual IP. If the IP matches the LBR-TO, we use LBR-FROM, otherwise we use the LBR-TO address as the beginning of the last basic block and decode forward. Once we find a match to the current IP, we use the previous location. This patch introduces a new ABI element: PERF_RECORD_MISC_EXACT, which conveys that the reported IP (PERF_SAMPLE_IP) is the exact instruction that caused the event (barring CPU errata). The fixup can fail due to various reasons: 1) LBR contains invalid data (quite possible) 2) part of the basic block got paged out 3) the reported IP isn't part of the basic block (see 1) Signed-off-by: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Masami Hiramatsu Cc: "Zhang, Yanmin" Cc: paulus@samba.org Cc: eranian@google.com Cc: robert.richter@amd.com Cc: fweisbec@gmail.com LKML-Reference: <20100304140100.619375431@chello.nl> Signed-off-by: Ingo Molnar diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h index db6109a..a9038c9 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h @@ -136,6 +136,25 @@ extern void perf_events_lapic_init(void); #define PERF_EVENT_INDEX_OFFSET 0 +/* + * Abuse bit 3 of the cpu eflags register to indicate proper PEBS IP fixups. + * This flag is otherwise unused and ABI specified to be 0, so nobody should + * care what we do with it. + */ +#define PERF_EFLAGS_EXACT (1UL << 3) + +#define perf_misc_flags(regs) \ +({ int misc = 0; \ + if (user_mode(regs)) \ + misc |= PERF_RECORD_MISC_USER; \ + else \ + misc |= PERF_RECORD_MISC_KERNEL; \ + if (regs->flags & PERF_EFLAGS_EXACT) \ + misc |= PERF_RECORD_MISC_EXACT; \ + misc; }) + +#define perf_instruction_pointer(regs) ((regs)->ip) + #else static inline void init_hw_perf_events(void) { } static inline void perf_events_lapic_init(void) { } diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 1badff6..5cb4e8d 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -29,6 +29,41 @@ #include #include +/* + * best effort, GUP based copy_from_user() that assumes IRQ or NMI context + */ +static unsigned long +copy_from_user_nmi(void *to, const void __user *from, unsigned long n) +{ + unsigned long offset, addr = (unsigned long)from; + int type = in_nmi() ? KM_NMI : KM_IRQ0; + unsigned long size, len = 0; + struct page *page; + void *map; + int ret; + + do { + ret = __get_user_pages_fast(addr, 1, 0, &page); + if (!ret) + break; + + offset = addr & (PAGE_SIZE - 1); + size = min(PAGE_SIZE - offset, n - len); + + map = kmap_atomic(page, type); + memcpy(to, map+offset, size); + kunmap_atomic(map, type); + put_page(page); + + len += size; + to += size; + addr += size; + + } while (len < n); + + return len; +} + static u64 perf_event_mask __read_mostly; struct event_constraint { @@ -1550,41 +1585,6 @@ perf_callchain_kernel(struct pt_regs *regs, struct perf_callchain_entry *entry) dump_trace(NULL, regs, NULL, regs->bp, &backtrace_ops, entry); } -/* - * best effort, GUP based copy_from_user() that assumes IRQ or NMI context - */ -static unsigned long -copy_from_user_nmi(void *to, const void __user *from, unsigned long n) -{ - unsigned long offset, addr = (unsigned long)from; - int type = in_nmi() ? KM_NMI : KM_IRQ0; - unsigned long size, len = 0; - struct page *page; - void *map; - int ret; - - do { - ret = __get_user_pages_fast(addr, 1, 0, &page); - if (!ret) - break; - - offset = addr & (PAGE_SIZE - 1); - size = min(PAGE_SIZE - offset, n - len); - - map = kmap_atomic(page, type); - memcpy(to, map+offset, size); - kunmap_atomic(map, type); - put_page(page); - - len += size; - to += size; - addr += size; - - } while (len < n); - - return len; -} - static int copy_stack_frame(const void __user *fp, struct stack_frame *frame) { unsigned long bytes; diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 44f6ed4..7eb78be 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -547,7 +547,7 @@ static void intel_pmu_disable_event(struct perf_event *event) x86_pmu_disable_event(event); if (unlikely(event->attr.precise)) - intel_pmu_pebs_disable(hwc); + intel_pmu_pebs_disable(event); } static void intel_pmu_enable_fixed(struct hw_perf_event *hwc) @@ -600,7 +600,7 @@ static void intel_pmu_enable_event(struct perf_event *event) } if (unlikely(event->attr.precise)) - intel_pmu_pebs_enable(hwc); + intel_pmu_pebs_enable(event); __x86_pmu_enable_event(hwc); } diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c index 0d994ef..50e6ff3 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -331,26 +331,32 @@ intel_pebs_constraints(struct perf_event *event) return &emptyconstraint; } -static void intel_pmu_pebs_enable(struct hw_perf_event *hwc) +static void intel_pmu_pebs_enable(struct perf_event *event) { struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + struct hw_perf_event *hwc = &event->hw; u64 val = cpuc->pebs_enabled; hwc->config &= ~ARCH_PERFMON_EVENTSEL_INT; val |= 1ULL << hwc->idx; wrmsrl(MSR_IA32_PEBS_ENABLE, val); + + intel_pmu_lbr_enable(event); } -static void intel_pmu_pebs_disable(struct hw_perf_event *hwc) +static void intel_pmu_pebs_disable(struct perf_event *event) { struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + struct hw_perf_event *hwc = &event->hw; u64 val = cpuc->pebs_enabled; val &= ~(1ULL << hwc->idx); wrmsrl(MSR_IA32_PEBS_ENABLE, val); hwc->config |= ARCH_PERFMON_EVENTSEL_INT; + + intel_pmu_lbr_disable(event); } static void intel_pmu_pebs_enable_all(void) @@ -369,6 +375,70 @@ static void intel_pmu_pebs_disable_all(void) wrmsrl(MSR_IA32_PEBS_ENABLE, 0); } +#include + +#define MAX_INSN_SIZE 16 + +static inline bool kernel_ip(unsigned long ip) +{ +#ifdef CONFIG_X86_32 + return ip > PAGE_OFFSET; +#else + return (long)ip < 0; +#endif +} + +static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs) +{ + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + unsigned long from = cpuc->lbr_entries[0].from; + unsigned long old_to, to = cpuc->lbr_entries[0].to; + unsigned long ip = regs->ip; + + if (!cpuc->lbr_stack.nr || !from || !to) + return 0; + + if (ip < to) + return 0; + + /* + * We sampled a branch insn, rewind using the LBR stack + */ + if (ip == to) { + regs->ip = from; + return 1; + } + + do { + struct insn insn; + u8 buf[MAX_INSN_SIZE]; + void *kaddr; + + old_to = to; + if (!kernel_ip(ip)) { + int bytes, size = min_t(int, MAX_INSN_SIZE, ip - to); + + bytes = copy_from_user_nmi(buf, (void __user *)to, size); + if (bytes != size) + return 0; + + kaddr = buf; + } else + kaddr = (void *)to; + + kernel_insn_init(&insn, kaddr); + insn_get_length(&insn); + to += insn.length; + } while (to < ip); + + if (to == ip) { + regs->ip = old_to; + return 1; + } + + return 0; +} + static int intel_pmu_save_and_restart(struct perf_event *event); static void intel_pmu_disable_event(struct perf_event *event); @@ -424,6 +494,11 @@ static void intel_pmu_drain_pebs_core(struct pt_regs *iregs) regs.bp = at->bp; regs.sp = at->sp; + if (intel_pmu_pebs_fixup_ip(®s)) + regs.flags |= PERF_EFLAGS_EXACT; + else + regs.flags &= ~PERF_EFLAGS_EXACT; + if (perf_event_overflow(event, 1, &data, ®s)) intel_pmu_disable_event(event); @@ -487,6 +562,11 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs) regs.bp = at->bp; regs.sp = at->sp; + if (intel_pmu_pebs_fixup_ip(®s)) + regs.flags |= PERF_EFLAGS_EXACT; + else + regs.flags &= ~PERF_EFLAGS_EXACT; + if (perf_event_overflow(event, 1, &data, ®s)) intel_pmu_disable_event(event); } diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index ab4fd9e..be85f7c 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -294,6 +294,12 @@ struct perf_event_mmap_page { #define PERF_RECORD_MISC_USER (2 << 0) #define PERF_RECORD_MISC_HYPERVISOR (3 << 0) +#define PERF_RECORD_MISC_EXACT (1 << 14) +/* + * Reserve the last bit to indicate some extended misc field + */ +#define PERF_RECORD_MISC_EXT_RESERVED (1 << 15) + struct perf_event_header { __u32 type; __u16 misc; -- cgit v0.10.2 From 1676b8a077c352085d52578fb4f29350b58b6e74 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 4 Mar 2010 14:19:36 +0100 Subject: perf-top: Show the percentage of successfull PEBS-fixups Use the PERF_RECORD_MISC_EXACT information to measure the success rate of the PEBS fix-up. Signed-off-by: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: paulus@samba.org Cc: eranian@google.com Cc: robert.richter@amd.com Cc: fweisbec@gmail.com LKML-Reference: <20100304140100.694233760@chello.nl> Signed-off-by: Ingo Molnar diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 31f2e59..c051833 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -410,6 +410,7 @@ static double sym_weight(const struct sym_entry *sym) static long samples; static long userspace_samples; +static long exact_samples; static const char CONSOLE_CLEAR[] = ""; static void __list_insert_active_sym(struct sym_entry *syme) @@ -450,6 +451,7 @@ static void print_sym_table(void) int counter, snap = !display_weighted ? sym_counter : 0; float samples_per_sec = samples/delay_secs; float ksamples_per_sec = (samples-userspace_samples)/delay_secs; + float esamples_percent = (100.0*exact_samples)/samples; float sum_ksamples = 0.0; struct sym_entry *syme, *n; struct rb_root tmp = RB_ROOT; @@ -457,7 +459,7 @@ static void print_sym_table(void) int sym_width = 0, dso_width = 0, max_dso_width; const int win_width = winsize.ws_col - 1; - samples = userspace_samples = 0; + samples = userspace_samples = exact_samples = 0; /* Sort the active symbols */ pthread_mutex_lock(&active_symbols_lock); @@ -488,9 +490,10 @@ static void print_sym_table(void) puts(CONSOLE_CLEAR); printf("%-*.*s\n", win_width, win_width, graph_dotted_line); - printf( " PerfTop:%8.0f irqs/sec kernel:%4.1f%% [", + printf( " PerfTop:%8.0f irqs/sec kernel:%4.1f%% exact: %4.1f%% [", samples_per_sec, - 100.0 - (100.0*((samples_per_sec-ksamples_per_sec)/samples_per_sec))); + 100.0 - (100.0*((samples_per_sec-ksamples_per_sec)/samples_per_sec)), + esamples_percent); if (nr_counters == 1 || !display_weighted) { printf("%Ld", (u64)attrs[0].sample_period); @@ -954,6 +957,9 @@ static void event__process_sample(const event_t *self, return; } + if (self->header.misc & PERF_RECORD_MISC_EXACT) + exact_samples++; + if (event__preprocess_sample(self, session, &al, symbol_filter) < 0 || al.filtered) return; -- cgit v0.10.2 From 8db909a7e3c888b5d45aef7650d74ccebe3ce725 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 3 Mar 2010 17:07:40 +0100 Subject: perf, x86: Clean up IA32_PERF_CAPABILITIES usage Saner PERF_CAPABILITIES support, which also exposes pebs_trap. Use that latter to make PEBS's use of LBR conditional since a fault-like pebs should already report the correct IP. ( As of this writing there is no known hardware that implements !pebs_trap ) Signed-off-by: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: paulus@samba.org Cc: eranian@google.com Cc: robert.richter@amd.com Cc: fweisbec@gmail.com LKML-Reference: <20100304140100.770650663@chello.nl> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 5cb4e8d..7b5430b 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -154,6 +154,17 @@ struct cpu_hw_events { #define for_each_event_constraint(e, c) \ for ((e) = (c); (e)->cmask; (e)++) +union perf_capabilities { + struct { + u64 lbr_format : 6; + u64 pebs_trap : 1; + u64 pebs_arch_reg : 1; + u64 pebs_format : 4; + u64 smm_freeze : 1; + }; + u64 capabilities; +}; + /* * struct x86_pmu - generic x86 pmu */ @@ -195,7 +206,8 @@ struct x86_pmu { /* * Intel Arch Perfmon v2+ */ - u64 intel_ctrl; + u64 intel_ctrl; + union perf_capabilities intel_cap; /* * Intel DebugStore bits @@ -210,7 +222,6 @@ struct x86_pmu { */ unsigned long lbr_tos, lbr_from, lbr_to; /* MSR base regs */ int lbr_nr; /* hardware stack size */ - int lbr_format; /* hardware format */ }; static struct x86_pmu x86_pmu __read_mostly; diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 7eb78be..246c072 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -835,6 +835,16 @@ static __init int intel_pmu_init(void) if (version > 1) x86_pmu.num_events_fixed = max((int)edx.split.num_events_fixed, 3); + /* + * v2 and above have a perf capabilities MSR + */ + if (version > 1) { + u64 capabilities; + + rdmsrl(MSR_IA32_PERF_CAPABILITIES, capabilities); + x86_pmu.intel_cap.capabilities = capabilities; + } + intel_ds_init(); /* diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c index 50e6ff3..5e40294 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -342,7 +342,8 @@ static void intel_pmu_pebs_enable(struct perf_event *event) val |= 1ULL << hwc->idx; wrmsrl(MSR_IA32_PEBS_ENABLE, val); - intel_pmu_lbr_enable(event); + if (x86_pmu.intel_cap.pebs_trap) + intel_pmu_lbr_enable(event); } static void intel_pmu_pebs_disable(struct perf_event *event) @@ -356,7 +357,8 @@ static void intel_pmu_pebs_disable(struct perf_event *event) hwc->config |= ARCH_PERFMON_EVENTSEL_INT; - intel_pmu_lbr_disable(event); + if (x86_pmu.intel_cap.pebs_trap) + intel_pmu_lbr_disable(event); } static void intel_pmu_pebs_enable_all(void) @@ -395,6 +397,12 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs) unsigned long old_to, to = cpuc->lbr_entries[0].to; unsigned long ip = regs->ip; + /* + * We don't need to fixup if the PEBS assist is fault like + */ + if (!x86_pmu.intel_cap.pebs_trap) + return 1; + if (!cpuc->lbr_stack.nr || !from || !to) return 0; @@ -589,34 +597,26 @@ static void intel_ds_init(void) x86_pmu.bts = boot_cpu_has(X86_FEATURE_BTS); x86_pmu.pebs = boot_cpu_has(X86_FEATURE_PEBS); if (x86_pmu.pebs) { - int format = 0; - - if (x86_pmu.version > 1) { - u64 capabilities; - /* - * v2+ has a PEBS format field - */ - rdmsrl(MSR_IA32_PERF_CAPABILITIES, capabilities); - format = (capabilities >> 8) & 0xf; - } + char pebs_type = x86_pmu.intel_cap.pebs_trap ? '+' : '-'; + int format = x86_pmu.intel_cap.pebs_format; switch (format) { case 0: - printk(KERN_CONT "PEBS v0, "); + printk(KERN_CONT "PEBS fmt0%c, ", pebs_type); x86_pmu.pebs_record_size = sizeof(struct pebs_record_core); x86_pmu.drain_pebs = intel_pmu_drain_pebs_core; x86_pmu.pebs_constraints = intel_core_pebs_events; break; case 1: - printk(KERN_CONT "PEBS v1, "); + printk(KERN_CONT "PEBS fmt1%c, ", pebs_type); x86_pmu.pebs_record_size = sizeof(struct pebs_record_nhm); x86_pmu.drain_pebs = intel_pmu_drain_pebs_nhm; x86_pmu.pebs_constraints = intel_nehalem_pebs_events; break; default: - printk(KERN_CONT "PEBS unknown format: %d, ", format); + printk(KERN_CONT "no PEBS fmt%d%c, ", format, pebs_type); x86_pmu.pebs = 0; break; } diff --git a/arch/x86/kernel/cpu/perf_event_intel_lbr.c b/arch/x86/kernel/cpu/perf_event_intel_lbr.c index ea3e99e..4f3a124 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_lbr.c +++ b/arch/x86/kernel/cpu/perf_event_intel_lbr.c @@ -53,7 +53,7 @@ static void intel_pmu_lbr_reset_64(void) static void intel_pmu_lbr_reset(void) { - if (x86_pmu.lbr_format == LBR_FORMAT_32) + if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_32) intel_pmu_lbr_reset_32(); else intel_pmu_lbr_reset_64(); @@ -155,6 +155,7 @@ static void intel_pmu_lbr_read_32(struct cpu_hw_events *cpuc) static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc) { unsigned long mask = x86_pmu.lbr_nr - 1; + int lbr_format = x86_pmu.intel_cap.lbr_format; u64 tos = intel_pmu_lbr_tos(); int i; @@ -165,7 +166,7 @@ static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc) rdmsrl(x86_pmu.lbr_from + lbr_idx, from); rdmsrl(x86_pmu.lbr_to + lbr_idx, to); - if (x86_pmu.lbr_format == LBR_FORMAT_EIP_FLAGS) { + if (lbr_format == LBR_FORMAT_EIP_FLAGS) { flags = !!(from & LBR_FROM_FLAG_MISPRED); from = (u64)((((s64)from) << 1) >> 1); } @@ -184,23 +185,14 @@ static void intel_pmu_lbr_read(void) if (!cpuc->lbr_users) return; - if (x86_pmu.lbr_format == LBR_FORMAT_32) + if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_32) intel_pmu_lbr_read_32(cpuc); else intel_pmu_lbr_read_64(cpuc); } -static int intel_pmu_lbr_format(void) -{ - u64 capabilities; - - rdmsrl(MSR_IA32_PERF_CAPABILITIES, capabilities); - return capabilities & 0x1f; -} - static void intel_pmu_lbr_init_core(void) { - x86_pmu.lbr_format = intel_pmu_lbr_format(); x86_pmu.lbr_nr = 4; x86_pmu.lbr_tos = 0x01c9; x86_pmu.lbr_from = 0x40; @@ -209,7 +201,6 @@ static void intel_pmu_lbr_init_core(void) static void intel_pmu_lbr_init_nhm(void) { - x86_pmu.lbr_format = intel_pmu_lbr_format(); x86_pmu.lbr_nr = 16; x86_pmu.lbr_tos = 0x01c9; x86_pmu.lbr_from = 0x680; @@ -218,7 +209,6 @@ static void intel_pmu_lbr_init_nhm(void) static void intel_pmu_lbr_init_atom(void) { - x86_pmu.lbr_format = intel_pmu_lbr_format(); x86_pmu.lbr_nr = 8; x86_pmu.lbr_tos = 0x01c9; x86_pmu.lbr_from = 0x40; -- cgit v0.10.2 From 7e1a40dda619b0483fbe0740494ed2c2a1f05289 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 4 Mar 2010 12:38:03 +0100 Subject: perf, x86: Expose the full PEBS record using PERF_SAMPLE_RAW Expose the full PEBS record using PERF_SAMPLE_RAW Signed-off-by: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: paulus@samba.org Cc: eranian@google.com Cc: robert.richter@amd.com Cc: fweisbec@gmail.com LKML-Reference: <20100304140100.847218224@chello.nl> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c index 5e40294..ef56f05 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -457,6 +457,7 @@ static void intel_pmu_drain_pebs_core(struct pt_regs *iregs) struct perf_event *event = cpuc->events[0]; /* PMC0 only */ struct pebs_record_core *at, *top; struct perf_sample_data data; + struct perf_raw_record raw; struct pt_regs regs; int n; @@ -479,6 +480,12 @@ static void intel_pmu_drain_pebs_core(struct pt_regs *iregs) perf_sample_data_init(&data, 0); data.period = event->hw.last_period; + if (event->attr.sample_type & PERF_SAMPLE_RAW) { + raw.size = x86_pmu.pebs_record_size; + raw.data = at; + data.raw = &raw; + } + n = top - at; /* @@ -521,6 +528,7 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs) struct pebs_record_nhm *at, *top; struct perf_sample_data data; struct perf_event *event = NULL; + struct perf_raw_record raw; struct pt_regs regs; int bit, n; @@ -562,6 +570,12 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs) perf_sample_data_init(&data, 0); data.period = event->hw.last_period; + if (event->attr.sample_type & PERF_SAMPLE_RAW) { + raw.size = x86_pmu.pebs_record_size; + raw.data = at; + data.raw = &raw; + } + /* * See the comment in intel_pmu_drain_pebs_core() */ -- cgit v0.10.2 From 30a813ae035d3e220a89609adce878e045c49547 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 4 Mar 2010 13:49:21 +0100 Subject: x86: Move MAX_INSN_SIZE into asm/insn.h Since there's now two users for this, place it in a common header. Signed-off-by: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Masami Hiramatsu Cc: paulus@samba.org Cc: eranian@google.com Cc: robert.richter@amd.com Cc: fweisbec@gmail.com LKML-Reference: <20100304140100.923774125@chello.nl> Signed-off-by: Ingo Molnar diff --git a/arch/x86/include/asm/insn.h b/arch/x86/include/asm/insn.h index 96c2e0a..88c765e 100644 --- a/arch/x86/include/asm/insn.h +++ b/arch/x86/include/asm/insn.h @@ -68,6 +68,8 @@ struct insn { const insn_byte_t *next_byte; }; +#define MAX_INSN_SIZE 16 + #define X86_MODRM_MOD(modrm) (((modrm) & 0xc0) >> 6) #define X86_MODRM_REG(modrm) (((modrm) & 0x38) >> 3) #define X86_MODRM_RM(modrm) ((modrm) & 0x07) diff --git a/arch/x86/include/asm/kprobes.h b/arch/x86/include/asm/kprobes.h index 4ffa345..5478825 100644 --- a/arch/x86/include/asm/kprobes.h +++ b/arch/x86/include/asm/kprobes.h @@ -24,6 +24,7 @@ #include #include #include +#include #define __ARCH_WANT_KPROBES_INSN_SLOT @@ -36,7 +37,6 @@ typedef u8 kprobe_opcode_t; #define RELATIVEJUMP_SIZE 5 #define RELATIVECALL_OPCODE 0xe8 #define RELATIVE_ADDR_SIZE 4 -#define MAX_INSN_SIZE 16 #define MAX_STACK_SIZE 64 #define MIN_STACK_SIZE(ADDR) \ (((MAX_STACK_SIZE) < (((unsigned long)current_thread_info()) + \ diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c index ef56f05..72453ac 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -379,8 +379,6 @@ static void intel_pmu_pebs_disable_all(void) #include -#define MAX_INSN_SIZE 16 - static inline bool kernel_ip(unsigned long ip) { #ifdef CONFIG_X86_32 -- cgit v0.10.2 From 3adaebd69557615c1bf0365ce5e32d93ac7d82af Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 5 Mar 2010 12:09:29 +0100 Subject: perf, x86: Fix silly bug in data store buffer allocation Fix up the ds allocation error path, where we could free @buffer before we used it. Signed-off-by: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: paulus@samba.org Cc: eranian@google.com Cc: robert.richter@amd.com Cc: fweisbec@gmail.com LKML-Reference: <20100305154128.813452402@chello.nl> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c index 72453ac..a67fff1 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -127,10 +127,8 @@ static int reserve_ds_buffers(void) err = -ENOMEM; ds = kzalloc(sizeof(*ds), GFP_KERNEL); - if (unlikely(!ds)) { - kfree(buffer); + if (unlikely(!ds)) break; - } per_cpu(cpu_hw_events, cpu).ds = ds; if (x86_pmu.bts) { -- cgit v0.10.2 From 3c44780b220e876b01e39d4028cd6f4205fbf5d6 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 4 Mar 2010 21:49:01 +0100 Subject: perf, x86: Disable PEBS on clovertown chips This CPU has just too many handycaps to be really useful. Signed-off-by: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: paulus@samba.org Cc: eranian@google.com Cc: robert.richter@amd.com Cc: fweisbec@gmail.com LKML-Reference: <20100305154128.890278662@chello.nl> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 7b5430b..335ee1d 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -197,6 +197,7 @@ struct x86_pmu { void (*put_event_constraints)(struct cpu_hw_events *cpuc, struct perf_event *event); struct event_constraint *event_constraints; + void (*quirks)(void); void (*cpu_prepare)(int cpu); void (*cpu_starting)(int cpu); @@ -1373,6 +1374,9 @@ void __init init_hw_perf_events(void) pr_cont("%s PMU driver.\n", x86_pmu.name); + if (x86_pmu.quirks) + x86_pmu.quirks(); + if (x86_pmu.num_events > X86_PMC_MAX_GENERIC) { WARN(1, KERN_ERR "hw perf events %d > max(%d), clipping!", x86_pmu.num_events, X86_PMC_MAX_GENERIC); diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 246c072..224c952 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -792,6 +792,32 @@ static __initconst struct x86_pmu intel_pmu = { .cpu_dying = fini_debug_store_on_cpu, }; +static void intel_clovertown_quirks(void) +{ + /* + * PEBS is unreliable due to: + * + * AJ67 - PEBS may experience CPL leaks + * AJ68 - PEBS PMI may be delayed by one event + * AJ69 - GLOBAL_STATUS[62] will only be set when DEBUGCTL[12] + * AJ106 - FREEZE_LBRS_ON_PMI doesn't work in combination with PEBS + * + * AJ67 could be worked around by restricting the OS/USR flags. + * AJ69 could be worked around by setting PMU_FREEZE_ON_PMI. + * + * AJ106 could possibly be worked around by not allowing LBR + * usage from PEBS, including the fixup. + * AJ68 could possibly be worked around by always programming + * a pebs_event_reset[0] value and coping with the lost events. + * + * But taken together it might just make sense to not enable PEBS on + * these chips. + */ + printk(KERN_WARNING "PEBS disabled due to CPU errata.\n"); + x86_pmu.pebs = 0; + x86_pmu.pebs_constraints = NULL; +} + static __init int intel_pmu_init(void) { union cpuid10_edx edx; @@ -856,6 +882,7 @@ static __init int intel_pmu_init(void) break; case 15: /* original 65 nm celeron/pentium/core2/xeon, "Merom"/"Conroe" */ + x86_pmu.quirks = intel_clovertown_quirks; case 22: /* single-core 65 nm celeron/core2solo "Merom-L"/"Conroe-L" */ case 23: /* current 45 nm celeron/core2/xeon "Penryn"/"Wolfdale" */ case 29: /* six-core 45 nm xeon "Dunnington" */ -- cgit v0.10.2 From 74846d35b24b6efd61bb88a0a750b6bb257e6e78 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 5 Mar 2010 13:49:35 +0100 Subject: perf, x86: Clear the LBRs on init Some CPUs have errata where the LBR is not cleared on Power-On. So always clear the LBRs before use. Signed-off-by: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: paulus@samba.org Cc: eranian@google.com Cc: robert.richter@amd.com Cc: fweisbec@gmail.com LKML-Reference: <20100305154128.966563424@chello.nl> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 224c952..c135ed7 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -767,6 +767,20 @@ static __initconst struct x86_pmu core_pmu = { .event_constraints = intel_core_event_constraints, }; +static void intel_pmu_cpu_starting(int cpu) +{ + init_debug_store_on_cpu(cpu); + /* + * Deal with CPUs that don't clear their LBRs on power-up. + */ + intel_pmu_lbr_reset(); +} + +static void intel_pmu_cpu_dying(int cpu) +{ + fini_debug_store_on_cpu(cpu); +} + static __initconst struct x86_pmu intel_pmu = { .name = "Intel", .handle_irq = intel_pmu_handle_irq, @@ -788,8 +802,8 @@ static __initconst struct x86_pmu intel_pmu = { .max_period = (1ULL << 31) - 1, .get_event_constraints = intel_get_event_constraints, - .cpu_starting = init_debug_store_on_cpu, - .cpu_dying = fini_debug_store_on_cpu, + .cpu_starting = intel_pmu_cpu_starting, + .cpu_dying = intel_pmu_cpu_dying, }; static void intel_clovertown_quirks(void) diff --git a/arch/x86/kernel/cpu/perf_event_intel_lbr.c b/arch/x86/kernel/cpu/perf_event_intel_lbr.c index 4f3a124..dcec765 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_lbr.c +++ b/arch/x86/kernel/cpu/perf_event_intel_lbr.c @@ -53,6 +53,9 @@ static void intel_pmu_lbr_reset_64(void) static void intel_pmu_lbr_reset(void) { + if (!x86_pmu.lbr_nr) + return; + if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_32) intel_pmu_lbr_reset_32(); else -- cgit v0.10.2 From a562b1871f7f7d2f3a835c3c1e07fa58d473cfb7 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 5 Mar 2010 16:29:14 +0100 Subject: perf, x86: Robustify PEBS fixup It turns out the LBR is massively unreliable on certain CPUs, so code the fixup a little more defensive to avoid crashing the kernel. Signed-off-by: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: paulus@samba.org Cc: eranian@google.com Cc: robert.richter@amd.com Cc: fweisbec@gmail.com LKML-Reference: <20100305154129.042271287@chello.nl> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c index a67fff1..e7ac517 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -399,10 +399,23 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs) if (!x86_pmu.intel_cap.pebs_trap) return 1; + /* + * No LBR entry, no basic block, no rewinding + */ if (!cpuc->lbr_stack.nr || !from || !to) return 0; - if (ip < to) + /* + * Basic blocks should never cross user/kernel boundaries + */ + if (kernel_ip(ip) != kernel_ip(to)) + return 0; + + /* + * unsigned math, either ip is before the start (impossible) or + * the basic block is larger than 1 page (sanity) + */ + if ((ip - to) > PAGE_SIZE) return 0; /* @@ -420,7 +433,7 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs) old_to = to; if (!kernel_ip(ip)) { - int bytes, size = min_t(int, MAX_INSN_SIZE, ip - to); + int bytes, size = MAX_INSN_SIZE; bytes = copy_from_user_nmi(buf, (void __user *)to, size); if (bytes != size) @@ -440,6 +453,10 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs) return 1; } + /* + * Even though we decoded the basic block, the instruction stream + * never matched the given IP, either the TO or the IP got corrupted. + */ return 0; } -- cgit v0.10.2 From cc7f00820b2f3be656569c41158d9323e425bcfe Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 8 Mar 2010 17:51:33 +0100 Subject: perf, x86: Avoid double disable on throttle vs ioctl(PERF_IOC_DISABLE) Calling ioctl(PERF_EVENT_IOC_DISABLE) on a thottled counter would result in a double disable, cure this by using x86_pmu_{start,stop} for throttle/unthrottle and teach x86_pmu_stop() to check ->active_mask. Signed-off-by: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: paulus@samba.org Cc: eranian@google.com Cc: robert.richter@amd.com Cc: fweisbec@gmail.com LKML-Reference: Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c index e7ac517..a7401e4 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -461,7 +461,6 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs) } static int intel_pmu_save_and_restart(struct perf_event *event); -static void intel_pmu_disable_event(struct perf_event *event); static void intel_pmu_drain_pebs_core(struct pt_regs *iregs) { @@ -528,7 +527,7 @@ static void intel_pmu_drain_pebs_core(struct pt_regs *iregs) regs.flags &= ~PERF_EFLAGS_EXACT; if (perf_event_overflow(event, 1, &data, ®s)) - intel_pmu_disable_event(event); + x86_pmu_stop(event); out: intel_pmu_pebs_enable_all(); @@ -603,7 +602,7 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs) regs.flags &= ~PERF_EFLAGS_EXACT; if (perf_event_overflow(event, 1, &data, ®s)) - intel_pmu_disable_event(event); + x86_pmu_stop(event); } out: intel_pmu_pebs_enable_all(); -- cgit v0.10.2 From 8f4aebd2be9892bf8fb79a2d8576d3f3ee7f00f6 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Sat, 6 Mar 2010 13:26:11 +0100 Subject: perf, x86: Fix pebs drains I overlooked the perf_disable()/perf_enable() calls in intel_pmu_handle_irq(), (pointed out by Markus) so we should not explicitly disable_all/enable_all pebs counters in the drain functions, these are already disabled and enabling them early is confusing. Signed-off-by: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: paulus@samba.org Cc: eranian@google.com Cc: robert.richter@amd.com Cc: fweisbec@gmail.com LKML-Reference: Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c index a7401e4..66c6962 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -476,18 +476,16 @@ static void intel_pmu_drain_pebs_core(struct pt_regs *iregs) if (!event || !ds || !x86_pmu.pebs) return; - intel_pmu_pebs_disable_all(); - at = (struct pebs_record_core *)(unsigned long)ds->pebs_buffer_base; top = (struct pebs_record_core *)(unsigned long)ds->pebs_index; if (top <= at) - goto out; + return; ds->pebs_index = ds->pebs_buffer_base; if (!intel_pmu_save_and_restart(event)) - goto out; + return; perf_sample_data_init(&data, 0); data.period = event->hw.last_period; @@ -528,9 +526,6 @@ static void intel_pmu_drain_pebs_core(struct pt_regs *iregs) if (perf_event_overflow(event, 1, &data, ®s)) x86_pmu_stop(event); - -out: - intel_pmu_pebs_enable_all(); } static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs) @@ -547,13 +542,11 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs) if (!ds || !x86_pmu.pebs) return; - intel_pmu_pebs_disable_all(); - at = (struct pebs_record_nhm *)(unsigned long)ds->pebs_buffer_base; top = (struct pebs_record_nhm *)(unsigned long)ds->pebs_index; if (top <= at) - goto out; + return; ds->pebs_index = ds->pebs_buffer_base; @@ -604,8 +597,6 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs) if (perf_event_overflow(event, 1, &data, ®s)) x86_pmu_stop(event); } -out: - intel_pmu_pebs_enable_all(); } /* -- cgit v0.10.2 From 4807e3d5dc7bb7057dd6ca3abb09f3da2eb8c323 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Sat, 6 Mar 2010 13:47:07 +0100 Subject: perf, x86: Fix PEBS enable/disable vs cpuc->enabled We should never call ->enable with the pmu enabled, and we _can_ have ->disable called with the pmu enabled. Signed-off-by: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: paulus@samba.org Cc: eranian@google.com Cc: robert.richter@amd.com Cc: fweisbec@gmail.com LKML-Reference: Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c index 66c6962..9ad0e67 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -338,7 +338,7 @@ static void intel_pmu_pebs_enable(struct perf_event *event) hwc->config &= ~ARCH_PERFMON_EVENTSEL_INT; val |= 1ULL << hwc->idx; - wrmsrl(MSR_IA32_PEBS_ENABLE, val); + WARN_ON_ONCE(cpuc->enabled); if (x86_pmu.intel_cap.pebs_trap) intel_pmu_lbr_enable(event); @@ -351,7 +351,8 @@ static void intel_pmu_pebs_disable(struct perf_event *event) u64 val = cpuc->pebs_enabled; val &= ~(1ULL << hwc->idx); - wrmsrl(MSR_IA32_PEBS_ENABLE, val); + if (cpuc->enabled) + wrmsrl(MSR_IA32_PEBS_ENABLE, val); hwc->config |= ARCH_PERFMON_EVENTSEL_INT; -- cgit v0.10.2 From 2df202bf7520eaffcbfb07e45dfa3cfb0aeee2c0 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Sat, 6 Mar 2010 13:48:54 +0100 Subject: perf, x86: Fix LBR enable/disable vs cpuc->enabled We should never call ->enable with the pmu enabled, and we _can_ have ->disable called with the pmu enabled. Signed-off-by: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: paulus@samba.org Cc: eranian@google.com Cc: robert.richter@amd.com Cc: fweisbec@gmail.com LKML-Reference: Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event_intel_lbr.c b/arch/x86/kernel/cpu/perf_event_intel_lbr.c index dcec765..0145f99 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_lbr.c +++ b/arch/x86/kernel/cpu/perf_event_intel_lbr.c @@ -69,7 +69,7 @@ static void intel_pmu_lbr_enable(struct perf_event *event) if (!x86_pmu.lbr_nr) return; - WARN_ON(cpuc->enabled); + WARN_ON_ONCE(cpuc->enabled); /* * Reset the LBR stack if this is the first LBR user or @@ -93,9 +93,10 @@ static void intel_pmu_lbr_disable(struct perf_event *event) return; cpuc->lbr_users--; - BUG_ON(cpuc->lbr_users < 0); - WARN_ON(cpuc->enabled); + + if (cpuc->enabled && !cpuc->lbr_users) + __intel_pmu_lbr_disable(); } static void intel_pmu_lbr_enable_all(void) -- cgit v0.10.2 From d329527e47851f84b1e7944ed9601205f35f1b93 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 8 Mar 2010 13:57:14 +0100 Subject: perf, x86: Reorder intel_pmu_enable_all() The documentation says we have to enable PEBS before we enable the PMU proper. Signed-off-by: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: paulus@samba.org Cc: eranian@google.com Cc: robert.richter@amd.com Cc: fweisbec@gmail.com LKML-Reference: Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index c135ed7..d3e2424 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -487,6 +487,8 @@ static void intel_pmu_enable_all(void) { struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + intel_pmu_pebs_enable_all(); + intel_pmu_lbr_enable_all(); wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, x86_pmu.intel_ctrl); if (test_bit(X86_PMC_IDX_FIXED_BTS, cpuc->active_mask)) { @@ -498,9 +500,6 @@ static void intel_pmu_enable_all(void) intel_pmu_enable_bts(event->hw.config); } - - intel_pmu_pebs_enable_all(); - intel_pmu_lbr_enable_all(); } static inline u64 intel_pmu_get_status(void) -- cgit v0.10.2 From 12ab854d744f04bfc5c6c4db723b7e31fc03eb29 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Sat, 6 Mar 2010 18:57:38 +0100 Subject: perf, x86: Deal with multiple state bits for pebs-fmt1 Its unclear if the PEBS state record will have only a single bit set, in case it does not and accumulates bits, deal with that by only processing each event once. Also, robustify some of the code. Signed-off-by: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: paulus@samba.org Cc: eranian@google.com Cc: robert.richter@amd.com Cc: fweisbec@gmail.com LKML-Reference: Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c index 9ad0e67..b4680da 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -538,6 +538,7 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs) struct perf_event *event = NULL; struct perf_raw_record raw; struct pt_regs regs; + u64 status = 0; int bit, n; if (!ds || !x86_pmu.pebs) @@ -561,13 +562,22 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs) for ( ; at < top; at++) { for_each_bit(bit, (unsigned long *)&at->status, MAX_PEBS_EVENTS) { - if (!cpuc->events[bit]->attr.precise) + event = cpuc->events[bit]; + if (!test_bit(bit, cpuc->active_mask)) continue; - event = cpuc->events[bit]; + WARN_ON_ONCE(!event); + + if (!event->attr.precise) + continue; + + if (__test_and_set_bit(bit, (unsigned long *)&status)) + continue; + + break; } - if (!event) + if (!event || bit >= MAX_PEBS_EVENTS) continue; if (!intel_pmu_save_and_restart(event)) -- cgit v0.10.2 From ad0e6cfe2a2a61d7b5530188e571d508146cb43b Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Sat, 6 Mar 2010 19:49:06 +0100 Subject: perf, x86: Fix silly bug in intel_pmu_pebs_{enable,disable} We need to use the actual cpuc->pebs_enabled value, not a local copy for the changes to take effect. Signed-off-by: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: paulus@samba.org Cc: eranian@google.com Cc: robert.richter@amd.com Cc: fweisbec@gmail.com LKML-Reference: Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c index b4680da..2423694 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -333,11 +333,10 @@ static void intel_pmu_pebs_enable(struct perf_event *event) { struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); struct hw_perf_event *hwc = &event->hw; - u64 val = cpuc->pebs_enabled; hwc->config &= ~ARCH_PERFMON_EVENTSEL_INT; - val |= 1ULL << hwc->idx; + cpuc->pebs_enabled |= 1ULL << hwc->idx; WARN_ON_ONCE(cpuc->enabled); if (x86_pmu.intel_cap.pebs_trap) @@ -348,11 +347,10 @@ static void intel_pmu_pebs_disable(struct perf_event *event) { struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); struct hw_perf_event *hwc = &event->hw; - u64 val = cpuc->pebs_enabled; - val &= ~(1ULL << hwc->idx); + cpuc->pebs_enabled &= ~(1ULL << hwc->idx); if (cpuc->enabled) - wrmsrl(MSR_IA32_PEBS_ENABLE, val); + wrmsrl(MSR_IA32_PEBS_ENABLE, cpuc->pebs_enabled); hwc->config |= ARCH_PERFMON_EVENTSEL_INT; -- cgit v0.10.2 From b83a46e7da4a948cc852ba7805dfb1a392dec861 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 8 Mar 2010 13:51:12 +0100 Subject: perf, x86: Don't reset the LBR as frequently If we reset the LBR on each first counter, simple counter rotation which first deschedules all counters and then reschedules the new ones will lead to LBR reset, even though we're still in the same task context. Reduce this by not flushing on the first counter but only flushing on different task contexts. Signed-off-by: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: paulus@samba.org Cc: eranian@google.com Cc: robert.richter@amd.com Cc: fweisbec@gmail.com LKML-Reference: Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event_intel_lbr.c b/arch/x86/kernel/cpu/perf_event_intel_lbr.c index 0145f99..f278136 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_lbr.c +++ b/arch/x86/kernel/cpu/perf_event_intel_lbr.c @@ -72,12 +72,11 @@ static void intel_pmu_lbr_enable(struct perf_event *event) WARN_ON_ONCE(cpuc->enabled); /* - * Reset the LBR stack if this is the first LBR user or - * we changed task context so as to avoid data leaks. + * Reset the LBR stack if we changed task context to + * avoid data leaks. */ - if (!cpuc->lbr_users || - (event->ctx->task && cpuc->lbr_context != event->ctx)) { + if (event->ctx->task && cpuc->lbr_context != event->ctx) { intel_pmu_lbr_reset(); cpuc->lbr_context = event->ctx; } @@ -93,7 +92,7 @@ static void intel_pmu_lbr_disable(struct perf_event *event) return; cpuc->lbr_users--; - BUG_ON(cpuc->lbr_users < 0); + WARN_ON_ONCE(cpuc->lbr_users < 0); if (cpuc->enabled && !cpuc->lbr_users) __intel_pmu_lbr_disable(); -- cgit v0.10.2 From 7645a24cbd01cbf4865d1273d5ddaa8d8c2ccb3a Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 8 Mar 2010 13:51:31 +0100 Subject: perf, x86: Remove checking_{wr,rd}msr() usage We don't need checking_{wr,rd}msr() calls, since we should know what cpu we're running on and not use blindly poke at msrs. Signed-off-by: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: paulus@samba.org Cc: eranian@google.com Cc: robert.richter@amd.com Cc: fweisbec@gmail.com LKML-Reference: Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 335ee1d..e24f637 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -29,6 +29,17 @@ #include #include +#if 0 +#undef wrmsrl +#define wrmsrl(msr, val) \ +do { \ + trace_printk("wrmsrl(%lx, %lx)\n", (unsigned long)(msr),\ + (unsigned long)(val)); \ + native_write_msr((msr), (u32)((u64)(val)), \ + (u32)((u64)(val) >> 32)); \ +} while (0) +#endif + /* * best effort, GUP based copy_from_user() that assumes IRQ or NMI context */ @@ -821,14 +832,15 @@ void hw_perf_enable(void) static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc) { - (void)checking_wrmsrl(hwc->config_base + hwc->idx, + wrmsrl(hwc->config_base + hwc->idx, hwc->config | ARCH_PERFMON_EVENTSEL_ENABLE); } static inline void x86_pmu_disable_event(struct perf_event *event) { struct hw_perf_event *hwc = &event->hw; - (void)checking_wrmsrl(hwc->config_base + hwc->idx, hwc->config); + + wrmsrl(hwc->config_base + hwc->idx, hwc->config); } static DEFINE_PER_CPU(u64 [X86_PMC_IDX_MAX], pmc_prev_left); @@ -843,7 +855,7 @@ x86_perf_event_set_period(struct perf_event *event) struct hw_perf_event *hwc = &event->hw; s64 left = atomic64_read(&hwc->period_left); s64 period = hwc->sample_period; - int err, ret = 0, idx = hwc->idx; + int ret = 0, idx = hwc->idx; if (idx == X86_PMC_IDX_FIXED_BTS) return 0; @@ -881,8 +893,8 @@ x86_perf_event_set_period(struct perf_event *event) */ atomic64_set(&hwc->prev_count, (u64)-left); - err = checking_wrmsrl(hwc->event_base + idx, - (u64)(-left) & x86_pmu.event_mask); + wrmsrl(hwc->event_base + idx, + (u64)(-left) & x86_pmu.event_mask); perf_event_update_userpage(event); @@ -987,7 +999,7 @@ void perf_event_print_debug(void) pr_info("CPU#%d: fixed: %016llx\n", cpu, fixed); pr_info("CPU#%d: pebs: %016llx\n", cpu, pebs); } - pr_info("CPU#%d: active: %016llx\n", cpu, *(u64 *)cpuc->active_mask); + pr_info("CPU#%d: active: %016llx\n", cpu, *(u64 *)cpuc->active_mask); for (idx = 0; idx < x86_pmu.num_events; idx++) { rdmsrl(x86_pmu.eventsel + idx, pmc_ctrl); diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index d3e2424..971dc6e 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -525,7 +525,7 @@ static void intel_pmu_disable_fixed(struct hw_perf_event *hwc) rdmsrl(hwc->config_base, ctrl_val); ctrl_val &= ~mask; - (void)checking_wrmsrl(hwc->config_base, ctrl_val); + wrmsrl(hwc->config_base, ctrl_val); } static void intel_pmu_disable_event(struct perf_event *event) @@ -553,7 +553,6 @@ static void intel_pmu_enable_fixed(struct hw_perf_event *hwc) { int idx = hwc->idx - X86_PMC_IDX_FIXED; u64 ctrl_val, bits, mask; - int err; /* * Enable IRQ generation (0x8), @@ -578,7 +577,7 @@ static void intel_pmu_enable_fixed(struct hw_perf_event *hwc) rdmsrl(hwc->config_base, ctrl_val); ctrl_val &= ~mask; ctrl_val |= bits; - err = checking_wrmsrl(hwc->config_base, ctrl_val); + wrmsrl(hwc->config_base, ctrl_val); } static void intel_pmu_enable_event(struct perf_event *event) -- cgit v0.10.2 From d80c7502ff63aa0d99d8c0c5803d28bbef67a74e Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 9 Mar 2010 11:41:02 +0100 Subject: perf, x86: Fixup the PEBS handler for Core2 cpus Pull the core handler in line with the nhm one, also make sure we always drain the buffer. Signed-off-by: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: paulus@samba.org Cc: eranian@google.com Cc: robert.richter@amd.com Cc: fweisbec@gmail.com LKML-Reference: Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c index 2423694..1bfd59b 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -472,20 +472,39 @@ static void intel_pmu_drain_pebs_core(struct pt_regs *iregs) struct pt_regs regs; int n; - if (!event || !ds || !x86_pmu.pebs) + if (!ds || !x86_pmu.pebs) return; at = (struct pebs_record_core *)(unsigned long)ds->pebs_buffer_base; top = (struct pebs_record_core *)(unsigned long)ds->pebs_index; - if (top <= at) + /* + * Whatever else happens, drain the thing + */ + ds->pebs_index = ds->pebs_buffer_base; + + if (!test_bit(0, cpuc->active_mask)) return; - ds->pebs_index = ds->pebs_buffer_base; + WARN_ON_ONCE(!event); + + if (!event->attr.precise) + return; + + n = top - at; + if (n <= 0) + return; if (!intel_pmu_save_and_restart(event)) return; + /* + * Should not happen, we program the threshold at 1 and do not + * set a reset value. + */ + WARN_ON_ONCE(n > 1); + at += n - 1; + perf_sample_data_init(&data, 0); data.period = event->hw.last_period; @@ -495,14 +514,6 @@ static void intel_pmu_drain_pebs_core(struct pt_regs *iregs) data.raw = &raw; } - n = top - at; - - /* - * Should not happen, we program the threshold at 1 and do not - * set a reset value. - */ - WARN_ON_ONCE(n > 1); - /* * We use the interrupt regs as a base because the PEBS record * does not contain a full regs set, specifically it seems to @@ -545,12 +556,11 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs) at = (struct pebs_record_nhm *)(unsigned long)ds->pebs_buffer_base; top = (struct pebs_record_nhm *)(unsigned long)ds->pebs_index; - if (top <= at) - return; - ds->pebs_index = ds->pebs_buffer_base; n = top - at; + if (n <= 0) + return; /* * Should not happen, we program the threshold at 1 and do not -- cgit v0.10.2 From 63fb3f9b2312e131be5a0a2dddb63f2fb123db9b Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 9 Mar 2010 11:51:02 +0100 Subject: perf, x86: Fix LBR read-out Don't decrement the TOS twice... Signed-off-by: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: paulus@samba.org Cc: eranian@google.com Cc: robert.richter@amd.com Cc: fweisbec@gmail.com LKML-Reference: Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event_intel_lbr.c b/arch/x86/kernel/cpu/perf_event_intel_lbr.c index f278136..df4c98e 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_lbr.c +++ b/arch/x86/kernel/cpu/perf_event_intel_lbr.c @@ -129,7 +129,7 @@ static void intel_pmu_lbr_read_32(struct cpu_hw_events *cpuc) u64 tos = intel_pmu_lbr_tos(); int i; - for (i = 0; i < x86_pmu.lbr_nr; i++, tos--) { + for (i = 0; i < x86_pmu.lbr_nr; i++) { unsigned long lbr_idx = (tos - i) & mask; union { struct { @@ -162,7 +162,7 @@ static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc) u64 tos = intel_pmu_lbr_tos(); int i; - for (i = 0; i < x86_pmu.lbr_nr; i++, tos--) { + for (i = 0; i < x86_pmu.lbr_nr; i++) { unsigned long lbr_idx = (tos - i) & mask; u64 from, to, flags = 0; -- cgit v0.10.2 From ba7e4d13fc7e25af1d167d40e6f028298dfc55ad Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 6 Jun 2009 13:58:12 +0200 Subject: perf, x86: Add INSTRUCTION_DECODER config flag The PEBS+LBR decoding magic needs the insn_get_length() infrastructure to be able to decode x86 instruction length. So split it out of KPROBES dependency and make it enabled when either KPROBES or PERF_EVENTS is enabled. Cc: Peter Zijlstra Cc: Masami Hiramatsu Cc: Frederic Weisbecker Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo LKML-Reference: Signed-off-by: Ingo Molnar diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index e984403..e1240f6 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -58,6 +58,9 @@ config X86 select HAVE_ARCH_KMEMCHECK select HAVE_USER_RETURN_NOTIFIER +config INSTRUCTION_DECODER + def_bool (KPROBES || PERF_EVENTS) + config OUTPUT_FORMAT string default "elf32-i386" if X86_32 diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 419386c..cbaf8f2 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -20,7 +20,7 @@ lib-y := delay.o lib-y += thunk_$(BITS).o lib-y += usercopy_$(BITS).o getuser.o putuser.o lib-y += memcpy_$(BITS).o -lib-$(CONFIG_KPROBES) += insn.o inat.o +lib-$(CONFIG_INSTRUCTION_DECODER) += insn.o inat.o obj-y += msr.o msr-reg.o msr-reg-export.o -- cgit v0.10.2 From caa0142d84ceb0fc83e28f0475d0a7316cb6df77 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 6 Jun 2009 13:58:12 +0200 Subject: perf, x86: Fix the !CONFIG_CPU_SUP_INTEL build Fix typo. But the modularization here is ugly and should be improved. Cc: Peter Zijlstra Cc: Frederic Weisbecker Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo LKML-Reference: Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c index 1bfd59b..c59678a 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -661,7 +661,7 @@ static void intel_ds_init(void) #else /* CONFIG_CPU_SUP_INTEL */ -static int reseve_ds_buffers(void) +static int reserve_ds_buffers(void) { return 0; } -- cgit v0.10.2 From 938179b4f8cf8a4f11234ebf2dff2eb48400acfe Mon Sep 17 00:00:00 2001 From: Dimitri Sivanich Date: Fri, 5 Mar 2010 11:42:03 -0600 Subject: x86: Improve Intel microcode loader performance We've noticed that on large SGI UV system configurations, running microcode.ctl can take very long periods of time. This is due to the large number of vmalloc/vfree calls made by the Intel generic_load_microcode() logic. By reusing allocated space, the following patch reduces the time to run microcode.ctl on a 1024 cpu system from approximately 80 seconds down to 1 or 2 seconds. Signed-off-by: Dimitri Sivanich Acked-by: Dmitry Adamushko Cc: Avi Kivity Cc: Bill Davidsen LKML-Reference: <20100305174203.GA19638@sgi.com> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c index 85a343e..3561702 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/microcode_intel.c @@ -343,10 +343,11 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size, int (*get_ucode_data)(void *, const void *, size_t)) { struct ucode_cpu_info *uci = ucode_cpu_info + cpu; - u8 *ucode_ptr = data, *new_mc = NULL, *mc; + u8 *ucode_ptr = data, *new_mc = NULL, *mc = NULL; int new_rev = uci->cpu_sig.rev; unsigned int leftover = size; enum ucode_state state = UCODE_OK; + unsigned int curr_mc_size = 0; while (leftover) { struct microcode_header_intel mc_header; @@ -361,9 +362,15 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size, break; } - mc = vmalloc(mc_size); - if (!mc) - break; + /* For performance reasons, reuse mc area when possible */ + if (!mc || mc_size > curr_mc_size) { + if (mc) + vfree(mc); + mc = vmalloc(mc_size); + if (!mc) + break; + curr_mc_size = mc_size; + } if (get_ucode_data(mc, ucode_ptr, mc_size) || microcode_sanity_check(mc) < 0) { @@ -376,13 +383,16 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size, vfree(new_mc); new_rev = mc_header.rev; new_mc = mc; - } else - vfree(mc); + mc = NULL; /* trigger new vmalloc */ + } ucode_ptr += mc_size; leftover -= mc_size; } + if (mc) + vfree(mc); + if (leftover) { if (new_mc) vfree(new_mc); -- cgit v0.10.2 From 6f4edd69e40aba4f45bf9558c1e9a950d79ab4e4 Mon Sep 17 00:00:00 2001 From: Jack Steiner Date: Wed, 10 Mar 2010 14:44:58 -0600 Subject: x86, UV: Clean up UV headers for MMR definitions Update UV mmr definitions header file. Eliminate definitions no longer needed. Move 2 definitions from tlb_uv.c into the header file where they belong. Signed-off-by: Jack Steiner LKML-Reference: <20100310204458.GA28835@sgi.com> Signed-off-by: Ingo Molnar diff --git a/arch/x86/include/asm/uv/uv_mmrs.h b/arch/x86/include/asm/uv/uv_mmrs.h index 2cae46c..b2f2d2e 100644 --- a/arch/x86/include/asm/uv/uv_mmrs.h +++ b/arch/x86/include/asm/uv/uv_mmrs.h @@ -1,4 +1,3 @@ - /* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -15,13 +14,25 @@ #define UV_MMR_ENABLE (1UL << 63) /* ========================================================================= */ +/* UVH_BAU_DATA_BROADCAST */ +/* ========================================================================= */ +#define UVH_BAU_DATA_BROADCAST 0x61688UL +#define UVH_BAU_DATA_BROADCAST_32 0x0440 + +#define UVH_BAU_DATA_BROADCAST_ENABLE_SHFT 0 +#define UVH_BAU_DATA_BROADCAST_ENABLE_MASK 0x0000000000000001UL + +union uvh_bau_data_broadcast_u { + unsigned long v; + struct uvh_bau_data_broadcast_s { + unsigned long enable : 1; /* RW */ + unsigned long rsvd_1_63: 63; /* */ + } s; +}; + +/* ========================================================================= */ /* UVH_BAU_DATA_CONFIG */ /* ========================================================================= */ -#define UVH_LB_BAU_MISC_CONTROL 0x320170UL -#define UV_ENABLE_INTD_SOFT_ACK_MODE_SHIFT 15 -#define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHIFT 16 -#define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD 0x000000000bUL -/* 1011 timebase 7 (168millisec) * 3 ticks -> 500ms */ #define UVH_BAU_DATA_CONFIG 0x61680UL #define UVH_BAU_DATA_CONFIG_32 0x0438 @@ -604,6 +615,68 @@ union uvh_lb_bau_intd_software_acknowledge_u { #define UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS_32 0x0a70 /* ========================================================================= */ +/* UVH_LB_BAU_MISC_CONTROL */ +/* ========================================================================= */ +#define UVH_LB_BAU_MISC_CONTROL 0x320170UL +#define UVH_LB_BAU_MISC_CONTROL_32 0x00a10 + +#define UVH_LB_BAU_MISC_CONTROL_REJECTION_DELAY_SHFT 0 +#define UVH_LB_BAU_MISC_CONTROL_REJECTION_DELAY_MASK 0x00000000000000ffUL +#define UVH_LB_BAU_MISC_CONTROL_APIC_MODE_SHFT 8 +#define UVH_LB_BAU_MISC_CONTROL_APIC_MODE_MASK 0x0000000000000100UL +#define UVH_LB_BAU_MISC_CONTROL_FORCE_BROADCAST_SHFT 9 +#define UVH_LB_BAU_MISC_CONTROL_FORCE_BROADCAST_MASK 0x0000000000000200UL +#define UVH_LB_BAU_MISC_CONTROL_FORCE_LOCK_NOP_SHFT 10 +#define UVH_LB_BAU_MISC_CONTROL_FORCE_LOCK_NOP_MASK 0x0000000000000400UL +#define UVH_LB_BAU_MISC_CONTROL_CSI_AGENT_PRESENCE_VECTOR_SHFT 11 +#define UVH_LB_BAU_MISC_CONTROL_CSI_AGENT_PRESENCE_VECTOR_MASK 0x0000000000003800UL +#define UVH_LB_BAU_MISC_CONTROL_DESCRIPTOR_FETCH_MODE_SHFT 14 +#define UVH_LB_BAU_MISC_CONTROL_DESCRIPTOR_FETCH_MODE_MASK 0x0000000000004000UL +#define UVH_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_SHFT 15 +#define UVH_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_MASK 0x0000000000008000UL +#define UVH_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHFT 16 +#define UVH_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_MASK 0x00000000000f0000UL +#define UVH_LB_BAU_MISC_CONTROL_ENABLE_DUAL_MAPPING_MODE_SHFT 20 +#define UVH_LB_BAU_MISC_CONTROL_ENABLE_DUAL_MAPPING_MODE_MASK 0x0000000000100000UL +#define UVH_LB_BAU_MISC_CONTROL_VGA_IO_PORT_DECODE_ENABLE_SHFT 21 +#define UVH_LB_BAU_MISC_CONTROL_VGA_IO_PORT_DECODE_ENABLE_MASK 0x0000000000200000UL +#define UVH_LB_BAU_MISC_CONTROL_VGA_IO_PORT_16_BIT_DECODE_SHFT 22 +#define UVH_LB_BAU_MISC_CONTROL_VGA_IO_PORT_16_BIT_DECODE_MASK 0x0000000000400000UL +#define UVH_LB_BAU_MISC_CONTROL_SUPPRESS_DEST_REGISTRATION_SHFT 23 +#define UVH_LB_BAU_MISC_CONTROL_SUPPRESS_DEST_REGISTRATION_MASK 0x0000000000800000UL +#define UVH_LB_BAU_MISC_CONTROL_PROGRAMMED_INITIAL_PRIORITY_SHFT 24 +#define UVH_LB_BAU_MISC_CONTROL_PROGRAMMED_INITIAL_PRIORITY_MASK 0x0000000007000000UL +#define UVH_LB_BAU_MISC_CONTROL_USE_INCOMING_PRIORITY_SHFT 27 +#define UVH_LB_BAU_MISC_CONTROL_USE_INCOMING_PRIORITY_MASK 0x0000000008000000UL +#define UVH_LB_BAU_MISC_CONTROL_ENABLE_PROGRAMMED_INITIAL_PRIORITY_SHFT 28 +#define UVH_LB_BAU_MISC_CONTROL_ENABLE_PROGRAMMED_INITIAL_PRIORITY_MASK 0x0000000010000000UL +#define UVH_LB_BAU_MISC_CONTROL_FUN_SHFT 48 +#define UVH_LB_BAU_MISC_CONTROL_FUN_MASK 0xffff000000000000UL + +union uvh_lb_bau_misc_control_u { + unsigned long v; + struct uvh_lb_bau_misc_control_s { + unsigned long rejection_delay : 8; /* RW */ + unsigned long apic_mode : 1; /* RW */ + unsigned long force_broadcast : 1; /* RW */ + unsigned long force_lock_nop : 1; /* RW */ + unsigned long csi_agent_presence_vector : 3; /* RW */ + unsigned long descriptor_fetch_mode : 1; /* RW */ + unsigned long enable_intd_soft_ack_mode : 1; /* RW */ + unsigned long intd_soft_ack_timeout_period : 4; /* RW */ + unsigned long enable_dual_mapping_mode : 1; /* RW */ + unsigned long vga_io_port_decode_enable : 1; /* RW */ + unsigned long vga_io_port_16_bit_decode : 1; /* RW */ + unsigned long suppress_dest_registration : 1; /* RW */ + unsigned long programmed_initial_priority : 3; /* RW */ + unsigned long use_incoming_priority : 1; /* RW */ + unsigned long enable_programmed_initial_priority : 1; /* RW */ + unsigned long rsvd_29_47 : 19; /* */ + unsigned long fun : 16; /* RW */ + } s; +}; + +/* ========================================================================= */ /* UVH_LB_BAU_SB_ACTIVATION_CONTROL */ /* ========================================================================= */ #define UVH_LB_BAU_SB_ACTIVATION_CONTROL 0x320020UL @@ -681,334 +754,6 @@ union uvh_lb_bau_sb_descriptor_base_u { }; /* ========================================================================= */ -/* UVH_LB_MCAST_AOERR0_RPT_ENABLE */ -/* ========================================================================= */ -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE 0x50b20UL - -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MCAST_OBESE_MSG_SHFT 0 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MCAST_OBESE_MSG_MASK 0x0000000000000001UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MCAST_DATA_SB_ERR_SHFT 1 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MCAST_DATA_SB_ERR_MASK 0x0000000000000002UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MCAST_NACK_BUFF_PARITY_SHFT 2 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MCAST_NACK_BUFF_PARITY_MASK 0x0000000000000004UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MCAST_TIMEOUT_SHFT 3 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MCAST_TIMEOUT_MASK 0x0000000000000008UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MCAST_INACTIVE_REPLY_SHFT 4 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MCAST_INACTIVE_REPLY_MASK 0x0000000000000010UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MCAST_UPGRADE_ERROR_SHFT 5 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MCAST_UPGRADE_ERROR_MASK 0x0000000000000020UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MCAST_REG_COUNT_UNDERFLOW_SHFT 6 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MCAST_REG_COUNT_UNDERFLOW_MASK 0x0000000000000040UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MCAST_REP_OBESE_MSG_SHFT 7 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MCAST_REP_OBESE_MSG_MASK 0x0000000000000080UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_UCACHE_REQ_RUNT_MSG_SHFT 8 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_UCACHE_REQ_RUNT_MSG_MASK 0x0000000000000100UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_UCACHE_REQ_OBESE_MSG_SHFT 9 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_UCACHE_REQ_OBESE_MSG_MASK 0x0000000000000200UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_UCACHE_REQ_DATA_SB_ERR_SHFT 10 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_UCACHE_REQ_DATA_SB_ERR_MASK 0x0000000000000400UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_UCACHE_REP_RUNT_MSG_SHFT 11 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_UCACHE_REP_RUNT_MSG_MASK 0x0000000000000800UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_UCACHE_REP_OBESE_MSG_SHFT 12 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_UCACHE_REP_OBESE_MSG_MASK 0x0000000000001000UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_UCACHE_REP_DATA_SB_ERR_SHFT 13 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_UCACHE_REP_DATA_SB_ERR_MASK 0x0000000000002000UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_UCACHE_REP_COMMAND_ERR_SHFT 14 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_UCACHE_REP_COMMAND_ERR_MASK 0x0000000000004000UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_UCACHE_PEND_TIMEOUT_SHFT 15 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_UCACHE_PEND_TIMEOUT_MASK 0x0000000000008000UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_REQ_RUNT_MSG_SHFT 16 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_REQ_RUNT_MSG_MASK 0x0000000000010000UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_REQ_OBESE_MSG_SHFT 17 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_REQ_OBESE_MSG_MASK 0x0000000000020000UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_REQ_DATA_SB_ERR_SHFT 18 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_REQ_DATA_SB_ERR_MASK 0x0000000000040000UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_REP_RUNT_MSG_SHFT 19 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_REP_RUNT_MSG_MASK 0x0000000000080000UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_REP_OBESE_MSG_SHFT 20 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_REP_OBESE_MSG_MASK 0x0000000000100000UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_REP_DATA_SB_ERR_SHFT 21 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_REP_DATA_SB_ERR_MASK 0x0000000000200000UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_AMO_TIMEOUT_SHFT 22 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_AMO_TIMEOUT_MASK 0x0000000000400000UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_PUT_TIMEOUT_SHFT 23 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_PUT_TIMEOUT_MASK 0x0000000000800000UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_SPURIOUS_EVENT_SHFT 24 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_MACC_SPURIOUS_EVENT_MASK 0x0000000001000000UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_IOH_DESTINATION_TABLE_PARITY_SHFT 25 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_IOH_DESTINATION_TABLE_PARITY_MASK 0x0000000002000000UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_GET_HAD_ERROR_REPLY_SHFT 26 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_GET_HAD_ERROR_REPLY_MASK 0x0000000004000000UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_GET_TIMEOUT_SHFT 27 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_GET_TIMEOUT_MASK 0x0000000008000000UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_LOCK_MANAGER_HAD_ERROR_REPLY_SHFT 28 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_LOCK_MANAGER_HAD_ERROR_REPLY_MASK 0x0000000010000000UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_PUT_HAD_ERROR_REPLY_SHFT 29 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_PUT_HAD_ERROR_REPLY_MASK 0x0000000020000000UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_PUT_TIMEOUT_SHFT 30 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_PUT_TIMEOUT_MASK 0x0000000040000000UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_SB_ACTIVATION_OVERRUN_SHFT 31 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_SB_ACTIVATION_OVERRUN_MASK 0x0000000080000000UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_COMPLETED_GB_ACTIVATION_HAD_ERROR_REPLY_SHFT 32 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_COMPLETED_GB_ACTIVATION_HAD_ERROR_REPLY_MASK 0x0000000100000000UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_COMPLETED_GB_ACTIVATION_TIMEOUT_SHFT 33 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_COMPLETED_GB_ACTIVATION_TIMEOUT_MASK 0x0000000200000000UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_DESCRIPTOR_BUFFER_0_PARITY_SHFT 34 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_DESCRIPTOR_BUFFER_0_PARITY_MASK 0x0000000400000000UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_DESCRIPTOR_BUFFER_1_PARITY_SHFT 35 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_DESCRIPTOR_BUFFER_1_PARITY_MASK 0x0000000800000000UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_SOCKET_DESTINATION_TABLE_PARITY_SHFT 36 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_SOCKET_DESTINATION_TABLE_PARITY_MASK 0x0000001000000000UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_BAU_REPLY_PAYLOAD_CORRUPTION_SHFT 37 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_BAU_REPLY_PAYLOAD_CORRUPTION_MASK 0x0000002000000000UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_IO_PORT_DESTINATION_TABLE_PARITY_SHFT 38 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_IO_PORT_DESTINATION_TABLE_PARITY_MASK 0x0000004000000000UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_INTD_SOFT_ACK_TIMEOUT_SHFT 39 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_INTD_SOFT_ACK_TIMEOUT_MASK 0x0000008000000000UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_INT_REP_OBESE_MSG_SHFT 40 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_INT_REP_OBESE_MSG_MASK 0x0000010000000000UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_INT_REP_COMMAND_ERR_SHFT 41 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_INT_REP_COMMAND_ERR_MASK 0x0000020000000000UL -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_INT_TIMEOUT_SHFT 42 -#define UVH_LB_MCAST_AOERR0_RPT_ENABLE_INT_TIMEOUT_MASK 0x0000040000000000UL - -union uvh_lb_mcast_aoerr0_rpt_enable_u { - unsigned long v; - struct uvh_lb_mcast_aoerr0_rpt_enable_s { - unsigned long mcast_obese_msg : 1; /* RW */ - unsigned long mcast_data_sb_err : 1; /* RW */ - unsigned long mcast_nack_buff_parity : 1; /* RW */ - unsigned long mcast_timeout : 1; /* RW */ - unsigned long mcast_inactive_reply : 1; /* RW */ - unsigned long mcast_upgrade_error : 1; /* RW */ - unsigned long mcast_reg_count_underflow : 1; /* RW */ - unsigned long mcast_rep_obese_msg : 1; /* RW */ - unsigned long ucache_req_runt_msg : 1; /* RW */ - unsigned long ucache_req_obese_msg : 1; /* RW */ - unsigned long ucache_req_data_sb_err : 1; /* RW */ - unsigned long ucache_rep_runt_msg : 1; /* RW */ - unsigned long ucache_rep_obese_msg : 1; /* RW */ - unsigned long ucache_rep_data_sb_err : 1; /* RW */ - unsigned long ucache_rep_command_err : 1; /* RW */ - unsigned long ucache_pend_timeout : 1; /* RW */ - unsigned long macc_req_runt_msg : 1; /* RW */ - unsigned long macc_req_obese_msg : 1; /* RW */ - unsigned long macc_req_data_sb_err : 1; /* RW */ - unsigned long macc_rep_runt_msg : 1; /* RW */ - unsigned long macc_rep_obese_msg : 1; /* RW */ - unsigned long macc_rep_data_sb_err : 1; /* RW */ - unsigned long macc_amo_timeout : 1; /* RW */ - unsigned long macc_put_timeout : 1; /* RW */ - unsigned long macc_spurious_event : 1; /* RW */ - unsigned long ioh_destination_table_parity : 1; /* RW */ - unsigned long get_had_error_reply : 1; /* RW */ - unsigned long get_timeout : 1; /* RW */ - unsigned long lock_manager_had_error_reply : 1; /* RW */ - unsigned long put_had_error_reply : 1; /* RW */ - unsigned long put_timeout : 1; /* RW */ - unsigned long sb_activation_overrun : 1; /* RW */ - unsigned long completed_gb_activation_had_error_reply : 1; /* RW */ - unsigned long completed_gb_activation_timeout : 1; /* RW */ - unsigned long descriptor_buffer_0_parity : 1; /* RW */ - unsigned long descriptor_buffer_1_parity : 1; /* RW */ - unsigned long socket_destination_table_parity : 1; /* RW */ - unsigned long bau_reply_payload_corruption : 1; /* RW */ - unsigned long io_port_destination_table_parity : 1; /* RW */ - unsigned long intd_soft_ack_timeout : 1; /* RW */ - unsigned long int_rep_obese_msg : 1; /* RW */ - unsigned long int_rep_command_err : 1; /* RW */ - unsigned long int_timeout : 1; /* RW */ - unsigned long rsvd_43_63 : 21; /* */ - } s; -}; - -/* ========================================================================= */ -/* UVH_LOCAL_INT0_CONFIG */ -/* ========================================================================= */ -#define UVH_LOCAL_INT0_CONFIG 0x61000UL - -#define UVH_LOCAL_INT0_CONFIG_VECTOR_SHFT 0 -#define UVH_LOCAL_INT0_CONFIG_VECTOR_MASK 0x00000000000000ffUL -#define UVH_LOCAL_INT0_CONFIG_DM_SHFT 8 -#define UVH_LOCAL_INT0_CONFIG_DM_MASK 0x0000000000000700UL -#define UVH_LOCAL_INT0_CONFIG_DESTMODE_SHFT 11 -#define UVH_LOCAL_INT0_CONFIG_DESTMODE_MASK 0x0000000000000800UL -#define UVH_LOCAL_INT0_CONFIG_STATUS_SHFT 12 -#define UVH_LOCAL_INT0_CONFIG_STATUS_MASK 0x0000000000001000UL -#define UVH_LOCAL_INT0_CONFIG_P_SHFT 13 -#define UVH_LOCAL_INT0_CONFIG_P_MASK 0x0000000000002000UL -#define UVH_LOCAL_INT0_CONFIG_T_SHFT 15 -#define UVH_LOCAL_INT0_CONFIG_T_MASK 0x0000000000008000UL -#define UVH_LOCAL_INT0_CONFIG_M_SHFT 16 -#define UVH_LOCAL_INT0_CONFIG_M_MASK 0x0000000000010000UL -#define UVH_LOCAL_INT0_CONFIG_APIC_ID_SHFT 32 -#define UVH_LOCAL_INT0_CONFIG_APIC_ID_MASK 0xffffffff00000000UL - -union uvh_local_int0_config_u { - unsigned long v; - struct uvh_local_int0_config_s { - unsigned long vector_ : 8; /* RW */ - unsigned long dm : 3; /* RW */ - unsigned long destmode : 1; /* RW */ - unsigned long status : 1; /* RO */ - unsigned long p : 1; /* RO */ - unsigned long rsvd_14 : 1; /* */ - unsigned long t : 1; /* RO */ - unsigned long m : 1; /* RW */ - unsigned long rsvd_17_31: 15; /* */ - unsigned long apic_id : 32; /* RW */ - } s; -}; - -/* ========================================================================= */ -/* UVH_LOCAL_INT0_ENABLE */ -/* ========================================================================= */ -#define UVH_LOCAL_INT0_ENABLE 0x65000UL - -#define UVH_LOCAL_INT0_ENABLE_LB_HCERR_SHFT 0 -#define UVH_LOCAL_INT0_ENABLE_LB_HCERR_MASK 0x0000000000000001UL -#define UVH_LOCAL_INT0_ENABLE_GR0_HCERR_SHFT 1 -#define UVH_LOCAL_INT0_ENABLE_GR0_HCERR_MASK 0x0000000000000002UL -#define UVH_LOCAL_INT0_ENABLE_GR1_HCERR_SHFT 2 -#define UVH_LOCAL_INT0_ENABLE_GR1_HCERR_MASK 0x0000000000000004UL -#define UVH_LOCAL_INT0_ENABLE_LH_HCERR_SHFT 3 -#define UVH_LOCAL_INT0_ENABLE_LH_HCERR_MASK 0x0000000000000008UL -#define UVH_LOCAL_INT0_ENABLE_RH_HCERR_SHFT 4 -#define UVH_LOCAL_INT0_ENABLE_RH_HCERR_MASK 0x0000000000000010UL -#define UVH_LOCAL_INT0_ENABLE_XN_HCERR_SHFT 5 -#define UVH_LOCAL_INT0_ENABLE_XN_HCERR_MASK 0x0000000000000020UL -#define UVH_LOCAL_INT0_ENABLE_SI_HCERR_SHFT 6 -#define UVH_LOCAL_INT0_ENABLE_SI_HCERR_MASK 0x0000000000000040UL -#define UVH_LOCAL_INT0_ENABLE_LB_AOERR0_SHFT 7 -#define UVH_LOCAL_INT0_ENABLE_LB_AOERR0_MASK 0x0000000000000080UL -#define UVH_LOCAL_INT0_ENABLE_GR0_AOERR0_SHFT 8 -#define UVH_LOCAL_INT0_ENABLE_GR0_AOERR0_MASK 0x0000000000000100UL -#define UVH_LOCAL_INT0_ENABLE_GR1_AOERR0_SHFT 9 -#define UVH_LOCAL_INT0_ENABLE_GR1_AOERR0_MASK 0x0000000000000200UL -#define UVH_LOCAL_INT0_ENABLE_LH_AOERR0_SHFT 10 -#define UVH_LOCAL_INT0_ENABLE_LH_AOERR0_MASK 0x0000000000000400UL -#define UVH_LOCAL_INT0_ENABLE_RH_AOERR0_SHFT 11 -#define UVH_LOCAL_INT0_ENABLE_RH_AOERR0_MASK 0x0000000000000800UL -#define UVH_LOCAL_INT0_ENABLE_XN_AOERR0_SHFT 12 -#define UVH_LOCAL_INT0_ENABLE_XN_AOERR0_MASK 0x0000000000001000UL -#define UVH_LOCAL_INT0_ENABLE_SI_AOERR0_SHFT 13 -#define UVH_LOCAL_INT0_ENABLE_SI_AOERR0_MASK 0x0000000000002000UL -#define UVH_LOCAL_INT0_ENABLE_LB_AOERR1_SHFT 14 -#define UVH_LOCAL_INT0_ENABLE_LB_AOERR1_MASK 0x0000000000004000UL -#define UVH_LOCAL_INT0_ENABLE_GR0_AOERR1_SHFT 15 -#define UVH_LOCAL_INT0_ENABLE_GR0_AOERR1_MASK 0x0000000000008000UL -#define UVH_LOCAL_INT0_ENABLE_GR1_AOERR1_SHFT 16 -#define UVH_LOCAL_INT0_ENABLE_GR1_AOERR1_MASK 0x0000000000010000UL -#define UVH_LOCAL_INT0_ENABLE_LH_AOERR1_SHFT 17 -#define UVH_LOCAL_INT0_ENABLE_LH_AOERR1_MASK 0x0000000000020000UL -#define UVH_LOCAL_INT0_ENABLE_RH_AOERR1_SHFT 18 -#define UVH_LOCAL_INT0_ENABLE_RH_AOERR1_MASK 0x0000000000040000UL -#define UVH_LOCAL_INT0_ENABLE_XN_AOERR1_SHFT 19 -#define UVH_LOCAL_INT0_ENABLE_XN_AOERR1_MASK 0x0000000000080000UL -#define UVH_LOCAL_INT0_ENABLE_SI_AOERR1_SHFT 20 -#define UVH_LOCAL_INT0_ENABLE_SI_AOERR1_MASK 0x0000000000100000UL -#define UVH_LOCAL_INT0_ENABLE_RH_VPI_INT_SHFT 21 -#define UVH_LOCAL_INT0_ENABLE_RH_VPI_INT_MASK 0x0000000000200000UL -#define UVH_LOCAL_INT0_ENABLE_SYSTEM_SHUTDOWN_INT_SHFT 22 -#define UVH_LOCAL_INT0_ENABLE_SYSTEM_SHUTDOWN_INT_MASK 0x0000000000400000UL -#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_0_SHFT 23 -#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_0_MASK 0x0000000000800000UL -#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_1_SHFT 24 -#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_1_MASK 0x0000000001000000UL -#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_2_SHFT 25 -#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_2_MASK 0x0000000002000000UL -#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_3_SHFT 26 -#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_3_MASK 0x0000000004000000UL -#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_4_SHFT 27 -#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_4_MASK 0x0000000008000000UL -#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_5_SHFT 28 -#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_5_MASK 0x0000000010000000UL -#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_6_SHFT 29 -#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_6_MASK 0x0000000020000000UL -#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_7_SHFT 30 -#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_7_MASK 0x0000000040000000UL -#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_8_SHFT 31 -#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_8_MASK 0x0000000080000000UL -#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_9_SHFT 32 -#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_9_MASK 0x0000000100000000UL -#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_10_SHFT 33 -#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_10_MASK 0x0000000200000000UL -#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_11_SHFT 34 -#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_11_MASK 0x0000000400000000UL -#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_12_SHFT 35 -#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_12_MASK 0x0000000800000000UL -#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_13_SHFT 36 -#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_13_MASK 0x0000001000000000UL -#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_14_SHFT 37 -#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_14_MASK 0x0000002000000000UL -#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_15_SHFT 38 -#define UVH_LOCAL_INT0_ENABLE_LB_IRQ_INT_15_MASK 0x0000004000000000UL -#define UVH_LOCAL_INT0_ENABLE_L1_NMI_INT_SHFT 39 -#define UVH_LOCAL_INT0_ENABLE_L1_NMI_INT_MASK 0x0000008000000000UL -#define UVH_LOCAL_INT0_ENABLE_STOP_CLOCK_SHFT 40 -#define UVH_LOCAL_INT0_ENABLE_STOP_CLOCK_MASK 0x0000010000000000UL -#define UVH_LOCAL_INT0_ENABLE_ASIC_TO_L1_SHFT 41 -#define UVH_LOCAL_INT0_ENABLE_ASIC_TO_L1_MASK 0x0000020000000000UL -#define UVH_LOCAL_INT0_ENABLE_L1_TO_ASIC_SHFT 42 -#define UVH_LOCAL_INT0_ENABLE_L1_TO_ASIC_MASK 0x0000040000000000UL -#define UVH_LOCAL_INT0_ENABLE_LTC_INT_SHFT 43 -#define UVH_LOCAL_INT0_ENABLE_LTC_INT_MASK 0x0000080000000000UL -#define UVH_LOCAL_INT0_ENABLE_LA_SEQ_TRIGGER_SHFT 44 -#define UVH_LOCAL_INT0_ENABLE_LA_SEQ_TRIGGER_MASK 0x0000100000000000UL - -union uvh_local_int0_enable_u { - unsigned long v; - struct uvh_local_int0_enable_s { - unsigned long lb_hcerr : 1; /* RW */ - unsigned long gr0_hcerr : 1; /* RW */ - unsigned long gr1_hcerr : 1; /* RW */ - unsigned long lh_hcerr : 1; /* RW */ - unsigned long rh_hcerr : 1; /* RW */ - unsigned long xn_hcerr : 1; /* RW */ - unsigned long si_hcerr : 1; /* RW */ - unsigned long lb_aoerr0 : 1; /* RW */ - unsigned long gr0_aoerr0 : 1; /* RW */ - unsigned long gr1_aoerr0 : 1; /* RW */ - unsigned long lh_aoerr0 : 1; /* RW */ - unsigned long rh_aoerr0 : 1; /* RW */ - unsigned long xn_aoerr0 : 1; /* RW */ - unsigned long si_aoerr0 : 1; /* RW */ - unsigned long lb_aoerr1 : 1; /* RW */ - unsigned long gr0_aoerr1 : 1; /* RW */ - unsigned long gr1_aoerr1 : 1; /* RW */ - unsigned long lh_aoerr1 : 1; /* RW */ - unsigned long rh_aoerr1 : 1; /* RW */ - unsigned long xn_aoerr1 : 1; /* RW */ - unsigned long si_aoerr1 : 1; /* RW */ - unsigned long rh_vpi_int : 1; /* RW */ - unsigned long system_shutdown_int : 1; /* RW */ - unsigned long lb_irq_int_0 : 1; /* RW */ - unsigned long lb_irq_int_1 : 1; /* RW */ - unsigned long lb_irq_int_2 : 1; /* RW */ - unsigned long lb_irq_int_3 : 1; /* RW */ - unsigned long lb_irq_int_4 : 1; /* RW */ - unsigned long lb_irq_int_5 : 1; /* RW */ - unsigned long lb_irq_int_6 : 1; /* RW */ - unsigned long lb_irq_int_7 : 1; /* RW */ - unsigned long lb_irq_int_8 : 1; /* RW */ - unsigned long lb_irq_int_9 : 1; /* RW */ - unsigned long lb_irq_int_10 : 1; /* RW */ - unsigned long lb_irq_int_11 : 1; /* RW */ - unsigned long lb_irq_int_12 : 1; /* RW */ - unsigned long lb_irq_int_13 : 1; /* RW */ - unsigned long lb_irq_int_14 : 1; /* RW */ - unsigned long lb_irq_int_15 : 1; /* RW */ - unsigned long l1_nmi_int : 1; /* RW */ - unsigned long stop_clock : 1; /* RW */ - unsigned long asic_to_l1 : 1; /* RW */ - unsigned long l1_to_asic : 1; /* RW */ - unsigned long ltc_int : 1; /* RW */ - unsigned long la_seq_trigger : 1; /* RW */ - unsigned long rsvd_45_63 : 19; /* */ - } s; -}; - -/* ========================================================================= */ /* UVH_NODE_ID */ /* ========================================================================= */ #define UVH_NODE_ID 0x0UL @@ -1112,26 +857,6 @@ union uvh_rh_gam_alias210_redirect_config_2_mmr_u { }; /* ========================================================================= */ -/* UVH_RH_GAM_CFG_OVERLAY_CONFIG_MMR */ -/* ========================================================================= */ -#define UVH_RH_GAM_CFG_OVERLAY_CONFIG_MMR 0x1600020UL - -#define UVH_RH_GAM_CFG_OVERLAY_CONFIG_MMR_BASE_SHFT 26 -#define UVH_RH_GAM_CFG_OVERLAY_CONFIG_MMR_BASE_MASK 0x00003ffffc000000UL -#define UVH_RH_GAM_CFG_OVERLAY_CONFIG_MMR_ENABLE_SHFT 63 -#define UVH_RH_GAM_CFG_OVERLAY_CONFIG_MMR_ENABLE_MASK 0x8000000000000000UL - -union uvh_rh_gam_cfg_overlay_config_mmr_u { - unsigned long v; - struct uvh_rh_gam_cfg_overlay_config_mmr_s { - unsigned long rsvd_0_25: 26; /* */ - unsigned long base : 20; /* RW */ - unsigned long rsvd_46_62: 17; /* */ - unsigned long enable : 1; /* RW */ - } s; -}; - -/* ========================================================================= */ /* UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR */ /* ========================================================================= */ #define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR 0x1600010UL @@ -1263,101 +988,6 @@ union uvh_rtc1_int_config_u { }; /* ========================================================================= */ -/* UVH_RTC2_INT_CONFIG */ -/* ========================================================================= */ -#define UVH_RTC2_INT_CONFIG 0x61600UL - -#define UVH_RTC2_INT_CONFIG_VECTOR_SHFT 0 -#define UVH_RTC2_INT_CONFIG_VECTOR_MASK 0x00000000000000ffUL -#define UVH_RTC2_INT_CONFIG_DM_SHFT 8 -#define UVH_RTC2_INT_CONFIG_DM_MASK 0x0000000000000700UL -#define UVH_RTC2_INT_CONFIG_DESTMODE_SHFT 11 -#define UVH_RTC2_INT_CONFIG_DESTMODE_MASK 0x0000000000000800UL -#define UVH_RTC2_INT_CONFIG_STATUS_SHFT 12 -#define UVH_RTC2_INT_CONFIG_STATUS_MASK 0x0000000000001000UL -#define UVH_RTC2_INT_CONFIG_P_SHFT 13 -#define UVH_RTC2_INT_CONFIG_P_MASK 0x0000000000002000UL -#define UVH_RTC2_INT_CONFIG_T_SHFT 15 -#define UVH_RTC2_INT_CONFIG_T_MASK 0x0000000000008000UL -#define UVH_RTC2_INT_CONFIG_M_SHFT 16 -#define UVH_RTC2_INT_CONFIG_M_MASK 0x0000000000010000UL -#define UVH_RTC2_INT_CONFIG_APIC_ID_SHFT 32 -#define UVH_RTC2_INT_CONFIG_APIC_ID_MASK 0xffffffff00000000UL - -union uvh_rtc2_int_config_u { - unsigned long v; - struct uvh_rtc2_int_config_s { - unsigned long vector_ : 8; /* RW */ - unsigned long dm : 3; /* RW */ - unsigned long destmode : 1; /* RW */ - unsigned long status : 1; /* RO */ - unsigned long p : 1; /* RO */ - unsigned long rsvd_14 : 1; /* */ - unsigned long t : 1; /* RO */ - unsigned long m : 1; /* RW */ - unsigned long rsvd_17_31: 15; /* */ - unsigned long apic_id : 32; /* RW */ - } s; -}; - -/* ========================================================================= */ -/* UVH_RTC3_INT_CONFIG */ -/* ========================================================================= */ -#define UVH_RTC3_INT_CONFIG 0x61640UL - -#define UVH_RTC3_INT_CONFIG_VECTOR_SHFT 0 -#define UVH_RTC3_INT_CONFIG_VECTOR_MASK 0x00000000000000ffUL -#define UVH_RTC3_INT_CONFIG_DM_SHFT 8 -#define UVH_RTC3_INT_CONFIG_DM_MASK 0x0000000000000700UL -#define UVH_RTC3_INT_CONFIG_DESTMODE_SHFT 11 -#define UVH_RTC3_INT_CONFIG_DESTMODE_MASK 0x0000000000000800UL -#define UVH_RTC3_INT_CONFIG_STATUS_SHFT 12 -#define UVH_RTC3_INT_CONFIG_STATUS_MASK 0x0000000000001000UL -#define UVH_RTC3_INT_CONFIG_P_SHFT 13 -#define UVH_RTC3_INT_CONFIG_P_MASK 0x0000000000002000UL -#define UVH_RTC3_INT_CONFIG_T_SHFT 15 -#define UVH_RTC3_INT_CONFIG_T_MASK 0x0000000000008000UL -#define UVH_RTC3_INT_CONFIG_M_SHFT 16 -#define UVH_RTC3_INT_CONFIG_M_MASK 0x0000000000010000UL -#define UVH_RTC3_INT_CONFIG_APIC_ID_SHFT 32 -#define UVH_RTC3_INT_CONFIG_APIC_ID_MASK 0xffffffff00000000UL - -union uvh_rtc3_int_config_u { - unsigned long v; - struct uvh_rtc3_int_config_s { - unsigned long vector_ : 8; /* RW */ - unsigned long dm : 3; /* RW */ - unsigned long destmode : 1; /* RW */ - unsigned long status : 1; /* RO */ - unsigned long p : 1; /* RO */ - unsigned long rsvd_14 : 1; /* */ - unsigned long t : 1; /* RO */ - unsigned long m : 1; /* RW */ - unsigned long rsvd_17_31: 15; /* */ - unsigned long apic_id : 32; /* RW */ - } s; -}; - -/* ========================================================================= */ -/* UVH_RTC_INC_RATIO */ -/* ========================================================================= */ -#define UVH_RTC_INC_RATIO 0x350000UL - -#define UVH_RTC_INC_RATIO_FRACTION_SHFT 0 -#define UVH_RTC_INC_RATIO_FRACTION_MASK 0x00000000000fffffUL -#define UVH_RTC_INC_RATIO_RATIO_SHFT 20 -#define UVH_RTC_INC_RATIO_RATIO_MASK 0x0000000000700000UL - -union uvh_rtc_inc_ratio_u { - unsigned long v; - struct uvh_rtc_inc_ratio_s { - unsigned long fraction : 20; /* RW */ - unsigned long ratio : 3; /* RW */ - unsigned long rsvd_23_63: 41; /* */ - } s; -}; - -/* ========================================================================= */ /* UVH_SI_ADDR_MAP_CONFIG */ /* ========================================================================= */ #define UVH_SI_ADDR_MAP_CONFIG 0xc80000UL diff --git a/arch/x86/kernel/tlb_uv.c b/arch/x86/kernel/tlb_uv.c index 364d015ef..ef68ba4 100644 --- a/arch/x86/kernel/tlb_uv.c +++ b/arch/x86/kernel/tlb_uv.c @@ -20,6 +20,8 @@ #include #include +#define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD 0x000000000bUL + static struct bau_control **uv_bau_table_bases __read_mostly; static int uv_bau_retry_limit __read_mostly; @@ -478,16 +480,16 @@ static void uv_enable_timeouts(void) * To program the period, the SOFT_ACK_MODE must be off. */ mmr_image &= ~((unsigned long)1 << - UV_ENABLE_INTD_SOFT_ACK_MODE_SHIFT); + UVH_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_SHFT); uv_write_global_mmr64 (pnode, UVH_LB_BAU_MISC_CONTROL, mmr_image); /* * Set the 4-bit period. */ mmr_image &= ~((unsigned long)0xf << - UV_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHIFT); + UVH_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHFT); mmr_image |= (UV_INTD_SOFT_ACK_TIMEOUT_PERIOD << - UV_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHIFT); + UVH_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHFT); uv_write_global_mmr64 (pnode, UVH_LB_BAU_MISC_CONTROL, mmr_image); /* @@ -496,7 +498,7 @@ static void uv_enable_timeouts(void) * indicated in bits 2:0 (7 causes all of them to timeout). */ mmr_image |= ((unsigned long)1 << - UV_ENABLE_INTD_SOFT_ACK_MODE_SHIFT); + UVH_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_SHFT); uv_write_global_mmr64 (pnode, UVH_LB_BAU_MISC_CONTROL, mmr_image); } -- cgit v0.10.2 From 41acab8851a0408c1d5ad6c21a07456f88b54d40 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Wed, 10 Mar 2010 23:37:45 -0300 Subject: sched: Implement group scheduler statistics in one struct Put all statistic fields of sched_entity in one struct, sched_statistics, and embed it into sched_entity. This change allows to memset the sched_statistics to 0 when needed (for instance when forking), avoiding bugs of non initialized fields. Signed-off-by: Lucas De Marchi Signed-off-by: Peter Zijlstra LKML-Reference: <1268275065-18542-1-git-send-email-lucas.de.marchi@gmail.com> Signed-off-by: Ingo Molnar diff --git a/include/linux/sched.h b/include/linux/sched.h index 4b1753f..8cc863d 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1127,36 +1127,8 @@ struct load_weight { unsigned long weight, inv_weight; }; -/* - * CFS stats for a schedulable entity (task, task-group etc) - * - * Current field usage histogram: - * - * 4 se->block_start - * 4 se->run_node - * 4 se->sleep_start - * 6 se->load.weight - */ -struct sched_entity { - struct load_weight load; /* for load-balancing */ - struct rb_node run_node; - struct list_head group_node; - unsigned int on_rq; - - u64 exec_start; - u64 sum_exec_runtime; - u64 vruntime; - u64 prev_sum_exec_runtime; - - u64 last_wakeup; - u64 avg_overlap; - - u64 nr_migrations; - - u64 start_runtime; - u64 avg_wakeup; - #ifdef CONFIG_SCHEDSTATS +struct sched_statistics { u64 wait_start; u64 wait_max; u64 wait_count; @@ -1188,6 +1160,30 @@ struct sched_entity { u64 nr_wakeups_affine_attempts; u64 nr_wakeups_passive; u64 nr_wakeups_idle; +}; +#endif + +struct sched_entity { + struct load_weight load; /* for load-balancing */ + struct rb_node run_node; + struct list_head group_node; + unsigned int on_rq; + + u64 exec_start; + u64 sum_exec_runtime; + u64 vruntime; + u64 prev_sum_exec_runtime; + + u64 last_wakeup; + u64 avg_overlap; + + u64 nr_migrations; + + u64 start_runtime; + u64 avg_wakeup; + +#ifdef CONFIG_SCHEDSTATS + struct sched_statistics statistics; #endif #ifdef CONFIG_FAIR_GROUP_SCHED diff --git a/kernel/sched.c b/kernel/sched.c index 2c1db81..a4aa071 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -2437,15 +2437,15 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, out_activate: #endif /* CONFIG_SMP */ - schedstat_inc(p, se.nr_wakeups); + schedstat_inc(p, se.statistics.nr_wakeups); if (wake_flags & WF_SYNC) - schedstat_inc(p, se.nr_wakeups_sync); + schedstat_inc(p, se.statistics.nr_wakeups_sync); if (orig_cpu != cpu) - schedstat_inc(p, se.nr_wakeups_migrate); + schedstat_inc(p, se.statistics.nr_wakeups_migrate); if (cpu == this_cpu) - schedstat_inc(p, se.nr_wakeups_local); + schedstat_inc(p, se.statistics.nr_wakeups_local); else - schedstat_inc(p, se.nr_wakeups_remote); + schedstat_inc(p, se.statistics.nr_wakeups_remote); activate_task(rq, p, 1); success = 1; @@ -2532,36 +2532,7 @@ static void __sched_fork(struct task_struct *p) p->se.avg_wakeup = sysctl_sched_wakeup_granularity; #ifdef CONFIG_SCHEDSTATS - p->se.wait_start = 0; - p->se.wait_max = 0; - p->se.wait_count = 0; - p->se.wait_sum = 0; - - p->se.sleep_start = 0; - p->se.sleep_max = 0; - p->se.sum_sleep_runtime = 0; - - p->se.block_start = 0; - p->se.block_max = 0; - p->se.exec_max = 0; - p->se.slice_max = 0; - - p->se.nr_migrations_cold = 0; - p->se.nr_failed_migrations_affine = 0; - p->se.nr_failed_migrations_running = 0; - p->se.nr_failed_migrations_hot = 0; - p->se.nr_forced_migrations = 0; - - p->se.nr_wakeups = 0; - p->se.nr_wakeups_sync = 0; - p->se.nr_wakeups_migrate = 0; - p->se.nr_wakeups_local = 0; - p->se.nr_wakeups_remote = 0; - p->se.nr_wakeups_affine = 0; - p->se.nr_wakeups_affine_attempts = 0; - p->se.nr_wakeups_passive = 0; - p->se.nr_wakeups_idle = 0; - + memset(&p->se.statistics, 0, sizeof(p->se.statistics)); #endif INIT_LIST_HEAD(&p->rt.run_list); @@ -7910,9 +7881,9 @@ void normalize_rt_tasks(void) p->se.exec_start = 0; #ifdef CONFIG_SCHEDSTATS - p->se.wait_start = 0; - p->se.sleep_start = 0; - p->se.block_start = 0; + p->se.statistics.wait_start = 0; + p->se.statistics.sleep_start = 0; + p->se.statistics.block_start = 0; #endif if (!rt_task(p)) { diff --git a/kernel/sched_debug.c b/kernel/sched_debug.c index 67f95aa..ad9df44 100644 --- a/kernel/sched_debug.c +++ b/kernel/sched_debug.c @@ -70,16 +70,16 @@ static void print_cfs_group_stats(struct seq_file *m, int cpu, PN(se->vruntime); PN(se->sum_exec_runtime); #ifdef CONFIG_SCHEDSTATS - PN(se->wait_start); - PN(se->sleep_start); - PN(se->block_start); - PN(se->sleep_max); - PN(se->block_max); - PN(se->exec_max); - PN(se->slice_max); - PN(se->wait_max); - PN(se->wait_sum); - P(se->wait_count); + PN(se->statistics.wait_start); + PN(se->statistics.sleep_start); + PN(se->statistics.block_start); + PN(se->statistics.sleep_max); + PN(se->statistics.block_max); + PN(se->statistics.exec_max); + PN(se->statistics.slice_max); + PN(se->statistics.wait_max); + PN(se->statistics.wait_sum); + P(se->statistics.wait_count); #endif P(se->load.weight); #undef PN @@ -104,7 +104,7 @@ print_task(struct seq_file *m, struct rq *rq, struct task_struct *p) SEQ_printf(m, "%9Ld.%06ld %9Ld.%06ld %9Ld.%06ld", SPLIT_NS(p->se.vruntime), SPLIT_NS(p->se.sum_exec_runtime), - SPLIT_NS(p->se.sum_sleep_runtime)); + SPLIT_NS(p->se.statistics.sum_sleep_runtime)); #else SEQ_printf(m, "%15Ld %15Ld %15Ld.%06ld %15Ld.%06ld %15Ld.%06ld", 0LL, 0LL, 0LL, 0L, 0LL, 0L, 0LL, 0L); @@ -413,34 +413,34 @@ void proc_sched_show_task(struct task_struct *p, struct seq_file *m) nr_switches = p->nvcsw + p->nivcsw; #ifdef CONFIG_SCHEDSTATS - PN(se.wait_start); - PN(se.sleep_start); - PN(se.block_start); - PN(se.sleep_max); - PN(se.block_max); - PN(se.exec_max); - PN(se.slice_max); - PN(se.wait_max); - PN(se.wait_sum); - P(se.wait_count); - PN(se.iowait_sum); - P(se.iowait_count); + PN(se.statistics.wait_start); + PN(se.statistics.sleep_start); + PN(se.statistics.block_start); + PN(se.statistics.sleep_max); + PN(se.statistics.block_max); + PN(se.statistics.exec_max); + PN(se.statistics.slice_max); + PN(se.statistics.wait_max); + PN(se.statistics.wait_sum); + P(se.statistics.wait_count); + PN(se.statistics.iowait_sum); + P(se.statistics.iowait_count); P(sched_info.bkl_count); P(se.nr_migrations); - P(se.nr_migrations_cold); - P(se.nr_failed_migrations_affine); - P(se.nr_failed_migrations_running); - P(se.nr_failed_migrations_hot); - P(se.nr_forced_migrations); - P(se.nr_wakeups); - P(se.nr_wakeups_sync); - P(se.nr_wakeups_migrate); - P(se.nr_wakeups_local); - P(se.nr_wakeups_remote); - P(se.nr_wakeups_affine); - P(se.nr_wakeups_affine_attempts); - P(se.nr_wakeups_passive); - P(se.nr_wakeups_idle); + P(se.statistics.nr_migrations_cold); + P(se.statistics.nr_failed_migrations_affine); + P(se.statistics.nr_failed_migrations_running); + P(se.statistics.nr_failed_migrations_hot); + P(se.statistics.nr_forced_migrations); + P(se.statistics.nr_wakeups); + P(se.statistics.nr_wakeups_sync); + P(se.statistics.nr_wakeups_migrate); + P(se.statistics.nr_wakeups_local); + P(se.statistics.nr_wakeups_remote); + P(se.statistics.nr_wakeups_affine); + P(se.statistics.nr_wakeups_affine_attempts); + P(se.statistics.nr_wakeups_passive); + P(se.statistics.nr_wakeups_idle); { u64 avg_atom, avg_per_cpu; @@ -491,32 +491,7 @@ void proc_sched_show_task(struct task_struct *p, struct seq_file *m) void proc_sched_set_task(struct task_struct *p) { #ifdef CONFIG_SCHEDSTATS - p->se.wait_max = 0; - p->se.wait_sum = 0; - p->se.wait_count = 0; - p->se.iowait_sum = 0; - p->se.iowait_count = 0; - p->se.sleep_max = 0; - p->se.sum_sleep_runtime = 0; - p->se.block_max = 0; - p->se.exec_max = 0; - p->se.slice_max = 0; - p->se.nr_migrations = 0; - p->se.nr_migrations_cold = 0; - p->se.nr_failed_migrations_affine = 0; - p->se.nr_failed_migrations_running = 0; - p->se.nr_failed_migrations_hot = 0; - p->se.nr_forced_migrations = 0; - p->se.nr_wakeups = 0; - p->se.nr_wakeups_sync = 0; - p->se.nr_wakeups_migrate = 0; - p->se.nr_wakeups_local = 0; - p->se.nr_wakeups_remote = 0; - p->se.nr_wakeups_affine = 0; - p->se.nr_wakeups_affine_attempts = 0; - p->se.nr_wakeups_passive = 0; - p->se.nr_wakeups_idle = 0; - p->sched_info.bkl_count = 0; + memset(&p->se.statistics, 0, sizeof(p->se.statistics)); #endif p->se.sum_exec_runtime = 0; p->se.prev_sum_exec_runtime = 0; diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 3e1fd96..8ad164b 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -505,7 +505,8 @@ __update_curr(struct cfs_rq *cfs_rq, struct sched_entity *curr, { unsigned long delta_exec_weighted; - schedstat_set(curr->exec_max, max((u64)delta_exec, curr->exec_max)); + schedstat_set(curr->statistics.exec_max, + max((u64)delta_exec, curr->statistics.exec_max)); curr->sum_exec_runtime += delta_exec; schedstat_add(cfs_rq, exec_clock, delta_exec); @@ -548,7 +549,7 @@ static void update_curr(struct cfs_rq *cfs_rq) static inline void update_stats_wait_start(struct cfs_rq *cfs_rq, struct sched_entity *se) { - schedstat_set(se->wait_start, rq_of(cfs_rq)->clock); + schedstat_set(se->statistics.wait_start, rq_of(cfs_rq)->clock); } /* @@ -567,18 +568,18 @@ static void update_stats_enqueue(struct cfs_rq *cfs_rq, struct sched_entity *se) static void update_stats_wait_end(struct cfs_rq *cfs_rq, struct sched_entity *se) { - schedstat_set(se->wait_max, max(se->wait_max, - rq_of(cfs_rq)->clock - se->wait_start)); - schedstat_set(se->wait_count, se->wait_count + 1); - schedstat_set(se->wait_sum, se->wait_sum + - rq_of(cfs_rq)->clock - se->wait_start); + schedstat_set(se->statistics.wait_max, max(se->statistics.wait_max, + rq_of(cfs_rq)->clock - se->statistics.wait_start)); + schedstat_set(se->statistics.wait_count, se->statistics.wait_count + 1); + schedstat_set(se->statistics.wait_sum, se->statistics.wait_sum + + rq_of(cfs_rq)->clock - se->statistics.wait_start); #ifdef CONFIG_SCHEDSTATS if (entity_is_task(se)) { trace_sched_stat_wait(task_of(se), - rq_of(cfs_rq)->clock - se->wait_start); + rq_of(cfs_rq)->clock - se->statistics.wait_start); } #endif - schedstat_set(se->wait_start, 0); + schedstat_set(se->statistics.wait_start, 0); } static inline void @@ -657,39 +658,39 @@ static void enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se) if (entity_is_task(se)) tsk = task_of(se); - if (se->sleep_start) { - u64 delta = rq_of(cfs_rq)->clock - se->sleep_start; + if (se->statistics.sleep_start) { + u64 delta = rq_of(cfs_rq)->clock - se->statistics.sleep_start; if ((s64)delta < 0) delta = 0; - if (unlikely(delta > se->sleep_max)) - se->sleep_max = delta; + if (unlikely(delta > se->statistics.sleep_max)) + se->statistics.sleep_max = delta; - se->sleep_start = 0; - se->sum_sleep_runtime += delta; + se->statistics.sleep_start = 0; + se->statistics.sum_sleep_runtime += delta; if (tsk) { account_scheduler_latency(tsk, delta >> 10, 1); trace_sched_stat_sleep(tsk, delta); } } - if (se->block_start) { - u64 delta = rq_of(cfs_rq)->clock - se->block_start; + if (se->statistics.block_start) { + u64 delta = rq_of(cfs_rq)->clock - se->statistics.block_start; if ((s64)delta < 0) delta = 0; - if (unlikely(delta > se->block_max)) - se->block_max = delta; + if (unlikely(delta > se->statistics.block_max)) + se->statistics.block_max = delta; - se->block_start = 0; - se->sum_sleep_runtime += delta; + se->statistics.block_start = 0; + se->statistics.sum_sleep_runtime += delta; if (tsk) { if (tsk->in_iowait) { - se->iowait_sum += delta; - se->iowait_count++; + se->statistics.iowait_sum += delta; + se->statistics.iowait_count++; trace_sched_stat_iowait(tsk, delta); } @@ -826,9 +827,9 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep) struct task_struct *tsk = task_of(se); if (tsk->state & TASK_INTERRUPTIBLE) - se->sleep_start = rq_of(cfs_rq)->clock; + se->statistics.sleep_start = rq_of(cfs_rq)->clock; if (tsk->state & TASK_UNINTERRUPTIBLE) - se->block_start = rq_of(cfs_rq)->clock; + se->statistics.block_start = rq_of(cfs_rq)->clock; } #endif } @@ -912,7 +913,7 @@ set_next_entity(struct cfs_rq *cfs_rq, struct sched_entity *se) * when there are only lesser-weight tasks around): */ if (rq_of(cfs_rq)->load.weight >= 2*se->load.weight) { - se->slice_max = max(se->slice_max, + se->statistics.slice_max = max(se->statistics.slice_max, se->sum_exec_runtime - se->prev_sum_exec_runtime); } #endif @@ -1306,7 +1307,7 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync) if (sync && balanced) return 1; - schedstat_inc(p, se.nr_wakeups_affine_attempts); + schedstat_inc(p, se.statistics.nr_wakeups_affine_attempts); tl_per_task = cpu_avg_load_per_task(this_cpu); if (balanced || @@ -1318,7 +1319,7 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync) * there is no bad imbalance. */ schedstat_inc(sd, ttwu_move_affine); - schedstat_inc(p, se.nr_wakeups_affine); + schedstat_inc(p, se.statistics.nr_wakeups_affine); return 1; } @@ -1844,13 +1845,13 @@ int can_migrate_task(struct task_struct *p, struct rq *rq, int this_cpu, * 3) are cache-hot on their current CPU. */ if (!cpumask_test_cpu(this_cpu, &p->cpus_allowed)) { - schedstat_inc(p, se.nr_failed_migrations_affine); + schedstat_inc(p, se.statistics.nr_failed_migrations_affine); return 0; } *all_pinned = 0; if (task_running(rq, p)) { - schedstat_inc(p, se.nr_failed_migrations_running); + schedstat_inc(p, se.statistics.nr_failed_migrations_running); return 0; } @@ -1866,14 +1867,14 @@ int can_migrate_task(struct task_struct *p, struct rq *rq, int this_cpu, #ifdef CONFIG_SCHEDSTATS if (tsk_cache_hot) { schedstat_inc(sd, lb_hot_gained[idle]); - schedstat_inc(p, se.nr_forced_migrations); + schedstat_inc(p, se.statistics.nr_forced_migrations); } #endif return 1; } if (tsk_cache_hot) { - schedstat_inc(p, se.nr_failed_migrations_hot); + schedstat_inc(p, se.statistics.nr_failed_migrations_hot); return 0; } return 1; diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index c4fb42a..0335e87 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c @@ -613,7 +613,7 @@ static void update_curr_rt(struct rq *rq) if (unlikely((s64)delta_exec < 0)) delta_exec = 0; - schedstat_set(curr->se.exec_max, max(curr->se.exec_max, delta_exec)); + schedstat_set(curr->se.statistics.exec_max, max(curr->se.statistics.exec_max, delta_exec)); curr->se.sum_exec_runtime += delta_exec; account_group_exec_runtime(curr, delta_exec); -- cgit v0.10.2 From 9b33fa6ba0e2f90fdf407501db801c2511121564 Mon Sep 17 00:00:00 2001 From: "eranian@google.com" Date: Wed, 10 Mar 2010 22:26:05 -0800 Subject: perf_events: Improve task_sched_in() This patch is an optimization in perf_event_task_sched_in() to avoid scheduling the events twice in a row. Without it, the perf_disable()/perf_enable() pair is invoked twice, thereby pinned events counts while scheduling flexible events and we go throuh hw_perf_enable() twice. By encapsulating, the whole sequence into perf_disable()/perf_enable() we ensure, hw_perf_enable() is going to be invoked only once because of the refcount protection. Signed-off-by: Stephane Eranian Signed-off-by: Peter Zijlstra LKML-Reference: <1268288765-5326-1-git-send-email-eranian@google.com> Signed-off-by: Ingo Molnar diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 52c69a3..3853d49 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -1368,6 +1368,8 @@ void perf_event_task_sched_in(struct task_struct *task) if (cpuctx->task_ctx == ctx) return; + perf_disable(); + /* * We want to keep the following priority order: * cpu pinned (that don't need to move), task pinned, @@ -1380,6 +1382,8 @@ void perf_event_task_sched_in(struct task_struct *task) ctx_sched_in(ctx, cpuctx, EVENT_FLEXIBLE); cpuctx->task_ctx = ctx; + + perf_enable(); } #define MAX_INTERRUPTS (~0ULL) -- cgit v0.10.2 From 39c0cbe2150cbd848a25ba6cdb271d1ad46818ad Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Thu, 11 Mar 2010 17:17:13 +0100 Subject: sched: Rate-limit nohz Entering nohz code on every micro-idle is costing ~10% throughput for netperf TCP_RR when scheduling cross-cpu. Rate limiting entry fixes this, but raises ticks a bit. On my Q6600, an idle box goes from ~85 interrupts/sec to 128. The higher the context switch rate, the more nohz entry costs. With this patch and some cycle recovery patches in my tree, max cross cpu context switch rate is improved by ~16%, a large portion of which of which is this ratelimiting. Signed-off-by: Mike Galbraith Signed-off-by: Peter Zijlstra LKML-Reference: <1268301003.6785.28.camel@marge.simson.net> Signed-off-by: Ingo Molnar diff --git a/include/linux/sched.h b/include/linux/sched.h index 8cc863d..13efe7d 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -271,11 +271,17 @@ extern cpumask_var_t nohz_cpu_mask; #if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ) extern int select_nohz_load_balancer(int cpu); extern int get_nohz_load_balancer(void); +extern int nohz_ratelimit(int cpu); #else static inline int select_nohz_load_balancer(int cpu) { return 0; } + +static inline int nohz_ratelimit(int cpu) +{ + return 0; +} #endif /* diff --git a/kernel/sched.c b/kernel/sched.c index a4aa071..60b1bbe 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -492,6 +492,7 @@ struct rq { #define CPU_LOAD_IDX_MAX 5 unsigned long cpu_load[CPU_LOAD_IDX_MAX]; #ifdef CONFIG_NO_HZ + u64 nohz_stamp; unsigned char in_nohz_recently; #endif /* capture load from *all* tasks on this cpu: */ @@ -1228,6 +1229,17 @@ void wake_up_idle_cpu(int cpu) if (!tsk_is_polling(rq->idle)) smp_send_reschedule(cpu); } + +int nohz_ratelimit(int cpu) +{ + struct rq *rq = cpu_rq(cpu); + u64 diff = rq->clock - rq->nohz_stamp; + + rq->nohz_stamp = rq->clock; + + return diff < (NSEC_PER_SEC / HZ) >> 1; +} + #endif /* CONFIG_NO_HZ */ static u64 sched_avg_period(void) diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index f992762..f25735a 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -262,6 +262,9 @@ void tick_nohz_stop_sched_tick(int inidle) goto end; } + if (nohz_ratelimit(cpu)) + goto end; + ts->idle_calls++; /* Read jiffies and the time when jiffies were updated last */ do { -- cgit v0.10.2 From b42e0c41a422a212ddea0666d5a3a0e3c35206db Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Thu, 11 Mar 2010 17:15:38 +0100 Subject: sched: Remove avg_wakeup Testing the load which led to this heuristic (nfs4 kbuild) shows that it has outlived it's usefullness. With intervening load balancing changes, I cannot see any difference with/without, so recover there fastpath cycles. Signed-off-by: Mike Galbraith Signed-off-by: Peter Zijlstra LKML-Reference: <1268301062.6785.29.camel@marge.simson.net> Signed-off-by: Ingo Molnar diff --git a/include/linux/sched.h b/include/linux/sched.h index 13efe7d..70c560f 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1185,9 +1185,6 @@ struct sched_entity { u64 nr_migrations; - u64 start_runtime; - u64 avg_wakeup; - #ifdef CONFIG_SCHEDSTATS struct sched_statistics statistics; #endif diff --git a/kernel/sched.c b/kernel/sched.c index 60b1bbe..35a8626 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1880,9 +1880,6 @@ static void update_avg(u64 *avg, u64 sample) static void enqueue_task(struct rq *rq, struct task_struct *p, int wakeup, bool head) { - if (wakeup) - p->se.start_runtime = p->se.sum_exec_runtime; - sched_info_queued(p); p->sched_class->enqueue_task(rq, p, wakeup, head); p->se.on_rq = 1; @@ -1890,17 +1887,11 @@ enqueue_task(struct rq *rq, struct task_struct *p, int wakeup, bool head) static void dequeue_task(struct rq *rq, struct task_struct *p, int sleep) { - if (sleep) { - if (p->se.last_wakeup) { - update_avg(&p->se.avg_overlap, - p->se.sum_exec_runtime - p->se.last_wakeup); - p->se.last_wakeup = 0; - } else { - update_avg(&p->se.avg_wakeup, - sysctl_sched_wakeup_granularity); - } + if (sleep && p->se.last_wakeup) { + update_avg(&p->se.avg_overlap, + p->se.sum_exec_runtime - p->se.last_wakeup); + p->se.last_wakeup = 0; } - sched_info_dequeued(p); p->sched_class->dequeue_task(rq, p, sleep); p->se.on_rq = 0; @@ -2466,13 +2457,6 @@ out_activate: */ if (!in_interrupt()) { struct sched_entity *se = ¤t->se; - u64 sample = se->sum_exec_runtime; - - if (se->last_wakeup) - sample -= se->last_wakeup; - else - sample -= se->start_runtime; - update_avg(&se->avg_wakeup, sample); se->last_wakeup = se->sum_exec_runtime; } @@ -2540,8 +2524,6 @@ static void __sched_fork(struct task_struct *p) p->se.nr_migrations = 0; p->se.last_wakeup = 0; p->se.avg_overlap = 0; - p->se.start_runtime = 0; - p->se.avg_wakeup = sysctl_sched_wakeup_granularity; #ifdef CONFIG_SCHEDSTATS memset(&p->se.statistics, 0, sizeof(p->se.statistics)); diff --git a/kernel/sched_debug.c b/kernel/sched_debug.c index ad9df44..20b95a4 100644 --- a/kernel/sched_debug.c +++ b/kernel/sched_debug.c @@ -408,7 +408,6 @@ void proc_sched_show_task(struct task_struct *p, struct seq_file *m) PN(se.vruntime); PN(se.sum_exec_runtime); PN(se.avg_overlap); - PN(se.avg_wakeup); nr_switches = p->nvcsw + p->nivcsw; diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 8ad164b..6fc6285 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -1592,42 +1592,11 @@ static int select_task_rq_fair(struct task_struct *p, int sd_flag, int wake_flag } #endif /* CONFIG_SMP */ -/* - * Adaptive granularity - * - * se->avg_wakeup gives the average time a task runs until it does a wakeup, - * with the limit of wakeup_gran -- when it never does a wakeup. - * - * So the smaller avg_wakeup is the faster we want this task to preempt, - * but we don't want to treat the preemptee unfairly and therefore allow it - * to run for at least the amount of time we'd like to run. - * - * NOTE: we use 2*avg_wakeup to increase the probability of actually doing one - * - * NOTE: we use *nr_running to scale with load, this nicely matches the - * degrading latency on load. - */ -static unsigned long -adaptive_gran(struct sched_entity *curr, struct sched_entity *se) -{ - u64 this_run = curr->sum_exec_runtime - curr->prev_sum_exec_runtime; - u64 expected_wakeup = 2*se->avg_wakeup * cfs_rq_of(se)->nr_running; - u64 gran = 0; - - if (this_run < expected_wakeup) - gran = expected_wakeup - this_run; - - return min_t(s64, gran, sysctl_sched_wakeup_granularity); -} - static unsigned long wakeup_gran(struct sched_entity *curr, struct sched_entity *se) { unsigned long gran = sysctl_sched_wakeup_granularity; - if (cfs_rq_of(curr)->curr && sched_feat(ADAPTIVE_GRAN)) - gran = adaptive_gran(curr, se); - /* * Since its curr running now, convert the gran from real-time * to virtual-time in his units. diff --git a/kernel/sched_features.h b/kernel/sched_features.h index d5059fd..96ef5db 100644 --- a/kernel/sched_features.h +++ b/kernel/sched_features.h @@ -31,12 +31,6 @@ SCHED_FEAT(START_DEBIT, 1) SCHED_FEAT(WAKEUP_PREEMPT, 1) /* - * Compute wakeup_gran based on task behaviour, clipped to - * [0, sched_wakeup_gran_ns] - */ -SCHED_FEAT(ADAPTIVE_GRAN, 1) - -/* * When converting the wakeup granularity to virtual time, do it such * that heavier tasks preempting a lighter task have an edge. */ -- cgit v0.10.2 From e12f31d3e5d36328c7fbd0fce40a95e70b59152c Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Thu, 11 Mar 2010 17:15:51 +0100 Subject: sched: Remove avg_overlap Both avg_overlap and avg_wakeup had an inherent problem in that their accuracy was detrimentally affected by cross-cpu wakeups, this because we are missing the necessary call to update_curr(). This can't be fixed without increasing overhead in our already too fat fastpath. Additionally, with recent load balancing changes making us prefer to place tasks in an idle cache domain (which is good for compute bound loads), communicating tasks suffer when a sync wakeup, which would enable affine placement, is turned into a non-sync wakeup by SYNC_LESS. With one task on the runqueue, wake_affine() rejects the affine wakeup request, leaving the unfortunate where placed, taking frequent cache misses. Remove it, and recover some fastpath cycles. Signed-off-by: Mike Galbraith Signed-off-by: Peter Zijlstra LKML-Reference: <1268301121.6785.30.camel@marge.simson.net> Signed-off-by: Ingo Molnar diff --git a/include/linux/sched.h b/include/linux/sched.h index 70c560f..8604884 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1180,9 +1180,6 @@ struct sched_entity { u64 vruntime; u64 prev_sum_exec_runtime; - u64 last_wakeup; - u64 avg_overlap; - u64 nr_migrations; #ifdef CONFIG_SCHEDSTATS diff --git a/kernel/sched.c b/kernel/sched.c index 35a8626..68ed6f4 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1887,11 +1887,6 @@ enqueue_task(struct rq *rq, struct task_struct *p, int wakeup, bool head) static void dequeue_task(struct rq *rq, struct task_struct *p, int sleep) { - if (sleep && p->se.last_wakeup) { - update_avg(&p->se.avg_overlap, - p->se.sum_exec_runtime - p->se.last_wakeup); - p->se.last_wakeup = 0; - } sched_info_dequeued(p); p->sched_class->dequeue_task(rq, p, sleep); p->se.on_rq = 0; @@ -2452,15 +2447,6 @@ out_activate: activate_task(rq, p, 1); success = 1; - /* - * Only attribute actual wakeups done by this task. - */ - if (!in_interrupt()) { - struct sched_entity *se = ¤t->se; - - se->last_wakeup = se->sum_exec_runtime; - } - out_running: trace_sched_wakeup(rq, p, success); check_preempt_curr(rq, p, wake_flags); @@ -2522,8 +2508,6 @@ static void __sched_fork(struct task_struct *p) p->se.sum_exec_runtime = 0; p->se.prev_sum_exec_runtime = 0; p->se.nr_migrations = 0; - p->se.last_wakeup = 0; - p->se.avg_overlap = 0; #ifdef CONFIG_SCHEDSTATS memset(&p->se.statistics, 0, sizeof(p->se.statistics)); @@ -3594,23 +3578,6 @@ static inline void schedule_debug(struct task_struct *prev) static void put_prev_task(struct rq *rq, struct task_struct *prev) { - if (prev->state == TASK_RUNNING) { - u64 runtime = prev->se.sum_exec_runtime; - - runtime -= prev->se.prev_sum_exec_runtime; - runtime = min_t(u64, runtime, 2*sysctl_sched_migration_cost); - - /* - * In order to avoid avg_overlap growing stale when we are - * indeed overlapping and hence not getting put to sleep, grow - * the avg_overlap on preemption. - * - * We use the average preemption runtime because that - * correlates to the amount of cache footprint a task can - * build up. - */ - update_avg(&prev->se.avg_overlap, runtime); - } prev->sched_class->put_prev_task(rq, prev); } diff --git a/kernel/sched_debug.c b/kernel/sched_debug.c index 20b95a4..8a46a71 100644 --- a/kernel/sched_debug.c +++ b/kernel/sched_debug.c @@ -407,7 +407,6 @@ void proc_sched_show_task(struct task_struct *p, struct seq_file *m) PN(se.exec_start); PN(se.vruntime); PN(se.sum_exec_runtime); - PN(se.avg_overlap); nr_switches = p->nvcsw + p->nivcsw; diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 6fc6285..c3b69d4 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -1241,7 +1241,6 @@ static inline unsigned long effective_load(struct task_group *tg, int cpu, static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync) { - struct task_struct *curr = current; unsigned long this_load, load; int idx, this_cpu, prev_cpu; unsigned long tl_per_task; @@ -1256,18 +1255,6 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync) load = source_load(prev_cpu, idx); this_load = target_load(this_cpu, idx); - if (sync) { - if (sched_feat(SYNC_LESS) && - (curr->se.avg_overlap > sysctl_sched_migration_cost || - p->se.avg_overlap > sysctl_sched_migration_cost)) - sync = 0; - } else { - if (sched_feat(SYNC_MORE) && - (curr->se.avg_overlap < sysctl_sched_migration_cost && - p->se.avg_overlap < sysctl_sched_migration_cost)) - sync = 1; - } - /* * If sync wakeup then subtract the (maximum possible) * effect of the currently running task from the load @@ -1711,11 +1698,6 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int wake_ if (sched_feat(WAKEUP_SYNC) && sync) goto preempt; - if (sched_feat(WAKEUP_OVERLAP) && - se->avg_overlap < sysctl_sched_migration_cost && - pse->avg_overlap < sysctl_sched_migration_cost) - goto preempt; - if (!sched_feat(WAKEUP_PREEMPT)) return; diff --git a/kernel/sched_features.h b/kernel/sched_features.h index 96ef5db..c545e04 100644 --- a/kernel/sched_features.h +++ b/kernel/sched_features.h @@ -42,12 +42,6 @@ SCHED_FEAT(ASYM_GRAN, 1) SCHED_FEAT(WAKEUP_SYNC, 0) /* - * Wakeup preempt based on task behaviour. Tasks that do not overlap - * don't get preempted. - */ -SCHED_FEAT(WAKEUP_OVERLAP, 0) - -/* * Use the SYNC wakeup hint, pipes and the likes use this to indicate * the remote end is likely to consume the data we just wrote, and * therefore has cache benefit from being placed on the same cpu, see @@ -64,16 +58,6 @@ SCHED_FEAT(SYNC_WAKEUPS, 1) SCHED_FEAT(AFFINE_WAKEUPS, 1) /* - * Weaken SYNC hint based on overlap - */ -SCHED_FEAT(SYNC_LESS, 1) - -/* - * Add SYNC hint based on overlap - */ -SCHED_FEAT(SYNC_MORE, 0) - -/* * Prefer to schedule the task we woke last (assuming it failed * wakeup-preemption), since its likely going to consume data we * touched, increases cache locality. -- cgit v0.10.2 From a64692a3afd85fe048551ab89142fd5ca99a0dbd Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Thu, 11 Mar 2010 17:16:20 +0100 Subject: sched: Cleanup/optimize clock updates Now that we no longer depend on the clock being updated prior to enqueueing on migratory wakeup, we can clean up a bit, placing calls to update_rq_clock() exactly where they are needed, ie on enqueue, dequeue and schedule events. In the case of a freshly enqueued task immediately preempting, we can skip the update during preemption, as the clock was just updated by the enqueue event. We also save an unneeded call during a migratory wakeup by not updating the previous runqueue, where update_curr() won't be invoked. Signed-off-by: Mike Galbraith Signed-off-by: Peter Zijlstra LKML-Reference: <1268301199.6785.32.camel@marge.simson.net> Signed-off-by: Ingo Molnar diff --git a/kernel/sched.c b/kernel/sched.c index 68ed6f4..16559de 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -495,6 +495,8 @@ struct rq { u64 nohz_stamp; unsigned char in_nohz_recently; #endif + unsigned int skip_clock_update; + /* capture load from *all* tasks on this cpu: */ struct load_weight load; unsigned long nr_load_updates; @@ -592,6 +594,13 @@ static inline void check_preempt_curr(struct rq *rq, struct task_struct *p, int flags) { rq->curr->sched_class->check_preempt_curr(rq, p, flags); + + /* + * A queue event has occurred, and we're going to schedule. In + * this case, we can save a useless back to back clock update. + */ + if (test_tsk_need_resched(p)) + rq->skip_clock_update = 1; } static inline int cpu_of(struct rq *rq) @@ -626,7 +635,8 @@ static inline int cpu_of(struct rq *rq) inline void update_rq_clock(struct rq *rq) { - rq->clock = sched_clock_cpu(cpu_of(rq)); + if (!rq->skip_clock_update) + rq->clock = sched_clock_cpu(cpu_of(rq)); } /* @@ -1782,8 +1792,6 @@ static void double_rq_lock(struct rq *rq1, struct rq *rq2) raw_spin_lock_nested(&rq1->lock, SINGLE_DEPTH_NESTING); } } - update_rq_clock(rq1); - update_rq_clock(rq2); } /* @@ -1880,6 +1888,7 @@ static void update_avg(u64 *avg, u64 sample) static void enqueue_task(struct rq *rq, struct task_struct *p, int wakeup, bool head) { + update_rq_clock(rq); sched_info_queued(p); p->sched_class->enqueue_task(rq, p, wakeup, head); p->se.on_rq = 1; @@ -1887,6 +1896,7 @@ enqueue_task(struct rq *rq, struct task_struct *p, int wakeup, bool head) static void dequeue_task(struct rq *rq, struct task_struct *p, int sleep) { + update_rq_clock(rq); sched_info_dequeued(p); p->sched_class->dequeue_task(rq, p, sleep); p->se.on_rq = 0; @@ -2366,7 +2376,6 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, smp_wmb(); rq = task_rq_lock(p, &flags); - update_rq_clock(rq); if (!(p->state & state)) goto out; @@ -2407,7 +2416,6 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, rq = cpu_rq(cpu); raw_spin_lock(&rq->lock); - update_rq_clock(rq); /* * We migrated the task without holding either rq->lock, however @@ -2624,7 +2632,6 @@ void wake_up_new_task(struct task_struct *p, unsigned long clone_flags) BUG_ON(p->state != TASK_WAKING); p->state = TASK_RUNNING; - update_rq_clock(rq); activate_task(rq, p, 0); trace_sched_wakeup_new(rq, p, 1); check_preempt_curr(rq, p, WF_FORK); @@ -3578,6 +3585,9 @@ static inline void schedule_debug(struct task_struct *prev) static void put_prev_task(struct rq *rq, struct task_struct *prev) { + if (prev->se.on_rq) + update_rq_clock(rq); + rq->skip_clock_update = 0; prev->sched_class->put_prev_task(rq, prev); } @@ -3640,7 +3650,6 @@ need_resched_nonpreemptible: hrtick_clear(rq); raw_spin_lock_irq(&rq->lock); - update_rq_clock(rq); clear_tsk_need_resched(prev); if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) { @@ -4197,7 +4206,6 @@ void rt_mutex_setprio(struct task_struct *p, int prio) BUG_ON(prio < 0 || prio > MAX_PRIO); rq = task_rq_lock(p, &flags); - update_rq_clock(rq); oldprio = p->prio; prev_class = p->sched_class; @@ -4240,7 +4248,6 @@ void set_user_nice(struct task_struct *p, long nice) * the task might be in the middle of scheduling on another CPU. */ rq = task_rq_lock(p, &flags); - update_rq_clock(rq); /* * The RT priorities are set via sched_setscheduler(), but we still * allow the 'normal' nice value to be set - but as expected @@ -4523,7 +4530,6 @@ recheck: raw_spin_unlock_irqrestore(&p->pi_lock, flags); goto recheck; } - update_rq_clock(rq); on_rq = p->se.on_rq; running = task_current(rq, p); if (on_rq) @@ -5530,7 +5536,6 @@ void sched_idle_next(void) __setscheduler(rq, p, SCHED_FIFO, MAX_RT_PRIO-1); - update_rq_clock(rq); activate_task(rq, p, 0); raw_spin_unlock_irqrestore(&rq->lock, flags); @@ -5585,7 +5590,6 @@ static void migrate_dead_tasks(unsigned int dead_cpu) for ( ; ; ) { if (!rq->nr_running) break; - update_rq_clock(rq); next = pick_next_task(rq); if (!next) break; @@ -5869,7 +5873,6 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu) rq->migration_thread = NULL; /* Idle task back to normal (off runqueue, low prio) */ raw_spin_lock_irq(&rq->lock); - update_rq_clock(rq); deactivate_task(rq, rq->idle, 0); __setscheduler(rq, rq->idle, SCHED_NORMAL, 0); rq->idle->sched_class = &idle_sched_class; @@ -7815,7 +7818,6 @@ static void normalize_task(struct rq *rq, struct task_struct *p) { int on_rq; - update_rq_clock(rq); on_rq = p->se.on_rq; if (on_rq) deactivate_task(rq, p, 0); @@ -8177,8 +8179,6 @@ void sched_move_task(struct task_struct *tsk) rq = task_rq_lock(tsk, &flags); - update_rq_clock(rq); - running = task_current(rq, tsk); on_rq = tsk->se.on_rq; diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index c3b69d4..69e5820 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -3064,8 +3064,6 @@ static void active_load_balance(struct rq *busiest_rq, int busiest_cpu) /* move a task from busiest_rq to target_rq */ double_lock_balance(busiest_rq, target_rq); - update_rq_clock(busiest_rq); - update_rq_clock(target_rq); /* Search for an sd spanning us and the target CPU. */ for_each_domain(target_cpu, sd) { -- cgit v0.10.2 From 21406928afe43f1db6acab4931bb8c886f4d04ce Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Thu, 11 Mar 2010 17:17:15 +0100 Subject: sched: Tweak sched_latency and min_granularity Allow LAST_BUDDY to kick in sooner, improving cache utilization as soon as a second buddy pair arrives on scene. The cost is latency starting to climb sooner, the tbenefit for tbench 8 on my Q6600 box is ~2%. No detrimental effects noted in normal idesktop usage. Signed-off-by: Mike Galbraith Signed-off-by: Peter Zijlstra LKML-Reference: <1268301285.6785.34.camel@marge.simson.net> Signed-off-by: Ingo Molnar diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 69e5820..d19df5b 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -35,8 +35,8 @@ * (to see the precise effective timeslice length of your workload, * run vmstat and monitor the context-switches (cs) field) */ -unsigned int sysctl_sched_latency = 5000000ULL; -unsigned int normalized_sysctl_sched_latency = 5000000ULL; +unsigned int sysctl_sched_latency = 6000000ULL; +unsigned int normalized_sysctl_sched_latency = 6000000ULL; /* * The initial- and re-scaling of tunables is configurable @@ -52,15 +52,15 @@ enum sched_tunable_scaling sysctl_sched_tunable_scaling /* * Minimal preemption granularity for CPU-bound tasks: - * (default: 1 msec * (1 + ilog(ncpus)), units: nanoseconds) + * (default: 2 msec * (1 + ilog(ncpus)), units: nanoseconds) */ -unsigned int sysctl_sched_min_granularity = 1000000ULL; -unsigned int normalized_sysctl_sched_min_granularity = 1000000ULL; +unsigned int sysctl_sched_min_granularity = 2000000ULL; +unsigned int normalized_sysctl_sched_min_granularity = 2000000ULL; /* * is kept at sysctl_sched_latency / sysctl_sched_min_granularity */ -static unsigned int sched_nr_latency = 5; +static unsigned int sched_nr_latency = 3; /* * After fork, child runs first. If set to 0 (default) then -- cgit v0.10.2 From 8b911acdf08477c059d1c36c21113ab1696c612b Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Thu, 11 Mar 2010 17:17:16 +0100 Subject: sched: Fix select_idle_sibling() Don't bother with selection when the current cpu is idle. Recent load balancing changes also make it no longer necessary to check wake_affine() success before returning the selected sibling, so we now always use it. Signed-off-by: Mike Galbraith Signed-off-by: Peter Zijlstra LKML-Reference: <1268301369.6785.36.camel@marge.simson.net> Signed-off-by: Ingo Molnar diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index d19df5b..0008cc4 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -1439,7 +1439,7 @@ static int select_task_rq_fair(struct task_struct *p, int sd_flag, int wake_flag int cpu = smp_processor_id(); int prev_cpu = task_cpu(p); int new_cpu = cpu; - int want_affine = 0; + int want_affine = 0, cpu_idle = !current->pid; int want_sd = 1; int sync = wake_flags & WF_SYNC; @@ -1497,13 +1497,15 @@ static int select_task_rq_fair(struct task_struct *p, int sd_flag, int wake_flag * If there's an idle sibling in this domain, make that * the wake_affine target instead of the current cpu. */ - if (tmp->flags & SD_SHARE_PKG_RESOURCES) + if (!cpu_idle && tmp->flags & SD_SHARE_PKG_RESOURCES) target = select_idle_sibling(p, tmp, target); if (target >= 0) { if (tmp->flags & SD_WAKE_AFFINE) { affine_sd = tmp; want_affine = 0; + if (target != cpu) + cpu_idle = 1; } cpu = target; } @@ -1519,6 +1521,7 @@ static int select_task_rq_fair(struct task_struct *p, int sd_flag, int wake_flag sd = tmp; } +#ifdef CONFIG_FAIR_GROUP_SCHED if (sched_feat(LB_SHARES_UPDATE)) { /* * Pick the largest domain to update shares over @@ -1532,9 +1535,12 @@ static int select_task_rq_fair(struct task_struct *p, int sd_flag, int wake_flag if (tmp) update_shares(tmp); } +#endif - if (affine_sd && wake_affine(affine_sd, p, sync)) - return cpu; + if (affine_sd) { + if (cpu_idle || cpu == prev_cpu || wake_affine(affine_sd, p, sync)) + return cpu; + } while (sd) { int load_idx = sd->forkexec_idx; -- cgit v0.10.2 From 6bc6cf2b61336ed0c55a615eb4c0c8ed5daf3f08 Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Thu, 11 Mar 2010 17:17:17 +0100 Subject: sched: Remove NORMALIZED_SLEEPER This feature hasn't been enabled in a long time, remove effectively dead code. Signed-off-by: Mike Galbraith Signed-off-by: Peter Zijlstra LKML-Reference: <1268301447.6785.38.camel@marge.simson.net> Signed-off-by: Ingo Molnar diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 0008cc4..de98e2e 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -742,16 +742,6 @@ place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int initial) unsigned long thresh = sysctl_sched_latency; /* - * Convert the sleeper threshold into virtual time. - * SCHED_IDLE is a special sub-class. We care about - * fairness only relative to other SCHED_IDLE tasks, - * all of which have the same weight. - */ - if (sched_feat(NORMALIZED_SLEEPER) && (!entity_is_task(se) || - task_of(se)->policy != SCHED_IDLE)) - thresh = calc_delta_fair(thresh, se); - - /* * Halve their sleep time's effect, to allow * for a gentler effect of sleepers: */ diff --git a/kernel/sched_features.h b/kernel/sched_features.h index c545e04..4042883 100644 --- a/kernel/sched_features.h +++ b/kernel/sched_features.h @@ -13,13 +13,6 @@ SCHED_FEAT(FAIR_SLEEPERS, 1) SCHED_FEAT(GENTLE_FAIR_SLEEPERS, 1) /* - * By not normalizing the sleep time, heavy tasks get an effective - * longer period, and lighter task an effective shorter period they - * are considered running. - */ -SCHED_FEAT(NORMALIZED_SLEEPER, 0) - -/* * Place new tasks ahead so that they do not starve already running * tasks */ -- cgit v0.10.2 From 5ca9880c6f4ba4c84b517bc2fed5366adf63d191 Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Thu, 11 Mar 2010 17:17:17 +0100 Subject: sched: Remove FAIR_SLEEPERS feature Our preemption model relies too heavily on sleeper fairness to disable it without dire consequences. Remove the feature, and save a branch or two. Signed-off-by: Mike Galbraith Signed-off-by: Peter Zijlstra LKML-Reference: <1268301520.6785.40.camel@marge.simson.net> Signed-off-by: Ingo Molnar diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index de98e2e..97682f9 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -738,7 +738,7 @@ place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int initial) vruntime += sched_vslice(cfs_rq, se); /* sleeps up to a single latency don't count. */ - if (!initial && sched_feat(FAIR_SLEEPERS)) { + if (!initial) { unsigned long thresh = sysctl_sched_latency; /* diff --git a/kernel/sched_features.h b/kernel/sched_features.h index 4042883..850f980 100644 --- a/kernel/sched_features.h +++ b/kernel/sched_features.h @@ -1,11 +1,4 @@ /* - * Disregards a certain amount of sleep time (sched_latency_ns) and - * considers the task to be running during that period. This gives it - * a service deficit on wakeup, allowing it to run sooner. - */ -SCHED_FEAT(FAIR_SLEEPERS, 1) - -/* * Only give sleepers 50% of their service deficit. This allows * them to run sooner, but does not allow tons of sleepers to * rip the spread apart. -- cgit v0.10.2 From f2e74eeac03ffb779d64b66a643c5e598145a28b Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Thu, 11 Mar 2010 17:17:18 +0100 Subject: sched: Remove WAKEUP_SYNC feature This feature never earned its keep, remove it. Signed-off-by: Mike Galbraith Signed-off-by: Peter Zijlstra LKML-Reference: <1268301591.6785.42.camel@marge.simson.net> Signed-off-by: Ingo Molnar diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 97682f9..1d99535 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -1658,7 +1658,6 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int wake_ struct task_struct *curr = rq->curr; struct sched_entity *se = &curr->se, *pse = &p->se; struct cfs_rq *cfs_rq = task_cfs_rq(curr); - int sync = wake_flags & WF_SYNC; int scale = cfs_rq->nr_running >= sched_nr_latency; if (unlikely(rt_prio(p->prio))) @@ -1691,9 +1690,6 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int wake_ if (unlikely(curr->policy == SCHED_IDLE)) goto preempt; - if (sched_feat(WAKEUP_SYNC) && sync) - goto preempt; - if (!sched_feat(WAKEUP_PREEMPT)) return; diff --git a/kernel/sched_features.h b/kernel/sched_features.h index 850f980..1cb7c47 100644 --- a/kernel/sched_features.h +++ b/kernel/sched_features.h @@ -23,11 +23,6 @@ SCHED_FEAT(WAKEUP_PREEMPT, 1) SCHED_FEAT(ASYM_GRAN, 1) /* - * Always wakeup-preempt SYNC wakeups, see SYNC_WAKEUPS. - */ -SCHED_FEAT(WAKEUP_SYNC, 0) - -/* * Use the SYNC wakeup hint, pipes and the likes use this to indicate * the remote end is likely to consume the data we just wrote, and * therefore has cache benefit from being placed on the same cpu, see -- cgit v0.10.2 From c6ee36c423c3ed1fb86bb3eabba9fc256a300d16 Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Thu, 11 Mar 2010 17:16:43 +0100 Subject: sched: Remove SYNC_WAKEUPS feature Sync wakeups are critical functionality with a long history. Remove it, we don't need the branch or icache footprint. Signed-off-by: Mike Galbraith Signed-off-by: Peter Zijlstra LKML-Reference: <1268301817.6785.47.camel@marge.simson.net> Signed-off-by: Ingo Molnar diff --git a/kernel/sched.c b/kernel/sched.c index 16559de..cc6dc8c 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -2369,9 +2369,6 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, unsigned long flags; struct rq *rq; - if (!sched_feat(SYNC_WAKEUPS)) - wake_flags &= ~WF_SYNC; - this_cpu = get_cpu(); smp_wmb(); diff --git a/kernel/sched_features.h b/kernel/sched_features.h index 1cb7c47..f54b6f9 100644 --- a/kernel/sched_features.h +++ b/kernel/sched_features.h @@ -23,14 +23,6 @@ SCHED_FEAT(WAKEUP_PREEMPT, 1) SCHED_FEAT(ASYM_GRAN, 1) /* - * Use the SYNC wakeup hint, pipes and the likes use this to indicate - * the remote end is likely to consume the data we just wrote, and - * therefore has cache benefit from being placed on the same cpu, see - * also AFFINE_WAKEUPS. - */ -SCHED_FEAT(SYNC_WAKEUPS, 1) - -/* * Based on load and program behaviour, see if it makes sense to place * a newly woken task on the same cpu as the task that woke it -- * improve cache locality. Typically used with SYNC wakeups as -- cgit v0.10.2 From 13814d42e45dfbe845a0bbe5184565d9236896ae Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Thu, 11 Mar 2010 17:17:04 +0100 Subject: sched: Remove ASYM_GRAN feature This features has been enabled for quite a while, after testing showed that easing preemption for light tasks was harmful to high priority threads. Remove the feature flag. Signed-off-by: Mike Galbraith Signed-off-by: Peter Zijlstra LKML-Reference: <1268301675.6785.44.camel@marge.simson.net> Signed-off-by: Ingo Molnar diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 1d99535..9357ecd 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -1583,24 +1583,18 @@ wakeup_gran(struct sched_entity *curr, struct sched_entity *se) /* * Since its curr running now, convert the gran from real-time * to virtual-time in his units. + * + * By using 'se' instead of 'curr' we penalize light tasks, so + * they get preempted easier. That is, if 'se' < 'curr' then + * the resulting gran will be larger, therefore penalizing the + * lighter, if otoh 'se' > 'curr' then the resulting gran will + * be smaller, again penalizing the lighter task. + * + * This is especially important for buddies when the leftmost + * task is higher priority than the buddy. */ - if (sched_feat(ASYM_GRAN)) { - /* - * By using 'se' instead of 'curr' we penalize light tasks, so - * they get preempted easier. That is, if 'se' < 'curr' then - * the resulting gran will be larger, therefore penalizing the - * lighter, if otoh 'se' > 'curr' then the resulting gran will - * be smaller, again penalizing the lighter task. - * - * This is especially important for buddies when the leftmost - * task is higher priority than the buddy. - */ - if (unlikely(se->load.weight != NICE_0_LOAD)) - gran = calc_delta_fair(gran, se); - } else { - if (unlikely(curr->load.weight != NICE_0_LOAD)) - gran = calc_delta_fair(gran, curr); - } + if (unlikely(se->load.weight != NICE_0_LOAD)) + gran = calc_delta_fair(gran, se); return gran; } diff --git a/kernel/sched_features.h b/kernel/sched_features.h index f54b6f9..83c66e8 100644 --- a/kernel/sched_features.h +++ b/kernel/sched_features.h @@ -17,12 +17,6 @@ SCHED_FEAT(START_DEBIT, 1) SCHED_FEAT(WAKEUP_PREEMPT, 1) /* - * When converting the wakeup granularity to virtual time, do it such - * that heavier tasks preempting a lighter task have an edge. - */ -SCHED_FEAT(ASYM_GRAN, 1) - -/* * Based on load and program behaviour, see if it makes sense to place * a newly woken task on the same cpu as the task that woke it -- * improve cache locality. Typically used with SYNC wakeups as -- cgit v0.10.2 From beac4c7e4a1cc6d57801f690e5e82fa2c9c245c8 Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Thu, 11 Mar 2010 17:17:20 +0100 Subject: sched: Remove AFFINE_WAKEUPS feature Disabling affine wakeups is too horrible to contemplate. Remove the feature flag. Signed-off-by: Mike Galbraith Signed-off-by: Peter Zijlstra LKML-Reference: <1268301890.6785.50.camel@marge.simson.net> Signed-off-by: Ingo Molnar diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 9357ecd..35a5c64 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -1434,8 +1434,7 @@ static int select_task_rq_fair(struct task_struct *p, int sd_flag, int wake_flag int sync = wake_flags & WF_SYNC; if (sd_flag & SD_BALANCE_WAKE) { - if (sched_feat(AFFINE_WAKEUPS) && - cpumask_test_cpu(cpu, &p->cpus_allowed)) + if (cpumask_test_cpu(cpu, &p->cpus_allowed)) want_affine = 1; new_cpu = prev_cpu; } -- cgit v0.10.2 From a072738e04f0eb26370e39ec679e9a0d65e49aea Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Thu, 11 Mar 2010 19:54:39 +0300 Subject: perf, x86: Implement initial P4 PMU driver The netburst PMU is way different from the "architectural perfomance monitoring" specification that current CPUs use. P4 uses a tuple of ESCR+CCCR+COUNTER MSR registers to handle perfomance monitoring events. A few implementational details: 1) We need a separate x86_pmu::hw_config helper in struct x86_pmu since register bit-fields are quite different from P6, Core and later cpu series. 2) For the same reason is a x86_pmu::schedule_events helper introduced. 3) hw_perf_event::config consists of packed ESCR+CCCR values. It's allowed since in reality both registers only use a half of their size. Of course before making a real write into a particular MSR we need to unpack the value and extend it to a proper size. 4) The tuple of packed ESCR+CCCR in hw_perf_event::config doesn't describe the memory address of ESCR MSR register so that we need to keep a mapping between these tuples used and available ESCR (various P4 events may use same ESCRs but not simultaneously), for this sake every active event has a per-cpu map of hw_perf_event::idx <--> ESCR addresses. 5) Since hw_perf_event::idx is an offset to counter/control register we need to lift X86_PMC_MAX_GENERIC up, otherwise kernel strips it down to 8 registers and event armed may never be turned off (ie the bit in active_mask is set but the loop never reaches this index to check), thanks to Peter Zijlstra Restrictions: - No cascaded counters support (do we ever need them?) - No dependent events support (so PERF_COUNT_HW_INSTRUCTIONS doesn't work for now) - There are events with same counters which can't work simultaneously (need to use intersected ones due to broken counter 1) - No PERF_COUNT_HW_CACHE_ events yet Todo: - Implement dependent events - Need proper hashing for event opcodes (no linear search, good for debugging stage but not in real loads) - Some events counted during a clock cycle -- need to set threshold for them and count every clock cycle just to get summary statistics (ie to behave the same way as other PMUs do) - Need to swicth to use event_constraints - To support RAW events we need to encode a global list of P4 events into p4_templates - Cache events need to be added Event support status matrix: Event status ----------------------------- cycles works cache-references works cache-misses works branch-misses works bus-cycles partially (does not work on 64bit cpu with HT enabled) instruction doesnt work (needs dependent event [mop tagging]) branches doesnt work Signed-off-by: Cyrill Gorcunov Signed-off-by: Lin Ming Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Stephane Eranian Cc: Robert Richter Cc: Frederic Weisbecker LKML-Reference: <20100311165439.GB5129@lenovo> Signed-off-by: Ingo Molnar diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h index a9038c9..124dddd 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h @@ -5,7 +5,7 @@ * Performance event hw details: */ -#define X86_PMC_MAX_GENERIC 8 +#define X86_PMC_MAX_GENERIC 32 #define X86_PMC_MAX_FIXED 3 #define X86_PMC_IDX_GENERIC 0 diff --git a/arch/x86/include/asm/perf_event_p4.h b/arch/x86/include/asm/perf_event_p4.h new file mode 100644 index 0000000..829f471 --- /dev/null +++ b/arch/x86/include/asm/perf_event_p4.h @@ -0,0 +1,707 @@ +/* + * Netburst Perfomance Events (P4, old Xeon) + */ + +#ifndef PERF_EVENT_P4_H +#define PERF_EVENT_P4_H + +#include +#include + +/* + * NetBurst has perfomance MSRs shared between + * threads if HT is turned on, ie for both logical + * processors (mem: in turn in Atom with HT support + * perf-MSRs are not shared and every thread has its + * own perf-MSRs set) + */ +#define ARCH_P4_TOTAL_ESCR (46) +#define ARCH_P4_RESERVED_ESCR (2) /* IQ_ESCR(0,1) not always present */ +#define ARCH_P4_MAX_ESCR (ARCH_P4_TOTAL_ESCR - ARCH_P4_RESERVED_ESCR) +#define ARCH_P4_MAX_CCCR (18) +#define ARCH_P4_MAX_COUNTER (ARCH_P4_MAX_CCCR / 2) + +#define P4_EVNTSEL_EVENT_MASK 0x7e000000U +#define P4_EVNTSEL_EVENT_SHIFT 25 +#define P4_EVNTSEL_EVENTMASK_MASK 0x01fffe00U +#define P4_EVNTSEL_EVENTMASK_SHIFT 9 +#define P4_EVNTSEL_TAG_MASK 0x000001e0U +#define P4_EVNTSEL_TAG_SHIFT 5 +#define P4_EVNTSEL_TAG_ENABLE 0x00000010U +#define P4_EVNTSEL_T0_OS 0x00000008U +#define P4_EVNTSEL_T0_USR 0x00000004U +#define P4_EVNTSEL_T1_OS 0x00000002U +#define P4_EVNTSEL_T1_USR 0x00000001U + +/* Non HT mask */ +#define P4_EVNTSEL_MASK \ + (P4_EVNTSEL_EVENT_MASK | \ + P4_EVNTSEL_EVENTMASK_MASK | \ + P4_EVNTSEL_TAG_MASK | \ + P4_EVNTSEL_TAG_ENABLE | \ + P4_EVNTSEL_T0_OS | \ + P4_EVNTSEL_T0_USR) + +/* HT mask */ +#define P4_EVNTSEL_MASK_HT \ + (P4_EVNTSEL_MASK | \ + P4_EVNTSEL_T1_OS | \ + P4_EVNTSEL_T1_USR) + +#define P4_CCCR_OVF 0x80000000U +#define P4_CCCR_CASCADE 0x40000000U +#define P4_CCCR_OVF_PMI_T0 0x04000000U +#define P4_CCCR_OVF_PMI_T1 0x08000000U +#define P4_CCCR_FORCE_OVF 0x02000000U +#define P4_CCCR_EDGE 0x01000000U +#define P4_CCCR_THRESHOLD_MASK 0x00f00000U +#define P4_CCCR_THRESHOLD_SHIFT 20 +#define P4_CCCR_THRESHOLD(v) ((v) << P4_CCCR_THRESHOLD_SHIFT) +#define P4_CCCR_COMPLEMENT 0x00080000U +#define P4_CCCR_COMPARE 0x00040000U +#define P4_CCCR_ESCR_SELECT_MASK 0x0000e000U +#define P4_CCCR_ESCR_SELECT_SHIFT 13 +#define P4_CCCR_ENABLE 0x00001000U +#define P4_CCCR_THREAD_SINGLE 0x00010000U +#define P4_CCCR_THREAD_BOTH 0x00020000U +#define P4_CCCR_THREAD_ANY 0x00030000U + +/* Non HT mask */ +#define P4_CCCR_MASK \ + (P4_CCCR_OVF | \ + P4_CCCR_CASCADE | \ + P4_CCCR_OVF_PMI_T0 | \ + P4_CCCR_FORCE_OVF | \ + P4_CCCR_EDGE | \ + P4_CCCR_THRESHOLD_MASK | \ + P4_CCCR_COMPLEMENT | \ + P4_CCCR_COMPARE | \ + P4_CCCR_ESCR_SELECT_MASK | \ + P4_CCCR_ENABLE) + +/* HT mask */ +#define P4_CCCR_MASK_HT \ + (P4_CCCR_MASK | \ + P4_CCCR_THREAD_ANY) + +/* + * format is 32 bit: ee ss aa aa + * where + * ee - 8 bit event + * ss - 8 bit selector + * aa aa - 16 bits reserved for tags/attributes + */ +#define P4_EVENT_PACK(event, selector) (((event) << 24) | ((selector) << 16)) +#define P4_EVENT_UNPACK_EVENT(packed) (((packed) >> 24) & 0xff) +#define P4_EVENT_UNPACK_SELECTOR(packed) (((packed) >> 16) & 0xff) +#define P4_EVENT_PACK_ATTR(attr) ((attr)) +#define P4_EVENT_UNPACK_ATTR(packed) ((packed) & 0xffff) +#define P4_MAKE_EVENT_ATTR(class, name, bit) class##_##name = (1 << bit) +#define P4_EVENT_ATTR(class, name) class##_##name +#define P4_EVENT_ATTR_STR(class, name) __stringify(class##_##name) + +/* + * config field is 64bit width and consists of + * HT << 63 | ESCR << 32 | CCCR + * where HT is HyperThreading bit (since ESCR + * has it reserved we may use it for own purpose) + * + * note that this is NOT the addresses of respective + * ESCR and CCCR but rather an only packed value should + * be unpacked and written to a proper addresses + * + * the base idea is to pack as much info as + * possible + */ +#define p4_config_pack_escr(v) (((u64)(v)) << 32) +#define p4_config_pack_cccr(v) (((u64)(v)) & 0xffffffffULL) +#define p4_config_unpack_escr(v) (((u64)(v)) >> 32) +#define p4_config_unpack_cccr(v) (((u64)(v)) & 0xffffffffULL) + +#define p4_config_unpack_emask(v) \ + ({ \ + u32 t = p4_config_unpack_escr((v)); \ + t &= P4_EVNTSEL_EVENTMASK_MASK; \ + t >>= P4_EVNTSEL_EVENTMASK_SHIFT; \ + t; \ + }) + +#define P4_CONFIG_HT_SHIFT 63 +#define P4_CONFIG_HT (1ULL << P4_CONFIG_HT_SHIFT) + +static inline u32 p4_config_unpack_opcode(u64 config) +{ + u32 e, s; + + /* + * we don't care about HT presence here since + * event opcode doesn't depend on it + */ + e = (p4_config_unpack_escr(config) & P4_EVNTSEL_EVENT_MASK) >> P4_EVNTSEL_EVENT_SHIFT; + s = (p4_config_unpack_cccr(config) & P4_CCCR_ESCR_SELECT_MASK) >> P4_CCCR_ESCR_SELECT_SHIFT; + + return P4_EVENT_PACK(e, s); +} + +static inline bool p4_is_event_cascaded(u64 config) +{ + u32 cccr = p4_config_unpack_cccr(config); + return !!(cccr & P4_CCCR_CASCADE); +} + +static inline int p4_ht_config_thread(u64 config) +{ + return !!(config & P4_CONFIG_HT); +} + +static inline u64 p4_set_ht_bit(u64 config) +{ + return config | P4_CONFIG_HT; +} + +static inline u64 p4_clear_ht_bit(u64 config) +{ + return config & ~P4_CONFIG_HT; +} + +static inline int p4_ht_active(void) +{ +#ifdef CONFIG_SMP + return smp_num_siblings > 1; +#endif + return 0; +} + +static inline int p4_ht_thread(int cpu) +{ +#ifdef CONFIG_SMP + if (smp_num_siblings == 2) + return cpu != cpumask_first(__get_cpu_var(cpu_sibling_map)); +#endif + return 0; +} + +static inline int p4_should_swap_ts(u64 config, int cpu) +{ + return p4_ht_config_thread(config) ^ p4_ht_thread(cpu); +} + +static inline u32 p4_default_cccr_conf(int cpu) +{ + /* + * Note that P4_CCCR_THREAD_ANY is "required" on + * non-HT machines (on HT machines we count TS events + * regardless the state of second logical processor + */ + u32 cccr = P4_CCCR_THREAD_ANY; + + if (!p4_ht_thread(cpu)) + cccr |= P4_CCCR_OVF_PMI_T0; + else + cccr |= P4_CCCR_OVF_PMI_T1; + + return cccr; +} + +static inline u32 p4_default_escr_conf(int cpu, int exclude_os, int exclude_usr) +{ + u32 escr = 0; + + if (!p4_ht_thread(cpu)) { + if (!exclude_os) + escr |= P4_EVNTSEL_T0_OS; + if (!exclude_usr) + escr |= P4_EVNTSEL_T0_USR; + } else { + if (!exclude_os) + escr |= P4_EVNTSEL_T1_OS; + if (!exclude_usr) + escr |= P4_EVNTSEL_T1_USR; + } + + return escr; +} + +/* + * Comments below the event represent ESCR restriction + * for this event and counter index per ESCR + * + * MSR_P4_IQ_ESCR0 and MSR_P4_IQ_ESCR1 are available only on early + * processor builds (family 0FH, models 01H-02H). These MSRs + * are not available on later versions, so that we don't use + * them completely + * + * Also note that CCCR1 do not have P4_CCCR_ENABLE bit properly + * working so that we should not use this CCCR and respective + * counter as result + */ +#define P4_TC_DELIVER_MODE P4_EVENT_PACK(0x01, 0x01) + /* + * MSR_P4_TC_ESCR0: 4, 5 + * MSR_P4_TC_ESCR1: 6, 7 + */ + +#define P4_BPU_FETCH_REQUEST P4_EVENT_PACK(0x03, 0x00) + /* + * MSR_P4_BPU_ESCR0: 0, 1 + * MSR_P4_BPU_ESCR1: 2, 3 + */ + +#define P4_ITLB_REFERENCE P4_EVENT_PACK(0x18, 0x03) + /* + * MSR_P4_ITLB_ESCR0: 0, 1 + * MSR_P4_ITLB_ESCR1: 2, 3 + */ + +#define P4_MEMORY_CANCEL P4_EVENT_PACK(0x02, 0x05) + /* + * MSR_P4_DAC_ESCR0: 8, 9 + * MSR_P4_DAC_ESCR1: 10, 11 + */ + +#define P4_MEMORY_COMPLETE P4_EVENT_PACK(0x08, 0x02) + /* + * MSR_P4_SAAT_ESCR0: 8, 9 + * MSR_P4_SAAT_ESCR1: 10, 11 + */ + +#define P4_LOAD_PORT_REPLAY P4_EVENT_PACK(0x04, 0x02) + /* + * MSR_P4_SAAT_ESCR0: 8, 9 + * MSR_P4_SAAT_ESCR1: 10, 11 + */ + +#define P4_STORE_PORT_REPLAY P4_EVENT_PACK(0x05, 0x02) + /* + * MSR_P4_SAAT_ESCR0: 8, 9 + * MSR_P4_SAAT_ESCR1: 10, 11 + */ + +#define P4_MOB_LOAD_REPLAY P4_EVENT_PACK(0x03, 0x02) + /* + * MSR_P4_MOB_ESCR0: 0, 1 + * MSR_P4_MOB_ESCR1: 2, 3 + */ + +#define P4_PAGE_WALK_TYPE P4_EVENT_PACK(0x01, 0x04) + /* + * MSR_P4_PMH_ESCR0: 0, 1 + * MSR_P4_PMH_ESCR1: 2, 3 + */ + +#define P4_BSQ_CACHE_REFERENCE P4_EVENT_PACK(0x0c, 0x07) + /* + * MSR_P4_BSU_ESCR0: 0, 1 + * MSR_P4_BSU_ESCR1: 2, 3 + */ + +#define P4_IOQ_ALLOCATION P4_EVENT_PACK(0x03, 0x06) + /* + * MSR_P4_FSB_ESCR0: 0, 1 + * MSR_P4_FSB_ESCR1: 2, 3 + */ + +#define P4_IOQ_ACTIVE_ENTRIES P4_EVENT_PACK(0x1a, 0x06) + /* + * MSR_P4_FSB_ESCR1: 2, 3 + */ + +#define P4_FSB_DATA_ACTIVITY P4_EVENT_PACK(0x17, 0x06) + /* + * MSR_P4_FSB_ESCR0: 0, 1 + * MSR_P4_FSB_ESCR1: 2, 3 + */ + +#define P4_BSQ_ALLOCATION P4_EVENT_PACK(0x05, 0x07) + /* + * MSR_P4_BSU_ESCR0: 0, 1 + */ + +#define P4_BSQ_ACTIVE_ENTRIES P4_EVENT_PACK(0x06, 0x07) + /* + * MSR_P4_BSU_ESCR1: 2, 3 + */ + +#define P4_SSE_INPUT_ASSIST P4_EVENT_PACK(0x34, 0x01) + /* + * MSR_P4_FIRM_ESCR: 8, 9 + * MSR_P4_FIRM_ESCR: 10, 11 + */ + +#define P4_PACKED_SP_UOP P4_EVENT_PACK(0x08, 0x01) + /* + * MSR_P4_FIRM_ESCR0: 8, 9 + * MSR_P4_FIRM_ESCR1: 10, 11 + */ + +#define P4_PACKED_DP_UOP P4_EVENT_PACK(0x0c, 0x01) + /* + * MSR_P4_FIRM_ESCR0: 8, 9 + * MSR_P4_FIRM_ESCR1: 10, 11 + */ + +#define P4_SCALAR_SP_UOP P4_EVENT_PACK(0x0a, 0x01) + /* + * MSR_P4_FIRM_ESCR0: 8, 9 + * MSR_P4_FIRM_ESCR1: 10, 11 + */ + +#define P4_SCALAR_DP_UOP P4_EVENT_PACK(0x0e, 0x01) + /* + * MSR_P4_FIRM_ESCR0: 8, 9 + * MSR_P4_FIRM_ESCR1: 10, 11 + */ + +#define P4_64BIT_MMX_UOP P4_EVENT_PACK(0x02, 0x01) + /* + * MSR_P4_FIRM_ESCR0: 8, 9 + * MSR_P4_FIRM_ESCR1: 10, 11 + */ + +#define P4_128BIT_MMX_UOP P4_EVENT_PACK(0x1a, 0x01) + /* + * MSR_P4_FIRM_ESCR0: 8, 9 + * MSR_P4_FIRM_ESCR1: 10, 11 + */ + +#define P4_X87_FP_UOP P4_EVENT_PACK(0x04, 0x01) + /* + * MSR_P4_FIRM_ESCR0: 8, 9 + * MSR_P4_FIRM_ESCR1: 10, 11 + */ + +#define P4_TC_MISC P4_EVENT_PACK(0x06, 0x01) + /* + * MSR_P4_TC_ESCR0: 4, 5 + * MSR_P4_TC_ESCR1: 6, 7 + */ + +#define P4_GLOBAL_POWER_EVENTS P4_EVENT_PACK(0x13, 0x06) + /* + * MSR_P4_FSB_ESCR0: 0, 1 + * MSR_P4_FSB_ESCR1: 2, 3 + */ + +#define P4_TC_MS_XFER P4_EVENT_PACK(0x05, 0x00) + /* + * MSR_P4_MS_ESCR0: 4, 5 + * MSR_P4_MS_ESCR1: 6, 7 + */ + +#define P4_UOP_QUEUE_WRITES P4_EVENT_PACK(0x09, 0x00) + /* + * MSR_P4_MS_ESCR0: 4, 5 + * MSR_P4_MS_ESCR1: 6, 7 + */ + +#define P4_RETIRED_MISPRED_BRANCH_TYPE P4_EVENT_PACK(0x05, 0x02) + /* + * MSR_P4_TBPU_ESCR0: 4, 5 + * MSR_P4_TBPU_ESCR0: 6, 7 + */ + +#define P4_RETIRED_BRANCH_TYPE P4_EVENT_PACK(0x04, 0x02) + /* + * MSR_P4_TBPU_ESCR0: 4, 5 + * MSR_P4_TBPU_ESCR0: 6, 7 + */ + +#define P4_RESOURCE_STALL P4_EVENT_PACK(0x01, 0x01) + /* + * MSR_P4_ALF_ESCR0: 12, 13, 16 + * MSR_P4_ALF_ESCR1: 14, 15, 17 + */ + +#define P4_WC_BUFFER P4_EVENT_PACK(0x05, 0x05) + /* + * MSR_P4_DAC_ESCR0: 8, 9 + * MSR_P4_DAC_ESCR1: 10, 11 + */ + +#define P4_B2B_CYCLES P4_EVENT_PACK(0x16, 0x03) + /* + * MSR_P4_FSB_ESCR0: 0, 1 + * MSR_P4_FSB_ESCR1: 2, 3 + */ + +#define P4_BNR P4_EVENT_PACK(0x08, 0x03) + /* + * MSR_P4_FSB_ESCR0: 0, 1 + * MSR_P4_FSB_ESCR1: 2, 3 + */ + +#define P4_SNOOP P4_EVENT_PACK(0x06, 0x03) + /* + * MSR_P4_FSB_ESCR0: 0, 1 + * MSR_P4_FSB_ESCR1: 2, 3 + */ + +#define P4_RESPONSE P4_EVENT_PACK(0x04, 0x03) + /* + * MSR_P4_FSB_ESCR0: 0, 1 + * MSR_P4_FSB_ESCR1: 2, 3 + */ + +#define P4_FRONT_END_EVENT P4_EVENT_PACK(0x08, 0x05) + /* + * MSR_P4_CRU_ESCR2: 12, 13, 16 + * MSR_P4_CRU_ESCR3: 14, 15, 17 + */ + +#define P4_EXECUTION_EVENT P4_EVENT_PACK(0x0c, 0x05) + /* + * MSR_P4_CRU_ESCR2: 12, 13, 16 + * MSR_P4_CRU_ESCR3: 14, 15, 17 + */ + +#define P4_REPLAY_EVENT P4_EVENT_PACK(0x09, 0x05) + /* + * MSR_P4_CRU_ESCR2: 12, 13, 16 + * MSR_P4_CRU_ESCR3: 14, 15, 17 + */ + +#define P4_INSTR_RETIRED P4_EVENT_PACK(0x02, 0x04) + /* + * MSR_P4_CRU_ESCR2: 12, 13, 16 + * MSR_P4_CRU_ESCR3: 14, 15, 17 + */ + +#define P4_UOPS_RETIRED P4_EVENT_PACK(0x01, 0x04) + /* + * MSR_P4_CRU_ESCR2: 12, 13, 16 + * MSR_P4_CRU_ESCR3: 14, 15, 17 + */ + +#define P4_UOP_TYPE P4_EVENT_PACK(0x02, 0x02) + /* + * MSR_P4_RAT_ESCR0: 12, 13, 16 + * MSR_P4_RAT_ESCR1: 14, 15, 17 + */ + +#define P4_BRANCH_RETIRED P4_EVENT_PACK(0x06, 0x05) + /* + * MSR_P4_CRU_ESCR2: 12, 13, 16 + * MSR_P4_CRU_ESCR3: 14, 15, 17 + */ + +#define P4_MISPRED_BRANCH_RETIRED P4_EVENT_PACK(0x03, 0x04) + /* + * MSR_P4_CRU_ESCR0: 12, 13, 16 + * MSR_P4_CRU_ESCR1: 14, 15, 17 + */ + +#define P4_X87_ASSIST P4_EVENT_PACK(0x03, 0x05) + /* + * MSR_P4_CRU_ESCR2: 12, 13, 16 + * MSR_P4_CRU_ESCR3: 14, 15, 17 + */ + +#define P4_MACHINE_CLEAR P4_EVENT_PACK(0x02, 0x05) + /* + * MSR_P4_CRU_ESCR2: 12, 13, 16 + * MSR_P4_CRU_ESCR3: 14, 15, 17 + */ + +#define P4_INSTR_COMPLETED P4_EVENT_PACK(0x07, 0x04) + /* + * MSR_P4_CRU_ESCR0: 12, 13, 16 + * MSR_P4_CRU_ESCR1: 14, 15, 17 + */ + +/* + * a caller should use P4_EVENT_ATTR helper to + * pick the attribute needed, for example + * + * P4_EVENT_ATTR(P4_TC_DELIVER_MODE, DD) + */ +enum P4_EVENTS_ATTR { + P4_MAKE_EVENT_ATTR(P4_TC_DELIVER_MODE, DD, 0), + P4_MAKE_EVENT_ATTR(P4_TC_DELIVER_MODE, DB, 1), + P4_MAKE_EVENT_ATTR(P4_TC_DELIVER_MODE, DI, 2), + P4_MAKE_EVENT_ATTR(P4_TC_DELIVER_MODE, BD, 3), + P4_MAKE_EVENT_ATTR(P4_TC_DELIVER_MODE, BB, 4), + P4_MAKE_EVENT_ATTR(P4_TC_DELIVER_MODE, BI, 5), + P4_MAKE_EVENT_ATTR(P4_TC_DELIVER_MODE, ID, 6), + + P4_MAKE_EVENT_ATTR(P4_BPU_FETCH_REQUEST, TCMISS, 0), + + P4_MAKE_EVENT_ATTR(P4_ITLB_REFERENCE, HIT, 0), + P4_MAKE_EVENT_ATTR(P4_ITLB_REFERENCE, MISS, 1), + P4_MAKE_EVENT_ATTR(P4_ITLB_REFERENCE, HIT_UK, 2), + + P4_MAKE_EVENT_ATTR(P4_MEMORY_CANCEL, ST_RB_FULL, 2), + P4_MAKE_EVENT_ATTR(P4_MEMORY_CANCEL, 64K_CONF, 3), + + P4_MAKE_EVENT_ATTR(P4_MEMORY_COMPLETE, LSC, 0), + P4_MAKE_EVENT_ATTR(P4_MEMORY_COMPLETE, SSC, 1), + + P4_MAKE_EVENT_ATTR(P4_LOAD_PORT_REPLAY, SPLIT_LD, 1), + + P4_MAKE_EVENT_ATTR(P4_STORE_PORT_REPLAY, SPLIT_ST, 1), + + P4_MAKE_EVENT_ATTR(P4_MOB_LOAD_REPLAY, NO_STA, 1), + P4_MAKE_EVENT_ATTR(P4_MOB_LOAD_REPLAY, NO_STD, 3), + P4_MAKE_EVENT_ATTR(P4_MOB_LOAD_REPLAY, PARTIAL_DATA, 4), + P4_MAKE_EVENT_ATTR(P4_MOB_LOAD_REPLAY, UNALGN_ADDR, 5), + + P4_MAKE_EVENT_ATTR(P4_PAGE_WALK_TYPE, DTMISS, 0), + P4_MAKE_EVENT_ATTR(P4_PAGE_WALK_TYPE, ITMISS, 1), + + P4_MAKE_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_2ndL_HITS, 0), + P4_MAKE_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_2ndL_HITE, 1), + P4_MAKE_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_2ndL_HITM, 2), + P4_MAKE_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_3rdL_HITS, 3), + P4_MAKE_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_3rdL_HITE, 4), + P4_MAKE_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_3rdL_HITM, 5), + P4_MAKE_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_2ndL_MISS, 8), + P4_MAKE_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_3rdL_MISS, 9), + P4_MAKE_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, WR_2ndL_MISS, 10), + + P4_MAKE_EVENT_ATTR(P4_IOQ_ALLOCATION, DEFAULT, 0), + P4_MAKE_EVENT_ATTR(P4_IOQ_ALLOCATION, ALL_READ, 5), + P4_MAKE_EVENT_ATTR(P4_IOQ_ALLOCATION, ALL_WRITE, 6), + P4_MAKE_EVENT_ATTR(P4_IOQ_ALLOCATION, MEM_UC, 7), + P4_MAKE_EVENT_ATTR(P4_IOQ_ALLOCATION, MEM_WC, 8), + P4_MAKE_EVENT_ATTR(P4_IOQ_ALLOCATION, MEM_WT, 9), + P4_MAKE_EVENT_ATTR(P4_IOQ_ALLOCATION, MEM_WP, 10), + P4_MAKE_EVENT_ATTR(P4_IOQ_ALLOCATION, MEM_WB, 11), + P4_MAKE_EVENT_ATTR(P4_IOQ_ALLOCATION, OWN, 13), + P4_MAKE_EVENT_ATTR(P4_IOQ_ALLOCATION, OTHER, 14), + P4_MAKE_EVENT_ATTR(P4_IOQ_ALLOCATION, PREFETCH, 15), + + P4_MAKE_EVENT_ATTR(P4_IOQ_ACTIVE_ENTRIES, DEFAULT, 0), + P4_MAKE_EVENT_ATTR(P4_IOQ_ACTIVE_ENTRIES, ALL_READ, 5), + P4_MAKE_EVENT_ATTR(P4_IOQ_ACTIVE_ENTRIES, ALL_WRITE, 6), + P4_MAKE_EVENT_ATTR(P4_IOQ_ACTIVE_ENTRIES, MEM_UC, 7), + P4_MAKE_EVENT_ATTR(P4_IOQ_ACTIVE_ENTRIES, MEM_WC, 8), + P4_MAKE_EVENT_ATTR(P4_IOQ_ACTIVE_ENTRIES, MEM_WT, 9), + P4_MAKE_EVENT_ATTR(P4_IOQ_ACTIVE_ENTRIES, MEM_WP, 10), + P4_MAKE_EVENT_ATTR(P4_IOQ_ACTIVE_ENTRIES, MEM_WB, 11), + P4_MAKE_EVENT_ATTR(P4_IOQ_ACTIVE_ENTRIES, OWN, 13), + P4_MAKE_EVENT_ATTR(P4_IOQ_ACTIVE_ENTRIES, OTHER, 14), + P4_MAKE_EVENT_ATTR(P4_IOQ_ACTIVE_ENTRIES, PREFETCH, 15), + + P4_MAKE_EVENT_ATTR(P4_FSB_DATA_ACTIVITY, DRDY_DRV, 0), + P4_MAKE_EVENT_ATTR(P4_FSB_DATA_ACTIVITY, DRDY_OWN, 1), + P4_MAKE_EVENT_ATTR(P4_FSB_DATA_ACTIVITY, DRDY_OTHER, 2), + P4_MAKE_EVENT_ATTR(P4_FSB_DATA_ACTIVITY, DBSY_DRV, 3), + P4_MAKE_EVENT_ATTR(P4_FSB_DATA_ACTIVITY, DBSY_OWN, 4), + P4_MAKE_EVENT_ATTR(P4_FSB_DATA_ACTIVITY, DBSY_OTHER, 5), + + P4_MAKE_EVENT_ATTR(P4_BSQ_ALLOCATION, REQ_TYPE0, 0), + P4_MAKE_EVENT_ATTR(P4_BSQ_ALLOCATION, REQ_TYPE1, 1), + P4_MAKE_EVENT_ATTR(P4_BSQ_ALLOCATION, REQ_LEN0, 2), + P4_MAKE_EVENT_ATTR(P4_BSQ_ALLOCATION, REQ_LEN1, 3), + P4_MAKE_EVENT_ATTR(P4_BSQ_ALLOCATION, REQ_IO_TYPE, 5), + P4_MAKE_EVENT_ATTR(P4_BSQ_ALLOCATION, REQ_LOCK_TYPE, 6), + P4_MAKE_EVENT_ATTR(P4_BSQ_ALLOCATION, REQ_CACHE_TYPE, 7), + P4_MAKE_EVENT_ATTR(P4_BSQ_ALLOCATION, REQ_SPLIT_TYPE, 8), + P4_MAKE_EVENT_ATTR(P4_BSQ_ALLOCATION, REQ_DEM_TYPE, 9), + P4_MAKE_EVENT_ATTR(P4_BSQ_ALLOCATION, REQ_ORD_TYPE, 10), + P4_MAKE_EVENT_ATTR(P4_BSQ_ALLOCATION, MEM_TYPE0, 11), + P4_MAKE_EVENT_ATTR(P4_BSQ_ALLOCATION, MEM_TYPE1, 12), + P4_MAKE_EVENT_ATTR(P4_BSQ_ALLOCATION, MEM_TYPE2, 13), + + P4_MAKE_EVENT_ATTR(P4_BSQ_ACTIVE_ENTRIES, REQ_TYPE0, 0), + P4_MAKE_EVENT_ATTR(P4_BSQ_ACTIVE_ENTRIES, REQ_TYPE1, 1), + P4_MAKE_EVENT_ATTR(P4_BSQ_ACTIVE_ENTRIES, REQ_LEN0, 2), + P4_MAKE_EVENT_ATTR(P4_BSQ_ACTIVE_ENTRIES, REQ_LEN1, 3), + P4_MAKE_EVENT_ATTR(P4_BSQ_ACTIVE_ENTRIES, REQ_IO_TYPE, 5), + P4_MAKE_EVENT_ATTR(P4_BSQ_ACTIVE_ENTRIES, REQ_LOCK_TYPE, 6), + P4_MAKE_EVENT_ATTR(P4_BSQ_ACTIVE_ENTRIES, REQ_CACHE_TYPE, 7), + P4_MAKE_EVENT_ATTR(P4_BSQ_ACTIVE_ENTRIES, REQ_SPLIT_TYPE, 8), + P4_MAKE_EVENT_ATTR(P4_BSQ_ACTIVE_ENTRIES, REQ_DEM_TYPE, 9), + P4_MAKE_EVENT_ATTR(P4_BSQ_ACTIVE_ENTRIES, REQ_ORD_TYPE, 10), + P4_MAKE_EVENT_ATTR(P4_BSQ_ACTIVE_ENTRIES, MEM_TYPE0, 11), + P4_MAKE_EVENT_ATTR(P4_BSQ_ACTIVE_ENTRIES, MEM_TYPE1, 12), + P4_MAKE_EVENT_ATTR(P4_BSQ_ACTIVE_ENTRIES, MEM_TYPE2, 13), + + P4_MAKE_EVENT_ATTR(P4_SSE_INPUT_ASSIST, ALL, 15), + + P4_MAKE_EVENT_ATTR(P4_PACKED_SP_UOP, ALL, 15), + + P4_MAKE_EVENT_ATTR(P4_PACKED_DP_UOP, ALL, 15), + + P4_MAKE_EVENT_ATTR(P4_SCALAR_SP_UOP, ALL, 15), + + P4_MAKE_EVENT_ATTR(P4_SCALAR_DP_UOP, ALL, 15), + + P4_MAKE_EVENT_ATTR(P4_64BIT_MMX_UOP, ALL, 15), + + P4_MAKE_EVENT_ATTR(P4_128BIT_MMX_UOP, ALL, 15), + + P4_MAKE_EVENT_ATTR(P4_X87_FP_UOP, ALL, 15), + + P4_MAKE_EVENT_ATTR(P4_TC_MISC, FLUSH, 4), + + P4_MAKE_EVENT_ATTR(P4_GLOBAL_POWER_EVENTS, RUNNING, 0), + + P4_MAKE_EVENT_ATTR(P4_TC_MS_XFER, CISC, 0), + + P4_MAKE_EVENT_ATTR(P4_UOP_QUEUE_WRITES, FROM_TC_BUILD, 0), + P4_MAKE_EVENT_ATTR(P4_UOP_QUEUE_WRITES, FROM_TC_DELIVER, 1), + P4_MAKE_EVENT_ATTR(P4_UOP_QUEUE_WRITES, FROM_ROM, 2), + + P4_MAKE_EVENT_ATTR(P4_RETIRED_MISPRED_BRANCH_TYPE, CONDITIONAL, 1), + P4_MAKE_EVENT_ATTR(P4_RETIRED_MISPRED_BRANCH_TYPE, CALL, 2), + P4_MAKE_EVENT_ATTR(P4_RETIRED_MISPRED_BRANCH_TYPE, RETURN, 3), + P4_MAKE_EVENT_ATTR(P4_RETIRED_MISPRED_BRANCH_TYPE, INDIRECT, 4), + + P4_MAKE_EVENT_ATTR(P4_RETIRED_BRANCH_TYPE, CONDITIONAL, 1), + P4_MAKE_EVENT_ATTR(P4_RETIRED_BRANCH_TYPE, CALL, 2), + P4_MAKE_EVENT_ATTR(P4_RETIRED_BRANCH_TYPE, RETURN, 3), + P4_MAKE_EVENT_ATTR(P4_RETIRED_BRANCH_TYPE, INDIRECT, 4), + + P4_MAKE_EVENT_ATTR(P4_RESOURCE_STALL, SBFULL, 5), + + P4_MAKE_EVENT_ATTR(P4_WC_BUFFER, WCB_EVICTS, 0), + P4_MAKE_EVENT_ATTR(P4_WC_BUFFER, WCB_FULL_EVICTS, 1), + + P4_MAKE_EVENT_ATTR(P4_FRONT_END_EVENT, NBOGUS, 0), + P4_MAKE_EVENT_ATTR(P4_FRONT_END_EVENT, BOGUS, 1), + + P4_MAKE_EVENT_ATTR(P4_EXECUTION_EVENT, NBOGUS0, 0), + P4_MAKE_EVENT_ATTR(P4_EXECUTION_EVENT, NBOGUS1, 1), + P4_MAKE_EVENT_ATTR(P4_EXECUTION_EVENT, NBOGUS2, 2), + P4_MAKE_EVENT_ATTR(P4_EXECUTION_EVENT, NBOGUS3, 3), + P4_MAKE_EVENT_ATTR(P4_EXECUTION_EVENT, BOGUS0, 4), + P4_MAKE_EVENT_ATTR(P4_EXECUTION_EVENT, BOGUS1, 5), + P4_MAKE_EVENT_ATTR(P4_EXECUTION_EVENT, BOGUS2, 6), + P4_MAKE_EVENT_ATTR(P4_EXECUTION_EVENT, BOGUS3, 7), + + P4_MAKE_EVENT_ATTR(P4_REPLAY_EVENT, NBOGUS, 0), + P4_MAKE_EVENT_ATTR(P4_REPLAY_EVENT, BOGUS, 1), + + P4_MAKE_EVENT_ATTR(P4_INSTR_RETIRED, NBOGUSNTAG, 0), + P4_MAKE_EVENT_ATTR(P4_INSTR_RETIRED, NBOGUSTAG, 1), + P4_MAKE_EVENT_ATTR(P4_INSTR_RETIRED, BOGUSNTAG, 2), + P4_MAKE_EVENT_ATTR(P4_INSTR_RETIRED, BOGUSTAG, 3), + + P4_MAKE_EVENT_ATTR(P4_UOPS_RETIRED, NBOGUS, 0), + P4_MAKE_EVENT_ATTR(P4_UOPS_RETIRED, BOGUS, 1), + + P4_MAKE_EVENT_ATTR(P4_UOP_TYPE, TAGLOADS, 1), + P4_MAKE_EVENT_ATTR(P4_UOP_TYPE, TAGSTORES, 2), + + P4_MAKE_EVENT_ATTR(P4_BRANCH_RETIRED, MMNP, 0), + P4_MAKE_EVENT_ATTR(P4_BRANCH_RETIRED, MMNM, 1), + P4_MAKE_EVENT_ATTR(P4_BRANCH_RETIRED, MMTP, 2), + P4_MAKE_EVENT_ATTR(P4_BRANCH_RETIRED, MMTM, 3), + + P4_MAKE_EVENT_ATTR(P4_MISPRED_BRANCH_RETIRED, NBOGUS, 0), + + P4_MAKE_EVENT_ATTR(P4_X87_ASSIST, FPSU, 0), + P4_MAKE_EVENT_ATTR(P4_X87_ASSIST, FPSO, 1), + P4_MAKE_EVENT_ATTR(P4_X87_ASSIST, POAO, 2), + P4_MAKE_EVENT_ATTR(P4_X87_ASSIST, POAU, 3), + P4_MAKE_EVENT_ATTR(P4_X87_ASSIST, PREA, 4), + + P4_MAKE_EVENT_ATTR(P4_MACHINE_CLEAR, CLEAR, 0), + P4_MAKE_EVENT_ATTR(P4_MACHINE_CLEAR, MOCLEAR, 1), + P4_MAKE_EVENT_ATTR(P4_MACHINE_CLEAR, SMCLEAR, 2), + + P4_MAKE_EVENT_ATTR(P4_INSTR_COMPLETED, NBOGUS, 0), + P4_MAKE_EVENT_ATTR(P4_INSTR_COMPLETED, BOGUS, 1), +}; + +#endif /* PERF_EVENT_P4_H */ diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index e24f637..e6a3f5f 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -190,6 +190,8 @@ struct x86_pmu { void (*enable_all)(void); void (*enable)(struct perf_event *); void (*disable)(struct perf_event *); + int (*hw_config)(struct perf_event_attr *attr, struct hw_perf_event *hwc); + int (*schedule_events)(struct cpu_hw_events *cpuc, int n, int *assign); unsigned eventsel; unsigned perfctr; u64 (*event_map)(int); @@ -415,6 +417,25 @@ set_ext_hw_attr(struct hw_perf_event *hwc, struct perf_event_attr *attr) return 0; } +static int x86_hw_config(struct perf_event_attr *attr, struct hw_perf_event *hwc) +{ + /* + * Generate PMC IRQs: + * (keep 'enabled' bit clear for now) + */ + hwc->config = ARCH_PERFMON_EVENTSEL_INT; + + /* + * Count user and OS events unless requested not to + */ + if (!attr->exclude_user) + hwc->config |= ARCH_PERFMON_EVENTSEL_USR; + if (!attr->exclude_kernel) + hwc->config |= ARCH_PERFMON_EVENTSEL_OS; + + return 0; +} + /* * Setup the hardware configuration for a given attr_type */ @@ -446,23 +467,13 @@ static int __hw_perf_event_init(struct perf_event *event) event->destroy = hw_perf_event_destroy; - /* - * Generate PMC IRQs: - * (keep 'enabled' bit clear for now) - */ - hwc->config = ARCH_PERFMON_EVENTSEL_INT; - hwc->idx = -1; hwc->last_cpu = -1; hwc->last_tag = ~0ULL; - /* - * Count user and OS events unless requested not to. - */ - if (!attr->exclude_user) - hwc->config |= ARCH_PERFMON_EVENTSEL_USR; - if (!attr->exclude_kernel) - hwc->config |= ARCH_PERFMON_EVENTSEL_OS; + /* Processor specifics */ + if (x86_pmu.hw_config(attr, hwc)) + return -EOPNOTSUPP; if (!hwc->sample_period) { hwc->sample_period = x86_pmu.max_period; @@ -517,7 +528,7 @@ static int __hw_perf_event_init(struct perf_event *event) return -EOPNOTSUPP; /* BTS is currently only allowed for user-mode. */ - if (hwc->config & ARCH_PERFMON_EVENTSEL_OS) + if (!attr->exclude_kernel) return -EOPNOTSUPP; } @@ -931,7 +942,7 @@ static int x86_pmu_enable(struct perf_event *event) if (n < 0) return n; - ret = x86_schedule_events(cpuc, n, assign); + ret = x86_pmu.schedule_events(cpuc, n, assign); if (ret) return ret; /* @@ -1263,7 +1274,7 @@ int hw_perf_group_sched_in(struct perf_event *leader, if (n0 < 0) return n0; - ret = x86_schedule_events(cpuc, n0, assign); + ret = x86_pmu.schedule_events(cpuc, n0, assign); if (ret) return ret; @@ -1313,6 +1324,7 @@ undo: #include "perf_event_amd.c" #include "perf_event_p6.c" +#include "perf_event_p4.c" #include "perf_event_intel_lbr.c" #include "perf_event_intel_ds.c" #include "perf_event_intel.c" @@ -1515,7 +1527,7 @@ static int validate_group(struct perf_event *event) fake_cpuc->n_events = n; - ret = x86_schedule_events(fake_cpuc, n, NULL); + ret = x86_pmu.schedule_events(fake_cpuc, n, NULL); out_free: kfree(fake_cpuc); diff --git a/arch/x86/kernel/cpu/perf_event_amd.c b/arch/x86/kernel/cpu/perf_event_amd.c index 573458f..358a8e3 100644 --- a/arch/x86/kernel/cpu/perf_event_amd.c +++ b/arch/x86/kernel/cpu/perf_event_amd.c @@ -363,6 +363,8 @@ static __initconst struct x86_pmu amd_pmu = { .enable_all = x86_pmu_enable_all, .enable = x86_pmu_enable_event, .disable = x86_pmu_disable_event, + .hw_config = x86_hw_config, + .schedule_events = x86_schedule_events, .eventsel = MSR_K7_EVNTSEL0, .perfctr = MSR_K7_PERFCTR0, .event_map = amd_pmu_event_map, diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 971dc6e..044b843 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -749,6 +749,8 @@ static __initconst struct x86_pmu core_pmu = { .enable_all = x86_pmu_enable_all, .enable = x86_pmu_enable_event, .disable = x86_pmu_disable_event, + .hw_config = x86_hw_config, + .schedule_events = x86_schedule_events, .eventsel = MSR_ARCH_PERFMON_EVENTSEL0, .perfctr = MSR_ARCH_PERFMON_PERFCTR0, .event_map = intel_pmu_event_map, @@ -786,6 +788,8 @@ static __initconst struct x86_pmu intel_pmu = { .enable_all = intel_pmu_enable_all, .enable = intel_pmu_enable_event, .disable = intel_pmu_disable_event, + .hw_config = x86_hw_config, + .schedule_events = x86_schedule_events, .eventsel = MSR_ARCH_PERFMON_EVENTSEL0, .perfctr = MSR_ARCH_PERFMON_PERFCTR0, .event_map = intel_pmu_event_map, @@ -839,12 +843,13 @@ static __init int intel_pmu_init(void) int version; if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) { - /* check for P6 processor family */ - if (boot_cpu_data.x86 == 6) { - return p6_pmu_init(); - } else { + switch (boot_cpu_data.x86) { + case 0x6: + return p6_pmu_init(); + case 0xf: + return p4_pmu_init(); + } return -ENODEV; - } } /* diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c new file mode 100644 index 0000000..381f593 --- /dev/null +++ b/arch/x86/kernel/cpu/perf_event_p4.c @@ -0,0 +1,607 @@ +/* + * Netburst Perfomance Events (P4, old Xeon) + * + * Copyright (C) 2010 Parallels, Inc., Cyrill Gorcunov + * Copyright (C) 2010 Intel Corporation, Lin Ming + * + * For licencing details see kernel-base/COPYING + */ + +#ifdef CONFIG_CPU_SUP_INTEL + +#include + +/* + * array indices: 0,1 - HT threads, used with HT enabled cpu + */ +struct p4_event_template { + u32 opcode; /* ESCR event + CCCR selector */ + u64 config; /* packed predefined bits */ + int dep; /* upstream dependency event index */ + unsigned int emask; /* ESCR EventMask */ + unsigned int escr_msr[2]; /* ESCR MSR for this event */ + unsigned int cntr[2]; /* counter index (offset) */ +}; + +struct p4_pmu_res { + /* maps hw_conf::idx into template for ESCR sake */ + struct p4_event_template *tpl[ARCH_P4_MAX_CCCR]; +}; + +static DEFINE_PER_CPU(struct p4_pmu_res, p4_pmu_config); + +/* + * WARN: CCCR1 doesn't have a working enable bit so try to not + * use it if possible + * + * Also as only we start to support raw events we will need to + * append _all_ P4_EVENT_PACK'ed events here + */ +struct p4_event_template p4_templates[] = { + [0] = { + .opcode = P4_UOP_TYPE, + .config = 0, + .dep = -1, + .emask = + P4_EVENT_ATTR(P4_UOP_TYPE, TAGLOADS) | + P4_EVENT_ATTR(P4_UOP_TYPE, TAGSTORES), + .escr_msr = { MSR_P4_RAT_ESCR0, MSR_P4_RAT_ESCR1 }, + .cntr = { 16, 17 }, + }, + [1] = { + .opcode = P4_GLOBAL_POWER_EVENTS, + .config = 0, + .dep = -1, + .emask = + P4_EVENT_ATTR(P4_GLOBAL_POWER_EVENTS, RUNNING), + .escr_msr = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 }, + .cntr = { 0, 2 }, + }, + [2] = { + .opcode = P4_INSTR_RETIRED, + .config = 0, + .dep = 0, /* needs front-end tagging */ + .emask = + P4_EVENT_ATTR(P4_INSTR_RETIRED, NBOGUSNTAG) | + P4_EVENT_ATTR(P4_INSTR_RETIRED, NBOGUSTAG) | + P4_EVENT_ATTR(P4_INSTR_RETIRED, BOGUSNTAG) | + P4_EVENT_ATTR(P4_INSTR_RETIRED, BOGUSTAG), + .escr_msr = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 }, + .cntr = { 12, 14 }, + }, + [3] = { + .opcode = P4_BSQ_CACHE_REFERENCE, + .config = 0, + .dep = -1, + .emask = + P4_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_2ndL_HITS) | + P4_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_2ndL_HITE) | + P4_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_2ndL_HITM) | + P4_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_3rdL_HITS) | + P4_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_3rdL_HITE) | + P4_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_3rdL_HITM), + .escr_msr = { MSR_P4_BSU_ESCR0, MSR_P4_BSU_ESCR1 }, + .cntr = { 0, 2 }, + }, + [4] = { + .opcode = P4_BSQ_CACHE_REFERENCE, + .config = 0, + .dep = -1, + .emask = + P4_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_2ndL_MISS) | + P4_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_3rdL_MISS) | + P4_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, WR_2ndL_MISS), + .escr_msr = { MSR_P4_BSU_ESCR0, MSR_P4_BSU_ESCR1 }, + .cntr = { 0, 3 }, + }, + [5] = { + .opcode = P4_RETIRED_BRANCH_TYPE, + .config = 0, + .dep = -1, + .emask = + P4_EVENT_ATTR(P4_RETIRED_BRANCH_TYPE, CONDITIONAL) | + P4_EVENT_ATTR(P4_RETIRED_BRANCH_TYPE, CALL) | + P4_EVENT_ATTR(P4_RETIRED_BRANCH_TYPE, RETURN) | + P4_EVENT_ATTR(P4_RETIRED_BRANCH_TYPE, INDIRECT), + .escr_msr = { MSR_P4_TBPU_ESCR0, MSR_P4_TBPU_ESCR1 }, + .cntr = { 4, 6 }, + }, + [6] = { + .opcode = P4_MISPRED_BRANCH_RETIRED, + .config = 0, + .dep = -1, + .emask = + P4_EVENT_ATTR(P4_MISPRED_BRANCH_RETIRED, NBOGUS), + .escr_msr = { MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR1 }, + .cntr = { 12, 14 }, + }, + [7] = { + .opcode = P4_FSB_DATA_ACTIVITY, + .config = p4_config_pack_cccr(P4_CCCR_EDGE | P4_CCCR_COMPARE), + .dep = -1, + .emask = + P4_EVENT_ATTR(P4_FSB_DATA_ACTIVITY, DRDY_DRV) | + P4_EVENT_ATTR(P4_FSB_DATA_ACTIVITY, DRDY_OWN), + .escr_msr = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 }, + .cntr = { 0, 2 }, + }, +}; + +static struct p4_event_template *p4_event_map[PERF_COUNT_HW_MAX] = { + /* non-halted CPU clocks */ + [PERF_COUNT_HW_CPU_CYCLES] = &p4_templates[1], + + /* retired instructions: dep on tagging the FSB */ + [PERF_COUNT_HW_INSTRUCTIONS] = &p4_templates[2], + + /* cache hits */ + [PERF_COUNT_HW_CACHE_REFERENCES] = &p4_templates[3], + + /* cache misses */ + [PERF_COUNT_HW_CACHE_MISSES] = &p4_templates[4], + + /* branch instructions retired */ + [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = &p4_templates[5], + + /* mispredicted branches retired */ + [PERF_COUNT_HW_BRANCH_MISSES] = &p4_templates[6], + + /* bus ready clocks (cpu is driving #DRDY_DRV\#DRDY_OWN): */ + [PERF_COUNT_HW_BUS_CYCLES] = &p4_templates[7], +}; + +static u64 p4_pmu_event_map(int hw_event) +{ + struct p4_event_template *tpl; + u64 config; + + if (hw_event > ARRAY_SIZE(p4_event_map)) { + printk_once(KERN_ERR "PMU: Incorrect event index\n"); + return 0; + } + tpl = p4_event_map[hw_event]; + + /* + * fill config up according to + * a predefined event template + */ + config = tpl->config; + config |= p4_config_pack_escr(P4_EVENT_UNPACK_EVENT(tpl->opcode) << P4_EVNTSEL_EVENT_SHIFT); + config |= p4_config_pack_escr(tpl->emask << P4_EVNTSEL_EVENTMASK_SHIFT); + config |= p4_config_pack_cccr(P4_EVENT_UNPACK_SELECTOR(tpl->opcode) << P4_CCCR_ESCR_SELECT_SHIFT); + + /* on HT machine we need a special bit */ + if (p4_ht_active() && p4_ht_thread(raw_smp_processor_id())) + config = p4_set_ht_bit(config); + + return config; +} + +/* + * Note that we still have 5 events (from global events SDM list) + * intersected in opcode+emask bits so we will need another + * scheme there do distinguish templates. + */ +static inline int p4_pmu_emask_match(unsigned int dst, unsigned int src) +{ + return dst & src; +} + +static struct p4_event_template *p4_pmu_template_lookup(u64 config) +{ + u32 opcode = p4_config_unpack_opcode(config); + unsigned int emask = p4_config_unpack_emask(config); + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(p4_templates); i++) { + if (opcode == p4_templates[i].opcode && + p4_pmu_emask_match(emask, p4_templates[i].emask)) + return &p4_templates[i]; + } + + return NULL; +} + +/* + * We don't control raw events so it's up to the caller + * to pass sane values (and we don't count the thread number + * on HT machine but allow HT-compatible specifics to be + * passed on) + */ +static u64 p4_pmu_raw_event(u64 hw_event) +{ + return hw_event & + (p4_config_pack_escr(P4_EVNTSEL_MASK_HT) | + p4_config_pack_cccr(P4_CCCR_MASK_HT)); +} + +static int p4_hw_config(struct perf_event_attr *attr, struct hw_perf_event *hwc) +{ + int cpu = raw_smp_processor_id(); + + /* + * the reason we use cpu that early is that: if we get scheduled + * first time on the same cpu -- we will not need swap thread + * specific flags in config (and will save some cpu cycles) + */ + + /* CCCR by default */ + hwc->config = p4_config_pack_cccr(p4_default_cccr_conf(cpu)); + + /* Count user and OS events unless not requested to */ + hwc->config |= p4_config_pack_escr(p4_default_escr_conf(cpu, attr->exclude_kernel, + attr->exclude_user)); + return 0; +} + +static inline void p4_pmu_clear_cccr_ovf(struct hw_perf_event *hwc) +{ + unsigned long dummy; + + rdmsrl(hwc->config_base + hwc->idx, dummy); + if (dummy & P4_CCCR_OVF) { + (void)checking_wrmsrl(hwc->config_base + hwc->idx, + ((u64)dummy) & ~P4_CCCR_OVF); + } +} + +static inline void p4_pmu_disable_event(struct perf_event *event) +{ + struct hw_perf_event *hwc = &event->hw; + + /* + * If event gets disabled while counter is in overflowed + * state we need to clear P4_CCCR_OVF, otherwise interrupt get + * asserted again and again + */ + (void)checking_wrmsrl(hwc->config_base + hwc->idx, + (u64)(p4_config_unpack_cccr(hwc->config)) & + ~P4_CCCR_ENABLE & ~P4_CCCR_OVF); +} + +static void p4_pmu_disable_all(void) +{ + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + int idx; + + for (idx = 0; idx < x86_pmu.num_events; idx++) { + struct perf_event *event = cpuc->events[idx]; + if (!test_bit(idx, cpuc->active_mask)) + continue; + p4_pmu_disable_event(event); + } +} + +static void p4_pmu_enable_event(struct perf_event *event) +{ + struct hw_perf_event *hwc = &event->hw; + int thread = p4_ht_config_thread(hwc->config); + u64 escr_conf = p4_config_unpack_escr(p4_clear_ht_bit(hwc->config)); + u64 escr_base; + struct p4_event_template *tpl; + struct p4_pmu_res *c; + + /* + * some preparation work from per-cpu private fields + * since we need to find out which ESCR to use + */ + c = &__get_cpu_var(p4_pmu_config); + tpl = c->tpl[hwc->idx]; + if (!tpl) { + pr_crit("%s: Wrong index: %d\n", __func__, hwc->idx); + return; + } + escr_base = (u64)tpl->escr_msr[thread]; + + /* + * - we dont support cascaded counters yet + * - and counter 1 is broken (erratum) + */ + WARN_ON_ONCE(p4_is_event_cascaded(hwc->config)); + WARN_ON_ONCE(hwc->idx == 1); + + (void)checking_wrmsrl(escr_base, escr_conf); + (void)checking_wrmsrl(hwc->config_base + hwc->idx, + (u64)(p4_config_unpack_cccr(hwc->config)) | P4_CCCR_ENABLE); +} + +static void p4_pmu_enable_all(void) +{ + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + int idx; + + for (idx = 0; idx < x86_pmu.num_events; idx++) { + struct perf_event *event = cpuc->events[idx]; + if (!test_bit(idx, cpuc->active_mask)) + continue; + p4_pmu_enable_event(event); + } +} + +static int p4_pmu_handle_irq(struct pt_regs *regs) +{ + struct perf_sample_data data; + struct cpu_hw_events *cpuc; + struct perf_event *event; + struct hw_perf_event *hwc; + int idx, handled = 0; + u64 val; + + data.addr = 0; + data.raw = NULL; + + cpuc = &__get_cpu_var(cpu_hw_events); + + for (idx = 0; idx < x86_pmu.num_events; idx++) { + + if (!test_bit(idx, cpuc->active_mask)) + continue; + + event = cpuc->events[idx]; + hwc = &event->hw; + + WARN_ON_ONCE(hwc->idx != idx); + + /* + * FIXME: Redundant call, actually not needed + * but just to check if we're screwed + */ + p4_pmu_clear_cccr_ovf(hwc); + + val = x86_perf_event_update(event); + if (val & (1ULL << (x86_pmu.event_bits - 1))) + continue; + + /* + * event overflow + */ + handled = 1; + data.period = event->hw.last_period; + + if (!x86_perf_event_set_period(event)) + continue; + if (perf_event_overflow(event, 1, &data, regs)) + p4_pmu_disable_event(event); + } + + if (handled) { + /* p4 quirk: unmask it again */ + apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED); + inc_irq_stat(apic_perf_irqs); + } + + return handled; +} + +/* + * swap thread specific fields according to a thread + * we are going to run on + */ +static void p4_pmu_swap_config_ts(struct hw_perf_event *hwc, int cpu) +{ + u32 escr, cccr; + + /* + * we either lucky and continue on same cpu or no HT support + */ + if (!p4_should_swap_ts(hwc->config, cpu)) + return; + + /* + * the event is migrated from an another logical + * cpu, so we need to swap thread specific flags + */ + + escr = p4_config_unpack_escr(hwc->config); + cccr = p4_config_unpack_cccr(hwc->config); + + if (p4_ht_thread(cpu)) { + cccr &= ~P4_CCCR_OVF_PMI_T0; + cccr |= P4_CCCR_OVF_PMI_T1; + if (escr & P4_EVNTSEL_T0_OS) { + escr &= ~P4_EVNTSEL_T0_OS; + escr |= P4_EVNTSEL_T1_OS; + } + if (escr & P4_EVNTSEL_T0_USR) { + escr &= ~P4_EVNTSEL_T0_USR; + escr |= P4_EVNTSEL_T1_USR; + } + hwc->config = p4_config_pack_escr(escr); + hwc->config |= p4_config_pack_cccr(cccr); + hwc->config |= P4_CONFIG_HT; + } else { + cccr &= ~P4_CCCR_OVF_PMI_T1; + cccr |= P4_CCCR_OVF_PMI_T0; + if (escr & P4_EVNTSEL_T1_OS) { + escr &= ~P4_EVNTSEL_T1_OS; + escr |= P4_EVNTSEL_T0_OS; + } + if (escr & P4_EVNTSEL_T1_USR) { + escr &= ~P4_EVNTSEL_T1_USR; + escr |= P4_EVNTSEL_T0_USR; + } + hwc->config = p4_config_pack_escr(escr); + hwc->config |= p4_config_pack_cccr(cccr); + hwc->config &= ~P4_CONFIG_HT; + } +} + +/* ESCRs are not sequential in memory so we need a map */ +static unsigned int p4_escr_map[ARCH_P4_TOTAL_ESCR] = { + MSR_P4_ALF_ESCR0, /* 0 */ + MSR_P4_ALF_ESCR1, /* 1 */ + MSR_P4_BPU_ESCR0, /* 2 */ + MSR_P4_BPU_ESCR1, /* 3 */ + MSR_P4_BSU_ESCR0, /* 4 */ + MSR_P4_BSU_ESCR1, /* 5 */ + MSR_P4_CRU_ESCR0, /* 6 */ + MSR_P4_CRU_ESCR1, /* 7 */ + MSR_P4_CRU_ESCR2, /* 8 */ + MSR_P4_CRU_ESCR3, /* 9 */ + MSR_P4_CRU_ESCR4, /* 10 */ + MSR_P4_CRU_ESCR5, /* 11 */ + MSR_P4_DAC_ESCR0, /* 12 */ + MSR_P4_DAC_ESCR1, /* 13 */ + MSR_P4_FIRM_ESCR0, /* 14 */ + MSR_P4_FIRM_ESCR1, /* 15 */ + MSR_P4_FLAME_ESCR0, /* 16 */ + MSR_P4_FLAME_ESCR1, /* 17 */ + MSR_P4_FSB_ESCR0, /* 18 */ + MSR_P4_FSB_ESCR1, /* 19 */ + MSR_P4_IQ_ESCR0, /* 20 */ + MSR_P4_IQ_ESCR1, /* 21 */ + MSR_P4_IS_ESCR0, /* 22 */ + MSR_P4_IS_ESCR1, /* 23 */ + MSR_P4_ITLB_ESCR0, /* 24 */ + MSR_P4_ITLB_ESCR1, /* 25 */ + MSR_P4_IX_ESCR0, /* 26 */ + MSR_P4_IX_ESCR1, /* 27 */ + MSR_P4_MOB_ESCR0, /* 28 */ + MSR_P4_MOB_ESCR1, /* 29 */ + MSR_P4_MS_ESCR0, /* 30 */ + MSR_P4_MS_ESCR1, /* 31 */ + MSR_P4_PMH_ESCR0, /* 32 */ + MSR_P4_PMH_ESCR1, /* 33 */ + MSR_P4_RAT_ESCR0, /* 34 */ + MSR_P4_RAT_ESCR1, /* 35 */ + MSR_P4_SAAT_ESCR0, /* 36 */ + MSR_P4_SAAT_ESCR1, /* 37 */ + MSR_P4_SSU_ESCR0, /* 38 */ + MSR_P4_SSU_ESCR1, /* 39 */ + MSR_P4_TBPU_ESCR0, /* 40 */ + MSR_P4_TBPU_ESCR1, /* 41 */ + MSR_P4_TC_ESCR0, /* 42 */ + MSR_P4_TC_ESCR1, /* 43 */ + MSR_P4_U2L_ESCR0, /* 44 */ + MSR_P4_U2L_ESCR1, /* 45 */ +}; + +static int p4_get_escr_idx(unsigned int addr) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(p4_escr_map); i++) { + if (addr == p4_escr_map[i]) + return i; + } + + return -1; +} + +static int p4_pmu_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign) +{ + unsigned long used_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; + unsigned long escr_mask[BITS_TO_LONGS(ARCH_P4_TOTAL_ESCR)]; + + struct hw_perf_event *hwc; + struct p4_event_template *tpl; + struct p4_pmu_res *c; + int cpu = raw_smp_processor_id(); + int escr_idx, thread, i, num; + + bitmap_zero(used_mask, X86_PMC_IDX_MAX); + bitmap_zero(escr_mask, ARCH_P4_TOTAL_ESCR); + + c = &__get_cpu_var(p4_pmu_config); + /* + * Firstly find out which resource events are going + * to use, if ESCR+CCCR tuple is already borrowed + * then get out of here + */ + for (i = 0, num = n; i < n; i++, num--) { + hwc = &cpuc->event_list[i]->hw; + tpl = p4_pmu_template_lookup(hwc->config); + if (!tpl) + goto done; + thread = p4_ht_thread(cpu); + escr_idx = p4_get_escr_idx(tpl->escr_msr[thread]); + if (escr_idx == -1) + goto done; + + /* already allocated and remains on the same cpu */ + if (hwc->idx != -1 && !p4_should_swap_ts(hwc->config, cpu)) { + if (assign) + assign[i] = hwc->idx; + /* upstream dependent event */ + if (unlikely(tpl->dep != -1)) + printk_once(KERN_WARNING "PMU: Dep events are " + "not implemented yet\n"); + goto reserve; + } + + /* it may be already borrowed */ + if (test_bit(tpl->cntr[thread], used_mask) || + test_bit(escr_idx, escr_mask)) + goto done; + + /* + * ESCR+CCCR+COUNTERs are available to use lets swap + * thread specific bits, push assigned bits + * back and save template into per-cpu + * area (which will allow us to find out the ESCR + * to be used at moment of "enable event via real MSR") + */ + p4_pmu_swap_config_ts(hwc, cpu); + if (assign) { + assign[i] = tpl->cntr[thread]; + c->tpl[assign[i]] = tpl; + } +reserve: + set_bit(tpl->cntr[thread], used_mask); + set_bit(escr_idx, escr_mask); + } + +done: + return num ? -ENOSPC : 0; +} + +static __initconst struct x86_pmu p4_pmu = { + .name = "Netburst P4/Xeon", + .handle_irq = p4_pmu_handle_irq, + .disable_all = p4_pmu_disable_all, + .enable_all = p4_pmu_enable_all, + .enable = p4_pmu_enable_event, + .disable = p4_pmu_disable_event, + .eventsel = MSR_P4_BPU_CCCR0, + .perfctr = MSR_P4_BPU_PERFCTR0, + .event_map = p4_pmu_event_map, + .raw_event = p4_pmu_raw_event, + .max_events = ARRAY_SIZE(p4_event_map), + .get_event_constraints = x86_get_event_constraints, + /* + * IF HT disabled we may need to use all + * ARCH_P4_MAX_CCCR counters simulaneously + * though leave it restricted at moment assuming + * HT is on + */ + .num_events = ARCH_P4_MAX_CCCR, + .apic = 1, + .event_bits = 40, + .event_mask = (1ULL << 40) - 1, + .max_period = (1ULL << 39) - 1, + .hw_config = p4_hw_config, + .schedule_events = p4_pmu_schedule_events, +}; + +static __init int p4_pmu_init(void) +{ + unsigned int low, high; + + /* If we get stripped -- indexig fails */ + BUILD_BUG_ON(ARCH_P4_MAX_CCCR > X86_PMC_MAX_GENERIC); + + rdmsr(MSR_IA32_MISC_ENABLE, low, high); + if (!(low & (1 << 7))) { + pr_cont("unsupported Netburst CPU model %d ", + boot_cpu_data.x86_model); + return -ENODEV; + } + + pr_cont("Netburst events, "); + + x86_pmu = p4_pmu; + + return 0; +} + +#endif /* CONFIG_CPU_SUP_INTEL */ diff --git a/arch/x86/kernel/cpu/perf_event_p6.c b/arch/x86/kernel/cpu/perf_event_p6.c index a330485..6ff4d01d 100644 --- a/arch/x86/kernel/cpu/perf_event_p6.c +++ b/arch/x86/kernel/cpu/perf_event_p6.c @@ -109,6 +109,8 @@ static __initconst struct x86_pmu p6_pmu = { .enable_all = p6_pmu_enable_all, .enable = p6_pmu_enable_event, .disable = p6_pmu_disable_event, + .hw_config = x86_hw_config, + .schedule_events = x86_schedule_events, .eventsel = MSR_P6_EVNTSEL0, .perfctr = MSR_P6_PERFCTR0, .event_map = p6_pmu_event_map, -- cgit v0.10.2 From 6230f2c7ef01a69e2ba9370326572c287209d32a Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 11 Mar 2010 15:53:12 -0300 Subject: perf record: Mention paranoid sysctl when failing to create counter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [acme@mica linux-2.6-tip]$ perf record -a -f Fatal: Permission error - are you root? Consider tweaking /proc/sys/kernel/perf_event_paranoid. [acme@mica linux-2.6-tip]$ Suggested-by: Ingo Molnar Signed-off-by: Arnaldo Carvalho de Melo Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: <1268333592-30872-2-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 771533c..6e4a393 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -280,7 +280,8 @@ try_again: int err = errno; if (err == EPERM || err == EACCES) - die("Permission error - are you root?\n"); + die("Permission error - are you root?\n" + "\t Consider tweaking /proc/sys/kernel/perf_event_paranoid.\n"); else if (err == ENODEV && profile_cpu != -1) die("No such device - did you specify an out-of-range profile CPU?\n"); -- cgit v0.10.2 From 0b861225a5890f22445f08ca9cc7a87cff276ff7 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Fri, 12 Mar 2010 00:50:16 +0300 Subject: x86, perf: Fix NULL deref on not assigned x86_pmu In case of not assigned x86_pmu and software events NULL dereference may being hit via x86_pmu::schedule_events method. Fix it by checking if x86_pmu is initialized at all. Signed-off-by: Cyrill Gorcunov Cc: Lin Ming Cc: Arnaldo Carvalho de Melo Cc: Stephane Eranian Cc: Robert Richter Cc: Frederic Weisbecker Cc: Peter Zijlstra LKML-Reference: <20100311215016.GG25162@lenovo> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index e6a3f5f..5586a02 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -1269,6 +1269,9 @@ int hw_perf_group_sched_in(struct perf_event *leader, int assign[X86_PMC_IDX_MAX]; int n0, n1, ret; + if (!x86_pmu_initialized()) + return 0; + /* n0 = total number of events */ n0 = collect_events(cpuc, leader, true); if (n0 < 0) -- cgit v0.10.2 From fe2197b8bb2f318c1e0b0f589f24f781dd27d1f2 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 11 Mar 2010 20:12:40 -0300 Subject: perf symbols: Bump plt synthesizing warning debug level MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Arnaldo Carvalho de Melo Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: <1268349164-5822-1-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 323c0ae..75cd468 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -862,8 +862,8 @@ out_close: if (err == 0) return nr; out: - pr_warning("%s: problems reading %s PLT info.\n", - __func__, self->long_name); + pr_debug("%s: problems reading %s PLT info.\n", + __func__, self->long_name); return 0; } -- cgit v0.10.2 From 895f0edc3cd04a2a3de2c608ba20821b832a8abb Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 11 Mar 2010 20:12:41 -0300 Subject: perf top: Export get_window_dimensions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Will be used by the newt code too. Signed-off-by: Arnaldo Carvalho de Melo Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: <1268349164-5822-2-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index ec48223..57e232f 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -133,7 +133,7 @@ static inline struct symbol *sym_entry__symbol(struct sym_entry *self) return ((void *)self) + symbol_conf.priv_size; } -static void get_term_dimensions(struct winsize *ws) +void get_term_dimensions(struct winsize *ws) { char *s = getenv("LINES"); diff --git a/tools/perf/perf.h b/tools/perf/perf.h index 6fb379b..aa78615 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h @@ -1,6 +1,10 @@ #ifndef _PERF_PERF_H #define _PERF_PERF_H +struct winsize; + +void get_term_dimensions(struct winsize *ws); + #if defined(__i386__) #include "../../arch/x86/include/asm/unistd.h" #define rmb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory") -- cgit v0.10.2 From b4f5296f0eec2aa7061dfd8bb8c0744f095f9bd1 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 11 Mar 2010 20:12:42 -0300 Subject: perf tools: Use eprintf for pr_{err,warning,info} too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just like we do for pr_debug, so that we can have a single point where to redirect to the currently used output system, be it stdio or newt. Signed-off-by: Arnaldo Carvalho de Melo Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: <1268349164-5822-3-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h index c6c24c5..58720a1 100644 --- a/tools/perf/util/debug.h +++ b/tools/perf/util/debug.h @@ -7,8 +7,6 @@ extern int verbose; extern int dump_trace; -int eprintf(int level, - const char *fmt, ...) __attribute__((format(printf, 2, 3))); int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); void trace_event(event_t *event); diff --git a/tools/perf/util/include/linux/kernel.h b/tools/perf/util/include/linux/kernel.h index f261165..388ab1b 100644 --- a/tools/perf/util/include/linux/kernel.h +++ b/tools/perf/util/include/linux/kernel.h @@ -85,16 +85,19 @@ simple_strtoul(const char *nptr, char **endptr, int base) return strtoul(nptr, endptr, base); } +int eprintf(int level, + const char *fmt, ...) __attribute__((format(printf, 2, 3))); + #ifndef pr_fmt #define pr_fmt(fmt) fmt #endif #define pr_err(fmt, ...) \ - do { fprintf(stderr, pr_fmt(fmt), ##__VA_ARGS__); } while (0) + eprintf(0, pr_fmt(fmt), ##__VA_ARGS__) #define pr_warning(fmt, ...) \ - do { fprintf(stderr, pr_fmt(fmt), ##__VA_ARGS__); } while (0) + eprintf(0, pr_fmt(fmt), ##__VA_ARGS__) #define pr_info(fmt, ...) \ - do { fprintf(stderr, pr_fmt(fmt), ##__VA_ARGS__); } while (0) + eprintf(0, pr_fmt(fmt), ##__VA_ARGS__) #define pr_debug(fmt, ...) \ eprintf(1, pr_fmt(fmt), ##__VA_ARGS__) #define pr_debugN(n, fmt, ...) \ -- cgit v0.10.2 From dd2ee78dd8e4c6d6f1a333fd60c3dd27d1b07042 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 11 Mar 2010 20:12:43 -0300 Subject: perf tools: Add missing bytes printed in hist_entry__fprintf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need those to properly size the browser widht in the newt TUI. Signed-off-by: Arnaldo Carvalho de Melo Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: <1268349164-5822-4-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index bdcfd61..d43be34 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -455,11 +455,11 @@ static size_t hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self, return ret; } -static size_t hist_entry__fprintf(struct hist_entry *self, - struct perf_session *pair_session, - bool show_displacement, - long displacement, FILE *fp, - u64 session_total) +size_t hist_entry__fprintf(struct hist_entry *self, + struct perf_session *pair_session, + bool show_displacement, + long displacement, FILE *fp, + u64 session_total) { struct sort_entry *se; u64 count, total; @@ -485,9 +485,9 @@ static size_t hist_entry__fprintf(struct hist_entry *self, if (symbol_conf.show_nr_samples) { if (sep) - fprintf(fp, "%c%lld", *sep, count); + ret += fprintf(fp, "%c%lld", *sep, count); else - fprintf(fp, "%11lld", count); + ret += fprintf(fp, "%11lld", count); } if (pair_session) { @@ -518,9 +518,9 @@ static size_t hist_entry__fprintf(struct hist_entry *self, snprintf(bf, sizeof(bf), " "); if (sep) - fprintf(fp, "%c%s", *sep, bf); + ret += fprintf(fp, "%c%s", *sep, bf); else - fprintf(fp, "%6.6s", bf); + ret += fprintf(fp, "%6.6s", bf); } } @@ -528,7 +528,7 @@ static size_t hist_entry__fprintf(struct hist_entry *self, if (se->elide) continue; - fprintf(fp, "%s", sep ?: " "); + ret += fprintf(fp, "%s", sep ?: " "); ret += se->print(fp, self, se->width ? *se->width : 0); } @@ -544,8 +544,8 @@ static size_t hist_entry__fprintf(struct hist_entry *self, left_margin -= thread__comm_len(self->thread); } - hist_entry_callchain__fprintf(fp, self, session_total, - left_margin); + ret += hist_entry_callchain__fprintf(fp, self, session_total, + left_margin); } return ret; -- cgit v0.10.2 From f9224c5c944b60cf709db4adf1f5195264b8d194 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 11 Mar 2010 20:12:44 -0300 Subject: perf report: Implement initial UI using newt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Newt has widespread availability and provides a rather simple API as can be seen by the size of this patch. The work needed to support it will benefit other frontends too. In this initial patch it just checks if the output is a tty, if not it falls back to the previous behaviour, also if newt-devel/libnewt-dev is not installed the previous behaviour is maintaned. Pressing enter on a symbol will annotate it, ESC in the annotation window will return to the report symbol list. More work will be done to remove the special casing in color_fprintf, stop using fmemopen/FILE in the printing of hist_entries, etc. Also the annotation doesn't need to be done via spawning "perf annotate" and then browsing its output, we can do better by calling directly the builtin-annotate.c functions, that would then be moved to tools/perf/util/annotate.c and shared with perf top, etc But lets go by baby steps, this patch already improves perf usability by allowing to quickly do annotations on symbols from the report screen and provides a first experimentation with libnewt/TUI integration of tools. Tested on RHEL5 and Fedora12 X86_64 and on Debian PARISC64 to browse a perf.data file collected on a Fedora12 x86_64 box. Signed-off-by: Arnaldo Carvalho de Melo Cc: Avi Kivity Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: <1268349164-5822-5-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 8a8f52d..0abd25e 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -513,6 +513,14 @@ else LIB_OBJS += util/probe-finder.o endif +ifneq ($(shell sh -c "(echo '\#include '; echo 'int main(void) { newtInit(); newtCls(); return newtFinished(); }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -lnewt -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y) + msg := $(warning newt not found, disables TUI support. Please install newt-devel or libnewt-dev); + BASIC_CFLAGS += -DNO_NEWT_SUPPORT +else + EXTLIBS += -lnewt + LIB_OBJS += util/newt.o +endif + ifndef NO_LIBPERL PERL_EMBED_LDOPTS = `perl -MExtUtils::Embed -e ldopts 2>/dev/null` PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null` diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index f815de2..1f9f869 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -267,6 +267,7 @@ static int __cmd_report(void) int ret = -EINVAL; struct perf_session *session; struct rb_node *next; + const char *help = "For a higher level overview, try: perf report --sort comm,dso"; session = perf_session__new(input_name, O_RDONLY, force); if (session == NULL) @@ -301,30 +302,38 @@ static int __cmd_report(void) stats = rb_entry(next, struct event_stat_id, rb_node); perf_session__collapse_resort(&stats->hists); perf_session__output_resort(&stats->hists, stats->stats.total); - if (rb_first(&session->stats_by_id) == - rb_last(&session->stats_by_id)) - fprintf(stdout, "# Samples: %Ld\n#\n", - stats->stats.total); - else - fprintf(stdout, "# Samples: %Ld %s\n#\n", - stats->stats.total, - __event_name(stats->type, stats->config)); - perf_session__fprintf_hists(&stats->hists, NULL, false, stdout, + if (use_browser) + perf_session__browse_hists(&stats->hists, + stats->stats.total, help); + else { + if (rb_first(&session->stats_by_id) == + rb_last(&session->stats_by_id)) + fprintf(stdout, "# Samples: %Ld\n#\n", + stats->stats.total); + else + fprintf(stdout, "# Samples: %Ld %s\n#\n", + stats->stats.total, + __event_name(stats->type, stats->config)); + + perf_session__fprintf_hists(&stats->hists, NULL, false, stdout, stats->stats.total); - fprintf(stdout, "\n\n"); + fprintf(stdout, "\n\n"); + } + next = rb_next(&stats->rb_node); } - if (sort_order == default_sort_order && - parent_pattern == default_parent_pattern) - fprintf(stdout, "#\n# (For a higher level overview, try: perf report --sort comm,dso)\n#\n"); + if (!use_browser && sort_order == default_sort_order && + parent_pattern == default_parent_pattern) { + fprintf(stdout, "#\n# (%s)\n#\n", help); - if (show_threads) { - bool raw_printing_style = !strcmp(pretty_printing_style, "raw"); - perf_read_values_display(stdout, &show_threads_values, - raw_printing_style); - perf_read_values_destroy(&show_threads_values); + if (show_threads) { + bool style = !strcmp(pretty_printing_style, "raw"); + perf_read_values_display(stdout, &show_threads_values, + style); + perf_read_values_destroy(&show_threads_values); + } } out_delete: perf_session__delete(session); @@ -447,7 +456,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __used) { argc = parse_options(argc, argv, options, report_usage, 0); - setup_pager(); + setup_browser(); if (symbol__init() < 0) return -1; diff --git a/tools/perf/perf.c b/tools/perf/perf.c index 57cb107..9ff186b 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c @@ -265,6 +265,8 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv) if (status) return status & 0xff; + exit_browser(); + /* Somebody closed stdout? */ if (fstat(fileno(stdout), &st)) return 0; diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h index 918eb37..47b12a3 100644 --- a/tools/perf/util/cache.h +++ b/tools/perf/util/cache.h @@ -1,6 +1,7 @@ #ifndef __PERF_CACHE_H #define __PERF_CACHE_H +#include #include "util.h" #include "strbuf.h" #include "../perf.h" @@ -69,6 +70,19 @@ extern const char *pager_program; extern int pager_in_use(void); extern int pager_use_color; +extern bool use_browser; + +#ifdef NO_NEWT_SUPPORT +static inline void setup_browser(void) +{ + setup_pager(); +} +static inline void exit_browser(void) {} +#else +void setup_browser(void); +void exit_browser(void); +#endif + extern const char *editor_program; extern const char *excludes_file; diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c index e88bca5..9da0191 100644 --- a/tools/perf/util/color.c +++ b/tools/perf/util/color.c @@ -203,7 +203,10 @@ int color_fprintf(FILE *fp, const char *color, const char *fmt, ...) int r; va_start(args, fmt); - r = color_vfprintf(fp, color, fmt, args); + if (use_browser) + r = vfprintf(fp, fmt, args); + else + r = color_vfprintf(fp, color, fmt, args); va_end(args); return r; } diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c index 0905600..033d66d 100644 --- a/tools/perf/util/debug.c +++ b/tools/perf/util/debug.c @@ -6,6 +6,7 @@ #include #include +#include "cache.h" #include "color.h" #include "event.h" #include "debug.h" @@ -21,7 +22,10 @@ int eprintf(int level, const char *fmt, ...) if (verbose >= level) { va_start(args, fmt); - ret = vfprintf(stderr, fmt, args); + if (use_browser) + ret = browser__show_help(fmt, args); + else + ret = vfprintf(stderr, fmt, args); va_end(args); } diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h index 58720a1..03accb8 100644 --- a/tools/perf/util/debug.h +++ b/tools/perf/util/debug.h @@ -9,5 +9,6 @@ extern int dump_trace; int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); void trace_event(event_t *event); +int browser__show_help(const char *format, va_list ap); #endif /* __PERF_DEBUG_H */ diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 16f360c..fe366ce 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -18,6 +18,11 @@ struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists, u64 count, bool *hit); extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *); extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *); +size_t hist_entry__fprintf(struct hist_entry *self, + struct perf_session *pair_session, + bool show_displacement, + long displacement, FILE *fp, + u64 session_total); void hist_entry__free(struct hist_entry *); void perf_session__output_resort(struct rb_root *hists, u64 total_samples); diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c new file mode 100644 index 0000000..3d3a936 --- /dev/null +++ b/tools/perf/util/newt.c @@ -0,0 +1,194 @@ +#define _GNU_SOURCE +#include +#undef _GNU_SOURCE + +#include +#include + +#include "cache.h" +#include "hist.h" +#include "session.h" +#include "sort.h" +#include "symbol.h" + +static size_t hist_entry__append_browser(struct hist_entry *self, + newtComponent listbox, u64 total) +{ + char bf[1024]; + size_t len; + FILE *fp; + + if (symbol_conf.exclude_other && !self->parent) + return 0; + + fp = fmemopen(bf, sizeof(bf), "w"); + if (fp == NULL) + return 0; + + len = hist_entry__fprintf(self, NULL, false, 0, fp, total); + + fclose(fp); + newtListboxAppendEntry(listbox, bf, self); + return len; +} + +static void hist_entry__annotate_browser(struct hist_entry *self) +{ + FILE *fp; + struct winsize ws; + newtComponent form, listbox; + struct newtExitStruct es; + char *str; + size_t line_len, max_line_len = 0; + size_t max_usable_width; + char *line = NULL; + + if (self->sym == NULL) + return; + + if (asprintf(&str, "perf annotate %s | expand", self->sym->name) < 0) + return; + + fp = popen(str, "r"); + if (fp == NULL) + goto out_free_str; + + newtPushHelpLine("Press ESC to exit"); + get_term_dimensions(&ws); + listbox = newtListbox(0, 0, ws.ws_row - 5, NEWT_FLAG_SCROLL); + + while (!feof(fp)) { + if (getline(&line, &line_len, fp) < 0 || !line_len) + break; + while (line_len != 0 && isspace(line[line_len - 1])) + line[--line_len] = '\0'; + + if (line_len > max_line_len) + max_line_len = line_len; + newtListboxAppendEntry(listbox, line, NULL); + } + fclose(fp); + free(line); + + max_usable_width = ws.ws_col - 22; + if (max_line_len > max_usable_width) + max_line_len = max_usable_width; + + newtListboxSetWidth(listbox, max_line_len); + + newtCenteredWindow(max_line_len + 2, ws.ws_row - 5, self->sym->name); + form = newtForm(NULL, NULL, 0); + newtFormAddHotKey(form, NEWT_KEY_ESCAPE); + newtFormAddComponents(form, listbox, NULL); + + newtFormRun(form, &es); + newtFormDestroy(form); + newtPopWindow(); + newtPopHelpLine(); +out_free_str: + free(str); +} + +void perf_session__browse_hists(struct rb_root *hists, u64 session_total, + const char *helpline) +{ + struct sort_entry *se; + struct rb_node *nd; + unsigned int width; + char *col_width = symbol_conf.col_width_list_str; + struct winsize ws; + size_t max_len = 0; + char str[1024]; + newtComponent form, listbox; + struct newtExitStruct es; + + snprintf(str, sizeof(str), "Samples: %Ld", session_total); + newtDrawRootText(0, 0, str); + newtPushHelpLine(helpline); + + get_term_dimensions(&ws); + + form = newtForm(NULL, NULL, 0); + newtFormAddHotKey(form, NEWT_KEY_ESCAPE); + + listbox = newtListbox(1, 1, ws.ws_row - 2, (NEWT_FLAG_SCROLL | + NEWT_FLAG_BORDER | + NEWT_FLAG_RETURNEXIT)); + + list_for_each_entry(se, &hist_entry__sort_list, list) { + if (se->elide) + continue; + width = strlen(se->header); + if (se->width) { + if (symbol_conf.col_width_list_str) { + if (col_width) { + *se->width = atoi(col_width); + col_width = strchr(col_width, ','); + if (col_width) + ++col_width; + } + } + *se->width = max(*se->width, width); + } + } + + for (nd = rb_first(hists); nd; nd = rb_next(nd)) { + struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); + size_t len = hist_entry__append_browser(h, listbox, session_total); + if (len > max_len) + max_len = len; + } + + newtListboxSetWidth(listbox, max_len); + newtFormAddComponents(form, listbox, NULL); + + while (1) { + struct hist_entry *selection; + + newtFormRun(form, &es); + if (es.reason == NEWT_EXIT_HOTKEY) + break; + selection = newtListboxGetCurrent(listbox); + hist_entry__annotate_browser(selection); + } + + newtFormDestroy(form); +} + +int browser__show_help(const char *format, va_list ap) +{ + int ret; + static int backlog; + static char msg[1024]; + + ret = vsnprintf(msg + backlog, sizeof(msg) - backlog, format, ap); + backlog += ret; + + if (msg[backlog - 1] == '\n') { + newtPopHelpLine(); + newtPushHelpLine(msg); + newtRefresh(); + backlog = 0; + } + + return ret; +} + +bool use_browser; + +void setup_browser(void) +{ + if (!isatty(1)) + return; + + use_browser = true; + newtInit(); + newtCls(); + newtPushHelpLine(" "); +} + +void exit_browser(void) +{ + if (use_browser) + newtFinished(); +} diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 5c33417..34d7339 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -86,4 +86,13 @@ static inline struct map * { return map_groups__new_module(&self->kmaps, start, filename); } + +#ifdef NO_NEWT_SUPPORT +static inline void perf_session__browse_hists(struct rb_root *hists __used, + u64 session_total __used, + const char *helpline __used) {} +#else +void perf_session__browse_hists(struct rb_root *hists, u64 session_total, + const char *helpline); +#endif #endif /* __PERF_SESSION_H */ -- cgit v0.10.2 From 7081e087b90d4eb4348f7970bd6b266d837321ef Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 12 Mar 2010 10:48:12 -0300 Subject: perf newt: Add 'Q', 'q' and Ctrl+C as ways to exit from forms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These are keys people expect when pressed to exit the current widget, so have associate all of them to this semantic. Suggested-by: Ingo Molnar Signed-off-by: Arnaldo Carvalho de Melo Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: <1268401692-9361-1-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index 3d3a936..2a4308a 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -4,6 +4,7 @@ #include #include +#include #include "cache.h" #include "hist.h" @@ -11,6 +12,22 @@ #include "sort.h" #include "symbol.h" +static void newt_form__set_exit_keys(newtComponent self) +{ + newtFormAddHotKey(self, NEWT_KEY_ESCAPE); + newtFormAddHotKey(self, 'Q'); + newtFormAddHotKey(self, 'q'); + newtFormAddHotKey(self, CTRL('c')); +} + +static newtComponent newt_form__new(void) +{ + newtComponent self = newtForm(NULL, NULL, 0); + if (self) + newt_form__set_exit_keys(self); + return self; +} + static size_t hist_entry__append_browser(struct hist_entry *self, newtComponent listbox, u64 total) { @@ -77,8 +94,7 @@ static void hist_entry__annotate_browser(struct hist_entry *self) newtListboxSetWidth(listbox, max_line_len); newtCenteredWindow(max_line_len + 2, ws.ws_row - 5, self->sym->name); - form = newtForm(NULL, NULL, 0); - newtFormAddHotKey(form, NEWT_KEY_ESCAPE); + form = newt_form__new(); newtFormAddComponents(form, listbox, NULL); newtFormRun(form, &es); @@ -108,8 +124,7 @@ void perf_session__browse_hists(struct rb_root *hists, u64 session_total, get_term_dimensions(&ws); - form = newtForm(NULL, NULL, 0); - newtFormAddHotKey(form, NEWT_KEY_ESCAPE); + form = newt_form__new(); listbox = newtListbox(1, 1, ws.ws_row - 2, (NEWT_FLAG_SCROLL | NEWT_FLAG_BORDER | -- cgit v0.10.2 From cb7afb7092bc502b890f0a897ffd67c2b078d347 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 12 Mar 2010 12:46:47 -0300 Subject: perf newt: Use newtGetScreenSize MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For consistency, use the newt API more fully. Signed-off-by: Arnaldo Carvalho de Melo Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: <1268408808-13595-1-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index 2a4308a..f6ec6f5 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -52,7 +52,7 @@ static size_t hist_entry__append_browser(struct hist_entry *self, static void hist_entry__annotate_browser(struct hist_entry *self) { FILE *fp; - struct winsize ws; + int cols, rows; newtComponent form, listbox; struct newtExitStruct es; char *str; @@ -71,8 +71,8 @@ static void hist_entry__annotate_browser(struct hist_entry *self) goto out_free_str; newtPushHelpLine("Press ESC to exit"); - get_term_dimensions(&ws); - listbox = newtListbox(0, 0, ws.ws_row - 5, NEWT_FLAG_SCROLL); + newtGetScreenSize(&cols, &rows); + listbox = newtListbox(0, 0, rows - 5, NEWT_FLAG_SCROLL); while (!feof(fp)) { if (getline(&line, &line_len, fp) < 0 || !line_len) @@ -87,13 +87,13 @@ static void hist_entry__annotate_browser(struct hist_entry *self) fclose(fp); free(line); - max_usable_width = ws.ws_col - 22; + max_usable_width = cols - 22; if (max_line_len > max_usable_width) max_line_len = max_usable_width; newtListboxSetWidth(listbox, max_line_len); - newtCenteredWindow(max_line_len + 2, ws.ws_row - 5, self->sym->name); + newtCenteredWindow(max_line_len + 2, rows - 5, self->sym->name); form = newt_form__new(); newtFormAddComponents(form, listbox, NULL); @@ -112,7 +112,7 @@ void perf_session__browse_hists(struct rb_root *hists, u64 session_total, struct rb_node *nd; unsigned int width; char *col_width = symbol_conf.col_width_list_str; - struct winsize ws; + int rows; size_t max_len = 0; char str[1024]; newtComponent form, listbox; @@ -122,13 +122,13 @@ void perf_session__browse_hists(struct rb_root *hists, u64 session_total, newtDrawRootText(0, 0, str); newtPushHelpLine(helpline); - get_term_dimensions(&ws); + newtGetScreenSize(NULL, &rows); form = newt_form__new(); - listbox = newtListbox(1, 1, ws.ws_row - 2, (NEWT_FLAG_SCROLL | - NEWT_FLAG_BORDER | - NEWT_FLAG_RETURNEXIT)); + listbox = newtListbox(1, 1, rows - 2, (NEWT_FLAG_SCROLL | + NEWT_FLAG_BORDER | + NEWT_FLAG_RETURNEXIT)); list_for_each_entry(se, &hist_entry__sort_list, list) { if (se->elide) -- cgit v0.10.2 From 3997d3776a6e89586e76a0ef355bfbbd8a76966c Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 12 Mar 2010 12:46:48 -0300 Subject: perf hist: Don't fprintf the callgraph unconditionally MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [root@doppio ~]# perf report -i newt.data | head -10 # Samples: 11999679868 # # Overhead Command Shared Object Symbol # ........ ....... ............................. ...... # 63.61% perf libslang.so.2.1.4 [.] SLsmg_write_chars 6.30% perf perf [.] symbols__find 2.19% perf libnewt.so.0.52.10 [.] newtListboxAppendEntry 2.08% perf libslang.so.2.1.4 [.] SLsmg_write_chars@plt 1.99% perf libc-2.10.2.so [.] _IO_vfprintf_internal [root@doppio ~]# Not good, the newt form for report works, but slang has to eat the cost of the additional callgraph lines everytime it prints a line, and the callgraph doesn't appear on the screen, so move the callgraph printing to a separate function and don't use it in newt.c. Newt tree widgets are being investigated to properly support callgraphs, but till that gets merged, lets remove this huge overhead and show at least the symbol overheads for a callgraph rich perf.data with good performance. Signed-off-by: Arnaldo Carvalho de Melo Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: <1268408808-13595-2-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index d43be34..1a4e837 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -532,23 +532,23 @@ size_t hist_entry__fprintf(struct hist_entry *self, ret += se->print(fp, self, se->width ? *se->width : 0); } - ret += fprintf(fp, "\n"); - - if (symbol_conf.use_callchain) { - int left_margin = 0; + return ret + fprintf(fp, "\n"); +} - if (sort__first_dimension == SORT_COMM) { - se = list_first_entry(&hist_entry__sort_list, typeof(*se), - list); - left_margin = se->width ? *se->width : 0; - left_margin -= thread__comm_len(self->thread); - } +static size_t hist_entry__fprintf_callchain(struct hist_entry *self, FILE *fp, + u64 session_total) +{ + int left_margin = 0; - ret += hist_entry_callchain__fprintf(fp, self, session_total, - left_margin); + if (sort__first_dimension == SORT_COMM) { + struct sort_entry *se = list_first_entry(&hist_entry__sort_list, + typeof(*se), list); + left_margin = se->width ? *se->width : 0; + left_margin -= thread__comm_len(self->thread); } - return ret; + return hist_entry_callchain__fprintf(fp, self, session_total, + left_margin); } size_t perf_session__fprintf_hists(struct rb_root *hists, @@ -655,6 +655,10 @@ print_entries: } ret += hist_entry__fprintf(h, pair, show_displacement, displacement, fp, session_total); + + if (symbol_conf.use_callchain) + ret += hist_entry__fprintf_callchain(h, fp, session_total); + if (h->map == NULL && verbose > 1) { __map_groups__fprintf_maps(&h->thread->mg, MAP__FUNCTION, fp); -- cgit v0.10.2 From 567e54790e5c07152a93b6de4d0210af8b77da87 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 12 Mar 2010 21:05:10 -0300 Subject: perf tools: Fix non-newt build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The use_browser needs to be in a file that is always built and also we need a browser__show_help stub in that case. Reported-by: Anton Blanchard Signed-off-by: Arnaldo Carvalho de Melo Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: <1268438710-32697-1-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar diff --git a/tools/perf/perf.c b/tools/perf/perf.c index 9ff186b..0d4b9ed 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c @@ -16,6 +16,8 @@ #include "util/string.h" #include "util/debugfs.h" +bool use_browser; + const char perf_usage_string[] = "perf [--version] [--help] COMMAND [ARGS]"; diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h index 03accb8..0172edf 100644 --- a/tools/perf/util/debug.h +++ b/tools/perf/util/debug.h @@ -9,6 +9,14 @@ extern int dump_trace; int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); void trace_event(event_t *event); + +#ifdef NO_NEWT_SUPPORT +static inline int browser__show_help(const char *format __used, va_list ap __used) +{ + return 0; +} +#else int browser__show_help(const char *format, va_list ap); +#endif #endif /* __PERF_DEBUG_H */ diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index f6ec6f5..2836394 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -189,8 +189,6 @@ int browser__show_help(const char *format, va_list ap) return ret; } -bool use_browser; - void setup_browser(void) { if (!isatty(1)) -- cgit v0.10.2 From 8576e1971663ffdb6139041de97cdd2e1d4791cc Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sat, 13 Mar 2010 11:11:16 +0300 Subject: x86, perf: Unmask LVTPC only if we have APIC supported Ingo reported: | | There's a build failure on -tip with the P4 driver, on UP 32-bit, if | PERF_EVENTS is enabled but UP_APIC is disabled: | | arch/x86/built-in.o: In function `p4_pmu_handle_irq': | perf_event.c:(.text+0xa756): undefined reference to `apic' | perf_event.c:(.text+0xa76e): undefined reference to `apic' | So we have to unmask LVTPC only if we're configured to have one. Reported-by: Ingo Molnar Signed-off-by: Cyrill Gorcunov CC: Lin Ming CC: Peter Zijlstra LKML-Reference: <20100313081116.GA5179@lenovo> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index 381f593..ef861da1 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c @@ -365,8 +365,10 @@ static int p4_pmu_handle_irq(struct pt_regs *regs) } if (handled) { +#ifdef CONFIG_X86_LOCAL_APIC /* p4 quirk: unmask it again */ apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED); +#endif inc_irq_stat(apic_perf_irqs); } -- cgit v0.10.2 From e4495262826d1eabca3529fa6ac22394eb348132 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 15 Mar 2010 12:58:22 +0800 Subject: perf, x86: Enable not tagged retired instruction counting on P4s This should turn on instruction counting on P4s, which was missing in the first version of the new PMU driver. It's inaccurate for now, we still need dependant event to tag mops before we can count them precisely. The result is that the number of instruction may be lifted up. Signed-off-by: Cyrill Gorcunov Signed-off-by: Lin Ming Cc: Peter Zijlstra LKML-Reference: <1268629102.3355.11.camel@minggr.sh.intel.com> Signed-off-by: Ingo Molnar diff --git a/arch/x86/include/asm/perf_event_p4.h b/arch/x86/include/asm/perf_event_p4.h index 829f471..b47b9e9 100644 --- a/arch/x86/include/asm/perf_event_p4.h +++ b/arch/x86/include/asm/perf_event_p4.h @@ -324,8 +324,8 @@ static inline u32 p4_default_escr_conf(int cpu, int exclude_os, int exclude_usr) #define P4_SSE_INPUT_ASSIST P4_EVENT_PACK(0x34, 0x01) /* - * MSR_P4_FIRM_ESCR: 8, 9 - * MSR_P4_FIRM_ESCR: 10, 11 + * MSR_P4_FIRM_ESCR0: 8, 9 + * MSR_P4_FIRM_ESCR1: 10, 11 */ #define P4_PACKED_SP_UOP P4_EVENT_PACK(0x08, 0x01) @@ -462,8 +462,8 @@ static inline u32 p4_default_escr_conf(int cpu, int exclude_os, int exclude_usr) #define P4_INSTR_RETIRED P4_EVENT_PACK(0x02, 0x04) /* - * MSR_P4_CRU_ESCR2: 12, 13, 16 - * MSR_P4_CRU_ESCR3: 14, 15, 17 + * MSR_P4_CRU_ESCR0: 12, 13, 16 + * MSR_P4_CRU_ESCR1: 14, 15, 17 */ #define P4_UOPS_RETIRED P4_EVENT_PACK(0x01, 0x04) diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index ef861da1..a11ce73 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c @@ -60,13 +60,11 @@ struct p4_event_template p4_templates[] = { [2] = { .opcode = P4_INSTR_RETIRED, .config = 0, - .dep = 0, /* needs front-end tagging */ + .dep = -1, /* needs front-end tagging */ .emask = P4_EVENT_ATTR(P4_INSTR_RETIRED, NBOGUSNTAG) | - P4_EVENT_ATTR(P4_INSTR_RETIRED, NBOGUSTAG) | - P4_EVENT_ATTR(P4_INSTR_RETIRED, BOGUSNTAG) | - P4_EVENT_ATTR(P4_INSTR_RETIRED, BOGUSTAG), - .escr_msr = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 }, + P4_EVENT_ATTR(P4_INSTR_RETIRED, BOGUSNTAG), + .escr_msr = { MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR1 }, .cntr = { 12, 14 }, }, [3] = { -- cgit v0.10.2 From bedbfdea31daf3880745001d56450c683959ee7e Mon Sep 17 00:00:00 2001 From: Eric B Munson Date: Mon, 15 Mar 2010 11:46:57 -0300 Subject: perf record: Enable the enable_on_exec flag if record forks the target When forking its target, perf record can capture data from before the target application is started. Perf stat uses the enable_on_exec flag in the event attributes to keep from displaying events from before the target program starts, this patch adds the same functionality to perf record when it is will fork the target process. Signed-off-by: Eric B Munson Signed-off-by: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Frederic Weisbecker LKML-Reference: <1268664418-28328-1-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index bed175d..962cdbf 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -225,7 +225,7 @@ static struct perf_header_attr *get_header_attr(struct perf_event_attr *a, int n return h_attr; } -static void create_counter(int counter, int cpu, pid_t pid) +static void create_counter(int counter, int cpu, pid_t pid, bool forks) { char *filter = filters[counter]; struct perf_event_attr *attr = attrs + counter; @@ -277,6 +277,9 @@ static void create_counter(int counter, int cpu, pid_t pid) attr->inherit = inherit; attr->disabled = 1; + if (forks) + attr->enable_on_exec = 1; + try_again: fd[nr_cpu][counter] = sys_perf_event_open(attr, pid, cpu, group_fd, 0); @@ -381,13 +384,13 @@ try_again: ioctl(fd[nr_cpu][counter], PERF_EVENT_IOC_ENABLE); } -static void open_counters(int cpu, pid_t pid) +static void open_counters(int cpu, pid_t pid, bool forks) { int counter; group_fd = -1; for (counter = 0; counter < nr_counters; counter++) - create_counter(counter, cpu, pid); + create_counter(counter, cpu, pid, forks); nr_cpu++; } @@ -547,11 +550,11 @@ static int __cmd_record(int argc, const char **argv) if ((!system_wide && !inherit) || profile_cpu != -1) { - open_counters(profile_cpu, target_pid); + open_counters(profile_cpu, target_pid, forks); } else { nr_cpus = read_cpu_map(); for (i = 0; i < nr_cpus; i++) - open_counters(cpumap[i], target_pid); + open_counters(cpumap[i], target_pid, forks); } if (file_new) { -- cgit v0.10.2 From b0a9ab62ab96e258a0ddd81d7fe2719c3db36006 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 15 Mar 2010 11:46:58 -0300 Subject: perf top: Properly notify the user that vmlinux is missing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before this patch this message would very briefly appear on the screen and then the screen would get updates only on the top, for number of interrupts received, etc, but no annotation would be performed: [root@doppio linux-2.6-tip]# perf top -s n_tty_write > /tmp/bla objdump: '[kernel.kallsyms]': No such file Now this is what the user gets: [root@doppio linux-2.6-tip]# perf top -s n_tty_write Can't annotate n_tty_write: No vmlinux file was found in the path: [0] vmlinux [1] /boot/vmlinux [2] /boot/vmlinux-2.6.33-rc5 [3] /lib/modules/2.6.33-rc5/build/vmlinux [4] /usr/lib/debug/lib/modules/2.6.33-rc5/vmlinux [root@doppio linux-2.6-tip]# This bug was introduced when we added automatic search for vmlinux, before that time the user had to specify a vmlinux file. Reported-by: David S. Miller Reported-by: Ingo Molnar Signed-off-by: Arnaldo Carvalho de Melo Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras Cc: LKML-Reference: <1268664418-28328-2-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 57e232f..c968bd3 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -169,7 +169,7 @@ static void sig_winch_handler(int sig __used) update_print_entries(&winsize); } -static void parse_source(struct sym_entry *syme) +static int parse_source(struct sym_entry *syme) { struct symbol *sym; struct sym_entry_source *source; @@ -180,12 +180,21 @@ static void parse_source(struct sym_entry *syme) u64 len; if (!syme) - return; + return -1; + + sym = sym_entry__symbol(syme); + map = syme->map; + + /* + * We can't annotate with just /proc/kallsyms + */ + if (map->dso->origin == DSO__ORIG_KERNEL) + return -1; if (syme->src == NULL) { syme->src = zalloc(sizeof(*source)); if (syme->src == NULL) - return; + return -1; pthread_mutex_init(&syme->src->lock, NULL); } @@ -195,9 +204,6 @@ static void parse_source(struct sym_entry *syme) pthread_mutex_lock(&source->lock); goto out_assign; } - - sym = sym_entry__symbol(syme); - map = syme->map; path = map->dso->long_name; len = sym->end - sym->start; @@ -209,7 +215,7 @@ static void parse_source(struct sym_entry *syme) file = popen(command, "r"); if (!file) - return; + return -1; pthread_mutex_lock(&source->lock); source->lines_tail = &source->lines; @@ -245,6 +251,7 @@ static void parse_source(struct sym_entry *syme) out_assign: sym_filter_entry = syme; pthread_mutex_unlock(&source->lock); + return 0; } static void __zero_source_counters(struct sym_entry *syme) @@ -991,7 +998,17 @@ static void event__process_sample(const event_t *self, if (sym_filter_entry_sched) { sym_filter_entry = sym_filter_entry_sched; sym_filter_entry_sched = NULL; - parse_source(sym_filter_entry); + if (parse_source(sym_filter_entry) < 0) { + struct symbol *sym = sym_entry__symbol(sym_filter_entry); + + pr_err("Can't annotate %s", sym->name); + if (sym_filter_entry->map->dso->origin == DSO__ORIG_KERNEL) { + pr_err(": No vmlinux file was found in the path:\n"); + vmlinux_path__fprintf(stderr); + } else + pr_err(".\n"); + exit(1); + } } syme = symbol__priv(al.sym); diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 75cd468..292f941 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -18,18 +18,6 @@ #define NT_GNU_BUILD_ID 3 #endif -enum dso_origin { - DSO__ORIG_KERNEL = 0, - DSO__ORIG_JAVA_JIT, - DSO__ORIG_BUILD_ID_CACHE, - DSO__ORIG_FEDORA, - DSO__ORIG_UBUNTU, - DSO__ORIG_BUILDID, - DSO__ORIG_DSO, - DSO__ORIG_KMODULE, - DSO__ORIG_NOT_FOUND, -}; - static void dsos__add(struct list_head *head, struct dso *dso); static struct map *map__new2(u64 start, struct dso *dso, enum map_type type); static int dso__load_kernel_sym(struct dso *self, struct map *map, @@ -1017,7 +1005,7 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name, } curr_map->map_ip = identity__map_ip; curr_map->unmap_ip = identity__map_ip; - curr_dso->origin = DSO__ORIG_KERNEL; + curr_dso->origin = self->origin; map_groups__insert(kmap->kmaps, curr_map); dsos__add(&dsos__kernel, curr_dso); dso__set_loaded(curr_dso, map->type); @@ -1887,6 +1875,17 @@ out_fail: return -1; } +size_t vmlinux_path__fprintf(FILE *fp) +{ + int i; + size_t printed = 0; + + for (i = 0; i < vmlinux_path__nr_entries; ++i) + printed += fprintf(fp, "[%d] %s\n", i, vmlinux_path[i]); + + return printed; +} + static int setup_list(struct strlist **list, const char *list_str, const char *list_name) { diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 280dadd..d983bba 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -149,6 +149,19 @@ size_t dsos__fprintf_buildid(FILE *fp, bool with_hits); size_t dso__fprintf_buildid(struct dso *self, FILE *fp); size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp); + +enum dso_origin { + DSO__ORIG_KERNEL = 0, + DSO__ORIG_JAVA_JIT, + DSO__ORIG_BUILD_ID_CACHE, + DSO__ORIG_FEDORA, + DSO__ORIG_UBUNTU, + DSO__ORIG_BUILDID, + DSO__ORIG_DSO, + DSO__ORIG_KMODULE, + DSO__ORIG_NOT_FOUND, +}; + char dso__symtab_origin(const struct dso *self); void dso__set_long_name(struct dso *self, char *name); void dso__set_build_id(struct dso *self, void *build_id); @@ -168,4 +181,6 @@ int kallsyms__parse(const char *filename, void *arg, int symbol__init(void); bool symbol_type__is_a(char symbol_type, enum map_type map_type); +size_t vmlinux_path__fprintf(FILE *fp); + #endif /* __PERF_SYMBOL */ -- cgit v0.10.2 From d06d92b7c9b99ea52bdaeb13f544675529891b8a Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 15 Mar 2010 13:04:33 -0300 Subject: perf annotate: Properly notify the user that vmlinux is missing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before this patch we would not find a vmlinux, then try to pass objdump "[kernel.kallsyms]" as the filename, it would get confused and produce no output: [root@doppio ~]# perf annotate n_tty_write ------------------------------------------------ Percent | Source code & Disassembly of [kernel.kallsyms] ------------------------------------------------ Now we check that and emit meaningful warning: [root@doppio ~]# perf annotate n_tty_write Can't annotate n_tty_write: No vmlinux file was found in the path: [0] vmlinux [1] /boot/vmlinux [2] /boot/vmlinux-2.6.34-rc1-tip+ [3] /lib/modules/2.6.34-rc1-tip+/build/vmlinux [4] /usr/lib/debug/lib/modules/2.6.34-rc1-tip+/vmlinux [root@doppio ~]# This bug was introduced when we added automatic search for vmlinux, before that time the user had to specify a vmlinux file. v2: Print the warning just for the first symbol found when no symbol name is specified, otherwise it will spam the screen repeating the warning for each symbol. Reported-by: Ingo Molnar Signed-off-by: Arnaldo Carvalho de Melo Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras Cc: LKML-Reference: <1268669073-6856-1-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 6ad7148..45d1466 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -452,6 +452,16 @@ static void annotate_sym(struct hist_entry *he) if (!filename) return; + if (dso->origin == DSO__ORIG_KERNEL) { + if (dso->annotate_warned) + return; + dso->annotate_warned = 1; + pr_err("Can't annotate %s: No vmlinux file was found in the " + "path:\n", sym->name); + vmlinux_path__fprintf(stderr); + return; + } + pr_debug("%s: filename=%s, sym=%s, start=%#Lx, end=%#Lx\n", __func__, filename, sym->name, map->unmap_ip(map, sym->start), map->unmap_ip(map, sym->end)); diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index 2836394..2d19e7a 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -63,7 +63,7 @@ static void hist_entry__annotate_browser(struct hist_entry *self) if (self->sym == NULL) return; - if (asprintf(&str, "perf annotate %s | expand", self->sym->name) < 0) + if (asprintf(&str, "perf annotate %s 2>&1 | expand", self->sym->name) < 0) return; fp = popen(str, "r"); diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index d983bba..5bd91d1 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -106,6 +106,7 @@ struct dso { u8 has_build_id:1; u8 kernel:1; u8 hit:1; + u8 annotate_warned:1; unsigned char origin; u8 sorted_by_name; u8 loaded; -- cgit v0.10.2 From 1d199b1ad606ae8b88acebd295b101c4e1cf2a57 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Tue, 16 Mar 2010 01:05:02 +0100 Subject: perf: Fix unexported generic perf_arch_fetch_caller_regs perf_arch_fetch_caller_regs() is exported for the overriden x86 version, but not for the generic weak version. As a general rule, weak functions should not have their symbol exported in the same file they are defined. So let's export it on trace_event_perf.c as it is used by trace events only. This fixes: ERROR: ".perf_arch_fetch_caller_regs" [fs/xfs/xfs.ko] undefined! ERROR: ".perf_arch_fetch_caller_regs" [arch/powerpc/platforms/cell/spufs/spufs.ko] undefined! -v2: And also only build it if trace events are enabled. -v3: Fix changelog mistake Reported-by: Stephen Rothwell Signed-off-by: Frederic Weisbecker Cc: Peter Zijlstra Cc: Xiao Guangrong Cc: Paul Mackerras LKML-Reference: <1268697902-9518-1-git-send-regression-fweisbec@gmail.com> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 978d297..0d3466c 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -1695,6 +1695,7 @@ struct perf_callchain_entry *perf_callchain(struct pt_regs *regs) return entry; } +#ifdef CONFIG_EVENT_TRACING void perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip, int skip) { regs->ip = ip; @@ -1706,4 +1707,4 @@ void perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip, int ski regs->cs = __KERNEL_CS; local_save_flags(regs->flags); } -EXPORT_SYMBOL_GPL(perf_arch_fetch_caller_regs); +#endif diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 8bf6127..455393e 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -2790,10 +2790,12 @@ __weak struct perf_callchain_entry *perf_callchain(struct pt_regs *regs) return NULL; } +#ifdef CONFIG_EVENT_TRACING __weak void perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip, int skip) { } +#endif /* * Output diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c index 0709e4f..7d79a10 100644 --- a/kernel/trace/trace_event_perf.c +++ b/kernel/trace/trace_event_perf.c @@ -12,6 +12,8 @@ DEFINE_PER_CPU(struct pt_regs, perf_trace_regs); EXPORT_PER_CPU_SYMBOL_GPL(perf_trace_regs); +EXPORT_SYMBOL_GPL(perf_arch_fetch_caller_regs); + static char *perf_trace_buf; static char *perf_trace_buf_nmi; -- cgit v0.10.2 From 8ea7f544100844307072cae2f5fc108afdef999a Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Tue, 16 Mar 2010 10:12:36 +0800 Subject: x86, perf: Fix comments in Pentium-4 PMU definitions Reported-by: Cyrill Gorcunov Signed-off-by: Lin Ming Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo Cc: Frederic Weisbecker LKML-Reference: <1268705556.3379.8.camel@minggr.sh.intel.com> Signed-off-by: Ingo Molnar diff --git a/arch/x86/include/asm/perf_event_p4.h b/arch/x86/include/asm/perf_event_p4.h index b47b9e9..b842b32 100644 --- a/arch/x86/include/asm/perf_event_p4.h +++ b/arch/x86/include/asm/perf_event_p4.h @@ -319,6 +319,7 @@ static inline u32 p4_default_escr_conf(int cpu, int exclude_os, int exclude_usr) #define P4_BSQ_ACTIVE_ENTRIES P4_EVENT_PACK(0x06, 0x07) /* + * NOTE: no ESCR name in docs, it's guessed * MSR_P4_BSU_ESCR1: 2, 3 */ @@ -468,8 +469,8 @@ static inline u32 p4_default_escr_conf(int cpu, int exclude_os, int exclude_usr) #define P4_UOPS_RETIRED P4_EVENT_PACK(0x01, 0x04) /* - * MSR_P4_CRU_ESCR2: 12, 13, 16 - * MSR_P4_CRU_ESCR3: 14, 15, 17 + * MSR_P4_CRU_ESCR0: 12, 13, 16 + * MSR_P4_CRU_ESCR1: 14, 15, 17 */ #define P4_UOP_TYPE P4_EVENT_PACK(0x02, 0x02) -- cgit v0.10.2 From 6427462bfa50f50dc6c088c07037264fcc73eca1 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 15 Mar 2010 11:21:48 +0300 Subject: sched: Remove some dead code This was left over from "7c9414385e sched: Remove USER_SCHED" Signed-off-by: Dan Carpenter Acked-by: Dhaval Giani Cc: Kay Sievers Cc: Greg Kroah-Hartman LKML-Reference: <20100315082148.GD18181@bicker> Signed-off-by: Ingo Molnar diff --git a/kernel/user.c b/kernel/user.c index 766467b..ec3b222 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -178,8 +178,6 @@ struct user_struct *alloc_uid(struct user_namespace *ns, uid_t uid) return up; - put_user_ns(new->user_ns); - kmem_cache_free(uid_cachep, new); out_unlock: return NULL; } -- cgit v0.10.2 From 5cc718b9dad682329a60e73547c6e708faa5bbe4 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Mon, 15 Mar 2010 13:00:54 -0400 Subject: kprobes: Hide CONFIG_OPTPROBES and set if arch supports optimized kprobes Hide CONFIG_OPTPROBES and set if the arch supports optimized kprobes (IOW, HAVE_OPTPROBES=y), since this option doesn't change the major behavior of kprobes, and workarounds for minor changes are documented. Signed-off-by: Masami Hiramatsu Cc: systemtap Cc: DLE Cc: Dieter Ries Cc: Ananth N Mavinakayanahalli Cc: OGAWA Hirofumi Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo Cc: Frederic Weisbecker LKML-Reference: <20100315170054.31593.3153.stgit@localhost6.localdomain6> Signed-off-by: Ingo Molnar diff --git a/Documentation/kprobes.txt b/Documentation/kprobes.txt index 2f9115c..61c291c 100644 --- a/Documentation/kprobes.txt +++ b/Documentation/kprobes.txt @@ -165,8 +165,8 @@ the user entry_handler invocation is also skipped. 1.4 How Does Jump Optimization Work? -If you configured your kernel with CONFIG_OPTPROBES=y (currently -this option is supported on x86/x86-64, non-preemptive kernel) and +If your kernel is built with CONFIG_OPTPROBES=y (currently this flag +is automatically set 'y' on x86/x86-64, non-preemptive kernel) and the "debug.kprobes_optimization" kernel parameter is set to 1 (see sysctl(8)), Kprobes tries to reduce probe-hit overhead by using a jump instruction instead of a breakpoint instruction at each probepoint. @@ -271,8 +271,6 @@ tweak the kernel's execution path, you need to suppress optimization, using one of the following techniques: - Specify an empty function for the kprobe's post_handler or break_handler. or -- Config CONFIG_OPTPROBES=n. - or - Execute 'sysctl -w debug.kprobes_optimization=n' 2. Architectures Supported @@ -307,10 +305,6 @@ it useful to "Compile the kernel with debug info" (CONFIG_DEBUG_INFO), so you can use "objdump -d -l vmlinux" to see the source-to-object code mapping. -If you want to reduce probing overhead, set "Kprobes jump optimization -support" (CONFIG_OPTPROBES) to "y". You can find this option under the -"Kprobes" line. - 4. API Reference The Kprobes API includes a "register" function and an "unregister" diff --git a/arch/Kconfig b/arch/Kconfig index e5eb133..f06010f 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -42,15 +42,10 @@ config KPROBES If in doubt, say "N". config OPTPROBES - bool "Kprobes jump optimization support (EXPERIMENTAL)" - default y - depends on KPROBES + def_bool y + depends on KPROBES && HAVE_OPTPROBES depends on !PREEMPT - depends on HAVE_OPTPROBES select KALLSYMS_ALL - help - This option will allow kprobes to optimize breakpoint to - a jump for reducing its overhead. config HAVE_EFFICIENT_UNALIGNED_ACCESS bool -- cgit v0.10.2 From 984763cb90d4b5444baa0c3e43feff7926bf1834 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 16 Mar 2010 17:07:33 +0100 Subject: perf, x86: Report error code that returned from x86_pmu.hw_config() If x86_pmu.hw_config() fails a fixed error code (-EOPNOTSUPP) is returned even if a different error was reported. This patch fixes this. Signed-off-by: Robert Richter Acked-by: Cyrill Gorcunov Acked-by: Lin Ming Cc: acme@redhat.com Cc: eranian@google.com Cc: gorcunov@openvz.org Cc: peterz@infradead.org Cc: fweisbec@gmail.com LKML-Reference: <20100316160733.GR1585@erda.amd.com> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 0d3466c..5dacf63 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -472,8 +472,9 @@ static int __hw_perf_event_init(struct perf_event *event) hwc->last_tag = ~0ULL; /* Processor specifics */ - if (x86_pmu.hw_config(attr, hwc)) - return -EOPNOTSUPP; + err = x86_pmu.hw_config(attr, hwc); + if (err) + return err; if (!hwc->sample_period) { hwc->sample_period = x86_pmu.max_period; -- cgit v0.10.2 From a6b84574eed7e4fd8cb8dac2d0926fe2cf34b941 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Tue, 16 Mar 2010 01:05:02 +0100 Subject: perf: Fix unexported generic perf_arch_fetch_caller_regs perf_arch_fetch_caller_regs() is exported for the overriden x86 version, but not for the generic weak version. As a general rule, weak functions should not have their symbol exported in the same file they are defined. So let's export it on trace_event_perf.c as it is used by trace events only. This fixes: ERROR: ".perf_arch_fetch_caller_regs" [fs/xfs/xfs.ko] undefined! ERROR: ".perf_arch_fetch_caller_regs" [arch/powerpc/platforms/cell/spufs/spufs.ko] undefined! -v2: And also only build it if trace events are enabled. -v3: Fix changelog mistake Reported-by: Stephen Rothwell Signed-off-by: Frederic Weisbecker Cc: Peter Zijlstra Cc: Xiao Guangrong Cc: Paul Mackerras LKML-Reference: <1268697902-9518-1-git-send-regression-fweisbec@gmail.com> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 7645fae..60398a0 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -1702,6 +1702,7 @@ struct perf_callchain_entry *perf_callchain(struct pt_regs *regs) return entry; } +#ifdef CONFIG_EVENT_TRACING void perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip, int skip) { regs->ip = ip; @@ -1713,4 +1714,4 @@ void perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip, int ski regs->cs = __KERNEL_CS; local_save_flags(regs->flags); } -EXPORT_SYMBOL_GPL(perf_arch_fetch_caller_regs); +#endif diff --git a/kernel/perf_event.c b/kernel/perf_event.c index fb3031c..574ee58 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -2786,10 +2786,12 @@ __weak struct perf_callchain_entry *perf_callchain(struct pt_regs *regs) return NULL; } +#ifdef CONFIG_EVENT_TRACING __weak void perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip, int skip) { } +#endif /* * Output diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c index 0709e4f..7d79a10 100644 --- a/kernel/trace/trace_event_perf.c +++ b/kernel/trace/trace_event_perf.c @@ -12,6 +12,8 @@ DEFINE_PER_CPU(struct pt_regs, perf_trace_regs); EXPORT_PER_CPU_SYMBOL_GPL(perf_trace_regs); +EXPORT_SYMBOL_GPL(perf_arch_fetch_caller_regs); + static char *perf_trace_buf; static char *perf_trace_buf_nmi; -- cgit v0.10.2 From a1d37d5285bcda07f9c0b80a2634ca20ab545297 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Tue, 16 Mar 2010 18:05:21 -0400 Subject: perf tools: Introduce xzalloc() for detecting out of memory conditions Introducing xzalloc() which wrapping zalloc() for detecting out of memory conditions. Signed-off-by: Masami Hiramatsu Cc: systemtap Cc: DLE Cc: Frederic Weisbecker Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Mike Galbraith Cc: Peter Zijlstra LKML-Reference: <20100316220521.32050.85155.stgit@localhost6.localdomain6> [ -v2: small cleanups in surrounding code ] Signed-off-by: Ingo Molnar diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 0f5b2a6..5270108 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -295,6 +295,13 @@ extern void *xmemdupz(const void *data, size_t len); extern char *xstrndup(const char *str, size_t len); extern void *xrealloc(void *ptr, size_t size) __attribute__((weak)); +static inline void *xzalloc(size_t size) +{ + void *buf = xmalloc(size); + + return memset(buf, 0, size); +} + static inline void *zalloc(size_t size) { return calloc(1, size); @@ -309,6 +316,7 @@ static inline int has_extension(const char *filename, const char *ext) { size_t len = strlen(filename); size_t extlen = strlen(ext); + return len > extlen && !memcmp(filename + len - extlen, ext, extlen); } @@ -322,6 +330,7 @@ static inline int has_extension(const char *filename, const char *ext) #undef isalnum #undef tolower #undef toupper + extern unsigned char sane_ctype[256]; #define GIT_SPACE 0x01 #define GIT_DIGIT 0x02 -- cgit v0.10.2 From 31facc5f1ac674fbcc29f212377e589396bb934c Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Tue, 16 Mar 2010 18:05:30 -0400 Subject: perf probe: Use wrapper functions Use wrapped functions as much as possible, to check out of memory conditions in perf probe. Signed-off-by: Masami Hiramatsu Cc: systemtap Cc: DLE Cc: Frederic Weisbecker Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Mike Galbraith Cc: Peter Zijlstra LKML-Reference: <20100316220530.32050.53951.stgit@localhost6.localdomain6> Signed-off-by: Ingo Molnar diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index 152d6c9..b6afe7b 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c @@ -87,9 +87,7 @@ static void parse_probe_event_argv(int argc, const char **argv) len = 0; for (i = 0; i < argc; i++) len += strlen(argv[i]) + 1; - buf = zalloc(len + 1); - if (!buf) - die("Failed to allocate memory for binding arguments."); + buf = xzalloc(len + 1); len = 0; for (i = 0; i < argc; i++) len += sprintf(&buf[len], "%s ", argv[i]); diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 7c004b6..88a3b6d 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -33,6 +33,7 @@ #include #undef _GNU_SOURCE +#include "util.h" #include "event.h" #include "string.h" #include "strlist.h" @@ -90,9 +91,9 @@ void parse_line_range_desc(const char *arg, struct line_range *lr) if (*tmp != '\0') semantic_error("Tailing with invalid character '%d'.", *tmp); - tmp = strndup(arg, (ptr - arg)); + tmp = xstrndup(arg, (ptr - arg)); } else - tmp = strdup(arg); + tmp = xstrdup(arg); if (strchr(tmp, '.')) lr->file = tmp; @@ -135,7 +136,7 @@ static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp) if (!check_event_name(arg)) semantic_error("%s is bad for event name -it must " "follow C symbol-naming rule.", arg); - pp->event = strdup(arg); + pp->event = xstrdup(arg); arg = tmp; } @@ -147,17 +148,16 @@ static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp) /* Check arg is function or file and copy it */ if (strchr(arg, '.')) /* File */ - pp->file = strdup(arg); + pp->file = xstrdup(arg); else /* Function */ - pp->function = strdup(arg); - DIE_IF(pp->file == NULL && pp->function == NULL); + pp->function = xstrdup(arg); /* Parse other options */ while (ptr) { arg = ptr; c = nc; if (c == ';') { /* Lazy pattern must be the last part */ - pp->lazy_line = strdup(arg); + pp->lazy_line = xstrdup(arg); break; } ptr = strpbrk(arg, ";:+@%"); @@ -181,8 +181,7 @@ static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp) case '@': /* File name */ if (pp->file) semantic_error("SRC@SRC is not allowed."); - pp->file = strdup(arg); - DIE_IF(pp->file == NULL); + pp->file = xstrdup(arg); break; case '%': /* Probe places */ if (strcmp(arg, "return") == 0) { @@ -247,11 +246,9 @@ void parse_perf_probe_event(const char *str, struct probe_point *pp, /* Copy arguments and ensure return probe has no C argument */ pp->nr_args = argc - 1; - pp->args = zalloc(sizeof(char *) * pp->nr_args); + pp->args = xzalloc(sizeof(char *) * pp->nr_args); for (i = 0; i < pp->nr_args; i++) { - pp->args[i] = strdup(argv[i + 1]); - if (!pp->args[i]) - die("Failed to copy argument."); + pp->args[i] = xstrdup(argv[i + 1]); if (is_c_varname(pp->args[i])) { if (pp->retprobe) semantic_error("You can't specify local" @@ -299,14 +296,12 @@ void parse_trace_kprobe_event(const char *str, struct probe_point *pp) pp->file = NULL; pp->nr_args = argc - 2; - pp->args = zalloc(sizeof(char *) * pp->nr_args); + pp->args = xzalloc(sizeof(char *) * pp->nr_args); for (i = 0; i < pp->nr_args; i++) { p = strchr(argv[i + 2], '='); if (p) /* We don't need which register is assigned. */ *p = '\0'; - pp->args[i] = strdup(argv[i + 2]); - if (!pp->args[i]) - die("Failed to copy argument."); + pp->args[i] = xstrdup(argv[i + 2]); } argv_free(argv); @@ -319,10 +314,8 @@ int synthesize_perf_probe_point(struct probe_point *pp) char offs[64] = "", line[64] = ""; int ret; - pp->probes[0] = buf = zalloc(MAX_CMDLEN); + pp->probes[0] = buf = xzalloc(MAX_CMDLEN); pp->found = 1; - if (!buf) - die("Failed to allocate memory by zalloc."); if (pp->offset) { ret = e_snprintf(offs, 64, "+%d", pp->offset); if (ret <= 0) @@ -380,9 +373,7 @@ int synthesize_trace_kprobe_event(struct probe_point *pp) char *buf; int i, len, ret; - pp->probes[0] = buf = zalloc(MAX_CMDLEN); - if (!buf) - die("Failed to allocate memory by zalloc."); + pp->probes[0] = buf = xzalloc(MAX_CMDLEN); ret = e_snprintf(buf, MAX_CMDLEN, "%s+%d", pp->function, pp->offset); if (ret <= 0) goto error; @@ -612,10 +603,9 @@ void add_trace_kprobe_events(struct probe_point *probes, int nr_probes, for (j = 0; j < nr_probes; j++) { pp = probes + j; if (!pp->event) - pp->event = strdup(pp->function); + pp->event = xstrdup(pp->function); if (!pp->group) - pp->group = strdup(PERFPROBE_GROUP); - DIE_IF(!pp->event || !pp->group); + pp->group = xstrdup(PERFPROBE_GROUP); /* If force_add is true, suffix search is allowed */ allow_suffix = force_add; for (i = 0; i < pp->found; i++) { @@ -709,9 +699,7 @@ void del_trace_kprobe_events(struct strlist *dellist) namelist = get_perf_event_names(fd, true); strlist__for_each(ent, dellist) { - str = strdup(ent->s); - if (!str) - die("Failed to copy event."); + str = xstrdup(ent->s); pr_debug("Parsing: %s\n", str); p = strchr(str, ':'); if (p) { diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index c171a24..e887bb6 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -125,8 +125,7 @@ static void line_list__add_line(struct list_head *head, unsigned int line) p = head; found: pr_debug("line list: add a line %u\n", line); - ln = zalloc(sizeof(struct line_node)); - DIE_IF(ln == NULL); + ln = xzalloc(sizeof(struct line_node)); ln->line = line; INIT_LIST_HEAD(&ln->list); list_add(&ln->list, p); @@ -416,7 +415,7 @@ static void show_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf) (unsigned long)(pf->addr - eaddr)); /* Copy the function name if possible */ if (!pp->function) { - pp->function = strdup(name); + pp->function = xstrdup(name); pp->offset = (size_t)(pf->addr - eaddr); } } else { @@ -425,7 +424,7 @@ static void show_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf) (uintmax_t)pf->addr); if (!pp->function) { /* TODO: Use _stext */ - pp->function = strdup(""); + pp->function = xstrdup(""); pp->offset = (size_t)pf->addr; } } @@ -456,7 +455,7 @@ static void show_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf) if (pp->found == MAX_PROBES) die("Too many( > %d) probe point found.\n", MAX_PROBES); - pp->probes[pp->found] = strdup(tmp); + pp->probes[pp->found] = xstrdup(tmp); pp->found++; } @@ -506,8 +505,7 @@ static int find_lazy_match_lines(struct list_head *head, if (fd < 0) die("failed to open %s", fname); DIE_IF(fstat(fd, &st) < 0); - fbuf = malloc(st.st_size + 2); - DIE_IF(fbuf == NULL); + fbuf = xmalloc(st.st_size + 2); DIE_IF(read(fd, fbuf, st.st_size) < 0); close(fd); fbuf[st.st_size] = '\n'; /* Dummy line */ @@ -727,7 +725,7 @@ static void find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf) /* Copy real path */ if (!lf->lr->path) - lf->lr->path = strdup(src); + lf->lr->path = xstrdup(src); line_list__add_line(&lf->lr->line_list, (unsigned int)lineno); } /* Update status */ -- cgit v0.10.2 From e0faa8d35845bb1893cf9e608a5a5d92e9390bf0 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Tue, 16 Mar 2010 18:05:37 -0400 Subject: perf probe: Move add-probe routine to util/ Move add-probe routine to util/probe_event.c. This simplifies main routine for reducing maintenance cost. Signed-off-by: Masami Hiramatsu Cc: systemtap Cc: DLE Cc: Frederic Weisbecker Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Mike Galbraith Cc: Peter Zijlstra LKML-Reference: <20100316220537.32050.72214.stgit@localhost6.localdomain6> Signed-off-by: Ingo Molnar diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index b6afe7b..2087034 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c @@ -36,11 +36,9 @@ #include "builtin.h" #include "util/util.h" #include "util/strlist.h" -#include "util/event.h" +#include "util/symbol.h" #include "util/debug.h" #include "util/debugfs.h" -#include "util/symbol.h" -#include "util/thread.h" #include "util/parse-options.h" #include "util/parse-events.h" /* For debugfs_path */ #include "util/probe-finder.h" @@ -57,8 +55,6 @@ static struct { int nr_probe; struct probe_point probes[MAX_PROBES]; struct strlist *dellist; - struct map_groups kmap_groups; - struct map *kmaps[MAP__NR_TYPES]; struct line_range line_range; } session; @@ -114,29 +110,7 @@ static int opt_del_probe_event(const struct option *opt __used, return 0; } -/* Currently just checking function name from symbol map */ -static void evaluate_probe_point(struct probe_point *pp) -{ - struct symbol *sym; - sym = map__find_symbol_by_name(session.kmaps[MAP__FUNCTION], - pp->function, NULL); - if (!sym) - die("Kernel symbol \'%s\' not found - probe not added.", - pp->function); -} - #ifndef NO_DWARF_SUPPORT -static int open_vmlinux(void) -{ - if (map__load(session.kmaps[MAP__FUNCTION], NULL) < 0) { - pr_debug("Failed to load kernel map.\n"); - return -EINVAL; - } - pr_debug("Try to open %s\n", - session.kmaps[MAP__FUNCTION]->dso->long_name); - return open(session.kmaps[MAP__FUNCTION]->dso->long_name, O_RDONLY); -} - static int opt_show_lines(const struct option *opt __used, const char *str, int unset __used) { @@ -204,31 +178,8 @@ static const struct option options[] = { OPT_END() }; -/* Initialize symbol maps for vmlinux */ -static void init_vmlinux(void) -{ - symbol_conf.sort_by_name = true; - if (symbol_conf.vmlinux_name == NULL) - symbol_conf.try_vmlinux_path = true; - else - pr_debug("Use vmlinux: %s\n", symbol_conf.vmlinux_name); - if (symbol__init() < 0) - die("Failed to init symbol map."); - - map_groups__init(&session.kmap_groups); - if (map_groups__create_kernel_maps(&session.kmap_groups, - session.kmaps) < 0) - die("Failed to create kernel maps."); -} - int cmd_probe(int argc, const char **argv, const char *prefix __used) { - int i, ret; -#ifndef NO_DWARF_SUPPORT - int fd; -#endif - struct probe_point *pp; - argc = parse_options(argc, argv, options, probe_usage, PARSE_OPT_STOP_AT_NON_OPTION); if (argc > 0) { @@ -267,14 +218,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) " --add/--del.\n"); usage_with_options(probe_usage, options); } - init_vmlinux(); - fd = open_vmlinux(); - if (fd < 0) - die("Could not open debuginfo file."); - ret = find_line_range(fd, &session.line_range); - if (ret <= 0) - die("Source line is not found.\n"); - close(fd); + show_line_range(&session.line_range); return 0; } @@ -287,72 +231,8 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) return 0; } - /* Add probes */ - init_vmlinux(); - - if (session.need_dwarf) -#ifdef NO_DWARF_SUPPORT - die("Debuginfo-analysis is not supported"); -#else /* !NO_DWARF_SUPPORT */ - pr_debug("Some probes require debuginfo.\n"); - - fd = open_vmlinux(); - if (fd < 0) { - if (session.need_dwarf) - die("Could not open debuginfo file."); - - pr_debug("Could not open vmlinux/module file." - " Try to use symbols.\n"); - goto end_dwarf; - } - - /* Searching probe points */ - for (i = 0; i < session.nr_probe; i++) { - pp = &session.probes[i]; - if (pp->found) - continue; - - lseek(fd, SEEK_SET, 0); - ret = find_probe_point(fd, pp); - if (ret > 0) - continue; - if (ret == 0) { /* No error but failed to find probe point. */ - synthesize_perf_probe_point(pp); - die("Probe point '%s' not found. - probe not added.", - pp->probes[0]); - } - /* Error path */ - if (session.need_dwarf) { - if (ret == -ENOENT) - pr_warning("No dwarf info found in the vmlinux - please rebuild with CONFIG_DEBUG_INFO=y.\n"); - die("Could not analyze debuginfo."); - } - pr_debug("An error occurred in debuginfo analysis." - " Try to use symbols.\n"); - break; - } - close(fd); - -end_dwarf: -#endif /* !NO_DWARF_SUPPORT */ - - /* Synthesize probes without dwarf */ - for (i = 0; i < session.nr_probe; i++) { - pp = &session.probes[i]; - if (pp->found) /* This probe is already found. */ - continue; - - evaluate_probe_point(pp); - ret = synthesize_trace_kprobe_event(pp); - if (ret == -E2BIG) - die("probe point definition becomes too long."); - else if (ret < 0) - die("Failed to synthesize a probe point."); - } - - /* Settng up probe points */ add_trace_kprobe_events(session.probes, session.nr_probe, - session.force_add); + session.force_add, session.need_dwarf); return 0; } diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 88a3b6d..1e60a65 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -40,6 +40,8 @@ #include "debug.h" #include "cache.h" #include "color.h" +#include "symbol.h" +#include "thread.h" #include "parse-events.h" /* For debugfs_path */ #include "probe-event.h" @@ -65,6 +67,38 @@ static int e_snprintf(char *str, size_t size, const char *format, ...) return ret; } + +static struct map_groups kmap_groups; +static struct map *kmaps[MAP__NR_TYPES]; + +/* Initialize symbol maps for vmlinux */ +static void init_vmlinux(void) +{ + symbol_conf.sort_by_name = true; + if (symbol_conf.vmlinux_name == NULL) + symbol_conf.try_vmlinux_path = true; + else + pr_debug("Use vmlinux: %s\n", symbol_conf.vmlinux_name); + if (symbol__init() < 0) + die("Failed to init symbol map."); + + map_groups__init(&kmap_groups); + if (map_groups__create_kernel_maps(&kmap_groups, kmaps) < 0) + die("Failed to create kernel maps."); +} + +#ifndef NO_DWARF_SUPPORT +static int open_vmlinux(void) +{ + if (map__load(kmaps[MAP__FUNCTION], NULL) < 0) { + pr_debug("Failed to load kernel map.\n"); + return -EINVAL; + } + pr_debug("Try to open %s\n", kmaps[MAP__FUNCTION]->dso->long_name); + return open(kmaps[MAP__FUNCTION]->dso->long_name, O_RDONLY); +} +#endif + void parse_line_range_desc(const char *arg, struct line_range *lr) { const char *ptr; @@ -586,8 +620,8 @@ static void get_new_event_name(char *buf, size_t len, const char *base, die("Too many events are on the same function."); } -void add_trace_kprobe_events(struct probe_point *probes, int nr_probes, - bool force_add) +static void __add_trace_kprobe_events(struct probe_point *probes, + int nr_probes, bool force_add) { int i, j, fd; struct probe_point *pp; @@ -640,6 +674,92 @@ void add_trace_kprobe_events(struct probe_point *probes, int nr_probes, close(fd); } +/* Currently just checking function name from symbol map */ +static void evaluate_probe_point(struct probe_point *pp) +{ + struct symbol *sym; + sym = map__find_symbol_by_name(kmaps[MAP__FUNCTION], + pp->function, NULL); + if (!sym) + die("Kernel symbol \'%s\' not found - probe not added.", + pp->function); +} + +void add_trace_kprobe_events(struct probe_point *probes, int nr_probes, + bool force_add, bool need_dwarf) +{ + int i, ret; + struct probe_point *pp; +#ifndef NO_DWARF_SUPPORT + int fd; +#endif + /* Add probes */ + init_vmlinux(); + + if (need_dwarf) +#ifdef NO_DWARF_SUPPORT + die("Debuginfo-analysis is not supported"); +#else /* !NO_DWARF_SUPPORT */ + pr_debug("Some probes require debuginfo.\n"); + + fd = open_vmlinux(); + if (fd < 0) { + if (need_dwarf) + die("Could not open debuginfo file."); + + pr_debug("Could not open vmlinux/module file." + " Try to use symbols.\n"); + goto end_dwarf; + } + + /* Searching probe points */ + for (i = 0; i < nr_probes; i++) { + pp = &probes[i]; + if (pp->found) + continue; + + lseek(fd, SEEK_SET, 0); + ret = find_probe_point(fd, pp); + if (ret > 0) + continue; + if (ret == 0) { /* No error but failed to find probe point. */ + synthesize_perf_probe_point(pp); + die("Probe point '%s' not found. - probe not added.", + pp->probes[0]); + } + /* Error path */ + if (need_dwarf) { + if (ret == -ENOENT) + pr_warning("No dwarf info found in the vmlinux - please rebuild with CONFIG_DEBUG_INFO=y.\n"); + die("Could not analyze debuginfo."); + } + pr_debug("An error occurred in debuginfo analysis." + " Try to use symbols.\n"); + break; + } + close(fd); + +end_dwarf: +#endif /* !NO_DWARF_SUPPORT */ + + /* Synthesize probes without dwarf */ + for (i = 0; i < nr_probes; i++) { + pp = &probes[i]; + if (pp->found) /* This probe is already found. */ + continue; + + evaluate_probe_point(pp); + ret = synthesize_trace_kprobe_event(pp); + if (ret == -E2BIG) + die("probe point definition becomes too long."); + else if (ret < 0) + die("Failed to synthesize a probe point."); + } + + /* Settng up probe points */ + __add_trace_kprobe_events(probes, nr_probes, force_add); +} + static void __del_trace_kprobe_event(int fd, struct str_node *ent) { char *p; @@ -759,6 +879,17 @@ void show_line_range(struct line_range *lr) unsigned int l = 1; struct line_node *ln; FILE *fp; + int fd, ret; + + /* Search a line range */ + init_vmlinux(); + fd = open_vmlinux(); + if (fd < 0) + die("Could not open debuginfo file."); + ret = find_line_range(fd, lr); + if (ret <= 0) + die("Source line is not found.\n"); + close(fd); setup_pager(); @@ -788,3 +919,5 @@ void show_line_range(struct line_range *lr) fclose(fp); } + + diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h index 711287d..3865e16 100644 --- a/tools/perf/util/probe-event.h +++ b/tools/perf/util/probe-event.h @@ -13,7 +13,7 @@ extern int synthesize_perf_probe_event(struct probe_point *pp); extern void parse_trace_kprobe_event(const char *str, struct probe_point *pp); extern int synthesize_trace_kprobe_event(struct probe_point *pp); extern void add_trace_kprobe_events(struct probe_point *probes, int nr_probes, - bool force_add); + bool force_add, bool need_dwarf); extern void del_trace_kprobe_events(struct strlist *dellist); extern void show_perf_probe_events(void); extern void show_line_range(struct line_range *lr); -- cgit v0.10.2 From 12a1fadb41b5a6733c36b488b881fb19a28c92d3 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Tue, 16 Mar 2010 18:05:44 -0400 Subject: perf probe: Rename session to param Since this name 'session' conflicts with 'perf_session', and this structure just holds parameters anymore. Signed-off-by: Masami Hiramatsu Cc: systemtap Cc: DLE Cc: Frederic Weisbecker Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Mike Galbraith Cc: Peter Zijlstra LKML-Reference: <20100316220544.32050.8788.stgit@localhost6.localdomain6> Signed-off-by: Ingo Molnar diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index 2087034..f577e14 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c @@ -56,20 +56,20 @@ static struct { struct probe_point probes[MAX_PROBES]; struct strlist *dellist; struct line_range line_range; -} session; +} params; /* Parse an event definition. Note that any error must die. */ static void parse_probe_event(const char *str) { - struct probe_point *pp = &session.probes[session.nr_probe]; + struct probe_point *pp = ¶ms.probes[params.nr_probe]; - pr_debug("probe-definition(%d): %s\n", session.nr_probe, str); - if (++session.nr_probe == MAX_PROBES) + pr_debug("probe-definition(%d): %s\n", params.nr_probe, str); + if (++params.nr_probe == MAX_PROBES) die("Too many probes (> %d) are specified.", MAX_PROBES); /* Parse perf-probe event into probe_point */ - parse_perf_probe_event(str, pp, &session.need_dwarf); + parse_perf_probe_event(str, pp, ¶ms.need_dwarf); pr_debug("%d arguments\n", pp->nr_args); } @@ -103,9 +103,9 @@ static int opt_del_probe_event(const struct option *opt __used, const char *str, int unset __used) { if (str) { - if (!session.dellist) - session.dellist = strlist__new(true, NULL); - strlist__add(session.dellist, str); + if (!params.dellist) + params.dellist = strlist__new(true, NULL); + strlist__add(params.dellist, str); } return 0; } @@ -115,9 +115,9 @@ static int opt_show_lines(const struct option *opt __used, const char *str, int unset __used) { if (str) - parse_line_range_desc(str, &session.line_range); - INIT_LIST_HEAD(&session.line_range.line_list); - session.show_lines = true; + parse_line_range_desc(str, ¶ms.line_range); + INIT_LIST_HEAD(¶ms.line_range.line_list); + params.show_lines = true; return 0; } #endif @@ -140,7 +140,7 @@ static const struct option options[] = { OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, "file", "vmlinux pathname"), #endif - OPT_BOOLEAN('l', "list", &session.list_events, + OPT_BOOLEAN('l', "list", ¶ms.list_events, "list up current probe events"), OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.", opt_del_probe_event), @@ -168,7 +168,7 @@ static const struct option options[] = { #endif "\t\t\tkprobe-tracer argument format.)\n", opt_add_probe_event), - OPT_BOOLEAN('f', "force", &session.force_add, "forcibly add events" + OPT_BOOLEAN('f', "force", ¶ms.force_add, "forcibly add events" " with existing name"), #ifndef NO_DWARF_SUPPORT OPT_CALLBACK('L', "line", NULL, @@ -190,20 +190,20 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) parse_probe_event_argv(argc, argv); } - if ((!session.nr_probe && !session.dellist && !session.list_events && - !session.show_lines)) + if ((!params.nr_probe && !params.dellist && !params.list_events && + !params.show_lines)) usage_with_options(probe_usage, options); if (debugfs_valid_mountpoint(debugfs_path) < 0) die("Failed to find debugfs path."); - if (session.list_events) { - if (session.nr_probe != 0 || session.dellist) { + if (params.list_events) { + if (params.nr_probe != 0 || params.dellist) { pr_warning(" Error: Don't use --list with" " --add/--del.\n"); usage_with_options(probe_usage, options); } - if (session.show_lines) { + if (params.show_lines) { pr_warning(" Error: Don't use --list with --line.\n"); usage_with_options(probe_usage, options); } @@ -212,27 +212,27 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) } #ifndef NO_DWARF_SUPPORT - if (session.show_lines) { - if (session.nr_probe != 0 || session.dellist) { + if (params.show_lines) { + if (params.nr_probe != 0 || params.dellist) { pr_warning(" Error: Don't use --line with" " --add/--del.\n"); usage_with_options(probe_usage, options); } - show_line_range(&session.line_range); + show_line_range(¶ms.line_range); return 0; } #endif - if (session.dellist) { - del_trace_kprobe_events(session.dellist); - strlist__delete(session.dellist); - if (session.nr_probe == 0) + if (params.dellist) { + del_trace_kprobe_events(params.dellist); + strlist__delete(params.dellist); + if (params.nr_probe == 0) return 0; } - add_trace_kprobe_events(session.probes, session.nr_probe, - session.force_add, session.need_dwarf); + add_trace_kprobe_events(params.probes, params.nr_probe, + params.force_add, params.need_dwarf); return 0; } -- cgit v0.10.2 From 95a3e4c4e21de1920a2ddb54bfc57c0af7e2561e Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Tue, 16 Mar 2010 18:05:51 -0400 Subject: perf probe: Rename some die_get_* functions Rename die_get_real_subprogram and die_get_inlinefunc to die_find_real_subprogram and die_find_inlinefunc respectively, because these functions search its children. After that, 'die_get_' means getting a property of that die, and 'die_find_' means searching DIE-tree to get an appropriate child die. Signed-off-by: Masami Hiramatsu Cc: systemtap Cc: DLE Cc: Frederic Weisbecker Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Mike Galbraith Cc: Peter Zijlstra LKML-Reference: <20100316220551.32050.36181.stgit@localhost6.localdomain6> Signed-off-by: Ingo Molnar diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index e887bb6..c91a960 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -204,8 +204,8 @@ static int __die_search_func_cb(Dwarf_Die *fn_die, void *data) } /* Search a real subprogram including this line, */ -static Dwarf_Die *die_get_real_subprogram(Dwarf_Die *cu_die, Dwarf_Addr addr, - Dwarf_Die *die_mem) +static Dwarf_Die *die_find_real_subprogram(Dwarf_Die *cu_die, Dwarf_Addr addr, + Dwarf_Die *die_mem) { struct __addr_die_search_param ad; ad.addr = addr; @@ -218,8 +218,8 @@ static Dwarf_Die *die_get_real_subprogram(Dwarf_Die *cu_die, Dwarf_Addr addr, } /* Similar to dwarf_getfuncs, but returns inlined_subroutine if exists. */ -static Dwarf_Die *die_get_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr, - Dwarf_Die *die_mem) +static Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr, + Dwarf_Die *die_mem) { Dwarf_Die child_die; int ret; @@ -233,7 +233,7 @@ static Dwarf_Die *die_get_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr, dwarf_haspc(die_mem, addr)) return die_mem; - if (die_get_inlinefunc(die_mem, addr, &child_die)) { + if (die_find_inlinefunc(die_mem, addr, &child_die)) { memcpy(die_mem, &child_die, sizeof(Dwarf_Die)); return die_mem; } @@ -401,7 +401,7 @@ static void show_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf) /* If no real subprogram, find a real one */ if (!sp_die || dwarf_tag(sp_die) != DW_TAG_subprogram) { - sp_die = die_get_real_subprogram(&pf->cu_die, + sp_die = die_find_real_subprogram(&pf->cu_die, pf->addr, &die_mem); if (!sp_die) die("Probe point is not found in subprograms."); @@ -564,7 +564,7 @@ static void find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf) if (!dwarf_haspc(sp_die, addr)) continue; /* Address filtering 2: No child include addr? */ - if (die_get_inlinefunc(sp_die, addr, &die_mem)) + if (die_find_inlinefunc(sp_die, addr, &die_mem)) continue; } @@ -714,7 +714,7 @@ static void find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf) continue; /* Address filtering 2: No child include addr? */ - if (die_get_inlinefunc(sp_die, addr, &die_mem)) + if (die_find_inlinefunc(sp_die, addr, &die_mem)) continue; } -- cgit v0.10.2 From 016f262e4fb10c6ecff709317098912f94a21efa Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Tue, 16 Mar 2010 18:05:58 -0400 Subject: perf probe: Introduce die_find_child() function Introduce die_find_child() function to integrate DIE-tree searching functions. Signed-off-by: Masami Hiramatsu Cc: systemtap Cc: DLE Cc: Frederic Weisbecker Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Mike Galbraith Cc: Peter Zijlstra LKML-Reference: <20100316220558.32050.7905.stgit@localhost6.localdomain6> Signed-off-by: Ingo Molnar diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index c91a960..3942e14 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -186,6 +186,62 @@ static const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname) return src; } +/* Compare diename and tname */ +static bool die_compare_name(Dwarf_Die *dw_die, const char *tname) +{ + const char *name; + name = dwarf_diename(dw_die); + DIE_IF(name == NULL); + return strcmp(tname, name); +} + +/* Get entry pc(or low pc, 1st entry of ranges) of the die */ +static Dwarf_Addr die_get_entrypc(Dwarf_Die *dw_die) +{ + Dwarf_Addr epc; + int ret; + + ret = dwarf_entrypc(dw_die, &epc); + DIE_IF(ret == -1); + return epc; +} + +/* Return values for die_find callbacks */ +enum { + DIE_FIND_CB_FOUND = 0, /* End of Search */ + DIE_FIND_CB_CHILD = 1, /* Search only children */ + DIE_FIND_CB_SIBLING = 2, /* Search only siblings */ + DIE_FIND_CB_CONTINUE = 3, /* Search children and siblings */ +}; + +/* Search a child die */ +static Dwarf_Die *die_find_child(Dwarf_Die *rt_die, + int (*callback)(Dwarf_Die *, void *), + void *data, Dwarf_Die *die_mem) +{ + Dwarf_Die child_die; + int ret; + + ret = dwarf_child(rt_die, die_mem); + if (ret != 0) + return NULL; + + do { + ret = callback(die_mem, data); + if (ret == DIE_FIND_CB_FOUND) + return die_mem; + + if ((ret & DIE_FIND_CB_CHILD) && + die_find_child(die_mem, callback, data, &child_die)) { + memcpy(die_mem, &child_die, sizeof(Dwarf_Die)); + return die_mem; + } + } while ((ret & DIE_FIND_CB_SIBLING) && + dwarf_siblingof(die_mem, die_mem) == 0); + + return NULL; +} + struct __addr_die_search_param { Dwarf_Addr addr; Dwarf_Die *die_mem; @@ -217,77 +273,45 @@ static Dwarf_Die *die_find_real_subprogram(Dwarf_Die *cu_die, Dwarf_Addr addr, return die_mem; } -/* Similar to dwarf_getfuncs, but returns inlined_subroutine if exists. */ -static Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr, - Dwarf_Die *die_mem) +/* die_find callback for inline function search */ +static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data) { - Dwarf_Die child_die; - int ret; + Dwarf_Addr *addr = data; - ret = dwarf_child(sp_die, die_mem); - if (ret != 0) - return NULL; - - do { - if (dwarf_tag(die_mem) == DW_TAG_inlined_subroutine && - dwarf_haspc(die_mem, addr)) - return die_mem; + if (dwarf_tag(die_mem) == DW_TAG_inlined_subroutine && + dwarf_haspc(die_mem, *addr)) + return DIE_FIND_CB_FOUND; - if (die_find_inlinefunc(die_mem, addr, &child_die)) { - memcpy(die_mem, &child_die, sizeof(Dwarf_Die)); - return die_mem; - } - } while (dwarf_siblingof(die_mem, die_mem) == 0); - - return NULL; + return DIE_FIND_CB_CONTINUE; } -/* Compare diename and tname */ -static bool die_compare_name(Dwarf_Die *dw_die, const char *tname) +/* Similar to dwarf_getfuncs, but returns inlined_subroutine if exists. */ +static Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr, + Dwarf_Die *die_mem) { - const char *name; - name = dwarf_diename(dw_die); - DIE_IF(name == NULL); - return strcmp(tname, name); + return die_find_child(sp_die, __die_find_inline_cb, &addr, die_mem); } -/* Get entry pc(or low pc, 1st entry of ranges) of the die */ -static Dwarf_Addr die_get_entrypc(Dwarf_Die *dw_die) +static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data) { - Dwarf_Addr epc; - int ret; + const char *name = data; + int tag; - ret = dwarf_entrypc(dw_die, &epc); - DIE_IF(ret == -1); - return epc; + tag = dwarf_tag(die_mem); + if ((tag == DW_TAG_formal_parameter || + tag == DW_TAG_variable) && + (die_compare_name(die_mem, name) == 0)) + return DIE_FIND_CB_FOUND; + + return DIE_FIND_CB_CONTINUE; } -/* Get a variable die */ +/* Find a variable called 'name' */ static Dwarf_Die *die_find_variable(Dwarf_Die *sp_die, const char *name, Dwarf_Die *die_mem) { - Dwarf_Die child_die; - int tag; - int ret; - - ret = dwarf_child(sp_die, die_mem); - if (ret != 0) - return NULL; - - do { - tag = dwarf_tag(die_mem); - if ((tag == DW_TAG_formal_parameter || - tag == DW_TAG_variable) && - (die_compare_name(die_mem, name) == 0)) - return die_mem; - - if (die_find_variable(die_mem, name, &child_die)) { - memcpy(die_mem, &child_die, sizeof(Dwarf_Die)); - return die_mem; - } - } while (dwarf_siblingof(die_mem, die_mem) == 0); - - return NULL; + return die_find_child(sp_die, __die_find_variable_cb, (void *)name, + die_mem); } /* -- cgit v0.10.2 From f4d7da499e4fc1fdff8f26fdeb1a058d475a7a6c Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Tue, 16 Mar 2010 18:06:05 -0400 Subject: perf probe: Add --dry-run option Add --dry-run option for debugging and testing. Signed-off-by: Masami Hiramatsu Cc: systemtap Cc: DLE Cc: Frederic Weisbecker Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Mike Galbraith Cc: Peter Zijlstra LKML-Reference: <20100316220605.32050.6571.stgit@localhost6.localdomain6> Signed-off-by: Ingo Molnar diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt index 34202b1..0f944b3 100644 --- a/tools/perf/Documentation/perf-probe.txt +++ b/tools/perf/Documentation/perf-probe.txt @@ -57,6 +57,11 @@ OPTIONS --force:: Forcibly add events with existing name. +-n:: +--dry-run:: + Dry run. With this option, --add and --del doesn't execute actual + adding and removal operations. + PROBE SYNTAX ------------ Probe points are defined by following syntax. diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index f577e14..a1a2891 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c @@ -175,6 +175,7 @@ static const struct option options[] = { "FUNC[:RLN[+NUM|:RLN2]]|SRC:ALN[+NUM|:ALN2]", "Show source code lines.", opt_show_lines), #endif + OPT__DRY_RUN(&probe_event_dry_run), OPT_END() }; diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 1e60a65..ac41578 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -49,6 +49,8 @@ #define MAX_PROBE_ARGS 128 #define PERFPROBE_GROUP "probe" +bool probe_event_dry_run; /* Dry run flag */ + #define semantic_error(msg ...) die("Semantic error :" msg) /* If there is no space to write, returns -E2BIG. */ @@ -430,7 +432,7 @@ error: return ret; } -static int open_kprobe_events(int flags, int mode) +static int open_kprobe_events(bool readwrite) { char buf[PATH_MAX]; int ret; @@ -439,7 +441,11 @@ static int open_kprobe_events(int flags, int mode) if (ret < 0) die("Failed to make kprobe_events path."); - ret = open(buf, flags, mode); + if (readwrite && !probe_event_dry_run) + ret = open(buf, O_RDWR, O_APPEND); + else + ret = open(buf, O_RDONLY, 0); + if (ret < 0) { if (errno == ENOENT) die("kprobe_events file does not exist -" @@ -535,7 +541,7 @@ void show_perf_probe_events(void) setup_pager(); memset(&pp, 0, sizeof(pp)); - fd = open_kprobe_events(O_RDONLY, 0); + fd = open_kprobe_events(false); rawlist = get_trace_kprobe_event_rawlist(fd); close(fd); @@ -585,9 +591,11 @@ static void write_trace_kprobe_event(int fd, const char *buf) int ret; pr_debug("Writing event: %s\n", buf); - ret = write(fd, buf, strlen(buf)); - if (ret <= 0) - die("Failed to write event: %s", strerror(errno)); + if (!probe_event_dry_run) { + ret = write(fd, buf, strlen(buf)); + if (ret <= 0) + die("Failed to write event: %s", strerror(errno)); + } } static void get_new_event_name(char *buf, size_t len, const char *base, @@ -630,7 +638,7 @@ static void __add_trace_kprobe_events(struct probe_point *probes, struct strlist *namelist; bool allow_suffix; - fd = open_kprobe_events(O_RDWR, O_APPEND); + fd = open_kprobe_events(true); /* Get current event names */ namelist = get_perf_event_names(fd, false); @@ -814,7 +822,7 @@ void del_trace_kprobe_events(struct strlist *dellist) struct str_node *ent; struct strlist *namelist; - fd = open_kprobe_events(O_RDWR, O_APPEND); + fd = open_kprobe_events(true); /* Get current event names */ namelist = get_perf_event_names(fd, true); diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h index 3865e16..703b887 100644 --- a/tools/perf/util/probe-event.h +++ b/tools/perf/util/probe-event.h @@ -5,6 +5,8 @@ #include "probe-finder.h" #include "strlist.h" +extern bool probe_event_dry_run; + extern void parse_line_range_desc(const char *arg, struct line_range *lr); extern void parse_perf_probe_event(const char *str, struct probe_point *pp, bool *need_dwarf); -- cgit v0.10.2 From 4235b0454ebeefc2295ad8417e18a8761425b19e Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Tue, 16 Mar 2010 18:06:12 -0400 Subject: perf probe: Introduce kprobe_trace_event and perf_probe_event Introduce kprobe_trace_event and perf_probe_event and replace old probe_point structure with it. probe_point structure is not enough flexible nor extensible. New data structures will help implementing further features. Signed-off-by: Masami Hiramatsu Cc: systemtap Cc: DLE Cc: Frederic Weisbecker Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Mike Galbraith Cc: Peter Zijlstra LKML-Reference: <20100316220612.32050.33806.stgit@localhost6.localdomain6> Signed-off-by: Ingo Molnar diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index a1a2891..e0dafd9 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c @@ -48,12 +48,11 @@ /* Session management structure */ static struct { - bool need_dwarf; bool list_events; bool force_add; bool show_lines; - int nr_probe; - struct probe_point probes[MAX_PROBES]; + int nevents; + struct perf_probe_event events[MAX_PROBES]; struct strlist *dellist; struct line_range line_range; } params; @@ -62,16 +61,16 @@ static struct { /* Parse an event definition. Note that any error must die. */ static void parse_probe_event(const char *str) { - struct probe_point *pp = ¶ms.probes[params.nr_probe]; + struct perf_probe_event *pev = ¶ms.events[params.nevents]; - pr_debug("probe-definition(%d): %s\n", params.nr_probe, str); - if (++params.nr_probe == MAX_PROBES) + pr_debug("probe-definition(%d): %s\n", params.nevents, str); + if (++params.nevents == MAX_PROBES) die("Too many probes (> %d) are specified.", MAX_PROBES); - /* Parse perf-probe event into probe_point */ - parse_perf_probe_event(str, pp, ¶ms.need_dwarf); + /* Parse a perf-probe command into event */ + parse_perf_probe_command(str, pev); - pr_debug("%d arguments\n", pp->nr_args); + pr_debug("%d arguments\n", pev->nargs); } static void parse_probe_event_argv(int argc, const char **argv) @@ -191,7 +190,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) parse_probe_event_argv(argc, argv); } - if ((!params.nr_probe && !params.dellist && !params.list_events && + if ((!params.nevents && !params.dellist && !params.list_events && !params.show_lines)) usage_with_options(probe_usage, options); @@ -199,7 +198,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) die("Failed to find debugfs path."); if (params.list_events) { - if (params.nr_probe != 0 || params.dellist) { + if (params.nevents != 0 || params.dellist) { pr_warning(" Error: Don't use --list with" " --add/--del.\n"); usage_with_options(probe_usage, options); @@ -214,7 +213,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) #ifndef NO_DWARF_SUPPORT if (params.show_lines) { - if (params.nr_probe != 0 || params.dellist) { + if (params.nevents != 0 || params.dellist) { pr_warning(" Error: Don't use --line with" " --add/--del.\n"); usage_with_options(probe_usage, options); @@ -226,14 +225,13 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) #endif if (params.dellist) { - del_trace_kprobe_events(params.dellist); + del_perf_probe_events(params.dellist); strlist__delete(params.dellist); - if (params.nr_probe == 0) + if (params.nevents == 0) return 0; } - add_trace_kprobe_events(params.probes, params.nr_probe, - params.force_add, params.need_dwarf); + add_perf_probe_events(params.events, params.nevents, params.force_add); return 0; } diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index ac41578..b44ddfb 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -44,6 +44,7 @@ #include "thread.h" #include "parse-events.h" /* For debugfs_path */ #include "probe-event.h" +#include "probe-finder.h" #define MAX_CMDLEN 256 #define MAX_PROBE_ARGS 128 @@ -150,8 +151,9 @@ static bool check_event_name(const char *name) } /* Parse probepoint definition. */ -static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp) +static void parse_perf_probe_point(char *arg, struct perf_probe_event *pev) { + struct perf_probe_point *pp = &pev->point; char *ptr, *tmp; char c, nc = 0; /* @@ -172,7 +174,8 @@ static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp) if (!check_event_name(arg)) semantic_error("%s is bad for event name -it must " "follow C symbol-naming rule.", arg); - pp->event = xstrdup(arg); + pev->event = xstrdup(arg); + pev->group = NULL; arg = tmp; } @@ -255,57 +258,65 @@ static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp) semantic_error("Offset/Line/Lazy pattern can't be used with " "return probe."); - pr_debug("symbol:%s file:%s line:%d offset:%d return:%d lazy:%s\n", + pr_debug("symbol:%s file:%s line:%d offset:%lu return:%d lazy:%s\n", pp->function, pp->file, pp->line, pp->offset, pp->retprobe, pp->lazy_line); } -/* Parse perf-probe event definition */ -void parse_perf_probe_event(const char *str, struct probe_point *pp, - bool *need_dwarf) +/* Parse perf-probe event command */ +void parse_perf_probe_command(const char *cmd, struct perf_probe_event *pev) { char **argv; int argc, i; - *need_dwarf = false; - - argv = argv_split(str, &argc); + argv = argv_split(cmd, &argc); if (!argv) die("argv_split failed."); if (argc > MAX_PROBE_ARGS + 1) semantic_error("Too many arguments"); /* Parse probe point */ - parse_perf_probe_probepoint(argv[0], pp); - if (pp->file || pp->line || pp->lazy_line) - *need_dwarf = true; + parse_perf_probe_point(argv[0], pev); /* Copy arguments and ensure return probe has no C argument */ - pp->nr_args = argc - 1; - pp->args = xzalloc(sizeof(char *) * pp->nr_args); - for (i = 0; i < pp->nr_args; i++) { - pp->args[i] = xstrdup(argv[i + 1]); - if (is_c_varname(pp->args[i])) { - if (pp->retprobe) - semantic_error("You can't specify local" - " variable for kretprobe"); - *need_dwarf = true; - } + pev->nargs = argc - 1; + pev->args = xzalloc(sizeof(struct perf_probe_arg) * pev->nargs); + for (i = 0; i < pev->nargs; i++) { + pev->args[i].name = xstrdup(argv[i + 1]); + if (is_c_varname(pev->args[i].name) && pev->point.retprobe) + semantic_error("You can't specify local variable for" + " kretprobe"); } argv_free(argv); } +/* Return true if this perf_probe_event requires debuginfo */ +bool perf_probe_event_need_dwarf(struct perf_probe_event *pev) +{ + int i; + + if (pev->point.file || pev->point.line || pev->point.lazy_line) + return true; + + for (i = 0; i < pev->nargs; i++) + if (is_c_varname(pev->args[i].name)) + return true; + + return false; +} + /* Parse kprobe_events event into struct probe_point */ -void parse_trace_kprobe_event(const char *str, struct probe_point *pp) +void parse_kprobe_trace_command(const char *cmd, struct kprobe_trace_event *tev) { + struct kprobe_trace_point *tp = &tev->point; char pr; char *p; int ret, i, argc; char **argv; - pr_debug("Parsing kprobe_events: %s\n", str); - argv = argv_split(str, &argc); + pr_debug("Parsing kprobe_events: %s\n", cmd); + argv = argv_split(cmd, &argc); if (!argv) die("argv_split failed."); if (argc < 2) @@ -313,47 +324,46 @@ void parse_trace_kprobe_event(const char *str, struct probe_point *pp) /* Scan event and group name. */ ret = sscanf(argv[0], "%c:%a[^/ \t]/%a[^ \t]", - &pr, (float *)(void *)&pp->group, - (float *)(void *)&pp->event); + &pr, (float *)(void *)&tev->group, + (float *)(void *)&tev->event); if (ret != 3) semantic_error("Failed to parse event name: %s", argv[0]); - pr_debug("Group:%s Event:%s probe:%c\n", pp->group, pp->event, pr); + pr_debug("Group:%s Event:%s probe:%c\n", tev->group, tev->event, pr); - pp->retprobe = (pr == 'r'); + tp->retprobe = (pr == 'r'); /* Scan function name and offset */ - ret = sscanf(argv[1], "%a[^+]+%d", (float *)(void *)&pp->function, - &pp->offset); + ret = sscanf(argv[1], "%a[^+]+%lu", (float *)(void *)&tp->symbol, + &tp->offset); if (ret == 1) - pp->offset = 0; - - /* kprobe_events doesn't have this information */ - pp->line = 0; - pp->file = NULL; + tp->offset = 0; - pp->nr_args = argc - 2; - pp->args = xzalloc(sizeof(char *) * pp->nr_args); - for (i = 0; i < pp->nr_args; i++) { + tev->nargs = argc - 2; + tev->args = xzalloc(sizeof(struct kprobe_trace_arg) * tev->nargs); + for (i = 0; i < tev->nargs; i++) { p = strchr(argv[i + 2], '='); if (p) /* We don't need which register is assigned. */ - *p = '\0'; - pp->args[i] = xstrdup(argv[i + 2]); + *p++ = '\0'; + else + p = argv[i + 2]; + tev->args[i].name = xstrdup(argv[i + 2]); + /* TODO: parse regs and offset */ + tev->args[i].value = xstrdup(p); } argv_free(argv); } -/* Synthesize only probe point (not argument) */ -int synthesize_perf_probe_point(struct probe_point *pp) +/* Compose only probe point (not argument) */ +static char *synthesize_perf_probe_point(struct perf_probe_point *pp) { char *buf; char offs[64] = "", line[64] = ""; int ret; - pp->probes[0] = buf = xzalloc(MAX_CMDLEN); - pp->found = 1; + buf = xzalloc(MAX_CMDLEN); if (pp->offset) { - ret = e_snprintf(offs, 64, "+%d", pp->offset); + ret = e_snprintf(offs, 64, "+%lu", pp->offset); if (ret <= 0) goto error; } @@ -368,68 +378,209 @@ int synthesize_perf_probe_point(struct probe_point *pp) offs, pp->retprobe ? "%return" : "", line); else ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", pp->file, line); - if (ret <= 0) { + if (ret <= 0) + goto error; + + return buf; error: - free(pp->probes[0]); - pp->probes[0] = NULL; - pp->found = 0; - } - return ret; + die("Failed to synthesize perf probe point: %s", strerror(-ret)); } -int synthesize_perf_probe_event(struct probe_point *pp) +#if 0 +char *synthesize_perf_probe_command(struct perf_probe_event *pev) { char *buf; int i, len, ret; - len = synthesize_perf_probe_point(pp); - if (len < 0) - return 0; + buf = synthesize_perf_probe_point(&pev->point); + if (!buf) + return NULL; - buf = pp->probes[0]; - for (i = 0; i < pp->nr_args; i++) { + len = strlen(buf); + for (i = 0; i < pev->nargs; i++) { ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s", - pp->args[i]); - if (ret <= 0) - goto error; + pev->args[i].name); + if (ret <= 0) { + free(buf); + return NULL; + } len += ret; } - pp->found = 1; - return pp->found; -error: - free(pp->probes[0]); - pp->probes[0] = NULL; + return buf; +} +#endif + +static int __synthesize_kprobe_trace_arg_ref(struct kprobe_trace_arg_ref *ref, + char **buf, size_t *buflen, + int depth) +{ + int ret; + if (ref->next) { + depth = __synthesize_kprobe_trace_arg_ref(ref->next, buf, + buflen, depth + 1); + if (depth < 0) + goto out; + } + + ret = e_snprintf(*buf, *buflen, "%+ld(", ref->offset); + if (ret < 0) + depth = ret; + else { + *buf += ret; + *buflen -= ret; + } +out: + return depth; - return ret; } -int synthesize_trace_kprobe_event(struct probe_point *pp) +static int synthesize_kprobe_trace_arg(struct kprobe_trace_arg *arg, + char *buf, size_t buflen) { + int ret, depth = 0; + char *tmp = buf; + + /* Argument name or separator */ + if (arg->name) + ret = e_snprintf(buf, buflen, " %s=", arg->name); + else + ret = e_snprintf(buf, buflen, " "); + if (ret < 0) + return ret; + buf += ret; + buflen -= ret; + + /* Dereferencing arguments */ + if (arg->ref) { + depth = __synthesize_kprobe_trace_arg_ref(arg->ref, &buf, + &buflen, 1); + if (depth < 0) + return depth; + } + + /* Print argument value */ + ret = e_snprintf(buf, buflen, "%s", arg->value); + if (ret < 0) + return ret; + buf += ret; + buflen -= ret; + + /* Closing */ + while (depth--) { + ret = e_snprintf(buf, buflen, ")"); + if (ret < 0) + return ret; + buf += ret; + buflen -= ret; + } + + return buf - tmp; +} + +char *synthesize_kprobe_trace_command(struct kprobe_trace_event *tev) +{ + struct kprobe_trace_point *tp = &tev->point; char *buf; int i, len, ret; - pp->probes[0] = buf = xzalloc(MAX_CMDLEN); - ret = e_snprintf(buf, MAX_CMDLEN, "%s+%d", pp->function, pp->offset); - if (ret <= 0) + buf = xzalloc(MAX_CMDLEN); + len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s+%lu", + tp->retprobe ? 'r' : 'p', + tev->group, tev->event, + tp->symbol, tp->offset); + if (len <= 0) goto error; - len = ret; - for (i = 0; i < pp->nr_args; i++) { - ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s", - pp->args[i]); + for (i = 0; i < tev->nargs; i++) { + ret = synthesize_kprobe_trace_arg(&tev->args[i], buf + len, + MAX_CMDLEN - len); if (ret <= 0) goto error; len += ret; } - pp->found = 1; - return pp->found; + return buf; error: - free(pp->probes[0]); - pp->probes[0] = NULL; + free(buf); + return NULL; +} - return ret; +void convert_to_perf_probe_event(struct kprobe_trace_event *tev, + struct perf_probe_event *pev) +{ + char buf[64]; + int i; + + pev->event = xstrdup(tev->event); + pev->group = xstrdup(tev->group); + + /* Convert trace_point to probe_point */ + pev->point.function = xstrdup(tev->point.symbol); + pev->point.offset = tev->point.offset; + pev->point.retprobe = tev->point.retprobe; + + /* Convert trace_arg to probe_arg */ + pev->nargs = tev->nargs; + pev->args = xzalloc(sizeof(struct perf_probe_arg) * pev->nargs); + for (i = 0; i < tev->nargs; i++) + if (tev->args[i].name) + pev->args[i].name = xstrdup(tev->args[i].name); + else { + synthesize_kprobe_trace_arg(&tev->args[i], buf, 64); + pev->args[i].name = xstrdup(buf); + } +} + +void clear_perf_probe_event(struct perf_probe_event *pev) +{ + struct perf_probe_point *pp = &pev->point; + int i; + + if (pev->event) + free(pev->event); + if (pev->group) + free(pev->group); + if (pp->file) + free(pp->file); + if (pp->function) + free(pp->function); + if (pp->lazy_line) + free(pp->lazy_line); + for (i = 0; i < pev->nargs; i++) + if (pev->args[i].name) + free(pev->args[i].name); + if (pev->args) + free(pev->args); + memset(pev, 0, sizeof(*pev)); +} + +void clear_kprobe_trace_event(struct kprobe_trace_event *tev) +{ + struct kprobe_trace_arg_ref *ref, *next; + int i; + + if (tev->event) + free(tev->event); + if (tev->group) + free(tev->group); + if (tev->point.symbol) + free(tev->point.symbol); + for (i = 0; i < tev->nargs; i++) { + if (tev->args[i].name) + free(tev->args[i].name); + if (tev->args[i].value) + free(tev->args[i].value); + ref = tev->args[i].ref; + while (ref) { + next = ref->next; + free(ref); + ref = next; + } + } + if (tev->args) + free(tev->args); + memset(tev, 0, sizeof(*tev)); } static int open_kprobe_events(bool readwrite) @@ -458,7 +609,7 @@ static int open_kprobe_events(bool readwrite) } /* Get raw string list of current kprobe_events */ -static struct strlist *get_trace_kprobe_event_rawlist(int fd) +static struct strlist *get_kprobe_trace_command_rawlist(int fd) { int ret, idx; FILE *fp; @@ -486,99 +637,82 @@ static struct strlist *get_trace_kprobe_event_rawlist(int fd) return sl; } -/* Free and zero clear probe_point */ -static void clear_probe_point(struct probe_point *pp) -{ - int i; - - if (pp->event) - free(pp->event); - if (pp->group) - free(pp->group); - if (pp->function) - free(pp->function); - if (pp->file) - free(pp->file); - if (pp->lazy_line) - free(pp->lazy_line); - for (i = 0; i < pp->nr_args; i++) - free(pp->args[i]); - if (pp->args) - free(pp->args); - for (i = 0; i < pp->found; i++) - free(pp->probes[i]); - memset(pp, 0, sizeof(*pp)); -} - /* Show an event */ -static void show_perf_probe_event(const char *event, const char *place, - struct probe_point *pp) +static void show_perf_probe_event(struct perf_probe_event *pev) { int i, ret; char buf[128]; + char *place; - ret = e_snprintf(buf, 128, "%s:%s", pp->group, event); + /* Synthesize only event probe point */ + place = synthesize_perf_probe_point(&pev->point); + + ret = e_snprintf(buf, 128, "%s:%s", pev->group, pev->event); if (ret < 0) die("Failed to copy event: %s", strerror(-ret)); printf(" %-40s (on %s", buf, place); - if (pp->nr_args > 0) { + if (pev->nargs > 0) { printf(" with"); - for (i = 0; i < pp->nr_args; i++) - printf(" %s", pp->args[i]); + for (i = 0; i < pev->nargs; i++) + printf(" %s", pev->args[i].name); } printf(")\n"); + free(place); } /* List up current perf-probe events */ void show_perf_probe_events(void) { int fd; - struct probe_point pp; + struct kprobe_trace_event tev; + struct perf_probe_event pev; struct strlist *rawlist; struct str_node *ent; setup_pager(); - memset(&pp, 0, sizeof(pp)); + + memset(&tev, 0, sizeof(tev)); + memset(&pev, 0, sizeof(pev)); fd = open_kprobe_events(false); - rawlist = get_trace_kprobe_event_rawlist(fd); + rawlist = get_kprobe_trace_command_rawlist(fd); close(fd); strlist__for_each(ent, rawlist) { - parse_trace_kprobe_event(ent->s, &pp); - /* Synthesize only event probe point */ - synthesize_perf_probe_point(&pp); + parse_kprobe_trace_command(ent->s, &tev); + convert_to_perf_probe_event(&tev, &pev); /* Show an event */ - show_perf_probe_event(pp.event, pp.probes[0], &pp); - clear_probe_point(&pp); + show_perf_probe_event(&pev); + clear_perf_probe_event(&pev); + clear_kprobe_trace_event(&tev); } strlist__delete(rawlist); } /* Get current perf-probe event names */ -static struct strlist *get_perf_event_names(int fd, bool include_group) +static struct strlist *get_kprobe_trace_event_names(int fd, bool include_group) { char buf[128]; struct strlist *sl, *rawlist; struct str_node *ent; - struct probe_point pp; + struct kprobe_trace_event tev; - memset(&pp, 0, sizeof(pp)); - rawlist = get_trace_kprobe_event_rawlist(fd); + memset(&tev, 0, sizeof(tev)); + rawlist = get_kprobe_trace_command_rawlist(fd); sl = strlist__new(true, NULL); strlist__for_each(ent, rawlist) { - parse_trace_kprobe_event(ent->s, &pp); + parse_kprobe_trace_command(ent->s, &tev); if (include_group) { - if (e_snprintf(buf, 128, "%s:%s", pp.group, - pp.event) < 0) + if (e_snprintf(buf, 128, "%s:%s", tev.group, + tev.event) < 0) die("Failed to copy group:event name."); strlist__add(sl, buf); } else - strlist__add(sl, pp.event); - clear_probe_point(&pp); + strlist__add(sl, tev.event); + clear_kprobe_trace_event(&tev); } strlist__delete(rawlist); @@ -586,9 +720,10 @@ static struct strlist *get_perf_event_names(int fd, bool include_group) return sl; } -static void write_trace_kprobe_event(int fd, const char *buf) +static void write_kprobe_trace_event(int fd, struct kprobe_trace_event *tev) { int ret; + char *buf = synthesize_kprobe_trace_command(tev); pr_debug("Writing event: %s\n", buf); if (!probe_event_dry_run) { @@ -596,6 +731,7 @@ static void write_trace_kprobe_event(int fd, const char *buf) if (ret <= 0) die("Failed to write event: %s", strerror(errno)); } + free(buf); } static void get_new_event_name(char *buf, size_t len, const char *base, @@ -628,81 +764,83 @@ static void get_new_event_name(char *buf, size_t len, const char *base, die("Too many events are on the same function."); } -static void __add_trace_kprobe_events(struct probe_point *probes, - int nr_probes, bool force_add) +static void __add_kprobe_trace_events(struct perf_probe_event *pev, + struct kprobe_trace_event *tevs, + int ntevs, bool allow_suffix) { - int i, j, fd; - struct probe_point *pp; - char buf[MAX_CMDLEN]; - char event[64]; + int i, fd; + struct kprobe_trace_event *tev; + char buf[64]; + const char *event, *group; struct strlist *namelist; - bool allow_suffix; fd = open_kprobe_events(true); /* Get current event names */ - namelist = get_perf_event_names(fd, false); - - for (j = 0; j < nr_probes; j++) { - pp = probes + j; - if (!pp->event) - pp->event = xstrdup(pp->function); - if (!pp->group) - pp->group = xstrdup(PERFPROBE_GROUP); - /* If force_add is true, suffix search is allowed */ - allow_suffix = force_add; - for (i = 0; i < pp->found; i++) { - /* Get an unused new event name */ - get_new_event_name(event, 64, pp->event, namelist, - allow_suffix); - snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s\n", - pp->retprobe ? 'r' : 'p', - pp->group, event, - pp->probes[i]); - write_trace_kprobe_event(fd, buf); - printf("Added new event:\n"); - /* Get the first parameter (probe-point) */ - sscanf(pp->probes[i], "%s", buf); - show_perf_probe_event(event, buf, pp); - /* Add added event name to namelist */ - strlist__add(namelist, event); - /* - * Probes after the first probe which comes from same - * user input are always allowed to add suffix, because - * there might be several addresses corresponding to - * one code line. - */ - allow_suffix = true; - } + namelist = get_kprobe_trace_event_names(fd, false); + + printf("Add new event%s\n", (ntevs > 1) ? "s:" : ":"); + for (i = 0; i < ntevs; i++) { + tev = &tevs[i]; + if (pev->event) + event = pev->event; + else + if (pev->point.function) + event = pev->point.function; + else + event = tev->point.symbol; + if (pev->group) + group = pev->group; + else + group = PERFPROBE_GROUP; + + /* Get an unused new event name */ + get_new_event_name(buf, 64, event, namelist, allow_suffix); + event = buf; + + tev->event = xstrdup(event); + tev->group = xstrdup(group); + write_kprobe_trace_event(fd, tev); + /* Add added event name to namelist */ + strlist__add(namelist, event); + + /* Trick here - save current event/group */ + event = pev->event; + group = pev->group; + pev->event = tev->event; + pev->group = tev->group; + show_perf_probe_event(pev); + /* Trick here - restore current event/group */ + pev->event = (char *)event; + pev->group = (char *)group; + + /* + * Probes after the first probe which comes from same + * user input are always allowed to add suffix, because + * there might be several addresses corresponding to + * one code line. + */ + allow_suffix = true; } /* Show how to use the event. */ printf("\nYou can now use it on all perf tools, such as:\n\n"); - printf("\tperf record -e %s:%s -a sleep 1\n\n", PERFPROBE_GROUP, event); + printf("\tperf record -e %s:%s -a sleep 1\n\n", tev->group, tev->event); strlist__delete(namelist); close(fd); } -/* Currently just checking function name from symbol map */ -static void evaluate_probe_point(struct probe_point *pp) +static int convert_to_kprobe_trace_events(struct perf_probe_event *pev, + struct kprobe_trace_event **tevs) { struct symbol *sym; - sym = map__find_symbol_by_name(kmaps[MAP__FUNCTION], - pp->function, NULL); - if (!sym) - die("Kernel symbol \'%s\' not found - probe not added.", - pp->function); -} - -void add_trace_kprobe_events(struct probe_point *probes, int nr_probes, - bool force_add, bool need_dwarf) -{ - int i, ret; - struct probe_point *pp; + bool need_dwarf; #ifndef NO_DWARF_SUPPORT int fd; #endif - /* Add probes */ - init_vmlinux(); + int ntevs = 0, i; + struct kprobe_trace_event *tev; + + need_dwarf = perf_probe_event_need_dwarf(pev); if (need_dwarf) #ifdef NO_DWARF_SUPPORT @@ -721,57 +859,90 @@ void add_trace_kprobe_events(struct probe_point *probes, int nr_probes, } /* Searching probe points */ - for (i = 0; i < nr_probes; i++) { - pp = &probes[i]; - if (pp->found) - continue; - - lseek(fd, SEEK_SET, 0); - ret = find_probe_point(fd, pp); - if (ret > 0) - continue; - if (ret == 0) { /* No error but failed to find probe point. */ - synthesize_perf_probe_point(pp); - die("Probe point '%s' not found. - probe not added.", - pp->probes[0]); - } - /* Error path */ - if (need_dwarf) { - if (ret == -ENOENT) - pr_warning("No dwarf info found in the vmlinux - please rebuild with CONFIG_DEBUG_INFO=y.\n"); - die("Could not analyze debuginfo."); - } - pr_debug("An error occurred in debuginfo analysis." - " Try to use symbols.\n"); - break; + ntevs = find_kprobe_trace_events(fd, pev, tevs); + + if (ntevs > 0) /* Found */ + goto found; + + if (ntevs == 0) /* No error but failed to find probe point. */ + die("Probe point '%s' not found. - probe not added.", + synthesize_perf_probe_point(&pev->point)); + + /* Error path */ + if (need_dwarf) { + if (ntevs == -ENOENT) + pr_warning("No dwarf info found in the vmlinux - please rebuild with CONFIG_DEBUG_INFO=y.\n"); + die("Could not analyze debuginfo."); } - close(fd); + pr_debug("An error occurred in debuginfo analysis." + " Try to use symbols.\n"); end_dwarf: #endif /* !NO_DWARF_SUPPORT */ - /* Synthesize probes without dwarf */ - for (i = 0; i < nr_probes; i++) { - pp = &probes[i]; - if (pp->found) /* This probe is already found. */ - continue; + /* Allocate trace event buffer */ + ntevs = 1; + tev = *tevs = xzalloc(sizeof(struct kprobe_trace_event)); + + /* Copy parameters */ + tev->point.symbol = xstrdup(pev->point.function); + tev->point.offset = pev->point.offset; + tev->nargs = pev->nargs; + if (tev->nargs) { + tev->args = xzalloc(sizeof(struct kprobe_trace_arg) + * tev->nargs); + for (i = 0; i < tev->nargs; i++) + tev->args[i].value = xstrdup(pev->args[i].name); + } + + /* Currently just checking function name from symbol map */ + sym = map__find_symbol_by_name(kmaps[MAP__FUNCTION], + tev->point.symbol, NULL); + if (!sym) + die("Kernel symbol \'%s\' not found - probe not added.", + tev->point.symbol); +found: + close(fd); + return ntevs; +} + +struct __event_package { + struct perf_probe_event *pev; + struct kprobe_trace_event *tevs; + int ntevs; +}; - evaluate_probe_point(pp); - ret = synthesize_trace_kprobe_event(pp); - if (ret == -E2BIG) - die("probe point definition becomes too long."); - else if (ret < 0) - die("Failed to synthesize a probe point."); +void add_perf_probe_events(struct perf_probe_event *pevs, int npevs, + bool force_add) +{ + int i; + struct __event_package *pkgs; + + pkgs = xzalloc(sizeof(struct __event_package) * npevs); + + /* Init vmlinux path */ + init_vmlinux(); + + /* Loop 1: convert all events */ + for (i = 0; i < npevs; i++) { + pkgs[i].pev = &pevs[i]; + /* Convert with or without debuginfo */ + pkgs[i].ntevs = convert_to_kprobe_trace_events(pkgs[i].pev, + &pkgs[i].tevs); } - /* Settng up probe points */ - __add_trace_kprobe_events(probes, nr_probes, force_add); + /* Loop 2: add all events */ + for (i = 0; i < npevs; i++) + __add_kprobe_trace_events(pkgs[i].pev, pkgs[i].tevs, + pkgs[i].ntevs, force_add); + /* TODO: cleanup all trace events? */ } static void __del_trace_kprobe_event(int fd, struct str_node *ent) { char *p; char buf[128]; + int ret; /* Convert from perf-probe event to trace-kprobe event */ if (e_snprintf(buf, 128, "-:%s", ent->s) < 0) @@ -781,7 +952,10 @@ static void __del_trace_kprobe_event(int fd, struct str_node *ent) die("Internal error: %s should have ':' but not.", ent->s); *p = '/'; - write_trace_kprobe_event(fd, buf); + pr_debug("Writing event: %s\n", buf); + ret = write(fd, buf, strlen(buf)); + if (ret <= 0) + die("Failed to write event: %s", strerror(errno)); printf("Remove event: %s\n", ent->s); } @@ -814,7 +988,7 @@ static void del_trace_kprobe_event(int fd, const char *group, pr_info("Info: event \"%s\" does not exist, could not remove it.\n", buf); } -void del_trace_kprobe_events(struct strlist *dellist) +void del_perf_probe_events(struct strlist *dellist) { int fd; const char *group, *event; @@ -824,7 +998,7 @@ void del_trace_kprobe_events(struct strlist *dellist) fd = open_kprobe_events(true); /* Get current event names */ - namelist = get_perf_event_names(fd, true); + namelist = get_kprobe_trace_event_names(fd, true); strlist__for_each(ent, dellist) { str = xstrdup(ent->s); diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h index 703b887..2a2f0a2 100644 --- a/tools/perf/util/probe-event.h +++ b/tools/perf/util/probe-event.h @@ -2,24 +2,113 @@ #define _PROBE_EVENT_H #include -#include "probe-finder.h" #include "strlist.h" extern bool probe_event_dry_run; -extern void parse_line_range_desc(const char *arg, struct line_range *lr); -extern void parse_perf_probe_event(const char *str, struct probe_point *pp, - bool *need_dwarf); -extern int synthesize_perf_probe_point(struct probe_point *pp); -extern int synthesize_perf_probe_event(struct probe_point *pp); -extern void parse_trace_kprobe_event(const char *str, struct probe_point *pp); -extern int synthesize_trace_kprobe_event(struct probe_point *pp); -extern void add_trace_kprobe_events(struct probe_point *probes, int nr_probes, - bool force_add, bool need_dwarf); -extern void del_trace_kprobe_events(struct strlist *dellist); +/* kprobe-tracer tracing point */ +struct kprobe_trace_point { + char *symbol; /* Base symbol */ + unsigned long offset; /* Offset from symbol */ + bool retprobe; /* Return probe flag */ +}; + +/* kprobe-tracer tracing argument referencing offset */ +struct kprobe_trace_arg_ref { + struct kprobe_trace_arg_ref *next; /* Next reference */ + long offset; /* Offset value */ +}; + +/* kprobe-tracer tracing argument */ +struct kprobe_trace_arg { + char *name; /* Argument name */ + char *value; /* Base value */ + struct kprobe_trace_arg_ref *ref; /* Referencing offset */ +}; + +/* kprobe-tracer tracing event (point + arg) */ +struct kprobe_trace_event { + char *event; /* Event name */ + char *group; /* Group name */ + struct kprobe_trace_point point; /* Trace point */ + int nargs; /* Number of args */ + struct kprobe_trace_arg *args; /* Arguments */ +}; + +/* Perf probe probing point */ +struct perf_probe_point { + char *file; /* File path */ + char *function; /* Function name */ + int line; /* Line number */ + char *lazy_line; /* Lazy matching pattern */ + unsigned long offset; /* Offset from function entry */ + bool retprobe; /* Return probe flag */ +}; + +/* Perf probe probing argument */ +struct perf_probe_arg { + char *name; /* Argument name */ +}; + +/* Perf probe probing event (point + arg) */ +struct perf_probe_event { + char *event; /* Event name */ + char *group; /* Group name */ + struct perf_probe_point point; /* Probe point */ + int nargs; /* Number of arguments */ + struct perf_probe_arg *args; /* Arguments */ +}; + + +/* Line number container */ +struct line_node { + struct list_head list; + unsigned int line; +}; + +/* Line range */ +struct line_range { + char *file; /* File name */ + char *function; /* Function name */ + unsigned int start; /* Start line number */ + unsigned int end; /* End line number */ + int offset; /* Start line offset */ + char *path; /* Real path name */ + struct list_head line_list; /* Visible lines */ +}; + +/* Command string to events */ +extern void parse_perf_probe_command(const char *cmd, + struct perf_probe_event *pev); +extern void parse_kprobe_trace_command(const char *cmd, + struct kprobe_trace_event *tev); + +/* Events to command string */ +extern char *synthesize_perf_probe_command(struct perf_probe_event *pev); +extern char *synthesize_kprobe_trace_command(struct kprobe_trace_event *tev); + +/* Check the perf_probe_event needs debuginfo */ +extern bool perf_probe_event_need_dwarf(struct perf_probe_event *pev); + +/* Convert from kprobe_trace_event to perf_probe_event */ +extern void convert_to_perf_probe_event(struct kprobe_trace_event *tev, + struct perf_probe_event *pev); + +/* Release event contents */ +extern void clear_perf_probe_event(struct perf_probe_event *pev); +extern void clear_kprobe_trace_event(struct kprobe_trace_event *tev); + +/* Command string to line-range */ +extern void parse_line_range_desc(const char *cmd, struct line_range *lr); + + +extern void add_perf_probe_events(struct perf_probe_event *pevs, int ntevs, + bool force_add); +extern void del_perf_probe_events(struct strlist *dellist); extern void show_perf_probe_events(void); extern void show_line_range(struct line_range *lr); + /* Maximum index number of event-name postfix */ #define MAX_EVENT_INDEX 1024 diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 3942e14..251b4c4 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -319,19 +319,20 @@ static Dwarf_Die *die_find_variable(Dwarf_Die *sp_die, const char *name, */ /* Show a location */ -static void show_location(Dwarf_Op *op, struct probe_finder *pf) +static void convert_location(Dwarf_Op *op, struct probe_finder *pf) { unsigned int regn; Dwarf_Word offs = 0; - int deref = 0, ret; + bool ref = false; const char *regs; + struct kprobe_trace_arg *tvar = pf->tvar; /* TODO: support CFA */ /* If this is based on frame buffer, set the offset */ if (op->atom == DW_OP_fbreg) { if (pf->fb_ops == NULL) die("The attribute of frame base is not supported.\n"); - deref = 1; + ref = true; offs = op->number; op = &pf->fb_ops[0]; } @@ -339,13 +340,13 @@ static void show_location(Dwarf_Op *op, struct probe_finder *pf) if (op->atom >= DW_OP_breg0 && op->atom <= DW_OP_breg31) { regn = op->atom - DW_OP_breg0; offs += op->number; - deref = 1; + ref = true; } else if (op->atom >= DW_OP_reg0 && op->atom <= DW_OP_reg31) { regn = op->atom - DW_OP_reg0; } else if (op->atom == DW_OP_bregx) { regn = op->number; offs += op->number2; - deref = 1; + ref = true; } else if (op->atom == DW_OP_regx) { regn = op->number; } else @@ -355,17 +356,15 @@ static void show_location(Dwarf_Op *op, struct probe_finder *pf) if (!regs) die("%u exceeds max register number.", regn); - if (deref) - ret = snprintf(pf->buf, pf->len, " %s=%+jd(%s)", - pf->var, (intmax_t)offs, regs); - else - ret = snprintf(pf->buf, pf->len, " %s=%s", pf->var, regs); - DIE_IF(ret < 0); - DIE_IF(ret >= pf->len); + tvar->value = xstrdup(regs); + if (ref) { + tvar->ref = xzalloc(sizeof(struct kprobe_trace_arg_ref)); + tvar->ref->offset = (long)offs; + } } /* Show a variables in kprobe event format */ -static void show_variable(Dwarf_Die *vr_die, struct probe_finder *pf) +static void convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf) { Dwarf_Attribute attr; Dwarf_Op *expr; @@ -379,50 +378,51 @@ static void show_variable(Dwarf_Die *vr_die, struct probe_finder *pf) if (ret <= 0 || nexpr == 0) goto error; - show_location(expr, pf); + convert_location(expr, pf); /* *expr will be cached in libdw. Don't free it. */ return ; error: /* TODO: Support const_value */ die("Failed to find the location of %s at this address.\n" - " Perhaps, it has been optimized out.", pf->var); + " Perhaps, it has been optimized out.", pf->pvar->name); } /* Find a variable in a subprogram die */ static void find_variable(Dwarf_Die *sp_die, struct probe_finder *pf) { - int ret; Dwarf_Die vr_die; /* TODO: Support struct members and arrays */ - if (!is_c_varname(pf->var)) { - /* Output raw parameters */ - ret = snprintf(pf->buf, pf->len, " %s", pf->var); - DIE_IF(ret < 0); - DIE_IF(ret >= pf->len); - return ; + if (!is_c_varname(pf->pvar->name)) { + /* Copy raw parameters */ + pf->tvar->value = xstrdup(pf->pvar->name); + } else { + pf->tvar->name = xstrdup(pf->pvar->name); + pr_debug("Searching '%s' variable in context.\n", + pf->pvar->name); + /* Search child die for local variables and parameters. */ + if (!die_find_variable(sp_die, pf->pvar->name, &vr_die)) + die("Failed to find '%s' in this function.", + pf->pvar->name); + convert_variable(&vr_die, pf); } - - pr_debug("Searching '%s' variable in context.\n", pf->var); - /* Search child die for local variables and parameters. */ - if (!die_find_variable(sp_die, pf->var, &vr_die)) - die("Failed to find '%s' in this function.", pf->var); - - show_variable(&vr_die, pf); } /* Show a probe point to output buffer */ -static void show_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf) +static void convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf) { - struct probe_point *pp = pf->pp; + struct kprobe_trace_event *tev; Dwarf_Addr eaddr; Dwarf_Die die_mem; const char *name; - char tmp[MAX_PROBE_BUFFER]; - int ret, i, len; + int ret, i; Dwarf_Attribute fb_attr; size_t nops; + if (pf->ntevs == MAX_PROBES) + die("Too many( > %d) probe point found.\n", MAX_PROBES); + tev = &pf->tevs[pf->ntevs++]; + /* If no real subprogram, find a real one */ if (!sp_die || dwarf_tag(sp_die) != DW_TAG_subprogram) { sp_die = die_find_real_subprogram(&pf->cu_die, @@ -431,31 +431,18 @@ static void show_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf) die("Probe point is not found in subprograms."); } - /* Output name of probe point */ + /* Copy the name of probe point */ name = dwarf_diename(sp_die); if (name) { dwarf_entrypc(sp_die, &eaddr); - ret = snprintf(tmp, MAX_PROBE_BUFFER, "%s+%lu", name, - (unsigned long)(pf->addr - eaddr)); - /* Copy the function name if possible */ - if (!pp->function) { - pp->function = xstrdup(name); - pp->offset = (size_t)(pf->addr - eaddr); - } - } else { + tev->point.symbol = xstrdup(name); + tev->point.offset = (unsigned long)(pf->addr - eaddr); + } else /* This function has no name. */ - ret = snprintf(tmp, MAX_PROBE_BUFFER, "0x%jx", - (uintmax_t)pf->addr); - if (!pp->function) { - /* TODO: Use _stext */ - pp->function = xstrdup(""); - pp->offset = (size_t)pf->addr; - } - } - DIE_IF(ret < 0); - DIE_IF(ret >= MAX_PROBE_BUFFER); - len = ret; - pr_debug("Probe point found: %s\n", tmp); + tev->point.offset = (unsigned long)pf->addr; + + pr_debug("Probe point found: %s+%lu\n", tev->point.symbol, + tev->point.offset); /* Get the frame base attribute/ops */ dwarf_attr(sp_die, DW_AT_frame_base, &fb_attr); @@ -465,22 +452,16 @@ static void show_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf) /* Find each argument */ /* TODO: use dwarf_cfi_addrframe */ - for (i = 0; i < pp->nr_args; i++) { - pf->var = pp->args[i]; - pf->buf = &tmp[len]; - pf->len = MAX_PROBE_BUFFER - len; + tev->nargs = pf->pev->nargs; + tev->args = xzalloc(sizeof(struct kprobe_trace_arg) * tev->nargs); + for (i = 0; i < pf->pev->nargs; i++) { + pf->pvar = &pf->pev->args[i]; + pf->tvar = &tev->args[i]; find_variable(sp_die, pf); - len += strlen(pf->buf); } /* *pf->fb_ops will be cached in libdw. Don't free it. */ pf->fb_ops = NULL; - - if (pp->found == MAX_PROBES) - die("Too many( > %d) probe point found.\n", MAX_PROBES); - - pp->probes[pp->found] = xstrdup(tmp); - pp->found++; } /* Find probe point from its line number */ @@ -512,7 +493,7 @@ static void find_probe_point_by_line(struct probe_finder *pf) (int)i, lineno, (uintmax_t)addr); pf->addr = addr; - show_probe_point(NULL, pf); + convert_probe_point(NULL, pf); /* Continuing, because target line might be inlined. */ } } @@ -563,7 +544,7 @@ static void find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf) if (list_empty(&pf->lcache)) { /* Matching lazy line pattern */ ret = find_lazy_match_lines(&pf->lcache, pf->fname, - pf->pp->lazy_line); + pf->pev->point.lazy_line); if (ret <= 0) die("No matched lines found in %s.", pf->fname); } @@ -596,7 +577,7 @@ static void find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf) (int)i, lineno, (unsigned long long)addr); pf->addr = addr; - show_probe_point(sp_die, pf); + convert_probe_point(sp_die, pf); /* Continuing, because target line might be inlined. */ } /* TODO: deallocate lines, but how? */ @@ -605,7 +586,7 @@ static void find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf) static int probe_point_inline_cb(Dwarf_Die *in_die, void *data) { struct probe_finder *pf = (struct probe_finder *)data; - struct probe_point *pp = pf->pp; + struct perf_probe_point *pp = &pf->pev->point; if (pp->lazy_line) find_probe_point_lazy(in_die, pf); @@ -616,7 +597,7 @@ static int probe_point_inline_cb(Dwarf_Die *in_die, void *data) pr_debug("found inline addr: 0x%jx\n", (uintmax_t)pf->addr); - show_probe_point(in_die, pf); + convert_probe_point(in_die, pf); } return DWARF_CB_OK; @@ -626,7 +607,7 @@ static int probe_point_inline_cb(Dwarf_Die *in_die, void *data) static int probe_point_search_cb(Dwarf_Die *sp_die, void *data) { struct probe_finder *pf = (struct probe_finder *)data; - struct probe_point *pp = pf->pp; + struct perf_probe_point *pp = &pf->pev->point; /* Check tag and diename */ if (dwarf_tag(sp_die) != DW_TAG_subprogram || @@ -646,7 +627,7 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data) pf->addr = die_get_entrypc(sp_die); pf->addr += pp->offset; /* TODO: Check the address in this function */ - show_probe_point(sp_die, pf); + convert_probe_point(sp_die, pf); } } else /* Inlined function: search instances */ @@ -660,20 +641,25 @@ static void find_probe_point_by_func(struct probe_finder *pf) dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, pf, 0); } -/* Find a probe point */ -int find_probe_point(int fd, struct probe_point *pp) +/* Find kprobe_trace_events specified by perf_probe_event from debuginfo */ +int find_kprobe_trace_events(int fd, struct perf_probe_event *pev, + struct kprobe_trace_event **tevs) { - struct probe_finder pf = {.pp = pp}; + struct probe_finder pf = {.pev = pev}; + struct perf_probe_point *pp = &pev->point; Dwarf_Off off, noff; size_t cuhl; Dwarf_Die *diep; Dwarf *dbg; + pf.tevs = xzalloc(sizeof(struct kprobe_trace_event) * MAX_PROBES); + *tevs = pf.tevs; + pf.ntevs = 0; + dbg = dwarf_begin(fd, DWARF_C_READ); if (!dbg) return -ENOENT; - pp->found = 0; off = 0; line_list__init(&pf.lcache); /* Loop on CUs (Compilation Unit) */ @@ -704,7 +690,7 @@ int find_probe_point(int fd, struct probe_point *pp) line_list__free(&pf.lcache); dwarf_end(dbg); - return pp->found; + return pf.ntevs; } /* Find line range from its line number */ diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h index 21f7354..4949526 100644 --- a/tools/perf/util/probe-finder.h +++ b/tools/perf/util/probe-finder.h @@ -3,6 +3,7 @@ #include #include "util.h" +#include "probe-event.h" #define MAX_PATH_LEN 256 #define MAX_PROBE_BUFFER 1024 @@ -14,67 +15,32 @@ static inline int is_c_varname(const char *name) return isalpha(name[0]) || name[0] == '_'; } -struct probe_point { - char *event; /* Event name */ - char *group; /* Event group */ - - /* Inputs */ - char *file; /* File name */ - int line; /* Line number */ - char *lazy_line; /* Lazy line pattern */ - - char *function; /* Function name */ - int offset; /* Offset bytes */ - - int nr_args; /* Number of arguments */ - char **args; /* Arguments */ - - int retprobe; /* Return probe */ - - /* Output */ - int found; /* Number of found probe points */ - char *probes[MAX_PROBES]; /* Output buffers (will be allocated)*/ -}; - -/* Line number container */ -struct line_node { - struct list_head list; - unsigned int line; -}; - -/* Line range */ -struct line_range { - char *file; /* File name */ - char *function; /* Function name */ - unsigned int start; /* Start line number */ - unsigned int end; /* End line number */ - int offset; /* Start line offset */ - char *path; /* Real path name */ - struct list_head line_list; /* Visible lines */ -}; - #ifndef NO_DWARF_SUPPORT -extern int find_probe_point(int fd, struct probe_point *pp); +/* Find kprobe_trace_events specified by perf_probe_event from debuginfo */ +extern int find_kprobe_trace_events(int fd, struct perf_probe_event *pev, + struct kprobe_trace_event **tevs); + extern int find_line_range(int fd, struct line_range *lr); #include #include struct probe_finder { - struct probe_point *pp; /* Target probe point */ + struct perf_probe_event *pev; /* Target probe event */ + int ntevs; /* number of trace events */ + struct kprobe_trace_event *tevs; /* Result trace events */ /* For function searching */ Dwarf_Addr addr; /* Address */ - const char *fname; /* File name */ + const char *fname; /* Real file name */ int lno; /* Line number */ Dwarf_Die cu_die; /* Current CU */ + struct list_head lcache; /* Line cache for lazy match */ /* For variable searching */ Dwarf_Op *fb_ops; /* Frame base attribute */ - const char *var; /* Current variable name */ - char *buf; /* Current output buffer */ - int len; /* Length of output buffer */ - struct list_head lcache; /* Line cache for lazy match */ + struct perf_probe_arg *pvar; /* Current target variable */ + struct kprobe_trace_arg *tvar; /* Current result variable */ }; struct line_finder { -- cgit v0.10.2 From fb1587d869a399554220e166d4b90b581a8ade01 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Tue, 16 Mar 2010 18:06:19 -0400 Subject: perf probe: List probes with line number and file name Improve --list to show current exist probes with line number and file name. This enables user easily to check which line is already probed. for example: ./perf probe --list probe:vfs_read (on vfs_read:8@linux-2.6-tip/fs/read_write.c) Signed-off-by: Masami Hiramatsu Cc: systemtap Cc: DLE Cc: Frederic Weisbecker Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Mike Galbraith Cc: Peter Zijlstra LKML-Reference: <20100316220619.32050.48702.stgit@localhost6.localdomain6> Signed-off-by: Ingo Molnar diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index b44ddfb..4e3c1ae 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -70,7 +70,6 @@ static int e_snprintf(char *str, size_t size, const char *format, ...) return ret; } - static struct map_groups kmap_groups; static struct map *kmaps[MAP__NR_TYPES]; @@ -357,27 +356,39 @@ void parse_kprobe_trace_command(const char *cmd, struct kprobe_trace_event *tev) /* Compose only probe point (not argument) */ static char *synthesize_perf_probe_point(struct perf_probe_point *pp) { - char *buf; - char offs[64] = "", line[64] = ""; - int ret; + char *buf, *tmp; + char offs[32] = "", line[32] = "", file[32] = ""; + int ret, len; buf = xzalloc(MAX_CMDLEN); if (pp->offset) { - ret = e_snprintf(offs, 64, "+%lu", pp->offset); + ret = e_snprintf(offs, 32, "+%lu", pp->offset); if (ret <= 0) goto error; } if (pp->line) { - ret = e_snprintf(line, 64, ":%d", pp->line); + ret = e_snprintf(line, 32, ":%d", pp->line); + if (ret <= 0) + goto error; + } + if (pp->file) { + len = strlen(pp->file) - 32; + if (len < 0) + len = 0; + tmp = strchr(pp->file + len, '/'); + if (!tmp) + tmp = pp->file + len - 1; + ret = e_snprintf(file, 32, "@%s", tmp + 1); if (ret <= 0) goto error; } if (pp->function) - ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s", pp->function, - offs, pp->retprobe ? "%return" : "", line); + ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s%s", pp->function, + offs, pp->retprobe ? "%return" : "", line, + file); else - ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", pp->file, line); + ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", file, line); if (ret <= 0) goto error; @@ -511,15 +522,32 @@ void convert_to_perf_probe_event(struct kprobe_trace_event *tev, { char buf[64]; int i; +#ifndef NO_DWARF_SUPPORT + struct symbol *sym; + int fd, ret = 0; - pev->event = xstrdup(tev->event); - pev->group = xstrdup(tev->group); - + sym = map__find_symbol_by_name(kmaps[MAP__FUNCTION], + tev->point.symbol, NULL); + if (sym) { + fd = open_vmlinux(); + ret = find_perf_probe_point(fd, sym->start + tev->point.offset, + &pev->point); + close(fd); + } + if (ret <= 0) { + pev->point.function = xstrdup(tev->point.symbol); + pev->point.offset = tev->point.offset; + } +#else /* Convert trace_point to probe_point */ pev->point.function = xstrdup(tev->point.symbol); pev->point.offset = tev->point.offset; +#endif pev->point.retprobe = tev->point.retprobe; + pev->event = xstrdup(tev->event); + pev->group = xstrdup(tev->group); + /* Convert trace_arg to probe_arg */ pev->nargs = tev->nargs; pev->args = xzalloc(sizeof(struct perf_probe_arg) * pev->nargs); @@ -650,7 +678,7 @@ static void show_perf_probe_event(struct perf_probe_event *pev) ret = e_snprintf(buf, 128, "%s:%s", pev->group, pev->event); if (ret < 0) die("Failed to copy event: %s", strerror(-ret)); - printf(" %-40s (on %s", buf, place); + printf(" %-20s (on %s", buf, place); if (pev->nargs > 0) { printf(" with"); @@ -671,6 +699,7 @@ void show_perf_probe_events(void) struct str_node *ent; setup_pager(); + init_vmlinux(); memset(&tev, 0, sizeof(tev)); memset(&pev, 0, sizeof(pev)); diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 251b4c4..e02b607 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -693,6 +693,76 @@ int find_kprobe_trace_events(int fd, struct perf_probe_event *pev, return pf.ntevs; } +/* Reverse search */ +int find_perf_probe_point(int fd, unsigned long addr, + struct perf_probe_point *ppt) +{ + Dwarf_Die cudie, spdie, indie; + Dwarf *dbg; + Dwarf_Line *line; + Dwarf_Addr laddr, eaddr; + const char *tmp; + int lineno, ret = 0; + + dbg = dwarf_begin(fd, DWARF_C_READ); + if (!dbg) + return -ENOENT; + + /* Find cu die */ + if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr, &cudie)) + return -EINVAL; + + /* Find a corresponding line */ + line = dwarf_getsrc_die(&cudie, (Dwarf_Addr)addr); + if (line) { + dwarf_lineaddr(line, &laddr); + if ((Dwarf_Addr)addr == laddr) { + dwarf_lineno(line, &lineno); + ppt->line = lineno; + + tmp = dwarf_linesrc(line, NULL, NULL); + DIE_IF(!tmp); + ppt->file = xstrdup(tmp); + ret = 1; + } + } + + /* Find a corresponding function */ + if (die_find_real_subprogram(&cudie, (Dwarf_Addr)addr, &spdie)) { + tmp = dwarf_diename(&spdie); + if (!tmp) + goto end; + + dwarf_entrypc(&spdie, &eaddr); + if (!lineno) { + /* We don't have a line number, let's use offset */ + ppt->function = xstrdup(tmp); + ppt->offset = addr - (unsigned long)eaddr; + ret = 1; + goto end; + } + if (die_find_inlinefunc(&spdie, (Dwarf_Addr)addr, &indie)) { + /* addr in an inline function */ + tmp = dwarf_diename(&indie); + if (!tmp) + goto end; + dwarf_decl_line(&indie, &lineno); + } else { + if (eaddr == addr) /* No offset: function entry */ + lineno = ppt->line; + else + dwarf_decl_line(&spdie, &lineno); + } + ppt->function = xstrdup(tmp); + ppt->line -= lineno; /* Make a relative line number */ + } + +end: + dwarf_end(dbg); + return ret; +} + + /* Find line range from its line number */ static void find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf) { diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h index 4949526..2f2307d 100644 --- a/tools/perf/util/probe-finder.h +++ b/tools/perf/util/probe-finder.h @@ -20,6 +20,10 @@ static inline int is_c_varname(const char *name) extern int find_kprobe_trace_events(int fd, struct perf_probe_event *pev, struct kprobe_trace_event **tevs); +/* Find a perf_probe_point from debuginfo */ +extern int find_perf_probe_point(int fd, unsigned long addr, + struct perf_probe_point *ppt); + extern int find_line_range(int fd, struct line_range *lr); #include -- cgit v0.10.2 From 7df2f32956cf0f1a45df38cd0e0fe0c3467580e8 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Tue, 16 Mar 2010 18:06:26 -0400 Subject: perf probe: Add data structure member access support Support accessing members in the data structures. With this, perf-probe accepts data-structure members(IOW, it now accepts dot '.' and arrow '->' operators) as probe arguemnts. e.g. ./perf probe --add 'schedule:44 rq->curr' ./perf probe --add 'vfs_read file->f_op->read file->f_path.dentry' Note that '>' can be interpreted as redirection in command-line. Signed-off-by: Masami Hiramatsu Cc: systemtap Cc: DLE Cc: Frederic Weisbecker Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Mike Galbraith Cc: Peter Zijlstra LKML-Reference: <20100316220626.32050.57552.stgit@localhost6.localdomain6> Signed-off-by: Ingo Molnar diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 4e3c1ae..64dea6c 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -262,6 +262,49 @@ static void parse_perf_probe_point(char *arg, struct perf_probe_event *pev) pp->lazy_line); } +/* Parse perf-probe event argument */ +static void parse_perf_probe_arg(const char *str, struct perf_probe_arg *arg) +{ + const char *tmp; + struct perf_probe_arg_field **fieldp; + + pr_debug("parsing arg: %s into ", str); + + tmp = strpbrk(str, "-."); + if (!is_c_varname(str) || !tmp) { + /* A variable, register, symbol or special value */ + arg->name = xstrdup(str); + pr_debug("%s\n", arg->name); + return; + } + + /* Structure fields */ + arg->name = xstrndup(str, tmp - str); + pr_debug("%s, ", arg->name); + fieldp = &arg->field; + + do { + *fieldp = xzalloc(sizeof(struct perf_probe_arg_field)); + if (*tmp == '.') { + str = tmp + 1; + (*fieldp)->ref = false; + } else if (tmp[1] == '>') { + str = tmp + 2; + (*fieldp)->ref = true; + } else + semantic_error("Argument parse error: %s", str); + + tmp = strpbrk(str, "-."); + if (tmp) { + (*fieldp)->name = xstrndup(str, tmp - str); + pr_debug("%s(%d), ", (*fieldp)->name, (*fieldp)->ref); + fieldp = &(*fieldp)->next; + } + } while (tmp); + (*fieldp)->name = xstrdup(str); + pr_debug("%s(%d)\n", (*fieldp)->name, (*fieldp)->ref); +} + /* Parse perf-probe event command */ void parse_perf_probe_command(const char *cmd, struct perf_probe_event *pev) { @@ -281,7 +324,7 @@ void parse_perf_probe_command(const char *cmd, struct perf_probe_event *pev) pev->nargs = argc - 1; pev->args = xzalloc(sizeof(struct perf_probe_arg) * pev->nargs); for (i = 0; i < pev->nargs; i++) { - pev->args[i].name = xstrdup(argv[i + 1]); + parse_perf_probe_arg(argv[i + 1], &pev->args[i]); if (is_c_varname(pev->args[i].name) && pev->point.retprobe) semantic_error("You can't specify local variable for" " kretprobe"); @@ -353,6 +396,33 @@ void parse_kprobe_trace_command(const char *cmd, struct kprobe_trace_event *tev) argv_free(argv); } +/* Compose only probe arg */ +int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len) +{ + struct perf_probe_arg_field *field = pa->field; + int ret; + char *tmp = buf; + + ret = e_snprintf(tmp, len, "%s", pa->name); + if (ret <= 0) + goto error; + tmp += ret; + len -= ret; + + while (field) { + ret = e_snprintf(tmp, len, "%s%s", field->ref ? "->" : ".", + field->name); + if (ret <= 0) + goto error; + tmp += ret; + len -= ret; + field = field->next; + } + return tmp - buf; +error: + die("Failed to synthesize perf probe argument: %s", strerror(-ret)); +} + /* Compose only probe point (not argument) */ static char *synthesize_perf_probe_point(struct perf_probe_point *pp) { @@ -563,6 +633,7 @@ void convert_to_perf_probe_event(struct kprobe_trace_event *tev, void clear_perf_probe_event(struct perf_probe_event *pev) { struct perf_probe_point *pp = &pev->point; + struct perf_probe_arg_field *field, *next; int i; if (pev->event) @@ -575,9 +646,18 @@ void clear_perf_probe_event(struct perf_probe_event *pev) free(pp->function); if (pp->lazy_line) free(pp->lazy_line); - for (i = 0; i < pev->nargs; i++) + for (i = 0; i < pev->nargs; i++) { if (pev->args[i].name) free(pev->args[i].name); + field = pev->args[i].field; + while (field) { + next = field->next; + if (field->name) + free(field->name); + free(field); + field = next; + } + } if (pev->args) free(pev->args); memset(pev, 0, sizeof(*pev)); @@ -682,8 +762,10 @@ static void show_perf_probe_event(struct perf_probe_event *pev) if (pev->nargs > 0) { printf(" with"); - for (i = 0; i < pev->nargs; i++) - printf(" %s", pev->args[i].name); + for (i = 0; i < pev->nargs; i++) { + synthesize_perf_probe_arg(&pev->args[i], buf, 128); + printf(" %s", buf); + } } printf(")\n"); free(place); diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h index 2a2f0a2..cd308b0 100644 --- a/tools/perf/util/probe-event.h +++ b/tools/perf/util/probe-event.h @@ -45,9 +45,17 @@ struct perf_probe_point { bool retprobe; /* Return probe flag */ }; +/* Perf probe probing argument field chain */ +struct perf_probe_arg_field { + struct perf_probe_arg_field *next; /* Next field */ + char *name; /* Name of the field */ + bool ref; /* Referencing flag */ +}; + /* Perf probe probing argument */ struct perf_probe_arg { - char *name; /* Argument name */ + char *name; /* Argument name */ + struct perf_probe_arg_field *field; /* Structure fields */ }; /* Perf probe probing event (point + arg) */ @@ -86,6 +94,8 @@ extern void parse_kprobe_trace_command(const char *cmd, /* Events to command string */ extern char *synthesize_perf_probe_command(struct perf_probe_event *pev); extern char *synthesize_kprobe_trace_command(struct kprobe_trace_event *tev); +extern int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, + size_t len); /* Check the perf_probe_event needs debuginfo */ extern bool perf_probe_event_need_dwarf(struct perf_probe_event *pev); diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index e02b607..db52ec2 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -206,6 +206,28 @@ static Dwarf_Addr die_get_entrypc(Dwarf_Die *dw_die) return epc; } +/* Get type die, but skip qualifiers and typedef */ +static Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem) +{ + Dwarf_Attribute attr; + int tag; + + do { + if (dwarf_attr(vr_die, DW_AT_type, &attr) == NULL || + dwarf_formref_die(&attr, die_mem) == NULL) + return NULL; + + tag = dwarf_tag(die_mem); + vr_die = die_mem; + } while (tag == DW_TAG_const_type || + tag == DW_TAG_restrict_type || + tag == DW_TAG_volatile_type || + tag == DW_TAG_shared_type || + tag == DW_TAG_typedef); + + return die_mem; +} + /* Return values for die_find callbacks */ enum { DIE_FIND_CB_FOUND = 0, /* End of Search */ @@ -314,6 +336,25 @@ static Dwarf_Die *die_find_variable(Dwarf_Die *sp_die, const char *name, die_mem); } +static int __die_find_member_cb(Dwarf_Die *die_mem, void *data) +{ + const char *name = data; + + if ((dwarf_tag(die_mem) == DW_TAG_member) && + (die_compare_name(die_mem, name) == 0)) + return DIE_FIND_CB_FOUND; + + return DIE_FIND_CB_SIBLING; +} + +/* Find a member called 'name' */ +static Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name, + Dwarf_Die *die_mem) +{ + return die_find_child(st_die, __die_find_member_cb, (void *)name, + die_mem); +} + /* * Probe finder related functions */ @@ -363,6 +404,62 @@ static void convert_location(Dwarf_Op *op, struct probe_finder *pf) } } +static void convert_variable_fields(Dwarf_Die *vr_die, const char *varname, + struct perf_probe_arg_field *field, + struct kprobe_trace_arg_ref **ref_ptr) +{ + struct kprobe_trace_arg_ref *ref = *ref_ptr; + Dwarf_Attribute attr; + Dwarf_Die member; + Dwarf_Die type; + Dwarf_Word offs; + + pr_debug("converting %s in %s\n", field->name, varname); + if (die_get_real_type(vr_die, &type) == NULL) + die("Failed to get a type information of %s.", varname); + + /* Check the pointer and dereference */ + if (dwarf_tag(&type) == DW_TAG_pointer_type) { + if (!field->ref) + die("Semantic error: %s must be referred by '->'", + field->name); + /* Get the type pointed by this pointer */ + if (die_get_real_type(&type, &type) == NULL) + die("Failed to get a type information of %s.", varname); + + ref = xzalloc(sizeof(struct kprobe_trace_arg_ref)); + if (*ref_ptr) + (*ref_ptr)->next = ref; + else + *ref_ptr = ref; + } else { + if (field->ref) + die("Semantic error: %s must be referred by '.'", + field->name); + if (!ref) + die("Structure on a register is not supported yet."); + } + + /* Verify it is a data structure */ + if (dwarf_tag(&type) != DW_TAG_structure_type) + die("%s is not a data structure.", varname); + + if (die_find_member(&type, field->name, &member) == NULL) + die("%s(tyep:%s) has no member %s.", varname, + dwarf_diename(&type), field->name); + + /* Get the offset of the field */ + if (dwarf_attr(&member, DW_AT_data_member_location, &attr) == NULL || + dwarf_formudata(&attr, &offs) != 0) + die("Failed to get the offset of %s.", field->name); + ref->offset += (long)offs; + + /* Converting next field */ + if (field->next) + convert_variable_fields(&member, field->name, field->next, + &ref); +} + /* Show a variables in kprobe event format */ static void convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf) { @@ -379,6 +476,10 @@ static void convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf) goto error; convert_location(expr, pf); + + if (pf->pvar->field) + convert_variable_fields(vr_die, pf->pvar->name, + pf->pvar->field, &pf->tvar->ref); /* *expr will be cached in libdw. Don't free it. */ return ; error: @@ -391,13 +492,15 @@ error: static void find_variable(Dwarf_Die *sp_die, struct probe_finder *pf) { Dwarf_Die vr_die; + char buf[128]; /* TODO: Support struct members and arrays */ if (!is_c_varname(pf->pvar->name)) { /* Copy raw parameters */ pf->tvar->value = xstrdup(pf->pvar->name); } else { - pf->tvar->name = xstrdup(pf->pvar->name); + synthesize_perf_probe_arg(pf->pvar, buf, 128); + pf->tvar->name = xstrdup(buf); pr_debug("Searching '%s' variable in context.\n", pf->pvar->name); /* Search child die for local variables and parameters. */ -- cgit v0.10.2 From 3b0d516463f8deb897a55cb81e9dbbe58a2490ed Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 17 Mar 2010 12:13:28 +0100 Subject: perf probe: Fix !dwarf build Fix the !drawf build. This uses the existing NO_DWARF_SUPPORT mechanism we use for that, but it's really fragile and needs a cleanup. (in a separate patch) 1) Such uses: #ifndef NO_DWARF_SUPPORT are double inverted logic a'la 'not not'. Instead the flag should be called DWARF_SUPPORT. 2) Furthermore, assymetric #ifdef polluted code flow like: if (need_dwarf) #ifdef NO_DWARF_SUPPORT die("Debuginfo-analysis is not supported"); #else /* !NO_DWARF_SUPPORT */ pr_debug("Some probes require debuginfo.\n"); fd = open_vmlinux(); is very fragile and not acceptable. Instead of that helper functions should be created and the dwarf/no-dwarf logic should be separated more cleanly. 3) Local variable #ifdefs like this: #ifndef NO_DWARF_SUPPORT int fd; #endif Are fragile as well and should be eliminated. Helper functions achieve that too. Cc: Masami Hiramatsu Cc: Frederic Weisbecker Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Mike Galbraith Cc: Peter Zijlstra LKML-Reference: <20100316220612.32050.33806.stgit@localhost6.localdomain6> Signed-off-by: Ingo Molnar diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 64dea6c..f333269 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -1012,8 +1012,10 @@ end_dwarf: if (!sym) die("Kernel symbol \'%s\' not found - probe not added.", tev->point.symbol); +#ifndef NO_DWARF_SUPPORT found: close(fd); +#endif return ntevs; } @@ -1172,10 +1174,13 @@ void show_line_range(struct line_range *lr) unsigned int l = 1; struct line_node *ln; FILE *fp; +#ifndef NO_DWARF_SUPPORT int fd, ret; +#endif /* Search a line range */ init_vmlinux(); +#ifndef NO_DWARF_SUPPORT fd = open_vmlinux(); if (fd < 0) die("Could not open debuginfo file."); @@ -1183,6 +1188,7 @@ void show_line_range(struct line_range *lr) if (ret <= 0) die("Source line is not found.\n"); close(fd); +#endif setup_pager(); -- cgit v0.10.2 From b27ea29c6267889be255f2217fa7a6106e6a8b04 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Wed, 17 Mar 2010 12:49:10 +0100 Subject: perf/core, x86: Reduce number of CONFIG_X86_LOCAL_APIC macros The function reserve_pmc_hardware() and release_pmc_hardware() were hard to read. This patch improves readability of the code by removing most of the CONFIG_X86_LOCAL_APIC macros. Signed-off-by: Robert Richter Cc: Stephane Eranian Cc: Peter Zijlstra LKML-Reference: <1268826553-19518-2-git-send-email-robert.richter@amd.com> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 5dacf63..793e63f 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -313,9 +313,10 @@ again: static atomic_t active_events; static DEFINE_MUTEX(pmc_reserve_mutex); +#ifdef CONFIG_X86_LOCAL_APIC + static bool reserve_pmc_hardware(void) { -#ifdef CONFIG_X86_LOCAL_APIC int i; if (nmi_watchdog == NMI_LOCAL_APIC) @@ -330,11 +331,9 @@ static bool reserve_pmc_hardware(void) if (!reserve_evntsel_nmi(x86_pmu.eventsel + i)) goto eventsel_fail; } -#endif return true; -#ifdef CONFIG_X86_LOCAL_APIC eventsel_fail: for (i--; i >= 0; i--) release_evntsel_nmi(x86_pmu.eventsel + i); @@ -349,12 +348,10 @@ perfctr_fail: enable_lapic_nmi_watchdog(); return false; -#endif } static void release_pmc_hardware(void) { -#ifdef CONFIG_X86_LOCAL_APIC int i; for (i = 0; i < x86_pmu.num_events; i++) { @@ -364,9 +361,15 @@ static void release_pmc_hardware(void) if (nmi_watchdog == NMI_LOCAL_APIC) enable_lapic_nmi_watchdog(); -#endif } +#else + +static bool reserve_pmc_hardware(void) { return true; } +static void release_pmc_hardware(void) {} + +#endif + static int reserve_ds_buffers(void); static void release_ds_buffers(void); -- cgit v0.10.2 From 141c4296cb630a7ed4c3730913bc3c0617ef9753 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Wed, 17 Mar 2010 12:49:11 +0100 Subject: perf/core: Correct files in MAINTAINERS entry This corrects the file entries for perf_events. The following files are caught now: $ xargs | eval ls $(cat) | sort -u kernel/perf_event*.c include/linux/perf_event.h arch/*/kernel/perf_event*.c arch/*/kernel/*/perf_event*.c arch/*/kernel/*/*/perf_event*.c arch/*/include/asm/perf_event.h arch/*/lib/perf_event*.c arch/*/kernel/perf_callchain.c arch/alpha/include/asm/perf_event.h arch/arm/include/asm/perf_event.h arch/arm/kernel/perf_event.c arch/frv/include/asm/perf_event.h arch/frv/lib/perf_event.c arch/parisc/include/asm/perf_event.h arch/powerpc/include/asm/perf_event.h arch/powerpc/kernel/perf_callchain.c arch/powerpc/kernel/perf_event.c arch/s390/include/asm/perf_event.h arch/sh/include/asm/perf_event.h arch/sh/kernel/cpu/sh4a/perf_event.c arch/sh/kernel/cpu/sh4/perf_event.c arch/sh/kernel/perf_callchain.c arch/sh/kernel/perf_event.c arch/sparc/include/asm/perf_event.h arch/sparc/kernel/perf_event.c arch/x86/include/asm/perf_event.h arch/x86/kernel/cpu/perf_event_amd.c arch/x86/kernel/cpu/perf_event.c arch/x86/kernel/cpu/perf_event_intel.c arch/x86/kernel/cpu/perf_event_p6.c include/linux/perf_event.h kernel/perf_event.c Signed-off-by: Robert Richter Cc: Stephane Eranian Cc: Peter Zijlstra LKML-Reference: <1268826553-19518-3-git-send-email-robert.richter@amd.com> Signed-off-by: Ingo Molnar diff --git a/MAINTAINERS b/MAINTAINERS index 14d5c4c..e3aa850 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4295,13 +4295,13 @@ M: Paul Mackerras M: Ingo Molnar M: Arnaldo Carvalho de Melo S: Supported -F: kernel/perf_event.c +F: kernel/perf_event*.c F: include/linux/perf_event.h -F: arch/*/kernel/perf_event.c -F: arch/*/kernel/*/perf_event.c -F: arch/*/kernel/*/*/perf_event.c +F: arch/*/kernel/perf_event*.c +F: arch/*/kernel/*/perf_event*.c +F: arch/*/kernel/*/*/perf_event*.c F: arch/*/include/asm/perf_event.h -F: arch/*/lib/perf_event.c +F: arch/*/lib/perf_event*.c F: arch/*/kernel/perf_callchain.c F: tools/perf/ -- cgit v0.10.2 From 10f1014d86fd4fe5087080d609b51183396c5e4c Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Wed, 17 Mar 2010 12:49:12 +0100 Subject: perf/core, x86: Remove cpu_hw_events.interrupts This member in the struct is not used anymore and can be removed. Signed-off-by: Robert Richter Cc: Stephane Eranian Cc: Peter Zijlstra LKML-Reference: <1268826553-19518-4-git-send-email-robert.richter@amd.com> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 793e63f..104292a 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -102,7 +102,6 @@ struct cpu_hw_events { */ struct perf_event *events[X86_PMC_IDX_MAX]; /* in counter order */ unsigned long active_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; - unsigned long interrupts; int enabled; int n_events; -- cgit v0.10.2 From d6dc0b4ead6e8720096ecfa3d9e899b47ddbc8ed Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Wed, 17 Mar 2010 12:49:13 +0100 Subject: perf/core, x86: Remove duplicate perf_event_mask variable The same information is stored also in x86_pmu.intel_ctrl. This patch removes perf_event_mask and instead uses x86_pmu.intel_ctrl directly. Signed-off-by: Robert Richter Cc: Stephane Eranian Cc: Peter Zijlstra LKML-Reference: <1268826553-19518-5-git-send-email-robert.richter@amd.com> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 104292a..c97d5b5 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -75,8 +75,6 @@ copy_from_user_nmi(void *to, const void __user *from, unsigned long n) return len; } -static u64 perf_event_mask __read_mostly; - struct event_constraint { union { unsigned long idxmsk[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; @@ -1406,7 +1404,7 @@ void __init init_hw_perf_events(void) x86_pmu.num_events, X86_PMC_MAX_GENERIC); x86_pmu.num_events = X86_PMC_MAX_GENERIC; } - perf_event_mask = (1 << x86_pmu.num_events) - 1; + x86_pmu.intel_ctrl = (1 << x86_pmu.num_events) - 1; perf_max_events = x86_pmu.num_events; if (x86_pmu.num_events_fixed > X86_PMC_MAX_FIXED) { @@ -1415,9 +1413,8 @@ void __init init_hw_perf_events(void) x86_pmu.num_events_fixed = X86_PMC_MAX_FIXED; } - perf_event_mask |= + x86_pmu.intel_ctrl |= ((1LL << x86_pmu.num_events_fixed)-1) << X86_PMC_IDX_FIXED; - x86_pmu.intel_ctrl = perf_event_mask; perf_events_lapic_init(); register_die_notifier(&perf_event_nmi_notifier); @@ -1442,7 +1439,7 @@ void __init init_hw_perf_events(void) pr_info("... value mask: %016Lx\n", x86_pmu.event_mask); pr_info("... max period: %016Lx\n", x86_pmu.max_period); pr_info("... fixed-purpose events: %d\n", x86_pmu.num_events_fixed); - pr_info("... event mask: %016Lx\n", perf_event_mask); + pr_info("... event mask: %016Lx\n", x86_pmu.intel_ctrl); perf_cpu_notifier(x86_pmu_notifier); } -- cgit v0.10.2 From 2acebe9ecb2b77876e87a1480729cfb2db4570dd Mon Sep 17 00:00:00 2001 From: Jack Steiner Date: Wed, 17 Mar 2010 10:40:38 -0500 Subject: x86, UV: Delete unneeded boot messages SGI:UV: Delete extra boot messages that describe the system topology. These messages are no longer useful. Signed-off-by: Jack Steiner LKML-Reference: <20100317154038.GA29346@sgi.com> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index 3740c8a..9a93b07 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c @@ -736,9 +736,6 @@ void __init uv_system_init(void) uv_node_to_blade[nid] = blade; uv_cpu_to_blade[cpu] = blade; max_pnode = max(pnode, max_pnode); - - printk(KERN_DEBUG "UV: cpu %d, apicid 0x%x, pnode %d, nid %d, lcpu %d, blade %d\n", - cpu, apicid, pnode, nid, lcpu, blade); } /* Add blade/pnode info for nodes without cpus */ -- cgit v0.10.2 From 6be2850effd6a8bae11d623c8c52e88d2fbc0e96 Mon Sep 17 00:00:00 2001 From: "Zhang, Yanmin" Date: Thu, 18 Mar 2010 11:36:03 -0300 Subject: perf stat: Enable counters when collecting process-wide or system-wide data Command 'perf stat' doesn't enable counters when collecting an existing (by -p) process or system-wide statistics. Fix the issue. Change the condition of fork/exec subcommand. If there is a subcommand parameter, perf always forks/execs it. The usage example is: # perf stat -a sleep 10 So this command could collect statistics for 10 seconds precisely. User still could stop it by CTRL+C. Without the new capability, user could only use CTRL+C to stop it without precise time clock. Another issue is 'perf stat -a' consumes 100% time of a full single logical cpu. It has a bad impact on running workload. Fix it by adding a sleep(1) in the while(!done) loop in function run_perf_stat. Signed-off-by: Zhang Yanmin Signed-off-by: Arnaldo Carvalho de Melo Cc: Avi Kivity Cc: Peter Zijlstra Cc: Sheng Yang Cc: Marcelo Tosatti Cc: Joerg Roedel Cc: Jes Sorensen Cc: Gleb Natapov Cc: Zachary Amsden Cc: LKML-Reference: <1268922965-14774-1-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 95db31c..5f41244 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -159,8 +159,10 @@ static void create_perf_stat_counter(int counter, int pid) } } else { attr->inherit = inherit; - attr->disabled = 1; - attr->enable_on_exec = 1; + if (target_pid == -1) { + attr->disabled = 1; + attr->enable_on_exec = 1; + } fd[0][counter] = sys_perf_event_open(attr, pid, -1, -1, 0); if (fd[0][counter] < 0 && verbose) @@ -251,9 +253,9 @@ static int run_perf_stat(int argc __used, const char **argv) unsigned long long t0, t1; int status = 0; int counter; - int pid = target_pid; + int pid; int child_ready_pipe[2], go_pipe[2]; - const bool forks = (target_pid == -1 && argc > 0); + const bool forks = (argc > 0); char buf; if (!system_wide) @@ -265,10 +267,10 @@ static int run_perf_stat(int argc __used, const char **argv) } if (forks) { - if ((pid = fork()) < 0) + if ((child_pid = fork()) < 0) perror("failed to fork"); - if (!pid) { + if (!child_pid) { close(child_ready_pipe[0]); close(go_pipe[1]); fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC); @@ -297,8 +299,6 @@ static int run_perf_stat(int argc __used, const char **argv) exit(-1); } - child_pid = pid; - /* * Wait for the child to be ready to exec. */ @@ -309,6 +309,10 @@ static int run_perf_stat(int argc __used, const char **argv) close(child_ready_pipe[0]); } + if (target_pid == -1) + pid = child_pid; + else + pid = target_pid; for (counter = 0; counter < nr_counters; counter++) create_perf_stat_counter(counter, pid); @@ -321,7 +325,7 @@ static int run_perf_stat(int argc __used, const char **argv) close(go_pipe[1]); wait(&status); } else { - while(!done); + while(!done) sleep(1); } t1 = rdclock(); @@ -459,7 +463,7 @@ static volatile int signr = -1; static void skip_signal(int signo) { - if(target_pid != -1) + if(child_pid == -1) done = 1; signr = signo; -- cgit v0.10.2 From 46be604b5ba738d53e5f5314813a4e7092864baf Mon Sep 17 00:00:00 2001 From: "Zhang, Yanmin" Date: Thu, 18 Mar 2010 11:36:04 -0300 Subject: perf record: Enable counters only when kernel is execing subcommand 'perf record' starts counters before subcommand is execed, so the statistics is not precise because it includes data of some preparation steps. I fix it with the patch. In addition, change the condition to fork/exec subcommand. If there is a subcommand parameter, perf always fork/exec it. The usage example is: # perf record -f -a sleep 10 So this command could collect statistics for 10 seconds precisely. User still could stop it by CTRL+C. Without the new capability, user could only input CTRL+C to stop it without precise time clock. Signed-off-by: Zhang Yanmin Signed-off-by: Arnaldo Carvalho de Melo Cc: Avi Kivity Cc: Peter Zijlstra Cc: Sheng Yang Cc: oerg Roedel Cc: Jes Sorensen Cc: Marcelo Tosatti Cc: Gleb Natapov Cc: Cc: Zachary Amsden LKML-Reference: <1268922965-14774-2-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 962cdbf..e2b35ad 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -225,7 +225,7 @@ static struct perf_header_attr *get_header_attr(struct perf_event_attr *a, int n return h_attr; } -static void create_counter(int counter, int cpu, pid_t pid, bool forks) +static void create_counter(int counter, int cpu, pid_t pid) { char *filter = filters[counter]; struct perf_event_attr *attr = attrs + counter; @@ -275,10 +275,10 @@ static void create_counter(int counter, int cpu, pid_t pid, bool forks) attr->mmap = track; attr->comm = track; attr->inherit = inherit; - attr->disabled = 1; - - if (forks) + if (target_pid == -1 && !system_wide) { + attr->disabled = 1; attr->enable_on_exec = 1; + } try_again: fd[nr_cpu][counter] = sys_perf_event_open(attr, pid, cpu, group_fd, 0); @@ -380,17 +380,15 @@ try_again: exit(-1); } } - - ioctl(fd[nr_cpu][counter], PERF_EVENT_IOC_ENABLE); } -static void open_counters(int cpu, pid_t pid, bool forks) +static void open_counters(int cpu, pid_t pid) { int counter; group_fd = -1; for (counter = 0; counter < nr_counters; counter++) - create_counter(counter, cpu, pid, forks); + create_counter(counter, cpu, pid); nr_cpu++; } @@ -425,7 +423,7 @@ static int __cmd_record(int argc, const char **argv) int err; unsigned long waking = 0; int child_ready_pipe[2], go_pipe[2]; - const bool forks = target_pid == -1 && argc > 0; + const bool forks = argc > 0; char buf; page_size = sysconf(_SC_PAGE_SIZE); @@ -496,13 +494,13 @@ static int __cmd_record(int argc, const char **argv) atexit(atexit_header); if (forks) { - pid = fork(); + child_pid = fork(); if (pid < 0) { perror("failed to fork"); exit(-1); } - if (!pid) { + if (!child_pid) { close(child_ready_pipe[0]); close(go_pipe[1]); fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC); @@ -531,11 +529,6 @@ static int __cmd_record(int argc, const char **argv) exit(-1); } - child_pid = pid; - - if (!system_wide) - target_pid = pid; - close(child_ready_pipe[1]); close(go_pipe[0]); /* @@ -548,13 +541,17 @@ static int __cmd_record(int argc, const char **argv) close(child_ready_pipe[0]); } + if (forks && target_pid == -1 && !system_wide) + pid = child_pid; + else + pid = target_pid; if ((!system_wide && !inherit) || profile_cpu != -1) { - open_counters(profile_cpu, target_pid, forks); + open_counters(profile_cpu, pid); } else { nr_cpus = read_cpu_map(); for (i = 0; i < nr_cpus; i++) - open_counters(cpumap[i], target_pid, forks); + open_counters(cpumap[i], pid); } if (file_new) { -- cgit v0.10.2 From d6d901c23a9c4c7361aa901b5b2dda69703dd5e0 Mon Sep 17 00:00:00 2001 From: "Zhang, Yanmin" Date: Thu, 18 Mar 2010 11:36:05 -0300 Subject: perf events: Change perf parameter --pid to process-wide collection instead of thread-wide Parameter --pid (or -p) of perf currently means a thread-wide collection. For exmaple, if a process whose id is 8888 has 10 threads, 'perf top -p 8888' just collects the main thread statistics. That's misleading. Users are used to attach a whole process when debugging a process by gdb. To follow normal usage style, the patch change --pid to process-wide collection and add --tid (-t) to mean a thread-wide collection. Usage example is: # perf top -p 8888 # perf record -p 8888 -f sleep 10 # perf stat -p 8888 -f sleep 10 Above commands collect the statistics of all threads of process 8888. Signed-off-by: Zhang Yanmin Signed-off-by: Arnaldo Carvalho de Melo Cc: Avi Kivity Cc: Peter Zijlstra Cc: Sheng Yang Cc: Joerg Roedel Cc: Jes Sorensen Cc: Marcelo Tosatti Cc: Gleb Natapov Cc: zhiteng.huang@intel.com Cc: Zachary Amsden LKML-Reference: <1268922965-14774-3-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index e2b35ad..bb5b23d 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -27,7 +27,7 @@ #include #include -static int fd[MAX_NR_CPUS][MAX_COUNTERS]; +static int *fd[MAX_NR_CPUS][MAX_COUNTERS]; static long default_interval = 0; @@ -43,6 +43,9 @@ static int raw_samples = 0; static int system_wide = 0; static int profile_cpu = -1; static pid_t target_pid = -1; +static pid_t target_tid = -1; +static pid_t *all_tids = NULL; +static int thread_num = 0; static pid_t child_pid = -1; static int inherit = 1; static int force = 0; @@ -60,7 +63,7 @@ static struct timeval this_read; static u64 bytes_written = 0; -static struct pollfd event_array[MAX_NR_CPUS * MAX_COUNTERS]; +static struct pollfd *event_array; static int nr_poll = 0; static int nr_cpu = 0; @@ -77,7 +80,7 @@ struct mmap_data { unsigned int prev; }; -static struct mmap_data mmap_array[MAX_NR_CPUS][MAX_COUNTERS]; +static struct mmap_data *mmap_array[MAX_NR_CPUS][MAX_COUNTERS]; static unsigned long mmap_read_head(struct mmap_data *md) { @@ -225,12 +228,13 @@ static struct perf_header_attr *get_header_attr(struct perf_event_attr *a, int n return h_attr; } -static void create_counter(int counter, int cpu, pid_t pid) +static void create_counter(int counter, int cpu) { char *filter = filters[counter]; struct perf_event_attr *attr = attrs + counter; struct perf_header_attr *h_attr; int track = !counter; /* only the first counter needs these */ + int thread_index; int ret; struct { u64 count; @@ -280,115 +284,124 @@ static void create_counter(int counter, int cpu, pid_t pid) attr->enable_on_exec = 1; } + for (thread_index = 0; thread_index < thread_num; thread_index++) { try_again: - fd[nr_cpu][counter] = sys_perf_event_open(attr, pid, cpu, group_fd, 0); - - if (fd[nr_cpu][counter] < 0) { - int err = errno; - - if (err == EPERM || err == EACCES) - die("Permission error - are you root?\n" - "\t Consider tweaking /proc/sys/kernel/perf_event_paranoid.\n"); - else if (err == ENODEV && profile_cpu != -1) - die("No such device - did you specify an out-of-range profile CPU?\n"); + fd[nr_cpu][counter][thread_index] = sys_perf_event_open(attr, + all_tids[thread_index], cpu, group_fd, 0); + + if (fd[nr_cpu][counter][thread_index] < 0) { + int err = errno; + + if (err == EPERM || err == EACCES) + die("Permission error - are you root?\n" + "\t Consider tweaking" + " /proc/sys/kernel/perf_event_paranoid.\n"); + else if (err == ENODEV && profile_cpu != -1) { + die("No such device - did you specify" + " an out-of-range profile CPU?\n"); + } - /* - * If it's cycles then fall back to hrtimer - * based cpu-clock-tick sw counter, which - * is always available even if no PMU support: - */ - if (attr->type == PERF_TYPE_HARDWARE - && attr->config == PERF_COUNT_HW_CPU_CYCLES) { - - if (verbose) - warning(" ... trying to fall back to cpu-clock-ticks\n"); - attr->type = PERF_TYPE_SOFTWARE; - attr->config = PERF_COUNT_SW_CPU_CLOCK; - goto try_again; - } - printf("\n"); - error("perfcounter syscall returned with %d (%s)\n", - fd[nr_cpu][counter], strerror(err)); + /* + * If it's cycles then fall back to hrtimer + * based cpu-clock-tick sw counter, which + * is always available even if no PMU support: + */ + if (attr->type == PERF_TYPE_HARDWARE + && attr->config == PERF_COUNT_HW_CPU_CYCLES) { + + if (verbose) + warning(" ... trying to fall back to cpu-clock-ticks\n"); + attr->type = PERF_TYPE_SOFTWARE; + attr->config = PERF_COUNT_SW_CPU_CLOCK; + goto try_again; + } + printf("\n"); + error("perfcounter syscall returned with %d (%s)\n", + fd[nr_cpu][counter][thread_index], strerror(err)); #if defined(__i386__) || defined(__x86_64__) - if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP) - die("No hardware sampling interrupt available. No APIC? If so then you can boot the kernel with the \"lapic\" boot parameter to force-enable it.\n"); + if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP) + die("No hardware sampling interrupt available." + " No APIC? If so then you can boot the kernel" + " with the \"lapic\" boot parameter to" + " force-enable it.\n"); #endif - die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); - exit(-1); - } + die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); + exit(-1); + } - h_attr = get_header_attr(attr, counter); - if (h_attr == NULL) - die("nomem\n"); + h_attr = get_header_attr(attr, counter); + if (h_attr == NULL) + die("nomem\n"); - if (!file_new) { - if (memcmp(&h_attr->attr, attr, sizeof(*attr))) { - fprintf(stderr, "incompatible append\n"); - exit(-1); + if (!file_new) { + if (memcmp(&h_attr->attr, attr, sizeof(*attr))) { + fprintf(stderr, "incompatible append\n"); + exit(-1); + } } - } - if (read(fd[nr_cpu][counter], &read_data, sizeof(read_data)) == -1) { - perror("Unable to read perf file descriptor\n"); - exit(-1); - } + if (read(fd[nr_cpu][counter][thread_index], &read_data, sizeof(read_data)) == -1) { + perror("Unable to read perf file descriptor\n"); + exit(-1); + } - if (perf_header_attr__add_id(h_attr, read_data.id) < 0) { - pr_warning("Not enough memory to add id\n"); - exit(-1); - } + if (perf_header_attr__add_id(h_attr, read_data.id) < 0) { + pr_warning("Not enough memory to add id\n"); + exit(-1); + } - assert(fd[nr_cpu][counter] >= 0); - fcntl(fd[nr_cpu][counter], F_SETFL, O_NONBLOCK); + assert(fd[nr_cpu][counter][thread_index] >= 0); + fcntl(fd[nr_cpu][counter][thread_index], F_SETFL, O_NONBLOCK); - /* - * First counter acts as the group leader: - */ - if (group && group_fd == -1) - group_fd = fd[nr_cpu][counter]; - if (multiplex && multiplex_fd == -1) - multiplex_fd = fd[nr_cpu][counter]; + /* + * First counter acts as the group leader: + */ + if (group && group_fd == -1) + group_fd = fd[nr_cpu][counter][thread_index]; + if (multiplex && multiplex_fd == -1) + multiplex_fd = fd[nr_cpu][counter][thread_index]; - if (multiplex && fd[nr_cpu][counter] != multiplex_fd) { + if (multiplex && fd[nr_cpu][counter][thread_index] != multiplex_fd) { - ret = ioctl(fd[nr_cpu][counter], PERF_EVENT_IOC_SET_OUTPUT, multiplex_fd); - assert(ret != -1); - } else { - event_array[nr_poll].fd = fd[nr_cpu][counter]; - event_array[nr_poll].events = POLLIN; - nr_poll++; - - mmap_array[nr_cpu][counter].counter = counter; - mmap_array[nr_cpu][counter].prev = 0; - mmap_array[nr_cpu][counter].mask = mmap_pages*page_size - 1; - mmap_array[nr_cpu][counter].base = mmap(NULL, (mmap_pages+1)*page_size, - PROT_READ|PROT_WRITE, MAP_SHARED, fd[nr_cpu][counter], 0); - if (mmap_array[nr_cpu][counter].base == MAP_FAILED) { - error("failed to mmap with %d (%s)\n", errno, strerror(errno)); - exit(-1); + ret = ioctl(fd[nr_cpu][counter][thread_index], PERF_EVENT_IOC_SET_OUTPUT, multiplex_fd); + assert(ret != -1); + } else { + event_array[nr_poll].fd = fd[nr_cpu][counter][thread_index]; + event_array[nr_poll].events = POLLIN; + nr_poll++; + + mmap_array[nr_cpu][counter][thread_index].counter = counter; + mmap_array[nr_cpu][counter][thread_index].prev = 0; + mmap_array[nr_cpu][counter][thread_index].mask = mmap_pages*page_size - 1; + mmap_array[nr_cpu][counter][thread_index].base = mmap(NULL, (mmap_pages+1)*page_size, + PROT_READ|PROT_WRITE, MAP_SHARED, fd[nr_cpu][counter][thread_index], 0); + if (mmap_array[nr_cpu][counter][thread_index].base == MAP_FAILED) { + error("failed to mmap with %d (%s)\n", errno, strerror(errno)); + exit(-1); + } } - } - if (filter != NULL) { - ret = ioctl(fd[nr_cpu][counter], - PERF_EVENT_IOC_SET_FILTER, filter); - if (ret) { - error("failed to set filter with %d (%s)\n", errno, - strerror(errno)); - exit(-1); + if (filter != NULL) { + ret = ioctl(fd[nr_cpu][counter][thread_index], + PERF_EVENT_IOC_SET_FILTER, filter); + if (ret) { + error("failed to set filter with %d (%s)\n", errno, + strerror(errno)); + exit(-1); + } } } } -static void open_counters(int cpu, pid_t pid) +static void open_counters(int cpu) { int counter; group_fd = -1; for (counter = 0; counter < nr_counters; counter++) - create_counter(counter, cpu, pid); + create_counter(counter, cpu); nr_cpu++; } @@ -529,6 +542,9 @@ static int __cmd_record(int argc, const char **argv) exit(-1); } + if (!system_wide && target_tid == -1 && target_pid == -1) + all_tids[0] = child_pid; + close(child_ready_pipe[1]); close(go_pipe[0]); /* @@ -541,17 +557,12 @@ static int __cmd_record(int argc, const char **argv) close(child_ready_pipe[0]); } - if (forks && target_pid == -1 && !system_wide) - pid = child_pid; - else - pid = target_pid; - if ((!system_wide && !inherit) || profile_cpu != -1) { - open_counters(profile_cpu, pid); + open_counters(profile_cpu); } else { nr_cpus = read_cpu_map(); for (i = 0; i < nr_cpus; i++) - open_counters(cpumap[i], pid); + open_counters(cpumap[i]); } if (file_new) { @@ -576,7 +587,7 @@ static int __cmd_record(int argc, const char **argv) } if (!system_wide && profile_cpu == -1) - event__synthesize_thread(target_pid, process_synthesized_event, + event__synthesize_thread(target_tid, process_synthesized_event, session); else event__synthesize_threads(process_synthesized_event, session); @@ -599,11 +610,16 @@ static int __cmd_record(int argc, const char **argv) for (;;) { int hits = samples; + int thread; for (i = 0; i < nr_cpu; i++) { for (counter = 0; counter < nr_counters; counter++) { - if (mmap_array[i][counter].base) - mmap_read(&mmap_array[i][counter]); + for (thread = 0; + thread < thread_num; thread++) { + if (mmap_array[i][counter][thread].base) + mmap_read(&mmap_array[i][counter][thread]); + } + } } @@ -616,8 +632,15 @@ static int __cmd_record(int argc, const char **argv) if (done) { for (i = 0; i < nr_cpu; i++) { - for (counter = 0; counter < nr_counters; counter++) - ioctl(fd[i][counter], PERF_EVENT_IOC_DISABLE); + for (counter = 0; + counter < nr_counters; + counter++) { + for (thread = 0; + thread < thread_num; + thread++) + ioctl(fd[i][counter][thread], + PERF_EVENT_IOC_DISABLE); + } } } } @@ -649,7 +672,9 @@ static const struct option options[] = { OPT_CALLBACK(0, "filter", NULL, "filter", "event filter", parse_filter), OPT_INTEGER('p', "pid", &target_pid, - "record events on existing pid"), + "record events on existing process id"), + OPT_INTEGER('t', "tid", &target_tid, + "record events on existing thread id"), OPT_INTEGER('r', "realtime", &realtime_prio, "collect data with this RT SCHED_FIFO priority"), OPT_BOOLEAN('R', "raw-samples", &raw_samples, @@ -690,10 +715,12 @@ static const struct option options[] = { int cmd_record(int argc, const char **argv, const char *prefix __used) { int counter; + int i,j; argc = parse_options(argc, argv, options, record_usage, PARSE_OPT_STOP_AT_NON_OPTION); - if (!argc && target_pid == -1 && !system_wide && profile_cpu == -1) + if (!argc && target_pid == -1 && target_tid == -1 && + !system_wide && profile_cpu == -1) usage_with_options(record_usage, options); symbol__init(); @@ -704,6 +731,37 @@ int cmd_record(int argc, const char **argv, const char *prefix __used) attrs[0].config = PERF_COUNT_HW_CPU_CYCLES; } + if (target_pid != -1) { + target_tid = target_pid; + thread_num = find_all_tid(target_pid, &all_tids); + if (thread_num <= 0) { + fprintf(stderr, "Can't find all threads of pid %d\n", + target_pid); + usage_with_options(record_usage, options); + } + } else { + all_tids=malloc(sizeof(pid_t)); + if (!all_tids) + return -ENOMEM; + + all_tids[0] = target_tid; + thread_num = 1; + } + + for (i = 0; i < MAX_NR_CPUS; i++) { + for (j = 0; j < MAX_COUNTERS; j++) { + fd[i][j] = malloc(sizeof(int)*thread_num); + mmap_array[i][j] = malloc( + sizeof(struct mmap_data)*thread_num); + if (!fd[i][j] || !mmap_array[i][j]) + return -ENOMEM; + } + } + event_array = malloc( + sizeof(struct pollfd)*MAX_NR_CPUS*MAX_COUNTERS*thread_num); + if (!event_array) + return -ENOMEM; + /* * User specified count overrides default frequency. */ diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 5f41244..c92f90f 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -46,6 +46,7 @@ #include "util/debug.h" #include "util/header.h" #include "util/cpumap.h" +#include "util/thread.h" #include #include @@ -74,10 +75,13 @@ static int run_count = 1; static int inherit = 1; static int scale = 1; static pid_t target_pid = -1; +static pid_t target_tid = -1; +static pid_t *all_tids = NULL; +static int thread_num = 0; static pid_t child_pid = -1; static int null_run = 0; -static int fd[MAX_NR_CPUS][MAX_COUNTERS]; +static int *fd[MAX_NR_CPUS][MAX_COUNTERS]; static int event_scaled[MAX_COUNTERS]; @@ -140,9 +144,10 @@ struct stats runtime_branches_stats; #define ERR_PERF_OPEN \ "Error: counter %d, sys_perf_event_open() syscall returned with %d (%s)\n" -static void create_perf_stat_counter(int counter, int pid) +static void create_perf_stat_counter(int counter) { struct perf_event_attr *attr = attrs + counter; + int thread; if (scale) attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | @@ -152,10 +157,11 @@ static void create_perf_stat_counter(int counter, int pid) unsigned int cpu; for (cpu = 0; cpu < nr_cpus; cpu++) { - fd[cpu][counter] = sys_perf_event_open(attr, -1, cpumap[cpu], -1, 0); - if (fd[cpu][counter] < 0 && verbose) + fd[cpu][counter][0] = sys_perf_event_open(attr, + -1, cpumap[cpu], -1, 0); + if (fd[cpu][counter][0] < 0 && verbose) fprintf(stderr, ERR_PERF_OPEN, counter, - fd[cpu][counter], strerror(errno)); + fd[cpu][counter][0], strerror(errno)); } } else { attr->inherit = inherit; @@ -163,11 +169,14 @@ static void create_perf_stat_counter(int counter, int pid) attr->disabled = 1; attr->enable_on_exec = 1; } - - fd[0][counter] = sys_perf_event_open(attr, pid, -1, -1, 0); - if (fd[0][counter] < 0 && verbose) - fprintf(stderr, ERR_PERF_OPEN, counter, - fd[0][counter], strerror(errno)); + for (thread = 0; thread < thread_num; thread++) { + fd[0][counter][thread] = sys_perf_event_open(attr, + all_tids[thread], -1, -1, 0); + if (fd[0][counter][thread] < 0 && verbose) + fprintf(stderr, ERR_PERF_OPEN, counter, + fd[0][counter][thread], + strerror(errno)); + } } } @@ -192,25 +201,28 @@ static void read_counter(int counter) unsigned int cpu; size_t res, nv; int scaled; - int i; + int i, thread; count[0] = count[1] = count[2] = 0; nv = scale ? 3 : 1; for (cpu = 0; cpu < nr_cpus; cpu++) { - if (fd[cpu][counter] < 0) - continue; - - res = read(fd[cpu][counter], single_count, nv * sizeof(u64)); - assert(res == nv * sizeof(u64)); - - close(fd[cpu][counter]); - fd[cpu][counter] = -1; - - count[0] += single_count[0]; - if (scale) { - count[1] += single_count[1]; - count[2] += single_count[2]; + for (thread = 0; thread < thread_num; thread++) { + if (fd[cpu][counter][thread] < 0) + continue; + + res = read(fd[cpu][counter][thread], + single_count, nv * sizeof(u64)); + assert(res == nv * sizeof(u64)); + + close(fd[cpu][counter][thread]); + fd[cpu][counter][thread] = -1; + + count[0] += single_count[0]; + if (scale) { + count[1] += single_count[1]; + count[2] += single_count[2]; + } } } @@ -253,7 +265,6 @@ static int run_perf_stat(int argc __used, const char **argv) unsigned long long t0, t1; int status = 0; int counter; - int pid; int child_ready_pipe[2], go_pipe[2]; const bool forks = (argc > 0); char buf; @@ -299,6 +310,9 @@ static int run_perf_stat(int argc __used, const char **argv) exit(-1); } + if (target_tid == -1 && target_pid == -1 && !system_wide) + all_tids[0] = child_pid; + /* * Wait for the child to be ready to exec. */ @@ -309,12 +323,8 @@ static int run_perf_stat(int argc __used, const char **argv) close(child_ready_pipe[0]); } - if (target_pid == -1) - pid = child_pid; - else - pid = target_pid; for (counter = 0; counter < nr_counters; counter++) - create_perf_stat_counter(counter, pid); + create_perf_stat_counter(counter); /* * Enable counters and exec the command: @@ -433,12 +443,14 @@ static void print_stat(int argc, const char **argv) fprintf(stderr, "\n"); fprintf(stderr, " Performance counter stats for "); - if(target_pid == -1) { + if(target_pid == -1 && target_tid == -1) { fprintf(stderr, "\'%s", argv[0]); for (i = 1; i < argc; i++) fprintf(stderr, " %s", argv[i]); - }else - fprintf(stderr, "task pid \'%d", target_pid); + } else if (target_pid != -1) + fprintf(stderr, "process id \'%d", target_pid); + else + fprintf(stderr, "thread id \'%d", target_tid); fprintf(stderr, "\'"); if (run_count > 1) @@ -493,7 +505,9 @@ static const struct option options[] = { OPT_BOOLEAN('i', "inherit", &inherit, "child tasks inherit counters"), OPT_INTEGER('p', "pid", &target_pid, - "stat events on existing pid"), + "stat events on existing process id"), + OPT_INTEGER('t', "tid", &target_tid, + "stat events on existing thread id"), OPT_BOOLEAN('a', "all-cpus", &system_wide, "system-wide collection from all CPUs"), OPT_BOOLEAN('c', "scale", &scale, @@ -510,10 +524,11 @@ static const struct option options[] = { int cmd_stat(int argc, const char **argv, const char *prefix __used) { int status; + int i,j; argc = parse_options(argc, argv, options, stat_usage, PARSE_OPT_STOP_AT_NON_OPTION); - if (!argc && target_pid == -1) + if (!argc && target_pid == -1 && target_tid == -1) usage_with_options(stat_usage, options); if (run_count <= 0) usage_with_options(stat_usage, options); @@ -529,6 +544,31 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used) else nr_cpus = 1; + if (target_pid != -1) { + target_tid = target_pid; + thread_num = find_all_tid(target_pid, &all_tids); + if (thread_num <= 0) { + fprintf(stderr, "Can't find all threads of pid %d\n", + target_pid); + usage_with_options(stat_usage, options); + } + } else { + all_tids=malloc(sizeof(pid_t)); + if (!all_tids) + return -ENOMEM; + + all_tids[0] = target_tid; + thread_num = 1; + } + + for (i = 0; i < MAX_NR_CPUS; i++) { + for (j = 0; j < MAX_COUNTERS; j++) { + fd[i][j] = malloc(sizeof(int)*thread_num); + if (!fd[i][j]) + return -ENOMEM; + } + } + /* * We dont want to block the signals - that would cause * child tasks to inherit that and Ctrl-C would not work. diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 887ebbf..5f3ac9f 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -55,7 +55,7 @@ #include #include -static int fd[MAX_NR_CPUS][MAX_COUNTERS]; +static int *fd[MAX_NR_CPUS][MAX_COUNTERS]; static int system_wide = 0; @@ -65,6 +65,9 @@ static int count_filter = 5; static int print_entries; static int target_pid = -1; +static int target_tid = -1; +static pid_t *all_tids = NULL; +static int thread_num = 0; static int inherit = 0; static int profile_cpu = -1; static int nr_cpus = 0; @@ -524,13 +527,15 @@ static void print_sym_table(void) if (target_pid != -1) printf(" (target_pid: %d", target_pid); + else if (target_tid != -1) + printf(" (target_tid: %d", target_tid); else printf(" (all"); if (profile_cpu != -1) printf(", cpu: %d)\n", profile_cpu); else { - if (target_pid != -1) + if (target_tid != -1) printf(")\n"); else printf(", %d CPUs)\n", nr_cpus); @@ -1129,16 +1134,21 @@ static void perf_session__mmap_read_counter(struct perf_session *self, md->prev = old; } -static struct pollfd event_array[MAX_NR_CPUS * MAX_COUNTERS]; -static struct mmap_data mmap_array[MAX_NR_CPUS][MAX_COUNTERS]; +static struct pollfd *event_array; +static struct mmap_data *mmap_array[MAX_NR_CPUS][MAX_COUNTERS]; static void perf_session__mmap_read(struct perf_session *self) { - int i, counter; + int i, counter, thread_index; for (i = 0; i < nr_cpus; i++) { for (counter = 0; counter < nr_counters; counter++) - perf_session__mmap_read_counter(self, &mmap_array[i][counter]); + for (thread_index = 0; + thread_index < thread_num; + thread_index++) { + perf_session__mmap_read_counter(self, + &mmap_array[i][counter][thread_index]); + } } } @@ -1149,9 +1159,10 @@ static void start_counter(int i, int counter) { struct perf_event_attr *attr; int cpu; + int thread_index; cpu = profile_cpu; - if (target_pid == -1 && profile_cpu == -1) + if (target_tid == -1 && profile_cpu == -1) cpu = cpumap[i]; attr = attrs + counter; @@ -1167,55 +1178,58 @@ static void start_counter(int i, int counter) attr->inherit = (cpu < 0) && inherit; attr->mmap = 1; + for (thread_index = 0; thread_index < thread_num; thread_index++) { try_again: - fd[i][counter] = sys_perf_event_open(attr, target_pid, cpu, group_fd, 0); - - if (fd[i][counter] < 0) { - int err = errno; + fd[i][counter][thread_index] = sys_perf_event_open(attr, + all_tids[thread_index], cpu, group_fd, 0); + + if (fd[i][counter][thread_index] < 0) { + int err = errno; + + if (err == EPERM || err == EACCES) + die("No permission - are you root?\n"); + /* + * If it's cycles then fall back to hrtimer + * based cpu-clock-tick sw counter, which + * is always available even if no PMU support: + */ + if (attr->type == PERF_TYPE_HARDWARE + && attr->config == PERF_COUNT_HW_CPU_CYCLES) { + + if (verbose) + warning(" ... trying to fall back to cpu-clock-ticks\n"); + + attr->type = PERF_TYPE_SOFTWARE; + attr->config = PERF_COUNT_SW_CPU_CLOCK; + goto try_again; + } + printf("\n"); + error("perfcounter syscall returned with %d (%s)\n", + fd[i][counter][thread_index], strerror(err)); + die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); + exit(-1); + } + assert(fd[i][counter][thread_index] >= 0); + fcntl(fd[i][counter][thread_index], F_SETFL, O_NONBLOCK); - if (err == EPERM || err == EACCES) - die("No permission - are you root?\n"); /* - * If it's cycles then fall back to hrtimer - * based cpu-clock-tick sw counter, which - * is always available even if no PMU support: + * First counter acts as the group leader: */ - if (attr->type == PERF_TYPE_HARDWARE - && attr->config == PERF_COUNT_HW_CPU_CYCLES) { - - if (verbose) - warning(" ... trying to fall back to cpu-clock-ticks\n"); - - attr->type = PERF_TYPE_SOFTWARE; - attr->config = PERF_COUNT_SW_CPU_CLOCK; - goto try_again; - } - printf("\n"); - error("perfcounter syscall returned with %d (%s)\n", - fd[i][counter], strerror(err)); - die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); - exit(-1); + if (group && group_fd == -1) + group_fd = fd[i][counter][thread_index]; + + event_array[nr_poll].fd = fd[i][counter][thread_index]; + event_array[nr_poll].events = POLLIN; + nr_poll++; + + mmap_array[i][counter][thread_index].counter = counter; + mmap_array[i][counter][thread_index].prev = 0; + mmap_array[i][counter][thread_index].mask = mmap_pages*page_size - 1; + mmap_array[i][counter][thread_index].base = mmap(NULL, (mmap_pages+1)*page_size, + PROT_READ, MAP_SHARED, fd[i][counter][thread_index], 0); + if (mmap_array[i][counter][thread_index].base == MAP_FAILED) + die("failed to mmap with %d (%s)\n", errno, strerror(errno)); } - assert(fd[i][counter] >= 0); - fcntl(fd[i][counter], F_SETFL, O_NONBLOCK); - - /* - * First counter acts as the group leader: - */ - if (group && group_fd == -1) - group_fd = fd[i][counter]; - - event_array[nr_poll].fd = fd[i][counter]; - event_array[nr_poll].events = POLLIN; - nr_poll++; - - mmap_array[i][counter].counter = counter; - mmap_array[i][counter].prev = 0; - mmap_array[i][counter].mask = mmap_pages*page_size - 1; - mmap_array[i][counter].base = mmap(NULL, (mmap_pages+1)*page_size, - PROT_READ, MAP_SHARED, fd[i][counter], 0); - if (mmap_array[i][counter].base == MAP_FAILED) - die("failed to mmap with %d (%s)\n", errno, strerror(errno)); } static int __cmd_top(void) @@ -1231,8 +1245,8 @@ static int __cmd_top(void) if (session == NULL) return -ENOMEM; - if (target_pid != -1) - event__synthesize_thread(target_pid, event__process, session); + if (target_tid != -1) + event__synthesize_thread(target_tid, event__process, session); else event__synthesize_threads(event__process, session); @@ -1243,7 +1257,7 @@ static int __cmd_top(void) } /* Wait for a minimal set of events before starting the snapshot */ - poll(event_array, nr_poll, 100); + poll(&event_array[0], nr_poll, 100); perf_session__mmap_read(session); @@ -1286,7 +1300,9 @@ static const struct option options[] = { OPT_INTEGER('c', "count", &default_interval, "event period to sample"), OPT_INTEGER('p', "pid", &target_pid, - "profile events on existing pid"), + "profile events on existing process id"), + OPT_INTEGER('t', "tid", &target_tid, + "profile events on existing thread id"), OPT_BOOLEAN('a', "all-cpus", &system_wide, "system-wide collection from all CPUs"), OPT_INTEGER('C', "CPU", &profile_cpu, @@ -1327,6 +1343,7 @@ static const struct option options[] = { int cmd_top(int argc, const char **argv, const char *prefix __used) { int counter; + int i,j; page_size = sysconf(_SC_PAGE_SIZE); @@ -1334,8 +1351,39 @@ int cmd_top(int argc, const char **argv, const char *prefix __used) if (argc) usage_with_options(top_usage, options); + if (target_pid != -1) { + target_tid = target_pid; + thread_num = find_all_tid(target_pid, &all_tids); + if (thread_num <= 0) { + fprintf(stderr, "Can't find all threads of pid %d\n", + target_pid); + usage_with_options(top_usage, options); + } + } else { + all_tids=malloc(sizeof(pid_t)); + if (!all_tids) + return -ENOMEM; + + all_tids[0] = target_tid; + thread_num = 1; + } + + for (i = 0; i < MAX_NR_CPUS; i++) { + for (j = 0; j < MAX_COUNTERS; j++) { + fd[i][j] = malloc(sizeof(int)*thread_num); + mmap_array[i][j] = malloc( + sizeof(struct mmap_data)*thread_num); + if (!fd[i][j] || !mmap_array[i][j]) + return -ENOMEM; + } + } + event_array = malloc( + sizeof(struct pollfd)*MAX_NR_CPUS*MAX_COUNTERS*thread_num); + if (!event_array) + return -ENOMEM; + /* CPU and PID are mutually exclusive */ - if (target_pid != -1 && profile_cpu != -1) { + if (target_tid > 0 && profile_cpu != -1) { printf("WARNING: PID switch overriding CPU\n"); sleep(1); profile_cpu = -1; @@ -1376,7 +1424,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used) attrs[counter].sample_period = default_interval; } - if (target_pid != -1 || profile_cpu != -1) + if (target_tid != -1 || profile_cpu != -1) nr_cpus = 1; else nr_cpus = read_cpu_map(); diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index fa96831..ea65062 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c @@ -7,6 +7,37 @@ #include "util.h" #include "debug.h" +int find_all_tid(int pid, pid_t ** all_tid) +{ + char name[256]; + int items; + struct dirent **namelist = NULL; + int ret = 0; + int i; + + sprintf(name, "/proc/%d/task", pid); + items = scandir(name, &namelist, NULL, NULL); + if (items <= 0) + return -ENOENT; + *all_tid = malloc(sizeof(pid_t) * items); + if (!*all_tid) { + ret = -ENOMEM; + goto failure; + } + + for (i = 0; i < items; i++) + (*all_tid)[i] = atoi(namelist[i]->d_name); + + ret = items; + +failure: + for (i=0; i Date: Wed, 17 Mar 2010 13:37:00 +0300 Subject: x86, apic: Allow to use certain functions without APIC built-in support In case even if the kernel is configured so that no APIC support is built-in we still may allow to use certain apic functions as dummy calls. In particular we start using it in perf-events code. Note that this is not that same as NOOP apic driver (which is used if APIC support is present but no physical APIC is available), this is for the case when we don't have apic code compiled in at all. Signed-off-by: Cyrill Gorcunov Cc: H. Peter Anvin Cc: Yinghai Lu Cc: Yinghai Lu LKML-Reference: <20100317104356.011052632@openvz.org> Signed-off-by: Ingo Molnar diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index b4ac2cd..1fa03e0 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -373,6 +373,7 @@ extern atomic_t init_deasserted; extern int wakeup_secondary_cpu_via_nmi(int apicid, unsigned long start_eip); #endif +#ifdef CONFIG_X86_LOCAL_APIC static inline u32 apic_read(u32 reg) { return apic->read(reg); @@ -403,10 +404,19 @@ static inline u32 safe_apic_wait_icr_idle(void) return apic->safe_wait_icr_idle(); } +#else /* CONFIG_X86_LOCAL_APIC */ + +static inline u32 apic_read(u32 reg) { return 0; } +static inline void apic_write(u32 reg, u32 val) { } +static inline u64 apic_icr_read(void) { return 0; } +static inline void apic_icr_write(u32 low, u32 high) { } +static inline void apic_wait_icr_idle(void) { } +static inline u32 safe_apic_wait_icr_idle(void) { return 0; } + +#endif /* CONFIG_X86_LOCAL_APIC */ static inline void ack_APIC_irq(void) { -#ifdef CONFIG_X86_LOCAL_APIC /* * ack_APIC_irq() actually gets compiled as a single instruction * ... yummie. @@ -414,7 +424,6 @@ static inline void ack_APIC_irq(void) /* Docs say use 0 for future compatibility */ apic_write(APIC_EOI, 0); -#endif } static inline unsigned default_get_apic_id(unsigned long x) -- cgit v0.10.2 From 7335f75e9ca166044e38a96abad422d8e6e364b5 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Wed, 17 Mar 2010 13:37:01 +0300 Subject: x86, perf: Use apic_write unconditionally Since apic_write() maps to a plain noop in the !CONFIG_X86_LOCAL_APIC case we're safe to remove this conditional compilation and clean up the code a bit. Signed-off-by: Cyrill Gorcunov Cc: fweisbec@gmail.com Cc: acme@redhat.com Cc: eranian@google.com Cc: peterz@infradead.org LKML-Reference: <20100317104356.232371479@openvz.org> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index c97d5b5..14eca80 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -1136,7 +1136,6 @@ void set_perf_event_pending(void) void perf_events_lapic_init(void) { -#ifdef CONFIG_X86_LOCAL_APIC if (!x86_pmu.apic || !x86_pmu_initialized()) return; @@ -1144,7 +1143,6 @@ void perf_events_lapic_init(void) * Always use NMI for PMU */ apic_write(APIC_LVTPC, APIC_DM_NMI); -#endif } static int __kprobes @@ -1168,9 +1166,7 @@ perf_event_nmi_handler(struct notifier_block *self, regs = args->regs; -#ifdef CONFIG_X86_LOCAL_APIC apic_write(APIC_LVTPC, APIC_DM_NMI); -#endif /* * Can't rely on the handled return value to say it was our NMI, two * events could trigger 'simultaneously' raising two back-to-back NMIs. diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index a11ce73..0367889 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c @@ -363,10 +363,8 @@ static int p4_pmu_handle_irq(struct pt_regs *regs) } if (handled) { -#ifdef CONFIG_X86_LOCAL_APIC /* p4 quirk: unmask it again */ apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED); -#endif inc_irq_stat(apic_perf_irqs); } -- cgit v0.10.2 From 55632770d7298835645489828af87f854c47749c Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 18 Mar 2010 16:51:16 +0100 Subject: perf events: Fix false positive build warning with older GCC's gcc 4.2.1 produces: util/probe-event.c: In function 'add_perf_probe_events': util/probe-event.c:883: warning: 'tev' may be used uninitialized in this function make: *** [util/probe-event.o] Error 1 Newer GCCs get this right. To work it around, initialize the variable to NULL so that older GCCs see it as initialized too. Cc: Masami Hiramatsu Cc: Frederic Weisbecker Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Mike Galbraith Cc: Peter Zijlstra LKML-Reference: <20100316220612.32050.33806.stgit@localhost6.localdomain6> Signed-off-by: Ingo Molnar diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index f333269..c6603f3 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -880,7 +880,7 @@ static void __add_kprobe_trace_events(struct perf_probe_event *pev, int ntevs, bool allow_suffix) { int i, fd; - struct kprobe_trace_event *tev; + struct kprobe_trace_event *tev = NULL; char buf[64]; const char *event, *group; struct strlist *namelist; -- cgit v0.10.2 From f34edbc1cdb0f8f83d94e1d668dd6e41abf0defb Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Thu, 18 Mar 2010 18:33:07 +0800 Subject: perf, x86: Add a key to simplify template lookup in Pentium-4 PMU Currently, we use opcode(Event and Event-Selector) + emask to look up template in p4_templates. But cache events (L1-dcache-load-misses, LLC-load-misses, etc) use the same event(P4_REPLAY_EVENT) to do the counting, ie, they have the same opcode and emask. So we can not use current lookup mechanism to find the template for cache events. This patch introduces a "key", which is the index into p4_templates. The low 12 bits of CCCR are reserved, so we can hide the "key" in the low 12 bits of hwc->config. We extract the key from hwc->config and then quickly find the template. Signed-off-by: Lin Ming Reviewed-by: Cyrill Gorcunov Cc: Peter Zijlstra LKML-Reference: <1268908387.13901.127.camel@minggr.sh.intel.com> Signed-off-by: Ingo Molnar diff --git a/arch/x86/include/asm/perf_event_p4.h b/arch/x86/include/asm/perf_event_p4.h index b842b32..7d3406a 100644 --- a/arch/x86/include/asm/perf_event_p4.h +++ b/arch/x86/include/asm/perf_event_p4.h @@ -65,6 +65,7 @@ #define P4_CCCR_THREAD_SINGLE 0x00010000U #define P4_CCCR_THREAD_BOTH 0x00020000U #define P4_CCCR_THREAD_ANY 0x00030000U +#define P4_CCCR_RESERVED 0x00000fffU /* Non HT mask */ #define P4_CCCR_MASK \ @@ -116,7 +117,7 @@ #define p4_config_pack_escr(v) (((u64)(v)) << 32) #define p4_config_pack_cccr(v) (((u64)(v)) & 0xffffffffULL) #define p4_config_unpack_escr(v) (((u64)(v)) >> 32) -#define p4_config_unpack_cccr(v) (((u64)(v)) & 0xffffffffULL) +#define p4_config_unpack_cccr(v) (((u64)(v)) & 0xfffff000ULL) #define p4_config_unpack_emask(v) \ ({ \ @@ -126,6 +127,8 @@ t; \ }) +#define p4_config_unpack_key(v) (((u64)(v)) & P4_CCCR_RESERVED) + #define P4_CONFIG_HT_SHIFT 63 #define P4_CONFIG_HT (1ULL << P4_CONFIG_HT_SHIFT) diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index 0367889..3e97ed3 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c @@ -18,6 +18,7 @@ struct p4_event_template { u32 opcode; /* ESCR event + CCCR selector */ u64 config; /* packed predefined bits */ int dep; /* upstream dependency event index */ + int key; /* index into p4_templates */ unsigned int emask; /* ESCR EventMask */ unsigned int escr_msr[2]; /* ESCR MSR for this event */ unsigned int cntr[2]; /* counter index (offset) */ @@ -39,38 +40,31 @@ static DEFINE_PER_CPU(struct p4_pmu_res, p4_pmu_config); */ struct p4_event_template p4_templates[] = { [0] = { - .opcode = P4_UOP_TYPE, - .config = 0, - .dep = -1, - .emask = - P4_EVENT_ATTR(P4_UOP_TYPE, TAGLOADS) | - P4_EVENT_ATTR(P4_UOP_TYPE, TAGSTORES), - .escr_msr = { MSR_P4_RAT_ESCR0, MSR_P4_RAT_ESCR1 }, - .cntr = { 16, 17 }, - }, - [1] = { .opcode = P4_GLOBAL_POWER_EVENTS, .config = 0, .dep = -1, + .key = 0, .emask = P4_EVENT_ATTR(P4_GLOBAL_POWER_EVENTS, RUNNING), .escr_msr = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 }, .cntr = { 0, 2 }, }, - [2] = { + [1] = { .opcode = P4_INSTR_RETIRED, .config = 0, .dep = -1, /* needs front-end tagging */ + .key = 1, .emask = P4_EVENT_ATTR(P4_INSTR_RETIRED, NBOGUSNTAG) | P4_EVENT_ATTR(P4_INSTR_RETIRED, BOGUSNTAG), .escr_msr = { MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR1 }, .cntr = { 12, 14 }, }, - [3] = { + [2] = { .opcode = P4_BSQ_CACHE_REFERENCE, .config = 0, .dep = -1, + .key = 2, .emask = P4_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_2ndL_HITS) | P4_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_2ndL_HITE) | @@ -81,10 +75,11 @@ struct p4_event_template p4_templates[] = { .escr_msr = { MSR_P4_BSU_ESCR0, MSR_P4_BSU_ESCR1 }, .cntr = { 0, 2 }, }, - [4] = { + [3] = { .opcode = P4_BSQ_CACHE_REFERENCE, .config = 0, .dep = -1, + .key = 3, .emask = P4_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_2ndL_MISS) | P4_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_3rdL_MISS) | @@ -92,10 +87,11 @@ struct p4_event_template p4_templates[] = { .escr_msr = { MSR_P4_BSU_ESCR0, MSR_P4_BSU_ESCR1 }, .cntr = { 0, 3 }, }, - [5] = { + [4] = { .opcode = P4_RETIRED_BRANCH_TYPE, .config = 0, .dep = -1, + .key = 4, .emask = P4_EVENT_ATTR(P4_RETIRED_BRANCH_TYPE, CONDITIONAL) | P4_EVENT_ATTR(P4_RETIRED_BRANCH_TYPE, CALL) | @@ -104,48 +100,38 @@ struct p4_event_template p4_templates[] = { .escr_msr = { MSR_P4_TBPU_ESCR0, MSR_P4_TBPU_ESCR1 }, .cntr = { 4, 6 }, }, - [6] = { + [5] = { .opcode = P4_MISPRED_BRANCH_RETIRED, .config = 0, .dep = -1, + .key = 5, .emask = P4_EVENT_ATTR(P4_MISPRED_BRANCH_RETIRED, NBOGUS), .escr_msr = { MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR1 }, .cntr = { 12, 14 }, }, - [7] = { + [6] = { .opcode = P4_FSB_DATA_ACTIVITY, .config = p4_config_pack_cccr(P4_CCCR_EDGE | P4_CCCR_COMPARE), .dep = -1, + .key = 6, .emask = P4_EVENT_ATTR(P4_FSB_DATA_ACTIVITY, DRDY_DRV) | P4_EVENT_ATTR(P4_FSB_DATA_ACTIVITY, DRDY_OWN), .escr_msr = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 }, .cntr = { 0, 2 }, }, -}; - -static struct p4_event_template *p4_event_map[PERF_COUNT_HW_MAX] = { - /* non-halted CPU clocks */ - [PERF_COUNT_HW_CPU_CYCLES] = &p4_templates[1], - - /* retired instructions: dep on tagging the FSB */ - [PERF_COUNT_HW_INSTRUCTIONS] = &p4_templates[2], - - /* cache hits */ - [PERF_COUNT_HW_CACHE_REFERENCES] = &p4_templates[3], - - /* cache misses */ - [PERF_COUNT_HW_CACHE_MISSES] = &p4_templates[4], - - /* branch instructions retired */ - [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = &p4_templates[5], - - /* mispredicted branches retired */ - [PERF_COUNT_HW_BRANCH_MISSES] = &p4_templates[6], - - /* bus ready clocks (cpu is driving #DRDY_DRV\#DRDY_OWN): */ - [PERF_COUNT_HW_BUS_CYCLES] = &p4_templates[7], + [7] = { + .opcode = P4_UOP_TYPE, + .config = 0, + .dep = -1, + .key = 7, + .emask = + P4_EVENT_ATTR(P4_UOP_TYPE, TAGLOADS) | + P4_EVENT_ATTR(P4_UOP_TYPE, TAGSTORES), + .escr_msr = { MSR_P4_RAT_ESCR0, MSR_P4_RAT_ESCR1 }, + .cntr = { 16, 17 }, + }, }; static u64 p4_pmu_event_map(int hw_event) @@ -153,11 +139,11 @@ static u64 p4_pmu_event_map(int hw_event) struct p4_event_template *tpl; u64 config; - if (hw_event > ARRAY_SIZE(p4_event_map)) { + if (hw_event > ARRAY_SIZE(p4_templates)) { printk_once(KERN_ERR "PMU: Incorrect event index\n"); return 0; } - tpl = p4_event_map[hw_event]; + tpl = &p4_templates[hw_event]; /* * fill config up according to @@ -167,6 +153,7 @@ static u64 p4_pmu_event_map(int hw_event) config |= p4_config_pack_escr(P4_EVENT_UNPACK_EVENT(tpl->opcode) << P4_EVNTSEL_EVENT_SHIFT); config |= p4_config_pack_escr(tpl->emask << P4_EVNTSEL_EVENTMASK_SHIFT); config |= p4_config_pack_cccr(P4_EVENT_UNPACK_SELECTOR(tpl->opcode) << P4_CCCR_ESCR_SELECT_SHIFT); + config |= p4_config_pack_cccr(hw_event & P4_CCCR_RESERVED); /* on HT machine we need a special bit */ if (p4_ht_active() && p4_ht_thread(raw_smp_processor_id())) @@ -187,17 +174,12 @@ static inline int p4_pmu_emask_match(unsigned int dst, unsigned int src) static struct p4_event_template *p4_pmu_template_lookup(u64 config) { - u32 opcode = p4_config_unpack_opcode(config); - unsigned int emask = p4_config_unpack_emask(config); - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(p4_templates); i++) { - if (opcode == p4_templates[i].opcode && - p4_pmu_emask_match(emask, p4_templates[i].emask)) - return &p4_templates[i]; - } + int key = p4_config_unpack_key(config); - return NULL; + if (key < ARRAY_SIZE(p4_templates)) + return &p4_templates[key]; + else + return NULL; } /* @@ -564,7 +546,7 @@ static __initconst struct x86_pmu p4_pmu = { .perfctr = MSR_P4_BPU_PERFCTR0, .event_map = p4_pmu_event_map, .raw_event = p4_pmu_raw_event, - .max_events = ARRAY_SIZE(p4_event_map), + .max_events = ARRAY_SIZE(p4_templates), .get_event_constraints = x86_get_event_constraints, /* * IF HT disabled we may need to use all -- cgit v0.10.2 From cb7d6b5053e86598735d9af19930f5929f007b7f Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Thu, 18 Mar 2010 18:33:12 +0800 Subject: perf, x86: Add cache events for the Pentium-4 PMU Move the HT bit setting code from p4_pmu_event_map to p4_hw_config. So the cache events can get HT bit set correctly. Tested on my P4 desktop, below 6 cache events work: L1-dcache-load-misses LLC-load-misses dTLB-load-misses dTLB-store-misses iTLB-loads iTLB-load-misses Signed-off-by: Lin Ming Reviewed-by: Cyrill Gorcunov Cc: Peter Zijlstra LKML-Reference: <1268908392.13901.128.camel@minggr.sh.intel.com> Signed-off-by: Ingo Molnar diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 1cd58cd..aef562c 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -357,6 +357,8 @@ #define MSR_P4_U2L_ESCR0 0x000003b0 #define MSR_P4_U2L_ESCR1 0x000003b1 +#define MSR_P4_PEBS_MATRIX_VERT 0x000003f2 + /* Intel Core-based CPU performance counters */ #define MSR_CORE_PERF_FIXED_CTR0 0x00000309 #define MSR_CORE_PERF_FIXED_CTR1 0x0000030a diff --git a/arch/x86/include/asm/perf_event_p4.h b/arch/x86/include/asm/perf_event_p4.h index 7d3406a..871249c 100644 --- a/arch/x86/include/asm/perf_event_p4.h +++ b/arch/x86/include/asm/perf_event_p4.h @@ -708,4 +708,14 @@ enum P4_EVENTS_ATTR { P4_MAKE_EVENT_ATTR(P4_INSTR_COMPLETED, BOGUS, 1), }; +enum { + KEY_P4_L1D_OP_READ_RESULT_MISS, + KEY_P4_LL_OP_READ_RESULT_MISS, + KEY_P4_DTLB_OP_READ_RESULT_MISS, + KEY_P4_DTLB_OP_WRITE_RESULT_MISS, + KEY_P4_ITLB_OP_READ_RESULT_ACCESS, + KEY_P4_ITLB_OP_READ_RESULT_MISS, + KEY_P4_UOP_TYPE, +}; + #endif /* PERF_EVENT_P4_H */ diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index 3e97ed3..b7bf991 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c @@ -19,6 +19,11 @@ struct p4_event_template { u64 config; /* packed predefined bits */ int dep; /* upstream dependency event index */ int key; /* index into p4_templates */ + u64 msr; /* + * the high 32 bits set into MSR_IA32_PEBS_ENABLE and + * the low 32 bits set into MSR_P4_PEBS_MATRIX_VERT + * for cache events + */ unsigned int emask; /* ESCR EventMask */ unsigned int escr_msr[2]; /* ESCR MSR for this event */ unsigned int cntr[2]; /* counter index (offset) */ @@ -31,6 +36,67 @@ struct p4_pmu_res { static DEFINE_PER_CPU(struct p4_pmu_res, p4_pmu_config); +#define P4_CACHE_EVENT_CONFIG(event, bit) \ + p4_config_pack_escr(P4_EVENT_UNPACK_EVENT(event) << P4_EVNTSEL_EVENT_SHIFT) | \ + p4_config_pack_escr((event##_##bit) << P4_EVNTSEL_EVENTMASK_SHIFT) | \ + p4_config_pack_cccr(P4_EVENT_UNPACK_SELECTOR(event) << P4_CCCR_ESCR_SELECT_SHIFT) + +static __initconst u64 p4_hw_cache_event_ids + [PERF_COUNT_HW_CACHE_MAX] + [PERF_COUNT_HW_CACHE_OP_MAX] + [PERF_COUNT_HW_CACHE_RESULT_MAX] = +{ + [ C(L1D ) ] = { + [ C(OP_READ) ] = { + [ C(RESULT_ACCESS) ] = 0x0, + /* 1stL_cache_load_miss_retired */ + [ C(RESULT_MISS) ] = P4_CACHE_EVENT_CONFIG(P4_REPLAY_EVENT, NBOGUS) + | KEY_P4_L1D_OP_READ_RESULT_MISS, + }, + }, + [ C(LL ) ] = { + [ C(OP_READ) ] = { + [ C(RESULT_ACCESS) ] = 0x0, + /* 2ndL_cache_load_miss_retired */ + [ C(RESULT_MISS) ] = P4_CACHE_EVENT_CONFIG(P4_REPLAY_EVENT, NBOGUS) + | KEY_P4_LL_OP_READ_RESULT_MISS, + }, + }, + [ C(DTLB) ] = { + [ C(OP_READ) ] = { + [ C(RESULT_ACCESS) ] = 0x0, + /* DTLB_load_miss_retired */ + [ C(RESULT_MISS) ] = P4_CACHE_EVENT_CONFIG(P4_REPLAY_EVENT, NBOGUS) + | KEY_P4_DTLB_OP_READ_RESULT_MISS, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = 0x0, + /* DTLB_store_miss_retired */ + [ C(RESULT_MISS) ] = P4_CACHE_EVENT_CONFIG(P4_REPLAY_EVENT, NBOGUS) + | KEY_P4_DTLB_OP_WRITE_RESULT_MISS, + }, + }, + [ C(ITLB) ] = { + [ C(OP_READ) ] = { + /* ITLB_reference.HIT */ + [ C(RESULT_ACCESS) ] = P4_CACHE_EVENT_CONFIG(P4_ITLB_REFERENCE, HIT) + | KEY_P4_ITLB_OP_READ_RESULT_ACCESS, + + /* ITLB_reference.MISS */ + [ C(RESULT_MISS) ] = P4_CACHE_EVENT_CONFIG(P4_ITLB_REFERENCE, MISS) + | KEY_P4_ITLB_OP_READ_RESULT_MISS, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = -1, + [ C(RESULT_MISS) ] = -1, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = -1, + [ C(RESULT_MISS) ] = -1, + }, + }, +}; + /* * WARN: CCCR1 doesn't have a working enable bit so try to not * use it if possible @@ -121,11 +187,77 @@ struct p4_event_template p4_templates[] = { .escr_msr = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 }, .cntr = { 0, 2 }, }, - [7] = { + [KEY_P4_L1D_OP_READ_RESULT_MISS] = { + .opcode = P4_REPLAY_EVENT, + .config = 0, + .dep = -1, + .msr = (u64)(1 << 0 | 1 << 24) << 32 | (1 << 0), + .key = KEY_P4_L1D_OP_READ_RESULT_MISS, + .emask = + P4_EVENT_ATTR(P4_REPLAY_EVENT, NBOGUS), + .escr_msr = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR2 }, + .cntr = { 16, 17 }, + }, + [KEY_P4_LL_OP_READ_RESULT_MISS] = { + .opcode = P4_REPLAY_EVENT, + .config = 0, + .dep = -1, + .msr = (u64)(1 << 1 | 1 << 24) << 32 | (1 << 0), + .key = KEY_P4_LL_OP_READ_RESULT_MISS, + .emask = + P4_EVENT_ATTR(P4_REPLAY_EVENT, NBOGUS), + .escr_msr = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR2 }, + .cntr = { 16, 17 }, + }, + [KEY_P4_DTLB_OP_READ_RESULT_MISS] = { + .opcode = P4_REPLAY_EVENT, + .config = 0, + .dep = -1, + .msr = (u64)(1 << 2 | 1 << 24) << 32 | (1 << 0), + .key = KEY_P4_DTLB_OP_READ_RESULT_MISS, + .emask = + P4_EVENT_ATTR(P4_REPLAY_EVENT, NBOGUS), + .escr_msr = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR2 }, + .cntr = { 16, 17 }, + }, + [KEY_P4_DTLB_OP_WRITE_RESULT_MISS] = { + .opcode = P4_REPLAY_EVENT, + .config = 0, + .dep = -1, + .msr = (u64)(1 << 2 | 1 << 24) << 32 | (1 << 1), + .key = KEY_P4_DTLB_OP_WRITE_RESULT_MISS, + .emask = + P4_EVENT_ATTR(P4_REPLAY_EVENT, NBOGUS), + .escr_msr = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR2 }, + .cntr = { 16, 17 }, + }, + [KEY_P4_ITLB_OP_READ_RESULT_ACCESS] = { + .opcode = P4_ITLB_REFERENCE, + .config = 0, + .dep = -1, + .msr = 0, + .key = KEY_P4_ITLB_OP_READ_RESULT_ACCESS, + .emask = + P4_EVENT_ATTR(P4_ITLB_REFERENCE, HIT), + .escr_msr = { MSR_P4_ITLB_ESCR0, MSR_P4_ITLB_ESCR1 }, + .cntr = { 0, 2 }, + }, + [KEY_P4_ITLB_OP_READ_RESULT_MISS] = { + .opcode = P4_ITLB_REFERENCE, + .config = 0, + .dep = -1, + .msr = 0, + .key = KEY_P4_ITLB_OP_READ_RESULT_MISS, + .emask = + P4_EVENT_ATTR(P4_ITLB_REFERENCE, MISS), + .escr_msr = { MSR_P4_ITLB_ESCR0, MSR_P4_ITLB_ESCR1 }, + .cntr = { 0, 2 }, + }, + [KEY_P4_UOP_TYPE] = { .opcode = P4_UOP_TYPE, .config = 0, .dep = -1, - .key = 7, + .key = KEY_P4_UOP_TYPE, .emask = P4_EVENT_ATTR(P4_UOP_TYPE, TAGLOADS) | P4_EVENT_ATTR(P4_UOP_TYPE, TAGSTORES), @@ -155,10 +287,6 @@ static u64 p4_pmu_event_map(int hw_event) config |= p4_config_pack_cccr(P4_EVENT_UNPACK_SELECTOR(tpl->opcode) << P4_CCCR_ESCR_SELECT_SHIFT); config |= p4_config_pack_cccr(hw_event & P4_CCCR_RESERVED); - /* on HT machine we need a special bit */ - if (p4_ht_active() && p4_ht_thread(raw_smp_processor_id())) - config = p4_set_ht_bit(config); - return config; } @@ -211,6 +339,10 @@ static int p4_hw_config(struct perf_event_attr *attr, struct hw_perf_event *hwc) /* Count user and OS events unless not requested to */ hwc->config |= p4_config_pack_escr(p4_default_escr_conf(cpu, attr->exclude_kernel, attr->exclude_user)); + /* on HT machine we need a special bit */ + if (p4_ht_active() && p4_ht_thread(cpu)) + hwc->config = p4_set_ht_bit(hwc->config); + return 0; } @@ -271,6 +403,12 @@ static void p4_pmu_enable_event(struct perf_event *event) pr_crit("%s: Wrong index: %d\n", __func__, hwc->idx); return; } + + if (tpl->msr) { + (void)checking_wrmsrl(MSR_IA32_PEBS_ENABLE, tpl->msr >> 32); + (void)checking_wrmsrl(MSR_P4_PEBS_MATRIX_VERT, tpl->msr & 0xffffffff); + } + escr_base = (u64)tpl->escr_msr[thread]; /* @@ -577,6 +715,9 @@ static __init int p4_pmu_init(void) return -ENODEV; } + memcpy(hw_cache_event_ids, p4_hw_cache_event_ids, + sizeof(hw_cache_event_ids)); + pr_cont("Netburst events, "); x86_pmu = p4_pmu; -- cgit v0.10.2 From 4b24a88b35e15e04bd8f2c5dda65b5dc8ebca05f Mon Sep 17 00:00:00 2001 From: Stephane Eranian Date: Wed, 17 Mar 2010 23:21:01 +0200 Subject: perf_events: Fix resource leak in x86 __hw_perf_event_init() If reserve_pmc_hardware() succeeds but reserve_ds_buffers() fails, then we need to release_pmc_hardware. It won't be done by the destroy() callback because we return before setting it in case of error. Signed-off-by: Stephane Eranian Cc: Cc: peterz@infradead.org Cc: paulus@samba.org Cc: davem@davemloft.net Cc: fweisbec@gmail.com Cc: robert.richter@amd.com Cc: perfmon2-devel@lists.sf.net LKML-Reference: <4ba1568b.15185e0a.182a.7802@mx.google.com> Signed-off-by: Ingo Molnar -- arch/x86/kernel/cpu/perf_event.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 14eca80..f571f51 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -455,8 +455,11 @@ static int __hw_perf_event_init(struct perf_event *event) if (atomic_read(&active_events) == 0) { if (!reserve_pmc_hardware()) err = -EBUSY; - else + else { err = reserve_ds_buffers(); + if (err) + release_pmc_hardware(); + } } if (!err) atomic_inc(&active_events); -- cgit v0.10.2 From 9c8c6bad3137112d2c7bf3d215b736ee4215fa74 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Fri, 19 Mar 2010 00:12:56 +0300 Subject: x86, perf: Fix few cosmetic dabs for P4 pmu (comments and constantify) - A few ESCR have escaped fixing at previous attempt. - p4_escr_map is read only, make it const. Nothing serious. Signed-off-by: Cyrill Gorcunov Cc: Lin Ming LKML-Reference: <20100318211256.GH5062@lenovo> Signed-off-by: Ingo Molnar diff --git a/arch/x86/include/asm/perf_event_p4.h b/arch/x86/include/asm/perf_event_p4.h index 871249c..2a1a57f 100644 --- a/arch/x86/include/asm/perf_event_p4.h +++ b/arch/x86/include/asm/perf_event_p4.h @@ -401,13 +401,13 @@ static inline u32 p4_default_escr_conf(int cpu, int exclude_os, int exclude_usr) #define P4_RETIRED_MISPRED_BRANCH_TYPE P4_EVENT_PACK(0x05, 0x02) /* * MSR_P4_TBPU_ESCR0: 4, 5 - * MSR_P4_TBPU_ESCR0: 6, 7 + * MSR_P4_TBPU_ESCR1: 6, 7 */ #define P4_RETIRED_BRANCH_TYPE P4_EVENT_PACK(0x04, 0x02) /* * MSR_P4_TBPU_ESCR0: 4, 5 - * MSR_P4_TBPU_ESCR0: 6, 7 + * MSR_P4_TBPU_ESCR1: 6, 7 */ #define P4_RESOURCE_STALL P4_EVENT_PACK(0x01, 0x01) diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index b7bf991..b8a811a 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c @@ -545,7 +545,7 @@ static void p4_pmu_swap_config_ts(struct hw_perf_event *hwc, int cpu) } /* ESCRs are not sequential in memory so we need a map */ -static unsigned int p4_escr_map[ARCH_P4_TOTAL_ESCR] = { +static const unsigned int p4_escr_map[ARCH_P4_TOTAL_ESCR] = { MSR_P4_ALF_ESCR0, /* 0 */ MSR_P4_ALF_ESCR1, /* 1 */ MSR_P4_BPU_ESCR0, /* 2 */ -- cgit v0.10.2 From 01e9651a21bc0e6731da733593e4aaf4cf46b5e5 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 10 Mar 2010 09:31:01 +0000 Subject: sh: add INTC out of memory error handling Extend the INTC code to warn and return an error code in the case of memory allocation failure. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c index c275039..d4aa4d1 100644 --- a/drivers/sh/intc.c +++ b/drivers/sh/intc.c @@ -789,13 +789,15 @@ static void intc_redirect_irq(unsigned int irq, struct irq_desc *desc) generic_handle_irq((unsigned int)get_irq_data(irq)); } -void __init register_intc_controller(struct intc_desc *desc) +int __init register_intc_controller(struct intc_desc *desc) { unsigned int i, k, smp; struct intc_hw_desc *hw = &desc->hw; struct intc_desc_int *d; d = kzalloc(sizeof(*d), GFP_NOWAIT); + if (!d) + goto err0; INIT_LIST_HEAD(&d->list); list_add(&d->list, &intc_list); @@ -806,8 +808,13 @@ void __init register_intc_controller(struct intc_desc *desc) d->nr_reg += hw->ack_regs ? hw->nr_ack_regs : 0; d->reg = kzalloc(d->nr_reg * sizeof(*d->reg), GFP_NOWAIT); + if (!d->reg) + goto err1; + #ifdef CONFIG_SMP d->smp = kzalloc(d->nr_reg * sizeof(*d->smp), GFP_NOWAIT); + if (!d->smp) + goto err2; #endif k = 0; @@ -822,6 +829,8 @@ void __init register_intc_controller(struct intc_desc *desc) if (hw->prio_regs) { d->prio = kzalloc(hw->nr_vectors * sizeof(*d->prio), GFP_NOWAIT); + if (!d->prio) + goto err3; for (i = 0; i < hw->nr_prio_regs; i++) { smp = IS_SMP(hw->prio_regs[i]); @@ -833,6 +842,8 @@ void __init register_intc_controller(struct intc_desc *desc) if (hw->sense_regs) { d->sense = kzalloc(hw->nr_vectors * sizeof(*d->sense), GFP_NOWAIT); + if (!d->sense) + goto err4; for (i = 0; i < hw->nr_sense_regs; i++) k += save_reg(d, k, hw->sense_regs[i].reg, 0); @@ -912,6 +923,22 @@ void __init register_intc_controller(struct intc_desc *desc) /* enable bits matching force_enable after registering irqs */ if (desc->force_enable) intc_enable_disable_enum(desc, d, desc->force_enable, 1); + + return 0; + err4: + kfree(d->prio); + err3: +#ifdef CONFIG_SMP + kfree(d->smp); + err2: +#endif + kfree(d->reg); + err1: + kfree(d); + err0: + pr_err("unable to allocate INTC memory\n"); + + return -ENOMEM; } static int intc_suspend(struct sys_device *dev, pm_message_t state) diff --git a/include/linux/sh_intc.h b/include/linux/sh_intc.h index 51d288d..df37770 100644 --- a/include/linux/sh_intc.h +++ b/include/linux/sh_intc.h @@ -92,7 +92,7 @@ struct intc_desc symbol __initdata = { \ prio_regs, sense_regs, ack_regs), \ } -void __init register_intc_controller(struct intc_desc *desc); +int __init register_intc_controller(struct intc_desc *desc); int intc_set_priority(unsigned int irq, unsigned int prio); int reserve_irq_vector(unsigned int irq); -- cgit v0.10.2 From dec710b77c2cf04bf512acada3c14a16f11708d9 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 19 Mar 2010 16:48:01 +0900 Subject: sh: INTC ioremap support Extend the INTC code with ioremap() support V2. Support INTC controllers that are not accessible through a 1:1 virt:phys window. Needed by SH-Mobile ARM INTCS. The INTC code behaves as usual if the io window resource is omitted. The slow phys->virt lookup only happens during setup. The fast path code operates on virtual addresses. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c index d4aa4d1..a700dfe 100644 --- a/drivers/sh/intc.c +++ b/drivers/sh/intc.c @@ -43,6 +43,12 @@ struct intc_handle_int { unsigned long handle; }; +struct intc_window { + phys_addr_t phys; + void __iomem *virt; + unsigned long size; +}; + struct intc_desc_int { struct list_head list; struct sys_device sysdev; @@ -56,6 +62,8 @@ struct intc_desc_int { unsigned int nr_prio; struct intc_handle_int *sense; unsigned int nr_sense; + struct intc_window *window; + unsigned int nr_windows; struct irq_chip chip; }; @@ -420,11 +428,39 @@ static int intc_set_sense(unsigned int irq, unsigned int type) return 0; } +static unsigned long intc_phys_to_virt(struct intc_desc_int *d, + unsigned long address) +{ + struct intc_window *window; + int k; + + /* scan through physical windows and convert address */ + for (k = 0; k < d->nr_windows; k++) { + window = d->window + k; + + if (address < window->phys) + continue; + + if (address >= (window->phys + window->size)) + continue; + + address -= window->phys; + address += (unsigned long)window->virt; + + return address; + } + + /* no windows defined, register must be 1:1 mapped virt:phys */ + return address; +} + static unsigned int __init intc_get_reg(struct intc_desc_int *d, - unsigned long address) + unsigned long address) { unsigned int k; + address = intc_phys_to_virt(d, address); + for (k = 0; k < d->nr_reg; k++) { if (d->reg[k] == address) return k; @@ -774,6 +810,8 @@ static unsigned int __init save_reg(struct intc_desc_int *d, unsigned int smp) { if (value) { + value = intc_phys_to_virt(d, value); + d->reg[cnt] = value; #ifdef CONFIG_SMP d->smp[cnt] = smp; @@ -794,6 +832,7 @@ int __init register_intc_controller(struct intc_desc *desc) unsigned int i, k, smp; struct intc_hw_desc *hw = &desc->hw; struct intc_desc_int *d; + struct resource *res; d = kzalloc(sizeof(*d), GFP_NOWAIT); if (!d) @@ -802,6 +841,25 @@ int __init register_intc_controller(struct intc_desc *desc) INIT_LIST_HEAD(&d->list); list_add(&d->list, &intc_list); + if (desc->num_resources) { + d->nr_windows = desc->num_resources; + d->window = kzalloc(d->nr_windows * sizeof(*d->window), + GFP_NOWAIT); + if (!d->window) + goto err1; + + for (k = 0; k < d->nr_windows; k++) { + res = desc->resource + k; + WARN_ON(resource_type(res) != IORESOURCE_MEM); + d->window[k].phys = res->start; + d->window[k].size = resource_size(res); + d->window[k].virt = ioremap_nocache(res->start, + resource_size(res)); + if (!d->window[k].virt) + goto err2; + } + } + d->nr_reg = hw->mask_regs ? hw->nr_mask_regs * 2 : 0; d->nr_reg += hw->prio_regs ? hw->nr_prio_regs * 2 : 0; d->nr_reg += hw->sense_regs ? hw->nr_sense_regs : 0; @@ -809,12 +867,12 @@ int __init register_intc_controller(struct intc_desc *desc) d->reg = kzalloc(d->nr_reg * sizeof(*d->reg), GFP_NOWAIT); if (!d->reg) - goto err1; + goto err2; #ifdef CONFIG_SMP d->smp = kzalloc(d->nr_reg * sizeof(*d->smp), GFP_NOWAIT); if (!d->smp) - goto err2; + goto err3; #endif k = 0; @@ -830,7 +888,7 @@ int __init register_intc_controller(struct intc_desc *desc) d->prio = kzalloc(hw->nr_vectors * sizeof(*d->prio), GFP_NOWAIT); if (!d->prio) - goto err3; + goto err4; for (i = 0; i < hw->nr_prio_regs; i++) { smp = IS_SMP(hw->prio_regs[i]); @@ -843,7 +901,7 @@ int __init register_intc_controller(struct intc_desc *desc) d->sense = kzalloc(hw->nr_vectors * sizeof(*d->sense), GFP_NOWAIT); if (!d->sense) - goto err4; + goto err5; for (i = 0; i < hw->nr_sense_regs; i++) k += save_reg(d, k, hw->sense_regs[i].reg, 0); @@ -925,17 +983,23 @@ int __init register_intc_controller(struct intc_desc *desc) intc_enable_disable_enum(desc, d, desc->force_enable, 1); return 0; - err4: +err5: kfree(d->prio); - err3: +err4: #ifdef CONFIG_SMP kfree(d->smp); - err2: +err3: #endif kfree(d->reg); - err1: +err2: + for (k = 0; k < d->nr_windows; k++) + if (d->window[k].virt) + iounmap(d->window[k].virt); + + kfree(d->window); +err1: kfree(d); - err0: +err0: pr_err("unable to allocate INTC memory\n"); return -ENOMEM; diff --git a/include/linux/sh_intc.h b/include/linux/sh_intc.h index df37770..01d8168 100644 --- a/include/linux/sh_intc.h +++ b/include/linux/sh_intc.h @@ -1,6 +1,8 @@ #ifndef __SH_INTC_H #define __SH_INTC_H +#include + typedef unsigned char intc_enum; struct intc_vect { @@ -71,6 +73,8 @@ struct intc_hw_desc { struct intc_desc { char *name; + struct resource *resource; + unsigned int num_resources; intc_enum force_enable; intc_enum force_disable; struct intc_hw_desc hw; -- cgit v0.10.2 From 40b7e05e17eef31ff30fe08dfc2424ef653a792c Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Fri, 19 Mar 2010 15:28:58 +0800 Subject: perf, x86: Fix key indexing in Pentium-4 PMU Index 0-6 in p4_templates are reserved for common hardware events. So p4_templates is arranged as below: 0 - 6: common hardware events 7 - N: cache events N+1 - ...: other raw events Reported-by: Cyrill Gorcunov Signed-off-by: Lin Ming Acked-by: Cyrill Gorcunov Cc: Peter Zijlstra LKML-Reference: <1268983738.13901.142.camel@minggr.sh.intel.com> Signed-off-by: Ingo Molnar diff --git a/arch/x86/include/asm/perf_event_p4.h b/arch/x86/include/asm/perf_event_p4.h index 2a1a57f..facf961 100644 --- a/arch/x86/include/asm/perf_event_p4.h +++ b/arch/x86/include/asm/perf_event_p4.h @@ -709,7 +709,7 @@ enum P4_EVENTS_ATTR { }; enum { - KEY_P4_L1D_OP_READ_RESULT_MISS, + KEY_P4_L1D_OP_READ_RESULT_MISS = PERF_COUNT_HW_MAX, KEY_P4_LL_OP_READ_RESULT_MISS, KEY_P4_DTLB_OP_READ_RESULT_MISS, KEY_P4_DTLB_OP_WRITE_RESULT_MISS, -- cgit v0.10.2 From 0deac0bf66110fe70507c5dcec661c9e85fa07ca Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 15 Mar 2010 20:36:22 +0000 Subject: ARM: Arrange for COMMON_CLKDEV to select HAVE_CLK If support for COMMON_CLKDEV is enabled, we have CLK support. Signed-off-by: Russell King diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c5408bf..bcaa8c8 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -238,7 +238,6 @@ config ARCH_INTEGRATOR bool "ARM Ltd. Integrator family" select ARM_AMBA select ARCH_HAS_CPUFREQ - select HAVE_CLK select COMMON_CLKDEV select ICST525 help @@ -247,7 +246,6 @@ config ARCH_INTEGRATOR config ARCH_REALVIEW bool "ARM Ltd. RealView family" select ARM_AMBA - select HAVE_CLK select COMMON_CLKDEV select ICST307 select GENERIC_TIME @@ -260,7 +258,6 @@ config ARCH_VERSATILE bool "ARM Ltd. Versatile family" select ARM_AMBA select ARM_VIC - select HAVE_CLK select COMMON_CLKDEV select ICST307 select GENERIC_TIME @@ -321,7 +318,6 @@ config ARCH_EP93XX select ARM_AMBA select ARM_VIC select GENERIC_GPIO - select HAVE_CLK select COMMON_CLKDEV select ARCH_REQUIRE_GPIOLIB select ARCH_HAS_HOLES_MEMORYMODEL @@ -341,7 +337,6 @@ config ARCH_MXC select GENERIC_TIME select GENERIC_CLOCKEVENTS select ARCH_REQUIRE_GPIOLIB - select HAVE_CLK select COMMON_CLKDEV help Support for Freescale MXC/iMX-based family of processors @@ -349,7 +344,6 @@ config ARCH_MXC config ARCH_STMP3XXX bool "Freescale STMP3xxx" select CPU_ARM926T - select HAVE_CLK select COMMON_CLKDEV select ARCH_REQUIRE_GPIOLIB select GENERIC_TIME @@ -516,7 +510,6 @@ config ARCH_MMP depends on MMU select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB - select HAVE_CLK select COMMON_CLKDEV select GENERIC_TIME select GENERIC_CLOCKEVENTS @@ -552,7 +545,6 @@ config ARCH_W90X900 select CPU_ARM926T select ARCH_REQUIRE_GPIOLIB select GENERIC_GPIO - select HAVE_CLK select COMMON_CLKDEV select GENERIC_TIME select GENERIC_CLOCKEVENTS @@ -568,7 +560,6 @@ config ARCH_W90X900 config ARCH_NUC93X bool "Nuvoton NUC93X CPU" select CPU_ARM926T - select HAVE_CLK select COMMON_CLKDEV help Support for Nuvoton (Winbond logic dept.) NUC93X MCU,The NUC93X is a @@ -577,7 +568,6 @@ config ARCH_NUC93X config ARCH_PNX4008 bool "Philips Nexperia PNX4008 Mobile" select CPU_ARM926T - select HAVE_CLK select COMMON_CLKDEV help This enables support for Philips PNX4008 mobile platform. @@ -588,7 +578,6 @@ config ARCH_PXA select ARCH_MTD_XIP select ARCH_HAS_CPUFREQ select GENERIC_GPIO - select HAVE_CLK select COMMON_CLKDEV select ARCH_REQUIRE_GPIOLIB select GENERIC_TIME @@ -743,7 +732,6 @@ config ARCH_U300 select ARM_VIC select GENERIC_TIME select GENERIC_CLOCKEVENTS - select HAVE_CLK select COMMON_CLKDEV select GENERIC_GPIO help @@ -764,7 +752,6 @@ config ARCH_NOMADIK select ARM_AMBA select ARM_VIC select CPU_ARM926T - select HAVE_CLK select COMMON_CLKDEV select GENERIC_TIME select GENERIC_CLOCKEVENTS @@ -780,7 +767,6 @@ config ARCH_DAVINCI select GENERIC_CLOCKEVENTS select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB - select HAVE_CLK select ZONE_DMA select HAVE_IDE select COMMON_CLKDEV diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig index 4efbb9d..b64bb78 100644 --- a/arch/arm/common/Kconfig +++ b/arch/arm/common/Kconfig @@ -40,3 +40,4 @@ config SHARP_SCOOP config COMMON_CLKDEV bool + select HAVE_CLK -- cgit v0.10.2 From e4bf5becccf4685754c4d8e4485bb2ff7d28147f Mon Sep 17 00:00:00 2001 From: viresh kumar Date: Tue, 9 Mar 2010 11:54:30 +0100 Subject: ARM: 5979/1: CLKDEV: return from clk_find as soon as we get maching clk clk_find function looks for clock with matching dev_id and con_id. We should return from clk_find as soon as we get a clock with matching dev_id and con_id. This can be done by comparing variable "match" with 3. Acked-by: Uwe Kleine-Konig Signed-off-by: Viresh Kumar Signed-off-by: Russell King diff --git a/arch/arm/common/clkdev.c b/arch/arm/common/clkdev.c index 6416d5b..4f8390d 100644 --- a/arch/arm/common/clkdev.c +++ b/arch/arm/common/clkdev.c @@ -52,12 +52,13 @@ static struct clk *clk_find(const char *dev_id, const char *con_id) continue; match += 1; } - if (match == 0) - continue; if (match > best) { clk = p->clk; - best = match; + if (match != 3) + best = match; + else + break; } } return clk; -- cgit v0.10.2 From 3a5e854e09b77c49c8030c7dfd3a3f506571a89a Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Wed, 3 Mar 2010 04:46:58 +0100 Subject: ARM: 5969/1: nomadik: move gpio to plat-nomadik Move the Nomadik GPIO driver to plat-nomadik so that it can also be used on the Ux500 platform. The mach-nomadik include/mach/gpio.h is replaced by one that includes the one now in plat-nomadik, so that code doesn't need to include the one in plat specifically, and can instead use as usual. Acked-by: Alessandro Rubini Acked-by: Linus Walleij Signed-off-by: Rabin Vincent Signed-off-by: Russell King diff --git a/arch/arm/mach-nomadik/Kconfig b/arch/arm/mach-nomadik/Kconfig index 3c5e0f5..71f3ea6 100644 --- a/arch/arm/mach-nomadik/Kconfig +++ b/arch/arm/mach-nomadik/Kconfig @@ -6,6 +6,7 @@ config MACH_NOMADIK_8815NHK bool "ST 8815 Nomadik Hardware Kit (evaluation board)" select NOMADIK_8815 select HAS_MTU + select NOMADIK_GPIO endmenu diff --git a/arch/arm/mach-nomadik/Makefile b/arch/arm/mach-nomadik/Makefile index 36f67fb..a6bbd1a 100644 --- a/arch/arm/mach-nomadik/Makefile +++ b/arch/arm/mach-nomadik/Makefile @@ -7,7 +7,7 @@ # Object file lists. -obj-y += clock.o gpio.o +obj-y += clock.o # Cpu revision obj-$(CONFIG_NOMADIK_8815) += cpu-8815.o diff --git a/arch/arm/mach-nomadik/gpio.c b/arch/arm/mach-nomadik/gpio.c deleted file mode 100644 index 9a09b27..0000000 --- a/arch/arm/mach-nomadik/gpio.c +++ /dev/null @@ -1,396 +0,0 @@ -/* - * Generic GPIO driver for logic cells found in the Nomadik SoC - * - * Copyright (C) 2008,2009 STMicroelectronics - * Copyright (C) 2009 Alessandro Rubini - * Rewritten based on work by Prafulla WADASKAR - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -/* - * The GPIO module in the Nomadik family of Systems-on-Chip is an - * AMBA device, managing 32 pins and alternate functions. The logic block - * is currently only used in the Nomadik. - * - * Symbols in this file are called "nmk_gpio" for "nomadik gpio" - */ - -#define NMK_GPIO_PER_CHIP 32 -struct nmk_gpio_chip { - struct gpio_chip chip; - void __iomem *addr; - unsigned int parent_irq; - spinlock_t *lock; - /* Keep track of configured edges */ - u32 edge_rising; - u32 edge_falling; -}; - -/* Mode functions */ -int nmk_gpio_set_mode(int gpio, int gpio_mode) -{ - struct nmk_gpio_chip *nmk_chip; - unsigned long flags; - u32 afunc, bfunc, bit; - - nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio)); - if (!nmk_chip) - return -EINVAL; - - bit = 1 << (gpio - nmk_chip->chip.base); - - spin_lock_irqsave(&nmk_chip->lock, flags); - afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & ~bit; - bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & ~bit; - if (gpio_mode & NMK_GPIO_ALT_A) - afunc |= bit; - if (gpio_mode & NMK_GPIO_ALT_B) - bfunc |= bit; - writel(afunc, nmk_chip->addr + NMK_GPIO_AFSLA); - writel(bfunc, nmk_chip->addr + NMK_GPIO_AFSLB); - spin_unlock_irqrestore(&nmk_chip->lock, flags); - - return 0; -} -EXPORT_SYMBOL(nmk_gpio_set_mode); - -int nmk_gpio_get_mode(int gpio) -{ - struct nmk_gpio_chip *nmk_chip; - u32 afunc, bfunc, bit; - - nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio)); - if (!nmk_chip) - return -EINVAL; - - bit = 1 << (gpio - nmk_chip->chip.base); - - afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & bit; - bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & bit; - - return (afunc ? NMK_GPIO_ALT_A : 0) | (bfunc ? NMK_GPIO_ALT_B : 0); -} -EXPORT_SYMBOL(nmk_gpio_get_mode); - - -/* IRQ functions */ -static inline int nmk_gpio_get_bitmask(int gpio) -{ - return 1 << (gpio % 32); -} - -static void nmk_gpio_irq_ack(unsigned int irq) -{ - int gpio; - struct nmk_gpio_chip *nmk_chip; - - gpio = NOMADIK_IRQ_TO_GPIO(irq); - nmk_chip = get_irq_chip_data(irq); - if (!nmk_chip) - return; - writel(nmk_gpio_get_bitmask(gpio), nmk_chip->addr + NMK_GPIO_IC); -} - -static void nmk_gpio_irq_mask(unsigned int irq) -{ - int gpio; - struct nmk_gpio_chip *nmk_chip; - unsigned long flags; - u32 bitmask, reg; - - gpio = NOMADIK_IRQ_TO_GPIO(irq); - nmk_chip = get_irq_chip_data(irq); - bitmask = nmk_gpio_get_bitmask(gpio); - if (!nmk_chip) - return; - - /* we must individually clear the two edges */ - spin_lock_irqsave(&nmk_chip->lock, flags); - if (nmk_chip->edge_rising & bitmask) { - reg = readl(nmk_chip->addr + NMK_GPIO_RWIMSC); - reg &= ~bitmask; - writel(reg, nmk_chip->addr + NMK_GPIO_RWIMSC); - } - if (nmk_chip->edge_falling & bitmask) { - reg = readl(nmk_chip->addr + NMK_GPIO_FWIMSC); - reg &= ~bitmask; - writel(reg, nmk_chip->addr + NMK_GPIO_FWIMSC); - } - spin_unlock_irqrestore(&nmk_chip->lock, flags); -}; - -static void nmk_gpio_irq_unmask(unsigned int irq) -{ - int gpio; - struct nmk_gpio_chip *nmk_chip; - unsigned long flags; - u32 bitmask, reg; - - gpio = NOMADIK_IRQ_TO_GPIO(irq); - nmk_chip = get_irq_chip_data(irq); - bitmask = nmk_gpio_get_bitmask(gpio); - if (!nmk_chip) - return; - - /* we must individually set the two edges */ - spin_lock_irqsave(&nmk_chip->lock, flags); - if (nmk_chip->edge_rising & bitmask) { - reg = readl(nmk_chip->addr + NMK_GPIO_RWIMSC); - reg |= bitmask; - writel(reg, nmk_chip->addr + NMK_GPIO_RWIMSC); - } - if (nmk_chip->edge_falling & bitmask) { - reg = readl(nmk_chip->addr + NMK_GPIO_FWIMSC); - reg |= bitmask; - writel(reg, nmk_chip->addr + NMK_GPIO_FWIMSC); - } - spin_unlock_irqrestore(&nmk_chip->lock, flags); -} - -static int nmk_gpio_irq_set_type(unsigned int irq, unsigned int type) -{ - int gpio; - struct nmk_gpio_chip *nmk_chip; - unsigned long flags; - u32 bitmask; - - gpio = NOMADIK_IRQ_TO_GPIO(irq); - nmk_chip = get_irq_chip_data(irq); - bitmask = nmk_gpio_get_bitmask(gpio); - if (!nmk_chip) - return -EINVAL; - - if (type & IRQ_TYPE_LEVEL_HIGH) - return -EINVAL; - if (type & IRQ_TYPE_LEVEL_LOW) - return -EINVAL; - - spin_lock_irqsave(&nmk_chip->lock, flags); - - nmk_chip->edge_rising &= ~bitmask; - if (type & IRQ_TYPE_EDGE_RISING) - nmk_chip->edge_rising |= bitmask; - writel(nmk_chip->edge_rising, nmk_chip->addr + NMK_GPIO_RIMSC); - - nmk_chip->edge_falling &= ~bitmask; - if (type & IRQ_TYPE_EDGE_FALLING) - nmk_chip->edge_falling |= bitmask; - writel(nmk_chip->edge_falling, nmk_chip->addr + NMK_GPIO_FIMSC); - - spin_unlock_irqrestore(&nmk_chip->lock, flags); - - nmk_gpio_irq_unmask(irq); - - return 0; -} - -static struct irq_chip nmk_gpio_irq_chip = { - .name = "Nomadik-GPIO", - .ack = nmk_gpio_irq_ack, - .mask = nmk_gpio_irq_mask, - .unmask = nmk_gpio_irq_unmask, - .set_type = nmk_gpio_irq_set_type, -}; - -static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) -{ - struct nmk_gpio_chip *nmk_chip; - struct irq_chip *host_chip; - unsigned int gpio_irq; - u32 pending; - unsigned int first_irq; - - nmk_chip = get_irq_data(irq); - first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base); - while ( (pending = readl(nmk_chip->addr + NMK_GPIO_IS)) ) { - gpio_irq = first_irq + __ffs(pending); - generic_handle_irq(gpio_irq); - } - if (0) {/* don't ack parent irq, as ack == disable */ - host_chip = get_irq_chip(irq); - host_chip->ack(irq); - } -} - -static int nmk_gpio_init_irq(struct nmk_gpio_chip *nmk_chip) -{ - unsigned int first_irq; - int i; - - first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base); - for (i = first_irq; i < first_irq + NMK_GPIO_PER_CHIP; i++) { - set_irq_chip(i, &nmk_gpio_irq_chip); - set_irq_handler(i, handle_edge_irq); - set_irq_flags(i, IRQF_VALID); - set_irq_chip_data(i, nmk_chip); - } - set_irq_chained_handler(nmk_chip->parent_irq, nmk_gpio_irq_handler); - set_irq_data(nmk_chip->parent_irq, nmk_chip); - return 0; -} - -/* I/O Functions */ -static int nmk_gpio_make_input(struct gpio_chip *chip, unsigned offset) -{ - struct nmk_gpio_chip *nmk_chip = - container_of(chip, struct nmk_gpio_chip, chip); - - writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC); - return 0; -} - -static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset, - int val) -{ - struct nmk_gpio_chip *nmk_chip = - container_of(chip, struct nmk_gpio_chip, chip); - - writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRS); - return 0; -} - -static int nmk_gpio_get_input(struct gpio_chip *chip, unsigned offset) -{ - struct nmk_gpio_chip *nmk_chip = - container_of(chip, struct nmk_gpio_chip, chip); - u32 bit = 1 << offset; - - return (readl(nmk_chip->addr + NMK_GPIO_DAT) & bit) != 0; -} - -static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned offset, - int val) -{ - struct nmk_gpio_chip *nmk_chip = - container_of(chip, struct nmk_gpio_chip, chip); - u32 bit = 1 << offset; - - if (val) - writel(bit, nmk_chip->addr + NMK_GPIO_DATS); - else - writel(bit, nmk_chip->addr + NMK_GPIO_DATC); -} - -/* This structure is replicated for each GPIO block allocated at probe time */ -static struct gpio_chip nmk_gpio_template = { - .direction_input = nmk_gpio_make_input, - .get = nmk_gpio_get_input, - .direction_output = nmk_gpio_make_output, - .set = nmk_gpio_set_output, - .ngpio = NMK_GPIO_PER_CHIP, - .can_sleep = 0, -}; - -static int __init nmk_gpio_probe(struct amba_device *dev, struct amba_id *id) -{ - struct nmk_gpio_platform_data *pdata; - struct nmk_gpio_chip *nmk_chip; - struct gpio_chip *chip; - int ret; - - pdata = dev->dev.platform_data; - ret = amba_request_regions(dev, pdata->name); - if (ret) - return ret; - - nmk_chip = kzalloc(sizeof(*nmk_chip), GFP_KERNEL); - if (!nmk_chip) { - ret = -ENOMEM; - goto out_amba; - } - /* - * The virt address in nmk_chip->addr is in the nomadik register space, - * so we can simply convert the resource address, without remapping - */ - nmk_chip->addr = io_p2v(dev->res.start); - nmk_chip->chip = nmk_gpio_template; - nmk_chip->parent_irq = pdata->parent_irq; - - chip = &nmk_chip->chip; - chip->base = pdata->first_gpio; - chip->label = pdata->name; - chip->dev = &dev->dev; - chip->owner = THIS_MODULE; - - ret = gpiochip_add(&nmk_chip->chip); - if (ret) - goto out_free; - - amba_set_drvdata(dev, nmk_chip); - - nmk_gpio_init_irq(nmk_chip); - - dev_info(&dev->dev, "Bits %i-%i at address %p\n", - nmk_chip->chip.base, nmk_chip->chip.base+31, nmk_chip->addr); - return 0; - - out_free: - kfree(nmk_chip); - out_amba: - amba_release_regions(dev); - dev_err(&dev->dev, "Failure %i for GPIO %i-%i\n", ret, - pdata->first_gpio, pdata->first_gpio+31); - return ret; -} - -static int nmk_gpio_remove(struct amba_device *dev) -{ - struct nmk_gpio_chip *nmk_chip; - - nmk_chip = amba_get_drvdata(dev); - gpiochip_remove(&nmk_chip->chip); - kfree(nmk_chip); - amba_release_regions(dev); - return 0; -} - - -/* We have 0x1f080060 and 0x1f180060, accept both using the mask */ -static struct amba_id nmk_gpio_ids[] = { - { - .id = 0x1f080060, - .mask = 0xffefffff, - }, - {0, 0}, -}; - -static struct amba_driver nmk_gpio_driver = { - .drv = { - .owner = THIS_MODULE, - .name = "gpio", - }, - .probe = nmk_gpio_probe, - .remove = nmk_gpio_remove, - .suspend = NULL, /* to be done */ - .resume = NULL, - .id_table = nmk_gpio_ids, -}; - -static int __init nmk_gpio_init(void) -{ - return amba_driver_register(&nmk_gpio_driver); -} - -arch_initcall(nmk_gpio_init); - -MODULE_AUTHOR("Prafulla WADASKAR and Alessandro Rubini"); -MODULE_DESCRIPTION("Nomadik GPIO Driver"); -MODULE_LICENSE("GPL"); - - diff --git a/arch/arm/mach-nomadik/include/mach/gpio.h b/arch/arm/mach-nomadik/include/mach/gpio.h index 61577c9..7a81a04 100644 --- a/arch/arm/mach-nomadik/include/mach/gpio.h +++ b/arch/arm/mach-nomadik/include/mach/gpio.h @@ -1,71 +1,6 @@ -/* - * Structures and registers for GPIO access in the Nomadik SoC - * - * Copyright (C) 2008 STMicroelectronics - * Author: Prafulla WADASKAR - * Copyright (C) 2009 Alessandro Rubini - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ #ifndef __ASM_ARCH_GPIO_H #define __ASM_ARCH_GPIO_H -#include - -/* - * These currently cause a function call to happen, they may be optimized - * if needed by adding cpu-specific defines to identify blocks - * (see mach-pxa/include/mach/gpio.h as an example using GPLR etc) - */ -#define gpio_get_value __gpio_get_value -#define gpio_set_value __gpio_set_value -#define gpio_cansleep __gpio_cansleep -#define gpio_to_irq __gpio_to_irq - -/* - * "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving - * the "gpio" namespace for generic and cross-machine functions - */ - -/* Register in the logic block */ -#define NMK_GPIO_DAT 0x00 -#define NMK_GPIO_DATS 0x04 -#define NMK_GPIO_DATC 0x08 -#define NMK_GPIO_PDIS 0x0c -#define NMK_GPIO_DIR 0x10 -#define NMK_GPIO_DIRS 0x14 -#define NMK_GPIO_DIRC 0x18 -#define NMK_GPIO_SLPC 0x1c -#define NMK_GPIO_AFSLA 0x20 -#define NMK_GPIO_AFSLB 0x24 - -#define NMK_GPIO_RIMSC 0x40 -#define NMK_GPIO_FIMSC 0x44 -#define NMK_GPIO_IS 0x48 -#define NMK_GPIO_IC 0x4c -#define NMK_GPIO_RWIMSC 0x50 -#define NMK_GPIO_FWIMSC 0x54 -#define NMK_GPIO_WKS 0x58 - -/* Alternate functions: function C is set in hw by setting both A and B */ -#define NMK_GPIO_ALT_GPIO 0 -#define NMK_GPIO_ALT_A 1 -#define NMK_GPIO_ALT_B 2 -#define NMK_GPIO_ALT_C (NMK_GPIO_ALT_A | NMK_GPIO_ALT_B) - -extern int nmk_gpio_set_mode(int gpio, int gpio_mode); -extern int nmk_gpio_get_mode(int gpio); - -/* - * Platform data to register a block: only the initial gpio/irq number. - */ -struct nmk_gpio_platform_data { - char *name; - int first_gpio; - int first_irq; - int parent_irq; -}; +#include #endif /* __ASM_ARCH_GPIO_H */ diff --git a/arch/arm/plat-nomadik/Kconfig b/arch/arm/plat-nomadik/Kconfig index 159daf5..5da3f97 100644 --- a/arch/arm/plat-nomadik/Kconfig +++ b/arch/arm/plat-nomadik/Kconfig @@ -19,4 +19,9 @@ config HAS_MTU to multiple interrupt generating programmable 32-bit free running decrementing counters. +config NOMADIK_GPIO + bool + help + Support for the Nomadik GPIO controller. + endif diff --git a/arch/arm/plat-nomadik/Makefile b/arch/arm/plat-nomadik/Makefile index 37c7cdd..c335473 100644 --- a/arch/arm/plat-nomadik/Makefile +++ b/arch/arm/plat-nomadik/Makefile @@ -3,3 +3,4 @@ # Licensed under GPLv2 obj-$(CONFIG_HAS_MTU) += timer.o +obj-$(CONFIG_NOMADIK_GPIO) += gpio.o diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c new file mode 100644 index 0000000..9a09b27 --- /dev/null +++ b/arch/arm/plat-nomadik/gpio.c @@ -0,0 +1,396 @@ +/* + * Generic GPIO driver for logic cells found in the Nomadik SoC + * + * Copyright (C) 2008,2009 STMicroelectronics + * Copyright (C) 2009 Alessandro Rubini + * Rewritten based on work by Prafulla WADASKAR + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* + * The GPIO module in the Nomadik family of Systems-on-Chip is an + * AMBA device, managing 32 pins and alternate functions. The logic block + * is currently only used in the Nomadik. + * + * Symbols in this file are called "nmk_gpio" for "nomadik gpio" + */ + +#define NMK_GPIO_PER_CHIP 32 +struct nmk_gpio_chip { + struct gpio_chip chip; + void __iomem *addr; + unsigned int parent_irq; + spinlock_t *lock; + /* Keep track of configured edges */ + u32 edge_rising; + u32 edge_falling; +}; + +/* Mode functions */ +int nmk_gpio_set_mode(int gpio, int gpio_mode) +{ + struct nmk_gpio_chip *nmk_chip; + unsigned long flags; + u32 afunc, bfunc, bit; + + nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio)); + if (!nmk_chip) + return -EINVAL; + + bit = 1 << (gpio - nmk_chip->chip.base); + + spin_lock_irqsave(&nmk_chip->lock, flags); + afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & ~bit; + bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & ~bit; + if (gpio_mode & NMK_GPIO_ALT_A) + afunc |= bit; + if (gpio_mode & NMK_GPIO_ALT_B) + bfunc |= bit; + writel(afunc, nmk_chip->addr + NMK_GPIO_AFSLA); + writel(bfunc, nmk_chip->addr + NMK_GPIO_AFSLB); + spin_unlock_irqrestore(&nmk_chip->lock, flags); + + return 0; +} +EXPORT_SYMBOL(nmk_gpio_set_mode); + +int nmk_gpio_get_mode(int gpio) +{ + struct nmk_gpio_chip *nmk_chip; + u32 afunc, bfunc, bit; + + nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio)); + if (!nmk_chip) + return -EINVAL; + + bit = 1 << (gpio - nmk_chip->chip.base); + + afunc = readl(nmk_chip->addr + NMK_GPIO_AFSLA) & bit; + bfunc = readl(nmk_chip->addr + NMK_GPIO_AFSLB) & bit; + + return (afunc ? NMK_GPIO_ALT_A : 0) | (bfunc ? NMK_GPIO_ALT_B : 0); +} +EXPORT_SYMBOL(nmk_gpio_get_mode); + + +/* IRQ functions */ +static inline int nmk_gpio_get_bitmask(int gpio) +{ + return 1 << (gpio % 32); +} + +static void nmk_gpio_irq_ack(unsigned int irq) +{ + int gpio; + struct nmk_gpio_chip *nmk_chip; + + gpio = NOMADIK_IRQ_TO_GPIO(irq); + nmk_chip = get_irq_chip_data(irq); + if (!nmk_chip) + return; + writel(nmk_gpio_get_bitmask(gpio), nmk_chip->addr + NMK_GPIO_IC); +} + +static void nmk_gpio_irq_mask(unsigned int irq) +{ + int gpio; + struct nmk_gpio_chip *nmk_chip; + unsigned long flags; + u32 bitmask, reg; + + gpio = NOMADIK_IRQ_TO_GPIO(irq); + nmk_chip = get_irq_chip_data(irq); + bitmask = nmk_gpio_get_bitmask(gpio); + if (!nmk_chip) + return; + + /* we must individually clear the two edges */ + spin_lock_irqsave(&nmk_chip->lock, flags); + if (nmk_chip->edge_rising & bitmask) { + reg = readl(nmk_chip->addr + NMK_GPIO_RWIMSC); + reg &= ~bitmask; + writel(reg, nmk_chip->addr + NMK_GPIO_RWIMSC); + } + if (nmk_chip->edge_falling & bitmask) { + reg = readl(nmk_chip->addr + NMK_GPIO_FWIMSC); + reg &= ~bitmask; + writel(reg, nmk_chip->addr + NMK_GPIO_FWIMSC); + } + spin_unlock_irqrestore(&nmk_chip->lock, flags); +}; + +static void nmk_gpio_irq_unmask(unsigned int irq) +{ + int gpio; + struct nmk_gpio_chip *nmk_chip; + unsigned long flags; + u32 bitmask, reg; + + gpio = NOMADIK_IRQ_TO_GPIO(irq); + nmk_chip = get_irq_chip_data(irq); + bitmask = nmk_gpio_get_bitmask(gpio); + if (!nmk_chip) + return; + + /* we must individually set the two edges */ + spin_lock_irqsave(&nmk_chip->lock, flags); + if (nmk_chip->edge_rising & bitmask) { + reg = readl(nmk_chip->addr + NMK_GPIO_RWIMSC); + reg |= bitmask; + writel(reg, nmk_chip->addr + NMK_GPIO_RWIMSC); + } + if (nmk_chip->edge_falling & bitmask) { + reg = readl(nmk_chip->addr + NMK_GPIO_FWIMSC); + reg |= bitmask; + writel(reg, nmk_chip->addr + NMK_GPIO_FWIMSC); + } + spin_unlock_irqrestore(&nmk_chip->lock, flags); +} + +static int nmk_gpio_irq_set_type(unsigned int irq, unsigned int type) +{ + int gpio; + struct nmk_gpio_chip *nmk_chip; + unsigned long flags; + u32 bitmask; + + gpio = NOMADIK_IRQ_TO_GPIO(irq); + nmk_chip = get_irq_chip_data(irq); + bitmask = nmk_gpio_get_bitmask(gpio); + if (!nmk_chip) + return -EINVAL; + + if (type & IRQ_TYPE_LEVEL_HIGH) + return -EINVAL; + if (type & IRQ_TYPE_LEVEL_LOW) + return -EINVAL; + + spin_lock_irqsave(&nmk_chip->lock, flags); + + nmk_chip->edge_rising &= ~bitmask; + if (type & IRQ_TYPE_EDGE_RISING) + nmk_chip->edge_rising |= bitmask; + writel(nmk_chip->edge_rising, nmk_chip->addr + NMK_GPIO_RIMSC); + + nmk_chip->edge_falling &= ~bitmask; + if (type & IRQ_TYPE_EDGE_FALLING) + nmk_chip->edge_falling |= bitmask; + writel(nmk_chip->edge_falling, nmk_chip->addr + NMK_GPIO_FIMSC); + + spin_unlock_irqrestore(&nmk_chip->lock, flags); + + nmk_gpio_irq_unmask(irq); + + return 0; +} + +static struct irq_chip nmk_gpio_irq_chip = { + .name = "Nomadik-GPIO", + .ack = nmk_gpio_irq_ack, + .mask = nmk_gpio_irq_mask, + .unmask = nmk_gpio_irq_unmask, + .set_type = nmk_gpio_irq_set_type, +}; + +static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) +{ + struct nmk_gpio_chip *nmk_chip; + struct irq_chip *host_chip; + unsigned int gpio_irq; + u32 pending; + unsigned int first_irq; + + nmk_chip = get_irq_data(irq); + first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base); + while ( (pending = readl(nmk_chip->addr + NMK_GPIO_IS)) ) { + gpio_irq = first_irq + __ffs(pending); + generic_handle_irq(gpio_irq); + } + if (0) {/* don't ack parent irq, as ack == disable */ + host_chip = get_irq_chip(irq); + host_chip->ack(irq); + } +} + +static int nmk_gpio_init_irq(struct nmk_gpio_chip *nmk_chip) +{ + unsigned int first_irq; + int i; + + first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base); + for (i = first_irq; i < first_irq + NMK_GPIO_PER_CHIP; i++) { + set_irq_chip(i, &nmk_gpio_irq_chip); + set_irq_handler(i, handle_edge_irq); + set_irq_flags(i, IRQF_VALID); + set_irq_chip_data(i, nmk_chip); + } + set_irq_chained_handler(nmk_chip->parent_irq, nmk_gpio_irq_handler); + set_irq_data(nmk_chip->parent_irq, nmk_chip); + return 0; +} + +/* I/O Functions */ +static int nmk_gpio_make_input(struct gpio_chip *chip, unsigned offset) +{ + struct nmk_gpio_chip *nmk_chip = + container_of(chip, struct nmk_gpio_chip, chip); + + writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRC); + return 0; +} + +static int nmk_gpio_make_output(struct gpio_chip *chip, unsigned offset, + int val) +{ + struct nmk_gpio_chip *nmk_chip = + container_of(chip, struct nmk_gpio_chip, chip); + + writel(1 << offset, nmk_chip->addr + NMK_GPIO_DIRS); + return 0; +} + +static int nmk_gpio_get_input(struct gpio_chip *chip, unsigned offset) +{ + struct nmk_gpio_chip *nmk_chip = + container_of(chip, struct nmk_gpio_chip, chip); + u32 bit = 1 << offset; + + return (readl(nmk_chip->addr + NMK_GPIO_DAT) & bit) != 0; +} + +static void nmk_gpio_set_output(struct gpio_chip *chip, unsigned offset, + int val) +{ + struct nmk_gpio_chip *nmk_chip = + container_of(chip, struct nmk_gpio_chip, chip); + u32 bit = 1 << offset; + + if (val) + writel(bit, nmk_chip->addr + NMK_GPIO_DATS); + else + writel(bit, nmk_chip->addr + NMK_GPIO_DATC); +} + +/* This structure is replicated for each GPIO block allocated at probe time */ +static struct gpio_chip nmk_gpio_template = { + .direction_input = nmk_gpio_make_input, + .get = nmk_gpio_get_input, + .direction_output = nmk_gpio_make_output, + .set = nmk_gpio_set_output, + .ngpio = NMK_GPIO_PER_CHIP, + .can_sleep = 0, +}; + +static int __init nmk_gpio_probe(struct amba_device *dev, struct amba_id *id) +{ + struct nmk_gpio_platform_data *pdata; + struct nmk_gpio_chip *nmk_chip; + struct gpio_chip *chip; + int ret; + + pdata = dev->dev.platform_data; + ret = amba_request_regions(dev, pdata->name); + if (ret) + return ret; + + nmk_chip = kzalloc(sizeof(*nmk_chip), GFP_KERNEL); + if (!nmk_chip) { + ret = -ENOMEM; + goto out_amba; + } + /* + * The virt address in nmk_chip->addr is in the nomadik register space, + * so we can simply convert the resource address, without remapping + */ + nmk_chip->addr = io_p2v(dev->res.start); + nmk_chip->chip = nmk_gpio_template; + nmk_chip->parent_irq = pdata->parent_irq; + + chip = &nmk_chip->chip; + chip->base = pdata->first_gpio; + chip->label = pdata->name; + chip->dev = &dev->dev; + chip->owner = THIS_MODULE; + + ret = gpiochip_add(&nmk_chip->chip); + if (ret) + goto out_free; + + amba_set_drvdata(dev, nmk_chip); + + nmk_gpio_init_irq(nmk_chip); + + dev_info(&dev->dev, "Bits %i-%i at address %p\n", + nmk_chip->chip.base, nmk_chip->chip.base+31, nmk_chip->addr); + return 0; + + out_free: + kfree(nmk_chip); + out_amba: + amba_release_regions(dev); + dev_err(&dev->dev, "Failure %i for GPIO %i-%i\n", ret, + pdata->first_gpio, pdata->first_gpio+31); + return ret; +} + +static int nmk_gpio_remove(struct amba_device *dev) +{ + struct nmk_gpio_chip *nmk_chip; + + nmk_chip = amba_get_drvdata(dev); + gpiochip_remove(&nmk_chip->chip); + kfree(nmk_chip); + amba_release_regions(dev); + return 0; +} + + +/* We have 0x1f080060 and 0x1f180060, accept both using the mask */ +static struct amba_id nmk_gpio_ids[] = { + { + .id = 0x1f080060, + .mask = 0xffefffff, + }, + {0, 0}, +}; + +static struct amba_driver nmk_gpio_driver = { + .drv = { + .owner = THIS_MODULE, + .name = "gpio", + }, + .probe = nmk_gpio_probe, + .remove = nmk_gpio_remove, + .suspend = NULL, /* to be done */ + .resume = NULL, + .id_table = nmk_gpio_ids, +}; + +static int __init nmk_gpio_init(void) +{ + return amba_driver_register(&nmk_gpio_driver); +} + +arch_initcall(nmk_gpio_init); + +MODULE_AUTHOR("Prafulla WADASKAR and Alessandro Rubini"); +MODULE_DESCRIPTION("Nomadik GPIO Driver"); +MODULE_LICENSE("GPL"); + + diff --git a/arch/arm/plat-nomadik/include/plat/gpio.h b/arch/arm/plat-nomadik/include/plat/gpio.h new file mode 100644 index 0000000..1d665a0a --- /dev/null +++ b/arch/arm/plat-nomadik/include/plat/gpio.h @@ -0,0 +1,71 @@ +/* + * Structures and registers for GPIO access in the Nomadik SoC + * + * Copyright (C) 2008 STMicroelectronics + * Author: Prafulla WADASKAR + * Copyright (C) 2009 Alessandro Rubini + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef __ASM_PLAT_GPIO_H +#define __ASM_PLAT_GPIO_H + +#include + +/* + * These currently cause a function call to happen, they may be optimized + * if needed by adding cpu-specific defines to identify blocks + * (see mach-pxa/include/mach/gpio.h as an example using GPLR etc) + */ +#define gpio_get_value __gpio_get_value +#define gpio_set_value __gpio_set_value +#define gpio_cansleep __gpio_cansleep +#define gpio_to_irq __gpio_to_irq + +/* + * "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving + * the "gpio" namespace for generic and cross-machine functions + */ + +/* Register in the logic block */ +#define NMK_GPIO_DAT 0x00 +#define NMK_GPIO_DATS 0x04 +#define NMK_GPIO_DATC 0x08 +#define NMK_GPIO_PDIS 0x0c +#define NMK_GPIO_DIR 0x10 +#define NMK_GPIO_DIRS 0x14 +#define NMK_GPIO_DIRC 0x18 +#define NMK_GPIO_SLPC 0x1c +#define NMK_GPIO_AFSLA 0x20 +#define NMK_GPIO_AFSLB 0x24 + +#define NMK_GPIO_RIMSC 0x40 +#define NMK_GPIO_FIMSC 0x44 +#define NMK_GPIO_IS 0x48 +#define NMK_GPIO_IC 0x4c +#define NMK_GPIO_RWIMSC 0x50 +#define NMK_GPIO_FWIMSC 0x54 +#define NMK_GPIO_WKS 0x58 + +/* Alternate functions: function C is set in hw by setting both A and B */ +#define NMK_GPIO_ALT_GPIO 0 +#define NMK_GPIO_ALT_A 1 +#define NMK_GPIO_ALT_B 2 +#define NMK_GPIO_ALT_C (NMK_GPIO_ALT_A | NMK_GPIO_ALT_B) + +extern int nmk_gpio_set_mode(int gpio, int gpio_mode); +extern int nmk_gpio_get_mode(int gpio); + +/* + * Platform data to register a block: only the initial gpio/irq number. + */ +struct nmk_gpio_platform_data { + char *name; + int first_gpio; + int first_irq; + int parent_irq; +}; + +#endif /* __ASM_PLAT_GPIO_H */ -- cgit v0.10.2 From c0fcb8dba829421fe20652a376a2bedaf168238f Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Wed, 3 Mar 2010 04:48:54 +0100 Subject: ARM: 5970/1: nomadik-gpio: fix spinlock usage Fix the incorrect spinlock usage which leads to these compiler warnings: arch/arm/plat-nomadik/gpio.c:60: warning: passing argument 1 of `spinlock_check' from incompatible pointer type arch/arm/plat-nomadik/gpio.c:69: warning: passing argument 1 of `spin_unlock_irqrestore' from incompatible pointer type Acked-by: Alessandro Rubini Acked-by: Linus Walleij Signed-off-by: Rabin Vincent Signed-off-by: Russell King diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c index 9a09b27..a9ee988 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c @@ -36,7 +36,7 @@ struct nmk_gpio_chip { struct gpio_chip chip; void __iomem *addr; unsigned int parent_irq; - spinlock_t *lock; + spinlock_t lock; /* Keep track of configured edges */ u32 edge_rising; u32 edge_falling; @@ -321,6 +321,7 @@ static int __init nmk_gpio_probe(struct amba_device *dev, struct amba_id *id) nmk_chip->addr = io_p2v(dev->res.start); nmk_chip->chip = nmk_gpio_template; nmk_chip->parent_irq = pdata->parent_irq; + spin_lock_init(&nmk_chip->lock); chip = &nmk_chip->chip; chip->base = pdata->first_gpio; -- cgit v0.10.2 From aaedaa2b5c610ae97f863078075d8d3c6ef91575 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Wed, 3 Mar 2010 04:50:27 +0100 Subject: ARM: 5971/1: nomadik-gpio: mask/ack/unmask the parent irq Since we register as a chained handler, we need to take care of acking the parent irq. Current code had the acking disabled because just acking the interrupt disables it on some interrupt controllers (like the VIC used on Nomadik). However, not acking at all is incorrect because interrupt controllers like the GIC need an EOI indication, which is done in the ack routine. Solve this by maskacking and unmasking it appropriately, similar to how handle_level_irq operates. Acked-by: Alessandro Rubini Acked-by: Linus Walleij Signed-off-by: Rabin Vincent Signed-off-by: Russell King diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c index a9ee988..4c3ea1a 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c @@ -211,21 +211,27 @@ static struct irq_chip nmk_gpio_irq_chip = { static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) { struct nmk_gpio_chip *nmk_chip; - struct irq_chip *host_chip; + struct irq_chip *host_chip = get_irq_chip(irq); unsigned int gpio_irq; u32 pending; unsigned int first_irq; + if (host_chip->mask_ack) + host_chip->mask_ack(irq); + else { + host_chip->mask(irq); + if (host_chip->ack) + host_chip->ack(irq); + } + nmk_chip = get_irq_data(irq); first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base); while ( (pending = readl(nmk_chip->addr + NMK_GPIO_IS)) ) { gpio_irq = first_irq + __ffs(pending); generic_handle_irq(gpio_irq); } - if (0) {/* don't ack parent irq, as ack == disable */ - host_chip = get_irq_chip(irq); - host_chip->ack(irq); - } + + host_chip->unmask(irq); } static int nmk_gpio_init_irq(struct nmk_gpio_chip *nmk_chip) -- cgit v0.10.2 From 3e3c62ca5395df48319b808379bc9fd487ff3c29 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Wed, 3 Mar 2010 04:52:34 +0100 Subject: ARM: 5972/1: nomadik-gpio: convert to platform driver On the U8500 platform there are four GPIO blocks, each with a 4K address space, including the peripheral identification. However, each of these blocks have a varying number of banks, each of which have 32 GPIOs and an interrupt line. The current nomadik-gpio driver implementation can handle each of these sub-banks easily with one instance each, but cannot as-is be hooked up to them because it is an AMBA driver and it expects to see a peripheral with the appropriate peripheral ids but having only one bank and only one interrupt. Solve this by converting the driver to a platform driver. Acked-by: Alessandro Rubini Acked-by: Linus Walleij Signed-off-by: Rabin Vincent Signed-off-by: Russell King diff --git a/arch/arm/mach-nomadik/cpu-8815.c b/arch/arm/mach-nomadik/cpu-8815.c index 9bf33b3..91c3c90 100644 --- a/arch/arm/mach-nomadik/cpu-8815.c +++ b/arch/arm/mach-nomadik/cpu-8815.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -30,60 +31,66 @@ #include #include +#define __MEM_4K_RESOURCE(x) \ + .res = {.start = (x), .end = (x) + SZ_4K - 1, .flags = IORESOURCE_MEM} + /* The 8815 has 4 GPIO blocks, let's register them immediately */ + +#define GPIO_RESOURCE(block) \ + { \ + .start = NOMADIK_GPIO##block##_BASE, \ + .end = NOMADIK_GPIO##block##_BASE + SZ_4K - 1, \ + .flags = IORESOURCE_MEM, \ + }, \ + { \ + .start = IRQ_GPIO##block, \ + .end = IRQ_GPIO##block, \ + .flags = IORESOURCE_IRQ, \ + } + +#define GPIO_DEVICE(block) \ + { \ + .name = "gpio", \ + .id = block, \ + .num_resources = 2, \ + .resource = &cpu8815_gpio_resources[block * 2], \ + .dev = { \ + .platform_data = &cpu8815_gpio[block], \ + }, \ + } + static struct nmk_gpio_platform_data cpu8815_gpio[] = { { .name = "GPIO-0-31", .first_gpio = 0, .first_irq = NOMADIK_GPIO_TO_IRQ(0), - .parent_irq = IRQ_GPIO0, }, { .name = "GPIO-32-63", .first_gpio = 32, .first_irq = NOMADIK_GPIO_TO_IRQ(32), - .parent_irq = IRQ_GPIO1, }, { .name = "GPIO-64-95", .first_gpio = 64, .first_irq = NOMADIK_GPIO_TO_IRQ(64), - .parent_irq = IRQ_GPIO2, }, { .name = "GPIO-96-127", /* 124..127 not routed to pin */ .first_gpio = 96, .first_irq = NOMADIK_GPIO_TO_IRQ(96), - .parent_irq = IRQ_GPIO3, } }; -#define __MEM_4K_RESOURCE(x) \ - .res = {.start = (x), .end = (x) + SZ_4K - 1, .flags = IORESOURCE_MEM} +static struct resource cpu8815_gpio_resources[] = { + GPIO_RESOURCE(0), + GPIO_RESOURCE(1), + GPIO_RESOURCE(2), + GPIO_RESOURCE(3), +}; -static struct amba_device cpu8815_amba_gpio[] = { - { - .dev = { - .init_name = "gpio0", - .platform_data = cpu8815_gpio + 0, - }, - __MEM_4K_RESOURCE(NOMADIK_GPIO0_BASE), - }, { - .dev = { - .init_name = "gpio1", - .platform_data = cpu8815_gpio + 1, - }, - __MEM_4K_RESOURCE(NOMADIK_GPIO1_BASE), - }, { - .dev = { - .init_name = "gpio2", - .platform_data = cpu8815_gpio + 2, - }, - __MEM_4K_RESOURCE(NOMADIK_GPIO2_BASE), - }, { - .dev = { - .init_name = "gpio3", - .platform_data = cpu8815_gpio + 3, - }, - __MEM_4K_RESOURCE(NOMADIK_GPIO3_BASE), - }, +static struct platform_device cpu8815_platform_gpio[] = { + GPIO_DEVICE(0), + GPIO_DEVICE(1), + GPIO_DEVICE(2), + GPIO_DEVICE(3), }; static struct amba_device cpu8815_amba_rng = { @@ -93,11 +100,14 @@ static struct amba_device cpu8815_amba_rng = { __MEM_4K_RESOURCE(NOMADIK_RNG_BASE), }; +static struct platform_device *platform_devs[] __initdata = { + cpu8815_platform_gpio + 0, + cpu8815_platform_gpio + 1, + cpu8815_platform_gpio + 2, + cpu8815_platform_gpio + 3, +}; + static struct amba_device *amba_devs[] __initdata = { - cpu8815_amba_gpio + 0, - cpu8815_amba_gpio + 1, - cpu8815_amba_gpio + 2, - cpu8815_amba_gpio + 3, &cpu8815_amba_rng }; @@ -105,6 +115,7 @@ static int __init cpu8815_init(void) { int i; + platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); for (i = 0; i < ARRAY_SIZE(amba_devs); i++) amba_device_register(amba_devs[i], &iomem_resource); return 0; diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c index 4c3ea1a..092f380 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include @@ -303,30 +303,48 @@ static struct gpio_chip nmk_gpio_template = { .can_sleep = 0, }; -static int __init nmk_gpio_probe(struct amba_device *dev, struct amba_id *id) +static int __init nmk_gpio_probe(struct platform_device *dev) { - struct nmk_gpio_platform_data *pdata; + struct nmk_gpio_platform_data *pdata = dev->dev.platform_data; struct nmk_gpio_chip *nmk_chip; struct gpio_chip *chip; + struct resource *res; + int irq; int ret; - pdata = dev->dev.platform_data; - ret = amba_request_regions(dev, pdata->name); - if (ret) - return ret; + if (!pdata) + return -ENODEV; + + res = platform_get_resource(dev, IORESOURCE_MEM, 0); + if (!res) { + ret = -ENOENT; + goto out; + } + + irq = platform_get_irq(dev, 0); + if (irq < 0) { + ret = irq; + goto out; + } + + if (request_mem_region(res->start, resource_size(res), + dev_name(&dev->dev)) == NULL) { + ret = -EBUSY; + goto out; + } nmk_chip = kzalloc(sizeof(*nmk_chip), GFP_KERNEL); if (!nmk_chip) { ret = -ENOMEM; - goto out_amba; + goto out_release; } /* * The virt address in nmk_chip->addr is in the nomadik register space, * so we can simply convert the resource address, without remapping */ - nmk_chip->addr = io_p2v(dev->res.start); + nmk_chip->addr = io_p2v(res->start); nmk_chip->chip = nmk_gpio_template; - nmk_chip->parent_irq = pdata->parent_irq; + nmk_chip->parent_irq = irq; spin_lock_init(&nmk_chip->lock); chip = &nmk_chip->chip; @@ -339,7 +357,7 @@ static int __init nmk_gpio_probe(struct amba_device *dev, struct amba_id *id) if (ret) goto out_free; - amba_set_drvdata(dev, nmk_chip); + platform_set_drvdata(dev, nmk_chip); nmk_gpio_init_irq(nmk_chip); @@ -347,51 +365,45 @@ static int __init nmk_gpio_probe(struct amba_device *dev, struct amba_id *id) nmk_chip->chip.base, nmk_chip->chip.base+31, nmk_chip->addr); return 0; - out_free: +out_free: kfree(nmk_chip); - out_amba: - amba_release_regions(dev); +out_release: + release_mem_region(res->start, resource_size(res)); +out: dev_err(&dev->dev, "Failure %i for GPIO %i-%i\n", ret, pdata->first_gpio, pdata->first_gpio+31); return ret; } -static int nmk_gpio_remove(struct amba_device *dev) +static int __exit nmk_gpio_remove(struct platform_device *dev) { struct nmk_gpio_chip *nmk_chip; + struct resource *res; + + res = platform_get_resource(dev, IORESOURCE_MEM, 0); - nmk_chip = amba_get_drvdata(dev); + nmk_chip = platform_get_drvdata(dev); gpiochip_remove(&nmk_chip->chip); kfree(nmk_chip); - amba_release_regions(dev); + release_mem_region(res->start, resource_size(res)); return 0; } -/* We have 0x1f080060 and 0x1f180060, accept both using the mask */ -static struct amba_id nmk_gpio_ids[] = { - { - .id = 0x1f080060, - .mask = 0xffefffff, - }, - {0, 0}, -}; - -static struct amba_driver nmk_gpio_driver = { - .drv = { +static struct platform_driver nmk_gpio_driver = { + .driver = { .owner = THIS_MODULE, .name = "gpio", }, .probe = nmk_gpio_probe, - .remove = nmk_gpio_remove, + .remove = __exit_p(nmk_gpio_remove), .suspend = NULL, /* to be done */ .resume = NULL, - .id_table = nmk_gpio_ids, }; static int __init nmk_gpio_init(void) { - return amba_driver_register(&nmk_gpio_driver); + return platform_driver_register(&nmk_gpio_driver); } arch_initcall(nmk_gpio_init); diff --git a/arch/arm/plat-nomadik/include/plat/gpio.h b/arch/arm/plat-nomadik/include/plat/gpio.h index 1d665a0a..4200811 100644 --- a/arch/arm/plat-nomadik/include/plat/gpio.h +++ b/arch/arm/plat-nomadik/include/plat/gpio.h @@ -65,7 +65,6 @@ struct nmk_gpio_platform_data { char *name; int first_gpio; int first_irq; - int parent_irq; }; #endif /* __ASM_PLAT_GPIO_H */ -- cgit v0.10.2 From cc2c13342508d52cf08ea81f639b5de69607fd5d Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Mon, 1 Mar 2010 05:03:31 +0100 Subject: ARM: 5962/1: ux500: move system timer to cpu file There is nothing board-specific about the system timer, so move it to the CPU file. Acked-by: Linus Walleij Acked-by: Srinidhi Kasagar Signed-off-by: Rabin Vincent Signed-off-by: Russell King diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 803aec1..c2b4a35 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -17,11 +17,9 @@ #include #include -#include #include #include -#include #include #include @@ -201,22 +199,6 @@ static struct platform_device *platform_devs[] __initdata = { &i2c_controller3, }; -static void __init u8500_timer_init(void) -{ -#ifdef CONFIG_LOCAL_TIMERS - /* Setup the local timer base */ - twd_base = __io_address(U8500_TWD_BASE); -#endif - /* Setup the MTU base */ - mtu_base = __io_address(U8500_MTU0_BASE); - - nmdk_timer_init(); -} - -static struct sys_timer u8500_timer = { - .init = u8500_timer_init, -}; - static void __init u8500_init_machine(void) { int i; diff --git a/arch/arm/mach-ux500/cpu-u8500.c b/arch/arm/mach-ux500/cpu-u8500.c index 397bc1f..588b059 100644 --- a/arch/arm/mach-ux500/cpu-u8500.c +++ b/arch/arm/mach-ux500/cpu-u8500.c @@ -14,10 +14,14 @@ #include #include #include +#include +#include #include #include +#include #include +#include /* add any platform devices here - TODO */ static struct platform_device *platform_devs[] __initdata = { @@ -63,3 +67,19 @@ void __init u8500_init_devices(void) return ; } + +static void __init u8500_timer_init(void) +{ +#ifdef CONFIG_LOCAL_TIMERS + /* Setup the local timer base */ + twd_base = __io_address(U8500_TWD_BASE); +#endif + /* Setup the MTU base */ + mtu_base = __io_address(U8500_MTU0_BASE); + + nmdk_timer_init(); +} + +struct sys_timer u8500_timer = { + .init = u8500_timer_init, +}; diff --git a/arch/arm/mach-ux500/include/mach/setup.h b/arch/arm/mach-ux500/include/mach/setup.h index cf0ce16..65112bf 100644 --- a/arch/arm/mach-ux500/include/mach/setup.h +++ b/arch/arm/mach-ux500/include/mach/setup.h @@ -20,4 +20,7 @@ extern void u8500_init_irq(void); /* We re-use nomadik_timer for this platform */ extern void nmdk_timer_init(void); +struct sys_timer; +extern struct sys_timer u8500_timer; + #endif /* __ASM_ARCH_SETUP_H */ -- cgit v0.10.2 From 75a36ee01e860be693220f1c40e2c04fb6cc69ba Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Mon, 1 Mar 2010 05:05:56 +0100 Subject: ARM: 5963/1: ux500: add support for u8500 v1 revision Add cpu_is_u8500{ed/v1}() functions to determine the variant based on the CPU id, add the changed peripheral addresses, and fixup the MTU address. Acked-by: Linus Walleij Acked-by: Srinidhi Kasagar Signed-off-by: Rabin Vincent Signed-off-by: Russell King diff --git a/arch/arm/mach-ux500/cpu-u8500.c b/arch/arm/mach-ux500/cpu-u8500.c index 588b059..f368504 100644 --- a/arch/arm/mach-ux500/cpu-u8500.c +++ b/arch/arm/mach-ux500/cpu-u8500.c @@ -40,15 +40,27 @@ static struct map_desc u8500_io_desc[] __initdata = { __IO_DEV_DESC(U8500_UART2_BASE, SZ_4K), __IO_DEV_DESC(U8500_GIC_CPU_BASE, SZ_4K), __IO_DEV_DESC(U8500_GIC_DIST_BASE, SZ_4K), - __IO_DEV_DESC(U8500_MTU0_BASE, SZ_4K), __IO_DEV_DESC(U8500_TWD_BASE, SZ_4K), __IO_DEV_DESC(U8500_SCU_BASE, SZ_4K), __IO_DEV_DESC(U8500_BACKUPRAM0_BASE, SZ_8K), }; +static struct map_desc u8500ed_io_desc[] __initdata = { + __IO_DEV_DESC(U8500_MTU0_BASE_ED, SZ_4K), +}; + +static struct map_desc u8500v1_io_desc[] __initdata = { + __IO_DEV_DESC(U8500_MTU0_BASE_V1, SZ_4K), +}; + void __init u8500_map_io(void) { iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc)); + + if (cpu_is_u8500ed()) + iotable_init(u8500ed_io_desc, ARRAY_SIZE(u8500ed_io_desc)); + else + iotable_init(u8500v1_io_desc, ARRAY_SIZE(u8500v1_io_desc)); } void __init u8500_init_irq(void) @@ -75,7 +87,10 @@ static void __init u8500_timer_init(void) twd_base = __io_address(U8500_TWD_BASE); #endif /* Setup the MTU base */ - mtu_base = __io_address(U8500_MTU0_BASE); + if (cpu_is_u8500ed()) + mtu_base = __io_address(U8500_MTU0_BASE_ED); + else + mtu_base = __io_address(U8500_MTU0_BASE_V1); nmdk_timer_init(); } diff --git a/arch/arm/mach-ux500/include/mach/hardware.h b/arch/arm/mach-ux500/include/mach/hardware.h index 04ea836..f29a43d 100644 --- a/arch/arm/mach-ux500/include/mach/hardware.h +++ b/arch/arm/mach-ux500/include/mach/hardware.h @@ -56,16 +56,19 @@ #define U8500_TWD_SIZE 0x100 /* per7 base addressess */ -#define U8500_CR_BASE (U8500_PER7_BASE + 0x8000) -#define U8500_MTU0_BASE (U8500_PER7_BASE + 0xa000) -#define U8500_MTU1_BASE (U8500_PER7_BASE + 0xb000) -#define U8500_TZPC0_BASE (U8500_PER7_BASE + 0xc000) -#define U8500_CLKRST7_BASE (U8500_PER7_BASE + 0xf000) +#define U8500_CR_BASE_ED (U8500_PER7_BASE + 0x8000) +#define U8500_MTU0_BASE_ED (U8500_PER7_BASE + 0xa000) +#define U8500_MTU1_BASE_ED (U8500_PER7_BASE + 0xb000) +#define U8500_TZPC0_BASE_ED (U8500_PER7_BASE + 0xc000) +#define U8500_CLKRST7_BASE_ED (U8500_PER7_BASE + 0xf000) /* per6 base addressess */ #define U8500_RNG_BASE (U8500_PER6_BASE + 0x0000) #define U8500_PKA_BASE (U8500_PER6_BASE + 0x1000) #define U8500_PKAM_BASE (U8500_PER6_BASE + 0x2000) +#define U8500_MTU0_BASE_V1 (U8500_PER6_BASE + 0x6000) +#define U8500_MTU1_BASE_V1 (U8500_PER6_BASE + 0x7000) +#define U8500_CR_BASE_V1 (U8500_PER6_BASE + 0x8000) #define U8500_CRYPTO0_BASE (U8500_PER6_BASE + 0xa000) #define U8500_CRYPTO1_BASE (U8500_PER6_BASE + 0xb000) #define U8500_CLKRST6_BASE (U8500_PER6_BASE + 0xf000) @@ -128,4 +131,20 @@ /* ST-Ericsson modified pl022 id */ #define SSP_PER_ID 0x01080022 +#ifndef __ASSEMBLY__ + +#include + +static inline bool cpu_is_u8500ed(void) +{ + return (read_cpuid_id() & 15) == 0; +} + +static inline bool cpu_is_u8500v1(void) +{ + return (read_cpuid_id() & 15) == 1; +} + +#endif + #endif /* __MACH_HARDWARE_H */ -- cgit v0.10.2 From 1df20afce51e7af2a587425d1aafca2608fe0066 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Mon, 1 Mar 2010 05:07:47 +0100 Subject: ARM: 5964/1: ux500: support clock gating Implement clock gating support for the u8500 clocks. Acked-by: Linus Walleij Acked-by: Srinidhi Kasagar Signed-off-by: Rabin Vincent Signed-off-by: Russell King diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index c2b4a35..4335186 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -94,7 +94,7 @@ static struct pl022_ssp_controller ssp0_platform_data = { static struct amba_device pl022_device = { .dev = { .coherent_dma_mask = ~0, - .init_name = "pl022", + .init_name = "ssp0", .platform_data = &ssp0_platform_data, }, .res = { diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c index 8359a73..d16b8b5 100644 --- a/arch/arm/mach-ux500/clock.c +++ b/arch/arm/mach-ux500/clock.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2009 ST-Ericsson - * heavily based on realview platform + * Copyright (C) 2009 STMicroelectronics * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -12,33 +12,130 @@ #include #include #include -#include +#include #include -/* currently the clk structure - * just supports rate. This would - * be extended as and when new devices are - * added - TODO - */ -struct clk { - unsigned long rate; -}; +#include +#include "clock.h" + +#define PRCC_PCKEN 0x00 +#define PRCC_PCKDIS 0x04 +#define PRCC_KCKEN 0x08 +#define PRCC_KCKDIS 0x0C + +#define PRCM_YYCLKEN0_MGT_SET 0x510 +#define PRCM_YYCLKEN1_MGT_SET 0x514 +#define PRCM_YYCLKEN0_MGT_CLR 0x518 +#define PRCM_YYCLKEN1_MGT_CLR 0x51C +#define PRCM_YYCLKEN0_MGT_VAL 0x520 +#define PRCM_YYCLKEN1_MGT_VAL 0x524 + +#define PRCM_SVAMMDSPCLK_MGT 0x008 +#define PRCM_SIAMMDSPCLK_MGT 0x00C +#define PRCM_SGACLK_MGT 0x014 +#define PRCM_UARTCLK_MGT 0x018 +#define PRCM_MSP02CLK_MGT 0x01C +#define PRCM_MSP1CLK_MGT 0x288 +#define PRCM_I2CCLK_MGT 0x020 +#define PRCM_SDMMCCLK_MGT 0x024 +#define PRCM_SLIMCLK_MGT 0x028 +#define PRCM_PER1CLK_MGT 0x02C +#define PRCM_PER2CLK_MGT 0x030 +#define PRCM_PER3CLK_MGT 0x034 +#define PRCM_PER5CLK_MGT 0x038 +#define PRCM_PER6CLK_MGT 0x03C +#define PRCM_PER7CLK_MGT 0x040 +#define PRCM_LCDCLK_MGT 0x044 +#define PRCM_BMLCLK_MGT 0x04C +#define PRCM_HSITXCLK_MGT 0x050 +#define PRCM_HSIRXCLK_MGT 0x054 +#define PRCM_HDMICLK_MGT 0x058 +#define PRCM_APEATCLK_MGT 0x05C +#define PRCM_APETRACECLK_MGT 0x060 +#define PRCM_MCDECLK_MGT 0x064 +#define PRCM_IPI2CCLK_MGT 0x068 +#define PRCM_DSIALTCLK_MGT 0x06C +#define PRCM_DMACLK_MGT 0x074 +#define PRCM_B2R2CLK_MGT 0x078 +#define PRCM_TVCLK_MGT 0x07C +#define PRCM_UNIPROCLK_MGT 0x278 +#define PRCM_SSPCLK_MGT 0x280 +#define PRCM_RNGCLK_MGT 0x284 +#define PRCM_UICCCLK_MGT 0x27C + +#define PRCM_MGT_ENABLE (1 << 8) + +static DEFINE_SPINLOCK(clocks_lock); + +static void __clk_enable(struct clk *clk) +{ + if (clk->enabled++ == 0) { + if (clk->parent_cluster) + __clk_enable(clk->parent_cluster); + + if (clk->parent_periph) + __clk_enable(clk->parent_periph); + + if (clk->ops && clk->ops->enable) + clk->ops->enable(clk); + } +} int clk_enable(struct clk *clk) { + unsigned long flags; + + spin_lock_irqsave(&clocks_lock, flags); + __clk_enable(clk); + spin_unlock_irqrestore(&clocks_lock, flags); + return 0; } EXPORT_SYMBOL(clk_enable); +static void __clk_disable(struct clk *clk) +{ + if (--clk->enabled == 0) { + if (clk->ops && clk->ops->disable) + clk->ops->disable(clk); + + if (clk->parent_periph) + __clk_disable(clk->parent_periph); + + if (clk->parent_cluster) + __clk_disable(clk->parent_cluster); + } +} + void clk_disable(struct clk *clk) { + unsigned long flags; + + WARN_ON(!clk->enabled); + + spin_lock_irqsave(&clocks_lock, flags); + __clk_disable(clk); + spin_unlock_irqrestore(&clocks_lock, flags); } EXPORT_SYMBOL(clk_disable); unsigned long clk_get_rate(struct clk *clk) { - return clk->rate; + unsigned long rate; + + if (clk->ops && clk->ops->get_rate) + return clk->ops->get_rate(clk); + + rate = clk->rate; + if (!rate) { + if (clk->parent_periph) + rate = clk_get_rate(clk->parent_periph); + else if (clk->parent_cluster) + rate = clk_get_rate(clk->parent_cluster); + } + + return rate; } EXPORT_SYMBOL(clk_get_rate); @@ -56,37 +153,363 @@ int clk_set_rate(struct clk *clk, unsigned long rate) } EXPORT_SYMBOL(clk_set_rate); -/* ssp clock */ -static struct clk ssp_clk = { - .rate = 48000000, +static void clk_prcmu_enable(struct clk *clk) +{ + void __iomem *cg_set_reg = __io_address(U8500_PRCMU_BASE) + + PRCM_YYCLKEN0_MGT_SET + clk->prcmu_cg_off; + + writel(1 << clk->prcmu_cg_bit, cg_set_reg); +} + +static void clk_prcmu_disable(struct clk *clk) +{ + void __iomem *cg_clr_reg = __io_address(U8500_PRCMU_BASE) + + PRCM_YYCLKEN0_MGT_CLR + clk->prcmu_cg_off; + + writel(1 << clk->prcmu_cg_bit, cg_clr_reg); +} + +/* ED doesn't have the combined set/clr registers */ +static void clk_prcmu_ed_enable(struct clk *clk) +{ + void __iomem *addr = __io_address(U8500_PRCMU_BASE) + + clk->prcmu_cg_mgt; + + writel(readl(addr) | PRCM_MGT_ENABLE, addr); +} + +static void clk_prcmu_ed_disable(struct clk *clk) +{ + void __iomem *addr = __io_address(U8500_PRCMU_BASE) + + clk->prcmu_cg_mgt; + + writel(readl(addr) & ~PRCM_MGT_ENABLE, addr); +} + +static struct clkops clk_prcmu_ops = { + .enable = clk_prcmu_enable, + .disable = clk_prcmu_disable, }; -/* fixed clock */ -static struct clk f38_clk = { - .rate = 38400000, +static unsigned int clkrst_base[] = { + [1] = U8500_CLKRST1_BASE, + [2] = U8500_CLKRST2_BASE, + [3] = U8500_CLKRST3_BASE, + [5] = U8500_CLKRST5_BASE, + [6] = U8500_CLKRST6_BASE, + [7] = U8500_CLKRST7_BASE_ED, }; -static struct clk_lookup lookups[] = { - { - /* UART0 */ - .dev_id = "uart0", - .clk = &f38_clk, - }, { /* UART1 */ - .dev_id = "uart1", - .clk = &f38_clk, - }, { /* UART2 */ - .dev_id = "uart2", - .clk = &f38_clk, - }, { /* SSP */ - .dev_id = "pl022", - .clk = &ssp_clk, - } +static void clk_prcc_enable(struct clk *clk) +{ + void __iomem *addr = __io_address(clkrst_base[clk->cluster]); + + if (clk->prcc_kernel != -1) + writel(1 << clk->prcc_kernel, addr + PRCC_KCKEN); + + if (clk->prcc_bus != -1) + writel(1 << clk->prcc_bus, addr + PRCC_PCKEN); +} + +static void clk_prcc_disable(struct clk *clk) +{ + void __iomem *addr = __io_address(clkrst_base[clk->cluster]); + + if (clk->prcc_bus != -1) + writel(1 << clk->prcc_bus, addr + PRCC_PCKDIS); + + if (clk->prcc_kernel != -1) + writel(1 << clk->prcc_kernel, addr + PRCC_KCKDIS); +} + +static struct clkops clk_prcc_ops = { + .enable = clk_prcc_enable, + .disable = clk_prcc_disable, +}; + +static struct clk clk_32khz = { + .rate = 32000, +}; + +/* + * PRCMU level clock gating + */ + +/* Bank 0 */ +static DEFINE_PRCMU_CLK(svaclk, 0x0, 2, SVAMMDSPCLK); +static DEFINE_PRCMU_CLK(siaclk, 0x0, 3, SIAMMDSPCLK); +static DEFINE_PRCMU_CLK(sgaclk, 0x0, 4, SGACLK); +static DEFINE_PRCMU_CLK_RATE(uartclk, 0x0, 5, UARTCLK, 38400000); +static DEFINE_PRCMU_CLK(msp02clk, 0x0, 6, MSP02CLK); +static DEFINE_PRCMU_CLK(msp1clk, 0x0, 7, MSP1CLK); /* v1 */ +static DEFINE_PRCMU_CLK_RATE(i2cclk, 0x0, 8, I2CCLK, 48000000); +static DEFINE_PRCMU_CLK_RATE(sdmmcclk, 0x0, 9, SDMMCCLK, 50000000); +static DEFINE_PRCMU_CLK(slimclk, 0x0, 10, SLIMCLK); +static DEFINE_PRCMU_CLK(per1clk, 0x0, 11, PER1CLK); +static DEFINE_PRCMU_CLK(per2clk, 0x0, 12, PER2CLK); +static DEFINE_PRCMU_CLK(per3clk, 0x0, 13, PER3CLK); +static DEFINE_PRCMU_CLK(per5clk, 0x0, 14, PER5CLK); +static DEFINE_PRCMU_CLK_RATE(per6clk, 0x0, 15, PER6CLK, 133330000); +static DEFINE_PRCMU_CLK_RATE(per7clk, 0x0, 16, PER7CLK, 100000000); +static DEFINE_PRCMU_CLK(lcdclk, 0x0, 17, LCDCLK); +static DEFINE_PRCMU_CLK(bmlclk, 0x0, 18, BMLCLK); +static DEFINE_PRCMU_CLK(hsitxclk, 0x0, 19, HSITXCLK); +static DEFINE_PRCMU_CLK(hsirxclk, 0x0, 20, HSIRXCLK); +static DEFINE_PRCMU_CLK(hdmiclk, 0x0, 21, HDMICLK); +static DEFINE_PRCMU_CLK(apeatclk, 0x0, 22, APEATCLK); +static DEFINE_PRCMU_CLK(apetraceclk, 0x0, 23, APETRACECLK); +static DEFINE_PRCMU_CLK(mcdeclk, 0x0, 24, MCDECLK); +static DEFINE_PRCMU_CLK(ipi2clk, 0x0, 25, IPI2CCLK); +static DEFINE_PRCMU_CLK(dsialtclk, 0x0, 26, DSIALTCLK); /* v1 */ +static DEFINE_PRCMU_CLK(dmaclk, 0x0, 27, DMACLK); +static DEFINE_PRCMU_CLK(b2r2clk, 0x0, 28, B2R2CLK); +static DEFINE_PRCMU_CLK(tvclk, 0x0, 29, TVCLK); +static DEFINE_PRCMU_CLK(uniproclk, 0x0, 30, UNIPROCLK); /* v1 */ +static DEFINE_PRCMU_CLK_RATE(sspclk, 0x0, 31, SSPCLK, 48000000); /* v1 */ + +/* Bank 1 */ +static DEFINE_PRCMU_CLK(rngclk, 0x4, 0, RNGCLK); /* v1 */ +static DEFINE_PRCMU_CLK(uiccclk, 0x4, 1, UICCCLK); /* v1 */ + +/* + * PRCC level clock gating + * Format: per#, clk, PCKEN bit, KCKEN bit, parent + */ + +/* Peripheral Cluster #1 */ +static DEFINE_PRCC_CLK(1, i2c4, 10, 9, &clk_i2cclk); +static DEFINE_PRCC_CLK(1, gpio0, 9, -1, NULL); +static DEFINE_PRCC_CLK(1, slimbus0, 8, 8, &clk_slimclk); +static DEFINE_PRCC_CLK(1, spi3_ed, 7, 7, NULL); +static DEFINE_PRCC_CLK(1, spi3_v1, 7, -1, NULL); +static DEFINE_PRCC_CLK(1, i2c2, 6, 6, &clk_i2cclk); +static DEFINE_PRCC_CLK(1, sdi0, 5, 5, &clk_sdmmcclk); +static DEFINE_PRCC_CLK(1, msp1_ed, 4, 4, &clk_msp02clk); +static DEFINE_PRCC_CLK(1, msp1_v1, 4, 4, &clk_msp1clk); +static DEFINE_PRCC_CLK(1, msp0, 3, 3, &clk_msp02clk); +static DEFINE_PRCC_CLK(1, i2c1, 2, 2, &clk_i2cclk); +static DEFINE_PRCC_CLK(1, uart1, 1, 1, &clk_uartclk); +static DEFINE_PRCC_CLK(1, uart0, 0, 0, &clk_uartclk); + +/* Peripheral Cluster #2 */ + +static DEFINE_PRCC_CLK(2, gpio1_ed, 12, -1, NULL); +static DEFINE_PRCC_CLK(2, ssitx_ed, 11, -1, NULL); +static DEFINE_PRCC_CLK(2, ssirx_ed, 10, -1, NULL); +static DEFINE_PRCC_CLK(2, spi0_ed, 9, -1, NULL); +static DEFINE_PRCC_CLK(2, sdi3_ed, 8, 6, &clk_sdmmcclk); +static DEFINE_PRCC_CLK(2, sdi1_ed, 7, 5, &clk_sdmmcclk); +static DEFINE_PRCC_CLK(2, msp2_ed, 6, 4, &clk_msp02clk); +static DEFINE_PRCC_CLK(2, sdi4_ed, 4, 2, &clk_sdmmcclk); +static DEFINE_PRCC_CLK(2, pwl_ed, 3, 1, NULL); +static DEFINE_PRCC_CLK(2, spi1_ed, 2, -1, NULL); +static DEFINE_PRCC_CLK(2, spi2_ed, 1, -1, NULL); +static DEFINE_PRCC_CLK(2, i2c3_ed, 0, 0, &clk_i2cclk); + +static DEFINE_PRCC_CLK(2, gpio1_v1, 11, -1, NULL); +static DEFINE_PRCC_CLK(2, ssitx_v1, 10, 7, NULL); +static DEFINE_PRCC_CLK(2, ssirx_v1, 9, 6, NULL); +static DEFINE_PRCC_CLK(2, spi0_v1, 8, -1, NULL); +static DEFINE_PRCC_CLK(2, sdi3_v1, 7, 5, &clk_sdmmcclk); +static DEFINE_PRCC_CLK(2, sdi1_v1, 6, 4, &clk_sdmmcclk); +static DEFINE_PRCC_CLK(2, msp2_v1, 5, 3, &clk_msp02clk); +static DEFINE_PRCC_CLK(2, sdi4_v1, 4, 2, &clk_sdmmcclk); +static DEFINE_PRCC_CLK(2, pwl_v1, 3, 1, NULL); +static DEFINE_PRCC_CLK(2, spi1_v1, 2, -1, NULL); +static DEFINE_PRCC_CLK(2, spi2_v1, 1, -1, NULL); +static DEFINE_PRCC_CLK(2, i2c3_v1, 0, 0, &clk_i2cclk); + +/* Peripheral Cluster #3 */ +static DEFINE_PRCC_CLK(3, gpio2, 8, -1, NULL); +static DEFINE_PRCC_CLK(3, sdi5, 7, 7, &clk_sdmmcclk); +static DEFINE_PRCC_CLK(3, uart2, 6, 6, &clk_uartclk); +static DEFINE_PRCC_CLK(3, ske, 5, 5, &clk_32khz); +static DEFINE_PRCC_CLK(3, sdi2, 4, 4, &clk_sdmmcclk); +static DEFINE_PRCC_CLK(3, i2c0, 3, 3, &clk_i2cclk); +static DEFINE_PRCC_CLK(3, ssp1_ed, 2, 2, &clk_i2cclk); +static DEFINE_PRCC_CLK(3, ssp0_ed, 1, 1, &clk_i2cclk); +static DEFINE_PRCC_CLK(3, ssp1_v1, 2, 2, &clk_sspclk); +static DEFINE_PRCC_CLK(3, ssp0_v1, 1, 1, &clk_sspclk); +static DEFINE_PRCC_CLK(3, fsmc, 0, -1, NULL); + +/* Peripheral Cluster #4 is in the always on domain */ + +/* Peripheral Cluster #5 */ +static DEFINE_PRCC_CLK(5, gpio3, 1, -1, NULL); +static DEFINE_PRCC_CLK(5, usb_ed, 0, 0, &clk_i2cclk); +static DEFINE_PRCC_CLK(5, usb_v1, 0, 0, NULL); + +/* Peripheral Cluster #6 */ + +static DEFINE_PRCC_CLK(6, mtu1_v1, 8, -1, NULL); +static DEFINE_PRCC_CLK(6, mtu0_v1, 7, -1, NULL); +static DEFINE_PRCC_CLK(6, cfgreg_v1, 6, 6, NULL); +static DEFINE_PRCC_CLK(6, dmc_ed, 6, 6, NULL); +static DEFINE_PRCC_CLK(6, hash1, 5, -1, NULL); +static DEFINE_PRCC_CLK(6, unipro_v1, 4, 1, &clk_uniproclk); +static DEFINE_PRCC_CLK(6, cryp1_ed, 4, -1, NULL); +static DEFINE_PRCC_CLK(6, pka, 3, -1, NULL); +static DEFINE_PRCC_CLK(6, hash0, 2, -1, NULL); +static DEFINE_PRCC_CLK(6, cryp0, 1, -1, NULL); +static DEFINE_PRCC_CLK(6, rng_ed, 0, 0, &clk_i2cclk); +static DEFINE_PRCC_CLK(6, rng_v1, 0, 0, &clk_rngclk); + +/* Peripheral Cluster #7 */ + +static DEFINE_PRCC_CLK(7, tzpc0_ed, 4, -1, NULL); +static DEFINE_PRCC_CLK(7, mtu1_ed, 3, -1, NULL); +static DEFINE_PRCC_CLK(7, mtu0_ed, 2, -1, NULL); +static DEFINE_PRCC_CLK(7, wdg_ed, 1, -1, NULL); +static DEFINE_PRCC_CLK(7, cfgreg_ed, 0, -1, NULL); + +static struct clk_lookup u8500_common_clks[] = { + /* Peripheral Cluster #1 */ + CLK(gpio0, "gpioblock0", NULL), + CLK(slimbus0, "slimbus0", NULL), + CLK(i2c2, "nmk-i2c.2", NULL), + CLK(sdi0, "sdi0", NULL), + CLK(msp0, "msp0", NULL), + CLK(i2c1, "nmk-i2c.1", NULL), + CLK(uart1, "uart1", NULL), + CLK(uart0, "uart0", NULL), + + /* Peripheral Cluster #3 */ + CLK(gpio2, "gpioblock2", NULL), + CLK(sdi5, "sdi5", NULL), + CLK(uart2, "uart2", NULL), + CLK(ske, "ske", NULL), + CLK(sdi2, "sdi2", NULL), + CLK(i2c0, "nmk-i2c.0", NULL), + CLK(fsmc, "fsmc", NULL), + + /* Peripheral Cluster #5 */ + CLK(gpio3, "gpioblock3", NULL), + + /* Peripheral Cluster #6 */ + CLK(hash1, "hash1", NULL), + CLK(pka, "pka", NULL), + CLK(hash0, "hash0", NULL), + CLK(cryp0, "cryp0", NULL), + + /* PRCMU level clock gating */ + + /* Bank 0 */ + CLK(svaclk, "sva", NULL), + CLK(siaclk, "sia", NULL), + CLK(sgaclk, "sga", NULL), + CLK(slimclk, "slim", NULL), + CLK(lcdclk, "lcd", NULL), + CLK(bmlclk, "bml", NULL), + CLK(hsitxclk, "stm-hsi.0", NULL), + CLK(hsirxclk, "stm-hsi.1", NULL), + CLK(hdmiclk, "hdmi", NULL), + CLK(apeatclk, "apeat", NULL), + CLK(apetraceclk, "apetrace", NULL), + CLK(mcdeclk, "mcde", NULL), + CLK(ipi2clk, "ipi2", NULL), + CLK(dmaclk, "dma40", NULL), + CLK(b2r2clk, "b2r2", NULL), + CLK(tvclk, "tv", NULL), +}; + +static struct clk_lookup u8500_ed_clks[] = { + /* Peripheral Cluster #1 */ + CLK(spi3_ed, "spi3", NULL), + CLK(msp1_ed, "msp1", NULL), + + /* Peripheral Cluster #2 */ + CLK(gpio1_ed, "gpioblock1", NULL), + CLK(ssitx_ed, "ssitx", NULL), + CLK(ssirx_ed, "ssirx", NULL), + CLK(spi0_ed, "spi0", NULL), + CLK(sdi3_ed, "sdi3", NULL), + CLK(sdi1_ed, "sdi1", NULL), + CLK(msp2_ed, "msp2", NULL), + CLK(sdi4_ed, "sdi4", NULL), + CLK(pwl_ed, "pwl", NULL), + CLK(spi1_ed, "spi1", NULL), + CLK(spi2_ed, "spi2", NULL), + CLK(i2c3_ed, "nmk-i2c.3", NULL), + + /* Peripheral Cluster #3 */ + CLK(ssp1_ed, "ssp1", NULL), + CLK(ssp0_ed, "ssp0", NULL), + + /* Peripheral Cluster #5 */ + CLK(usb_ed, "musb_hdrc.0", "usb"), + + /* Peripheral Cluster #6 */ + CLK(dmc_ed, "dmc", NULL), + CLK(cryp1_ed, "cryp1", NULL), + CLK(rng_ed, "rng", NULL), + + /* Peripheral Cluster #7 */ + CLK(tzpc0_ed, "tzpc0", NULL), + CLK(mtu1_ed, "mtu1", NULL), + CLK(mtu0_ed, "mtu0", NULL), + CLK(wdg_ed, "wdg", NULL), + CLK(cfgreg_ed, "cfgreg", NULL), +}; + +static struct clk_lookup u8500_v1_clks[] = { + /* Peripheral Cluster #1 */ + CLK(i2c4, "nmk-i2c.4", NULL), + CLK(spi3_v1, "spi3", NULL), + CLK(msp1_v1, "msp1", NULL), + + /* Peripheral Cluster #2 */ + CLK(gpio1_v1, "gpioblock1", NULL), + CLK(ssitx_v1, "ssitx", NULL), + CLK(ssirx_v1, "ssirx", NULL), + CLK(spi0_v1, "spi0", NULL), + CLK(sdi3_v1, "sdi3", NULL), + CLK(sdi1_v1, "sdi1", NULL), + CLK(msp2_v1, "msp2", NULL), + CLK(sdi4_v1, "sdi4", NULL), + CLK(pwl_v1, "pwl", NULL), + CLK(spi1_v1, "spi1", NULL), + CLK(spi2_v1, "spi2", NULL), + CLK(i2c3_v1, "nmk-i2c.3", NULL), + + /* Peripheral Cluster #3 */ + CLK(ssp1_v1, "ssp1", NULL), + CLK(ssp0_v1, "ssp0", NULL), + + /* Peripheral Cluster #5 */ + CLK(usb_v1, "musb_hdrc.0", "usb"), + + /* Peripheral Cluster #6 */ + CLK(mtu1_v1, "mtu1", NULL), + CLK(mtu0_v1, "mtu0", NULL), + CLK(cfgreg_v1, "cfgreg", NULL), + CLK(hash1, "hash1", NULL), + CLK(unipro_v1, "unipro", NULL), + CLK(rng_v1, "rng", NULL), + + /* PRCMU level clock gating */ + + /* Bank 0 */ + CLK(uniproclk, "uniproclk", NULL), + CLK(dsialtclk, "dsialt", NULL), + + /* Bank 1 */ + CLK(rngclk, "rng", NULL), + CLK(uiccclk, "uicc", NULL), }; static int __init clk_init(void) { - /* register the clock lookups */ - clkdev_add_table(lookups, ARRAY_SIZE(lookups)); + if (cpu_is_u8500ed()) { + clk_prcmu_ops.enable = clk_prcmu_ed_enable; + clk_prcmu_ops.disable = clk_prcmu_ed_disable; + } + + clkdev_add_table(u8500_common_clks, ARRAY_SIZE(u8500_common_clks)); + if (cpu_is_u8500ed()) + clkdev_add_table(u8500_ed_clks, ARRAY_SIZE(u8500_ed_clks)); + else + clkdev_add_table(u8500_v1_clks, ARRAY_SIZE(u8500_v1_clks)); + return 0; } arch_initcall(clk_init); diff --git a/arch/arm/mach-ux500/clock.h b/arch/arm/mach-ux500/clock.h new file mode 100644 index 0000000..e4f99b6 --- /dev/null +++ b/arch/arm/mach-ux500/clock.h @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2010 ST-Ericsson + * Copyright (C) 2009 STMicroelectronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/** + * struct clkops - ux500 clock operations + * @enable: function to enable the clock + * @disable: function to disable the clock + * @get_rate: function to get the current clock rate + * + * This structure contains function pointers to functions that will be used to + * control the clock. All of these functions are optional. If get_rate is + * NULL, the rate in the struct clk will be used. + */ +struct clkops { + void (*enable) (struct clk *); + void (*disable) (struct clk *); + unsigned long (*get_rate) (struct clk *); +}; + +/** + * struct clk - ux500 clock structure + * @ops: pointer to clkops struct used to control this clock + * @name: name, for debugging + * @enabled: refcount. positive if enabled, zero if disabled + * @rate: fixed rate for clocks which don't implement + * ops->getrate + * @prcmu_cg_off: address offset of the combined enable/disable register + * (used on u8500v1) + * @prcmu_cg_bit: bit in the combined enable/disable register (used on + * u8500v1) + * @prcmu_cg_mgt: address of the enable/disable register (used on + * u8500ed) + * @cluster: peripheral cluster number + * @prcc_bus: bit for the bus clock in the peripheral's CLKRST + * @prcc_kernel: bit for the kernel clock in the peripheral's CLKRST. + * -1 if no kernel clock exists. + * @parent_cluster: pointer to parent's cluster clk struct + * @parent_periph: pointer to parent's peripheral clk struct + * + * Peripherals are organised into clusters, and each cluster has an associated + * bus clock. Some peripherals also have a parent peripheral clock. + * + * In order to enable a clock for a peripheral, we need to enable: + * (1) the parent cluster (bus) clock at the PRCMU level + * (2) the parent peripheral clock (if any) at the PRCMU level + * (3) the peripheral's bus & kernel clock at the PRCC level + * + * (1) and (2) are handled by defining clk structs (DEFINE_PRCMU_CLK) for each + * of the cluster and peripheral clocks, and hooking these as the parents of + * the individual peripheral clocks. + * + * (3) is handled by specifying the bits in the PRCC control registers required + * to enable these clocks and modifying them in the ->enable and + * ->disable callbacks of the peripheral clocks (DEFINE_PRCC_CLK). + * + * This structure describes both the PRCMU-level clocks and PRCC-level clocks. + * The prcmu_* fields are only used for the PRCMU clocks, and the cluster, + * prcc, and parent pointers are only used for the PRCC-level clocks. + */ +struct clk { + const struct clkops *ops; + const char *name; + unsigned int enabled; + + unsigned long rate; + struct list_head list; + + /* These three are only for PRCMU clks */ + + unsigned int prcmu_cg_off; + unsigned int prcmu_cg_bit; + unsigned int prcmu_cg_mgt; + + /* The rest are only for PRCC clks */ + + int cluster; + unsigned int prcc_bus; + unsigned int prcc_kernel; + + struct clk *parent_cluster; + struct clk *parent_periph; +}; + +#define DEFINE_PRCMU_CLK(_name, _cg_off, _cg_bit, _reg) \ +struct clk clk_##_name = { \ + .name = #_name, \ + .ops = &clk_prcmu_ops, \ + .prcmu_cg_off = _cg_off, \ + .prcmu_cg_bit = _cg_bit, \ + .prcmu_cg_mgt = PRCM_##_reg##_MGT \ + } + +#define DEFINE_PRCMU_CLK_RATE(_name, _cg_off, _cg_bit, _reg, _rate) \ +struct clk clk_##_name = { \ + .name = #_name, \ + .ops = &clk_prcmu_ops, \ + .prcmu_cg_off = _cg_off, \ + .prcmu_cg_bit = _cg_bit, \ + .rate = _rate, \ + .prcmu_cg_mgt = PRCM_##_reg##_MGT \ + } + +#define DEFINE_PRCC_CLK(_pclust, _name, _bus_en, _kernel_en, _kernclk) \ +struct clk clk_##_name = { \ + .name = #_name, \ + .ops = &clk_prcc_ops, \ + .cluster = _pclust, \ + .prcc_bus = _bus_en, \ + .prcc_kernel = _kernel_en, \ + .parent_cluster = &clk_per##_pclust##clk, \ + .parent_periph = _kernclk \ + } + +#define CLK(_clk, _devname, _conname) \ + { \ + .clk = &clk_##_clk, \ + .dev_id = _devname, \ + .con_id = _conname, \ + } diff --git a/arch/arm/mach-ux500/cpu-u8500.c b/arch/arm/mach-ux500/cpu-u8500.c index f368504..09bcba1 100644 --- a/arch/arm/mach-ux500/cpu-u8500.c +++ b/arch/arm/mach-ux500/cpu-u8500.c @@ -43,10 +43,17 @@ static struct map_desc u8500_io_desc[] __initdata = { __IO_DEV_DESC(U8500_TWD_BASE, SZ_4K), __IO_DEV_DESC(U8500_SCU_BASE, SZ_4K), __IO_DEV_DESC(U8500_BACKUPRAM0_BASE, SZ_8K), + __IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K), + __IO_DEV_DESC(U8500_CLKRST1_BASE, SZ_4K), + __IO_DEV_DESC(U8500_CLKRST2_BASE, SZ_4K), + __IO_DEV_DESC(U8500_CLKRST3_BASE, SZ_4K), + __IO_DEV_DESC(U8500_CLKRST5_BASE, SZ_4K), + __IO_DEV_DESC(U8500_CLKRST6_BASE, SZ_4K), }; static struct map_desc u8500ed_io_desc[] __initdata = { __IO_DEV_DESC(U8500_MTU0_BASE_ED, SZ_4K), + __IO_DEV_DESC(U8500_CLKRST7_BASE_ED, SZ_8K), }; static struct map_desc u8500v1_io_desc[] __initdata = { -- cgit v0.10.2 From 94bdc0e2d76c5f2467346bf14e7e16d6d8e0395d Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Wed, 3 Mar 2010 04:54:37 +0100 Subject: ARM: 5973/1: ux500: add gpio support Add support for the GPIOs on the U8500, using the plat-nomadik GPIO driver. Acked-by: Linus Walleij Acked-by: Srinidhi Kasagar Signed-off-by: Rabin Vincent Signed-off-by: Russell King diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c5408bf..540f859 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -756,6 +756,7 @@ config ARCH_U8500 select GENERIC_TIME select GENERIC_CLOCKEVENTS select COMMON_CLKDEV + select ARCH_REQUIRE_GPIOLIB help Support for ST-Ericsson's Ux500 architecture diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig index 03625d7..cd412a3 100644 --- a/arch/arm/mach-ux500/Kconfig +++ b/arch/arm/mach-ux500/Kconfig @@ -8,6 +8,7 @@ config MACH_U8500_MOP default y select ARM_GIC select HAS_MTU + select NOMADIK_GPIO help Include support for mop500 development platform based on U8500 architecture. The platform is based diff --git a/arch/arm/mach-ux500/cpu-u8500.c b/arch/arm/mach-ux500/cpu-u8500.c index 09bcba1..5fb4466 100644 --- a/arch/arm/mach-ux500/cpu-u8500.c +++ b/arch/arm/mach-ux500/cpu-u8500.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -23,9 +24,82 @@ #include #include -/* add any platform devices here - TODO */ +#define GPIO_RESOURCE(block) \ + { \ + .start = U8500_GPIOBANK##block##_BASE, \ + .end = U8500_GPIOBANK##block##_BASE + 127, \ + .flags = IORESOURCE_MEM, \ + }, \ + { \ + .start = IRQ_GPIO##block, \ + .end = IRQ_GPIO##block, \ + .flags = IORESOURCE_IRQ, \ + } + +#define GPIO_DEVICE(block) \ + { \ + .name = "gpio", \ + .id = block, \ + .num_resources = 2, \ + .resource = &u8500_gpio_resources[block * 2], \ + .dev = { \ + .platform_data = &u8500_gpio_data[block], \ + }, \ + } + +#define GPIO_DATA(_name, first) \ + { \ + .name = _name, \ + .first_gpio = first, \ + .first_irq = NOMADIK_GPIO_TO_IRQ(first), \ + } + +static struct nmk_gpio_platform_data u8500_gpio_data[] = { + GPIO_DATA("GPIO-0-31", 0), + GPIO_DATA("GPIO-32-63", 32), /* 37..63 not routed to pin */ + GPIO_DATA("GPIO-64-95", 64), + GPIO_DATA("GPIO-96-127", 96), /* 97..127 not routed to pin */ + GPIO_DATA("GPIO-128-159", 128), + GPIO_DATA("GPIO-160-191", 160), /* 172..191 not routed to pin */ + GPIO_DATA("GPIO-192-223", 192), + GPIO_DATA("GPIO-224-255", 224), /* 231..255 not routed to pin */ + GPIO_DATA("GPIO-256-288", 256), /* 258..288 not routed to pin */ +}; + +static struct resource u8500_gpio_resources[] = { + GPIO_RESOURCE(0), + GPIO_RESOURCE(1), + GPIO_RESOURCE(2), + GPIO_RESOURCE(3), + GPIO_RESOURCE(4), + GPIO_RESOURCE(5), + GPIO_RESOURCE(6), + GPIO_RESOURCE(7), + GPIO_RESOURCE(8), +}; + +static struct platform_device u8500_gpio_devs[] = { + GPIO_DEVICE(0), + GPIO_DEVICE(1), + GPIO_DEVICE(2), + GPIO_DEVICE(3), + GPIO_DEVICE(4), + GPIO_DEVICE(5), + GPIO_DEVICE(6), + GPIO_DEVICE(7), + GPIO_DEVICE(8), +}; + static struct platform_device *platform_devs[] __initdata = { - /* yet to be added, add i2c0, gpio.. */ + &u8500_gpio_devs[0], + &u8500_gpio_devs[1], + &u8500_gpio_devs[2], + &u8500_gpio_devs[3], + &u8500_gpio_devs[4], + &u8500_gpio_devs[5], + &u8500_gpio_devs[6], + &u8500_gpio_devs[7], + &u8500_gpio_devs[8], }; #define __IO_DEV_DESC(x, sz) { \ @@ -49,6 +123,10 @@ static struct map_desc u8500_io_desc[] __initdata = { __IO_DEV_DESC(U8500_CLKRST3_BASE, SZ_4K), __IO_DEV_DESC(U8500_CLKRST5_BASE, SZ_4K), __IO_DEV_DESC(U8500_CLKRST6_BASE, SZ_4K), + __IO_DEV_DESC(U8500_GPIO1_BASE, SZ_4K), + __IO_DEV_DESC(U8500_GPIO2_BASE, SZ_4K), + __IO_DEV_DESC(U8500_GPIO3_BASE, SZ_4K), + __IO_DEV_DESC(U8500_GPIO5_BASE, SZ_4K), }; static struct map_desc u8500ed_io_desc[] __initdata = { diff --git a/arch/arm/mach-ux500/include/mach/gpio.h b/arch/arm/mach-ux500/include/mach/gpio.h new file mode 100644 index 0000000..3c4cd31 --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/gpio.h @@ -0,0 +1,12 @@ +#ifndef __ASM_ARCH_GPIO_H +#define __ASM_ARCH_GPIO_H + +/* + * 288 (#267 is the highest one actually hooked up) onchip GPIOs, plus enough + * room for a couple of GPIO expanders. + */ +#define ARCH_NR_GPIOS 350 + +#include + +#endif /* __ASM_ARCH_GPIO_H */ diff --git a/arch/arm/mach-ux500/include/mach/hardware.h b/arch/arm/mach-ux500/include/mach/hardware.h index f29a43d..99ca89f 100644 --- a/arch/arm/mach-ux500/include/mach/hardware.h +++ b/arch/arm/mach-ux500/include/mach/hardware.h @@ -23,6 +23,8 @@ /* typesafe io address */ #define __io_address(n) __io(IO_ADDRESS(n)) +/* used by some plat-nomadik code */ +#define io_p2v(n) __io_address(n) /* * Base address definitions for U8500 Onchip IPs. All the @@ -128,6 +130,16 @@ #define U8500_GPIO1_BASE (U8500_PER1_BASE + 0xe000) #define U8500_CLKRST1_BASE (U8500_PER1_BASE + 0xf000) +#define U8500_GPIOBANK0_BASE U8500_GPIO1_BASE +#define U8500_GPIOBANK1_BASE (U8500_GPIO1_BASE + 0x80) +#define U8500_GPIOBANK2_BASE U8500_GPIO3_BASE +#define U8500_GPIOBANK3_BASE (U8500_GPIO3_BASE + 0x80) +#define U8500_GPIOBANK4_BASE (U8500_GPIO3_BASE + 0x100) +#define U8500_GPIOBANK5_BASE (U8500_GPIO3_BASE + 0x180) +#define U8500_GPIOBANK6_BASE U8500_GPIO2_BASE +#define U8500_GPIOBANK7_BASE (U8500_GPIO2_BASE + 0x80) +#define U8500_GPIOBANK8_BASE U8500_GPIO5_BASE + /* ST-Ericsson modified pl022 id */ #define SSP_PER_ID 0x01080022 diff --git a/arch/arm/mach-ux500/include/mach/irqs.h b/arch/arm/mach-ux500/include/mach/irqs.h index 394b5dd..8a1f697 100644 --- a/arch/arm/mach-ux500/include/mach/irqs.h +++ b/arch/arm/mach-ux500/include/mach/irqs.h @@ -66,6 +66,12 @@ /* There are 128 shared peripheral interrupts assigned to * INTID[160:32]. The first 32 interrupts are reserved. */ -#define NR_IRQS 161 +#define U8500_SOC_NR_IRQS 161 + +/* After chip-specific IRQ numbers we have the GPIO ones */ +#define NOMADIK_NR_GPIO 288 +#define NOMADIK_GPIO_TO_IRQ(gpio) ((gpio) + U8500_SOC_NR_IRQS) +#define NOMADIK_IRQ_TO_GPIO(irq) ((irq) - U8500_SOC_NR_IRQS) +#define NR_IRQS NOMADIK_GPIO_TO_IRQ(NOMADIK_NR_GPIO) #endif /*ASM_ARCH_IRQS_H*/ -- cgit v0.10.2 From b102c01faed5e0083a4e6d29a2d61f6b57716e94 Mon Sep 17 00:00:00 2001 From: Alessandro Rubini Date: Fri, 5 Mar 2010 12:38:51 +0100 Subject: ARM: 5978/1: plat-nomadik: use one-shot clock events This is a complete rewrite of the MTU driver, using one-shot for events and a free-running timer for stamping. It allows CONFIG_NO_HZ and CONFIG_HIGH_RES_TIMERS to work on Nomadik and Ux500. Signed-off-by: Alessandro Rubini Acked-by: Linus Walleij Acked-by: Andrea Gallo Signed-off-by: Russell King diff --git a/arch/arm/plat-nomadik/timer.c b/arch/arm/plat-nomadik/timer.c index fa7cb3a..db67402 100644 --- a/arch/arm/plat-nomadik/timer.c +++ b/arch/arm/plat-nomadik/timer.c @@ -2,7 +2,7 @@ * linux/arch/arm/mach-nomadik/timer.c * * Copyright (C) 2008 STMicroelectronics - * Copyright (C) 2009 Alessandro Rubini, somewhat based on at91sam926x + * Copyright (C) 2010 Alessandro Rubini * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, as @@ -18,123 +18,124 @@ #include -static u32 nmdk_count; /* accumulated count */ -static u32 nmdk_cycle; /* write-once */ +void __iomem *mtu_base; /* ssigned by machine code */ -/* setup by the platform code */ -void __iomem *mtu_base; - -/* - * clocksource: the MTU device is a decrementing counters, so we negate - * the value being read. - */ +/* clocksource: MTU decrements, so we negate the value being read. */ static cycle_t nmdk_read_timer(struct clocksource *cs) { - u32 count = readl(mtu_base + MTU_VAL(0)); - return nmdk_count + nmdk_cycle - count; - + return -readl(mtu_base + MTU_VAL(0)); } static struct clocksource nmdk_clksrc = { .name = "mtu_0", - .rating = 120, + .rating = 200, .read = nmdk_read_timer, + .mask = CLOCKSOURCE_MASK(32), .shift = 20, .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; -/* - * Clockevent device: currently only periodic mode is supported - */ +/* Clockevent device: use one-shot mode */ static void nmdk_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev) { + u32 cr; + switch (mode) { case CLOCK_EVT_MODE_PERIODIC: - /* count current value? */ - writel(readl(mtu_base + MTU_IMSC) | 1, mtu_base + MTU_IMSC); + pr_err("%s: periodic mode not supported\n", __func__); break; case CLOCK_EVT_MODE_ONESHOT: - BUG(); /* Not supported, yet */ - /* FALLTHROUGH */ + /* Load highest value, enable device, enable interrupts */ + cr = readl(mtu_base + MTU_CR(1)); + writel(0, mtu_base + MTU_LR(1)); + writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(1)); + writel(0x2, mtu_base + MTU_IMSC); + break; case CLOCK_EVT_MODE_SHUTDOWN: case CLOCK_EVT_MODE_UNUSED: - writel(readl(mtu_base + MTU_IMSC) & ~1, mtu_base + MTU_IMSC); + /* disable irq */ + writel(0, mtu_base + MTU_IMSC); break; case CLOCK_EVT_MODE_RESUME: break; } } +static int nmdk_clkevt_next(unsigned long evt, struct clock_event_device *ev) +{ + /* writing the value has immediate effect */ + writel(evt, mtu_base + MTU_LR(1)); + return 0; +} + static struct clock_event_device nmdk_clkevt = { - .name = "mtu_0", - .features = CLOCK_EVT_FEAT_PERIODIC, + .name = "mtu_1", + .features = CLOCK_EVT_FEAT_ONESHOT, .shift = 32, - .rating = 100, + .rating = 200, .set_mode = nmdk_clkevt_mode, + .set_next_event = nmdk_clkevt_next, }; /* - * IRQ Handler for the timer 0 of the MTU block. The irq is not shared - * as we are the only users of mtu0 by now. + * IRQ Handler for timer 1 of the MTU block. */ static irqreturn_t nmdk_timer_interrupt(int irq, void *dev_id) { - /* ack: "interrupt clear register" */ - writel(1 << 0, mtu_base + MTU_ICR); - - /* we can't count lost ticks, unfortunately */ - nmdk_count += nmdk_cycle; - nmdk_clkevt.event_handler(&nmdk_clkevt); + struct clock_event_device *evdev = dev_id; + writel(1 << 1, mtu_base + MTU_ICR); /* Interrupt clear reg */ + evdev->event_handler(evdev); return IRQ_HANDLED; } -/* - * Set up timer interrupt, and return the current time in seconds. - */ static struct irqaction nmdk_timer_irq = { .name = "Nomadik Timer Tick", .flags = IRQF_DISABLED | IRQF_TIMER, .handler = nmdk_timer_interrupt, + .dev_id = &nmdk_clkevt, }; -static void nmdk_timer_reset(void) -{ - u32 cr; - - writel(0, mtu_base + MTU_CR(0)); /* off */ - - /* configure load and background-load, and fire it up */ - writel(nmdk_cycle, mtu_base + MTU_LR(0)); - writel(nmdk_cycle, mtu_base + MTU_BGLR(0)); - cr = MTU_CRn_PERIODIC | MTU_CRn_PRESCALE_1 | MTU_CRn_32BITS; - writel(cr, mtu_base + MTU_CR(0)); - writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(0)); -} - void __init nmdk_timer_init(void) { unsigned long rate; - int bits; - - rate = CLOCK_TICK_RATE; /* 2.4MHz */ - nmdk_cycle = (rate + HZ/2) / HZ; + u32 cr = MTU_CRn_32BITS;; + + /* + * Tick rate is 2.4MHz for Nomadik and 110MHz for ux500: + * use a divide-by-16 counter if it's more than 16MHz + */ + rate = CLOCK_TICK_RATE; + if (rate > 16 << 20) { + rate /= 16; + cr |= MTU_CRn_PRESCALE_16; + } else { + cr |= MTU_CRn_PRESCALE_1; + } - /* Init the timer and register clocksource */ - nmdk_timer_reset(); + /* Timer 0 is the free running clocksource */ + writel(cr, mtu_base + MTU_CR(0)); + writel(0, mtu_base + MTU_LR(0)); + writel(0, mtu_base + MTU_BGLR(0)); + writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(0)); nmdk_clksrc.mult = clocksource_hz2mult(rate, nmdk_clksrc.shift); - bits = 8*sizeof(nmdk_count); - nmdk_clksrc.mask = CLOCKSOURCE_MASK(bits); if (clocksource_register(&nmdk_clksrc)) - printk(KERN_ERR "timer: failed to initialize clock " - "source %s\n", nmdk_clksrc.name); + pr_err("timer: failed to initialize clock source %s\n", + nmdk_clksrc.name); + + /* Timer 1 is used for events, fix according to rate */ + writel(cr | MTU_CRn_ONESHOT, mtu_base + MTU_CR(1)); /* off, currently */ + nmdk_clkevt.mult = div_sc(rate, NSEC_PER_SEC, nmdk_clkevt.shift); + nmdk_clkevt.max_delta_ns = + clockevent_delta2ns(0xffffffff, &nmdk_clkevt); + nmdk_clkevt.min_delta_ns = + clockevent_delta2ns(0x00000002, &nmdk_clkevt); + nmdk_clkevt.cpumask = cpumask_of(0); /* Register irq and clockevents */ setup_irq(IRQ_MTU0, &nmdk_timer_irq); - nmdk_clkevt.mult = div_sc(rate, NSEC_PER_SEC, nmdk_clkevt.shift); - nmdk_clkevt.cpumask = cpumask_of(0); clockevents_register_device(&nmdk_clkevt); } -- cgit v0.10.2 From 4bd96a7a8185755b091233b16034c7436cbf57af Mon Sep 17 00:00:00 2001 From: Shane Wang Date: Wed, 10 Mar 2010 14:36:10 +0800 Subject: x86, tboot: Add support for S3 memory integrity protection This patch adds support for S3 memory integrity protection within an Intel(R) TXT launched kernel, for all kernel and userspace memory. All RAM used by the kernel and userspace, as indicated by memory ranges of type E820_RAM and E820_RESERVED_KERN in the e820 table, will be integrity protected. The MAINTAINERS file is also updated to reflect the maintainers of the TXT-related code. All MACing is done in tboot, based on a complexity analysis and tradeoff. v3: Compared with v2, this patch adds a check of array size in tboot.c, and a note to specify which c/s of tboot supports this kind of MACing in intel_txt.txt. Signed-off-by: Shane Wang LKML-Reference: <4B973DDA.6050902@intel.com> Signed-off-by: Joseph Cihula Acked-by: Pavel Machek Acked-by: Rafael J. Wysocki Signed-off-by: H. Peter Anvin diff --git a/Documentation/intel_txt.txt b/Documentation/intel_txt.txt index f40a1f0..87c8990 100644 --- a/Documentation/intel_txt.txt +++ b/Documentation/intel_txt.txt @@ -161,13 +161,15 @@ o In order to put a system into any of the sleep states after a TXT has been restored, it will restore the TPM PCRs and then transfer control back to the kernel's S3 resume vector. In order to preserve system integrity across S3, the kernel - provides tboot with a set of memory ranges (kernel - code/data/bss, S3 resume code, and AP trampoline) that tboot - will calculate a MAC (message authentication code) over and then - seal with the TPM. On resume and once the measured environment - has been re-established, tboot will re-calculate the MAC and - verify it against the sealed value. Tboot's policy determines - what happens if the verification fails. + provides tboot with a set of memory ranges (RAM and RESERVED_KERN + in the e820 table, but not any memory that BIOS might alter over + the S3 transition) that tboot will calculate a MAC (message + authentication code) over and then seal with the TPM. On resume + and once the measured environment has been re-established, tboot + will re-calculate the MAC and verify it against the sealed value. + Tboot's policy determines what happens if the verification fails. + Note that the c/s 194 of tboot which has the new MAC code supports + this. That's pretty much it for TXT support. diff --git a/MAINTAINERS b/MAINTAINERS index 47cc449..d3072cb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2940,6 +2940,17 @@ S: Odd Fixes F: Documentation/networking/README.ipw2200 F: drivers/net/wireless/ipw2x00/ipw2200.* +INTEL(R) TRUSTED EXECUTION TECHNOLOGY (TXT) +M: Joseph Cihula +M: Shane Wang +L: tboot-devel@lists.sourceforge.net +W: http://tboot.sourceforge.net +T: Mercurial http://www.bughost.org/repos.hg/tboot.hg +S: Supported +F: Documentation/intel_txt.txt +F: include/linux/tboot.h +F: arch/x86/kernel/tboot.c + INTEL WIRELESS WIMAX CONNECTION 2400 M: Inaky Perez-Gonzalez M: linux-wimax@intel.com diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h index 0e22296..ec8a52d 100644 --- a/arch/x86/include/asm/e820.h +++ b/arch/x86/include/asm/e820.h @@ -45,7 +45,12 @@ #define E820_NVS 4 #define E820_UNUSABLE 5 -/* reserved RAM used by kernel itself */ +/* + * reserved RAM used by kernel itself + * if CONFIG_INTEL_TXT is enabled, memory of this type will be + * included in the S3 integrity calculation and so should not include + * any memory that BIOS might alter over the S3 transition + */ #define E820_RESERVED_KERN 128 #ifndef __ASSEMBLY__ diff --git a/arch/x86/kernel/tboot.c b/arch/x86/kernel/tboot.c index 86c9f91..cc2c604 100644 --- a/arch/x86/kernel/tboot.c +++ b/arch/x86/kernel/tboot.c @@ -175,6 +175,9 @@ static void add_mac_region(phys_addr_t start, unsigned long size) struct tboot_mac_region *mr; phys_addr_t end = start + size; + if (tboot->num_mac_regions >= MAX_TB_MAC_REGIONS) + panic("tboot: Too many MAC regions\n"); + if (start && size) { mr = &tboot->mac_regions[tboot->num_mac_regions++]; mr->start = round_down(start, PAGE_SIZE); @@ -184,18 +187,17 @@ static void add_mac_region(phys_addr_t start, unsigned long size) static int tboot_setup_sleep(void) { + int i; + tboot->num_mac_regions = 0; - /* S3 resume code */ - add_mac_region(acpi_wakeup_address, WAKEUP_SIZE); + for (i = 0; i < e820.nr_map; i++) { + if ((e820.map[i].type != E820_RAM) + && (e820.map[i].type != E820_RESERVED_KERN)) + continue; -#ifdef CONFIG_X86_TRAMPOLINE - /* AP trampoline code */ - add_mac_region(virt_to_phys(trampoline_base), TRAMPOLINE_SIZE); -#endif - - /* kernel code + data + bss */ - add_mac_region(virt_to_phys(_text), _end - _text); + add_mac_region(e820.map[i].addr, e820.map[i].size); + } tboot->acpi_sinfo.kernel_s3_resume_vector = acpi_wakeup_address; -- cgit v0.10.2 From 301fde27c7fcd0380b02b175d547e894ff65d78a Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Mon, 22 Mar 2010 13:09:33 -0300 Subject: perf: Fix orphan callchain branches Callchains have markers inside their capture to tell we enter a context (kernel, user, ...). Those are not displayed in the callchains but they are incidentally an active part of the radix tree where callchains are stored, just like any other address. If we have the two following callchains: addr1 -> addr2 -> user context -> addr3 addr1 -> addr2 -> user context -> addr4 addr1 -> addr2 -> addr 5 This is pretty common if addr1 and addr2 are part of an interrupt path, addr3 and addr4 are user addresses and addr5 is a kernel non interrupt path. This will be stored as follows in the tree: addr1 addr2 / \ / addr5 user context / \ addr3 addr4 But we ignore the context markers in the report, hence the addr3 and addr4 will appear as orphan branches: |--28.30%-- hrtimer_interrupt | smp_apic_timer_interrupt | apic_timer_interrupt | | <------------- here, no parent! | | | | | |--11.11%-- 0x7fae7bccb875 | | | | | |--11.11%-- 0xffffffffff60013b | | | | | |--11.11%-- __pthread_mutex_lock_internal | | | | | |--11.11%-- __errno_location Fix this by removing the context markers when we process the callchains to the tree. Reported-by: Arnaldo Carvalho de Melo Signed-off-by: Frederic Weisbecker Cc: Paul Mackerras Cc: Peter Zijlstra Signed-off-by: Arnaldo Carvalho de Melo LKML-Reference: <1269274173-20328-1-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 1f9f869..d609afb 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -83,6 +83,7 @@ static int perf_session__add_hist_entry(struct perf_session *self, { struct symbol **syms = NULL, *parent = NULL; bool hit; + int err; struct hist_entry *he; struct event_stat_id *stats; struct perf_event_attr *attr; @@ -109,8 +110,11 @@ static int perf_session__add_hist_entry(struct perf_session *self, if (symbol_conf.use_callchain) { if (!hit) callchain_init(&he->callchain); - append_chain(&he->callchain, data->callchain, syms); + err = append_chain(&he->callchain, data->callchain, syms); free(syms); + + if (err) + return err; } return 0; diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index b3b7125..883844e 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009, Frederic Weisbecker + * Copyright (C) 2009-2010, Frederic Weisbecker * * Handle the callchains from the stream in an ad-hoc radix tree and then * sort them in an rbtree. @@ -183,12 +183,23 @@ create_child(struct callchain_node *parent, bool inherit_children) return new; } + +struct resolved_ip { + u64 ip; + struct symbol *sym; +}; + +struct resolved_chain { + u64 nr; + struct resolved_ip ips[0]; +}; + + /* * Fill the node with callchain values */ static void -fill_node(struct callchain_node *node, struct ip_callchain *chain, - int start, struct symbol **syms) +fill_node(struct callchain_node *node, struct resolved_chain *chain, int start) { unsigned int i; @@ -200,8 +211,8 @@ fill_node(struct callchain_node *node, struct ip_callchain *chain, perror("not enough memory for the code path tree"); return; } - call->ip = chain->ips[i]; - call->sym = syms[i]; + call->ip = chain->ips[i].ip; + call->sym = chain->ips[i].sym; list_add_tail(&call->list, &node->val); } node->val_nr = chain->nr - start; @@ -210,13 +221,13 @@ fill_node(struct callchain_node *node, struct ip_callchain *chain, } static void -add_child(struct callchain_node *parent, struct ip_callchain *chain, - int start, struct symbol **syms) +add_child(struct callchain_node *parent, struct resolved_chain *chain, + int start) { struct callchain_node *new; new = create_child(parent, false); - fill_node(new, chain, start, syms); + fill_node(new, chain, start); new->children_hit = 0; new->hit = 1; @@ -228,9 +239,8 @@ add_child(struct callchain_node *parent, struct ip_callchain *chain, * Then create another child to host the given callchain of new branch */ static void -split_add_child(struct callchain_node *parent, struct ip_callchain *chain, - struct callchain_list *to_split, int idx_parents, int idx_local, - struct symbol **syms) +split_add_child(struct callchain_node *parent, struct resolved_chain *chain, + struct callchain_list *to_split, int idx_parents, int idx_local) { struct callchain_node *new; struct list_head *old_tail; @@ -257,7 +267,7 @@ split_add_child(struct callchain_node *parent, struct ip_callchain *chain, /* create a new child for the new branch if any */ if (idx_total < chain->nr) { parent->hit = 0; - add_child(parent, chain, idx_total, syms); + add_child(parent, chain, idx_total); parent->children_hit++; } else { parent->hit = 1; @@ -265,32 +275,33 @@ split_add_child(struct callchain_node *parent, struct ip_callchain *chain, } static int -__append_chain(struct callchain_node *root, struct ip_callchain *chain, - unsigned int start, struct symbol **syms); +__append_chain(struct callchain_node *root, struct resolved_chain *chain, + unsigned int start); static void -__append_chain_children(struct callchain_node *root, struct ip_callchain *chain, - struct symbol **syms, unsigned int start) +__append_chain_children(struct callchain_node *root, + struct resolved_chain *chain, + unsigned int start) { struct callchain_node *rnode; /* lookup in childrens */ chain_for_each_child(rnode, root) { - unsigned int ret = __append_chain(rnode, chain, start, syms); + unsigned int ret = __append_chain(rnode, chain, start); if (!ret) goto inc_children_hit; } /* nothing in children, add to the current node */ - add_child(root, chain, start, syms); + add_child(root, chain, start); inc_children_hit: root->children_hit++; } static int -__append_chain(struct callchain_node *root, struct ip_callchain *chain, - unsigned int start, struct symbol **syms) +__append_chain(struct callchain_node *root, struct resolved_chain *chain, + unsigned int start) { struct callchain_list *cnode; unsigned int i = start; @@ -302,13 +313,19 @@ __append_chain(struct callchain_node *root, struct ip_callchain *chain, * anywhere inside a function. */ list_for_each_entry(cnode, &root->val, list) { + struct symbol *sym; + if (i == chain->nr) break; - if (cnode->sym && syms[i]) { - if (cnode->sym->start != syms[i]->start) + + sym = chain->ips[i].sym; + + if (cnode->sym && sym) { + if (cnode->sym->start != sym->start) break; - } else if (cnode->ip != chain->ips[i]) + } else if (cnode->ip != chain->ips[i].ip) break; + if (!found) found = true; i++; @@ -320,7 +337,7 @@ __append_chain(struct callchain_node *root, struct ip_callchain *chain, /* we match only a part of the node. Split it and add the new chain */ if (i - start < root->val_nr) { - split_add_child(root, chain, cnode, start, i - start, syms); + split_add_child(root, chain, cnode, start, i - start); return 0; } @@ -331,15 +348,51 @@ __append_chain(struct callchain_node *root, struct ip_callchain *chain, } /* We match the node and still have a part remaining */ - __append_chain_children(root, chain, syms, i); + __append_chain_children(root, chain, i); return 0; } -void append_chain(struct callchain_node *root, struct ip_callchain *chain, +static void +filter_context(struct ip_callchain *old, struct resolved_chain *new, + struct symbol **syms) +{ + int i, j = 0; + + for (i = 0; i < (int)old->nr; i++) { + if (old->ips[i] >= PERF_CONTEXT_MAX) + continue; + + new->ips[j].ip = old->ips[i]; + new->ips[j].sym = syms[i]; + j++; + } + + new->nr = j; +} + + +int append_chain(struct callchain_node *root, struct ip_callchain *chain, struct symbol **syms) { + struct resolved_chain *filtered; + if (!chain->nr) - return; - __append_chain_children(root, chain, syms, 0); + return 0; + + filtered = malloc(sizeof(*filtered) + + chain->nr * sizeof(struct resolved_ip)); + if (!filtered) + return -ENOMEM; + + filter_context(chain, filtered, syms); + + if (!filtered->nr) + goto end; + + __append_chain_children(root, filtered, 0); +end: + free(filtered); + + return 0; } diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index ad4626d..bbd76da 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h @@ -56,6 +56,6 @@ static inline u64 cumul_hits(struct callchain_node *node) } int register_callchain_param(struct callchain_param *param); -void append_chain(struct callchain_node *root, struct ip_callchain *chain, - struct symbol **syms); +int append_chain(struct callchain_node *root, struct ip_callchain *chain, + struct symbol **syms); #endif /* __PERF_CALLCHAIN_H */ diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index c37da8b..5843a9c 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -328,8 +328,6 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct callchain_node *self, left_margin); i = 0; list_for_each_entry(chain, &child->val, list) { - if (chain->ip >= PERF_CONTEXT_MAX) - continue; ret += ipchain__fprintf_graph(fp, chain, depth, new_depth_mask, i++, new_total, @@ -368,9 +366,6 @@ static size_t callchain__fprintf_graph(FILE *fp, struct callchain_node *self, int ret = 0; list_for_each_entry(chain, &self->val, list) { - if (chain->ip >= PERF_CONTEXT_MAX) - continue; - if (!i++ && sort__first_dimension == SORT_SYM) continue; -- cgit v0.10.2 From f3a1f0ea9432ec395cd112f42201e8e523c07bc5 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 22 Mar 2010 13:10:25 -0300 Subject: perf newt: Properly restore the screen when error exiting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Show an OK message box with the last message sent via pr_err, etc. Reported-by: Ingo Molnar Signed-off-by: Arnaldo Carvalho de Melo Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: <1269274229-20442-1-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar diff --git a/tools/perf/perf.c b/tools/perf/perf.c index d2de839..2826e70 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c @@ -264,11 +264,11 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv) set_debugfs_path(); status = p->fn(argc, argv, prefix); + exit_browser(status); + if (status) return status & 0xff; - exit_browser(); - /* Somebody closed stdout? */ if (fstat(fileno(stdout), &st)) return 0; diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h index 47b12a3..4b9aab7 100644 --- a/tools/perf/util/cache.h +++ b/tools/perf/util/cache.h @@ -77,10 +77,10 @@ static inline void setup_browser(void) { setup_pager(); } -static inline void exit_browser(void) {} +static inline void exit_browser(bool wait_for_ok __used) {} #else void setup_browser(void); -void exit_browser(void); +void exit_browser(bool wait_for_ok); #endif extern const char *editor_program; diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index 2d19e7a..3c2ef95 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -170,18 +170,20 @@ void perf_session__browse_hists(struct rb_root *hists, u64 session_total, newtFormDestroy(form); } +static char browser__last_msg[1024]; + int browser__show_help(const char *format, va_list ap) { int ret; static int backlog; - static char msg[1024]; - ret = vsnprintf(msg + backlog, sizeof(msg) - backlog, format, ap); + ret = vsnprintf(browser__last_msg + backlog, + sizeof(browser__last_msg) - backlog, format, ap); backlog += ret; - if (msg[backlog - 1] == '\n') { + if (browser__last_msg[backlog - 1] == '\n') { newtPopHelpLine(); - newtPushHelpLine(msg); + newtPushHelpLine(browser__last_msg); newtRefresh(); backlog = 0; } @@ -200,8 +202,13 @@ void setup_browser(void) newtPushHelpLine(" "); } -void exit_browser(void) +void exit_browser(bool wait_for_ok) { - if (use_browser) + if (use_browser) { + if (wait_for_ok) { + char title[] = "Fatal Error", ok[] = "Ok"; + newtWinMessage(title, ok, browser__last_msg); + } newtFinished(); + } } -- cgit v0.10.2 From 4b4da7f76660ea8b5aa45615165c48f62167ffa8 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Mon, 22 Mar 2010 13:10:26 -0300 Subject: perf probe: Cleanup debuginfo related code Cleanup debuginfo related code to eliminate fragile code which pointed by Ingo (Thanks!). 1) Invert logic of NO_DWARF_SUPPORT to DWARF_SUPPORT. 2) For removing assymetric/local variable ifdefs, introduce more helper functions. 3) Change options order to reduce the number of ifdefs. Reported-by: Ingo Molnar Signed-off-by: Masami Hiramatsu Signed-off-by: Arnaldo Carvalho de Melo Cc: Frederic Weisbecker Cc: Paul Mackerras Cc: Mike Galbraith Cc: Peter Zijlstra LKML-Reference: <1269274229-20442-2-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 0abd25e..c991818 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -506,9 +506,8 @@ endif ifneq ($(shell sh -c "(echo '\#include '; echo '\#include '; echo 'int main(void) { Dwarf *dbg; dbg = dwarf_begin(0, DWARF_C_READ); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/elfutils -ldw -lelf -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y) msg := $(warning No libdw.h found or old libdw.h found, disables dwarf support. Please install elfutils-devel/elfutils-dev); - BASIC_CFLAGS += -DNO_DWARF_SUPPORT else - BASIC_CFLAGS += -I/usr/include/elfutils + BASIC_CFLAGS += -I/usr/include/elfutils -DDWARF_SUPPORT EXTLIBS += -lelf -ldw LIB_OBJS += util/probe-finder.o endif diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index e0dafd9..cf2ffa5 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c @@ -109,7 +109,7 @@ static int opt_del_probe_event(const struct option *opt __used, return 0; } -#ifndef NO_DWARF_SUPPORT +#ifdef DWARF_SUPPORT static int opt_show_lines(const struct option *opt __used, const char *str, int unset __used) { @@ -126,7 +126,7 @@ static const char * const probe_usage[] = { "perf probe [] --add 'PROBEDEF' [--add 'PROBEDEF' ...]", "perf probe [] --del '[GROUP:]EVENT' ...", "perf probe --list", -#ifndef NO_DWARF_SUPPORT +#ifdef DWARF_SUPPORT "perf probe --line 'LINEDESC'", #endif NULL @@ -135,20 +135,16 @@ static const char * const probe_usage[] = { static const struct option options[] = { OPT_BOOLEAN('v', "verbose", &verbose, "be more verbose (show parsed arguments, etc)"), -#ifndef NO_DWARF_SUPPORT - OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, - "file", "vmlinux pathname"), -#endif OPT_BOOLEAN('l', "list", ¶ms.list_events, "list up current probe events"), OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.", opt_del_probe_event), OPT_CALLBACK('a', "add", NULL, -#ifdef NO_DWARF_SUPPORT - "[EVENT=]FUNC[+OFF|%return] [ARG ...]", -#else +#ifdef DWARF_SUPPORT "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT" " [ARG ...]", +#else + "[EVENT=]FUNC[+OFF|%return] [ARG ...]", #endif "probe point definition, where\n" "\t\tGROUP:\tGroup name (optional)\n" @@ -156,23 +152,25 @@ static const struct option options[] = { "\t\tFUNC:\tFunction name\n" "\t\tOFF:\tOffset from function entry (in byte)\n" "\t\t%return:\tPut the probe at function return\n" -#ifdef NO_DWARF_SUPPORT - "\t\tARG:\tProbe argument (only \n" -#else +#ifdef DWARF_SUPPORT "\t\tSRC:\tSource code path\n" "\t\tRL:\tRelative line number from function entry.\n" "\t\tAL:\tAbsolute line number in file.\n" "\t\tPT:\tLazy expression of line code.\n" "\t\tARG:\tProbe argument (local variable name or\n" -#endif "\t\t\tkprobe-tracer argument format.)\n", +#else + "\t\tARG:\tProbe argument (kprobe-tracer argument format.)\n", +#endif opt_add_probe_event), OPT_BOOLEAN('f', "force", ¶ms.force_add, "forcibly add events" " with existing name"), -#ifndef NO_DWARF_SUPPORT +#ifdef DWARF_SUPPORT OPT_CALLBACK('L', "line", NULL, "FUNC[:RLN[+NUM|:RLN2]]|SRC:ALN[+NUM|:ALN2]", "Show source code lines.", opt_show_lines), + OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, + "file", "vmlinux pathname"), #endif OPT__DRY_RUN(&probe_event_dry_run), OPT_END() @@ -211,7 +209,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) return 0; } -#ifndef NO_DWARF_SUPPORT +#ifdef DWARF_SUPPORT if (params.show_lines) { if (params.nevents != 0 || params.dellist) { pr_warning(" Error: Don't use --line with" diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index c6603f3..3fc0be7 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -42,7 +42,8 @@ #include "color.h" #include "symbol.h" #include "thread.h" -#include "parse-events.h" /* For debugfs_path */ +#include "trace-event.h" /* For __unused */ +#include "parse-events.h" /* For debugfs_path */ #include "probe-event.h" #include "probe-finder.h" @@ -70,10 +71,11 @@ static int e_snprintf(char *str, size_t size, const char *format, ...) return ret; } +static char *synthesize_perf_probe_point(struct perf_probe_point *pp); static struct map_groups kmap_groups; static struct map *kmaps[MAP__NR_TYPES]; -/* Initialize symbol maps for vmlinux */ +/* Initialize symbol maps and path of vmlinux */ static void init_vmlinux(void) { symbol_conf.sort_by_name = true; @@ -89,7 +91,7 @@ static void init_vmlinux(void) die("Failed to create kernel maps."); } -#ifndef NO_DWARF_SUPPORT +#ifdef DWARF_SUPPORT static int open_vmlinux(void) { if (map__load(kmaps[MAP__FUNCTION], NULL) < 0) { @@ -99,6 +101,176 @@ static int open_vmlinux(void) pr_debug("Try to open %s\n", kmaps[MAP__FUNCTION]->dso->long_name); return open(kmaps[MAP__FUNCTION]->dso->long_name, O_RDONLY); } + +static void convert_to_perf_probe_point(struct kprobe_trace_point *tp, + struct perf_probe_point *pp) +{ + struct symbol *sym; + int fd, ret = 0; + + sym = map__find_symbol_by_name(kmaps[MAP__FUNCTION], + tp->symbol, NULL); + if (sym) { + fd = open_vmlinux(); + ret = find_perf_probe_point(fd, sym->start + tp->offset, pp); + close(fd); + } + if (ret <= 0) { + pp->function = xstrdup(tp->symbol); + pp->offset = tp->offset; + } + pp->retprobe = tp->retprobe; +} + +/* Try to find perf_probe_event with debuginfo */ +static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev, + struct kprobe_trace_event **tevs) +{ + bool need_dwarf = perf_probe_event_need_dwarf(pev); + int fd, ntevs; + + fd = open_vmlinux(); + if (fd < 0) { + if (need_dwarf) + die("Could not open debuginfo file."); + + pr_debug("Could not open vmlinux. Try to use symbols.\n"); + return 0; + } + + /* Searching trace events corresponding to probe event */ + ntevs = find_kprobe_trace_events(fd, pev, tevs); + close(fd); + + if (ntevs > 0) /* Succeeded to find trace events */ + return ntevs; + + if (ntevs == 0) /* No error but failed to find probe point. */ + die("Probe point '%s' not found. - probe not added.", + synthesize_perf_probe_point(&pev->point)); + + /* Error path */ + if (need_dwarf) { + if (ntevs == -ENOENT) + pr_warning("No dwarf info found in the vmlinux - " + "please rebuild with CONFIG_DEBUG_INFO=y.\n"); + die("Could not analyze debuginfo."); + } + pr_debug("An error occurred in debuginfo analysis." + " Try to use symbols.\n"); + return 0; + +} + +#define LINEBUF_SIZE 256 +#define NR_ADDITIONAL_LINES 2 + +static void show_one_line(FILE *fp, unsigned int l, bool skip, bool show_num) +{ + char buf[LINEBUF_SIZE]; + const char *color = PERF_COLOR_BLUE; + + if (fgets(buf, LINEBUF_SIZE, fp) == NULL) + goto error; + if (!skip) { + if (show_num) + fprintf(stdout, "%7u %s", l, buf); + else + color_fprintf(stdout, color, " %s", buf); + } + + while (strlen(buf) == LINEBUF_SIZE - 1 && + buf[LINEBUF_SIZE - 2] != '\n') { + if (fgets(buf, LINEBUF_SIZE, fp) == NULL) + goto error; + if (!skip) { + if (show_num) + fprintf(stdout, "%s", buf); + else + color_fprintf(stdout, color, "%s", buf); + } + } + return; +error: + if (feof(fp)) + die("Source file is shorter than expected."); + else + die("File read error: %s", strerror(errno)); +} + +/* + * Show line-range always requires debuginfo to find source file and + * line number. + */ +void show_line_range(struct line_range *lr) +{ + unsigned int l = 1; + struct line_node *ln; + FILE *fp; + int fd, ret; + + /* Search a line range */ + init_vmlinux(); + fd = open_vmlinux(); + if (fd < 0) + die("Could not open debuginfo file."); + ret = find_line_range(fd, lr); + if (ret <= 0) + die("Source line is not found.\n"); + close(fd); + + setup_pager(); + + if (lr->function) + fprintf(stdout, "<%s:%d>\n", lr->function, + lr->start - lr->offset); + else + fprintf(stdout, "<%s:%d>\n", lr->file, lr->start); + + fp = fopen(lr->path, "r"); + if (fp == NULL) + die("Failed to open %s: %s", lr->path, strerror(errno)); + /* Skip to starting line number */ + while (l < lr->start) + show_one_line(fp, l++, true, false); + + list_for_each_entry(ln, &lr->line_list, list) { + while (ln->line > l) + show_one_line(fp, (l++) - lr->offset, false, false); + show_one_line(fp, (l++) - lr->offset, false, true); + } + + if (lr->end == INT_MAX) + lr->end = l + NR_ADDITIONAL_LINES; + while (l < lr->end && !feof(fp)) + show_one_line(fp, (l++) - lr->offset, false, false); + + fclose(fp); +} + +#else /* !DWARF_SUPPORT */ + +static void convert_to_perf_probe_point(struct kprobe_trace_point *tp, + struct perf_probe_point *pp) +{ + pp->function = xstrdup(tp->symbol); + pp->offset = tp->offset; + pp->retprobe = tp->retprobe; +} + +static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev, + struct kprobe_trace_event **tevs __unused) +{ + if (perf_probe_event_need_dwarf(pev)) + die("Debuginfo-analysis is not supported"); + return 0; +} + +void show_line_range(struct line_range *lr __unused) +{ + die("Debuginfo-analysis is not supported"); +} + #endif void parse_line_range_desc(const char *arg, struct line_range *lr) @@ -592,32 +764,14 @@ void convert_to_perf_probe_event(struct kprobe_trace_event *tev, { char buf[64]; int i; -#ifndef NO_DWARF_SUPPORT - struct symbol *sym; - int fd, ret = 0; - - sym = map__find_symbol_by_name(kmaps[MAP__FUNCTION], - tev->point.symbol, NULL); - if (sym) { - fd = open_vmlinux(); - ret = find_perf_probe_point(fd, sym->start + tev->point.offset, - &pev->point); - close(fd); - } - if (ret <= 0) { - pev->point.function = xstrdup(tev->point.symbol); - pev->point.offset = tev->point.offset; - } -#else - /* Convert trace_point to probe_point */ - pev->point.function = xstrdup(tev->point.symbol); - pev->point.offset = tev->point.offset; -#endif - pev->point.retprobe = tev->point.retprobe; + /* Convert event/group name */ pev->event = xstrdup(tev->event); pev->group = xstrdup(tev->group); + /* Convert trace_point to probe_point */ + convert_to_perf_probe_point(&tev->point, &pev->point); + /* Convert trace_arg to probe_arg */ pev->nargs = tev->nargs; pev->args = xzalloc(sizeof(struct perf_probe_arg) * pev->nargs); @@ -944,52 +1098,13 @@ static int convert_to_kprobe_trace_events(struct perf_probe_event *pev, struct kprobe_trace_event **tevs) { struct symbol *sym; - bool need_dwarf; -#ifndef NO_DWARF_SUPPORT - int fd; -#endif int ntevs = 0, i; struct kprobe_trace_event *tev; - need_dwarf = perf_probe_event_need_dwarf(pev); - - if (need_dwarf) -#ifdef NO_DWARF_SUPPORT - die("Debuginfo-analysis is not supported"); -#else /* !NO_DWARF_SUPPORT */ - pr_debug("Some probes require debuginfo.\n"); - - fd = open_vmlinux(); - if (fd < 0) { - if (need_dwarf) - die("Could not open debuginfo file."); - - pr_debug("Could not open vmlinux/module file." - " Try to use symbols.\n"); - goto end_dwarf; - } - - /* Searching probe points */ - ntevs = find_kprobe_trace_events(fd, pev, tevs); - - if (ntevs > 0) /* Found */ - goto found; - - if (ntevs == 0) /* No error but failed to find probe point. */ - die("Probe point '%s' not found. - probe not added.", - synthesize_perf_probe_point(&pev->point)); - - /* Error path */ - if (need_dwarf) { - if (ntevs == -ENOENT) - pr_warning("No dwarf info found in the vmlinux - please rebuild with CONFIG_DEBUG_INFO=y.\n"); - die("Could not analyze debuginfo."); - } - pr_debug("An error occurred in debuginfo analysis." - " Try to use symbols.\n"); - -end_dwarf: -#endif /* !NO_DWARF_SUPPORT */ + /* Convert perf_probe_event with debuginfo */ + ntevs = try_to_find_kprobe_trace_events(pev, tevs); + if (ntevs > 0) + return ntevs; /* Allocate trace event buffer */ ntevs = 1; @@ -1012,10 +1127,7 @@ end_dwarf: if (!sym) die("Kernel symbol \'%s\' not found - probe not added.", tev->point.symbol); -#ifndef NO_DWARF_SUPPORT -found: - close(fd); -#endif + return ntevs; } @@ -1133,90 +1245,3 @@ void del_perf_probe_events(struct strlist *dellist) close(fd); } -#define LINEBUF_SIZE 256 -#define NR_ADDITIONAL_LINES 2 - -static void show_one_line(FILE *fp, unsigned int l, bool skip, bool show_num) -{ - char buf[LINEBUF_SIZE]; - const char *color = PERF_COLOR_BLUE; - - if (fgets(buf, LINEBUF_SIZE, fp) == NULL) - goto error; - if (!skip) { - if (show_num) - fprintf(stdout, "%7u %s", l, buf); - else - color_fprintf(stdout, color, " %s", buf); - } - - while (strlen(buf) == LINEBUF_SIZE - 1 && - buf[LINEBUF_SIZE - 2] != '\n') { - if (fgets(buf, LINEBUF_SIZE, fp) == NULL) - goto error; - if (!skip) { - if (show_num) - fprintf(stdout, "%s", buf); - else - color_fprintf(stdout, color, "%s", buf); - } - } - return; -error: - if (feof(fp)) - die("Source file is shorter than expected."); - else - die("File read error: %s", strerror(errno)); -} - -void show_line_range(struct line_range *lr) -{ - unsigned int l = 1; - struct line_node *ln; - FILE *fp; -#ifndef NO_DWARF_SUPPORT - int fd, ret; -#endif - - /* Search a line range */ - init_vmlinux(); -#ifndef NO_DWARF_SUPPORT - fd = open_vmlinux(); - if (fd < 0) - die("Could not open debuginfo file."); - ret = find_line_range(fd, lr); - if (ret <= 0) - die("Source line is not found.\n"); - close(fd); -#endif - - setup_pager(); - - if (lr->function) - fprintf(stdout, "<%s:%d>\n", lr->function, - lr->start - lr->offset); - else - fprintf(stdout, "<%s:%d>\n", lr->file, lr->start); - - fp = fopen(lr->path, "r"); - if (fp == NULL) - die("Failed to open %s: %s", lr->path, strerror(errno)); - /* Skip to starting line number */ - while (l < lr->start) - show_one_line(fp, l++, true, false); - - list_for_each_entry(ln, &lr->line_list, list) { - while (ln->line > l) - show_one_line(fp, (l++) - lr->offset, false, false); - show_one_line(fp, (l++) - lr->offset, false, true); - } - - if (lr->end == INT_MAX) - lr->end = l + NR_ADDITIONAL_LINES; - while (l < lr->end && !feof(fp)) - show_one_line(fp, (l++) - lr->offset, false, false); - - fclose(fp); -} - - diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h index 2f2307d..3564f22 100644 --- a/tools/perf/util/probe-finder.h +++ b/tools/perf/util/probe-finder.h @@ -15,7 +15,7 @@ static inline int is_c_varname(const char *name) return isalpha(name[0]) || name[0] == '_'; } -#ifndef NO_DWARF_SUPPORT +#ifdef DWARF_SUPPORT /* Find kprobe_trace_events specified by perf_probe_event from debuginfo */ extern int find_kprobe_trace_events(int fd, struct perf_probe_event *pev, struct kprobe_trace_event **tevs); @@ -57,6 +57,6 @@ struct line_finder { int found; }; -#endif /* NO_DWARF_SUPPORT */ +#endif /* DWARF_SUPPORT */ #endif /*_PROBE_FINDER_H */ -- cgit v0.10.2 From ca721e45b39209415d2288dbac3667b26d9d1def Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Mon, 22 Mar 2010 13:10:27 -0300 Subject: perf probe: Add NO_DWARF make option Add NO_DWARF make option for testing build without libdw. Signed-off-by: Masami Hiramatsu Signed-off-by: Arnaldo Carvalho de Melo Cc: Frederic Weisbecker Cc: Paul Mackerras Cc: Mike Galbraith Cc: Peter Zijlstra LKML-Reference: <1269274229-20442-3-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar diff --git a/tools/perf/Makefile b/tools/perf/Makefile index c991818..6903645 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -150,6 +150,8 @@ all:: # Define LDFLAGS=-static to build a static binary. # # Define EXTRA_CFLAGS=-m64 or EXTRA_CFLAGS=-m32 as appropriate for cross-builds. +# +# Define NO_DWARF if you do not want debug-info analysis feature at all. PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE @$(SHELL_PATH) util/PERF-VERSION-GEN @@ -507,10 +509,12 @@ endif ifneq ($(shell sh -c "(echo '\#include '; echo '\#include '; echo 'int main(void) { Dwarf *dbg; dbg = dwarf_begin(0, DWARF_C_READ); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/elfutils -ldw -lelf -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y) msg := $(warning No libdw.h found or old libdw.h found, disables dwarf support. Please install elfutils-devel/elfutils-dev); else +ifndef NO_DWARF BASIC_CFLAGS += -I/usr/include/elfutils -DDWARF_SUPPORT EXTLIBS += -lelf -ldw LIB_OBJS += util/probe-finder.o endif +endif ifneq ($(shell sh -c "(echo '\#include '; echo 'int main(void) { newtInit(); newtCls(); return newtFinished(); }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -lnewt -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y) msg := $(warning newt not found, disables TUI support. Please install newt-devel or libnewt-dev); -- cgit v0.10.2 From 084ab9f862416b2ddb4bb9804884de19bf09774d Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 22 Mar 2010 13:10:28 -0300 Subject: perf stat: Better report failure to collect system wide stats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before: [acme@doppio linux-2.6-tip]$ perf stat -a sleep 1s Performance counter stats for 'sleep 1s': task-clock-msecs context-switches CPU-migrations page-faults cycles instructions branches branch-misses cache-references cache-misses 1.016998463 seconds time elapsed [acme@doppio linux-2.6-tip]$ Now: [acme@doppio linux-2.6-tip]$ perf stat -a sleep 1s No permission to collect system-wide stats. Consider tweaking /proc/sys/kernel/perf_event_paranoid. [acme@doppio linux-2.6-tip]$ Reported-by: Ingo Molnar Signed-off-by: Arnaldo Carvalho de Melo Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: <1269274229-20442-4-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index c92f90f..1036ca7 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -144,10 +144,11 @@ struct stats runtime_branches_stats; #define ERR_PERF_OPEN \ "Error: counter %d, sys_perf_event_open() syscall returned with %d (%s)\n" -static void create_perf_stat_counter(int counter) +static int create_perf_stat_counter(int counter) { struct perf_event_attr *attr = attrs + counter; int thread; + int ncreated = 0; if (scale) attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | @@ -159,9 +160,11 @@ static void create_perf_stat_counter(int counter) for (cpu = 0; cpu < nr_cpus; cpu++) { fd[cpu][counter][0] = sys_perf_event_open(attr, -1, cpumap[cpu], -1, 0); - if (fd[cpu][counter][0] < 0 && verbose) - fprintf(stderr, ERR_PERF_OPEN, counter, - fd[cpu][counter][0], strerror(errno)); + if (fd[cpu][counter][0] < 0) + pr_debug(ERR_PERF_OPEN, counter, + fd[cpu][counter][0], strerror(errno)); + else + ++ncreated; } } else { attr->inherit = inherit; @@ -172,12 +175,16 @@ static void create_perf_stat_counter(int counter) for (thread = 0; thread < thread_num; thread++) { fd[0][counter][thread] = sys_perf_event_open(attr, all_tids[thread], -1, -1, 0); - if (fd[0][counter][thread] < 0 && verbose) - fprintf(stderr, ERR_PERF_OPEN, counter, - fd[0][counter][thread], - strerror(errno)); + if (fd[0][counter][thread] < 0) + pr_debug(ERR_PERF_OPEN, counter, + fd[0][counter][thread], + strerror(errno)); + else + ++ncreated; } } + + return ncreated; } /* @@ -264,7 +271,7 @@ static int run_perf_stat(int argc __used, const char **argv) { unsigned long long t0, t1; int status = 0; - int counter; + int counter, ncreated = 0; int child_ready_pipe[2], go_pipe[2]; const bool forks = (argc > 0); char buf; @@ -324,7 +331,16 @@ static int run_perf_stat(int argc __used, const char **argv) } for (counter = 0; counter < nr_counters; counter++) - create_perf_stat_counter(counter); + ncreated += create_perf_stat_counter(counter); + + if (ncreated == 0) { + pr_err("No permission to collect %sstats.\n" + "Consider tweaking /proc/sys/kernel/perf_event_paranoid.\n", + system_wide ? "system-wide " : ""); + if (child_pid != -1) + kill(child_pid, SIGTERM); + return -1; + } /* * Enable counters and exec the command: @@ -587,7 +603,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used) status = run_perf_stat(argc, argv); } - print_stat(argc, argv); + if (status != -1) + print_stat(argc, argv); return status; } -- cgit v0.10.2 From 478b0973bf8c90db3677fbb8d812e2bdefc43d9b Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 22 Mar 2010 13:10:29 -0300 Subject: perf tools: Exit browser before printing usage when unkown option passed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If not the screen will get garbled when using newt. Signed-off-by: Arnaldo Carvalho de Melo Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: <1269274229-20442-5-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c index efebd5b..79dfa0c 100644 --- a/tools/perf/util/parse-options.c +++ b/tools/perf/util/parse-options.c @@ -500,6 +500,7 @@ int usage_with_options_internal(const char * const *usagestr, void usage_with_options(const char * const *usagestr, const struct option *opts) { + exit_browser(false); usage_with_options_internal(usagestr, opts, 0); exit(129); } -- cgit v0.10.2 From 4ded2b250f1fbba4e414d17dc55ee513485c0aa1 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 22 Mar 2010 17:52:49 -0300 Subject: perf report: Implement Newt callgraphs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Starts collapsed, allows annotating by pressing 'A' or 'a' on the symbol, be it the top level one or any of the symbols in the chains. It (ab)uses the only tree widget in newt, that is actually a checkbox tree that we use with just one option ('.'), end result is usable but we really need to create a custom widget tree so that we can use the data structures we have (hist_entry rb_tree + callchain rb_tree + lists), so that we reduce the memory footprint by not creating a mirror set of data structures in the newtCheckboxTree widget. Thanks to Frédéric Weisbacker for fixing the orphanage problem in 301fde2, without that we were tripping a newt bug (fix already sent to newt's maintainer). Signed-off-by: Arnaldo Carvalho de Melo Cc: Avi Kivity Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: <1269291169-29820-1-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index 3c2ef95..12b229b 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -28,11 +28,197 @@ static newtComponent newt_form__new(void) return self; } +/* + * When debugging newt problems it was useful to be able to "unroll" + * the calls to newtCheckBoxTreeAdd{Array,Item}, so that we can generate + * a source file with the sequence of calls to these methods, to then + * tweak the arrays to get the intended results, so I'm keeping this code + * here, may be useful again in the future. + */ +#undef NEWT_DEBUG + +static void newt_checkbox_tree__add(newtComponent tree, const char *str, + void *priv, int *indexes) +{ +#ifdef NEWT_DEBUG + /* Print the newtCheckboxTreeAddArray to tinker with its index arrays */ + int i = 0, len = 40 - strlen(str); + + fprintf(stderr, + "\tnewtCheckboxTreeAddItem(tree, %*.*s\"%s\", (void *)%p, 0, ", + len, len, " ", str, priv); + while (indexes[i] != NEWT_ARG_LAST) { + if (indexes[i] != NEWT_ARG_APPEND) + fprintf(stderr, " %d,", indexes[i]); + else + fprintf(stderr, " %s,", "NEWT_ARG_APPEND"); + ++i; + } + fprintf(stderr, " %s", " NEWT_ARG_LAST);\n"); + fflush(stderr); +#endif + newtCheckboxTreeAddArray(tree, str, priv, 0, indexes); +} + +static char *callchain_list__sym_name(struct callchain_list *self, + char *bf, size_t bfsize) +{ + if (self->sym) + return self->sym->name; + + snprintf(bf, bfsize, "%#Lx", self->ip); + return bf; +} + +static void __callchain__append_graph_browser(struct callchain_node *self, + newtComponent tree, u64 total, + int *indexes, int depth) +{ + struct rb_node *node; + u64 new_total, remaining; + int idx = 0; + + if (callchain_param.mode == CHAIN_GRAPH_REL) + new_total = self->children_hit; + else + new_total = total; + + remaining = new_total; + node = rb_first(&self->rb_root); + while (node) { + struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node); + struct rb_node *next = rb_next(node); + u64 cumul = cumul_hits(child); + struct callchain_list *chain; + int first = true, printed = 0; + int chain_idx = -1; + remaining -= cumul; + + indexes[depth] = NEWT_ARG_APPEND; + indexes[depth + 1] = NEWT_ARG_LAST; + + list_for_each_entry(chain, &child->val, list) { + char ipstr[BITS_PER_LONG / 4 + 1], + *alloc_str = NULL; + const char *str = callchain_list__sym_name(chain, ipstr, sizeof(ipstr)); + + if (first) { + double percent = cumul * 100.0 / new_total; + + first = false; + if (asprintf(&alloc_str, "%2.2f%% %s", percent, str) < 0) + str = "Not enough memory!"; + else + str = alloc_str; + } else { + indexes[depth] = idx; + indexes[depth + 1] = NEWT_ARG_APPEND; + indexes[depth + 2] = NEWT_ARG_LAST; + ++chain_idx; + } + newt_checkbox_tree__add(tree, str, chain->sym, indexes); + free(alloc_str); + ++printed; + } + + indexes[depth] = idx; + if (chain_idx != -1) + indexes[depth + 1] = chain_idx; + if (printed != 0) + ++idx; + __callchain__append_graph_browser(child, tree, new_total, indexes, + depth + (chain_idx != -1 ? 2 : 1)); + node = next; + } +} + +static void callchain__append_graph_browser(struct callchain_node *self, + newtComponent tree, u64 total, + int *indexes, int parent_idx) +{ + struct callchain_list *chain; + int i = 0; + + indexes[1] = NEWT_ARG_APPEND; + indexes[2] = NEWT_ARG_LAST; + + list_for_each_entry(chain, &self->val, list) { + char ipstr[BITS_PER_LONG / 4 + 1], *str; + + if (chain->ip >= PERF_CONTEXT_MAX) + continue; + + if (!i++ && sort__first_dimension == SORT_SYM) + continue; + + str = callchain_list__sym_name(chain, ipstr, sizeof(ipstr)); + newt_checkbox_tree__add(tree, str, chain->sym, indexes); + } + + indexes[1] = parent_idx; + indexes[2] = NEWT_ARG_APPEND; + indexes[3] = NEWT_ARG_LAST; + __callchain__append_graph_browser(self, tree, total, indexes, 2); +} + +static void hist_entry__append_callchain_browser(struct hist_entry *self, + newtComponent tree, u64 total, int parent_idx) +{ + struct rb_node *rb_node; + int indexes[1024] = { [0] = parent_idx, }; + int idx = 0; + struct callchain_node *chain; + + rb_node = rb_first(&self->sorted_chain); + while (rb_node) { + chain = rb_entry(rb_node, struct callchain_node, rb_node); + switch (callchain_param.mode) { + case CHAIN_FLAT: + break; + case CHAIN_GRAPH_ABS: /* falldown */ + case CHAIN_GRAPH_REL: + callchain__append_graph_browser(chain, tree, total, indexes, idx++); + break; + case CHAIN_NONE: + default: + break; + } + rb_node = rb_next(rb_node); + } +} + +/* + * FIXME: get lib/string.c linked with perf somehow + */ +static char *skip_spaces(const char *str) +{ + while (isspace(*str)) + ++str; + return (char *)str; +} + +static char *strim(char *s) +{ + size_t size; + char *end; + + s = skip_spaces(s); + size = strlen(s); + if (!size) + return s; + + end = s + size - 1; + while (end >= s && isspace(*end)) + end--; + *(end + 1) = '\0'; + + return s; +} + static size_t hist_entry__append_browser(struct hist_entry *self, - newtComponent listbox, u64 total) + newtComponent tree, u64 total) { - char bf[1024]; - size_t len; + char bf[1024], *s; FILE *fp; if (symbol_conf.exclude_other && !self->parent) @@ -42,28 +228,46 @@ static size_t hist_entry__append_browser(struct hist_entry *self, if (fp == NULL) return 0; - len = hist_entry__fprintf(self, NULL, false, 0, fp, total); - + hist_entry__fprintf(self, NULL, false, 0, fp, total); fclose(fp); - newtListboxAppendEntry(listbox, bf, self); - return len; + + /* + * FIXME: We shouldn't need to trim, as the printing routines shouldn't + * add spaces it in the first place, the stdio output routines should + * call a __snprintf method instead of the current __print (that + * actually is a __fprintf) one, but get the raw string and _then_ add + * the newline, as this is a detail of stdio printing, not needed in + * other UIs, e.g. newt. + */ + s = strim(bf); + + if (symbol_conf.use_callchain) { + int indexes[2]; + + indexes[0] = NEWT_ARG_APPEND; + indexes[1] = NEWT_ARG_LAST; + newt_checkbox_tree__add(tree, s, self->sym, indexes); + } else + newtListboxAppendEntry(tree, s, self->sym); + + return strlen(s); } -static void hist_entry__annotate_browser(struct hist_entry *self) +static void symbol__annotate_browser(const struct symbol *self) { FILE *fp; int cols, rows; - newtComponent form, listbox; + newtComponent form, tree; struct newtExitStruct es; char *str; size_t line_len, max_line_len = 0; size_t max_usable_width; char *line = NULL; - if (self->sym == NULL) + if (self == NULL) return; - if (asprintf(&str, "perf annotate %s 2>&1 | expand", self->sym->name) < 0) + if (asprintf(&str, "perf annotate %s 2>&1 | expand", self->name) < 0) return; fp = popen(str, "r"); @@ -72,7 +276,7 @@ static void hist_entry__annotate_browser(struct hist_entry *self) newtPushHelpLine("Press ESC to exit"); newtGetScreenSize(&cols, &rows); - listbox = newtListbox(0, 0, rows - 5, NEWT_FLAG_SCROLL); + tree = newtListbox(0, 0, rows - 5, NEWT_FLAG_SCROLL); while (!feof(fp)) { if (getline(&line, &line_len, fp) < 0 || !line_len) @@ -82,7 +286,7 @@ static void hist_entry__annotate_browser(struct hist_entry *self) if (line_len > max_line_len) max_line_len = line_len; - newtListboxAppendEntry(listbox, line, NULL); + newtListboxAppendEntry(tree, line, NULL); } fclose(fp); free(line); @@ -91,11 +295,11 @@ static void hist_entry__annotate_browser(struct hist_entry *self) if (max_line_len > max_usable_width) max_line_len = max_usable_width; - newtListboxSetWidth(listbox, max_line_len); + newtListboxSetWidth(tree, max_line_len); - newtCenteredWindow(max_line_len + 2, rows - 5, self->sym->name); + newtCenteredWindow(max_line_len + 2, rows - 5, self->name); form = newt_form__new(); - newtFormAddComponents(form, listbox, NULL); + newtFormAddComponents(form, tree, NULL); newtFormRun(form, &es); newtFormDestroy(form); @@ -110,25 +314,27 @@ void perf_session__browse_hists(struct rb_root *hists, u64 session_total, { struct sort_entry *se; struct rb_node *nd; + char seq[] = "."; unsigned int width; char *col_width = symbol_conf.col_width_list_str; - int rows; - size_t max_len = 0; + int rows, cols, idx; + int max_len = 0; char str[1024]; - newtComponent form, listbox; + newtComponent form, tree; struct newtExitStruct es; snprintf(str, sizeof(str), "Samples: %Ld", session_total); newtDrawRootText(0, 0, str); newtPushHelpLine(helpline); - newtGetScreenSize(NULL, &rows); - - form = newt_form__new(); + newtGetScreenSize(&cols, &rows); - listbox = newtListbox(1, 1, rows - 2, (NEWT_FLAG_SCROLL | - NEWT_FLAG_BORDER | - NEWT_FLAG_RETURNEXIT)); + if (symbol_conf.use_callchain) + tree = newtCheckboxTreeMulti(0, 0, rows - 5, seq, + NEWT_FLAG_SCROLL); + else + tree = newtListbox(0, 0, rows - 5, (NEWT_FLAG_SCROLL | + NEWT_FLAG_RETURNEXIT)); list_for_each_entry(se, &hist_entry__sort_list, list) { if (se->elide) @@ -147,27 +353,48 @@ void perf_session__browse_hists(struct rb_root *hists, u64 session_total, } } + idx = 0; for (nd = rb_first(hists); nd; nd = rb_next(nd)) { struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); - size_t len = hist_entry__append_browser(h, listbox, session_total); + int len = hist_entry__append_browser(h, tree, session_total); if (len > max_len) max_len = len; + if (symbol_conf.use_callchain) { + hist_entry__append_callchain_browser(h, tree, session_total, idx++); + if (idx > 3300) + break; + } } - newtListboxSetWidth(listbox, max_len); - newtFormAddComponents(form, listbox, NULL); + if (max_len > cols) + max_len = cols - 3; + + if (!symbol_conf.use_callchain) + newtListboxSetWidth(tree, max_len); + + newtCenteredWindow(max_len + (symbol_conf.use_callchain ? 5 : 0), + rows - 5, "Report"); + form = newt_form__new(); + newtFormAddHotKey(form, 'A'); + newtFormAddHotKey(form, 'a'); + newtFormAddComponents(form, tree, NULL); while (1) { - struct hist_entry *selection; + const struct symbol *selection; newtFormRun(form, &es); - if (es.reason == NEWT_EXIT_HOTKEY) + if (es.reason == NEWT_EXIT_HOTKEY && + toupper(es.u.key) != 'A') break; - selection = newtListboxGetCurrent(listbox); - hist_entry__annotate_browser(selection); + if (!symbol_conf.use_callchain) + selection = newtListboxGetCurrent(tree); + else + selection = newtCheckboxTreeGetCurrent(tree); + symbol__annotate_browser(selection); } newtFormDestroy(form); + newtPopWindow(); } static char browser__last_msg[1024]; -- cgit v0.10.2 From 4bab9d426e6dbd9ea09330919a33d35d5faab400 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 19 Mar 2010 04:46:38 +0000 Subject: dmaengine: shdma: Remove sh_dmae_slave_chan_id enum This patch replaces the sh_dmae_slave_chan_id enum with an unsigned int. The purpose of this chainge is to make it possible to separate the slave id enums from the dmaengine header. The slave id enums varies with processor model, so in the future it makes sense to put these in the processor specific headers together with the pinmux enums. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/include/asm/dmaengine.h b/arch/sh/include/asm/dmaengine.h index bf2f30cf..568e991 100644 --- a/arch/sh/include/asm/dmaengine.h +++ b/arch/sh/include/asm/dmaengine.h @@ -17,7 +17,7 @@ #define SH_DMAC_MAX_CHANNELS 6 -enum sh_dmae_slave_chan_id { +enum { SHDMA_SLAVE_SCIF0_TX, SHDMA_SLAVE_SCIF0_RX, SHDMA_SLAVE_SCIF1_TX, @@ -38,7 +38,7 @@ enum sh_dmae_slave_chan_id { }; struct sh_dmae_slave_config { - enum sh_dmae_slave_chan_id slave_id; + unsigned int slave_id; dma_addr_t addr; u32 chcr; char mid_rid; @@ -68,7 +68,7 @@ struct device; /* Used by slave DMA clients to request DMA to/from a specific peripheral */ struct sh_dmae_slave { - enum sh_dmae_slave_chan_id slave_id; /* Set by the platform */ + unsigned int slave_id; /* Set by the platform */ struct device *dma_dev; /* Set by the platform */ struct sh_dmae_slave_config *config; /* Set by the driver */ }; diff --git a/arch/sh/include/asm/siu.h b/arch/sh/include/asm/siu.h index f1b1e69..e8d4142 100644 --- a/arch/sh/include/asm/siu.h +++ b/arch/sh/include/asm/siu.h @@ -17,10 +17,10 @@ struct device; struct siu_platform { struct device *dma_dev; - enum sh_dmae_slave_chan_id dma_slave_tx_a; - enum sh_dmae_slave_chan_id dma_slave_rx_a; - enum sh_dmae_slave_chan_id dma_slave_tx_b; - enum sh_dmae_slave_chan_id dma_slave_rx_b; + unsigned int dma_slave_tx_a; + unsigned int dma_slave_rx_a; + unsigned int dma_slave_tx_b; + unsigned int dma_slave_rx_b; }; #endif /* ASM_SIU_H */ diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index 5d17e09..e5588f4 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c @@ -266,7 +266,7 @@ static struct sh_desc *sh_dmae_get_desc(struct sh_dmae_chan *sh_chan) } static struct sh_dmae_slave_config *sh_dmae_find_slave( - struct sh_dmae_chan *sh_chan, enum sh_dmae_slave_chan_id slave_id) + struct sh_dmae_chan *sh_chan, struct sh_dmae_slave *param) { struct dma_device *dma_dev = sh_chan->common.device; struct sh_dmae_device *shdev = container_of(dma_dev, @@ -274,11 +274,11 @@ static struct sh_dmae_slave_config *sh_dmae_find_slave( struct sh_dmae_pdata *pdata = shdev->pdata; int i; - if ((unsigned)slave_id >= SHDMA_SLAVE_NUMBER) + if (param->slave_id >= SHDMA_SLAVE_NUMBER) return NULL; for (i = 0; i < pdata->slave_num; i++) - if (pdata->slave[i].slave_id == slave_id) + if (pdata->slave[i].slave_id == param->slave_id) return pdata->slave + i; return NULL; @@ -299,7 +299,7 @@ static int sh_dmae_alloc_chan_resources(struct dma_chan *chan) if (param) { struct sh_dmae_slave_config *cfg; - cfg = sh_dmae_find_slave(sh_chan, param->slave_id); + cfg = sh_dmae_find_slave(sh_chan, param); if (!cfg) return -EINVAL; diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index f7b9aff..2d9a06d 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -90,8 +90,8 @@ struct sci_port { struct dma_chan *chan_rx; #ifdef CONFIG_SERIAL_SH_SCI_DMA struct device *dma_dev; - enum sh_dmae_slave_chan_id slave_tx; - enum sh_dmae_slave_chan_id slave_rx; + unsigned int slave_tx; + unsigned int slave_rx; struct dma_async_tx_descriptor *desc_tx; struct dma_async_tx_descriptor *desc_rx[2]; dma_cookie_t cookie_tx; diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h index 193d4bf..f5364a1 100644 --- a/include/linux/serial_sci.h +++ b/include/linux/serial_sci.h @@ -33,8 +33,8 @@ struct plat_sci_port { char *clk; /* clock string */ struct device *dma_dev; #ifdef CONFIG_SERIAL_SH_SCI_DMA - enum sh_dmae_slave_chan_id dma_slave_tx; - enum sh_dmae_slave_chan_id dma_slave_rx; + unsigned int dma_slave_tx; + unsigned int dma_slave_rx; #endif }; -- cgit v0.10.2 From 02ca5083f60521d09f13224596564a405108bc4c Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 19 Mar 2010 04:46:47 +0000 Subject: dmaengine: shdma: Common SH_DMA_SLAVE_NUMBER Move SHDMA_SLAVE_NUMBER from asm/dmaengine.h to shdma.h. Set it to 256 to support a wide range of processors. The amount of memory consumed by this change is limited to 256 bits. While at it, rename to SH_DMA_SLAVE_NUMBER to match with the rest of the file. Signed-off-by: Magnus Damm Acked-by: Guennadi Liakhovetski Signed-off-by: Paul Mundt diff --git a/arch/sh/include/asm/dmaengine.h b/arch/sh/include/asm/dmaengine.h index 568e991..abb8d66 100644 --- a/arch/sh/include/asm/dmaengine.h +++ b/arch/sh/include/asm/dmaengine.h @@ -34,7 +34,6 @@ enum { SHDMA_SLAVE_SIUA_RX, SHDMA_SLAVE_SIUB_TX, SHDMA_SLAVE_SIUB_RX, - SHDMA_SLAVE_NUMBER, /* Must stay last */ }; struct sh_dmae_slave_config { diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index e5588f4..8360538 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c @@ -44,7 +44,7 @@ enum sh_dmae_desc_status { #define LOG2_DEFAULT_XFER_SIZE 2 /* A bitmask with bits enough for enum sh_dmae_slave_chan_id */ -static unsigned long sh_dmae_slave_used[BITS_TO_LONGS(SHDMA_SLAVE_NUMBER)]; +static unsigned long sh_dmae_slave_used[BITS_TO_LONGS(SH_DMA_SLAVE_NUMBER)]; static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all); @@ -274,7 +274,7 @@ static struct sh_dmae_slave_config *sh_dmae_find_slave( struct sh_dmae_pdata *pdata = shdev->pdata; int i; - if (param->slave_id >= SHDMA_SLAVE_NUMBER) + if (param->slave_id >= SH_DMA_SLAVE_NUMBER) return NULL; for (i = 0; i < pdata->slave_num; i++) diff --git a/drivers/dma/shdma.h b/drivers/dma/shdma.h index 153609a..d7ddf6f 100644 --- a/drivers/dma/shdma.h +++ b/drivers/dma/shdma.h @@ -19,6 +19,7 @@ #include +#define SH_DMA_SLAVE_NUMBER 256 #define SH_DMA_TCR_MAX 0x00FFFFFF /* 16MB */ struct device; -- cgit v0.10.2 From f354a38175f5219146f4675dca770e114cf3c502 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 19 Mar 2010 04:47:01 +0000 Subject: serial: sh-sci: Use sg_dma_len() and sg_dma_address() Convert the dmaengine code in sh-sci.c from directly accessing the struct scatterlist members length, dma_length and dma_address to using the macros sg_dma_len() and sg_dma_address(). Makes the code build for ARM. Signed-off-by: Magnus Damm Acked-by: Guennadi Liakhovetski Signed-off-by: Paul Mundt diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 2d9a06d..cd52dd6 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -916,10 +916,10 @@ static void sci_dma_tx_complete(void *arg) spin_lock_irqsave(&port->lock, flags); - xmit->tail += s->sg_tx.length; + xmit->tail += sg_dma_len(&s->sg_tx); xmit->tail &= UART_XMIT_SIZE - 1; - port->icount.tx += s->sg_tx.length; + port->icount.tx += sg_dma_len(&s->sg_tx); async_tx_ack(s->desc_tx); s->cookie_tx = -EINVAL; @@ -1134,14 +1134,13 @@ static void work_fn_tx(struct work_struct *work) */ spin_lock_irq(&port->lock); sg->offset = xmit->tail & (UART_XMIT_SIZE - 1); - sg->dma_address = (sg_dma_address(sg) & ~(UART_XMIT_SIZE - 1)) + + sg_dma_address(sg) = (sg_dma_address(sg) & ~(UART_XMIT_SIZE - 1)) + sg->offset; - sg->length = min((int)CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE), + sg_dma_len(sg) = min((int)CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE), CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE)); - sg->dma_length = sg->length; spin_unlock_irq(&port->lock); - BUG_ON(!sg->length); + BUG_ON(!sg_dma_len(sg)); desc = chan->device->device_prep_slave_sg(chan, sg, s->sg_len_tx, DMA_TO_DEVICE, @@ -1342,8 +1341,7 @@ static void sci_request_dma(struct uart_port *port) sg_init_table(sg, 1); sg_set_page(sg, virt_to_page(buf[i]), s->buf_len_rx, (int)buf[i] & ~PAGE_MASK); - sg->dma_address = dma[i]; - sg->dma_length = sg->length; + sg_dma_address(sg) = dma[i]; } INIT_WORK(&s->work_rx, work_fn_rx); -- cgit v0.10.2 From b2623a61cfd3c6badb8396dc85ab5a70f4a05f61 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 19 Mar 2010 04:47:10 +0000 Subject: dmaengine: shdma: Introduce include/linux/sh_dma.h Create a common platform data header file for the shdma dmaengine driver. This is done by moving common structures from sh asm/dmaengine.h to linux/sh_dma.h. DMA registers are also copied from sh asm/dma-register.h to make the code architecture independent. The sh header file asm/dmaengine.h is still kept with the slave id enum. This allows us to keep the old processor specific code as is and slowly move over to slave id enums in per-processor headers. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/include/asm/dmaengine.h b/arch/sh/include/asm/dmaengine.h index abb8d66..2a02b61 100644 --- a/arch/sh/include/asm/dmaengine.h +++ b/arch/sh/include/asm/dmaengine.h @@ -10,12 +10,7 @@ #ifndef ASM_DMAENGINE_H #define ASM_DMAENGINE_H -#include -#include - -#include - -#define SH_DMAC_MAX_CHANNELS 6 +#include enum { SHDMA_SLAVE_SCIF0_TX, @@ -36,57 +31,4 @@ enum { SHDMA_SLAVE_SIUB_RX, }; -struct sh_dmae_slave_config { - unsigned int slave_id; - dma_addr_t addr; - u32 chcr; - char mid_rid; -}; - -struct sh_dmae_channel { - unsigned int offset; - unsigned int dmars; - unsigned int dmars_bit; -}; - -struct sh_dmae_pdata { - struct sh_dmae_slave_config *slave; - int slave_num; - struct sh_dmae_channel *channel; - int channel_num; - unsigned int ts_low_shift; - unsigned int ts_low_mask; - unsigned int ts_high_shift; - unsigned int ts_high_mask; - unsigned int *ts_shift; - int ts_shift_num; - u16 dmaor_init; -}; - -struct device; - -/* Used by slave DMA clients to request DMA to/from a specific peripheral */ -struct sh_dmae_slave { - unsigned int slave_id; /* Set by the platform */ - struct device *dma_dev; /* Set by the platform */ - struct sh_dmae_slave_config *config; /* Set by the driver */ -}; - -struct sh_dmae_regs { - u32 sar; /* SAR / source address */ - u32 dar; /* DAR / destination address */ - u32 tcr; /* TCR / transfer count */ -}; - -struct sh_desc { - struct sh_dmae_regs hw; - struct list_head node; - struct dma_async_tx_descriptor async_tx; - enum dma_data_direction direction; - dma_cookie_t cookie; - size_t partial; - int chunks; - int mark; -}; - #endif diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index 8360538..7a18b58 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c @@ -25,8 +25,7 @@ #include #include #include - -#include +#include #include "shdma.h" diff --git a/drivers/dma/shdma.h b/drivers/dma/shdma.h index d7ddf6f..4021275 100644 --- a/drivers/dma/shdma.h +++ b/drivers/dma/shdma.h @@ -17,8 +17,7 @@ #include #include -#include - +#define SH_DMAC_MAX_CHANNELS 6 #define SH_DMA_SLAVE_NUMBER 256 #define SH_DMA_TCR_MAX 0x00FFFFFF /* 16MB */ diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h new file mode 100644 index 0000000..cdaaff4 --- /dev/null +++ b/include/linux/sh_dma.h @@ -0,0 +1,101 @@ +/* + * Header for the new SH dmaengine driver + * + * Copyright (C) 2010 Guennadi Liakhovetski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef SH_DMA_H +#define SH_DMA_H + +#include +#include + +/* Used by slave DMA clients to request DMA to/from a specific peripheral */ +struct sh_dmae_slave { + unsigned int slave_id; /* Set by the platform */ + struct device *dma_dev; /* Set by the platform */ + struct sh_dmae_slave_config *config; /* Set by the driver */ +}; + +struct sh_dmae_regs { + u32 sar; /* SAR / source address */ + u32 dar; /* DAR / destination address */ + u32 tcr; /* TCR / transfer count */ +}; + +struct sh_desc { + struct sh_dmae_regs hw; + struct list_head node; + struct dma_async_tx_descriptor async_tx; + enum dma_data_direction direction; + dma_cookie_t cookie; + size_t partial; + int chunks; + int mark; +}; +struct sh_dmae_slave_config { + unsigned int slave_id; + dma_addr_t addr; + u32 chcr; + char mid_rid; +}; + +struct sh_dmae_channel { + unsigned int offset; + unsigned int dmars; + unsigned int dmars_bit; +}; + +struct sh_dmae_pdata { + struct sh_dmae_slave_config *slave; + int slave_num; + struct sh_dmae_channel *channel; + int channel_num; + unsigned int ts_low_shift; + unsigned int ts_low_mask; + unsigned int ts_high_shift; + unsigned int ts_high_mask; + unsigned int *ts_shift; + int ts_shift_num; + u16 dmaor_init; +}; + +/* DMA register */ +#define SAR 0x00 +#define DAR 0x04 +#define TCR 0x08 +#define CHCR 0x0C +#define DMAOR 0x40 + +/* DMAOR definitions */ +#define DMAOR_AE 0x00000004 +#define DMAOR_NMIF 0x00000002 +#define DMAOR_DME 0x00000001 + +/* Definitions for the SuperH DMAC */ +#define REQ_L 0x00000000 +#define REQ_E 0x00080000 +#define RACK_H 0x00000000 +#define RACK_L 0x00040000 +#define ACK_R 0x00000000 +#define ACK_W 0x00020000 +#define ACK_H 0x00000000 +#define ACK_L 0x00010000 +#define DM_INC 0x00004000 +#define DM_DEC 0x00008000 +#define DM_FIX 0x0000c000 +#define SM_INC 0x00001000 +#define SM_DEC 0x00002000 +#define SM_FIX 0x00003000 +#define RS_IN 0x00000200 +#define RS_OUT 0x00000300 +#define TS_BLK 0x00000040 +#define TM_BUR 0x00000020 +#define CHCR_DE 0x00000001 +#define CHCR_TE 0x00000002 +#define CHCR_IE 0x00000004 + +#endif -- cgit v0.10.2 From 3089f381fbaf53560dcbcb4aef6ef17fe44e347c Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 19 Mar 2010 13:53:04 +0000 Subject: SH: extend SCI DMA support to work on SCIFA ports SCIFA ports have additional bits to control DMA requests and they must have respective interrupt sources enabled, as the datasheet suggests, the only way to avoid actually taking interrupts in addition to DMA events is by masking the IRQ on the CPU. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Paul Mundt diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index cd52dd6..304a877 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -106,6 +106,7 @@ struct sci_port { struct work_struct work_tx; struct work_struct work_rx; struct timer_list rx_timer; + unsigned int rx_timeout; #endif }; @@ -673,22 +674,22 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr) struct sci_port *s = to_sci_port(port); if (s->chan_rx) { - unsigned long tout; u16 scr = sci_in(port, SCSCR); u16 ssr = sci_in(port, SCxSR); /* Disable future Rx interrupts */ - sci_out(port, SCSCR, scr & ~SCI_CTRL_FLAGS_RIE); + if (port->type == PORT_SCIFA) { + disable_irq_nosync(irq); + scr |= 0x4000; + } else { + scr &= ~SCI_CTRL_FLAGS_RIE; + } + sci_out(port, SCSCR, scr); /* Clear current interrupt */ sci_out(port, SCxSR, ssr & ~(1 | SCxSR_RDxF(port))); - /* Calculate delay for 1.5 DMA buffers */ - tout = (port->timeout - HZ / 50) * s->buf_len_rx * 3 / - port->fifosize / 2; - dev_dbg(port->dev, "Rx IRQ: setup timeout in %lu ms\n", - tout * 1000 / HZ); - if (tout < 2) - tout = 2; - mod_timer(&s->rx_timer, jiffies + tout); + dev_dbg(port->dev, "Rx IRQ %lu: setup t-out in %u jiffies\n", + jiffies, s->rx_timeout); + mod_timer(&s->rx_timer, jiffies + s->rx_timeout); return IRQ_HANDLED; } @@ -925,13 +926,17 @@ static void sci_dma_tx_complete(void *arg) s->cookie_tx = -EINVAL; s->desc_tx = NULL; - spin_unlock_irqrestore(&port->lock, flags); - if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(port); - if (uart_circ_chars_pending(xmit)) + if (!uart_circ_empty(xmit)) { schedule_work(&s->work_tx); + } else if (port->type == PORT_SCIFA) { + u16 ctrl = sci_in(port, SCSCR); + sci_out(port, SCSCR, ctrl & ~SCI_CTRL_FLAGS_TIE); + } + + spin_unlock_irqrestore(&port->lock, flags); } /* Locking: called with port lock held */ @@ -975,13 +980,13 @@ static void sci_dma_rx_complete(void *arg) unsigned long flags; int count; - dev_dbg(port->dev, "%s(%d)\n", __func__, port->line); + dev_dbg(port->dev, "%s(%d) active #%d\n", __func__, port->line, s->active_rx); spin_lock_irqsave(&port->lock, flags); count = sci_dma_rx_push(s, tty, s->buf_len_rx); - mod_timer(&s->rx_timer, jiffies + msecs_to_jiffies(5)); + mod_timer(&s->rx_timer, jiffies + s->rx_timeout); spin_unlock_irqrestore(&port->lock, flags); @@ -1053,6 +1058,8 @@ static void sci_submit_rx(struct sci_port *s) sci_rx_dma_release(s, true); return; } + dev_dbg(s->port.dev, "%s(): cookie %d to #%d\n", __func__, + s->cookie_rx[i], i); } s->active_rx = s->cookie_rx[0]; @@ -1110,10 +1117,10 @@ static void work_fn_rx(struct work_struct *work) return; } - dev_dbg(port->dev, "%s: cookie %d #%d\n", __func__, - s->cookie_rx[new], new); - s->active_rx = s->cookie_rx[!new]; + + dev_dbg(port->dev, "%s: cookie %d #%d, new active #%d\n", __func__, + s->cookie_rx[new], new, s->active_rx); } static void work_fn_tx(struct work_struct *work) @@ -1175,23 +1182,28 @@ static void work_fn_tx(struct work_struct *work) static void sci_start_tx(struct uart_port *port) { + struct sci_port *s = to_sci_port(port); unsigned short ctrl; #ifdef CONFIG_SERIAL_SH_SCI_DMA - struct sci_port *s = to_sci_port(port); - - if (s->chan_tx) { - if (!uart_circ_empty(&s->port.state->xmit) && s->cookie_tx < 0) - schedule_work(&s->work_tx); - - return; + if (port->type == PORT_SCIFA) { + u16 new, scr = sci_in(port, SCSCR); + if (s->chan_tx) + new = scr | 0x8000; + else + new = scr & ~0x8000; + if (new != scr) + sci_out(port, SCSCR, new); } + if (s->chan_tx && !uart_circ_empty(&s->port.state->xmit) && + s->cookie_tx < 0) + schedule_work(&s->work_tx); #endif - - /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */ - ctrl = sci_in(port, SCSCR); - ctrl |= SCI_CTRL_FLAGS_TIE; - sci_out(port, SCSCR, ctrl); + if (!s->chan_tx || port->type == PORT_SCIFA) { + /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */ + ctrl = sci_in(port, SCSCR); + sci_out(port, SCSCR, ctrl | SCI_CTRL_FLAGS_TIE); + } } static void sci_stop_tx(struct uart_port *port) @@ -1200,6 +1212,8 @@ static void sci_stop_tx(struct uart_port *port) /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */ ctrl = sci_in(port, SCSCR); + if (port->type == PORT_SCIFA) + ctrl &= ~0x8000; ctrl &= ~SCI_CTRL_FLAGS_TIE; sci_out(port, SCSCR, ctrl); } @@ -1210,6 +1224,8 @@ static void sci_start_rx(struct uart_port *port) /* Set RIE (Receive Interrupt Enable) bit in SCSCR */ ctrl |= sci_in(port, SCSCR); + if (port->type == PORT_SCIFA) + ctrl &= ~0x4000; sci_out(port, SCSCR, ctrl); } @@ -1219,6 +1235,8 @@ static void sci_stop_rx(struct uart_port *port) /* Clear RIE (Receive Interrupt Enable) bit in SCSCR */ ctrl = sci_in(port, SCSCR); + if (port->type == PORT_SCIFA) + ctrl &= ~0x4000; ctrl &= ~(SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE); sci_out(port, SCSCR, ctrl); } @@ -1253,8 +1271,12 @@ static void rx_timer_fn(unsigned long arg) { struct sci_port *s = (struct sci_port *)arg; struct uart_port *port = &s->port; - u16 scr = sci_in(port, SCSCR); + + if (port->type == PORT_SCIFA) { + scr &= ~0x4000; + enable_irq(s->irqs[1]); + } sci_out(port, SCSCR, scr | SCI_CTRL_FLAGS_RIE); dev_dbg(port->dev, "DMA Rx timed out\n"); schedule_work(&s->work_rx); @@ -1404,8 +1426,12 @@ static void sci_shutdown(struct uart_port *port) static void sci_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { +#ifdef CONFIG_SERIAL_SH_SCI_DMA + struct sci_port *s = to_sci_port(port); +#endif unsigned int status, baud, smr_val, max_baud; int t = -1; + u16 scfcr = 0; /* * earlyprintk comes here early on with port->uartclk set to zero. @@ -1428,7 +1454,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */ if (port->type != PORT_SCI) - sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST); + sci_out(port, SCFCR, scfcr | SCFCR_RFRST | SCFCR_TFRST); smr_val = sci_in(port, SCSMR) & 3; if ((termios->c_cflag & CSIZE) == CS7) @@ -1459,10 +1485,32 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, } sci_init_pins(port, termios->c_cflag); - sci_out(port, SCFCR, (termios->c_cflag & CRTSCTS) ? SCFCR_MCE : 0); + sci_out(port, SCFCR, scfcr | ((termios->c_cflag & CRTSCTS) ? SCFCR_MCE : 0)); sci_out(port, SCSCR, SCSCR_INIT(port)); +#ifdef CONFIG_SERIAL_SH_SCI_DMA + /* + * Calculate delay for 1.5 DMA buffers: see + * drivers/serial/serial_core.c::uart_update_timeout(). With 10 bits + * (CS8), 250Hz, 115200 baud and 64 bytes FIFO, the above function + * calculates 1 jiffie for the data plus 5 jiffies for the "slop(e)." + * Then below we calculate 3 jiffies (12ms) for 1.5 DMA buffers (3 FIFO + * sizes), but it has been found out experimentally, that this is not + * enough: the driver too often needlessly runs on a DMA timeout. 20ms + * as a minimum seem to work perfectly. + */ + if (s->chan_rx) { + s->rx_timeout = (port->timeout - HZ / 50) * s->buf_len_rx * 3 / + port->fifosize / 2; + dev_dbg(port->dev, + "DMA Rx t-out %ums, tty t-out %u jiffies\n", + s->rx_timeout * 1000 / HZ, port->timeout); + if (s->rx_timeout < msecs_to_jiffies(20)) + s->rx_timeout = msecs_to_jiffies(20); + } +#endif + if ((termios->c_cflag & CREAD) != 0) sci_start_rx(port); } -- cgit v0.10.2 From 88978e562302c836c1c4597700c79d971e93abc0 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 23 Mar 2010 14:33:58 -0300 Subject: perf archive: Explain how to use the generated tarball MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [root@doppio ~]# perf archive Now please run: $ tar xvf perf.data.tar.bz2 -C ~/.debug wherever you need to run 'perf report' on. [root@doppio ~]# Signed-off-by: Arnaldo Carvalho de Melo Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: <1269365638-10223-1-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar diff --git a/tools/perf/perf-archive.sh b/tools/perf/perf-archive.sh index 910468e..2e7a4f4 100644 --- a/tools/perf/perf-archive.sh +++ b/tools/perf/perf-archive.sh @@ -30,4 +30,7 @@ done tar cfj $PERF_DATA.tar.bz2 -C $DEBUGDIR -T $MANIFEST rm -f $MANIFEST $BUILDIDS +echo -e "Now please run:\n" +echo -e "$ tar xvf $PERF_DATA.tar.bz2 -C ~/.debug\n" +echo "wherever you need to run 'perf report' on." exit 0 -- cgit v0.10.2 From 5cfc8ee0bb5134e1204e1ec5843e164f24315021 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Wed, 24 Mar 2010 00:22:36 +0000 Subject: ARM: convert arm to arch_gettimeoffset() Convert arm to use GENERIC_TIME via the arch_getoffset() infrastructure, reducing the amount of arch specific code we need to maintain. The arm architecture is the last arch that need to be converted. Signed-off-by: John Stultz Signed-off-by: Russell King Cc: Andrew Morton diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index bcaa8c8..bf856f4 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -42,6 +42,11 @@ config GENERIC_GPIO config GENERIC_TIME bool + default y + +config ARCH_USES_GETTIMEOFFSET + bool + default n config GENERIC_CLOCKEVENTS bool @@ -231,6 +236,7 @@ config ARCH_AAEC2000 select CPU_ARM920T select ARM_AMBA select HAVE_CLK + select ARCH_USES_GETTIMEOFFSET help This enables support for systems based on the Agilent AAEC-2000 @@ -271,6 +277,7 @@ config ARCH_AT91 select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB select HAVE_CLK + select ARCH_USES_GETTIMEOFFSET help This enables support for systems based on the Atmel AT91RM9200, AT91SAM9 and AT91CAP9 processors. @@ -290,6 +297,7 @@ config ARCH_BCMRING config ARCH_CLPS711X bool "Cirrus Logic CLPS711x/EP721x-based" select CPU_ARM720T + select ARCH_USES_GETTIMEOFFSET help Support for Cirrus Logic 711x/721x based boards. @@ -298,6 +306,7 @@ config ARCH_GEMINI select CPU_FA526 select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB + select ARCH_USES_GETTIMEOFFSET help Support for the Cortina Systems Gemini family SoCs @@ -306,6 +315,7 @@ config ARCH_EBSA110 select CPU_SA110 select ISA select NO_IOPORT + select ARCH_USES_GETTIMEOFFSET help This is an evaluation board for the StrongARM processor available from Digital. It has limited hardware on-board, including an @@ -321,6 +331,7 @@ config ARCH_EP93XX select COMMON_CLKDEV select ARCH_REQUIRE_GPIOLIB select ARCH_HAS_HOLES_MEMORYMODEL + select ARCH_USES_GETTIMEOFFSET help This enables support for the Cirrus EP93xx series of CPUs. @@ -328,6 +339,7 @@ config ARCH_FOOTBRIDGE bool "FootBridge" select CPU_SA110 select FOOTBRIDGE + select ARCH_USES_GETTIMEOFFSET help Support for systems based on the DC21285 companion chip ("FootBridge"), such as the Simtec CATS and the Rebel NetWinder. @@ -366,6 +378,7 @@ config ARCH_H720X bool "Hynix HMS720x-based" select CPU_ARM720T select ISA_DMA_API + select ARCH_USES_GETTIMEOFFSET help This enables support for systems based on the Hynix HMS720x @@ -408,6 +421,7 @@ config ARCH_IXP23XX depends on MMU select CPU_XSC3 select PCI + select ARCH_USES_GETTIMEOFFSET help Support for Intel's IXP23xx (XScale) family of processors. @@ -416,6 +430,7 @@ config ARCH_IXP2000 depends on MMU select CPU_XSCALE select PCI + select ARCH_USES_GETTIMEOFFSET help Support for Intel's IXP2400/2800 (XScale) family of processors. @@ -434,6 +449,7 @@ config ARCH_L7200 bool "LinkUp-L7200" select CPU_ARM720T select FIQ + select ARCH_USES_GETTIMEOFFSET help Say Y here if you intend to run this kernel on a LinkUp Systems L7200 Software Development Board which uses an ARM720T processor. @@ -523,6 +539,7 @@ config ARCH_KS8695 select CPU_ARM922T select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB + select ARCH_USES_GETTIMEOFFSET help Support for Micrel/Kendin KS8695 "Centaur" (ARM922T) based System-on-Chip devices. @@ -569,6 +586,7 @@ config ARCH_PNX4008 bool "Philips Nexperia PNX4008 Mobile" select CPU_ARM926T select COMMON_CLKDEV + select ARCH_USES_GETTIMEOFFSET help This enables support for Philips PNX4008 mobile platform. @@ -613,6 +631,7 @@ config ARCH_RPC select ISA_DMA_API select NO_IOPORT select ARCH_SPARSEMEM_ENABLE + select ARCH_USES_GETTIMEOFFSET help On the Acorn Risc-PC, Linux can support the internal IDE disk and CD-ROM interface, serial and parallel port, and the floppy drive. @@ -639,6 +658,7 @@ config ARCH_S3C2410 select GENERIC_GPIO select ARCH_HAS_CPUFREQ select HAVE_CLK + select ARCH_USES_GETTIMEOFFSET help Samsung S3C2410X CPU based systems, such as the Simtec Electronics BAST (), the IPAQ 1940 or @@ -652,6 +672,7 @@ config ARCH_S3C64XX select ARM_VIC select HAVE_CLK select NO_IOPORT + select ARCH_USES_GETTIMEOFFSET select ARCH_HAS_CPUFREQ select ARCH_REQUIRE_GPIOLIB select SAMSUNG_CLKSRC @@ -708,6 +729,7 @@ config ARCH_SHARK select ISA_DMA select ZONE_DMA select PCI + select ARCH_USES_GETTIMEOFFSET help Support for the StrongARM based Digital DNARD machine, also known as "Shark" (). @@ -717,6 +739,7 @@ config ARCH_LH7A40X select CPU_ARM922T select ARCH_DISCONTIGMEM_ENABLE if !LH7A40X_CONTIGMEM select ARCH_SPARSEMEM_ENABLE if !LH7A40X_CONTIGMEM + select ARCH_USES_GETTIMEOFFSET help Say Y here for systems based on one of the Sharp LH7A40X System on a Chip processors. These CPUs include an ARM922T diff --git a/arch/arm/include/asm/mach/time.h b/arch/arm/include/asm/mach/time.h index 8bffc3f..35d408f 100644 --- a/arch/arm/include/asm/mach/time.h +++ b/arch/arm/include/asm/mach/time.h @@ -38,7 +38,7 @@ struct sys_timer { void (*init)(void); void (*suspend)(void); void (*resume)(void); -#ifndef CONFIG_GENERIC_TIME +#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET unsigned long (*offset)(void); #endif }; diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index 2875380..38c261f 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c @@ -72,12 +72,15 @@ unsigned long profile_pc(struct pt_regs *regs) EXPORT_SYMBOL(profile_pc); #endif -#ifndef CONFIG_GENERIC_TIME -static unsigned long dummy_gettimeoffset(void) +#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET +u32 arch_gettimeoffset(void) { + if (system_timer->offset != NULL) + return system_timer->offset() * 1000; + return 0; } -#endif +#endif /* CONFIG_ARCH_USES_GETTIMEOFFSET */ #ifdef CONFIG_LEDS_TIMER static inline void do_leds(void) @@ -93,63 +96,6 @@ static inline void do_leds(void) #define do_leds() #endif -#ifndef CONFIG_GENERIC_TIME -void do_gettimeofday(struct timeval *tv) -{ - unsigned long flags; - unsigned long seq; - unsigned long usec, sec; - - do { - seq = read_seqbegin_irqsave(&xtime_lock, flags); - usec = system_timer->offset(); - sec = xtime.tv_sec; - usec += xtime.tv_nsec / 1000; - } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); - - /* usec may have gone up a lot: be safe */ - while (usec >= 1000000) { - usec -= 1000000; - sec++; - } - - tv->tv_sec = sec; - tv->tv_usec = usec; -} - -EXPORT_SYMBOL(do_gettimeofday); - -int do_settimeofday(struct timespec *tv) -{ - time_t wtm_sec, sec = tv->tv_sec; - long wtm_nsec, nsec = tv->tv_nsec; - - if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) - return -EINVAL; - - write_seqlock_irq(&xtime_lock); - /* - * This is revolting. We need to set "xtime" correctly. However, the - * value in this location is the value at the most recent update of - * wall time. Discover what correction gettimeofday() would have - * done, and then undo it! - */ - nsec -= system_timer->offset() * NSEC_PER_USEC; - - wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); - wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); - - set_normalized_timespec(&xtime, sec, nsec); - set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec); - - ntp_clear(); - write_sequnlock_irq(&xtime_lock); - clock_was_set(); - return 0; -} - -EXPORT_SYMBOL(do_settimeofday); -#endif /* !CONFIG_GENERIC_TIME */ #ifndef CONFIG_GENERIC_CLOCKEVENTS /* @@ -214,10 +160,6 @@ device_initcall(timer_init_sysfs); void __init time_init(void) { -#ifndef CONFIG_GENERIC_TIME - if (system_timer->offset == NULL) - system_timer->offset = dummy_gettimeoffset; -#endif system_timer->init(); } diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 2db43a5..8a5e8e9 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -97,6 +97,7 @@ config ARCH_AT572D940HF config ARCH_AT91X40 bool "AT91x40" + select ARCH_USES_GETTIMEOFFSET endchoice -- cgit v0.10.2 From d814f30105798b6677ecb73ed61d691ff96dada9 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Wed, 24 Mar 2010 12:09:26 +0800 Subject: x86, perf: Add raw events support for the P4 PMU The adding of raw event support lead to complete code refactoring. I hope is became more readable then it was. The list of changes: 1) The 64bit config field is enough to hold all information we need to track event details. To achieve it we used *own* enum for events selection in ESCR register and map this key into proper value at moment of event enabling. For the same reason we use 12LSB bits in CCCR register -- to track which exactly cache trace event was requested. And we cear this bits at real 'write' moment. 2) There is no per-cpu area reserved for P4 PMU anymore. We don't need it. All is held by config. 3) Now we may use any available counter, ie we try to grab any possible counter. v2: - Lin Ming reported the lack of ESCR selector in CCCR for cache events v3: - Don't loose cache event codes at config unpacking procedure, we may need it one day so no obscure hack behind our back, better to clear reserved bits explicitly when needed (thanks Ming for pointing out) - Lin Ming fixed misplaced opcodes in cache events Signed-off-by: Cyrill Gorcunov Tested-by: Lin Ming Signed-off-by: Lin Ming Cc: Arnaldo Carvalho de Melo Cc: Stephane Eranian Cc: Robert Richter Cc: Frederic Weisbecker Cc: Cyrill Gorcunov Cc: Peter Zijlstra LKML-Reference: <1269403766.3409.6.camel@minggr.sh.intel.com> [ v4: did a few whitespace fixlets ] Signed-off-by: Ingo Molnar diff --git a/arch/x86/include/asm/perf_event_p4.h b/arch/x86/include/asm/perf_event_p4.h index facf961..b05400a 100644 --- a/arch/x86/include/asm/perf_event_p4.h +++ b/arch/x86/include/asm/perf_event_p4.h @@ -15,38 +15,40 @@ * perf-MSRs are not shared and every thread has its * own perf-MSRs set) */ -#define ARCH_P4_TOTAL_ESCR (46) -#define ARCH_P4_RESERVED_ESCR (2) /* IQ_ESCR(0,1) not always present */ -#define ARCH_P4_MAX_ESCR (ARCH_P4_TOTAL_ESCR - ARCH_P4_RESERVED_ESCR) -#define ARCH_P4_MAX_CCCR (18) -#define ARCH_P4_MAX_COUNTER (ARCH_P4_MAX_CCCR / 2) - -#define P4_EVNTSEL_EVENT_MASK 0x7e000000U -#define P4_EVNTSEL_EVENT_SHIFT 25 -#define P4_EVNTSEL_EVENTMASK_MASK 0x01fffe00U -#define P4_EVNTSEL_EVENTMASK_SHIFT 9 -#define P4_EVNTSEL_TAG_MASK 0x000001e0U -#define P4_EVNTSEL_TAG_SHIFT 5 -#define P4_EVNTSEL_TAG_ENABLE 0x00000010U -#define P4_EVNTSEL_T0_OS 0x00000008U -#define P4_EVNTSEL_T0_USR 0x00000004U -#define P4_EVNTSEL_T1_OS 0x00000002U -#define P4_EVNTSEL_T1_USR 0x00000001U +#define ARCH_P4_TOTAL_ESCR (46) +#define ARCH_P4_RESERVED_ESCR (2) /* IQ_ESCR(0,1) not always present */ +#define ARCH_P4_MAX_ESCR (ARCH_P4_TOTAL_ESCR - ARCH_P4_RESERVED_ESCR) +#define ARCH_P4_MAX_CCCR (18) +#define ARCH_P4_MAX_COUNTER (ARCH_P4_MAX_CCCR / 2) + +#define P4_ESCR_EVENT_MASK 0x7e000000U +#define P4_ESCR_EVENT_SHIFT 25 +#define P4_ESCR_EVENTMASK_MASK 0x01fffe00U +#define P4_ESCR_EVENTMASK_SHIFT 9 +#define P4_ESCR_TAG_MASK 0x000001e0U +#define P4_ESCR_TAG_SHIFT 5 +#define P4_ESCR_TAG_ENABLE 0x00000010U +#define P4_ESCR_T0_OS 0x00000008U +#define P4_ESCR_T0_USR 0x00000004U +#define P4_ESCR_T1_OS 0x00000002U +#define P4_ESCR_T1_USR 0x00000001U + +#define P4_ESCR_EVENT(v) ((v) << P4_ESCR_EVENT_SHIFT) +#define P4_ESCR_EMASK(v) ((v) << P4_ESCR_EVENTMASK_SHIFT) +#define P4_ESCR_TAG(v) ((v) << P4_ESCR_TAG_SHIFT) /* Non HT mask */ -#define P4_EVNTSEL_MASK \ - (P4_EVNTSEL_EVENT_MASK | \ - P4_EVNTSEL_EVENTMASK_MASK | \ - P4_EVNTSEL_TAG_MASK | \ - P4_EVNTSEL_TAG_ENABLE | \ - P4_EVNTSEL_T0_OS | \ - P4_EVNTSEL_T0_USR) +#define P4_ESCR_MASK \ + (P4_ESCR_EVENT_MASK | \ + P4_ESCR_EVENTMASK_MASK | \ + P4_ESCR_TAG_MASK | \ + P4_ESCR_TAG_ENABLE | \ + P4_ESCR_T0_OS | \ + P4_ESCR_T0_USR) /* HT mask */ -#define P4_EVNTSEL_MASK_HT \ - (P4_EVNTSEL_MASK | \ - P4_EVNTSEL_T1_OS | \ - P4_EVNTSEL_T1_USR) +#define P4_ESCR_MASK_HT \ + (P4_ESCR_MASK | P4_ESCR_T1_OS | P4_ESCR_T1_USR) #define P4_CCCR_OVF 0x80000000U #define P4_CCCR_CASCADE 0x40000000U @@ -56,7 +58,6 @@ #define P4_CCCR_EDGE 0x01000000U #define P4_CCCR_THRESHOLD_MASK 0x00f00000U #define P4_CCCR_THRESHOLD_SHIFT 20 -#define P4_CCCR_THRESHOLD(v) ((v) << P4_CCCR_THRESHOLD_SHIFT) #define P4_CCCR_COMPLEMENT 0x00080000U #define P4_CCCR_COMPARE 0x00040000U #define P4_CCCR_ESCR_SELECT_MASK 0x0000e000U @@ -67,6 +68,13 @@ #define P4_CCCR_THREAD_ANY 0x00030000U #define P4_CCCR_RESERVED 0x00000fffU +#define P4_CCCR_THRESHOLD(v) ((v) << P4_CCCR_THRESHOLD_SHIFT) +#define P4_CCCR_ESEL(v) ((v) << P4_CCCR_ESCR_SELECT_SHIFT) + +/* Custom bits in reerved CCCR area */ +#define P4_CCCR_CACHE_OPS_MASK 0x0000003fU + + /* Non HT mask */ #define P4_CCCR_MASK \ (P4_CCCR_OVF | \ @@ -81,25 +89,11 @@ P4_CCCR_ENABLE) /* HT mask */ -#define P4_CCCR_MASK_HT \ - (P4_CCCR_MASK | \ - P4_CCCR_THREAD_ANY) +#define P4_CCCR_MASK_HT (P4_CCCR_MASK | P4_CCCR_THREAD_ANY) -/* - * format is 32 bit: ee ss aa aa - * where - * ee - 8 bit event - * ss - 8 bit selector - * aa aa - 16 bits reserved for tags/attributes - */ -#define P4_EVENT_PACK(event, selector) (((event) << 24) | ((selector) << 16)) -#define P4_EVENT_UNPACK_EVENT(packed) (((packed) >> 24) & 0xff) -#define P4_EVENT_UNPACK_SELECTOR(packed) (((packed) >> 16) & 0xff) -#define P4_EVENT_PACK_ATTR(attr) ((attr)) -#define P4_EVENT_UNPACK_ATTR(packed) ((packed) & 0xffff) -#define P4_MAKE_EVENT_ATTR(class, name, bit) class##_##name = (1 << bit) -#define P4_EVENT_ATTR(class, name) class##_##name -#define P4_EVENT_ATTR_STR(class, name) __stringify(class##_##name) +#define P4_GEN_ESCR_EMASK(class, name, bit) \ + class##__##name = ((1 << bit) << P4_ESCR_EVENTMASK_SHIFT) +#define P4_ESCR_EMASK_BIT(class, name) class##__##name /* * config field is 64bit width and consists of @@ -117,35 +111,29 @@ #define p4_config_pack_escr(v) (((u64)(v)) << 32) #define p4_config_pack_cccr(v) (((u64)(v)) & 0xffffffffULL) #define p4_config_unpack_escr(v) (((u64)(v)) >> 32) -#define p4_config_unpack_cccr(v) (((u64)(v)) & 0xfffff000ULL) +#define p4_config_unpack_cccr(v) (((u64)(v)) & 0xffffffffULL) #define p4_config_unpack_emask(v) \ ({ \ u32 t = p4_config_unpack_escr((v)); \ - t &= P4_EVNTSEL_EVENTMASK_MASK; \ - t >>= P4_EVNTSEL_EVENTMASK_SHIFT; \ + t = t & P4_ESCR_EVENTMASK_MASK; \ + t = t >> P4_ESCR_EVENTMASK_SHIFT; \ + t; \ + }) + +#define p4_config_unpack_event(v) \ + ({ \ + u32 t = p4_config_unpack_escr((v)); \ + t = t & P4_ESCR_EVENT_MASK; \ + t = t >> P4_ESCR_EVENT_SHIFT; \ t; \ }) -#define p4_config_unpack_key(v) (((u64)(v)) & P4_CCCR_RESERVED) +#define p4_config_unpack_cache_event(v) (((u64)(v)) & P4_CCCR_CACHE_OPS_MASK) #define P4_CONFIG_HT_SHIFT 63 #define P4_CONFIG_HT (1ULL << P4_CONFIG_HT_SHIFT) -static inline u32 p4_config_unpack_opcode(u64 config) -{ - u32 e, s; - - /* - * we don't care about HT presence here since - * event opcode doesn't depend on it - */ - e = (p4_config_unpack_escr(config) & P4_EVNTSEL_EVENT_MASK) >> P4_EVNTSEL_EVENT_SHIFT; - s = (p4_config_unpack_cccr(config) & P4_CCCR_ESCR_SELECT_MASK) >> P4_CCCR_ESCR_SELECT_SHIFT; - - return P4_EVENT_PACK(e, s); -} - static inline bool p4_is_event_cascaded(u64 config) { u32 cccr = p4_config_unpack_cccr(config); @@ -212,19 +200,73 @@ static inline u32 p4_default_escr_conf(int cpu, int exclude_os, int exclude_usr) if (!p4_ht_thread(cpu)) { if (!exclude_os) - escr |= P4_EVNTSEL_T0_OS; + escr |= P4_ESCR_T0_OS; if (!exclude_usr) - escr |= P4_EVNTSEL_T0_USR; + escr |= P4_ESCR_T0_USR; } else { if (!exclude_os) - escr |= P4_EVNTSEL_T1_OS; + escr |= P4_ESCR_T1_OS; if (!exclude_usr) - escr |= P4_EVNTSEL_T1_USR; + escr |= P4_ESCR_T1_USR; } return escr; } +enum P4_EVENTS { + P4_EVENT_TC_DELIVER_MODE, + P4_EVENT_BPU_FETCH_REQUEST, + P4_EVENT_ITLB_REFERENCE, + P4_EVENT_MEMORY_CANCEL, + P4_EVENT_MEMORY_COMPLETE, + P4_EVENT_LOAD_PORT_REPLAY, + P4_EVENT_STORE_PORT_REPLAY, + P4_EVENT_MOB_LOAD_REPLAY, + P4_EVENT_PAGE_WALK_TYPE, + P4_EVENT_BSQ_CACHE_REFERENCE, + P4_EVENT_IOQ_ALLOCATION, + P4_EVENT_IOQ_ACTIVE_ENTRIES, + P4_EVENT_FSB_DATA_ACTIVITY, + P4_EVENT_BSQ_ALLOCATION, + P4_EVENT_BSQ_ACTIVE_ENTRIES, + P4_EVENT_SSE_INPUT_ASSIST, + P4_EVENT_PACKED_SP_UOP, + P4_EVENT_PACKED_DP_UOP, + P4_EVENT_SCALAR_SP_UOP, + P4_EVENT_SCALAR_DP_UOP, + P4_EVENT_64BIT_MMX_UOP, + P4_EVENT_128BIT_MMX_UOP, + P4_EVENT_X87_FP_UOP, + P4_EVENT_TC_MISC, + P4_EVENT_GLOBAL_POWER_EVENTS, + P4_EVENT_TC_MS_XFER, + P4_EVENT_UOP_QUEUE_WRITES, + P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE, + P4_EVENT_RETIRED_BRANCH_TYPE, + P4_EVENT_RESOURCE_STALL, + P4_EVENT_WC_BUFFER, + P4_EVENT_B2B_CYCLES, + P4_EVENT_BNR, + P4_EVENT_SNOOP, + P4_EVENT_RESPONSE, + P4_EVENT_FRONT_END_EVENT, + P4_EVENT_EXECUTION_EVENT, + P4_EVENT_REPLAY_EVENT, + P4_EVENT_INSTR_RETIRED, + P4_EVENT_UOPS_RETIRED, + P4_EVENT_UOP_TYPE, + P4_EVENT_BRANCH_RETIRED, + P4_EVENT_MISPRED_BRANCH_RETIRED, + P4_EVENT_X87_ASSIST, + P4_EVENT_MACHINE_CLEAR, + P4_EVENT_INSTR_COMPLETED, +}; + +#define P4_OPCODE(event) event##_OPCODE +#define P4_OPCODE_ESEL(opcode) ((opcode & 0x00ff) >> 0) +#define P4_OPCODE_EVNT(opcode) ((opcode & 0xff00) >> 8) +#define P4_OPCODE_PACK(event, sel) (((event) << 8) | sel) + /* * Comments below the event represent ESCR restriction * for this event and counter index per ESCR @@ -238,484 +280,515 @@ static inline u32 p4_default_escr_conf(int cpu, int exclude_os, int exclude_usr) * working so that we should not use this CCCR and respective * counter as result */ -#define P4_TC_DELIVER_MODE P4_EVENT_PACK(0x01, 0x01) +enum P4_EVENT_OPCODES { + P4_OPCODE(P4_EVENT_TC_DELIVER_MODE) = P4_OPCODE_PACK(0x01, 0x01), /* * MSR_P4_TC_ESCR0: 4, 5 * MSR_P4_TC_ESCR1: 6, 7 */ -#define P4_BPU_FETCH_REQUEST P4_EVENT_PACK(0x03, 0x00) + P4_OPCODE(P4_EVENT_BPU_FETCH_REQUEST) = P4_OPCODE_PACK(0x03, 0x00), /* * MSR_P4_BPU_ESCR0: 0, 1 * MSR_P4_BPU_ESCR1: 2, 3 */ -#define P4_ITLB_REFERENCE P4_EVENT_PACK(0x18, 0x03) + P4_OPCODE(P4_EVENT_ITLB_REFERENCE) = P4_OPCODE_PACK(0x18, 0x03), /* * MSR_P4_ITLB_ESCR0: 0, 1 * MSR_P4_ITLB_ESCR1: 2, 3 */ -#define P4_MEMORY_CANCEL P4_EVENT_PACK(0x02, 0x05) + P4_OPCODE(P4_EVENT_MEMORY_CANCEL) = P4_OPCODE_PACK(0x02, 0x05), /* * MSR_P4_DAC_ESCR0: 8, 9 * MSR_P4_DAC_ESCR1: 10, 11 */ -#define P4_MEMORY_COMPLETE P4_EVENT_PACK(0x08, 0x02) + P4_OPCODE(P4_EVENT_MEMORY_COMPLETE) = P4_OPCODE_PACK(0x08, 0x02), /* * MSR_P4_SAAT_ESCR0: 8, 9 * MSR_P4_SAAT_ESCR1: 10, 11 */ -#define P4_LOAD_PORT_REPLAY P4_EVENT_PACK(0x04, 0x02) + P4_OPCODE(P4_EVENT_LOAD_PORT_REPLAY) = P4_OPCODE_PACK(0x04, 0x02), /* * MSR_P4_SAAT_ESCR0: 8, 9 * MSR_P4_SAAT_ESCR1: 10, 11 */ -#define P4_STORE_PORT_REPLAY P4_EVENT_PACK(0x05, 0x02) + P4_OPCODE(P4_EVENT_STORE_PORT_REPLAY) = P4_OPCODE_PACK(0x05, 0x02), /* * MSR_P4_SAAT_ESCR0: 8, 9 * MSR_P4_SAAT_ESCR1: 10, 11 */ -#define P4_MOB_LOAD_REPLAY P4_EVENT_PACK(0x03, 0x02) + P4_OPCODE(P4_EVENT_MOB_LOAD_REPLAY) = P4_OPCODE_PACK(0x03, 0x02), /* * MSR_P4_MOB_ESCR0: 0, 1 * MSR_P4_MOB_ESCR1: 2, 3 */ -#define P4_PAGE_WALK_TYPE P4_EVENT_PACK(0x01, 0x04) + P4_OPCODE(P4_EVENT_PAGE_WALK_TYPE) = P4_OPCODE_PACK(0x01, 0x04), /* * MSR_P4_PMH_ESCR0: 0, 1 * MSR_P4_PMH_ESCR1: 2, 3 */ -#define P4_BSQ_CACHE_REFERENCE P4_EVENT_PACK(0x0c, 0x07) + P4_OPCODE(P4_EVENT_BSQ_CACHE_REFERENCE) = P4_OPCODE_PACK(0x0c, 0x07), /* * MSR_P4_BSU_ESCR0: 0, 1 * MSR_P4_BSU_ESCR1: 2, 3 */ -#define P4_IOQ_ALLOCATION P4_EVENT_PACK(0x03, 0x06) + P4_OPCODE(P4_EVENT_IOQ_ALLOCATION) = P4_OPCODE_PACK(0x03, 0x06), /* * MSR_P4_FSB_ESCR0: 0, 1 * MSR_P4_FSB_ESCR1: 2, 3 */ -#define P4_IOQ_ACTIVE_ENTRIES P4_EVENT_PACK(0x1a, 0x06) + P4_OPCODE(P4_EVENT_IOQ_ACTIVE_ENTRIES) = P4_OPCODE_PACK(0x1a, 0x06), /* * MSR_P4_FSB_ESCR1: 2, 3 */ -#define P4_FSB_DATA_ACTIVITY P4_EVENT_PACK(0x17, 0x06) + P4_OPCODE(P4_EVENT_FSB_DATA_ACTIVITY) = P4_OPCODE_PACK(0x17, 0x06), /* * MSR_P4_FSB_ESCR0: 0, 1 * MSR_P4_FSB_ESCR1: 2, 3 */ -#define P4_BSQ_ALLOCATION P4_EVENT_PACK(0x05, 0x07) + P4_OPCODE(P4_EVENT_BSQ_ALLOCATION) = P4_OPCODE_PACK(0x05, 0x07), /* * MSR_P4_BSU_ESCR0: 0, 1 */ -#define P4_BSQ_ACTIVE_ENTRIES P4_EVENT_PACK(0x06, 0x07) + P4_OPCODE(P4_EVENT_BSQ_ACTIVE_ENTRIES) = P4_OPCODE_PACK(0x06, 0x07), /* * NOTE: no ESCR name in docs, it's guessed * MSR_P4_BSU_ESCR1: 2, 3 */ -#define P4_SSE_INPUT_ASSIST P4_EVENT_PACK(0x34, 0x01) + P4_OPCODE(P4_EVENT_SSE_INPUT_ASSIST) = P4_OPCODE_PACK(0x34, 0x01), /* * MSR_P4_FIRM_ESCR0: 8, 9 * MSR_P4_FIRM_ESCR1: 10, 11 */ -#define P4_PACKED_SP_UOP P4_EVENT_PACK(0x08, 0x01) + P4_OPCODE(P4_EVENT_PACKED_SP_UOP) = P4_OPCODE_PACK(0x08, 0x01), /* * MSR_P4_FIRM_ESCR0: 8, 9 * MSR_P4_FIRM_ESCR1: 10, 11 */ -#define P4_PACKED_DP_UOP P4_EVENT_PACK(0x0c, 0x01) + P4_OPCODE(P4_EVENT_PACKED_DP_UOP) = P4_OPCODE_PACK(0x0c, 0x01), /* * MSR_P4_FIRM_ESCR0: 8, 9 * MSR_P4_FIRM_ESCR1: 10, 11 */ -#define P4_SCALAR_SP_UOP P4_EVENT_PACK(0x0a, 0x01) + P4_OPCODE(P4_EVENT_SCALAR_SP_UOP) = P4_OPCODE_PACK(0x0a, 0x01), /* * MSR_P4_FIRM_ESCR0: 8, 9 * MSR_P4_FIRM_ESCR1: 10, 11 */ -#define P4_SCALAR_DP_UOP P4_EVENT_PACK(0x0e, 0x01) + P4_OPCODE(P4_EVENT_SCALAR_DP_UOP) = P4_OPCODE_PACK(0x0e, 0x01), /* * MSR_P4_FIRM_ESCR0: 8, 9 * MSR_P4_FIRM_ESCR1: 10, 11 */ -#define P4_64BIT_MMX_UOP P4_EVENT_PACK(0x02, 0x01) + P4_OPCODE(P4_EVENT_64BIT_MMX_UOP) = P4_OPCODE_PACK(0x02, 0x01), /* * MSR_P4_FIRM_ESCR0: 8, 9 * MSR_P4_FIRM_ESCR1: 10, 11 */ -#define P4_128BIT_MMX_UOP P4_EVENT_PACK(0x1a, 0x01) + P4_OPCODE(P4_EVENT_128BIT_MMX_UOP) = P4_OPCODE_PACK(0x1a, 0x01), /* * MSR_P4_FIRM_ESCR0: 8, 9 * MSR_P4_FIRM_ESCR1: 10, 11 */ -#define P4_X87_FP_UOP P4_EVENT_PACK(0x04, 0x01) + P4_OPCODE(P4_EVENT_X87_FP_UOP) = P4_OPCODE_PACK(0x04, 0x01), /* * MSR_P4_FIRM_ESCR0: 8, 9 * MSR_P4_FIRM_ESCR1: 10, 11 */ -#define P4_TC_MISC P4_EVENT_PACK(0x06, 0x01) + P4_OPCODE(P4_EVENT_TC_MISC) = P4_OPCODE_PACK(0x06, 0x01), /* * MSR_P4_TC_ESCR0: 4, 5 * MSR_P4_TC_ESCR1: 6, 7 */ -#define P4_GLOBAL_POWER_EVENTS P4_EVENT_PACK(0x13, 0x06) + P4_OPCODE(P4_EVENT_GLOBAL_POWER_EVENTS) = P4_OPCODE_PACK(0x13, 0x06), /* * MSR_P4_FSB_ESCR0: 0, 1 * MSR_P4_FSB_ESCR1: 2, 3 */ -#define P4_TC_MS_XFER P4_EVENT_PACK(0x05, 0x00) + P4_OPCODE(P4_EVENT_TC_MS_XFER) = P4_OPCODE_PACK(0x05, 0x00), /* * MSR_P4_MS_ESCR0: 4, 5 * MSR_P4_MS_ESCR1: 6, 7 */ -#define P4_UOP_QUEUE_WRITES P4_EVENT_PACK(0x09, 0x00) + P4_OPCODE(P4_EVENT_UOP_QUEUE_WRITES) = P4_OPCODE_PACK(0x09, 0x00), /* * MSR_P4_MS_ESCR0: 4, 5 * MSR_P4_MS_ESCR1: 6, 7 */ -#define P4_RETIRED_MISPRED_BRANCH_TYPE P4_EVENT_PACK(0x05, 0x02) + P4_OPCODE(P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE) = P4_OPCODE_PACK(0x05, 0x02), /* * MSR_P4_TBPU_ESCR0: 4, 5 * MSR_P4_TBPU_ESCR1: 6, 7 */ -#define P4_RETIRED_BRANCH_TYPE P4_EVENT_PACK(0x04, 0x02) + P4_OPCODE(P4_EVENT_RETIRED_BRANCH_TYPE) = P4_OPCODE_PACK(0x04, 0x02), /* * MSR_P4_TBPU_ESCR0: 4, 5 * MSR_P4_TBPU_ESCR1: 6, 7 */ -#define P4_RESOURCE_STALL P4_EVENT_PACK(0x01, 0x01) + P4_OPCODE(P4_EVENT_RESOURCE_STALL) = P4_OPCODE_PACK(0x01, 0x01), /* * MSR_P4_ALF_ESCR0: 12, 13, 16 * MSR_P4_ALF_ESCR1: 14, 15, 17 */ -#define P4_WC_BUFFER P4_EVENT_PACK(0x05, 0x05) + P4_OPCODE(P4_EVENT_WC_BUFFER) = P4_OPCODE_PACK(0x05, 0x05), /* * MSR_P4_DAC_ESCR0: 8, 9 * MSR_P4_DAC_ESCR1: 10, 11 */ -#define P4_B2B_CYCLES P4_EVENT_PACK(0x16, 0x03) + P4_OPCODE(P4_EVENT_B2B_CYCLES) = P4_OPCODE_PACK(0x16, 0x03), /* * MSR_P4_FSB_ESCR0: 0, 1 * MSR_P4_FSB_ESCR1: 2, 3 */ -#define P4_BNR P4_EVENT_PACK(0x08, 0x03) + P4_OPCODE(P4_EVENT_BNR) = P4_OPCODE_PACK(0x08, 0x03), /* * MSR_P4_FSB_ESCR0: 0, 1 * MSR_P4_FSB_ESCR1: 2, 3 */ -#define P4_SNOOP P4_EVENT_PACK(0x06, 0x03) + P4_OPCODE(P4_EVENT_SNOOP) = P4_OPCODE_PACK(0x06, 0x03), /* * MSR_P4_FSB_ESCR0: 0, 1 * MSR_P4_FSB_ESCR1: 2, 3 */ -#define P4_RESPONSE P4_EVENT_PACK(0x04, 0x03) + P4_OPCODE(P4_EVENT_RESPONSE) = P4_OPCODE_PACK(0x04, 0x03), /* * MSR_P4_FSB_ESCR0: 0, 1 * MSR_P4_FSB_ESCR1: 2, 3 */ -#define P4_FRONT_END_EVENT P4_EVENT_PACK(0x08, 0x05) + P4_OPCODE(P4_EVENT_FRONT_END_EVENT) = P4_OPCODE_PACK(0x08, 0x05), /* * MSR_P4_CRU_ESCR2: 12, 13, 16 * MSR_P4_CRU_ESCR3: 14, 15, 17 */ -#define P4_EXECUTION_EVENT P4_EVENT_PACK(0x0c, 0x05) + P4_OPCODE(P4_EVENT_EXECUTION_EVENT) = P4_OPCODE_PACK(0x0c, 0x05), /* * MSR_P4_CRU_ESCR2: 12, 13, 16 * MSR_P4_CRU_ESCR3: 14, 15, 17 */ -#define P4_REPLAY_EVENT P4_EVENT_PACK(0x09, 0x05) + P4_OPCODE(P4_EVENT_REPLAY_EVENT) = P4_OPCODE_PACK(0x09, 0x05), /* * MSR_P4_CRU_ESCR2: 12, 13, 16 * MSR_P4_CRU_ESCR3: 14, 15, 17 */ -#define P4_INSTR_RETIRED P4_EVENT_PACK(0x02, 0x04) + P4_OPCODE(P4_EVENT_INSTR_RETIRED) = P4_OPCODE_PACK(0x02, 0x04), /* * MSR_P4_CRU_ESCR0: 12, 13, 16 * MSR_P4_CRU_ESCR1: 14, 15, 17 */ -#define P4_UOPS_RETIRED P4_EVENT_PACK(0x01, 0x04) + P4_OPCODE(P4_EVENT_UOPS_RETIRED) = P4_OPCODE_PACK(0x01, 0x04), /* * MSR_P4_CRU_ESCR0: 12, 13, 16 * MSR_P4_CRU_ESCR1: 14, 15, 17 */ -#define P4_UOP_TYPE P4_EVENT_PACK(0x02, 0x02) + P4_OPCODE(P4_EVENT_UOP_TYPE) = P4_OPCODE_PACK(0x02, 0x02), /* * MSR_P4_RAT_ESCR0: 12, 13, 16 * MSR_P4_RAT_ESCR1: 14, 15, 17 */ -#define P4_BRANCH_RETIRED P4_EVENT_PACK(0x06, 0x05) + P4_OPCODE(P4_EVENT_BRANCH_RETIRED) = P4_OPCODE_PACK(0x06, 0x05), /* * MSR_P4_CRU_ESCR2: 12, 13, 16 * MSR_P4_CRU_ESCR3: 14, 15, 17 */ -#define P4_MISPRED_BRANCH_RETIRED P4_EVENT_PACK(0x03, 0x04) + P4_OPCODE(P4_EVENT_MISPRED_BRANCH_RETIRED) = P4_OPCODE_PACK(0x03, 0x04), /* * MSR_P4_CRU_ESCR0: 12, 13, 16 * MSR_P4_CRU_ESCR1: 14, 15, 17 */ -#define P4_X87_ASSIST P4_EVENT_PACK(0x03, 0x05) + P4_OPCODE(P4_EVENT_X87_ASSIST) = P4_OPCODE_PACK(0x03, 0x05), /* * MSR_P4_CRU_ESCR2: 12, 13, 16 * MSR_P4_CRU_ESCR3: 14, 15, 17 */ -#define P4_MACHINE_CLEAR P4_EVENT_PACK(0x02, 0x05) + P4_OPCODE(P4_EVENT_MACHINE_CLEAR) = P4_OPCODE_PACK(0x02, 0x05), /* * MSR_P4_CRU_ESCR2: 12, 13, 16 * MSR_P4_CRU_ESCR3: 14, 15, 17 */ -#define P4_INSTR_COMPLETED P4_EVENT_PACK(0x07, 0x04) + P4_OPCODE(P4_EVENT_INSTR_COMPLETED) = P4_OPCODE_PACK(0x07, 0x04), /* * MSR_P4_CRU_ESCR0: 12, 13, 16 * MSR_P4_CRU_ESCR1: 14, 15, 17 */ +}; /* - * a caller should use P4_EVENT_ATTR helper to - * pick the attribute needed, for example + * a caller should use P4_ESCR_EMASK_NAME helper to + * pick the EventMask needed, for example * - * P4_EVENT_ATTR(P4_TC_DELIVER_MODE, DD) + * P4_ESCR_EMASK_NAME(P4_EVENT_TC_DELIVER_MODE, DD) */ -enum P4_EVENTS_ATTR { - P4_MAKE_EVENT_ATTR(P4_TC_DELIVER_MODE, DD, 0), - P4_MAKE_EVENT_ATTR(P4_TC_DELIVER_MODE, DB, 1), - P4_MAKE_EVENT_ATTR(P4_TC_DELIVER_MODE, DI, 2), - P4_MAKE_EVENT_ATTR(P4_TC_DELIVER_MODE, BD, 3), - P4_MAKE_EVENT_ATTR(P4_TC_DELIVER_MODE, BB, 4), - P4_MAKE_EVENT_ATTR(P4_TC_DELIVER_MODE, BI, 5), - P4_MAKE_EVENT_ATTR(P4_TC_DELIVER_MODE, ID, 6), - - P4_MAKE_EVENT_ATTR(P4_BPU_FETCH_REQUEST, TCMISS, 0), - - P4_MAKE_EVENT_ATTR(P4_ITLB_REFERENCE, HIT, 0), - P4_MAKE_EVENT_ATTR(P4_ITLB_REFERENCE, MISS, 1), - P4_MAKE_EVENT_ATTR(P4_ITLB_REFERENCE, HIT_UK, 2), - - P4_MAKE_EVENT_ATTR(P4_MEMORY_CANCEL, ST_RB_FULL, 2), - P4_MAKE_EVENT_ATTR(P4_MEMORY_CANCEL, 64K_CONF, 3), - - P4_MAKE_EVENT_ATTR(P4_MEMORY_COMPLETE, LSC, 0), - P4_MAKE_EVENT_ATTR(P4_MEMORY_COMPLETE, SSC, 1), - - P4_MAKE_EVENT_ATTR(P4_LOAD_PORT_REPLAY, SPLIT_LD, 1), - - P4_MAKE_EVENT_ATTR(P4_STORE_PORT_REPLAY, SPLIT_ST, 1), - - P4_MAKE_EVENT_ATTR(P4_MOB_LOAD_REPLAY, NO_STA, 1), - P4_MAKE_EVENT_ATTR(P4_MOB_LOAD_REPLAY, NO_STD, 3), - P4_MAKE_EVENT_ATTR(P4_MOB_LOAD_REPLAY, PARTIAL_DATA, 4), - P4_MAKE_EVENT_ATTR(P4_MOB_LOAD_REPLAY, UNALGN_ADDR, 5), - - P4_MAKE_EVENT_ATTR(P4_PAGE_WALK_TYPE, DTMISS, 0), - P4_MAKE_EVENT_ATTR(P4_PAGE_WALK_TYPE, ITMISS, 1), - - P4_MAKE_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_2ndL_HITS, 0), - P4_MAKE_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_2ndL_HITE, 1), - P4_MAKE_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_2ndL_HITM, 2), - P4_MAKE_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_3rdL_HITS, 3), - P4_MAKE_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_3rdL_HITE, 4), - P4_MAKE_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_3rdL_HITM, 5), - P4_MAKE_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_2ndL_MISS, 8), - P4_MAKE_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_3rdL_MISS, 9), - P4_MAKE_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, WR_2ndL_MISS, 10), - - P4_MAKE_EVENT_ATTR(P4_IOQ_ALLOCATION, DEFAULT, 0), - P4_MAKE_EVENT_ATTR(P4_IOQ_ALLOCATION, ALL_READ, 5), - P4_MAKE_EVENT_ATTR(P4_IOQ_ALLOCATION, ALL_WRITE, 6), - P4_MAKE_EVENT_ATTR(P4_IOQ_ALLOCATION, MEM_UC, 7), - P4_MAKE_EVENT_ATTR(P4_IOQ_ALLOCATION, MEM_WC, 8), - P4_MAKE_EVENT_ATTR(P4_IOQ_ALLOCATION, MEM_WT, 9), - P4_MAKE_EVENT_ATTR(P4_IOQ_ALLOCATION, MEM_WP, 10), - P4_MAKE_EVENT_ATTR(P4_IOQ_ALLOCATION, MEM_WB, 11), - P4_MAKE_EVENT_ATTR(P4_IOQ_ALLOCATION, OWN, 13), - P4_MAKE_EVENT_ATTR(P4_IOQ_ALLOCATION, OTHER, 14), - P4_MAKE_EVENT_ATTR(P4_IOQ_ALLOCATION, PREFETCH, 15), - - P4_MAKE_EVENT_ATTR(P4_IOQ_ACTIVE_ENTRIES, DEFAULT, 0), - P4_MAKE_EVENT_ATTR(P4_IOQ_ACTIVE_ENTRIES, ALL_READ, 5), - P4_MAKE_EVENT_ATTR(P4_IOQ_ACTIVE_ENTRIES, ALL_WRITE, 6), - P4_MAKE_EVENT_ATTR(P4_IOQ_ACTIVE_ENTRIES, MEM_UC, 7), - P4_MAKE_EVENT_ATTR(P4_IOQ_ACTIVE_ENTRIES, MEM_WC, 8), - P4_MAKE_EVENT_ATTR(P4_IOQ_ACTIVE_ENTRIES, MEM_WT, 9), - P4_MAKE_EVENT_ATTR(P4_IOQ_ACTIVE_ENTRIES, MEM_WP, 10), - P4_MAKE_EVENT_ATTR(P4_IOQ_ACTIVE_ENTRIES, MEM_WB, 11), - P4_MAKE_EVENT_ATTR(P4_IOQ_ACTIVE_ENTRIES, OWN, 13), - P4_MAKE_EVENT_ATTR(P4_IOQ_ACTIVE_ENTRIES, OTHER, 14), - P4_MAKE_EVENT_ATTR(P4_IOQ_ACTIVE_ENTRIES, PREFETCH, 15), - - P4_MAKE_EVENT_ATTR(P4_FSB_DATA_ACTIVITY, DRDY_DRV, 0), - P4_MAKE_EVENT_ATTR(P4_FSB_DATA_ACTIVITY, DRDY_OWN, 1), - P4_MAKE_EVENT_ATTR(P4_FSB_DATA_ACTIVITY, DRDY_OTHER, 2), - P4_MAKE_EVENT_ATTR(P4_FSB_DATA_ACTIVITY, DBSY_DRV, 3), - P4_MAKE_EVENT_ATTR(P4_FSB_DATA_ACTIVITY, DBSY_OWN, 4), - P4_MAKE_EVENT_ATTR(P4_FSB_DATA_ACTIVITY, DBSY_OTHER, 5), - - P4_MAKE_EVENT_ATTR(P4_BSQ_ALLOCATION, REQ_TYPE0, 0), - P4_MAKE_EVENT_ATTR(P4_BSQ_ALLOCATION, REQ_TYPE1, 1), - P4_MAKE_EVENT_ATTR(P4_BSQ_ALLOCATION, REQ_LEN0, 2), - P4_MAKE_EVENT_ATTR(P4_BSQ_ALLOCATION, REQ_LEN1, 3), - P4_MAKE_EVENT_ATTR(P4_BSQ_ALLOCATION, REQ_IO_TYPE, 5), - P4_MAKE_EVENT_ATTR(P4_BSQ_ALLOCATION, REQ_LOCK_TYPE, 6), - P4_MAKE_EVENT_ATTR(P4_BSQ_ALLOCATION, REQ_CACHE_TYPE, 7), - P4_MAKE_EVENT_ATTR(P4_BSQ_ALLOCATION, REQ_SPLIT_TYPE, 8), - P4_MAKE_EVENT_ATTR(P4_BSQ_ALLOCATION, REQ_DEM_TYPE, 9), - P4_MAKE_EVENT_ATTR(P4_BSQ_ALLOCATION, REQ_ORD_TYPE, 10), - P4_MAKE_EVENT_ATTR(P4_BSQ_ALLOCATION, MEM_TYPE0, 11), - P4_MAKE_EVENT_ATTR(P4_BSQ_ALLOCATION, MEM_TYPE1, 12), - P4_MAKE_EVENT_ATTR(P4_BSQ_ALLOCATION, MEM_TYPE2, 13), - - P4_MAKE_EVENT_ATTR(P4_BSQ_ACTIVE_ENTRIES, REQ_TYPE0, 0), - P4_MAKE_EVENT_ATTR(P4_BSQ_ACTIVE_ENTRIES, REQ_TYPE1, 1), - P4_MAKE_EVENT_ATTR(P4_BSQ_ACTIVE_ENTRIES, REQ_LEN0, 2), - P4_MAKE_EVENT_ATTR(P4_BSQ_ACTIVE_ENTRIES, REQ_LEN1, 3), - P4_MAKE_EVENT_ATTR(P4_BSQ_ACTIVE_ENTRIES, REQ_IO_TYPE, 5), - P4_MAKE_EVENT_ATTR(P4_BSQ_ACTIVE_ENTRIES, REQ_LOCK_TYPE, 6), - P4_MAKE_EVENT_ATTR(P4_BSQ_ACTIVE_ENTRIES, REQ_CACHE_TYPE, 7), - P4_MAKE_EVENT_ATTR(P4_BSQ_ACTIVE_ENTRIES, REQ_SPLIT_TYPE, 8), - P4_MAKE_EVENT_ATTR(P4_BSQ_ACTIVE_ENTRIES, REQ_DEM_TYPE, 9), - P4_MAKE_EVENT_ATTR(P4_BSQ_ACTIVE_ENTRIES, REQ_ORD_TYPE, 10), - P4_MAKE_EVENT_ATTR(P4_BSQ_ACTIVE_ENTRIES, MEM_TYPE0, 11), - P4_MAKE_EVENT_ATTR(P4_BSQ_ACTIVE_ENTRIES, MEM_TYPE1, 12), - P4_MAKE_EVENT_ATTR(P4_BSQ_ACTIVE_ENTRIES, MEM_TYPE2, 13), - - P4_MAKE_EVENT_ATTR(P4_SSE_INPUT_ASSIST, ALL, 15), - - P4_MAKE_EVENT_ATTR(P4_PACKED_SP_UOP, ALL, 15), - - P4_MAKE_EVENT_ATTR(P4_PACKED_DP_UOP, ALL, 15), - - P4_MAKE_EVENT_ATTR(P4_SCALAR_SP_UOP, ALL, 15), - - P4_MAKE_EVENT_ATTR(P4_SCALAR_DP_UOP, ALL, 15), - - P4_MAKE_EVENT_ATTR(P4_64BIT_MMX_UOP, ALL, 15), - - P4_MAKE_EVENT_ATTR(P4_128BIT_MMX_UOP, ALL, 15), - - P4_MAKE_EVENT_ATTR(P4_X87_FP_UOP, ALL, 15), - - P4_MAKE_EVENT_ATTR(P4_TC_MISC, FLUSH, 4), - - P4_MAKE_EVENT_ATTR(P4_GLOBAL_POWER_EVENTS, RUNNING, 0), - - P4_MAKE_EVENT_ATTR(P4_TC_MS_XFER, CISC, 0), - - P4_MAKE_EVENT_ATTR(P4_UOP_QUEUE_WRITES, FROM_TC_BUILD, 0), - P4_MAKE_EVENT_ATTR(P4_UOP_QUEUE_WRITES, FROM_TC_DELIVER, 1), - P4_MAKE_EVENT_ATTR(P4_UOP_QUEUE_WRITES, FROM_ROM, 2), - - P4_MAKE_EVENT_ATTR(P4_RETIRED_MISPRED_BRANCH_TYPE, CONDITIONAL, 1), - P4_MAKE_EVENT_ATTR(P4_RETIRED_MISPRED_BRANCH_TYPE, CALL, 2), - P4_MAKE_EVENT_ATTR(P4_RETIRED_MISPRED_BRANCH_TYPE, RETURN, 3), - P4_MAKE_EVENT_ATTR(P4_RETIRED_MISPRED_BRANCH_TYPE, INDIRECT, 4), - - P4_MAKE_EVENT_ATTR(P4_RETIRED_BRANCH_TYPE, CONDITIONAL, 1), - P4_MAKE_EVENT_ATTR(P4_RETIRED_BRANCH_TYPE, CALL, 2), - P4_MAKE_EVENT_ATTR(P4_RETIRED_BRANCH_TYPE, RETURN, 3), - P4_MAKE_EVENT_ATTR(P4_RETIRED_BRANCH_TYPE, INDIRECT, 4), - - P4_MAKE_EVENT_ATTR(P4_RESOURCE_STALL, SBFULL, 5), - - P4_MAKE_EVENT_ATTR(P4_WC_BUFFER, WCB_EVICTS, 0), - P4_MAKE_EVENT_ATTR(P4_WC_BUFFER, WCB_FULL_EVICTS, 1), - - P4_MAKE_EVENT_ATTR(P4_FRONT_END_EVENT, NBOGUS, 0), - P4_MAKE_EVENT_ATTR(P4_FRONT_END_EVENT, BOGUS, 1), - - P4_MAKE_EVENT_ATTR(P4_EXECUTION_EVENT, NBOGUS0, 0), - P4_MAKE_EVENT_ATTR(P4_EXECUTION_EVENT, NBOGUS1, 1), - P4_MAKE_EVENT_ATTR(P4_EXECUTION_EVENT, NBOGUS2, 2), - P4_MAKE_EVENT_ATTR(P4_EXECUTION_EVENT, NBOGUS3, 3), - P4_MAKE_EVENT_ATTR(P4_EXECUTION_EVENT, BOGUS0, 4), - P4_MAKE_EVENT_ATTR(P4_EXECUTION_EVENT, BOGUS1, 5), - P4_MAKE_EVENT_ATTR(P4_EXECUTION_EVENT, BOGUS2, 6), - P4_MAKE_EVENT_ATTR(P4_EXECUTION_EVENT, BOGUS3, 7), - - P4_MAKE_EVENT_ATTR(P4_REPLAY_EVENT, NBOGUS, 0), - P4_MAKE_EVENT_ATTR(P4_REPLAY_EVENT, BOGUS, 1), - - P4_MAKE_EVENT_ATTR(P4_INSTR_RETIRED, NBOGUSNTAG, 0), - P4_MAKE_EVENT_ATTR(P4_INSTR_RETIRED, NBOGUSTAG, 1), - P4_MAKE_EVENT_ATTR(P4_INSTR_RETIRED, BOGUSNTAG, 2), - P4_MAKE_EVENT_ATTR(P4_INSTR_RETIRED, BOGUSTAG, 3), - - P4_MAKE_EVENT_ATTR(P4_UOPS_RETIRED, NBOGUS, 0), - P4_MAKE_EVENT_ATTR(P4_UOPS_RETIRED, BOGUS, 1), +enum P4_ESCR_EMASKS { + P4_GEN_ESCR_EMASK(P4_EVENT_TC_DELIVER_MODE, DD, 0), + P4_GEN_ESCR_EMASK(P4_EVENT_TC_DELIVER_MODE, DB, 1), + P4_GEN_ESCR_EMASK(P4_EVENT_TC_DELIVER_MODE, DI, 2), + P4_GEN_ESCR_EMASK(P4_EVENT_TC_DELIVER_MODE, BD, 3), + P4_GEN_ESCR_EMASK(P4_EVENT_TC_DELIVER_MODE, BB, 4), + P4_GEN_ESCR_EMASK(P4_EVENT_TC_DELIVER_MODE, BI, 5), + P4_GEN_ESCR_EMASK(P4_EVENT_TC_DELIVER_MODE, ID, 6), + + P4_GEN_ESCR_EMASK(P4_EVENT_BPU_FETCH_REQUEST, TCMISS, 0), + + P4_GEN_ESCR_EMASK(P4_EVENT_ITLB_REFERENCE, HIT, 0), + P4_GEN_ESCR_EMASK(P4_EVENT_ITLB_REFERENCE, MISS, 1), + P4_GEN_ESCR_EMASK(P4_EVENT_ITLB_REFERENCE, HIT_UK, 2), + + P4_GEN_ESCR_EMASK(P4_EVENT_MEMORY_CANCEL, ST_RB_FULL, 2), + P4_GEN_ESCR_EMASK(P4_EVENT_MEMORY_CANCEL, 64K_CONF, 3), + + P4_GEN_ESCR_EMASK(P4_EVENT_MEMORY_COMPLETE, LSC, 0), + P4_GEN_ESCR_EMASK(P4_EVENT_MEMORY_COMPLETE, SSC, 1), + + P4_GEN_ESCR_EMASK(P4_EVENT_LOAD_PORT_REPLAY, SPLIT_LD, 1), + + P4_GEN_ESCR_EMASK(P4_EVENT_STORE_PORT_REPLAY, SPLIT_ST, 1), + + P4_GEN_ESCR_EMASK(P4_EVENT_MOB_LOAD_REPLAY, NO_STA, 1), + P4_GEN_ESCR_EMASK(P4_EVENT_MOB_LOAD_REPLAY, NO_STD, 3), + P4_GEN_ESCR_EMASK(P4_EVENT_MOB_LOAD_REPLAY, PARTIAL_DATA, 4), + P4_GEN_ESCR_EMASK(P4_EVENT_MOB_LOAD_REPLAY, UNALGN_ADDR, 5), + + P4_GEN_ESCR_EMASK(P4_EVENT_PAGE_WALK_TYPE, DTMISS, 0), + P4_GEN_ESCR_EMASK(P4_EVENT_PAGE_WALK_TYPE, ITMISS, 1), + + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_HITS, 0), + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_HITE, 1), + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_HITM, 2), + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_HITS, 3), + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_HITE, 4), + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_HITM, 5), + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_MISS, 8), + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_MISS, 9), + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_CACHE_REFERENCE, WR_2ndL_MISS, 10), + + P4_GEN_ESCR_EMASK(P4_EVENT_IOQ_ALLOCATION, DEFAULT, 0), + P4_GEN_ESCR_EMASK(P4_EVENT_IOQ_ALLOCATION, ALL_READ, 5), + P4_GEN_ESCR_EMASK(P4_EVENT_IOQ_ALLOCATION, ALL_WRITE, 6), + P4_GEN_ESCR_EMASK(P4_EVENT_IOQ_ALLOCATION, MEM_UC, 7), + P4_GEN_ESCR_EMASK(P4_EVENT_IOQ_ALLOCATION, MEM_WC, 8), + P4_GEN_ESCR_EMASK(P4_EVENT_IOQ_ALLOCATION, MEM_WT, 9), + P4_GEN_ESCR_EMASK(P4_EVENT_IOQ_ALLOCATION, MEM_WP, 10), + P4_GEN_ESCR_EMASK(P4_EVENT_IOQ_ALLOCATION, MEM_WB, 11), + P4_GEN_ESCR_EMASK(P4_EVENT_IOQ_ALLOCATION, OWN, 13), + P4_GEN_ESCR_EMASK(P4_EVENT_IOQ_ALLOCATION, OTHER, 14), + P4_GEN_ESCR_EMASK(P4_EVENT_IOQ_ALLOCATION, PREFETCH, 15), + + P4_GEN_ESCR_EMASK(P4_EVENT_IOQ_ACTIVE_ENTRIES, DEFAULT, 0), + P4_GEN_ESCR_EMASK(P4_EVENT_IOQ_ACTIVE_ENTRIES, ALL_READ, 5), + P4_GEN_ESCR_EMASK(P4_EVENT_IOQ_ACTIVE_ENTRIES, ALL_WRITE, 6), + P4_GEN_ESCR_EMASK(P4_EVENT_IOQ_ACTIVE_ENTRIES, MEM_UC, 7), + P4_GEN_ESCR_EMASK(P4_EVENT_IOQ_ACTIVE_ENTRIES, MEM_WC, 8), + P4_GEN_ESCR_EMASK(P4_EVENT_IOQ_ACTIVE_ENTRIES, MEM_WT, 9), + P4_GEN_ESCR_EMASK(P4_EVENT_IOQ_ACTIVE_ENTRIES, MEM_WP, 10), + P4_GEN_ESCR_EMASK(P4_EVENT_IOQ_ACTIVE_ENTRIES, MEM_WB, 11), + P4_GEN_ESCR_EMASK(P4_EVENT_IOQ_ACTIVE_ENTRIES, OWN, 13), + P4_GEN_ESCR_EMASK(P4_EVENT_IOQ_ACTIVE_ENTRIES, OTHER, 14), + P4_GEN_ESCR_EMASK(P4_EVENT_IOQ_ACTIVE_ENTRIES, PREFETCH, 15), + + P4_GEN_ESCR_EMASK(P4_EVENT_FSB_DATA_ACTIVITY, DRDY_DRV, 0), + P4_GEN_ESCR_EMASK(P4_EVENT_FSB_DATA_ACTIVITY, DRDY_OWN, 1), + P4_GEN_ESCR_EMASK(P4_EVENT_FSB_DATA_ACTIVITY, DRDY_OTHER, 2), + P4_GEN_ESCR_EMASK(P4_EVENT_FSB_DATA_ACTIVITY, DBSY_DRV, 3), + P4_GEN_ESCR_EMASK(P4_EVENT_FSB_DATA_ACTIVITY, DBSY_OWN, 4), + P4_GEN_ESCR_EMASK(P4_EVENT_FSB_DATA_ACTIVITY, DBSY_OTHER, 5), + + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_ALLOCATION, REQ_TYPE0, 0), + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_ALLOCATION, REQ_TYPE1, 1), + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_ALLOCATION, REQ_LEN0, 2), + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_ALLOCATION, REQ_LEN1, 3), + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_ALLOCATION, REQ_IO_TYPE, 5), + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_ALLOCATION, REQ_LOCK_TYPE, 6), + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_ALLOCATION, REQ_CACHE_TYPE, 7), + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_ALLOCATION, REQ_SPLIT_TYPE, 8), + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_ALLOCATION, REQ_DEM_TYPE, 9), + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_ALLOCATION, REQ_ORD_TYPE, 10), + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_ALLOCATION, MEM_TYPE0, 11), + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_ALLOCATION, MEM_TYPE1, 12), + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_ALLOCATION, MEM_TYPE2, 13), + + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_TYPE0, 0), + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_TYPE1, 1), + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_LEN0, 2), + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_LEN1, 3), + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_IO_TYPE, 5), + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_LOCK_TYPE, 6), + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_CACHE_TYPE, 7), + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_SPLIT_TYPE, 8), + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_DEM_TYPE, 9), + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_ACTIVE_ENTRIES, REQ_ORD_TYPE, 10), + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_ACTIVE_ENTRIES, MEM_TYPE0, 11), + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_ACTIVE_ENTRIES, MEM_TYPE1, 12), + P4_GEN_ESCR_EMASK(P4_EVENT_BSQ_ACTIVE_ENTRIES, MEM_TYPE2, 13), + + P4_GEN_ESCR_EMASK(P4_EVENT_SSE_INPUT_ASSIST, ALL, 15), + + P4_GEN_ESCR_EMASK(P4_EVENT_PACKED_SP_UOP, ALL, 15), + + P4_GEN_ESCR_EMASK(P4_EVENT_PACKED_DP_UOP, ALL, 15), + + P4_GEN_ESCR_EMASK(P4_EVENT_SCALAR_SP_UOP, ALL, 15), + + P4_GEN_ESCR_EMASK(P4_EVENT_SCALAR_DP_UOP, ALL, 15), + + P4_GEN_ESCR_EMASK(P4_EVENT_64BIT_MMX_UOP, ALL, 15), + + P4_GEN_ESCR_EMASK(P4_EVENT_128BIT_MMX_UOP, ALL, 15), + + P4_GEN_ESCR_EMASK(P4_EVENT_X87_FP_UOP, ALL, 15), + + P4_GEN_ESCR_EMASK(P4_EVENT_TC_MISC, FLUSH, 4), + + P4_GEN_ESCR_EMASK(P4_EVENT_GLOBAL_POWER_EVENTS, RUNNING, 0), + + P4_GEN_ESCR_EMASK(P4_EVENT_TC_MS_XFER, CISC, 0), + + P4_GEN_ESCR_EMASK(P4_EVENT_UOP_QUEUE_WRITES, FROM_TC_BUILD, 0), + P4_GEN_ESCR_EMASK(P4_EVENT_UOP_QUEUE_WRITES, FROM_TC_DELIVER, 1), + P4_GEN_ESCR_EMASK(P4_EVENT_UOP_QUEUE_WRITES, FROM_ROM, 2), + + P4_GEN_ESCR_EMASK(P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE, CONDITIONAL, 1), + P4_GEN_ESCR_EMASK(P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE, CALL, 2), + P4_GEN_ESCR_EMASK(P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE, RETURN, 3), + P4_GEN_ESCR_EMASK(P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE, INDIRECT, 4), + + P4_GEN_ESCR_EMASK(P4_EVENT_RETIRED_BRANCH_TYPE, CONDITIONAL, 1), + P4_GEN_ESCR_EMASK(P4_EVENT_RETIRED_BRANCH_TYPE, CALL, 2), + P4_GEN_ESCR_EMASK(P4_EVENT_RETIRED_BRANCH_TYPE, RETURN, 3), + P4_GEN_ESCR_EMASK(P4_EVENT_RETIRED_BRANCH_TYPE, INDIRECT, 4), + + P4_GEN_ESCR_EMASK(P4_EVENT_RESOURCE_STALL, SBFULL, 5), + + P4_GEN_ESCR_EMASK(P4_EVENT_WC_BUFFER, WCB_EVICTS, 0), + P4_GEN_ESCR_EMASK(P4_EVENT_WC_BUFFER, WCB_FULL_EVICTS, 1), + + P4_GEN_ESCR_EMASK(P4_EVENT_FRONT_END_EVENT, NBOGUS, 0), + P4_GEN_ESCR_EMASK(P4_EVENT_FRONT_END_EVENT, BOGUS, 1), + + P4_GEN_ESCR_EMASK(P4_EVENT_EXECUTION_EVENT, NBOGUS0, 0), + P4_GEN_ESCR_EMASK(P4_EVENT_EXECUTION_EVENT, NBOGUS1, 1), + P4_GEN_ESCR_EMASK(P4_EVENT_EXECUTION_EVENT, NBOGUS2, 2), + P4_GEN_ESCR_EMASK(P4_EVENT_EXECUTION_EVENT, NBOGUS3, 3), + P4_GEN_ESCR_EMASK(P4_EVENT_EXECUTION_EVENT, BOGUS0, 4), + P4_GEN_ESCR_EMASK(P4_EVENT_EXECUTION_EVENT, BOGUS1, 5), + P4_GEN_ESCR_EMASK(P4_EVENT_EXECUTION_EVENT, BOGUS2, 6), + P4_GEN_ESCR_EMASK(P4_EVENT_EXECUTION_EVENT, BOGUS3, 7), + + P4_GEN_ESCR_EMASK(P4_EVENT_REPLAY_EVENT, NBOGUS, 0), + P4_GEN_ESCR_EMASK(P4_EVENT_REPLAY_EVENT, BOGUS, 1), + + P4_GEN_ESCR_EMASK(P4_EVENT_INSTR_RETIRED, NBOGUSNTAG, 0), + P4_GEN_ESCR_EMASK(P4_EVENT_INSTR_RETIRED, NBOGUSTAG, 1), + P4_GEN_ESCR_EMASK(P4_EVENT_INSTR_RETIRED, BOGUSNTAG, 2), + P4_GEN_ESCR_EMASK(P4_EVENT_INSTR_RETIRED, BOGUSTAG, 3), + + P4_GEN_ESCR_EMASK(P4_EVENT_UOPS_RETIRED, NBOGUS, 0), + P4_GEN_ESCR_EMASK(P4_EVENT_UOPS_RETIRED, BOGUS, 1), - P4_MAKE_EVENT_ATTR(P4_UOP_TYPE, TAGLOADS, 1), - P4_MAKE_EVENT_ATTR(P4_UOP_TYPE, TAGSTORES, 2), - - P4_MAKE_EVENT_ATTR(P4_BRANCH_RETIRED, MMNP, 0), - P4_MAKE_EVENT_ATTR(P4_BRANCH_RETIRED, MMNM, 1), - P4_MAKE_EVENT_ATTR(P4_BRANCH_RETIRED, MMTP, 2), - P4_MAKE_EVENT_ATTR(P4_BRANCH_RETIRED, MMTM, 3), + P4_GEN_ESCR_EMASK(P4_EVENT_UOP_TYPE, TAGLOADS, 1), + P4_GEN_ESCR_EMASK(P4_EVENT_UOP_TYPE, TAGSTORES, 2), + + P4_GEN_ESCR_EMASK(P4_EVENT_BRANCH_RETIRED, MMNP, 0), + P4_GEN_ESCR_EMASK(P4_EVENT_BRANCH_RETIRED, MMNM, 1), + P4_GEN_ESCR_EMASK(P4_EVENT_BRANCH_RETIRED, MMTP, 2), + P4_GEN_ESCR_EMASK(P4_EVENT_BRANCH_RETIRED, MMTM, 3), - P4_MAKE_EVENT_ATTR(P4_MISPRED_BRANCH_RETIRED, NBOGUS, 0), + P4_GEN_ESCR_EMASK(P4_EVENT_MISPRED_BRANCH_RETIRED, NBOGUS, 0), - P4_MAKE_EVENT_ATTR(P4_X87_ASSIST, FPSU, 0), - P4_MAKE_EVENT_ATTR(P4_X87_ASSIST, FPSO, 1), - P4_MAKE_EVENT_ATTR(P4_X87_ASSIST, POAO, 2), - P4_MAKE_EVENT_ATTR(P4_X87_ASSIST, POAU, 3), - P4_MAKE_EVENT_ATTR(P4_X87_ASSIST, PREA, 4), + P4_GEN_ESCR_EMASK(P4_EVENT_X87_ASSIST, FPSU, 0), + P4_GEN_ESCR_EMASK(P4_EVENT_X87_ASSIST, FPSO, 1), + P4_GEN_ESCR_EMASK(P4_EVENT_X87_ASSIST, POAO, 2), + P4_GEN_ESCR_EMASK(P4_EVENT_X87_ASSIST, POAU, 3), + P4_GEN_ESCR_EMASK(P4_EVENT_X87_ASSIST, PREA, 4), - P4_MAKE_EVENT_ATTR(P4_MACHINE_CLEAR, CLEAR, 0), - P4_MAKE_EVENT_ATTR(P4_MACHINE_CLEAR, MOCLEAR, 1), - P4_MAKE_EVENT_ATTR(P4_MACHINE_CLEAR, SMCLEAR, 2), + P4_GEN_ESCR_EMASK(P4_EVENT_MACHINE_CLEAR, CLEAR, 0), + P4_GEN_ESCR_EMASK(P4_EVENT_MACHINE_CLEAR, MOCLEAR, 1), + P4_GEN_ESCR_EMASK(P4_EVENT_MACHINE_CLEAR, SMCLEAR, 2), - P4_MAKE_EVENT_ATTR(P4_INSTR_COMPLETED, NBOGUS, 0), - P4_MAKE_EVENT_ATTR(P4_INSTR_COMPLETED, BOGUS, 1), + P4_GEN_ESCR_EMASK(P4_EVENT_INSTR_COMPLETED, NBOGUS, 0), + P4_GEN_ESCR_EMASK(P4_EVENT_INSTR_COMPLETED, BOGUS, 1), }; -enum { - KEY_P4_L1D_OP_READ_RESULT_MISS = PERF_COUNT_HW_MAX, - KEY_P4_LL_OP_READ_RESULT_MISS, - KEY_P4_DTLB_OP_READ_RESULT_MISS, - KEY_P4_DTLB_OP_WRITE_RESULT_MISS, - KEY_P4_ITLB_OP_READ_RESULT_ACCESS, - KEY_P4_ITLB_OP_READ_RESULT_MISS, - KEY_P4_UOP_TYPE, +/* P4 PEBS: stale for a while */ +#define P4_PEBS_METRIC_MASK 0x00001fffU +#define P4_PEBS_UOB_TAG 0x01000000U +#define P4_PEBS_ENABLE 0x02000000U + +/* Replay metrics for MSR_IA32_PEBS_ENABLE and MSR_P4_PEBS_MATRIX_VERT */ +#define P4_PEBS__1stl_cache_load_miss_retired 0x3000001 +#define P4_PEBS__2ndl_cache_load_miss_retired 0x3000002 +#define P4_PEBS__dtlb_load_miss_retired 0x3000004 +#define P4_PEBS__dtlb_store_miss_retired 0x3000004 +#define P4_PEBS__dtlb_all_miss_retired 0x3000004 +#define P4_PEBS__tagged_mispred_branch 0x3018000 +#define P4_PEBS__mob_load_replay_retired 0x3000200 +#define P4_PEBS__split_load_retired 0x3000400 +#define P4_PEBS__split_store_retired 0x3000400 + +#define P4_VERT__1stl_cache_load_miss_retired 0x0000001 +#define P4_VERT__2ndl_cache_load_miss_retired 0x0000001 +#define P4_VERT__dtlb_load_miss_retired 0x0000001 +#define P4_VERT__dtlb_store_miss_retired 0x0000002 +#define P4_VERT__dtlb_all_miss_retired 0x0000003 +#define P4_VERT__tagged_mispred_branch 0x0000010 +#define P4_VERT__mob_load_replay_retired 0x0000001 +#define P4_VERT__split_load_retired 0x0000001 +#define P4_VERT__split_store_retired 0x0000002 + +enum P4_CACHE_EVENTS { + P4_CACHE__NONE, + + P4_CACHE__1stl_cache_load_miss_retired, + P4_CACHE__2ndl_cache_load_miss_retired, + P4_CACHE__dtlb_load_miss_retired, + P4_CACHE__dtlb_store_miss_retired, + P4_CACHE__itlb_reference_hit, + P4_CACHE__itlb_reference_miss, + + P4_CACHE__MAX }; #endif /* PERF_EVENT_P4_H */ diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index b8a811a..f8fe069 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c @@ -11,35 +11,281 @@ #include +#define P4_CNTR_LIMIT 3 /* * array indices: 0,1 - HT threads, used with HT enabled cpu */ -struct p4_event_template { - u32 opcode; /* ESCR event + CCCR selector */ - u64 config; /* packed predefined bits */ - int dep; /* upstream dependency event index */ - int key; /* index into p4_templates */ - u64 msr; /* - * the high 32 bits set into MSR_IA32_PEBS_ENABLE and - * the low 32 bits set into MSR_P4_PEBS_MATRIX_VERT - * for cache events - */ - unsigned int emask; /* ESCR EventMask */ - unsigned int escr_msr[2]; /* ESCR MSR for this event */ - unsigned int cntr[2]; /* counter index (offset) */ +struct p4_event_bind { + unsigned int opcode; /* Event code and ESCR selector */ + unsigned int escr_msr[2]; /* ESCR MSR for this event */ + unsigned char cntr[2][P4_CNTR_LIMIT]; /* counter index (offset), -1 on abscence */ }; -struct p4_pmu_res { - /* maps hw_conf::idx into template for ESCR sake */ - struct p4_event_template *tpl[ARCH_P4_MAX_CCCR]; +struct p4_cache_event_bind { + unsigned int metric_pebs; + unsigned int metric_vert; }; -static DEFINE_PER_CPU(struct p4_pmu_res, p4_pmu_config); +#define P4_GEN_CACHE_EVENT_BIND(name) \ + [P4_CACHE__##name] = { \ + .metric_pebs = P4_PEBS__##name, \ + .metric_vert = P4_VERT__##name, \ + } + +static struct p4_cache_event_bind p4_cache_event_bind_map[] = { + P4_GEN_CACHE_EVENT_BIND(1stl_cache_load_miss_retired), + P4_GEN_CACHE_EVENT_BIND(2ndl_cache_load_miss_retired), + P4_GEN_CACHE_EVENT_BIND(dtlb_load_miss_retired), + P4_GEN_CACHE_EVENT_BIND(dtlb_store_miss_retired), +}; + +/* + * Note that we don't use CCCR1 here, there is an + * exception for P4_BSQ_ALLOCATION but we just have + * no workaround + * + * consider this binding as resources which particular + * event may borrow, it doesn't contain EventMask, + * Tags and friends -- they are left to a caller + */ +static struct p4_event_bind p4_event_bind_map[] = { + [P4_EVENT_TC_DELIVER_MODE] = { + .opcode = P4_OPCODE(P4_EVENT_TC_DELIVER_MODE), + .escr_msr = { MSR_P4_TC_ESCR0, MSR_P4_TC_ESCR1 }, + .cntr = { {4, 5, -1}, {6, 7, -1} }, + }, + [P4_EVENT_BPU_FETCH_REQUEST] = { + .opcode = P4_OPCODE(P4_EVENT_BPU_FETCH_REQUEST), + .escr_msr = { MSR_P4_BPU_ESCR0, MSR_P4_BPU_ESCR1 }, + .cntr = { {0, -1, -1}, {2, -1, -1} }, + }, + [P4_EVENT_ITLB_REFERENCE] = { + .opcode = P4_OPCODE(P4_EVENT_ITLB_REFERENCE), + .escr_msr = { MSR_P4_ITLB_ESCR0, MSR_P4_ITLB_ESCR1 }, + .cntr = { {0, -1, -1}, {2, -1, -1} }, + }, + [P4_EVENT_MEMORY_CANCEL] = { + .opcode = P4_OPCODE(P4_EVENT_MEMORY_CANCEL), + .escr_msr = { MSR_P4_DAC_ESCR0, MSR_P4_DAC_ESCR1 }, + .cntr = { {8, 9, -1}, {10, 11, -1} }, + }, + [P4_EVENT_MEMORY_COMPLETE] = { + .opcode = P4_OPCODE(P4_EVENT_MEMORY_COMPLETE), + .escr_msr = { MSR_P4_SAAT_ESCR0 , MSR_P4_SAAT_ESCR1 }, + .cntr = { {8, 9, -1}, {10, 11, -1} }, + }, + [P4_EVENT_LOAD_PORT_REPLAY] = { + .opcode = P4_OPCODE(P4_EVENT_LOAD_PORT_REPLAY), + .escr_msr = { MSR_P4_SAAT_ESCR0, MSR_P4_SAAT_ESCR1 }, + .cntr = { {8, 9, -1}, {10, 11, -1} }, + }, + [P4_EVENT_STORE_PORT_REPLAY] = { + .opcode = P4_OPCODE(P4_EVENT_STORE_PORT_REPLAY), + .escr_msr = { MSR_P4_SAAT_ESCR0 , MSR_P4_SAAT_ESCR1 }, + .cntr = { {8, 9, -1}, {10, 11, -1} }, + }, + [P4_EVENT_MOB_LOAD_REPLAY] = { + .opcode = P4_OPCODE(P4_EVENT_MOB_LOAD_REPLAY), + .escr_msr = { MSR_P4_MOB_ESCR0, MSR_P4_MOB_ESCR1 }, + .cntr = { {0, -1, -1}, {2, -1, -1} }, + }, + [P4_EVENT_PAGE_WALK_TYPE] = { + .opcode = P4_OPCODE(P4_EVENT_PAGE_WALK_TYPE), + .escr_msr = { MSR_P4_PMH_ESCR0, MSR_P4_PMH_ESCR1 }, + .cntr = { {0, -1, -1}, {2, -1, -1} }, + }, + [P4_EVENT_BSQ_CACHE_REFERENCE] = { + .opcode = P4_OPCODE(P4_EVENT_BSQ_CACHE_REFERENCE), + .escr_msr = { MSR_P4_BSU_ESCR0, MSR_P4_BSU_ESCR1 }, + .cntr = { {0, -1, -1}, {2, -1, -1} }, + }, + [P4_EVENT_IOQ_ALLOCATION] = { + .opcode = P4_OPCODE(P4_EVENT_IOQ_ALLOCATION), + .escr_msr = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 }, + .cntr = { {0, -1, -1}, {2, -1, -1} }, + }, + [P4_EVENT_IOQ_ACTIVE_ENTRIES] = { /* shared ESCR */ + .opcode = P4_OPCODE(P4_EVENT_IOQ_ACTIVE_ENTRIES), + .escr_msr = { MSR_P4_FSB_ESCR1, MSR_P4_FSB_ESCR1 }, + .cntr = { {2, -1, -1}, {3, -1, -1} }, + }, + [P4_EVENT_FSB_DATA_ACTIVITY] = { + .opcode = P4_OPCODE(P4_EVENT_FSB_DATA_ACTIVITY), + .escr_msr = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 }, + .cntr = { {0, -1, -1}, {2, -1, -1} }, + }, + [P4_EVENT_BSQ_ALLOCATION] = { /* shared ESCR, broken CCCR1 */ + .opcode = P4_OPCODE(P4_EVENT_BSQ_ALLOCATION), + .escr_msr = { MSR_P4_BSU_ESCR0, MSR_P4_BSU_ESCR0 }, + .cntr = { {0, -1, -1}, {1, -1, -1} }, + }, + [P4_EVENT_BSQ_ACTIVE_ENTRIES] = { /* shared ESCR */ + .opcode = P4_OPCODE(P4_EVENT_BSQ_ACTIVE_ENTRIES), + .escr_msr = { MSR_P4_BSU_ESCR1 , MSR_P4_BSU_ESCR1 }, + .cntr = { {2, -1, -1}, {3, -1, -1} }, + }, + [P4_EVENT_SSE_INPUT_ASSIST] = { + .opcode = P4_OPCODE(P4_EVENT_SSE_INPUT_ASSIST), + .escr_msr = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 }, + .cntr = { {8, 9, -1}, {10, 11, -1} }, + }, + [P4_EVENT_PACKED_SP_UOP] = { + .opcode = P4_OPCODE(P4_EVENT_PACKED_SP_UOP), + .escr_msr = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 }, + .cntr = { {8, 9, -1}, {10, 11, -1} }, + }, + [P4_EVENT_PACKED_DP_UOP] = { + .opcode = P4_OPCODE(P4_EVENT_PACKED_DP_UOP), + .escr_msr = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 }, + .cntr = { {8, 9, -1}, {10, 11, -1} }, + }, + [P4_EVENT_SCALAR_SP_UOP] = { + .opcode = P4_OPCODE(P4_EVENT_SCALAR_SP_UOP), + .escr_msr = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 }, + .cntr = { {8, 9, -1}, {10, 11, -1} }, + }, + [P4_EVENT_SCALAR_DP_UOP] = { + .opcode = P4_OPCODE(P4_EVENT_SCALAR_DP_UOP), + .escr_msr = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 }, + .cntr = { {8, 9, -1}, {10, 11, -1} }, + }, + [P4_EVENT_64BIT_MMX_UOP] = { + .opcode = P4_OPCODE(P4_EVENT_64BIT_MMX_UOP), + .escr_msr = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 }, + .cntr = { {8, 9, -1}, {10, 11, -1} }, + }, + [P4_EVENT_128BIT_MMX_UOP] = { + .opcode = P4_OPCODE(P4_EVENT_128BIT_MMX_UOP), + .escr_msr = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 }, + .cntr = { {8, 9, -1}, {10, 11, -1} }, + }, + [P4_EVENT_X87_FP_UOP] = { + .opcode = P4_OPCODE(P4_EVENT_X87_FP_UOP), + .escr_msr = { MSR_P4_FIRM_ESCR0, MSR_P4_FIRM_ESCR1 }, + .cntr = { {8, 9, -1}, {10, 11, -1} }, + }, + [P4_EVENT_TC_MISC] = { + .opcode = P4_OPCODE(P4_EVENT_TC_MISC), + .escr_msr = { MSR_P4_TC_ESCR0, MSR_P4_TC_ESCR1 }, + .cntr = { {4, 5, -1}, {6, 7, -1} }, + }, + [P4_EVENT_GLOBAL_POWER_EVENTS] = { + .opcode = P4_OPCODE(P4_EVENT_GLOBAL_POWER_EVENTS), + .escr_msr = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 }, + .cntr = { {0, -1, -1}, {2, -1, -1} }, + }, + [P4_EVENT_TC_MS_XFER] = { + .opcode = P4_OPCODE(P4_EVENT_TC_MS_XFER), + .escr_msr = { MSR_P4_MS_ESCR0, MSR_P4_MS_ESCR1 }, + .cntr = { {4, 5, -1}, {6, 7, -1} }, + }, + [P4_EVENT_UOP_QUEUE_WRITES] = { + .opcode = P4_OPCODE(P4_EVENT_UOP_QUEUE_WRITES), + .escr_msr = { MSR_P4_MS_ESCR0, MSR_P4_MS_ESCR1 }, + .cntr = { {4, 5, -1}, {6, 7, -1} }, + }, + [P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE] = { + .opcode = P4_OPCODE(P4_EVENT_RETIRED_MISPRED_BRANCH_TYPE), + .escr_msr = { MSR_P4_TBPU_ESCR0 , MSR_P4_TBPU_ESCR0 }, + .cntr = { {4, 5, -1}, {6, 7, -1} }, + }, + [P4_EVENT_RETIRED_BRANCH_TYPE] = { + .opcode = P4_OPCODE(P4_EVENT_RETIRED_BRANCH_TYPE), + .escr_msr = { MSR_P4_TBPU_ESCR0 , MSR_P4_TBPU_ESCR1 }, + .cntr = { {4, 5, -1}, {6, 7, -1} }, + }, + [P4_EVENT_RESOURCE_STALL] = { + .opcode = P4_OPCODE(P4_EVENT_RESOURCE_STALL), + .escr_msr = { MSR_P4_ALF_ESCR0, MSR_P4_ALF_ESCR1 }, + .cntr = { {12, 13, 16}, {14, 15, 17} }, + }, + [P4_EVENT_WC_BUFFER] = { + .opcode = P4_OPCODE(P4_EVENT_WC_BUFFER), + .escr_msr = { MSR_P4_DAC_ESCR0, MSR_P4_DAC_ESCR1 }, + .cntr = { {8, 9, -1}, {10, 11, -1} }, + }, + [P4_EVENT_B2B_CYCLES] = { + .opcode = P4_OPCODE(P4_EVENT_B2B_CYCLES), + .escr_msr = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 }, + .cntr = { {0, -1, -1}, {2, -1, -1} }, + }, + [P4_EVENT_BNR] = { + .opcode = P4_OPCODE(P4_EVENT_BNR), + .escr_msr = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 }, + .cntr = { {0, -1, -1}, {2, -1, -1} }, + }, + [P4_EVENT_SNOOP] = { + .opcode = P4_OPCODE(P4_EVENT_SNOOP), + .escr_msr = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 }, + .cntr = { {0, -1, -1}, {2, -1, -1} }, + }, + [P4_EVENT_RESPONSE] = { + .opcode = P4_OPCODE(P4_EVENT_RESPONSE), + .escr_msr = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 }, + .cntr = { {0, -1, -1}, {2, -1, -1} }, + }, + [P4_EVENT_FRONT_END_EVENT] = { + .opcode = P4_OPCODE(P4_EVENT_FRONT_END_EVENT), + .escr_msr = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 }, + .cntr = { {12, 13, 16}, {14, 15, 17} }, + }, + [P4_EVENT_EXECUTION_EVENT] = { + .opcode = P4_OPCODE(P4_EVENT_EXECUTION_EVENT), + .escr_msr = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 }, + .cntr = { {12, 13, 16}, {14, 15, 17} }, + }, + [P4_EVENT_REPLAY_EVENT] = { + .opcode = P4_OPCODE(P4_EVENT_REPLAY_EVENT), + .escr_msr = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 }, + .cntr = { {12, 13, 16}, {14, 15, 17} }, + }, + [P4_EVENT_INSTR_RETIRED] = { + .opcode = P4_OPCODE(P4_EVENT_INSTR_RETIRED), + .escr_msr = { MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR1 }, + .cntr = { {12, 13, 16}, {14, 15, 17} }, + }, + [P4_EVENT_UOPS_RETIRED] = { + .opcode = P4_OPCODE(P4_EVENT_UOPS_RETIRED), + .escr_msr = { MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR1 }, + .cntr = { {12, 13, 16}, {14, 15, 17} }, + }, + [P4_EVENT_UOP_TYPE] = { + .opcode = P4_OPCODE(P4_EVENT_UOP_TYPE), + .escr_msr = { MSR_P4_RAT_ESCR0, MSR_P4_RAT_ESCR1 }, + .cntr = { {12, 13, 16}, {14, 15, 17} }, + }, + [P4_EVENT_BRANCH_RETIRED] = { + .opcode = P4_OPCODE(P4_EVENT_BRANCH_RETIRED), + .escr_msr = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 }, + .cntr = { {12, 13, 16}, {14, 15, 17} }, + }, + [P4_EVENT_MISPRED_BRANCH_RETIRED] = { + .opcode = P4_OPCODE(P4_EVENT_MISPRED_BRANCH_RETIRED), + .escr_msr = { MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR1 }, + .cntr = { {12, 13, 16}, {14, 15, 17} }, + }, + [P4_EVENT_X87_ASSIST] = { + .opcode = P4_OPCODE(P4_EVENT_X87_ASSIST), + .escr_msr = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 }, + .cntr = { {12, 13, 16}, {14, 15, 17} }, + }, + [P4_EVENT_MACHINE_CLEAR] = { + .opcode = P4_OPCODE(P4_EVENT_MACHINE_CLEAR), + .escr_msr = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR3 }, + .cntr = { {12, 13, 16}, {14, 15, 17} }, + }, + [P4_EVENT_INSTR_COMPLETED] = { + .opcode = P4_OPCODE(P4_EVENT_INSTR_COMPLETED), + .escr_msr = { MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR1 }, + .cntr = { {12, 13, 16}, {14, 15, 17} }, + }, +}; -#define P4_CACHE_EVENT_CONFIG(event, bit) \ - p4_config_pack_escr(P4_EVENT_UNPACK_EVENT(event) << P4_EVNTSEL_EVENT_SHIFT) | \ - p4_config_pack_escr((event##_##bit) << P4_EVNTSEL_EVENTMASK_SHIFT) | \ - p4_config_pack_cccr(P4_EVENT_UNPACK_SELECTOR(event) << P4_CCCR_ESCR_SELECT_SHIFT) +#define P4_GEN_CACHE_EVENT(event, bit, cache_event) \ + p4_config_pack_escr(P4_ESCR_EVENT(event) | \ + P4_ESCR_EMASK_BIT(event, bit)) | \ + p4_config_pack_cccr(cache_event | \ + P4_CCCR_ESEL(P4_OPCODE_ESEL(P4_OPCODE(event)))) static __initconst u64 p4_hw_cache_event_ids [PERF_COUNT_HW_CACHE_MAX] @@ -49,42 +295,35 @@ static __initconst u64 p4_hw_cache_event_ids [ C(L1D ) ] = { [ C(OP_READ) ] = { [ C(RESULT_ACCESS) ] = 0x0, - /* 1stL_cache_load_miss_retired */ - [ C(RESULT_MISS) ] = P4_CACHE_EVENT_CONFIG(P4_REPLAY_EVENT, NBOGUS) - | KEY_P4_L1D_OP_READ_RESULT_MISS, + [ C(RESULT_MISS) ] = P4_GEN_CACHE_EVENT(P4_EVENT_REPLAY_EVENT, NBOGUS, + P4_CACHE__1stl_cache_load_miss_retired), }, }, [ C(LL ) ] = { [ C(OP_READ) ] = { [ C(RESULT_ACCESS) ] = 0x0, - /* 2ndL_cache_load_miss_retired */ - [ C(RESULT_MISS) ] = P4_CACHE_EVENT_CONFIG(P4_REPLAY_EVENT, NBOGUS) - | KEY_P4_LL_OP_READ_RESULT_MISS, + [ C(RESULT_MISS) ] = P4_GEN_CACHE_EVENT(P4_EVENT_REPLAY_EVENT, NBOGUS, + P4_CACHE__2ndl_cache_load_miss_retired), }, - }, +}, [ C(DTLB) ] = { [ C(OP_READ) ] = { [ C(RESULT_ACCESS) ] = 0x0, - /* DTLB_load_miss_retired */ - [ C(RESULT_MISS) ] = P4_CACHE_EVENT_CONFIG(P4_REPLAY_EVENT, NBOGUS) - | KEY_P4_DTLB_OP_READ_RESULT_MISS, + [ C(RESULT_MISS) ] = P4_GEN_CACHE_EVENT(P4_EVENT_REPLAY_EVENT, NBOGUS, + P4_CACHE__dtlb_load_miss_retired), }, [ C(OP_WRITE) ] = { [ C(RESULT_ACCESS) ] = 0x0, - /* DTLB_store_miss_retired */ - [ C(RESULT_MISS) ] = P4_CACHE_EVENT_CONFIG(P4_REPLAY_EVENT, NBOGUS) - | KEY_P4_DTLB_OP_WRITE_RESULT_MISS, + [ C(RESULT_MISS) ] = P4_GEN_CACHE_EVENT(P4_EVENT_REPLAY_EVENT, NBOGUS, + P4_CACHE__dtlb_store_miss_retired), }, }, [ C(ITLB) ] = { [ C(OP_READ) ] = { - /* ITLB_reference.HIT */ - [ C(RESULT_ACCESS) ] = P4_CACHE_EVENT_CONFIG(P4_ITLB_REFERENCE, HIT) - | KEY_P4_ITLB_OP_READ_RESULT_ACCESS, - - /* ITLB_reference.MISS */ - [ C(RESULT_MISS) ] = P4_CACHE_EVENT_CONFIG(P4_ITLB_REFERENCE, MISS) - | KEY_P4_ITLB_OP_READ_RESULT_MISS, + [ C(RESULT_ACCESS) ] = P4_GEN_CACHE_EVENT(P4_EVENT_ITLB_REFERENCE, HIT, + P4_CACHE__itlb_reference_hit), + [ C(RESULT_MISS) ] = P4_GEN_CACHE_EVENT(P4_EVENT_ITLB_REFERENCE, MISS, + P4_CACHE__itlb_reference_miss), }, [ C(OP_WRITE) ] = { [ C(RESULT_ACCESS) ] = -1, @@ -97,220 +336,90 @@ static __initconst u64 p4_hw_cache_event_ids }, }; -/* - * WARN: CCCR1 doesn't have a working enable bit so try to not - * use it if possible - * - * Also as only we start to support raw events we will need to - * append _all_ P4_EVENT_PACK'ed events here - */ -struct p4_event_template p4_templates[] = { - [0] = { - .opcode = P4_GLOBAL_POWER_EVENTS, - .config = 0, - .dep = -1, - .key = 0, - .emask = - P4_EVENT_ATTR(P4_GLOBAL_POWER_EVENTS, RUNNING), - .escr_msr = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 }, - .cntr = { 0, 2 }, - }, - [1] = { - .opcode = P4_INSTR_RETIRED, - .config = 0, - .dep = -1, /* needs front-end tagging */ - .key = 1, - .emask = - P4_EVENT_ATTR(P4_INSTR_RETIRED, NBOGUSNTAG) | - P4_EVENT_ATTR(P4_INSTR_RETIRED, BOGUSNTAG), - .escr_msr = { MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR1 }, - .cntr = { 12, 14 }, - }, - [2] = { - .opcode = P4_BSQ_CACHE_REFERENCE, - .config = 0, - .dep = -1, - .key = 2, - .emask = - P4_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_2ndL_HITS) | - P4_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_2ndL_HITE) | - P4_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_2ndL_HITM) | - P4_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_3rdL_HITS) | - P4_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_3rdL_HITE) | - P4_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_3rdL_HITM), - .escr_msr = { MSR_P4_BSU_ESCR0, MSR_P4_BSU_ESCR1 }, - .cntr = { 0, 2 }, - }, - [3] = { - .opcode = P4_BSQ_CACHE_REFERENCE, - .config = 0, - .dep = -1, - .key = 3, - .emask = - P4_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_2ndL_MISS) | - P4_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, RD_3rdL_MISS) | - P4_EVENT_ATTR(P4_BSQ_CACHE_REFERENCE, WR_2ndL_MISS), - .escr_msr = { MSR_P4_BSU_ESCR0, MSR_P4_BSU_ESCR1 }, - .cntr = { 0, 3 }, - }, - [4] = { - .opcode = P4_RETIRED_BRANCH_TYPE, - .config = 0, - .dep = -1, - .key = 4, - .emask = - P4_EVENT_ATTR(P4_RETIRED_BRANCH_TYPE, CONDITIONAL) | - P4_EVENT_ATTR(P4_RETIRED_BRANCH_TYPE, CALL) | - P4_EVENT_ATTR(P4_RETIRED_BRANCH_TYPE, RETURN) | - P4_EVENT_ATTR(P4_RETIRED_BRANCH_TYPE, INDIRECT), - .escr_msr = { MSR_P4_TBPU_ESCR0, MSR_P4_TBPU_ESCR1 }, - .cntr = { 4, 6 }, - }, - [5] = { - .opcode = P4_MISPRED_BRANCH_RETIRED, - .config = 0, - .dep = -1, - .key = 5, - .emask = - P4_EVENT_ATTR(P4_MISPRED_BRANCH_RETIRED, NBOGUS), - .escr_msr = { MSR_P4_CRU_ESCR0, MSR_P4_CRU_ESCR1 }, - .cntr = { 12, 14 }, - }, - [6] = { - .opcode = P4_FSB_DATA_ACTIVITY, - .config = p4_config_pack_cccr(P4_CCCR_EDGE | P4_CCCR_COMPARE), - .dep = -1, - .key = 6, - .emask = - P4_EVENT_ATTR(P4_FSB_DATA_ACTIVITY, DRDY_DRV) | - P4_EVENT_ATTR(P4_FSB_DATA_ACTIVITY, DRDY_OWN), - .escr_msr = { MSR_P4_FSB_ESCR0, MSR_P4_FSB_ESCR1 }, - .cntr = { 0, 2 }, - }, - [KEY_P4_L1D_OP_READ_RESULT_MISS] = { - .opcode = P4_REPLAY_EVENT, - .config = 0, - .dep = -1, - .msr = (u64)(1 << 0 | 1 << 24) << 32 | (1 << 0), - .key = KEY_P4_L1D_OP_READ_RESULT_MISS, - .emask = - P4_EVENT_ATTR(P4_REPLAY_EVENT, NBOGUS), - .escr_msr = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR2 }, - .cntr = { 16, 17 }, - }, - [KEY_P4_LL_OP_READ_RESULT_MISS] = { - .opcode = P4_REPLAY_EVENT, - .config = 0, - .dep = -1, - .msr = (u64)(1 << 1 | 1 << 24) << 32 | (1 << 0), - .key = KEY_P4_LL_OP_READ_RESULT_MISS, - .emask = - P4_EVENT_ATTR(P4_REPLAY_EVENT, NBOGUS), - .escr_msr = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR2 }, - .cntr = { 16, 17 }, - }, - [KEY_P4_DTLB_OP_READ_RESULT_MISS] = { - .opcode = P4_REPLAY_EVENT, - .config = 0, - .dep = -1, - .msr = (u64)(1 << 2 | 1 << 24) << 32 | (1 << 0), - .key = KEY_P4_DTLB_OP_READ_RESULT_MISS, - .emask = - P4_EVENT_ATTR(P4_REPLAY_EVENT, NBOGUS), - .escr_msr = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR2 }, - .cntr = { 16, 17 }, - }, - [KEY_P4_DTLB_OP_WRITE_RESULT_MISS] = { - .opcode = P4_REPLAY_EVENT, - .config = 0, - .dep = -1, - .msr = (u64)(1 << 2 | 1 << 24) << 32 | (1 << 1), - .key = KEY_P4_DTLB_OP_WRITE_RESULT_MISS, - .emask = - P4_EVENT_ATTR(P4_REPLAY_EVENT, NBOGUS), - .escr_msr = { MSR_P4_CRU_ESCR2, MSR_P4_CRU_ESCR2 }, - .cntr = { 16, 17 }, - }, - [KEY_P4_ITLB_OP_READ_RESULT_ACCESS] = { - .opcode = P4_ITLB_REFERENCE, - .config = 0, - .dep = -1, - .msr = 0, - .key = KEY_P4_ITLB_OP_READ_RESULT_ACCESS, - .emask = - P4_EVENT_ATTR(P4_ITLB_REFERENCE, HIT), - .escr_msr = { MSR_P4_ITLB_ESCR0, MSR_P4_ITLB_ESCR1 }, - .cntr = { 0, 2 }, - }, - [KEY_P4_ITLB_OP_READ_RESULT_MISS] = { - .opcode = P4_ITLB_REFERENCE, - .config = 0, - .dep = -1, - .msr = 0, - .key = KEY_P4_ITLB_OP_READ_RESULT_MISS, - .emask = - P4_EVENT_ATTR(P4_ITLB_REFERENCE, MISS), - .escr_msr = { MSR_P4_ITLB_ESCR0, MSR_P4_ITLB_ESCR1 }, - .cntr = { 0, 2 }, - }, - [KEY_P4_UOP_TYPE] = { - .opcode = P4_UOP_TYPE, - .config = 0, - .dep = -1, - .key = KEY_P4_UOP_TYPE, - .emask = - P4_EVENT_ATTR(P4_UOP_TYPE, TAGLOADS) | - P4_EVENT_ATTR(P4_UOP_TYPE, TAGSTORES), - .escr_msr = { MSR_P4_RAT_ESCR0, MSR_P4_RAT_ESCR1 }, - .cntr = { 16, 17 }, - }, +static u64 p4_general_events[PERF_COUNT_HW_MAX] = { + /* non-halted CPU clocks */ + [PERF_COUNT_HW_CPU_CYCLES] = + p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_GLOBAL_POWER_EVENTS) | + P4_ESCR_EMASK_BIT(P4_EVENT_GLOBAL_POWER_EVENTS, RUNNING)), + + /* + * retired instructions + * in a sake of simplicity we don't use the FSB tagging + */ + [PERF_COUNT_HW_INSTRUCTIONS] = + p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_INSTR_RETIRED) | + P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_RETIRED, NBOGUSNTAG) | + P4_ESCR_EMASK_BIT(P4_EVENT_INSTR_RETIRED, BOGUSNTAG)), + + /* cache hits */ + [PERF_COUNT_HW_CACHE_REFERENCES] = + p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_BSQ_CACHE_REFERENCE) | + P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_HITS) | + P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_HITE) | + P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_HITM) | + P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_HITS) | + P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_HITE) | + P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_HITM)), + + /* cache misses */ + [PERF_COUNT_HW_CACHE_MISSES] = + p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_BSQ_CACHE_REFERENCE) | + P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_2ndL_MISS) | + P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, RD_3rdL_MISS) | + P4_ESCR_EMASK_BIT(P4_EVENT_BSQ_CACHE_REFERENCE, WR_2ndL_MISS)), + + /* branch instructions retired */ + [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = + p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_RETIRED_BRANCH_TYPE) | + P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_BRANCH_TYPE, CONDITIONAL) | + P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_BRANCH_TYPE, CALL) | + P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_BRANCH_TYPE, RETURN) | + P4_ESCR_EMASK_BIT(P4_EVENT_RETIRED_BRANCH_TYPE, INDIRECT)), + + /* mispredicted branches retired */ + [PERF_COUNT_HW_BRANCH_MISSES] = + p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_MISPRED_BRANCH_RETIRED) | + P4_ESCR_EMASK_BIT(P4_EVENT_MISPRED_BRANCH_RETIRED, NBOGUS)), + + /* bus ready clocks (cpu is driving #DRDY_DRV\#DRDY_OWN): */ + [PERF_COUNT_HW_BUS_CYCLES] = + p4_config_pack_escr(P4_ESCR_EVENT(P4_EVENT_FSB_DATA_ACTIVITY) | + P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DRDY_DRV) | + P4_ESCR_EMASK_BIT(P4_EVENT_FSB_DATA_ACTIVITY, DRDY_OWN)) | + p4_config_pack_cccr(P4_CCCR_EDGE | P4_CCCR_COMPARE), }; +static struct p4_event_bind *p4_config_get_bind(u64 config) +{ + unsigned int evnt = p4_config_unpack_event(config); + struct p4_event_bind *bind = NULL; + + if (evnt < ARRAY_SIZE(p4_event_bind_map)) + bind = &p4_event_bind_map[evnt]; + + return bind; +} + static u64 p4_pmu_event_map(int hw_event) { - struct p4_event_template *tpl; + struct p4_event_bind *bind; + unsigned int esel; u64 config; - if (hw_event > ARRAY_SIZE(p4_templates)) { - printk_once(KERN_ERR "PMU: Incorrect event index\n"); + if (hw_event > ARRAY_SIZE(p4_general_events)) { + printk_once(KERN_ERR "P4 PMU: Bad index: %i\n", hw_event); return 0; } - tpl = &p4_templates[hw_event]; - /* - * fill config up according to - * a predefined event template - */ - config = tpl->config; - config |= p4_config_pack_escr(P4_EVENT_UNPACK_EVENT(tpl->opcode) << P4_EVNTSEL_EVENT_SHIFT); - config |= p4_config_pack_escr(tpl->emask << P4_EVNTSEL_EVENTMASK_SHIFT); - config |= p4_config_pack_cccr(P4_EVENT_UNPACK_SELECTOR(tpl->opcode) << P4_CCCR_ESCR_SELECT_SHIFT); - config |= p4_config_pack_cccr(hw_event & P4_CCCR_RESERVED); + config = p4_general_events[hw_event]; + bind = p4_config_get_bind(config); + esel = P4_OPCODE_ESEL(bind->opcode); + config |= p4_config_pack_cccr(P4_CCCR_ESEL(esel)); return config; } /* - * Note that we still have 5 events (from global events SDM list) - * intersected in opcode+emask bits so we will need another - * scheme there do distinguish templates. - */ -static inline int p4_pmu_emask_match(unsigned int dst, unsigned int src) -{ - return dst & src; -} - -static struct p4_event_template *p4_pmu_template_lookup(u64 config) -{ - int key = p4_config_unpack_key(config); - - if (key < ARRAY_SIZE(p4_templates)) - return &p4_templates[key]; - else - return NULL; -} - -/* * We don't control raw events so it's up to the caller * to pass sane values (and we don't count the thread number * on HT machine but allow HT-compatible specifics to be @@ -319,13 +428,14 @@ static struct p4_event_template *p4_pmu_template_lookup(u64 config) static u64 p4_pmu_raw_event(u64 hw_event) { return hw_event & - (p4_config_pack_escr(P4_EVNTSEL_MASK_HT) | + (p4_config_pack_escr(P4_ESCR_MASK_HT) | p4_config_pack_cccr(P4_CCCR_MASK_HT)); } static int p4_hw_config(struct perf_event_attr *attr, struct hw_perf_event *hwc) { int cpu = raw_smp_processor_id(); + u32 escr, cccr; /* * the reason we use cpu that early is that: if we get scheduled @@ -333,13 +443,10 @@ static int p4_hw_config(struct perf_event_attr *attr, struct hw_perf_event *hwc) * specific flags in config (and will save some cpu cycles) */ - /* CCCR by default */ - hwc->config = p4_config_pack_cccr(p4_default_cccr_conf(cpu)); + cccr = p4_default_cccr_conf(cpu); + escr = p4_default_escr_conf(cpu, attr->exclude_kernel, attr->exclude_user); + hwc->config = p4_config_pack_escr(escr) | p4_config_pack_cccr(cccr); - /* Count user and OS events unless not requested to */ - hwc->config |= p4_config_pack_escr(p4_default_escr_conf(cpu, attr->exclude_kernel, - attr->exclude_user)); - /* on HT machine we need a special bit */ if (p4_ht_active() && p4_ht_thread(cpu)) hwc->config = p4_set_ht_bit(hwc->config); @@ -368,7 +475,7 @@ static inline void p4_pmu_disable_event(struct perf_event *event) */ (void)checking_wrmsrl(hwc->config_base + hwc->idx, (u64)(p4_config_unpack_cccr(hwc->config)) & - ~P4_CCCR_ENABLE & ~P4_CCCR_OVF); + ~P4_CCCR_ENABLE & ~P4_CCCR_OVF & ~P4_CCCR_RESERVED); } static void p4_pmu_disable_all(void) @@ -389,27 +496,14 @@ static void p4_pmu_enable_event(struct perf_event *event) struct hw_perf_event *hwc = &event->hw; int thread = p4_ht_config_thread(hwc->config); u64 escr_conf = p4_config_unpack_escr(p4_clear_ht_bit(hwc->config)); - u64 escr_base; - struct p4_event_template *tpl; - struct p4_pmu_res *c; + unsigned int idx = p4_config_unpack_event(hwc->config); + unsigned int idx_cache = p4_config_unpack_cache_event(hwc->config); + struct p4_event_bind *bind; + struct p4_cache_event_bind *bind_cache; + u64 escr_addr, cccr; - /* - * some preparation work from per-cpu private fields - * since we need to find out which ESCR to use - */ - c = &__get_cpu_var(p4_pmu_config); - tpl = c->tpl[hwc->idx]; - if (!tpl) { - pr_crit("%s: Wrong index: %d\n", __func__, hwc->idx); - return; - } - - if (tpl->msr) { - (void)checking_wrmsrl(MSR_IA32_PEBS_ENABLE, tpl->msr >> 32); - (void)checking_wrmsrl(MSR_P4_PEBS_MATRIX_VERT, tpl->msr & 0xffffffff); - } - - escr_base = (u64)tpl->escr_msr[thread]; + bind = &p4_event_bind_map[idx]; + escr_addr = (u64)bind->escr_msr[thread]; /* * - we dont support cascaded counters yet @@ -418,9 +512,27 @@ static void p4_pmu_enable_event(struct perf_event *event) WARN_ON_ONCE(p4_is_event_cascaded(hwc->config)); WARN_ON_ONCE(hwc->idx == 1); - (void)checking_wrmsrl(escr_base, escr_conf); + /* we need a real Event value */ + escr_conf &= ~P4_ESCR_EVENT_MASK; + escr_conf |= P4_ESCR_EVENT(P4_OPCODE_EVNT(bind->opcode)); + + cccr = p4_config_unpack_cccr(hwc->config); + + /* + * it could be Cache event so that we need to + * set metrics into additional MSRs + */ + BUILD_BUG_ON(P4_CACHE__MAX > P4_CCCR_CACHE_OPS_MASK); + if (idx_cache > P4_CACHE__NONE && + idx_cache < ARRAY_SIZE(p4_cache_event_bind_map)) { + bind_cache = &p4_cache_event_bind_map[idx_cache]; + (void)checking_wrmsrl(MSR_IA32_PEBS_ENABLE, (u64)bind_cache->metric_pebs); + (void)checking_wrmsrl(MSR_P4_PEBS_MATRIX_VERT, (u64)bind_cache->metric_vert); + } + + (void)checking_wrmsrl(escr_addr, escr_conf); (void)checking_wrmsrl(hwc->config_base + hwc->idx, - (u64)(p4_config_unpack_cccr(hwc->config)) | P4_CCCR_ENABLE); + (cccr & ~P4_CCCR_RESERVED) | P4_CCCR_ENABLE); } static void p4_pmu_enable_all(void) @@ -516,13 +628,13 @@ static void p4_pmu_swap_config_ts(struct hw_perf_event *hwc, int cpu) if (p4_ht_thread(cpu)) { cccr &= ~P4_CCCR_OVF_PMI_T0; cccr |= P4_CCCR_OVF_PMI_T1; - if (escr & P4_EVNTSEL_T0_OS) { - escr &= ~P4_EVNTSEL_T0_OS; - escr |= P4_EVNTSEL_T1_OS; + if (escr & P4_ESCR_T0_OS) { + escr &= ~P4_ESCR_T0_OS; + escr |= P4_ESCR_T1_OS; } - if (escr & P4_EVNTSEL_T0_USR) { - escr &= ~P4_EVNTSEL_T0_USR; - escr |= P4_EVNTSEL_T1_USR; + if (escr & P4_ESCR_T0_USR) { + escr &= ~P4_ESCR_T0_USR; + escr |= P4_ESCR_T1_USR; } hwc->config = p4_config_pack_escr(escr); hwc->config |= p4_config_pack_cccr(cccr); @@ -530,13 +642,13 @@ static void p4_pmu_swap_config_ts(struct hw_perf_event *hwc, int cpu) } else { cccr &= ~P4_CCCR_OVF_PMI_T1; cccr |= P4_CCCR_OVF_PMI_T0; - if (escr & P4_EVNTSEL_T1_OS) { - escr &= ~P4_EVNTSEL_T1_OS; - escr |= P4_EVNTSEL_T0_OS; + if (escr & P4_ESCR_T1_OS) { + escr &= ~P4_ESCR_T1_OS; + escr |= P4_ESCR_T0_OS; } - if (escr & P4_EVNTSEL_T1_USR) { - escr &= ~P4_EVNTSEL_T1_USR; - escr |= P4_EVNTSEL_T0_USR; + if (escr & P4_ESCR_T1_USR) { + escr &= ~P4_ESCR_T1_USR; + escr |= P4_ESCR_T0_USR; } hwc->config = p4_config_pack_escr(escr); hwc->config |= p4_config_pack_cccr(cccr); @@ -606,66 +718,56 @@ static int p4_get_escr_idx(unsigned int addr) return -1; } +static int p4_next_cntr(int thread, unsigned long *used_mask, + struct p4_event_bind *bind) +{ + int i = 0, j; + + for (i = 0; i < P4_CNTR_LIMIT; i++) { + j = bind->cntr[thread][i++]; + if (j == -1 || !test_bit(j, used_mask)) + return j; + } + + return -1; +} + static int p4_pmu_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign) { unsigned long used_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; unsigned long escr_mask[BITS_TO_LONGS(ARCH_P4_TOTAL_ESCR)]; - - struct hw_perf_event *hwc; - struct p4_event_template *tpl; - struct p4_pmu_res *c; int cpu = raw_smp_processor_id(); - int escr_idx, thread, i, num; + struct hw_perf_event *hwc; + struct p4_event_bind *bind; + unsigned int i, thread, num; + int cntr_idx, escr_idx; bitmap_zero(used_mask, X86_PMC_IDX_MAX); bitmap_zero(escr_mask, ARCH_P4_TOTAL_ESCR); - c = &__get_cpu_var(p4_pmu_config); - /* - * Firstly find out which resource events are going - * to use, if ESCR+CCCR tuple is already borrowed - * then get out of here - */ for (i = 0, num = n; i < n; i++, num--) { + hwc = &cpuc->event_list[i]->hw; - tpl = p4_pmu_template_lookup(hwc->config); - if (!tpl) - goto done; thread = p4_ht_thread(cpu); - escr_idx = p4_get_escr_idx(tpl->escr_msr[thread]); - if (escr_idx == -1) - goto done; + bind = p4_config_get_bind(hwc->config); + escr_idx = p4_get_escr_idx(bind->escr_msr[thread]); - /* already allocated and remains on the same cpu */ if (hwc->idx != -1 && !p4_should_swap_ts(hwc->config, cpu)) { + cntr_idx = hwc->idx; if (assign) assign[i] = hwc->idx; - /* upstream dependent event */ - if (unlikely(tpl->dep != -1)) - printk_once(KERN_WARNING "PMU: Dep events are " - "not implemented yet\n"); goto reserve; } - /* it may be already borrowed */ - if (test_bit(tpl->cntr[thread], used_mask) || - test_bit(escr_idx, escr_mask)) + cntr_idx = p4_next_cntr(thread, used_mask, bind); + if (cntr_idx == -1 || test_bit(escr_idx, escr_mask)) goto done; - /* - * ESCR+CCCR+COUNTERs are available to use lets swap - * thread specific bits, push assigned bits - * back and save template into per-cpu - * area (which will allow us to find out the ESCR - * to be used at moment of "enable event via real MSR") - */ p4_pmu_swap_config_ts(hwc, cpu); - if (assign) { - assign[i] = tpl->cntr[thread]; - c->tpl[assign[i]] = tpl; - } + if (assign) + assign[i] = cntr_idx; reserve: - set_bit(tpl->cntr[thread], used_mask); + set_bit(cntr_idx, used_mask); set_bit(escr_idx, escr_mask); } @@ -684,7 +786,7 @@ static __initconst struct x86_pmu p4_pmu = { .perfctr = MSR_P4_BPU_PERFCTR0, .event_map = p4_pmu_event_map, .raw_event = p4_pmu_raw_event, - .max_events = ARRAY_SIZE(p4_templates), + .max_events = ARRAY_SIZE(p4_general_events), .get_event_constraints = x86_get_event_constraints, /* * IF HT disabled we may need to use all @@ -716,7 +818,7 @@ static __init int p4_pmu_init(void) } memcpy(hw_cache_event_ids, p4_hw_cache_event_ids, - sizeof(hw_cache_event_ids)); + sizeof(hw_cache_event_ids)); pr_cont("Netburst events, "); -- cgit v0.10.2 From 53c540195724b52422da067a31ef6916d2c70202 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 24 Mar 2010 16:40:14 -0300 Subject: perf report: Add a popup menu to ask what operation is to be performed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Right now it presents a menu with these options: +------------------------------+ | Annotate CURRENT_SYMBOL_NAME | | Exit | +------------------------------+ If the highlighted (current) symbol is not annotatable only the "Exit" option will appear. Also add a confirmation dialog when ESC is pressed on the top level to avoid exiting the application by pressing one too many ESC key. To get to the menu just press the -> (Right navigation key), to exit just press ESC. Signed-off-by: Arnaldo Carvalho de Melo Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: <1269459619-982-1-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index 12b229b..a3465a0 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -28,6 +28,47 @@ static newtComponent newt_form__new(void) return self; } +static int popup_menu(int argc, const char *argv[]) +{ + struct newtExitStruct es; + int i, rc = -1, max_len = 5; + newtComponent listbox, form = newt_form__new(); + + if (form == NULL) + return -1; + + listbox = newtListbox(0, 0, argc, NEWT_FLAG_RETURNEXIT); + if (listbox == NULL) + goto out_destroy_form; + + newtFormAddComponents(form, listbox, NULL); + + for (i = 0; i < argc; ++i) { + int len = strlen(argv[i]); + if (len > max_len) + max_len = len; + if (newtListboxAddEntry(listbox, argv[i], (void *)(long)i)) + goto out_destroy_form; + } + + newtCenteredWindow(max_len, argc, NULL); + newtFormRun(form, &es); + rc = newtListboxGetCurrent(listbox) - NULL; + if (es.reason == NEWT_EXIT_HOTKEY) + rc = -1; + newtPopWindow(); +out_destroy_form: + newtFormDestroy(form); + return rc; +} + +static bool dialog_yesno(const char *msg) +{ + /* newtWinChoice should really be accepting const char pointers... */ + char yes[] = "Yes", no[] = "No"; + return newtWinChoice(NULL, no, yes, (char *)msg) == 2; +} + /* * When debugging newt problems it was useful to be able to "unroll" * the calls to newtCheckBoxTreeAdd{Array,Item}, so that we can generate @@ -309,6 +350,19 @@ out_free_str: free(str); } +static const void *newt__symbol_tree_get_current(newtComponent self) +{ + if (symbol_conf.use_callchain) + return newtCheckboxTreeGetCurrent(self); + return newtListboxGetCurrent(self); +} + +static void perf_session__selection(newtComponent self, void *data) +{ + const struct symbol **symbol_ptr = data; + *symbol_ptr = newt__symbol_tree_get_current(self); +} + void perf_session__browse_hists(struct rb_root *hists, u64 session_total, const char *helpline) { @@ -322,6 +376,7 @@ void perf_session__browse_hists(struct rb_root *hists, u64 session_total, char str[1024]; newtComponent form, tree; struct newtExitStruct es; + const struct symbol *selection; snprintf(str, sizeof(str), "Samples: %Ld", session_total); newtDrawRootText(0, 0, str); @@ -336,6 +391,8 @@ void perf_session__browse_hists(struct rb_root *hists, u64 session_total, tree = newtListbox(0, 0, rows - 5, (NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT)); + newtComponentAddCallback(tree, perf_session__selection, &selection); + list_for_each_entry(se, &hist_entry__sort_list, list) { if (se->elide) continue; @@ -377,20 +434,43 @@ void perf_session__browse_hists(struct rb_root *hists, u64 session_total, form = newt_form__new(); newtFormAddHotKey(form, 'A'); newtFormAddHotKey(form, 'a'); + newtFormAddHotKey(form, NEWT_KEY_RIGHT); newtFormAddComponents(form, tree, NULL); + selection = newt__symbol_tree_get_current(tree); while (1) { - const struct symbol *selection; + char annotate[512]; + const char *options[2]; + int nr_options = 0, choice; newtFormRun(form, &es); - if (es.reason == NEWT_EXIT_HOTKEY && - toupper(es.u.key) != 'A') + if (es.reason == NEWT_EXIT_HOTKEY) { + if (toupper(es.u.key) == 'A') { + symbol__annotate_browser(selection); + continue; + } + if (es.u.key == NEWT_KEY_ESCAPE || + toupper(es.u.key) == 'Q' || + es.u.key == CTRL('c')) { + if (dialog_yesno("Do you really want to exit?")) + break; + else + continue; + } + } + + if (selection != NULL) { + snprintf(annotate, sizeof(annotate), + "Annotate %s", selection->name); + options[nr_options++] = annotate; + } + + options[nr_options++] = "Exit"; + choice = popup_menu(nr_options, options); + if (choice == nr_options - 1) break; - if (!symbol_conf.use_callchain) - selection = newtListboxGetCurrent(tree); - else - selection = newtCheckboxTreeGetCurrent(tree); - symbol__annotate_browser(selection); + else if (selection != NULL && choice >= 0) + symbol__annotate_browser(selection); } newtFormDestroy(form); -- cgit v0.10.2 From 96415e4d3f5fdf9cdb12eedfcbc58152b1e1458c Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 24 Mar 2010 16:40:15 -0300 Subject: perf symbols: Avoid unnecessary symbol loading when dso list is specified MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We were performing the full thread__find_addr_location operation, i.e. resolving to a map/dso _and_ loading its symbols when we can optimize it by first calling thread__find_addr_map to find just the map/dso, check if it is one that we are interested in (passed via --dsos/-d in 'perf annotate', 'perf report', etc) and if not avoid loading the symtab. Nice speedup when we know which DSO we're interested in. Signed-off-by: Arnaldo Carvalho de Melo Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: <1269459619-982-2-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 705ec63..c2808ad 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -513,24 +513,32 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session, dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); - thread__find_addr_location(thread, session, cpumode, MAP__FUNCTION, - self->ip.ip, al, filter); + thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION, + self->ip.ip, al); dump_printf(" ...... dso: %s\n", al->map ? al->map->dso->long_name : al->level == 'H' ? "[hypervisor]" : ""); - /* - * We have to do this here as we may have a dso with no symbol hit that - * has a name longer than the ones with symbols sampled. - */ - if (al->map && !sort_dso.elide && !al->map->dso->slen_calculated) - dso__calc_col_width(al->map->dso); - - if (symbol_conf.dso_list && - (!al->map || !al->map->dso || - !(strlist__has_entry(symbol_conf.dso_list, al->map->dso->short_name) || - (al->map->dso->short_name != al->map->dso->long_name && - strlist__has_entry(symbol_conf.dso_list, al->map->dso->long_name))))) - goto out_filtered; + al->sym = NULL; + + if (al->map) { + if (symbol_conf.dso_list && + (!al->map || !al->map->dso || + !(strlist__has_entry(symbol_conf.dso_list, + al->map->dso->short_name) || + (al->map->dso->short_name != al->map->dso->long_name && + strlist__has_entry(symbol_conf.dso_list, + al->map->dso->long_name))))) + goto out_filtered; + /* + * We have to do this here as we may have a dso with no symbol + * hit that has a name longer than the ones with symbols + * sampled. + */ + if (!sort_dso.elide && !al->map->dso->slen_calculated) + dso__calc_col_width(al->map->dso); + + al->sym = map__find_symbol(al->map, al->addr, filter); + } if (symbol_conf.sym_list && al->sym && !strlist__has_entry(symbol_conf.sym_list, al->sym->name)) -- cgit v0.10.2 From ac73c5a9c1767b2771e6d2b5accafdef89db04c2 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 24 Mar 2010 16:40:16 -0300 Subject: perf annotate: Allow specifying DSOs where to look for symbol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using the same parameter as in 'perf report', allowing to specify just one and disambiguate between DSOs that have the symbol of interest. Signed-off-by: Arnaldo Carvalho de Melo Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: <1269459619-982-3-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 45d1466..ce9b1ef 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -591,6 +591,8 @@ static const char * const annotate_usage[] = { static const struct option options[] = { OPT_STRING('i', "input", &input_name, "file", "input file name"), + OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]", + "only consider symbols in these dsos"), OPT_STRING('s', "symbol", &sym_hist_filter, "symbol", "symbol to annotate"), OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), -- cgit v0.10.2 From 59fd53062f71011a68d03f4cd0ba93d822ac3249 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 24 Mar 2010 16:40:17 -0300 Subject: perf tools: Introduce struct map_symbol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit That will be in both struct hist_entry and struct callchain_list, so that the TUI can store a pointer to the pair (map, symbol) in the trees where hist_entries and callchain_lists are present, to allow precise annotation instead of looking for the first symbol with the selected name. Signed-off-by: Arnaldo Carvalho de Melo Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: <1269459619-982-4-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index ce9b1ef..887e8e0 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -69,13 +69,13 @@ static int sym__alloc_hist(struct symbol *self) static int annotate__hist_hit(struct hist_entry *he, u64 ip) { unsigned int sym_size, offset; - struct symbol *sym = he->sym; + struct symbol *sym = he->ms.sym; struct sym_priv *priv; struct sym_hist *h; he->count++; - if (!sym || !he->map) + if (!sym || !he->ms.map) return 0; priv = symbol__priv(sym); @@ -85,7 +85,7 @@ static int annotate__hist_hit(struct hist_entry *he, u64 ip) sym_size = sym->end - sym->start; offset = ip - sym->start; - pr_debug3("%s: ip=%#Lx\n", __func__, he->map->unmap_ip(he->map, ip)); + pr_debug3("%s: ip=%#Lx\n", __func__, he->ms.map->unmap_ip(he->ms.map, ip)); if (offset >= sym_size) return 0; @@ -94,8 +94,8 @@ static int annotate__hist_hit(struct hist_entry *he, u64 ip) h->sum++; h->ip[offset]++; - pr_debug3("%#Lx %s: count++ [ip: %#Lx, %#Lx] => %Ld\n", he->sym->start, - he->sym->name, ip, ip - he->sym->start, h->ip[offset]); + pr_debug3("%#Lx %s: count++ [ip: %#Lx, %#Lx] => %Ld\n", he->ms.sym->start, + he->ms.sym->name, ip, ip - he->ms.sym->start, h->ip[offset]); return 0; } @@ -187,7 +187,7 @@ static struct objdump_line *objdump__get_next_ip_line(struct list_head *head, static int parse_line(FILE *file, struct hist_entry *he, struct list_head *head) { - struct symbol *sym = he->sym; + struct symbol *sym = he->ms.sym; struct objdump_line *objdump_line; char *line = NULL, *tmp, *tmp2; size_t line_len; @@ -226,7 +226,7 @@ static int parse_line(FILE *file, struct hist_entry *he, } if (line_ip != -1) { - u64 start = map__rip_2objdump(he->map, sym->start); + u64 start = map__rip_2objdump(he->ms.map, sym->start); offset = line_ip - start; } @@ -244,7 +244,7 @@ static int objdump_line__print(struct objdump_line *self, struct list_head *head, struct hist_entry *he, u64 len) { - struct symbol *sym = he->sym; + struct symbol *sym = he->ms.sym; static const char *prev_line; static const char *prev_color; @@ -327,7 +327,7 @@ static void insert_source_line(struct sym_ext *sym_ext) static void free_source_line(struct hist_entry *he, int len) { - struct sym_priv *priv = symbol__priv(he->sym); + struct sym_priv *priv = symbol__priv(he->ms.sym); struct sym_ext *sym_ext = priv->ext; int i; @@ -346,7 +346,7 @@ static void free_source_line(struct hist_entry *he, int len) static void get_source_line(struct hist_entry *he, int len, const char *filename) { - struct symbol *sym = he->sym; + struct symbol *sym = he->ms.sym; u64 start; int i; char cmd[PATH_MAX * 2]; @@ -361,7 +361,7 @@ get_source_line(struct hist_entry *he, int len, const char *filename) if (!priv->ext) return; - start = he->map->unmap_ip(he->map, sym->start); + start = he->ms.map->unmap_ip(he->ms.map, sym->start); for (i = 0; i < len; i++) { char *path = NULL; @@ -425,7 +425,7 @@ static void print_summary(const char *filename) static void hist_entry__print_hits(struct hist_entry *self) { - struct symbol *sym = self->sym; + struct symbol *sym = self->ms.sym; struct sym_priv *priv = symbol__priv(sym); struct sym_hist *h = priv->hist; u64 len = sym->end - sym->start, offset; @@ -439,9 +439,9 @@ static void hist_entry__print_hits(struct hist_entry *self) static void annotate_sym(struct hist_entry *he) { - struct map *map = he->map; + struct map *map = he->ms.map; struct dso *dso = map->dso; - struct symbol *sym = he->sym; + struct symbol *sym = he->ms.sym; const char *filename = dso->long_name, *d_filename; u64 len; char command[PATH_MAX*2]; @@ -526,17 +526,17 @@ static void perf_session__find_annotations(struct perf_session *self) struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node); struct sym_priv *priv; - if (he->sym == NULL) + if (he->ms.sym == NULL) continue; - priv = symbol__priv(he->sym); + priv = symbol__priv(he->ms.sym); if (priv->hist == NULL) continue; annotate_sym(he); /* * Since we have a hist_entry per IP for the same symbol, free - * he->sym->hist to signal we already processed this symbol. + * he->ms.sym->hist to signal we already processed this symbol. */ free(priv->hist); priv->hist = NULL; diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 5843a9c..4eefb52 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -22,8 +22,10 @@ struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists, struct hist_entry *he; struct hist_entry entry = { .thread = al->thread, - .map = al->map, - .sym = al->sym, + .ms = { + .map = al->map, + .sym = al->sym, + }, .ip = al->addr, .level = al->level, .count = count, @@ -654,7 +656,7 @@ print_entries: if (symbol_conf.use_callchain) ret += hist_entry__fprintf_callchain(h, fp, session_total); - if (h->map == NULL && verbose > 1) { + if (h->ms.map == NULL && verbose > 1) { __map_groups__fprintf_maps(&h->thread->mg, MAP__FUNCTION, fp); fprintf(fp, "%.10s end\n", graph_dotted_line); diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index a3465a0..25cd2e1 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -287,9 +287,9 @@ static size_t hist_entry__append_browser(struct hist_entry *self, indexes[0] = NEWT_ARG_APPEND; indexes[1] = NEWT_ARG_LAST; - newt_checkbox_tree__add(tree, s, self->sym, indexes); + newt_checkbox_tree__add(tree, s, self->ms.sym, indexes); } else - newtListboxAppendEntry(tree, s, self->sym); + newtListboxAppendEntry(tree, s, self->ms.sym); return strlen(s); } diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index cb0f327..9b80c13 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -131,8 +131,8 @@ sort__comm_print(FILE *fp, struct hist_entry *self, unsigned int width) int64_t sort__dso_cmp(struct hist_entry *left, struct hist_entry *right) { - struct dso *dso_l = left->map ? left->map->dso : NULL; - struct dso *dso_r = right->map ? right->map->dso : NULL; + struct dso *dso_l = left->ms.map ? left->ms.map->dso : NULL; + struct dso *dso_r = right->ms.map ? right->ms.map->dso : NULL; const char *dso_name_l, *dso_name_r; if (!dso_l || !dso_r) @@ -152,9 +152,9 @@ sort__dso_cmp(struct hist_entry *left, struct hist_entry *right) size_t sort__dso_print(FILE *fp, struct hist_entry *self, unsigned int width) { - if (self->map && self->map->dso) { - const char *dso_name = !verbose ? self->map->dso->short_name : - self->map->dso->long_name; + if (self->ms.map && self->ms.map->dso) { + const char *dso_name = !verbose ? self->ms.map->dso->short_name : + self->ms.map->dso->long_name; return repsep_fprintf(fp, "%-*s", width, dso_name); } @@ -168,11 +168,11 @@ sort__sym_cmp(struct hist_entry *left, struct hist_entry *right) { u64 ip_l, ip_r; - if (left->sym == right->sym) + if (left->ms.sym == right->ms.sym) return 0; - ip_l = left->sym ? left->sym->start : left->ip; - ip_r = right->sym ? right->sym->start : right->ip; + ip_l = left->ms.sym ? left->ms.sym->start : left->ip; + ip_r = right->ms.sym ? right->ms.sym->start : right->ip; return (int64_t)(ip_r - ip_l); } @@ -184,13 +184,13 @@ sort__sym_print(FILE *fp, struct hist_entry *self, unsigned int width __used) size_t ret = 0; if (verbose) { - char o = self->map ? dso__symtab_origin(self->map->dso) : '!'; + char o = self->ms.map ? dso__symtab_origin(self->ms.map->dso) : '!'; ret += repsep_fprintf(fp, "%#018llx %c ", (u64)self->ip, o); } ret += repsep_fprintf(fp, "[%c] ", self->level); - if (self->sym) - ret += repsep_fprintf(fp, "%s", self->sym->name); + if (self->ms.sym) + ret += repsep_fprintf(fp, "%s", self->ms.sym->name); else ret += repsep_fprintf(fp, "%#016llx", (u64)self->ip); diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index 753f9ea..5985686 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h @@ -45,8 +45,7 @@ struct hist_entry { struct rb_node rb_node; u64 count; struct thread *thread; - struct map *map; - struct symbol *sym; + struct map_symbol ms; u64 ip; char level; struct symbol *parent; diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 0da2455..a4a894b 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -88,6 +88,11 @@ struct ref_reloc_sym { u64 unrelocated_addr; }; +struct map_symbol { + struct map *map; + struct symbol *sym; +}; + struct addr_location { struct thread *thread; struct map *map; -- cgit v0.10.2 From b3c9ac0846c654dea4df095999ee202e8b4cb253 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 24 Mar 2010 16:40:18 -0300 Subject: perf callchains: Store the map together with the symbol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need this to know where a symbol in a callchain came from, for various reasons, among them precise annotation from a TUI/GUI tool. Signed-off-by: Arnaldo Carvalho de Melo Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: <1269459619-982-5-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index d609afb..6ab1698 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -81,7 +81,8 @@ static int perf_session__add_hist_entry(struct perf_session *self, struct addr_location *al, struct sample_data *data) { - struct symbol **syms = NULL, *parent = NULL; + struct map_symbol *syms = NULL; + struct symbol *parent = NULL; bool hit; int err; struct hist_entry *he; diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 883844e..db628af 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -185,8 +185,8 @@ create_child(struct callchain_node *parent, bool inherit_children) struct resolved_ip { - u64 ip; - struct symbol *sym; + u64 ip; + struct map_symbol ms; }; struct resolved_chain { @@ -212,7 +212,7 @@ fill_node(struct callchain_node *node, struct resolved_chain *chain, int start) return; } call->ip = chain->ips[i].ip; - call->sym = chain->ips[i].sym; + call->ms = chain->ips[i].ms; list_add_tail(&call->list, &node->val); } node->val_nr = chain->nr - start; @@ -318,10 +318,10 @@ __append_chain(struct callchain_node *root, struct resolved_chain *chain, if (i == chain->nr) break; - sym = chain->ips[i].sym; + sym = chain->ips[i].ms.sym; - if (cnode->sym && sym) { - if (cnode->sym->start != sym->start) + if (cnode->ms.sym && sym) { + if (cnode->ms.sym->start != sym->start) break; } else if (cnode->ip != chain->ips[i].ip) break; @@ -353,9 +353,8 @@ __append_chain(struct callchain_node *root, struct resolved_chain *chain, return 0; } -static void -filter_context(struct ip_callchain *old, struct resolved_chain *new, - struct symbol **syms) +static void filter_context(struct ip_callchain *old, struct resolved_chain *new, + struct map_symbol *syms) { int i, j = 0; @@ -364,7 +363,7 @@ filter_context(struct ip_callchain *old, struct resolved_chain *new, continue; new->ips[j].ip = old->ips[i]; - new->ips[j].sym = syms[i]; + new->ips[j].ms = syms[i]; j++; } @@ -373,7 +372,7 @@ filter_context(struct ip_callchain *old, struct resolved_chain *new, int append_chain(struct callchain_node *root, struct ip_callchain *chain, - struct symbol **syms) + struct map_symbol *syms) { struct resolved_chain *filtered; diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index bbd76da..8a7e8bb 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h @@ -39,7 +39,7 @@ struct callchain_param { struct callchain_list { u64 ip; - struct symbol *sym; + struct map_symbol ms; struct list_head list; }; @@ -57,5 +57,5 @@ static inline u64 cumul_hits(struct callchain_node *node) int register_callchain_param(struct callchain_param *param); int append_chain(struct callchain_node *root, struct ip_callchain *chain, - struct symbol **syms); + struct map_symbol *syms); #endif /* __PERF_CALLCHAIN_H */ diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 4eefb52..09e09e7 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -260,8 +260,8 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, } else ret += fprintf(fp, "%s", " "); } - if (chain->sym) - ret += fprintf(fp, "%s\n", chain->sym->name); + if (chain->ms.sym) + ret += fprintf(fp, "%s\n", chain->ms.sym->name); else ret += fprintf(fp, "%p\n", (void *)(long)chain->ip); @@ -280,7 +280,7 @@ static void init_rem_hits(void) } strcpy(rem_sq_bracket->name, "[...]"); - rem_hits.sym = rem_sq_bracket; + rem_hits.ms.sym = rem_sq_bracket; } static size_t __callchain__fprintf_graph(FILE *fp, struct callchain_node *self, @@ -382,8 +382,8 @@ static size_t callchain__fprintf_graph(FILE *fp, struct callchain_node *self, } else ret += callchain__fprintf_left_margin(fp, left_margin); - if (chain->sym) - ret += fprintf(fp, " %s\n", chain->sym->name); + if (chain->ms.sym) + ret += fprintf(fp, " %s\n", chain->ms.sym->name); else ret += fprintf(fp, " %p\n", (void *)(long)chain->ip); } @@ -408,8 +408,8 @@ static size_t callchain__fprintf_flat(FILE *fp, struct callchain_node *self, list_for_each_entry(chain, &self->val, list) { if (chain->ip >= PERF_CONTEXT_MAX) continue; - if (chain->sym) - ret += fprintf(fp, " %s\n", chain->sym->name); + if (chain->ms.sym) + ret += fprintf(fp, " %s\n", chain->ms.sym->name); else ret += fprintf(fp, " %p\n", (void *)(long)chain->ip); diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index 25cd2e1..f6953ca 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -104,8 +104,8 @@ static void newt_checkbox_tree__add(newtComponent tree, const char *str, static char *callchain_list__sym_name(struct callchain_list *self, char *bf, size_t bfsize) { - if (self->sym) - return self->sym->name; + if (self->ms.sym) + return self->ms.sym->name; snprintf(bf, bfsize, "%#Lx", self->ip); return bf; @@ -157,7 +157,7 @@ static void __callchain__append_graph_browser(struct callchain_node *self, indexes[depth + 2] = NEWT_ARG_LAST; ++chain_idx; } - newt_checkbox_tree__add(tree, str, chain->sym, indexes); + newt_checkbox_tree__add(tree, str, chain->ms.sym, indexes); free(alloc_str); ++printed; } @@ -193,7 +193,7 @@ static void callchain__append_graph_browser(struct callchain_node *self, continue; str = callchain_list__sym_name(chain, ipstr, sizeof(ipstr)); - newt_checkbox_tree__add(tree, str, chain->sym, indexes); + newt_checkbox_tree__add(tree, str, chain->ms.sym, indexes); } indexes[1] = parent_idx; diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index eed1cb8..2cef373 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -117,13 +117,13 @@ static bool symbol__match_parent_regex(struct symbol *sym) return 0; } -struct symbol **perf_session__resolve_callchain(struct perf_session *self, - struct thread *thread, - struct ip_callchain *chain, - struct symbol **parent) +struct map_symbol *perf_session__resolve_callchain(struct perf_session *self, + struct thread *thread, + struct ip_callchain *chain, + struct symbol **parent) { u8 cpumode = PERF_RECORD_MISC_USER; - struct symbol **syms = NULL; + struct map_symbol *syms = NULL; unsigned int i; if (symbol_conf.use_callchain) { @@ -160,7 +160,8 @@ struct symbol **perf_session__resolve_callchain(struct perf_session *self, *parent = al.sym; if (!symbol_conf.use_callchain) break; - syms[i] = al.sym; + syms[i].map = al.map; + syms[i].sym = al.sym; } } diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 34d7339..631f815 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -57,10 +57,10 @@ int __perf_session__process_events(struct perf_session *self, int perf_session__process_events(struct perf_session *self, struct perf_event_ops *event_ops); -struct symbol **perf_session__resolve_callchain(struct perf_session *self, - struct thread *thread, - struct ip_callchain *chain, - struct symbol **parent); +struct map_symbol *perf_session__resolve_callchain(struct perf_session *self, + struct thread *thread, + struct ip_callchain *chain, + struct symbol **parent); bool perf_session__has_traces(struct perf_session *self, const char *msg); -- cgit v0.10.2 From d5679ae4d2d4369477dc3b60027cca222aef33e9 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 24 Mar 2010 16:40:19 -0300 Subject: perf report: Pass the DSO to 'perf annotate' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So that we ensure that the symbol asked for annotation really is in the DSO we are interested in. Signed-off-by: Arnaldo Carvalho de Melo Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: <1269459619-982-6-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index f6953ca..e99bcc8 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -157,7 +157,7 @@ static void __callchain__append_graph_browser(struct callchain_node *self, indexes[depth + 2] = NEWT_ARG_LAST; ++chain_idx; } - newt_checkbox_tree__add(tree, str, chain->ms.sym, indexes); + newt_checkbox_tree__add(tree, str, &chain->ms, indexes); free(alloc_str); ++printed; } @@ -193,7 +193,7 @@ static void callchain__append_graph_browser(struct callchain_node *self, continue; str = callchain_list__sym_name(chain, ipstr, sizeof(ipstr)); - newt_checkbox_tree__add(tree, str, chain->ms.sym, indexes); + newt_checkbox_tree__add(tree, str, &chain->ms, indexes); } indexes[1] = parent_idx; @@ -287,14 +287,14 @@ static size_t hist_entry__append_browser(struct hist_entry *self, indexes[0] = NEWT_ARG_APPEND; indexes[1] = NEWT_ARG_LAST; - newt_checkbox_tree__add(tree, s, self->ms.sym, indexes); + newt_checkbox_tree__add(tree, s, &self->ms, indexes); } else - newtListboxAppendEntry(tree, s, self->ms.sym); + newtListboxAppendEntry(tree, s, &self->ms); return strlen(s); } -static void symbol__annotate_browser(const struct symbol *self) +static void map_symbol__annotate_browser(const struct map_symbol *self) { FILE *fp; int cols, rows; @@ -305,10 +305,11 @@ static void symbol__annotate_browser(const struct symbol *self) size_t max_usable_width; char *line = NULL; - if (self == NULL) + if (self->sym == NULL) return; - if (asprintf(&str, "perf annotate %s 2>&1 | expand", self->name) < 0) + if (asprintf(&str, "perf annotate -d \"%s\" %s 2>&1 | expand", + self->map->dso->name, self->sym->name) < 0) return; fp = popen(str, "r"); @@ -338,7 +339,7 @@ static void symbol__annotate_browser(const struct symbol *self) newtListboxSetWidth(tree, max_line_len); - newtCenteredWindow(max_line_len + 2, rows - 5, self->name); + newtCenteredWindow(max_line_len + 2, rows - 5, self->sym->name); form = newt_form__new(); newtFormAddComponents(form, tree, NULL); @@ -359,7 +360,7 @@ static const void *newt__symbol_tree_get_current(newtComponent self) static void perf_session__selection(newtComponent self, void *data) { - const struct symbol **symbol_ptr = data; + const struct map_symbol **symbol_ptr = data; *symbol_ptr = newt__symbol_tree_get_current(self); } @@ -376,7 +377,7 @@ void perf_session__browse_hists(struct rb_root *hists, u64 session_total, char str[1024]; newtComponent form, tree; struct newtExitStruct es; - const struct symbol *selection; + const struct map_symbol *selection; snprintf(str, sizeof(str), "Samples: %Ld", session_total); newtDrawRootText(0, 0, str); @@ -416,11 +417,8 @@ void perf_session__browse_hists(struct rb_root *hists, u64 session_total, int len = hist_entry__append_browser(h, tree, session_total); if (len > max_len) max_len = len; - if (symbol_conf.use_callchain) { + if (symbol_conf.use_callchain) hist_entry__append_callchain_browser(h, tree, session_total, idx++); - if (idx > 3300) - break; - } } if (max_len > cols) @@ -441,14 +439,12 @@ void perf_session__browse_hists(struct rb_root *hists, u64 session_total, while (1) { char annotate[512]; const char *options[2]; - int nr_options = 0, choice; + int nr_options = 0, choice = 0; newtFormRun(form, &es); if (es.reason == NEWT_EXIT_HOTKEY) { - if (toupper(es.u.key) == 'A') { - symbol__annotate_browser(selection); - continue; - } + if (toupper(es.u.key) == 'A') + goto do_annotate; if (es.u.key == NEWT_KEY_ESCAPE || toupper(es.u.key) == 'Q' || es.u.key == CTRL('c')) { @@ -459,9 +455,9 @@ void perf_session__browse_hists(struct rb_root *hists, u64 session_total, } } - if (selection != NULL) { + if (selection->sym != NULL) { snprintf(annotate, sizeof(annotate), - "Annotate %s", selection->name); + "Annotate %s", selection->sym->name); options[nr_options++] = annotate; } @@ -469,8 +465,17 @@ void perf_session__browse_hists(struct rb_root *hists, u64 session_total, choice = popup_menu(nr_options, options); if (choice == nr_options - 1) break; - else if (selection != NULL && choice >= 0) - symbol__annotate_browser(selection); +do_annotate: + if (selection->sym != NULL && choice >= 0) { + if (selection->map->dso->origin == DSO__ORIG_KERNEL) { + newtPopHelpLine(); + newtPushHelpLine("No vmlinux file found, can't " + "annotate with just a " + "kallsyms file"); + continue; + } + map_symbol__annotate_browser(selection); + } } newtFormDestroy(form); -- cgit v0.10.2 From b177f63f5226e75280855bbcd106e677250778bd Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 25 Mar 2010 19:58:57 -0300 Subject: perf symbols: Pass the mmap parameters instead of using mmap_event MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To reduce the coupling of the symbol system with the rest of perf. Signed-off-by: Arnaldo Carvalho de Melo Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: <1269557941-15617-2-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index c2808ad..052eaec 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -393,7 +393,8 @@ int event__process_mmap(event_t *self, struct perf_session *session) } thread = perf_session__findnew(session, self->mmap.pid); - map = map__new(&self->mmap, MAP__FUNCTION, + map = map__new(self->mmap.start, self->mmap.len, self->mmap.pgoff, + self->mmap.pid, self->mmap.filename, MAP__FUNCTION, session->cwd, session->cwdlen); if (thread == NULL || map == NULL) diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index e509cd5..a9b4227 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -1,4 +1,3 @@ -#include "event.h" #include "symbol.h" #include #include @@ -38,13 +37,12 @@ void map__init(struct map *self, enum map_type type, RB_CLEAR_NODE(&self->rb_node); } -struct map *map__new(struct mmap_event *event, enum map_type type, - char *cwd, int cwdlen) +struct map *map__new(u64 start, u64 len, u64 pgoff, u32 pid, char *filename, + enum map_type type, char *cwd, int cwdlen) { struct map *self = malloc(sizeof(*self)); if (self != NULL) { - const char *filename = event->filename; char newfilename[PATH_MAX]; struct dso *dso; int anon; @@ -62,7 +60,7 @@ struct map *map__new(struct mmap_event *event, enum map_type type, anon = is_anon_memory(filename); if (anon) { - snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", event->pid); + snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", pid); filename = newfilename; } @@ -70,8 +68,7 @@ struct map *map__new(struct mmap_event *event, enum map_type type, if (dso == NULL) goto out_delete; - map__init(self, type, event->start, event->start + event->len, - event->pgoff, dso); + map__init(self, type, start, start + len, pgoff, dso); if (anon) { set_identity: diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index b756368..a4a5bc4 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h @@ -68,14 +68,13 @@ u64 map__rip_2objdump(struct map *map, u64 rip); u64 map__objdump_2ip(struct map *map, u64 addr); struct symbol; -struct mmap_event; typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym); void map__init(struct map *self, enum map_type type, u64 start, u64 end, u64 pgoff, struct dso *dso); -struct map *map__new(struct mmap_event *event, enum map_type, - char *cwd, int cwdlen); +struct map *map__new(u64 start, u64 len, u64 pgoff, u32 pid, char *filename, + enum map_type type, char *cwd, int cwdlen); void map__delete(struct map *self); struct map *map__clone(struct map *self); int map__overlap(struct map *l, struct map *r); -- cgit v0.10.2 From 4b8cf84624e9a58a21aaac3d064222092ae234e0 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 25 Mar 2010 19:58:58 -0300 Subject: perf symbols: Move map related routines to map.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thru series of refactorings functions were being renamed but not moved to map.c to reduce patch noise, now lets have them in the same place so that use of the symbol system by tools can be constrained to building and linking fewer source files: symbol.c, map.c and rbtree.c. Signed-off-by: Arnaldo Carvalho de Melo Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: <1269557941-15617-3-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index a9b4227..9f2963f 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -1,8 +1,9 @@ #include "symbol.h" +#include #include #include #include -#include "debug.h" +#include "map.h" const char *map_type__name[MAP__NR_TYPES] = { [MAP__FUNCTION] = "Functions", @@ -232,3 +233,84 @@ u64 map__objdump_2ip(struct map *map, u64 addr) map->unmap_ip(map, addr); /* RIP -> IP */ return ip; } + +struct symbol *map_groups__find_symbol(struct map_groups *self, + enum map_type type, u64 addr, + symbol_filter_t filter) +{ + struct map *map = map_groups__find(self, type, addr); + + if (map != NULL) + return map__find_symbol(map, map->map_ip(map, addr), filter); + + return NULL; +} + +static u64 map__reloc_map_ip(struct map *map, u64 ip) +{ + return ip + (s64)map->pgoff; +} + +static u64 map__reloc_unmap_ip(struct map *map, u64 ip) +{ + return ip - (s64)map->pgoff; +} + +void map__reloc_vmlinux(struct map *self) +{ + struct kmap *kmap = map__kmap(self); + s64 reloc; + + if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->unrelocated_addr) + return; + + reloc = (kmap->ref_reloc_sym->unrelocated_addr - + kmap->ref_reloc_sym->addr); + + if (!reloc) + return; + + self->map_ip = map__reloc_map_ip; + self->unmap_ip = map__reloc_unmap_ip; + self->pgoff = reloc; +} + +void maps__insert(struct rb_root *maps, struct map *map) +{ + struct rb_node **p = &maps->rb_node; + struct rb_node *parent = NULL; + const u64 ip = map->start; + struct map *m; + + while (*p != NULL) { + parent = *p; + m = rb_entry(parent, struct map, rb_node); + if (ip < m->start) + p = &(*p)->rb_left; + else + p = &(*p)->rb_right; + } + + rb_link_node(&map->rb_node, parent, p); + rb_insert_color(&map->rb_node, maps); +} + +struct map *maps__find(struct rb_root *maps, u64 ip) +{ + struct rb_node **p = &maps->rb_node; + struct rb_node *parent = NULL; + struct map *m; + + while (*p != NULL) { + parent = *p; + m = rb_entry(parent, struct map, rb_node); + if (ip < m->start) + p = &(*p)->rb_left; + else if (ip > m->end) + p = &(*p)->rb_right; + else + return m; + } + + return NULL; +} diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index a4a5bc4..6a703fa 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h @@ -4,7 +4,8 @@ #include #include #include -#include +#include +#include "types.h" enum map_type { MAP__FUNCTION = 0, @@ -90,4 +91,48 @@ void map__fixup_end(struct map *self); void map__reloc_vmlinux(struct map *self); +struct map_groups { + struct rb_root maps[MAP__NR_TYPES]; + struct list_head removed_maps[MAP__NR_TYPES]; +}; + +size_t __map_groups__fprintf_maps(struct map_groups *self, + enum map_type type, FILE *fp); +void maps__insert(struct rb_root *maps, struct map *map); +struct map *maps__find(struct rb_root *maps, u64 addr); +void map_groups__init(struct map_groups *self); +size_t map_groups__fprintf_maps(struct map_groups *self, FILE *fp); + +static inline void map_groups__insert(struct map_groups *self, struct map *map) +{ + maps__insert(&self->maps[map->type], map); +} + +static inline struct map *map_groups__find(struct map_groups *self, + enum map_type type, u64 addr) +{ + return maps__find(&self->maps[type], addr); +} + +struct symbol *map_groups__find_symbol(struct map_groups *self, + enum map_type type, u64 addr, + symbol_filter_t filter); + +static inline struct symbol *map_groups__find_function(struct map_groups *self, + u64 addr, + symbol_filter_t filter) +{ + return map_groups__find_symbol(self, MAP__FUNCTION, addr, filter); +} + +struct map *map_groups__find_by_name(struct map_groups *self, + enum map_type type, const char *name); +int __map_groups__create_kernel_maps(struct map_groups *self, + struct map *vmlinux_maps[MAP__NR_TYPES], + struct dso *kernel); +int map_groups__create_kernel_maps(struct map_groups *self, + struct map *vmlinux_maps[MAP__NR_TYPES]); +struct map *map_groups__new_module(struct map_groups *self, u64 start, + const char *filename); + #endif /* __PERF_MAP_H */ diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 2cef373..76b4ac6 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -544,32 +544,3 @@ int perf_session__set_kallsyms_ref_reloc_sym(struct perf_session *self, return 0; } - -static u64 map__reloc_map_ip(struct map *map, u64 ip) -{ - return ip + (s64)map->pgoff; -} - -static u64 map__reloc_unmap_ip(struct map *map, u64 ip) -{ - return ip - (s64)map->pgoff; -} - -void map__reloc_vmlinux(struct map *self) -{ - struct kmap *kmap = map__kmap(self); - s64 reloc; - - if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->unrelocated_addr) - return; - - reloc = (kmap->ref_reloc_sym->unrelocated_addr - - kmap->ref_reloc_sym->addr); - - if (!reloc) - return; - - self->map_ip = map__reloc_map_ip; - self->unmap_ip = map__reloc_unmap_ip; - self->pgoff = reloc; -} diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index ea65062..9bbe27d 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c @@ -272,46 +272,6 @@ static int map_groups__fixup_overlappings(struct map_groups *self, return 0; } -void maps__insert(struct rb_root *maps, struct map *map) -{ - struct rb_node **p = &maps->rb_node; - struct rb_node *parent = NULL; - const u64 ip = map->start; - struct map *m; - - while (*p != NULL) { - parent = *p; - m = rb_entry(parent, struct map, rb_node); - if (ip < m->start) - p = &(*p)->rb_left; - else - p = &(*p)->rb_right; - } - - rb_link_node(&map->rb_node, parent, p); - rb_insert_color(&map->rb_node, maps); -} - -struct map *maps__find(struct rb_root *maps, u64 ip) -{ - struct rb_node **p = &maps->rb_node; - struct rb_node *parent = NULL; - struct map *m; - - while (*p != NULL) { - parent = *p; - m = rb_entry(parent, struct map, rb_node); - if (ip < m->start) - p = &(*p)->rb_left; - else if (ip > m->end) - p = &(*p)->rb_right; - else - return m; - } - - return NULL; -} - void thread__insert_map(struct thread *self, struct map *map) { map_groups__fixup_overlappings(&self->mg, map); @@ -367,16 +327,3 @@ size_t perf_session__fprintf(struct perf_session *self, FILE *fp) return ret; } - -struct symbol *map_groups__find_symbol(struct map_groups *self, - enum map_type type, u64 addr, - symbol_filter_t filter) -{ - struct map *map = map_groups__find(self, type, addr); - - if (map != NULL) - return map__find_symbol(map, map->map_ip(map, addr), filter); - - return NULL; -} - diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index a81426a..9c488fc 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h @@ -5,14 +5,6 @@ #include #include "symbol.h" -struct map_groups { - struct rb_root maps[MAP__NR_TYPES]; - struct list_head removed_maps[MAP__NR_TYPES]; -}; - -size_t __map_groups__fprintf_maps(struct map_groups *self, - enum map_type type, FILE *fp); - struct thread { struct rb_node rb_node; struct map_groups mg; @@ -23,30 +15,16 @@ struct thread { int comm_len; }; +struct perf_session; + int find_all_tid(int pid, pid_t ** all_tid); -void map_groups__init(struct map_groups *self); int thread__set_comm(struct thread *self, const char *comm); int thread__comm_len(struct thread *self); struct thread *perf_session__findnew(struct perf_session *self, pid_t pid); void thread__insert_map(struct thread *self, struct map *map); int thread__fork(struct thread *self, struct thread *parent); -size_t map_groups__fprintf_maps(struct map_groups *self, FILE *fp); size_t perf_session__fprintf(struct perf_session *self, FILE *fp); -void maps__insert(struct rb_root *maps, struct map *map); -struct map *maps__find(struct rb_root *maps, u64 addr); - -static inline void map_groups__insert(struct map_groups *self, struct map *map) -{ - maps__insert(&self->maps[map->type], map); -} - -static inline struct map *map_groups__find(struct map_groups *self, - enum map_type type, u64 addr) -{ - return maps__find(&self->maps[type], addr); -} - static inline struct map *thread__find_map(struct thread *self, enum map_type type, u64 addr) { @@ -63,26 +41,4 @@ void thread__find_addr_location(struct thread *self, enum map_type type, u64 addr, struct addr_location *al, symbol_filter_t filter); -struct symbol *map_groups__find_symbol(struct map_groups *self, - enum map_type type, u64 addr, - symbol_filter_t filter); - -static inline struct symbol *map_groups__find_function(struct map_groups *self, - u64 addr, - symbol_filter_t filter) -{ - return map_groups__find_symbol(self, MAP__FUNCTION, addr, filter); -} - -struct map *map_groups__find_by_name(struct map_groups *self, - enum map_type type, const char *name); - -int __map_groups__create_kernel_maps(struct map_groups *self, - struct map *vmlinux_maps[MAP__NR_TYPES], - struct dso *kernel); -int map_groups__create_kernel_maps(struct map_groups *self, - struct map *vmlinux_maps[MAP__NR_TYPES]); - -struct map *map_groups__new_module(struct map_groups *self, u64 start, - const char *filename); #endif /* __PERF_THREAD_H */ -- cgit v0.10.2 From 618038df3588fdfcaccfd40057f36ce792bee252 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 25 Mar 2010 19:58:59 -0300 Subject: perf tools: Move __used from perf.h to linux/compiler.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just like in the kernel and also to remove the need to include perf.h in the symbol subsystem. Signed-off-by: Arnaldo Carvalho de Melo Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: <1269557941-15617-4-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar diff --git a/tools/perf/perf.h b/tools/perf/perf.h index aa78615..ec21274 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h @@ -106,8 +106,6 @@ static inline unsigned long long rdclock(void) #define __user #define asmlinkage -#define __used __attribute__((__unused__)) - #define unlikely(x) __builtin_expect(!!(x), 0) #define min(x, y) ({ \ typeof(x) _min1 = (x); \ diff --git a/tools/perf/util/include/linux/compiler.h b/tools/perf/util/include/linux/compiler.h index dfb0713..791f9dd 100644 --- a/tools/perf/util/include/linux/compiler.h +++ b/tools/perf/util/include/linux/compiler.h @@ -7,4 +7,6 @@ #define __user #define __attribute_const__ +#define __used __attribute__((__unused__)) + #endif -- cgit v0.10.2 From 5aab621b7bf024608f0c089e21656e7fe875a150 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 25 Mar 2010 19:59:00 -0300 Subject: perf symbols: Move hex2u64 and strxfrchar to symbol.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mostly used in symbol.c so move them there to reduce the number of files needed to use the symbol system. Also do some header adjustments with the same intent. Signed-off-by: Arnaldo Carvalho de Melo Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: <1269557941-15617-5-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index a201445..435781e 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -5,6 +5,7 @@ #include "parse-events.h" #include "exec_cmd.h" #include "string.h" +#include "symbol.h" #include "cache.h" #include "header.h" #include "debugfs.h" diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c index a175949..d438924 100644 --- a/tools/perf/util/string.c +++ b/tools/perf/util/string.c @@ -1,49 +1,6 @@ #include "string.h" #include "util.h" -static int hex(char ch) -{ - if ((ch >= '0') && (ch <= '9')) - return ch - '0'; - if ((ch >= 'a') && (ch <= 'f')) - return ch - 'a' + 10; - if ((ch >= 'A') && (ch <= 'F')) - return ch - 'A' + 10; - return -1; -} - -/* - * While we find nice hex chars, build a long_val. - * Return number of chars processed. - */ -int hex2u64(const char *ptr, u64 *long_val) -{ - const char *p = ptr; - *long_val = 0; - - while (*p) { - const int hex_val = hex(*p); - - if (hex_val < 0) - break; - - *long_val = (*long_val << 4) | hex_val; - p++; - } - - return p - ptr; -} - -char *strxfrchar(char *s, char from, char to) -{ - char *p = s; - - while ((p = strchr(p, from)) != NULL) - *p++ = to; - - return s; -} - #define K 1024LL /* * perf_atoll() diff --git a/tools/perf/util/string.h b/tools/perf/util/string.h index 542e44d..7005824 100644 --- a/tools/perf/util/string.h +++ b/tools/perf/util/string.h @@ -4,8 +4,6 @@ #include #include "types.h" -int hex2u64(const char *ptr, u64 *val); -char *strxfrchar(char *s, char from, char to); s64 perf_atoll(const char *str); char **argv_split(const char *str, int *argcp); void argv_free(char **argv); diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 3eb9de4..f3d4151 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1,13 +1,19 @@ -#include "util.h" -#include "../perf.h" -#include "sort.h" -#include "string.h" +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "symbol.h" -#include "thread.h" +#include "strlist.h" -#include "debug.h" - -#include #include #include #include @@ -114,8 +120,8 @@ static void map_groups__fixup_end(struct map_groups *self) static struct symbol *symbol__new(u64 start, u64 len, const char *name) { size_t namelen = strlen(name) + 1; - struct symbol *self = zalloc(symbol_conf.priv_size + - sizeof(*self) + namelen); + struct symbol *self = calloc(1, (symbol_conf.priv_size + + sizeof(*self) + namelen)); if (self == NULL) return NULL; @@ -166,7 +172,7 @@ static void dso__set_basename(struct dso *self) struct dso *dso__new(const char *name) { - struct dso *self = zalloc(sizeof(*self) + strlen(name) + 1); + struct dso *self = calloc(1, sizeof(*self) + strlen(name) + 1); if (self != NULL) { int i; @@ -1382,13 +1388,13 @@ static int dso__kernel_module_get_build_id(struct dso *self) return 0; } -static int map_groups__set_modules_path_dir(struct map_groups *self, char *dirname) +static int map_groups__set_modules_path_dir(struct map_groups *self, char *dir_name) { struct dirent *dent; - DIR *dir = opendir(dirname); + DIR *dir = opendir(dir_name); if (!dir) { - pr_debug("%s: cannot open %s dir\n", __func__, dirname); + pr_debug("%s: cannot open %s dir\n", __func__, dir_name); return -1; } @@ -1401,7 +1407,7 @@ static int map_groups__set_modules_path_dir(struct map_groups *self, char *dirna continue; snprintf(path, sizeof(path), "%s/%s", - dirname, dent->d_name); + dir_name, dent->d_name); if (map_groups__set_modules_path_dir(self, path) < 0) goto failure; } else { @@ -1421,7 +1427,7 @@ static int map_groups__set_modules_path_dir(struct map_groups *self, char *dirna continue; snprintf(path, sizeof(path), "%s/%s", - dirname, dent->d_name); + dir_name, dent->d_name); long_name = strdup(path); if (long_name == NULL) @@ -1458,8 +1464,8 @@ static int map_groups__set_modules_path(struct map_groups *self) */ static struct map *map__new2(u64 start, struct dso *dso, enum map_type type) { - struct map *self = zalloc(sizeof(*self) + - (dso->kernel ? sizeof(struct kmap) : 0)); + struct map *self = calloc(1, (sizeof(*self) + + (dso->kernel ? sizeof(struct kmap) : 0))); if (self != NULL) { /* * ->end will be filled after we load all the symbols @@ -1963,3 +1969,46 @@ int map_groups__create_kernel_maps(struct map_groups *self, map_groups__fixup_end(self); return 0; } + +static int hex(char ch) +{ + if ((ch >= '0') && (ch <= '9')) + return ch - '0'; + if ((ch >= 'a') && (ch <= 'f')) + return ch - 'a' + 10; + if ((ch >= 'A') && (ch <= 'F')) + return ch - 'A' + 10; + return -1; +} + +/* + * While we find nice hex chars, build a long_val. + * Return number of chars processed. + */ +int hex2u64(const char *ptr, u64 *long_val) +{ + const char *p = ptr; + *long_val = 0; + + while (*p) { + const int hex_val = hex(*p); + + if (hex_val < 0) + break; + + *long_val = (*long_val << 4) | hex_val; + p++; + } + + return p - ptr; +} + +char *strxfrchar(char *s, char from, char to) +{ + char *p = s; + + while ((p = strchr(p, from)) != NULL) + *p++ = to; + + return s; +} diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index a4a894b..757fae3 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -3,10 +3,11 @@ #include #include -#include "types.h" +#include +#include "map.h" #include #include -#include "event.h" +#include #define DEBUG_CACHE_DIR ".debug" @@ -29,6 +30,9 @@ static inline char *bfd_demangle(void __used *v, const char __used *c, #endif #endif +int hex2u64(const char *ptr, u64 *val); +char *strxfrchar(char *s, char from, char to); + /* * libelf 0.8.x and earlier do not support ELF_C_READ_MMAP; * for newer versions we can use mmap to reduce memory usage: @@ -44,6 +48,8 @@ static inline char *bfd_demangle(void __used *v, const char __used *c, #define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ #endif +#define BUILD_ID_SIZE 20 + struct symbol { struct rb_node rb_node; u64 start; -- cgit v0.10.2 From 5a10317483f606106395814ee2fdaa2f1256a3b3 Mon Sep 17 00:00:00 2001 From: "Zhang, Yanmin" Date: Thu, 25 Mar 2010 19:59:01 -0300 Subject: perf record: Zero out mmap_array to fix segfault Reported-by: Li Zefan Tested-by: Li Zefan Signed-off-by: Zhang Yanmin Signed-off-by: Arnaldo Carvalho de Melo LKML-Reference: <1269557941-15617-6-git-send-email-acme@infradead.org> Cc: Signed-off-by: Ingo Molnar diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index bb5b23d..60ecdd3 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -751,7 +751,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used) for (i = 0; i < MAX_NR_CPUS; i++) { for (j = 0; j < MAX_COUNTERS; j++) { fd[i][j] = malloc(sizeof(int)*thread_num); - mmap_array[i][j] = malloc( + mmap_array[i][j] = zalloc( sizeof(struct mmap_data)*thread_num); if (!fd[i][j] || !mmap_array[i][j]) return -ENOMEM; diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 5f3ac9f..4abdd9b 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -1371,7 +1371,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used) for (i = 0; i < MAX_NR_CPUS; i++) { for (j = 0; j < MAX_COUNTERS; j++) { fd[i][j] = malloc(sizeof(int)*thread_num); - mmap_array[i][j] = malloc( + mmap_array[i][j] = zalloc( sizeof(struct mmap_data)*thread_num); if (!fd[i][j] || !mmap_array[i][j]) return -ENOMEM; -- cgit v0.10.2 From 7c5ecaf7666617889f337296c610815b519abfa9 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 25 Mar 2010 14:51:49 +0100 Subject: perf, x86: Clean up debugctlmsr bit definitions Move all debugctlmsr thingies into msr-index.h Signed-off-by: Peter Zijlstra LKML-Reference: <20100325135413.861425293@chello.nl> Signed-off-by: Ingo Molnar diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index aef562c..06e4cf0 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -71,11 +71,14 @@ #define MSR_IA32_LASTINTTOIP 0x000001de /* DEBUGCTLMSR bits (others vary by model): */ -#define _DEBUGCTLMSR_LBR 0 /* last branch recording */ -#define _DEBUGCTLMSR_BTF 1 /* single-step on branches */ - -#define DEBUGCTLMSR_LBR (1UL << _DEBUGCTLMSR_LBR) -#define DEBUGCTLMSR_BTF (1UL << _DEBUGCTLMSR_BTF) +#define DEBUGCTLMSR_LBR (1UL << 0) /* last branch recording */ +#define DEBUGCTLMSR_BTF (1UL << 1) /* single-step on branches */ +#define DEBUGCTLMSR_TR (1UL << 6) +#define DEBUGCTLMSR_BTS (1UL << 7) +#define DEBUGCTLMSR_BTINT (1UL << 8) +#define DEBUGCTLMSR_BTS_OFF_OS (1UL << 9) +#define DEBUGCTLMSR_BTS_OFF_USR (1UL << 10) +#define DEBUGCTLMSR_FREEZE_LBRS_ON_PMI (1UL << 11) #define MSR_IA32_MC0_CTL 0x00000400 #define MSR_IA32_MC0_STATUS 0x00000401 diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c index c59678a..2fea362 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -38,15 +38,6 @@ struct pebs_record_nhm { }; /* - * Bits in the debugctlmsr controlling branch tracing. - */ -#define X86_DEBUGCTL_TR (1 << 6) -#define X86_DEBUGCTL_BTS (1 << 7) -#define X86_DEBUGCTL_BTINT (1 << 8) -#define X86_DEBUGCTL_BTS_OFF_OS (1 << 9) -#define X86_DEBUGCTL_BTS_OFF_USR (1 << 10) - -/* * A debug store configuration. * * We only support architectures that use 64bit fields. @@ -193,15 +184,15 @@ static void intel_pmu_enable_bts(u64 config) debugctlmsr = get_debugctlmsr(); - debugctlmsr |= X86_DEBUGCTL_TR; - debugctlmsr |= X86_DEBUGCTL_BTS; - debugctlmsr |= X86_DEBUGCTL_BTINT; + debugctlmsr |= DEBUGCTLMSR_TR; + debugctlmsr |= DEBUGCTLMSR_BTS; + debugctlmsr |= DEBUGCTLMSR_BTINT; if (!(config & ARCH_PERFMON_EVENTSEL_OS)) - debugctlmsr |= X86_DEBUGCTL_BTS_OFF_OS; + debugctlmsr |= DEBUGCTLMSR_BTS_OFF_OS; if (!(config & ARCH_PERFMON_EVENTSEL_USR)) - debugctlmsr |= X86_DEBUGCTL_BTS_OFF_USR; + debugctlmsr |= DEBUGCTLMSR_BTS_OFF_USR; update_debugctlmsr(debugctlmsr); } @@ -217,8 +208,8 @@ static void intel_pmu_disable_bts(void) debugctlmsr = get_debugctlmsr(); debugctlmsr &= - ~(X86_DEBUGCTL_TR | X86_DEBUGCTL_BTS | X86_DEBUGCTL_BTINT | - X86_DEBUGCTL_BTS_OFF_OS | X86_DEBUGCTL_BTS_OFF_USR); + ~(DEBUGCTLMSR_TR | DEBUGCTLMSR_BTS | DEBUGCTLMSR_BTINT | + DEBUGCTLMSR_BTS_OFF_OS | DEBUGCTLMSR_BTS_OFF_USR); update_debugctlmsr(debugctlmsr); } diff --git a/arch/x86/kernel/cpu/perf_event_intel_lbr.c b/arch/x86/kernel/cpu/perf_event_intel_lbr.c index df4c98e..d202c1b 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_lbr.c +++ b/arch/x86/kernel/cpu/perf_event_intel_lbr.c @@ -12,15 +12,12 @@ enum { * otherwise it becomes near impossible to get a reliable stack. */ -#define X86_DEBUGCTL_LBR (1 << 0) -#define X86_DEBUGCTL_FREEZE_LBRS_ON_PMI (1 << 11) - static void __intel_pmu_lbr_enable(void) { u64 debugctl; rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl); - debugctl |= (X86_DEBUGCTL_LBR | X86_DEBUGCTL_FREEZE_LBRS_ON_PMI); + debugctl |= (DEBUGCTLMSR_LBR | DEBUGCTLMSR_FREEZE_LBRS_ON_PMI); wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctl); } @@ -29,7 +26,7 @@ static void __intel_pmu_lbr_disable(void) u64 debugctl; rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl); - debugctl &= ~(X86_DEBUGCTL_LBR | X86_DEBUGCTL_FREEZE_LBRS_ON_PMI); + debugctl &= ~(DEBUGCTLMSR_LBR | DEBUGCTLMSR_FREEZE_LBRS_ON_PMI); wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctl); } -- cgit v0.10.2 From faa4602e47690fb11221e00f9b9697c8dc0d4b19 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 25 Mar 2010 14:51:50 +0100 Subject: x86, perf, bts, mm: Delete the never used BTS-ptrace code Support for the PMU's BTS features has been upstreamed in v2.6.32, but we still have the old and disabled ptrace-BTS, as Linus noticed it not so long ago. It's buggy: TIF_DEBUGCTLMSR is trampling all over that MSR without regard for other uses (perf) and doesn't provide the flexibility needed for perf either. Its users are ptrace-block-step and ptrace-bts, since ptrace-bts was never used and ptrace-block-step can be implemented using a much simpler approach. So axe all 3000 lines of it. That includes the *locked_memory*() APIs in mm/mlock.c as well. Reported-by: Linus Torvalds Signed-off-by: Peter Zijlstra Cc: Roland McGrath Cc: Oleg Nesterov Cc: Markus Metzger Cc: Steven Rostedt Cc: Andrew Morton LKML-Reference: <20100325135413.938004390@chello.nl> Signed-off-by: Ingo Molnar diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu index a198293..918fbb1 100644 --- a/arch/x86/Kconfig.cpu +++ b/arch/x86/Kconfig.cpu @@ -502,23 +502,3 @@ config CPU_SUP_UMC_32 CPU might render the kernel unbootable. If unsure, say N. - -config X86_DS - def_bool X86_PTRACE_BTS - depends on X86_DEBUGCTLMSR - select HAVE_HW_BRANCH_TRACER - -config X86_PTRACE_BTS - bool "Branch Trace Store" - default y - depends on X86_DEBUGCTLMSR - depends on BROKEN - ---help--- - This adds a ptrace interface to the hardware's branch trace store. - - Debuggers may use it to collect an execution trace of the debugged - application in order to answer the question 'how did I get here?'. - Debuggers may trace user mode as well as kernel mode. - - Say Y unless there is no application development on this machine - and you want to save a small amount of code size. diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index bc01e3e..bd58c8a 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -174,15 +174,6 @@ config IOMMU_LEAK Add a simple leak tracer to the IOMMU code. This is useful when you are debugging a buggy device driver that leaks IOMMU mappings. -config X86_DS_SELFTEST - bool "DS selftest" - default y - depends on DEBUG_KERNEL - depends on X86_DS - ---help--- - Perform Debug Store selftests at boot time. - If in doubt, say "N". - config HAVE_MMIOTRACE_SUPPORT def_bool y diff --git a/arch/x86/include/asm/ds.h b/arch/x86/include/asm/ds.h deleted file mode 100644 index 70dac19..0000000 --- a/arch/x86/include/asm/ds.h +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Debug Store (DS) support - * - * This provides a low-level interface to the hardware's Debug Store - * feature that is used for branch trace store (BTS) and - * precise-event based sampling (PEBS). - * - * It manages: - * - DS and BTS hardware configuration - * - buffer overflow handling (to be done) - * - buffer access - * - * It does not do: - * - security checking (is the caller allowed to trace the task) - * - buffer allocation (memory accounting) - * - * - * Copyright (C) 2007-2009 Intel Corporation. - * Markus Metzger , 2007-2009 - */ - -#ifndef _ASM_X86_DS_H -#define _ASM_X86_DS_H - - -#include -#include -#include - - -#ifdef CONFIG_X86_DS - -struct task_struct; -struct ds_context; -struct ds_tracer; -struct bts_tracer; -struct pebs_tracer; - -typedef void (*bts_ovfl_callback_t)(struct bts_tracer *); -typedef void (*pebs_ovfl_callback_t)(struct pebs_tracer *); - - -/* - * A list of features plus corresponding macros to talk about them in - * the ds_request function's flags parameter. - * - * We use the enum to index an array of corresponding control bits; - * we use the macro to index a flags bit-vector. - */ -enum ds_feature { - dsf_bts = 0, - dsf_bts_kernel, -#define BTS_KERNEL (1 << dsf_bts_kernel) - /* trace kernel-mode branches */ - - dsf_bts_user, -#define BTS_USER (1 << dsf_bts_user) - /* trace user-mode branches */ - - dsf_bts_overflow, - dsf_bts_max, - dsf_pebs = dsf_bts_max, - - dsf_pebs_max, - dsf_ctl_max = dsf_pebs_max, - dsf_bts_timestamps = dsf_ctl_max, -#define BTS_TIMESTAMPS (1 << dsf_bts_timestamps) - /* add timestamps into BTS trace */ - -#define BTS_USER_FLAGS (BTS_KERNEL | BTS_USER | BTS_TIMESTAMPS) -}; - - -/* - * Request BTS or PEBS - * - * Due to alignement constraints, the actual buffer may be slightly - * smaller than the requested or provided buffer. - * - * Returns a pointer to a tracer structure on success, or - * ERR_PTR(errcode) on failure. - * - * The interrupt threshold is independent from the overflow callback - * to allow users to use their own overflow interrupt handling mechanism. - * - * The function might sleep. - * - * task: the task to request recording for - * cpu: the cpu to request recording for - * base: the base pointer for the (non-pageable) buffer; - * size: the size of the provided buffer in bytes - * ovfl: pointer to a function to be called on buffer overflow; - * NULL if cyclic buffer requested - * th: the interrupt threshold in records from the end of the buffer; - * -1 if no interrupt threshold is requested. - * flags: a bit-mask of the above flags - */ -extern struct bts_tracer *ds_request_bts_task(struct task_struct *task, - void *base, size_t size, - bts_ovfl_callback_t ovfl, - size_t th, unsigned int flags); -extern struct bts_tracer *ds_request_bts_cpu(int cpu, void *base, size_t size, - bts_ovfl_callback_t ovfl, - size_t th, unsigned int flags); -extern struct pebs_tracer *ds_request_pebs_task(struct task_struct *task, - void *base, size_t size, - pebs_ovfl_callback_t ovfl, - size_t th, unsigned int flags); -extern struct pebs_tracer *ds_request_pebs_cpu(int cpu, - void *base, size_t size, - pebs_ovfl_callback_t ovfl, - size_t th, unsigned int flags); - -/* - * Release BTS or PEBS resources - * Suspend and resume BTS or PEBS tracing - * - * Must be called with irq's enabled. - * - * tracer: the tracer handle returned from ds_request_~() - */ -extern void ds_release_bts(struct bts_tracer *tracer); -extern void ds_suspend_bts(struct bts_tracer *tracer); -extern void ds_resume_bts(struct bts_tracer *tracer); -extern void ds_release_pebs(struct pebs_tracer *tracer); -extern void ds_suspend_pebs(struct pebs_tracer *tracer); -extern void ds_resume_pebs(struct pebs_tracer *tracer); - -/* - * Release BTS or PEBS resources - * Suspend and resume BTS or PEBS tracing - * - * Cpu tracers must call this on the traced cpu. - * Task tracers must call ds_release_~_noirq() for themselves. - * - * May be called with irq's disabled. - * - * Returns 0 if successful; - * -EPERM if the cpu tracer does not trace the current cpu. - * -EPERM if the task tracer does not trace itself. - * - * tracer: the tracer handle returned from ds_request_~() - */ -extern int ds_release_bts_noirq(struct bts_tracer *tracer); -extern int ds_suspend_bts_noirq(struct bts_tracer *tracer); -extern int ds_resume_bts_noirq(struct bts_tracer *tracer); -extern int ds_release_pebs_noirq(struct pebs_tracer *tracer); -extern int ds_suspend_pebs_noirq(struct pebs_tracer *tracer); -extern int ds_resume_pebs_noirq(struct pebs_tracer *tracer); - - -/* - * The raw DS buffer state as it is used for BTS and PEBS recording. - * - * This is the low-level, arch-dependent interface for working - * directly on the raw trace data. - */ -struct ds_trace { - /* the number of bts/pebs records */ - size_t n; - /* the size of a bts/pebs record in bytes */ - size_t size; - /* pointers into the raw buffer: - - to the first entry */ - void *begin; - /* - one beyond the last entry */ - void *end; - /* - one beyond the newest entry */ - void *top; - /* - the interrupt threshold */ - void *ith; - /* flags given on ds_request() */ - unsigned int flags; -}; - -/* - * An arch-independent view on branch trace data. - */ -enum bts_qualifier { - bts_invalid, -#define BTS_INVALID bts_invalid - - bts_branch, -#define BTS_BRANCH bts_branch - - bts_task_arrives, -#define BTS_TASK_ARRIVES bts_task_arrives - - bts_task_departs, -#define BTS_TASK_DEPARTS bts_task_departs - - bts_qual_bit_size = 4, - bts_qual_max = (1 << bts_qual_bit_size), -}; - -struct bts_struct { - __u64 qualifier; - union { - /* BTS_BRANCH */ - struct { - __u64 from; - __u64 to; - } lbr; - /* BTS_TASK_ARRIVES or BTS_TASK_DEPARTS */ - struct { - __u64 clock; - pid_t pid; - } event; - } variant; -}; - - -/* - * The BTS state. - * - * This gives access to the raw DS state and adds functions to provide - * an arch-independent view of the BTS data. - */ -struct bts_trace { - struct ds_trace ds; - - int (*read)(struct bts_tracer *tracer, const void *at, - struct bts_struct *out); - int (*write)(struct bts_tracer *tracer, const struct bts_struct *in); -}; - - -/* - * The PEBS state. - * - * This gives access to the raw DS state and the PEBS-specific counter - * reset value. - */ -struct pebs_trace { - struct ds_trace ds; - - /* the number of valid counters in the below array */ - unsigned int counters; - -#define MAX_PEBS_COUNTERS 4 - /* the counter reset value */ - unsigned long long counter_reset[MAX_PEBS_COUNTERS]; -}; - - -/* - * Read the BTS or PEBS trace. - * - * Returns a view on the trace collected for the parameter tracer. - * - * The view remains valid as long as the traced task is not running or - * the tracer is suspended. - * Writes into the trace buffer are not reflected. - * - * tracer: the tracer handle returned from ds_request_~() - */ -extern const struct bts_trace *ds_read_bts(struct bts_tracer *tracer); -extern const struct pebs_trace *ds_read_pebs(struct pebs_tracer *tracer); - - -/* - * Reset the write pointer of the BTS/PEBS buffer. - * - * Returns 0 on success; -Eerrno on error - * - * tracer: the tracer handle returned from ds_request_~() - */ -extern int ds_reset_bts(struct bts_tracer *tracer); -extern int ds_reset_pebs(struct pebs_tracer *tracer); - -/* - * Set the PEBS counter reset value. - * - * Returns 0 on success; -Eerrno on error - * - * tracer: the tracer handle returned from ds_request_pebs() - * counter: the index of the counter - * value: the new counter reset value - */ -extern int ds_set_pebs_reset(struct pebs_tracer *tracer, - unsigned int counter, u64 value); - -/* - * Initialization - */ -struct cpuinfo_x86; -extern void __cpuinit ds_init_intel(struct cpuinfo_x86 *); - -/* - * Context switch work - */ -extern void ds_switch_to(struct task_struct *prev, struct task_struct *next); - -#else /* CONFIG_X86_DS */ - -struct cpuinfo_x86; -static inline void __cpuinit ds_init_intel(struct cpuinfo_x86 *ignored) {} -static inline void ds_switch_to(struct task_struct *prev, - struct task_struct *next) {} - -#endif /* CONFIG_X86_DS */ -#endif /* _ASM_X86_DS_H */ diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index b753ea5..5bec21a 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -21,7 +21,6 @@ struct mm_struct; #include #include #include -#include #include #include @@ -29,6 +28,7 @@ struct mm_struct; #include #include #include +#include #define HBP_NUM 4 /* @@ -473,10 +473,6 @@ struct thread_struct { unsigned long iopl; /* Max allowed port in the bitmap, in bytes: */ unsigned io_bitmap_max; -/* MSR_IA32_DEBUGCTLMSR value to switch in if TIF_DEBUGCTLMSR is set. */ - unsigned long debugctlmsr; - /* Debug Store context; see asm/ds.h */ - struct ds_context *ds_ctx; }; static inline unsigned long native_get_debugreg(int regno) @@ -814,21 +810,6 @@ static inline unsigned long get_debugctlmsr(void) return debugctlmsr; } -static inline unsigned long get_debugctlmsr_on_cpu(int cpu) -{ - u64 debugctlmsr = 0; - u32 val1, val2; - -#ifndef CONFIG_X86_DEBUGCTLMSR - if (boot_cpu_data.x86 < 6) - return 0; -#endif - rdmsr_on_cpu(cpu, MSR_IA32_DEBUGCTLMSR, &val1, &val2); - debugctlmsr = val1 | ((u64)val2 << 32); - - return debugctlmsr; -} - static inline void update_debugctlmsr(unsigned long debugctlmsr) { #ifndef CONFIG_X86_DEBUGCTLMSR @@ -838,18 +819,6 @@ static inline void update_debugctlmsr(unsigned long debugctlmsr) wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctlmsr); } -static inline void update_debugctlmsr_on_cpu(int cpu, - unsigned long debugctlmsr) -{ -#ifndef CONFIG_X86_DEBUGCTLMSR - if (boot_cpu_data.x86 < 6) - return; -#endif - wrmsr_on_cpu(cpu, MSR_IA32_DEBUGCTLMSR, - (u32)((u64)debugctlmsr), - (u32)((u64)debugctlmsr >> 32)); -} - /* * from system description table in BIOS. Mostly for MCA use, but * others may find it useful: diff --git a/arch/x86/include/asm/ptrace-abi.h b/arch/x86/include/asm/ptrace-abi.h index 8672303..52b098a 100644 --- a/arch/x86/include/asm/ptrace-abi.h +++ b/arch/x86/include/asm/ptrace-abi.h @@ -82,61 +82,6 @@ #ifndef __ASSEMBLY__ #include - -/* configuration/status structure used in PTRACE_BTS_CONFIG and - PTRACE_BTS_STATUS commands. -*/ -struct ptrace_bts_config { - /* requested or actual size of BTS buffer in bytes */ - __u32 size; - /* bitmask of below flags */ - __u32 flags; - /* buffer overflow signal */ - __u32 signal; - /* actual size of bts_struct in bytes */ - __u32 bts_size; -}; -#endif /* __ASSEMBLY__ */ - -#define PTRACE_BTS_O_TRACE 0x1 /* branch trace */ -#define PTRACE_BTS_O_SCHED 0x2 /* scheduling events w/ jiffies */ -#define PTRACE_BTS_O_SIGNAL 0x4 /* send SIG on buffer overflow - instead of wrapping around */ -#define PTRACE_BTS_O_ALLOC 0x8 /* (re)allocate buffer */ - -#define PTRACE_BTS_CONFIG 40 -/* Configure branch trace recording. - ADDR points to a struct ptrace_bts_config. - DATA gives the size of that buffer. - A new buffer is allocated, if requested in the flags. - An overflow signal may only be requested for new buffers. - Returns the number of bytes read. -*/ -#define PTRACE_BTS_STATUS 41 -/* Return the current configuration in a struct ptrace_bts_config - pointed to by ADDR; DATA gives the size of that buffer. - Returns the number of bytes written. -*/ -#define PTRACE_BTS_SIZE 42 -/* Return the number of available BTS records for draining. - DATA and ADDR are ignored. -*/ -#define PTRACE_BTS_GET 43 -/* Get a single BTS record. - DATA defines the index into the BTS array, where 0 is the newest - entry, and higher indices refer to older entries. - ADDR is pointing to struct bts_struct (see asm/ds.h). -*/ -#define PTRACE_BTS_CLEAR 44 -/* Clear the BTS buffer. - DATA and ADDR are ignored. -*/ -#define PTRACE_BTS_DRAIN 45 -/* Read all available BTS records and clear the buffer. - ADDR points to an array of struct bts_struct. - DATA gives the size of that buffer. - BTS records are read from oldest to newest. - Returns number of BTS records drained. -*/ +#endif #endif /* _ASM_X86_PTRACE_ABI_H */ diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h index 69a686a..78cd1ea 100644 --- a/arch/x86/include/asm/ptrace.h +++ b/arch/x86/include/asm/ptrace.h @@ -289,12 +289,6 @@ extern int do_get_thread_area(struct task_struct *p, int idx, extern int do_set_thread_area(struct task_struct *p, int idx, struct user_desc __user *info, int can_allocate); -#ifdef CONFIG_X86_PTRACE_BTS -extern void ptrace_bts_untrace(struct task_struct *tsk); - -#define arch_ptrace_untrace(tsk) ptrace_bts_untrace(tsk) -#endif /* CONFIG_X86_PTRACE_BTS */ - #endif /* __KERNEL__ */ #endif /* !__ASSEMBLY__ */ diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h index e0d2890..dc85e12 100644 --- a/arch/x86/include/asm/thread_info.h +++ b/arch/x86/include/asm/thread_info.h @@ -92,8 +92,6 @@ struct thread_info { #define TIF_IO_BITMAP 22 /* uses I/O bitmap */ #define TIF_FREEZE 23 /* is freezing for suspend */ #define TIF_FORCED_TF 24 /* true if TF in eflags artificially */ -#define TIF_DEBUGCTLMSR 25 /* uses thread_struct.debugctlmsr */ -#define TIF_DS_AREA_MSR 26 /* uses thread_struct.ds_area_msr */ #define TIF_LAZY_MMU_UPDATES 27 /* task is updating the mmu lazily */ #define TIF_SYSCALL_TRACEPOINT 28 /* syscall tracepoint instrumentation */ @@ -115,8 +113,6 @@ struct thread_info { #define _TIF_IO_BITMAP (1 << TIF_IO_BITMAP) #define _TIF_FREEZE (1 << TIF_FREEZE) #define _TIF_FORCED_TF (1 << TIF_FORCED_TF) -#define _TIF_DEBUGCTLMSR (1 << TIF_DEBUGCTLMSR) -#define _TIF_DS_AREA_MSR (1 << TIF_DS_AREA_MSR) #define _TIF_LAZY_MMU_UPDATES (1 << TIF_LAZY_MMU_UPDATES) #define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT) @@ -147,7 +143,7 @@ struct thread_info { /* flags to check in __switch_to() */ #define _TIF_WORK_CTXSW \ - (_TIF_IO_BITMAP|_TIF_DEBUGCTLMSR|_TIF_DS_AREA_MSR|_TIF_NOTSC) + (_TIF_IO_BITMAP|_TIF_NOTSC) #define _TIF_WORK_CTXSW_PREV (_TIF_WORK_CTXSW|_TIF_USER_RETURN_NOTIFY) #define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW|_TIF_DEBUG) diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 4c58352..e77b220 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -47,8 +47,6 @@ obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o obj-y += process.o obj-y += i387.o xsave.o obj-y += ptrace.o -obj-$(CONFIG_X86_DS) += ds.o -obj-$(CONFIG_X86_DS_SELFTEST) += ds_selftest.o obj-$(CONFIG_X86_32) += tls.o obj-$(CONFIG_IA32_EMULATION) += tls.o obj-y += step.o diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 7e1cca1..d72377c 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include @@ -367,7 +366,6 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) set_cpu_cap(c, X86_FEATURE_BTS); if (!(l1 & (1<<12))) set_cpu_cap(c, X86_FEATURE_PEBS); - ds_init_intel(c); } if (c->x86 == 6 && c->x86_model == 29 && cpu_has_clflush) diff --git a/arch/x86/kernel/ds.c b/arch/x86/kernel/ds.c deleted file mode 100644 index 1c47390..0000000 --- a/arch/x86/kernel/ds.c +++ /dev/null @@ -1,1437 +0,0 @@ -/* - * Debug Store support - * - * This provides a low-level interface to the hardware's Debug Store - * feature that is used for branch trace store (BTS) and - * precise-event based sampling (PEBS). - * - * It manages: - * - DS and BTS hardware configuration - * - buffer overflow handling (to be done) - * - buffer access - * - * It does not do: - * - security checking (is the caller allowed to trace the task) - * - buffer allocation (memory accounting) - * - * - * Copyright (C) 2007-2009 Intel Corporation. - * Markus Metzger , 2007-2009 - */ - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "ds_selftest.h" - -/* - * The configuration for a particular DS hardware implementation: - */ -struct ds_configuration { - /* The name of the configuration: */ - const char *name; - - /* The size of pointer-typed fields in DS, BTS, and PEBS: */ - unsigned char sizeof_ptr_field; - - /* The size of a BTS/PEBS record in bytes: */ - unsigned char sizeof_rec[2]; - - /* The number of pebs counter reset values in the DS structure. */ - unsigned char nr_counter_reset; - - /* Control bit-masks indexed by enum ds_feature: */ - unsigned long ctl[dsf_ctl_max]; -}; -static struct ds_configuration ds_cfg __read_mostly; - - -/* Maximal size of a DS configuration: */ -#define MAX_SIZEOF_DS 0x80 - -/* Maximal size of a BTS record: */ -#define MAX_SIZEOF_BTS (3 * 8) - -/* BTS and PEBS buffer alignment: */ -#define DS_ALIGNMENT (1 << 3) - -/* Number of buffer pointers in DS: */ -#define NUM_DS_PTR_FIELDS 8 - -/* Size of a pebs reset value in DS: */ -#define PEBS_RESET_FIELD_SIZE 8 - -/* Mask of control bits in the DS MSR register: */ -#define BTS_CONTROL \ - ( ds_cfg.ctl[dsf_bts] | \ - ds_cfg.ctl[dsf_bts_kernel] | \ - ds_cfg.ctl[dsf_bts_user] | \ - ds_cfg.ctl[dsf_bts_overflow] ) - -/* - * A BTS or PEBS tracer. - * - * This holds the configuration of the tracer and serves as a handle - * to identify tracers. - */ -struct ds_tracer { - /* The DS context (partially) owned by this tracer. */ - struct ds_context *context; - /* The buffer provided on ds_request() and its size in bytes. */ - void *buffer; - size_t size; -}; - -struct bts_tracer { - /* The common DS part: */ - struct ds_tracer ds; - - /* The trace including the DS configuration: */ - struct bts_trace trace; - - /* Buffer overflow notification function: */ - bts_ovfl_callback_t ovfl; - - /* Active flags affecting trace collection. */ - unsigned int flags; -}; - -struct pebs_tracer { - /* The common DS part: */ - struct ds_tracer ds; - - /* The trace including the DS configuration: */ - struct pebs_trace trace; - - /* Buffer overflow notification function: */ - pebs_ovfl_callback_t ovfl; -}; - -/* - * Debug Store (DS) save area configuration (see Intel64 and IA32 - * Architectures Software Developer's Manual, section 18.5) - * - * The DS configuration consists of the following fields; different - * architetures vary in the size of those fields. - * - * - double-word aligned base linear address of the BTS buffer - * - write pointer into the BTS buffer - * - end linear address of the BTS buffer (one byte beyond the end of - * the buffer) - * - interrupt pointer into BTS buffer - * (interrupt occurs when write pointer passes interrupt pointer) - * - double-word aligned base linear address of the PEBS buffer - * - write pointer into the PEBS buffer - * - end linear address of the PEBS buffer (one byte beyond the end of - * the buffer) - * - interrupt pointer into PEBS buffer - * (interrupt occurs when write pointer passes interrupt pointer) - * - value to which counter is reset following counter overflow - * - * Later architectures use 64bit pointers throughout, whereas earlier - * architectures use 32bit pointers in 32bit mode. - * - * - * We compute the base address for the first 8 fields based on: - * - the field size stored in the DS configuration - * - the relative field position - * - an offset giving the start of the respective region - * - * This offset is further used to index various arrays holding - * information for BTS and PEBS at the respective index. - * - * On later 32bit processors, we only access the lower 32bit of the - * 64bit pointer fields. The upper halves will be zeroed out. - */ - -enum ds_field { - ds_buffer_base = 0, - ds_index, - ds_absolute_maximum, - ds_interrupt_threshold, -}; - -enum ds_qualifier { - ds_bts = 0, - ds_pebs -}; - -static inline unsigned long -ds_get(const unsigned char *base, enum ds_qualifier qual, enum ds_field field) -{ - base += (ds_cfg.sizeof_ptr_field * (field + (4 * qual))); - return *(unsigned long *)base; -} - -static inline void -ds_set(unsigned char *base, enum ds_qualifier qual, enum ds_field field, - unsigned long value) -{ - base += (ds_cfg.sizeof_ptr_field * (field + (4 * qual))); - (*(unsigned long *)base) = value; -} - - -/* - * Locking is done only for allocating BTS or PEBS resources. - */ -static DEFINE_SPINLOCK(ds_lock); - -/* - * We either support (system-wide) per-cpu or per-thread allocation. - * We distinguish the two based on the task_struct pointer, where a - * NULL pointer indicates per-cpu allocation for the current cpu. - * - * Allocations are use-counted. As soon as resources are allocated, - * further allocations must be of the same type (per-cpu or - * per-thread). We model this by counting allocations (i.e. the number - * of tracers of a certain type) for one type negatively: - * =0 no tracers - * >0 number of per-thread tracers - * <0 number of per-cpu tracers - * - * Tracers essentially gives the number of ds contexts for a certain - * type of allocation. - */ -static atomic_t tracers = ATOMIC_INIT(0); - -static inline int get_tracer(struct task_struct *task) -{ - int error; - - spin_lock_irq(&ds_lock); - - if (task) { - error = -EPERM; - if (atomic_read(&tracers) < 0) - goto out; - atomic_inc(&tracers); - } else { - error = -EPERM; - if (atomic_read(&tracers) > 0) - goto out; - atomic_dec(&tracers); - } - - error = 0; -out: - spin_unlock_irq(&ds_lock); - return error; -} - -static inline void put_tracer(struct task_struct *task) -{ - if (task) - atomic_dec(&tracers); - else - atomic_inc(&tracers); -} - -/* - * The DS context is either attached to a thread or to a cpu: - * - in the former case, the thread_struct contains a pointer to the - * attached context. - * - in the latter case, we use a static array of per-cpu context - * pointers. - * - * Contexts are use-counted. They are allocated on first access and - * deallocated when the last user puts the context. - */ -struct ds_context { - /* The DS configuration; goes into MSR_IA32_DS_AREA: */ - unsigned char ds[MAX_SIZEOF_DS]; - - /* The owner of the BTS and PEBS configuration, respectively: */ - struct bts_tracer *bts_master; - struct pebs_tracer *pebs_master; - - /* Use count: */ - unsigned long count; - - /* Pointer to the context pointer field: */ - struct ds_context **this; - - /* The traced task; NULL for cpu tracing: */ - struct task_struct *task; - - /* The traced cpu; only valid if task is NULL: */ - int cpu; -}; - -static DEFINE_PER_CPU(struct ds_context *, cpu_ds_context); - - -static struct ds_context *ds_get_context(struct task_struct *task, int cpu) -{ - struct ds_context **p_context = - (task ? &task->thread.ds_ctx : &per_cpu(cpu_ds_context, cpu)); - struct ds_context *context = NULL; - struct ds_context *new_context = NULL; - - /* Chances are small that we already have a context. */ - new_context = kzalloc(sizeof(*new_context), GFP_KERNEL); - if (!new_context) - return NULL; - - spin_lock_irq(&ds_lock); - - context = *p_context; - if (likely(!context)) { - context = new_context; - - context->this = p_context; - context->task = task; - context->cpu = cpu; - context->count = 0; - - *p_context = context; - } - - context->count++; - - spin_unlock_irq(&ds_lock); - - if (context != new_context) - kfree(new_context); - - return context; -} - -static void ds_put_context(struct ds_context *context) -{ - struct task_struct *task; - unsigned long irq; - - if (!context) - return; - - spin_lock_irqsave(&ds_lock, irq); - - if (--context->count) { - spin_unlock_irqrestore(&ds_lock, irq); - return; - } - - *(context->this) = NULL; - - task = context->task; - - if (task) - clear_tsk_thread_flag(task, TIF_DS_AREA_MSR); - - /* - * We leave the (now dangling) pointer to the DS configuration in - * the DS_AREA msr. This is as good or as bad as replacing it with - * NULL - the hardware would crash if we enabled tracing. - * - * This saves us some problems with having to write an msr on a - * different cpu while preventing others from doing the same for the - * next context for that same cpu. - */ - - spin_unlock_irqrestore(&ds_lock, irq); - - /* The context might still be in use for context switching. */ - if (task && (task != current)) - wait_task_context_switch(task); - - kfree(context); -} - -static void ds_install_ds_area(struct ds_context *context) -{ - unsigned long ds; - - ds = (unsigned long)context->ds; - - /* - * There is a race between the bts master and the pebs master. - * - * The thread/cpu access is synchronized via get/put_cpu() for - * task tracing and via wrmsr_on_cpu for cpu tracing. - * - * If bts and pebs are collected for the same task or same cpu, - * the same confiuration is written twice. - */ - if (context->task) { - get_cpu(); - if (context->task == current) - wrmsrl(MSR_IA32_DS_AREA, ds); - set_tsk_thread_flag(context->task, TIF_DS_AREA_MSR); - put_cpu(); - } else - wrmsr_on_cpu(context->cpu, MSR_IA32_DS_AREA, - (u32)((u64)ds), (u32)((u64)ds >> 32)); -} - -/* - * Call the tracer's callback on a buffer overflow. - * - * context: the ds context - * qual: the buffer type - */ -static void ds_overflow(struct ds_context *context, enum ds_qualifier qual) -{ - switch (qual) { - case ds_bts: - if (context->bts_master && - context->bts_master->ovfl) - context->bts_master->ovfl(context->bts_master); - break; - case ds_pebs: - if (context->pebs_master && - context->pebs_master->ovfl) - context->pebs_master->ovfl(context->pebs_master); - break; - } -} - - -/* - * Write raw data into the BTS or PEBS buffer. - * - * The remainder of any partially written record is zeroed out. - * - * context: the DS context - * qual: the buffer type - * record: the data to write - * size: the size of the data - */ -static int ds_write(struct ds_context *context, enum ds_qualifier qual, - const void *record, size_t size) -{ - int bytes_written = 0; - - if (!record) - return -EINVAL; - - while (size) { - unsigned long base, index, end, write_end, int_th; - unsigned long write_size, adj_write_size; - - /* - * Write as much as possible without producing an - * overflow interrupt. - * - * Interrupt_threshold must either be - * - bigger than absolute_maximum or - * - point to a record between buffer_base and absolute_maximum - * - * Index points to a valid record. - */ - base = ds_get(context->ds, qual, ds_buffer_base); - index = ds_get(context->ds, qual, ds_index); - end = ds_get(context->ds, qual, ds_absolute_maximum); - int_th = ds_get(context->ds, qual, ds_interrupt_threshold); - - write_end = min(end, int_th); - - /* - * If we are already beyond the interrupt threshold, - * we fill the entire buffer. - */ - if (write_end <= index) - write_end = end; - - if (write_end <= index) - break; - - write_size = min((unsigned long) size, write_end - index); - memcpy((void *)index, record, write_size); - - record = (const char *)record + write_size; - size -= write_size; - bytes_written += write_size; - - adj_write_size = write_size / ds_cfg.sizeof_rec[qual]; - adj_write_size *= ds_cfg.sizeof_rec[qual]; - - /* Zero out trailing bytes. */ - memset((char *)index + write_size, 0, - adj_write_size - write_size); - index += adj_write_size; - - if (index >= end) - index = base; - ds_set(context->ds, qual, ds_index, index); - - if (index >= int_th) - ds_overflow(context, qual); - } - - return bytes_written; -} - - -/* - * Branch Trace Store (BTS) uses the following format. Different - * architectures vary in the size of those fields. - * - source linear address - * - destination linear address - * - flags - * - * Later architectures use 64bit pointers throughout, whereas earlier - * architectures use 32bit pointers in 32bit mode. - * - * We compute the base address for the fields based on: - * - the field size stored in the DS configuration - * - the relative field position - * - * In order to store additional information in the BTS buffer, we use - * a special source address to indicate that the record requires - * special interpretation. - * - * Netburst indicated via a bit in the flags field whether the branch - * was predicted; this is ignored. - * - * We use two levels of abstraction: - * - the raw data level defined here - * - an arch-independent level defined in ds.h - */ - -enum bts_field { - bts_from, - bts_to, - bts_flags, - - bts_qual = bts_from, - bts_clock = bts_to, - bts_pid = bts_flags, - - bts_qual_mask = (bts_qual_max - 1), - bts_escape = ((unsigned long)-1 & ~bts_qual_mask) -}; - -static inline unsigned long bts_get(const char *base, unsigned long field) -{ - base += (ds_cfg.sizeof_ptr_field * field); - return *(unsigned long *)base; -} - -static inline void bts_set(char *base, unsigned long field, unsigned long val) -{ - base += (ds_cfg.sizeof_ptr_field * field); - (*(unsigned long *)base) = val; -} - - -/* - * The raw BTS data is architecture dependent. - * - * For higher-level users, we give an arch-independent view. - * - ds.h defines struct bts_struct - * - bts_read translates one raw bts record into a bts_struct - * - bts_write translates one bts_struct into the raw format and - * writes it into the top of the parameter tracer's buffer. - * - * return: bytes read/written on success; -Eerrno, otherwise - */ -static int -bts_read(struct bts_tracer *tracer, const void *at, struct bts_struct *out) -{ - if (!tracer) - return -EINVAL; - - if (at < tracer->trace.ds.begin) - return -EINVAL; - - if (tracer->trace.ds.end < (at + tracer->trace.ds.size)) - return -EINVAL; - - memset(out, 0, sizeof(*out)); - if ((bts_get(at, bts_qual) & ~bts_qual_mask) == bts_escape) { - out->qualifier = (bts_get(at, bts_qual) & bts_qual_mask); - out->variant.event.clock = bts_get(at, bts_clock); - out->variant.event.pid = bts_get(at, bts_pid); - } else { - out->qualifier = bts_branch; - out->variant.lbr.from = bts_get(at, bts_from); - out->variant.lbr.to = bts_get(at, bts_to); - - if (!out->variant.lbr.from && !out->variant.lbr.to) - out->qualifier = bts_invalid; - } - - return ds_cfg.sizeof_rec[ds_bts]; -} - -static int bts_write(struct bts_tracer *tracer, const struct bts_struct *in) -{ - unsigned char raw[MAX_SIZEOF_BTS]; - - if (!tracer) - return -EINVAL; - - if (MAX_SIZEOF_BTS < ds_cfg.sizeof_rec[ds_bts]) - return -EOVERFLOW; - - switch (in->qualifier) { - case bts_invalid: - bts_set(raw, bts_from, 0); - bts_set(raw, bts_to, 0); - bts_set(raw, bts_flags, 0); - break; - case bts_branch: - bts_set(raw, bts_from, in->variant.lbr.from); - bts_set(raw, bts_to, in->variant.lbr.to); - bts_set(raw, bts_flags, 0); - break; - case bts_task_arrives: - case bts_task_departs: - bts_set(raw, bts_qual, (bts_escape | in->qualifier)); - bts_set(raw, bts_clock, in->variant.event.clock); - bts_set(raw, bts_pid, in->variant.event.pid); - break; - default: - return -EINVAL; - } - - return ds_write(tracer->ds.context, ds_bts, raw, - ds_cfg.sizeof_rec[ds_bts]); -} - - -static void ds_write_config(struct ds_context *context, - struct ds_trace *cfg, enum ds_qualifier qual) -{ - unsigned char *ds = context->ds; - - ds_set(ds, qual, ds_buffer_base, (unsigned long)cfg->begin); - ds_set(ds, qual, ds_index, (unsigned long)cfg->top); - ds_set(ds, qual, ds_absolute_maximum, (unsigned long)cfg->end); - ds_set(ds, qual, ds_interrupt_threshold, (unsigned long)cfg->ith); -} - -static void ds_read_config(struct ds_context *context, - struct ds_trace *cfg, enum ds_qualifier qual) -{ - unsigned char *ds = context->ds; - - cfg->begin = (void *)ds_get(ds, qual, ds_buffer_base); - cfg->top = (void *)ds_get(ds, qual, ds_index); - cfg->end = (void *)ds_get(ds, qual, ds_absolute_maximum); - cfg->ith = (void *)ds_get(ds, qual, ds_interrupt_threshold); -} - -static void ds_init_ds_trace(struct ds_trace *trace, enum ds_qualifier qual, - void *base, size_t size, size_t ith, - unsigned int flags) { - unsigned long buffer, adj; - - /* - * Adjust the buffer address and size to meet alignment - * constraints: - * - buffer is double-word aligned - * - size is multiple of record size - * - * We checked the size at the very beginning; we have enough - * space to do the adjustment. - */ - buffer = (unsigned long)base; - - adj = ALIGN(buffer, DS_ALIGNMENT) - buffer; - buffer += adj; - size -= adj; - - trace->n = size / ds_cfg.sizeof_rec[qual]; - trace->size = ds_cfg.sizeof_rec[qual]; - - size = (trace->n * trace->size); - - trace->begin = (void *)buffer; - trace->top = trace->begin; - trace->end = (void *)(buffer + size); - /* - * The value for 'no threshold' is -1, which will set the - * threshold outside of the buffer, just like we want it. - */ - ith *= ds_cfg.sizeof_rec[qual]; - trace->ith = (void *)(buffer + size - ith); - - trace->flags = flags; -} - - -static int ds_request(struct ds_tracer *tracer, struct ds_trace *trace, - enum ds_qualifier qual, struct task_struct *task, - int cpu, void *base, size_t size, size_t th) -{ - struct ds_context *context; - int error; - size_t req_size; - - error = -EOPNOTSUPP; - if (!ds_cfg.sizeof_rec[qual]) - goto out; - - error = -EINVAL; - if (!base) - goto out; - - req_size = ds_cfg.sizeof_rec[qual]; - /* We might need space for alignment adjustments. */ - if (!IS_ALIGNED((unsigned long)base, DS_ALIGNMENT)) - req_size += DS_ALIGNMENT; - - error = -EINVAL; - if (size < req_size) - goto out; - - if (th != (size_t)-1) { - th *= ds_cfg.sizeof_rec[qual]; - - error = -EINVAL; - if (size <= th) - goto out; - } - - tracer->buffer = base; - tracer->size = size; - - error = -ENOMEM; - context = ds_get_context(task, cpu); - if (!context) - goto out; - tracer->context = context; - - /* - * Defer any tracer-specific initialization work for the context until - * context ownership has been clarified. - */ - - error = 0; - out: - return error; -} - -static struct bts_tracer *ds_request_bts(struct task_struct *task, int cpu, - void *base, size_t size, - bts_ovfl_callback_t ovfl, size_t th, - unsigned int flags) -{ - struct bts_tracer *tracer; - int error; - - /* Buffer overflow notification is not yet implemented. */ - error = -EOPNOTSUPP; - if (ovfl) - goto out; - - error = get_tracer(task); - if (error < 0) - goto out; - - error = -ENOMEM; - tracer = kzalloc(sizeof(*tracer), GFP_KERNEL); - if (!tracer) - goto out_put_tracer; - tracer->ovfl = ovfl; - - /* Do some more error checking and acquire a tracing context. */ - error = ds_request(&tracer->ds, &tracer->trace.ds, - ds_bts, task, cpu, base, size, th); - if (error < 0) - goto out_tracer; - - /* Claim the bts part of the tracing context we acquired above. */ - spin_lock_irq(&ds_lock); - - error = -EPERM; - if (tracer->ds.context->bts_master) - goto out_unlock; - tracer->ds.context->bts_master = tracer; - - spin_unlock_irq(&ds_lock); - - /* - * Now that we own the bts part of the context, let's complete the - * initialization for that part. - */ - ds_init_ds_trace(&tracer->trace.ds, ds_bts, base, size, th, flags); - ds_write_config(tracer->ds.context, &tracer->trace.ds, ds_bts); - ds_install_ds_area(tracer->ds.context); - - tracer->trace.read = bts_read; - tracer->trace.write = bts_write; - - /* Start tracing. */ - ds_resume_bts(tracer); - - return tracer; - - out_unlock: - spin_unlock_irq(&ds_lock); - ds_put_context(tracer->ds.context); - out_tracer: - kfree(tracer); - out_put_tracer: - put_tracer(task); - out: - return ERR_PTR(error); -} - -struct bts_tracer *ds_request_bts_task(struct task_struct *task, - void *base, size_t size, - bts_ovfl_callback_t ovfl, - size_t th, unsigned int flags) -{ - return ds_request_bts(task, 0, base, size, ovfl, th, flags); -} - -struct bts_tracer *ds_request_bts_cpu(int cpu, void *base, size_t size, - bts_ovfl_callback_t ovfl, - size_t th, unsigned int flags) -{ - return ds_request_bts(NULL, cpu, base, size, ovfl, th, flags); -} - -static struct pebs_tracer *ds_request_pebs(struct task_struct *task, int cpu, - void *base, size_t size, - pebs_ovfl_callback_t ovfl, size_t th, - unsigned int flags) -{ - struct pebs_tracer *tracer; - int error; - - /* Buffer overflow notification is not yet implemented. */ - error = -EOPNOTSUPP; - if (ovfl) - goto out; - - error = get_tracer(task); - if (error < 0) - goto out; - - error = -ENOMEM; - tracer = kzalloc(sizeof(*tracer), GFP_KERNEL); - if (!tracer) - goto out_put_tracer; - tracer->ovfl = ovfl; - - /* Do some more error checking and acquire a tracing context. */ - error = ds_request(&tracer->ds, &tracer->trace.ds, - ds_pebs, task, cpu, base, size, th); - if (error < 0) - goto out_tracer; - - /* Claim the pebs part of the tracing context we acquired above. */ - spin_lock_irq(&ds_lock); - - error = -EPERM; - if (tracer->ds.context->pebs_master) - goto out_unlock; - tracer->ds.context->pebs_master = tracer; - - spin_unlock_irq(&ds_lock); - - /* - * Now that we own the pebs part of the context, let's complete the - * initialization for that part. - */ - ds_init_ds_trace(&tracer->trace.ds, ds_pebs, base, size, th, flags); - ds_write_config(tracer->ds.context, &tracer->trace.ds, ds_pebs); - ds_install_ds_area(tracer->ds.context); - - /* Start tracing. */ - ds_resume_pebs(tracer); - - return tracer; - - out_unlock: - spin_unlock_irq(&ds_lock); - ds_put_context(tracer->ds.context); - out_tracer: - kfree(tracer); - out_put_tracer: - put_tracer(task); - out: - return ERR_PTR(error); -} - -struct pebs_tracer *ds_request_pebs_task(struct task_struct *task, - void *base, size_t size, - pebs_ovfl_callback_t ovfl, - size_t th, unsigned int flags) -{ - return ds_request_pebs(task, 0, base, size, ovfl, th, flags); -} - -struct pebs_tracer *ds_request_pebs_cpu(int cpu, void *base, size_t size, - pebs_ovfl_callback_t ovfl, - size_t th, unsigned int flags) -{ - return ds_request_pebs(NULL, cpu, base, size, ovfl, th, flags); -} - -static void ds_free_bts(struct bts_tracer *tracer) -{ - struct task_struct *task; - - task = tracer->ds.context->task; - - WARN_ON_ONCE(tracer->ds.context->bts_master != tracer); - tracer->ds.context->bts_master = NULL; - - /* Make sure tracing stopped and the tracer is not in use. */ - if (task && (task != current)) - wait_task_context_switch(task); - - ds_put_context(tracer->ds.context); - put_tracer(task); - - kfree(tracer); -} - -void ds_release_bts(struct bts_tracer *tracer) -{ - might_sleep(); - - if (!tracer) - return; - - ds_suspend_bts(tracer); - ds_free_bts(tracer); -} - -int ds_release_bts_noirq(struct bts_tracer *tracer) -{ - struct task_struct *task; - unsigned long irq; - int error; - - if (!tracer) - return 0; - - task = tracer->ds.context->task; - - local_irq_save(irq); - - error = -EPERM; - if (!task && - (tracer->ds.context->cpu != smp_processor_id())) - goto out; - - error = -EPERM; - if (task && (task != current)) - goto out; - - ds_suspend_bts_noirq(tracer); - ds_free_bts(tracer); - - error = 0; - out: - local_irq_restore(irq); - return error; -} - -static void update_task_debugctlmsr(struct task_struct *task, - unsigned long debugctlmsr) -{ - task->thread.debugctlmsr = debugctlmsr; - - get_cpu(); - if (task == current) - update_debugctlmsr(debugctlmsr); - put_cpu(); -} - -void ds_suspend_bts(struct bts_tracer *tracer) -{ - struct task_struct *task; - unsigned long debugctlmsr; - int cpu; - - if (!tracer) - return; - - tracer->flags = 0; - - task = tracer->ds.context->task; - cpu = tracer->ds.context->cpu; - - WARN_ON(!task && irqs_disabled()); - - debugctlmsr = (task ? - task->thread.debugctlmsr : - get_debugctlmsr_on_cpu(cpu)); - debugctlmsr &= ~BTS_CONTROL; - - if (task) - update_task_debugctlmsr(task, debugctlmsr); - else - update_debugctlmsr_on_cpu(cpu, debugctlmsr); -} - -int ds_suspend_bts_noirq(struct bts_tracer *tracer) -{ - struct task_struct *task; - unsigned long debugctlmsr, irq; - int cpu, error = 0; - - if (!tracer) - return 0; - - tracer->flags = 0; - - task = tracer->ds.context->task; - cpu = tracer->ds.context->cpu; - - local_irq_save(irq); - - error = -EPERM; - if (!task && (cpu != smp_processor_id())) - goto out; - - debugctlmsr = (task ? - task->thread.debugctlmsr : - get_debugctlmsr()); - debugctlmsr &= ~BTS_CONTROL; - - if (task) - update_task_debugctlmsr(task, debugctlmsr); - else - update_debugctlmsr(debugctlmsr); - - error = 0; - out: - local_irq_restore(irq); - return error; -} - -static unsigned long ds_bts_control(struct bts_tracer *tracer) -{ - unsigned long control; - - control = ds_cfg.ctl[dsf_bts]; - if (!(tracer->trace.ds.flags & BTS_KERNEL)) - control |= ds_cfg.ctl[dsf_bts_kernel]; - if (!(tracer->trace.ds.flags & BTS_USER)) - control |= ds_cfg.ctl[dsf_bts_user]; - - return control; -} - -void ds_resume_bts(struct bts_tracer *tracer) -{ - struct task_struct *task; - unsigned long debugctlmsr; - int cpu; - - if (!tracer) - return; - - tracer->flags = tracer->trace.ds.flags; - - task = tracer->ds.context->task; - cpu = tracer->ds.context->cpu; - - WARN_ON(!task && irqs_disabled()); - - debugctlmsr = (task ? - task->thread.debugctlmsr : - get_debugctlmsr_on_cpu(cpu)); - debugctlmsr |= ds_bts_control(tracer); - - if (task) - update_task_debugctlmsr(task, debugctlmsr); - else - update_debugctlmsr_on_cpu(cpu, debugctlmsr); -} - -int ds_resume_bts_noirq(struct bts_tracer *tracer) -{ - struct task_struct *task; - unsigned long debugctlmsr, irq; - int cpu, error = 0; - - if (!tracer) - return 0; - - tracer->flags = tracer->trace.ds.flags; - - task = tracer->ds.context->task; - cpu = tracer->ds.context->cpu; - - local_irq_save(irq); - - error = -EPERM; - if (!task && (cpu != smp_processor_id())) - goto out; - - debugctlmsr = (task ? - task->thread.debugctlmsr : - get_debugctlmsr()); - debugctlmsr |= ds_bts_control(tracer); - - if (task) - update_task_debugctlmsr(task, debugctlmsr); - else - update_debugctlmsr(debugctlmsr); - - error = 0; - out: - local_irq_restore(irq); - return error; -} - -static void ds_free_pebs(struct pebs_tracer *tracer) -{ - struct task_struct *task; - - task = tracer->ds.context->task; - - WARN_ON_ONCE(tracer->ds.context->pebs_master != tracer); - tracer->ds.context->pebs_master = NULL; - - ds_put_context(tracer->ds.context); - put_tracer(task); - - kfree(tracer); -} - -void ds_release_pebs(struct pebs_tracer *tracer) -{ - might_sleep(); - - if (!tracer) - return; - - ds_suspend_pebs(tracer); - ds_free_pebs(tracer); -} - -int ds_release_pebs_noirq(struct pebs_tracer *tracer) -{ - struct task_struct *task; - unsigned long irq; - int error; - - if (!tracer) - return 0; - - task = tracer->ds.context->task; - - local_irq_save(irq); - - error = -EPERM; - if (!task && - (tracer->ds.context->cpu != smp_processor_id())) - goto out; - - error = -EPERM; - if (task && (task != current)) - goto out; - - ds_suspend_pebs_noirq(tracer); - ds_free_pebs(tracer); - - error = 0; - out: - local_irq_restore(irq); - return error; -} - -void ds_suspend_pebs(struct pebs_tracer *tracer) -{ - -} - -int ds_suspend_pebs_noirq(struct pebs_tracer *tracer) -{ - return 0; -} - -void ds_resume_pebs(struct pebs_tracer *tracer) -{ - -} - -int ds_resume_pebs_noirq(struct pebs_tracer *tracer) -{ - return 0; -} - -const struct bts_trace *ds_read_bts(struct bts_tracer *tracer) -{ - if (!tracer) - return NULL; - - ds_read_config(tracer->ds.context, &tracer->trace.ds, ds_bts); - return &tracer->trace; -} - -const struct pebs_trace *ds_read_pebs(struct pebs_tracer *tracer) -{ - if (!tracer) - return NULL; - - ds_read_config(tracer->ds.context, &tracer->trace.ds, ds_pebs); - - tracer->trace.counters = ds_cfg.nr_counter_reset; - memcpy(tracer->trace.counter_reset, - tracer->ds.context->ds + - (NUM_DS_PTR_FIELDS * ds_cfg.sizeof_ptr_field), - ds_cfg.nr_counter_reset * PEBS_RESET_FIELD_SIZE); - - return &tracer->trace; -} - -int ds_reset_bts(struct bts_tracer *tracer) -{ - if (!tracer) - return -EINVAL; - - tracer->trace.ds.top = tracer->trace.ds.begin; - - ds_set(tracer->ds.context->ds, ds_bts, ds_index, - (unsigned long)tracer->trace.ds.top); - - return 0; -} - -int ds_reset_pebs(struct pebs_tracer *tracer) -{ - if (!tracer) - return -EINVAL; - - tracer->trace.ds.top = tracer->trace.ds.begin; - - ds_set(tracer->ds.context->ds, ds_pebs, ds_index, - (unsigned long)tracer->trace.ds.top); - - return 0; -} - -int ds_set_pebs_reset(struct pebs_tracer *tracer, - unsigned int counter, u64 value) -{ - if (!tracer) - return -EINVAL; - - if (ds_cfg.nr_counter_reset < counter) - return -EINVAL; - - *(u64 *)(tracer->ds.context->ds + - (NUM_DS_PTR_FIELDS * ds_cfg.sizeof_ptr_field) + - (counter * PEBS_RESET_FIELD_SIZE)) = value; - - return 0; -} - -static const struct ds_configuration ds_cfg_netburst = { - .name = "Netburst", - .ctl[dsf_bts] = (1 << 2) | (1 << 3), - .ctl[dsf_bts_kernel] = (1 << 5), - .ctl[dsf_bts_user] = (1 << 6), - .nr_counter_reset = 1, -}; -static const struct ds_configuration ds_cfg_pentium_m = { - .name = "Pentium M", - .ctl[dsf_bts] = (1 << 6) | (1 << 7), - .nr_counter_reset = 1, -}; -static const struct ds_configuration ds_cfg_core2_atom = { - .name = "Core 2/Atom", - .ctl[dsf_bts] = (1 << 6) | (1 << 7), - .ctl[dsf_bts_kernel] = (1 << 9), - .ctl[dsf_bts_user] = (1 << 10), - .nr_counter_reset = 1, -}; -static const struct ds_configuration ds_cfg_core_i7 = { - .name = "Core i7", - .ctl[dsf_bts] = (1 << 6) | (1 << 7), - .ctl[dsf_bts_kernel] = (1 << 9), - .ctl[dsf_bts_user] = (1 << 10), - .nr_counter_reset = 4, -}; - -static void -ds_configure(const struct ds_configuration *cfg, - struct cpuinfo_x86 *cpu) -{ - unsigned long nr_pebs_fields = 0; - - printk(KERN_INFO "[ds] using %s configuration\n", cfg->name); - -#ifdef __i386__ - nr_pebs_fields = 10; -#else - nr_pebs_fields = 18; -#endif - - /* - * Starting with version 2, architectural performance - * monitoring supports a format specifier. - */ - if ((cpuid_eax(0xa) & 0xff) > 1) { - unsigned long perf_capabilities, format; - - rdmsrl(MSR_IA32_PERF_CAPABILITIES, perf_capabilities); - - format = (perf_capabilities >> 8) & 0xf; - - switch (format) { - case 0: - nr_pebs_fields = 18; - break; - case 1: - nr_pebs_fields = 22; - break; - default: - printk(KERN_INFO - "[ds] unknown PEBS format: %lu\n", format); - nr_pebs_fields = 0; - break; - } - } - - memset(&ds_cfg, 0, sizeof(ds_cfg)); - ds_cfg = *cfg; - - ds_cfg.sizeof_ptr_field = - (cpu_has(cpu, X86_FEATURE_DTES64) ? 8 : 4); - - ds_cfg.sizeof_rec[ds_bts] = ds_cfg.sizeof_ptr_field * 3; - ds_cfg.sizeof_rec[ds_pebs] = ds_cfg.sizeof_ptr_field * nr_pebs_fields; - - if (!cpu_has(cpu, X86_FEATURE_BTS)) { - ds_cfg.sizeof_rec[ds_bts] = 0; - printk(KERN_INFO "[ds] bts not available\n"); - } - if (!cpu_has(cpu, X86_FEATURE_PEBS)) { - ds_cfg.sizeof_rec[ds_pebs] = 0; - printk(KERN_INFO "[ds] pebs not available\n"); - } - - printk(KERN_INFO "[ds] sizes: address: %u bit, ", - 8 * ds_cfg.sizeof_ptr_field); - printk("bts/pebs record: %u/%u bytes\n", - ds_cfg.sizeof_rec[ds_bts], ds_cfg.sizeof_rec[ds_pebs]); - - WARN_ON_ONCE(MAX_PEBS_COUNTERS < ds_cfg.nr_counter_reset); -} - -void __cpuinit ds_init_intel(struct cpuinfo_x86 *c) -{ - /* Only configure the first cpu. Others are identical. */ - if (ds_cfg.name) - return; - - switch (c->x86) { - case 0x6: - switch (c->x86_model) { - case 0x9: - case 0xd: /* Pentium M */ - ds_configure(&ds_cfg_pentium_m, c); - break; - case 0xf: - case 0x17: /* Core2 */ - case 0x1c: /* Atom */ - ds_configure(&ds_cfg_core2_atom, c); - break; - case 0x1a: /* Core i7 */ - ds_configure(&ds_cfg_core_i7, c); - break; - default: - /* Sorry, don't know about them. */ - break; - } - break; - case 0xf: - switch (c->x86_model) { - case 0x0: - case 0x1: - case 0x2: /* Netburst */ - ds_configure(&ds_cfg_netburst, c); - break; - default: - /* Sorry, don't know about them. */ - break; - } - break; - default: - /* Sorry, don't know about them. */ - break; - } -} - -static inline void ds_take_timestamp(struct ds_context *context, - enum bts_qualifier qualifier, - struct task_struct *task) -{ - struct bts_tracer *tracer = context->bts_master; - struct bts_struct ts; - - /* Prevent compilers from reading the tracer pointer twice. */ - barrier(); - - if (!tracer || !(tracer->flags & BTS_TIMESTAMPS)) - return; - - memset(&ts, 0, sizeof(ts)); - ts.qualifier = qualifier; - ts.variant.event.clock = trace_clock_global(); - ts.variant.event.pid = task->pid; - - bts_write(tracer, &ts); -} - -/* - * Change the DS configuration from tracing prev to tracing next. - */ -void ds_switch_to(struct task_struct *prev, struct task_struct *next) -{ - struct ds_context *prev_ctx = prev->thread.ds_ctx; - struct ds_context *next_ctx = next->thread.ds_ctx; - unsigned long debugctlmsr = next->thread.debugctlmsr; - - /* Make sure all data is read before we start. */ - barrier(); - - if (prev_ctx) { - update_debugctlmsr(0); - - ds_take_timestamp(prev_ctx, bts_task_departs, prev); - } - - if (next_ctx) { - ds_take_timestamp(next_ctx, bts_task_arrives, next); - - wrmsrl(MSR_IA32_DS_AREA, (unsigned long)next_ctx->ds); - } - - update_debugctlmsr(debugctlmsr); -} - -static __init int ds_selftest(void) -{ - if (ds_cfg.sizeof_rec[ds_bts]) { - int error; - - error = ds_selftest_bts(); - if (error) { - WARN(1, "[ds] selftest failed. disabling bts.\n"); - ds_cfg.sizeof_rec[ds_bts] = 0; - } - } - - if (ds_cfg.sizeof_rec[ds_pebs]) { - int error; - - error = ds_selftest_pebs(); - if (error) { - WARN(1, "[ds] selftest failed. disabling pebs.\n"); - ds_cfg.sizeof_rec[ds_pebs] = 0; - } - } - - return 0; -} -device_initcall(ds_selftest); diff --git a/arch/x86/kernel/ds_selftest.c b/arch/x86/kernel/ds_selftest.c deleted file mode 100644 index 6bc7c19..0000000 --- a/arch/x86/kernel/ds_selftest.c +++ /dev/null @@ -1,408 +0,0 @@ -/* - * Debug Store support - selftest - * - * - * Copyright (C) 2009 Intel Corporation. - * Markus Metzger , 2009 - */ - -#include "ds_selftest.h" - -#include -#include -#include -#include - -#include - - -#define BUFFER_SIZE 521 /* Intentionally chose an odd size. */ -#define SMALL_BUFFER_SIZE 24 /* A single bts entry. */ - -struct ds_selftest_bts_conf { - struct bts_tracer *tracer; - int error; - int (*suspend)(struct bts_tracer *); - int (*resume)(struct bts_tracer *); -}; - -static int ds_selftest_bts_consistency(const struct bts_trace *trace) -{ - int error = 0; - - if (!trace) { - printk(KERN_CONT "failed to access trace..."); - /* Bail out. Other tests are pointless. */ - return -1; - } - - if (!trace->read) { - printk(KERN_CONT "bts read not available..."); - error = -1; - } - - /* Do some sanity checks on the trace configuration. */ - if (!trace->ds.n) { - printk(KERN_CONT "empty bts buffer..."); - error = -1; - } - if (!trace->ds.size) { - printk(KERN_CONT "bad bts trace setup..."); - error = -1; - } - if (trace->ds.end != - (char *)trace->ds.begin + (trace->ds.n * trace->ds.size)) { - printk(KERN_CONT "bad bts buffer setup..."); - error = -1; - } - /* - * We allow top in [begin; end], since its not clear when the - * overflow adjustment happens: after the increment or before the - * write. - */ - if ((trace->ds.top < trace->ds.begin) || - (trace->ds.end < trace->ds.top)) { - printk(KERN_CONT "bts top out of bounds..."); - error = -1; - } - - return error; -} - -static int ds_selftest_bts_read(struct bts_tracer *tracer, - const struct bts_trace *trace, - const void *from, const void *to) -{ - const unsigned char *at; - - /* - * Check a few things which do not belong to this test. - * They should be covered by other tests. - */ - if (!trace) - return -1; - - if (!trace->read) - return -1; - - if (to < from) - return -1; - - if (from < trace->ds.begin) - return -1; - - if (trace->ds.end < to) - return -1; - - if (!trace->ds.size) - return -1; - - /* Now to the test itself. */ - for (at = from; (void *)at < to; at += trace->ds.size) { - struct bts_struct bts; - unsigned long index; - int error; - - if (((void *)at - trace->ds.begin) % trace->ds.size) { - printk(KERN_CONT - "read from non-integer index..."); - return -1; - } - index = ((void *)at - trace->ds.begin) / trace->ds.size; - - memset(&bts, 0, sizeof(bts)); - error = trace->read(tracer, at, &bts); - if (error < 0) { - printk(KERN_CONT - "error reading bts trace at [%lu] (0x%p)...", - index, at); - return error; - } - - switch (bts.qualifier) { - case BTS_BRANCH: - break; - default: - printk(KERN_CONT - "unexpected bts entry %llu at [%lu] (0x%p)...", - bts.qualifier, index, at); - return -1; - } - } - - return 0; -} - -static void ds_selftest_bts_cpu(void *arg) -{ - struct ds_selftest_bts_conf *conf = arg; - const struct bts_trace *trace; - void *top; - - if (IS_ERR(conf->tracer)) { - conf->error = PTR_ERR(conf->tracer); - conf->tracer = NULL; - - printk(KERN_CONT - "initialization failed (err: %d)...", conf->error); - return; - } - - /* We should meanwhile have enough trace. */ - conf->error = conf->suspend(conf->tracer); - if (conf->error < 0) - return; - - /* Let's see if we can access the trace. */ - trace = ds_read_bts(conf->tracer); - - conf->error = ds_selftest_bts_consistency(trace); - if (conf->error < 0) - return; - - /* If everything went well, we should have a few trace entries. */ - if (trace->ds.top == trace->ds.begin) { - /* - * It is possible but highly unlikely that we got a - * buffer overflow and end up at exactly the same - * position we started from. - * Let's issue a warning, but continue. - */ - printk(KERN_CONT "no trace/overflow..."); - } - - /* Let's try to read the trace we collected. */ - conf->error = - ds_selftest_bts_read(conf->tracer, trace, - trace->ds.begin, trace->ds.top); - if (conf->error < 0) - return; - - /* - * Let's read the trace again. - * Since we suspended tracing, we should get the same result. - */ - top = trace->ds.top; - - trace = ds_read_bts(conf->tracer); - conf->error = ds_selftest_bts_consistency(trace); - if (conf->error < 0) - return; - - if (top != trace->ds.top) { - printk(KERN_CONT "suspend not working..."); - conf->error = -1; - return; - } - - /* Let's collect some more trace - see if resume is working. */ - conf->error = conf->resume(conf->tracer); - if (conf->error < 0) - return; - - conf->error = conf->suspend(conf->tracer); - if (conf->error < 0) - return; - - trace = ds_read_bts(conf->tracer); - - conf->error = ds_selftest_bts_consistency(trace); - if (conf->error < 0) - return; - - if (trace->ds.top == top) { - /* - * It is possible but highly unlikely that we got a - * buffer overflow and end up at exactly the same - * position we started from. - * Let's issue a warning and check the full trace. - */ - printk(KERN_CONT - "no resume progress/overflow..."); - - conf->error = - ds_selftest_bts_read(conf->tracer, trace, - trace->ds.begin, trace->ds.end); - } else if (trace->ds.top < top) { - /* - * We had a buffer overflow - the entire buffer should - * contain trace records. - */ - conf->error = - ds_selftest_bts_read(conf->tracer, trace, - trace->ds.begin, trace->ds.end); - } else { - /* - * It is quite likely that the buffer did not overflow. - * Let's just check the delta trace. - */ - conf->error = - ds_selftest_bts_read(conf->tracer, trace, top, - trace->ds.top); - } - if (conf->error < 0) - return; - - conf->error = 0; -} - -static int ds_suspend_bts_wrap(struct bts_tracer *tracer) -{ - ds_suspend_bts(tracer); - return 0; -} - -static int ds_resume_bts_wrap(struct bts_tracer *tracer) -{ - ds_resume_bts(tracer); - return 0; -} - -static void ds_release_bts_noirq_wrap(void *tracer) -{ - (void)ds_release_bts_noirq(tracer); -} - -static int ds_selftest_bts_bad_release_noirq(int cpu, - struct bts_tracer *tracer) -{ - int error = -EPERM; - - /* Try to release the tracer on the wrong cpu. */ - get_cpu(); - if (cpu != smp_processor_id()) { - error = ds_release_bts_noirq(tracer); - if (error != -EPERM) - printk(KERN_CONT "release on wrong cpu..."); - } - put_cpu(); - - return error ? 0 : -1; -} - -static int ds_selftest_bts_bad_request_cpu(int cpu, void *buffer) -{ - struct bts_tracer *tracer; - int error; - - /* Try to request cpu tracing while task tracing is active. */ - tracer = ds_request_bts_cpu(cpu, buffer, BUFFER_SIZE, NULL, - (size_t)-1, BTS_KERNEL); - error = PTR_ERR(tracer); - if (!IS_ERR(tracer)) { - ds_release_bts(tracer); - error = 0; - } - - if (error != -EPERM) - printk(KERN_CONT "cpu/task tracing overlap..."); - - return error ? 0 : -1; -} - -static int ds_selftest_bts_bad_request_task(void *buffer) -{ - struct bts_tracer *tracer; - int error; - - /* Try to request cpu tracing while task tracing is active. */ - tracer = ds_request_bts_task(current, buffer, BUFFER_SIZE, NULL, - (size_t)-1, BTS_KERNEL); - error = PTR_ERR(tracer); - if (!IS_ERR(tracer)) { - error = 0; - ds_release_bts(tracer); - } - - if (error != -EPERM) - printk(KERN_CONT "task/cpu tracing overlap..."); - - return error ? 0 : -1; -} - -int ds_selftest_bts(void) -{ - struct ds_selftest_bts_conf conf; - unsigned char buffer[BUFFER_SIZE], *small_buffer; - unsigned long irq; - int cpu; - - printk(KERN_INFO "[ds] bts selftest..."); - conf.error = 0; - - small_buffer = (unsigned char *)ALIGN((unsigned long)buffer, 8) + 8; - - get_online_cpus(); - for_each_online_cpu(cpu) { - conf.suspend = ds_suspend_bts_wrap; - conf.resume = ds_resume_bts_wrap; - conf.tracer = - ds_request_bts_cpu(cpu, buffer, BUFFER_SIZE, - NULL, (size_t)-1, BTS_KERNEL); - ds_selftest_bts_cpu(&conf); - if (conf.error >= 0) - conf.error = ds_selftest_bts_bad_request_task(buffer); - ds_release_bts(conf.tracer); - if (conf.error < 0) - goto out; - - conf.suspend = ds_suspend_bts_noirq; - conf.resume = ds_resume_bts_noirq; - conf.tracer = - ds_request_bts_cpu(cpu, buffer, BUFFER_SIZE, - NULL, (size_t)-1, BTS_KERNEL); - smp_call_function_single(cpu, ds_selftest_bts_cpu, &conf, 1); - if (conf.error >= 0) { - conf.error = - ds_selftest_bts_bad_release_noirq(cpu, - conf.tracer); - /* We must not release the tracer twice. */ - if (conf.error < 0) - conf.tracer = NULL; - } - if (conf.error >= 0) - conf.error = ds_selftest_bts_bad_request_task(buffer); - smp_call_function_single(cpu, ds_release_bts_noirq_wrap, - conf.tracer, 1); - if (conf.error < 0) - goto out; - } - - conf.suspend = ds_suspend_bts_wrap; - conf.resume = ds_resume_bts_wrap; - conf.tracer = - ds_request_bts_task(current, buffer, BUFFER_SIZE, - NULL, (size_t)-1, BTS_KERNEL); - ds_selftest_bts_cpu(&conf); - if (conf.error >= 0) - conf.error = ds_selftest_bts_bad_request_cpu(0, buffer); - ds_release_bts(conf.tracer); - if (conf.error < 0) - goto out; - - conf.suspend = ds_suspend_bts_noirq; - conf.resume = ds_resume_bts_noirq; - conf.tracer = - ds_request_bts_task(current, small_buffer, SMALL_BUFFER_SIZE, - NULL, (size_t)-1, BTS_KERNEL); - local_irq_save(irq); - ds_selftest_bts_cpu(&conf); - if (conf.error >= 0) - conf.error = ds_selftest_bts_bad_request_cpu(0, buffer); - ds_release_bts_noirq(conf.tracer); - local_irq_restore(irq); - if (conf.error < 0) - goto out; - - conf.error = 0; - out: - put_online_cpus(); - printk(KERN_CONT "%s.\n", (conf.error ? "failed" : "passed")); - - return conf.error; -} - -int ds_selftest_pebs(void) -{ - return 0; -} diff --git a/arch/x86/kernel/ds_selftest.h b/arch/x86/kernel/ds_selftest.h deleted file mode 100644 index 2ba8745..0000000 --- a/arch/x86/kernel/ds_selftest.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Debug Store support - selftest - * - * - * Copyright (C) 2009 Intel Corporation. - * Markus Metzger , 2009 - */ - -#ifdef CONFIG_X86_DS_SELFTEST -extern int ds_selftest_bts(void); -extern int ds_selftest_pebs(void); -#else -static inline int ds_selftest_bts(void) { return 0; } -static inline int ds_selftest_pebs(void) { return 0; } -#endif diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c index 6d81755..c89a386 100644 --- a/arch/x86/kernel/dumpstack.c +++ b/arch/x86/kernel/dumpstack.c @@ -224,11 +224,6 @@ unsigned __kprobes long oops_begin(void) int cpu; unsigned long flags; - /* notify the hw-branch tracer so it may disable tracing and - add the last trace to the trace buffer - - the earlier this happens, the more useful the trace. */ - trace_hw_branch_oops(); - oops_enter(); /* racy, but better than risking deadlock. */ diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c index b43bbae..7a880ad 100644 --- a/arch/x86/kernel/kprobes.c +++ b/arch/x86/kernel/kprobes.c @@ -422,14 +422,12 @@ static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs, static void __kprobes clear_btf(void) { - if (test_thread_flag(TIF_DEBUGCTLMSR)) - update_debugctlmsr(0); + /* XXX */ } static void __kprobes restore_btf(void) { - if (test_thread_flag(TIF_DEBUGCTLMSR)) - update_debugctlmsr(current->thread.debugctlmsr); + /* XXX */ } void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index ad95406..1a60beb 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -20,7 +20,6 @@ #include #include #include -#include #include unsigned long idle_halt; @@ -50,8 +49,6 @@ void free_thread_xstate(struct task_struct *tsk) kmem_cache_free(task_xstate_cachep, tsk->thread.xstate); tsk->thread.xstate = NULL; } - - WARN(tsk->thread.ds_ctx, "leaking DS context\n"); } void free_thread_info(struct thread_info *ti) @@ -198,12 +195,6 @@ void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, prev = &prev_p->thread; next = &next_p->thread; - if (test_tsk_thread_flag(next_p, TIF_DS_AREA_MSR) || - test_tsk_thread_flag(prev_p, TIF_DS_AREA_MSR)) - ds_switch_to(prev_p, next_p); - else if (next->debugctlmsr != prev->debugctlmsr) - update_debugctlmsr(next->debugctlmsr); - if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^ test_tsk_thread_flag(next_p, TIF_NOTSC)) { /* prev and next are different */ diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index f6c6266..75090c5 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -55,7 +55,6 @@ #include #include #include -#include #include asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); @@ -238,13 +237,6 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, kfree(p->thread.io_bitmap_ptr); p->thread.io_bitmap_max = 0; } - - clear_tsk_thread_flag(p, TIF_DS_AREA_MSR); - p->thread.ds_ctx = NULL; - - clear_tsk_thread_flag(p, TIF_DEBUGCTLMSR); - p->thread.debugctlmsr = 0; - return err; } diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index dc9690b..cc4258f 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -49,7 +49,6 @@ #include #include #include -#include #include asmlinkage extern void ret_from_fork(void); @@ -313,13 +312,6 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, if (err) goto out; } - - clear_tsk_thread_flag(p, TIF_DS_AREA_MSR); - p->thread.ds_ctx = NULL; - - clear_tsk_thread_flag(p, TIF_DEBUGCTLMSR); - p->thread.debugctlmsr = 0; - err = 0; out: if (err && p->thread.io_bitmap_ptr) { diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index a503b1f..f2fd3b8 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -2,9 +2,6 @@ /* * Pentium III FXSR, SSE support * Gareth Hughes , May 2000 - * - * BTS tracing - * Markus Metzger , Dec 2007 */ #include @@ -21,7 +18,6 @@ #include #include #include -#include #include #include @@ -35,7 +31,6 @@ #include #include #include -#include #include #include "tls.h" @@ -788,342 +783,6 @@ static int ioperm_get(struct task_struct *target, 0, IO_BITMAP_BYTES); } -#ifdef CONFIG_X86_PTRACE_BTS -/* - * A branch trace store context. - * - * Contexts may only be installed by ptrace_bts_config() and only for - * ptraced tasks. - * - * Contexts are destroyed when the tracee is detached from the tracer. - * The actual destruction work requires interrupts enabled, so the - * work is deferred and will be scheduled during __ptrace_unlink(). - * - * Contexts hold an additional task_struct reference on the traced - * task, as well as a reference on the tracer's mm. - * - * Ptrace already holds a task_struct for the duration of ptrace operations, - * but since destruction is deferred, it may be executed after both - * tracer and tracee exited. - */ -struct bts_context { - /* The branch trace handle. */ - struct bts_tracer *tracer; - - /* The buffer used to store the branch trace and its size. */ - void *buffer; - unsigned int size; - - /* The mm that paid for the above buffer. */ - struct mm_struct *mm; - - /* The task this context belongs to. */ - struct task_struct *task; - - /* The signal to send on a bts buffer overflow. */ - unsigned int bts_ovfl_signal; - - /* The work struct to destroy a context. */ - struct work_struct work; -}; - -static int alloc_bts_buffer(struct bts_context *context, unsigned int size) -{ - void *buffer = NULL; - int err = -ENOMEM; - - err = account_locked_memory(current->mm, current->signal->rlim, size); - if (err < 0) - return err; - - buffer = kzalloc(size, GFP_KERNEL); - if (!buffer) - goto out_refund; - - context->buffer = buffer; - context->size = size; - context->mm = get_task_mm(current); - - return 0; - - out_refund: - refund_locked_memory(current->mm, size); - return err; -} - -static inline void free_bts_buffer(struct bts_context *context) -{ - if (!context->buffer) - return; - - kfree(context->buffer); - context->buffer = NULL; - - refund_locked_memory(context->mm, context->size); - context->size = 0; - - mmput(context->mm); - context->mm = NULL; -} - -static void free_bts_context_work(struct work_struct *w) -{ - struct bts_context *context; - - context = container_of(w, struct bts_context, work); - - ds_release_bts(context->tracer); - put_task_struct(context->task); - free_bts_buffer(context); - kfree(context); -} - -static inline void free_bts_context(struct bts_context *context) -{ - INIT_WORK(&context->work, free_bts_context_work); - schedule_work(&context->work); -} - -static inline struct bts_context *alloc_bts_context(struct task_struct *task) -{ - struct bts_context *context = kzalloc(sizeof(*context), GFP_KERNEL); - if (context) { - context->task = task; - task->bts = context; - - get_task_struct(task); - } - - return context; -} - -static int ptrace_bts_read_record(struct task_struct *child, size_t index, - struct bts_struct __user *out) -{ - struct bts_context *context; - const struct bts_trace *trace; - struct bts_struct bts; - const unsigned char *at; - int error; - - context = child->bts; - if (!context) - return -ESRCH; - - trace = ds_read_bts(context->tracer); - if (!trace) - return -ESRCH; - - at = trace->ds.top - ((index + 1) * trace->ds.size); - if ((void *)at < trace->ds.begin) - at += (trace->ds.n * trace->ds.size); - - if (!trace->read) - return -EOPNOTSUPP; - - error = trace->read(context->tracer, at, &bts); - if (error < 0) - return error; - - if (copy_to_user(out, &bts, sizeof(bts))) - return -EFAULT; - - return sizeof(bts); -} - -static int ptrace_bts_drain(struct task_struct *child, - long size, - struct bts_struct __user *out) -{ - struct bts_context *context; - const struct bts_trace *trace; - const unsigned char *at; - int error, drained = 0; - - context = child->bts; - if (!context) - return -ESRCH; - - trace = ds_read_bts(context->tracer); - if (!trace) - return -ESRCH; - - if (!trace->read) - return -EOPNOTSUPP; - - if (size < (trace->ds.top - trace->ds.begin)) - return -EIO; - - for (at = trace->ds.begin; (void *)at < trace->ds.top; - out++, drained++, at += trace->ds.size) { - struct bts_struct bts; - - error = trace->read(context->tracer, at, &bts); - if (error < 0) - return error; - - if (copy_to_user(out, &bts, sizeof(bts))) - return -EFAULT; - } - - memset(trace->ds.begin, 0, trace->ds.n * trace->ds.size); - - error = ds_reset_bts(context->tracer); - if (error < 0) - return error; - - return drained; -} - -static int ptrace_bts_config(struct task_struct *child, - long cfg_size, - const struct ptrace_bts_config __user *ucfg) -{ - struct bts_context *context; - struct ptrace_bts_config cfg; - unsigned int flags = 0; - - if (cfg_size < sizeof(cfg)) - return -EIO; - - if (copy_from_user(&cfg, ucfg, sizeof(cfg))) - return -EFAULT; - - context = child->bts; - if (!context) - context = alloc_bts_context(child); - if (!context) - return -ENOMEM; - - if (cfg.flags & PTRACE_BTS_O_SIGNAL) { - if (!cfg.signal) - return -EINVAL; - - return -EOPNOTSUPP; - context->bts_ovfl_signal = cfg.signal; - } - - ds_release_bts(context->tracer); - context->tracer = NULL; - - if ((cfg.flags & PTRACE_BTS_O_ALLOC) && (cfg.size != context->size)) { - int err; - - free_bts_buffer(context); - if (!cfg.size) - return 0; - - err = alloc_bts_buffer(context, cfg.size); - if (err < 0) - return err; - } - - if (cfg.flags & PTRACE_BTS_O_TRACE) - flags |= BTS_USER; - - if (cfg.flags & PTRACE_BTS_O_SCHED) - flags |= BTS_TIMESTAMPS; - - context->tracer = - ds_request_bts_task(child, context->buffer, context->size, - NULL, (size_t)-1, flags); - if (unlikely(IS_ERR(context->tracer))) { - int error = PTR_ERR(context->tracer); - - free_bts_buffer(context); - context->tracer = NULL; - return error; - } - - return sizeof(cfg); -} - -static int ptrace_bts_status(struct task_struct *child, - long cfg_size, - struct ptrace_bts_config __user *ucfg) -{ - struct bts_context *context; - const struct bts_trace *trace; - struct ptrace_bts_config cfg; - - context = child->bts; - if (!context) - return -ESRCH; - - if (cfg_size < sizeof(cfg)) - return -EIO; - - trace = ds_read_bts(context->tracer); - if (!trace) - return -ESRCH; - - memset(&cfg, 0, sizeof(cfg)); - cfg.size = trace->ds.end - trace->ds.begin; - cfg.signal = context->bts_ovfl_signal; - cfg.bts_size = sizeof(struct bts_struct); - - if (cfg.signal) - cfg.flags |= PTRACE_BTS_O_SIGNAL; - - if (trace->ds.flags & BTS_USER) - cfg.flags |= PTRACE_BTS_O_TRACE; - - if (trace->ds.flags & BTS_TIMESTAMPS) - cfg.flags |= PTRACE_BTS_O_SCHED; - - if (copy_to_user(ucfg, &cfg, sizeof(cfg))) - return -EFAULT; - - return sizeof(cfg); -} - -static int ptrace_bts_clear(struct task_struct *child) -{ - struct bts_context *context; - const struct bts_trace *trace; - - context = child->bts; - if (!context) - return -ESRCH; - - trace = ds_read_bts(context->tracer); - if (!trace) - return -ESRCH; - - memset(trace->ds.begin, 0, trace->ds.n * trace->ds.size); - - return ds_reset_bts(context->tracer); -} - -static int ptrace_bts_size(struct task_struct *child) -{ - struct bts_context *context; - const struct bts_trace *trace; - - context = child->bts; - if (!context) - return -ESRCH; - - trace = ds_read_bts(context->tracer); - if (!trace) - return -ESRCH; - - return (trace->ds.top - trace->ds.begin) / trace->ds.size; -} - -/* - * Called from __ptrace_unlink() after the child has been moved back - * to its original parent. - */ -void ptrace_bts_untrace(struct task_struct *child) -{ - if (unlikely(child->bts)) { - free_bts_context(child->bts); - child->bts = NULL; - } -} -#endif /* CONFIG_X86_PTRACE_BTS */ - /* * Called by kernel/ptrace.c when detaching.. * @@ -1251,39 +910,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; #endif - /* - * These bits need more cooking - not enabled yet: - */ -#ifdef CONFIG_X86_PTRACE_BTS - case PTRACE_BTS_CONFIG: - ret = ptrace_bts_config - (child, data, (struct ptrace_bts_config __user *)addr); - break; - - case PTRACE_BTS_STATUS: - ret = ptrace_bts_status - (child, data, (struct ptrace_bts_config __user *)addr); - break; - - case PTRACE_BTS_SIZE: - ret = ptrace_bts_size(child); - break; - - case PTRACE_BTS_GET: - ret = ptrace_bts_read_record - (child, data, (struct bts_struct __user *) addr); - break; - - case PTRACE_BTS_CLEAR: - ret = ptrace_bts_clear(child); - break; - - case PTRACE_BTS_DRAIN: - ret = ptrace_bts_drain - (child, data, (struct bts_struct __user *) addr); - break; -#endif /* CONFIG_X86_PTRACE_BTS */ - default: ret = ptrace_request(child, request, addr, data); break; @@ -1543,14 +1169,6 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, case PTRACE_GET_THREAD_AREA: case PTRACE_SET_THREAD_AREA: -#ifdef CONFIG_X86_PTRACE_BTS - case PTRACE_BTS_CONFIG: - case PTRACE_BTS_STATUS: - case PTRACE_BTS_SIZE: - case PTRACE_BTS_GET: - case PTRACE_BTS_CLEAR: - case PTRACE_BTS_DRAIN: -#endif /* CONFIG_X86_PTRACE_BTS */ return arch_ptrace(child, request, addr, data); default: diff --git a/arch/x86/kernel/step.c b/arch/x86/kernel/step.c index 3149032..7beba07 100644 --- a/arch/x86/kernel/step.c +++ b/arch/x86/kernel/step.c @@ -158,22 +158,6 @@ static int enable_single_step(struct task_struct *child) } /* - * Install this value in MSR_IA32_DEBUGCTLMSR whenever child is running. - */ -static void write_debugctlmsr(struct task_struct *child, unsigned long val) -{ - if (child->thread.debugctlmsr == val) - return; - - child->thread.debugctlmsr = val; - - if (child != current) - return; - - update_debugctlmsr(val); -} - -/* * Enable single or block step. */ static void enable_step(struct task_struct *child, bool block) @@ -185,17 +169,9 @@ static void enable_step(struct task_struct *child, bool block) * So noone should try to use debugger block stepping in a program * that uses user-mode single stepping itself. */ - if (enable_single_step(child) && block) { - set_tsk_thread_flag(child, TIF_DEBUGCTLMSR); - write_debugctlmsr(child, - child->thread.debugctlmsr | DEBUGCTLMSR_BTF); - } else { - write_debugctlmsr(child, - child->thread.debugctlmsr & ~DEBUGCTLMSR_BTF); - - if (!child->thread.debugctlmsr) - clear_tsk_thread_flag(child, TIF_DEBUGCTLMSR); - } + if (!enable_single_step(child)) + return; + /* XXX */ } void user_enable_single_step(struct task_struct *child) @@ -213,11 +189,7 @@ void user_disable_single_step(struct task_struct *child) /* * Make sure block stepping (BTF) is disabled. */ - write_debugctlmsr(child, - child->thread.debugctlmsr & ~DEBUGCTLMSR_BTF); - - if (!child->thread.debugctlmsr) - clear_tsk_thread_flag(child, TIF_DEBUGCTLMSR); + /* XXX */ /* Always clear TIF_SINGLESTEP... */ clear_tsk_thread_flag(child, TIF_SINGLESTEP); diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 1168e44..e3da5d7 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -543,11 +543,6 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) /* DR6 may or may not be cleared by the CPU */ set_debugreg(0, 6); - /* - * The processor cleared BTF, so don't mark that we need it set. - */ - clear_tsk_thread_flag(tsk, TIF_DEBUGCTLMSR); - tsk->thread.debugctlmsr = 0; /* Store the virtualized DR6 value */ tsk->thread.debugreg6 = dr6; diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index 01e6ade..cc12b3c 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h @@ -504,18 +504,6 @@ extern int ftrace_dump_on_oops; #define INIT_TRACE_RECURSION #endif -#ifdef CONFIG_HW_BRANCH_TRACER - -void trace_hw_branch(u64 from, u64 to); -void trace_hw_branch_oops(void); - -#else /* CONFIG_HW_BRANCH_TRACER */ - -static inline void trace_hw_branch(u64 from, u64 to) {} -static inline void trace_hw_branch_oops(void) {} - -#endif /* CONFIG_HW_BRANCH_TRACER */ - #ifdef CONFIG_FTRACE_SYSCALLS unsigned long arch_syscall_addr(int nr); diff --git a/include/linux/mm.h b/include/linux/mm.h index e70f21b..c8442b6 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -19,7 +19,6 @@ struct anon_vma; struct file_ra_state; struct user_struct; struct writeback_control; -struct rlimit; #ifndef CONFIG_DISCONTIGMEM /* Don't use mapnrs, do it properly */ extern unsigned long max_mapnr; @@ -1449,9 +1448,6 @@ int vmemmap_populate_basepages(struct page *start_page, int vmemmap_populate(struct page *start_page, unsigned long pages, int node); void vmemmap_populate_print_last(void); -extern int account_locked_memory(struct mm_struct *mm, struct rlimit *rlim, - size_t size); -extern void refund_locked_memory(struct mm_struct *mm, size_t size); enum mf_flags { MF_COUNT_INCREASED = 1 << 0, diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h index e1fb607..4272521 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h @@ -345,18 +345,6 @@ static inline void user_single_step_siginfo(struct task_struct *tsk, #define arch_ptrace_stop(code, info) do { } while (0) #endif -#ifndef arch_ptrace_untrace -/* - * Do machine-specific work before untracing child. - * - * This is called for a normal detach as well as from ptrace_exit() - * when the tracing task dies. - * - * Called with write_lock(&tasklist_lock) held. - */ -#define arch_ptrace_untrace(task) do { } while (0) -#endif - extern int task_current_syscall(struct task_struct *target, long *callno, unsigned long args[6], unsigned int maxargs, unsigned long *sp, unsigned long *pc); diff --git a/include/linux/sched.h b/include/linux/sched.h index dad7f66..e0447c6 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -99,7 +99,6 @@ struct futex_pi_state; struct robust_list_head; struct bio_list; struct fs_struct; -struct bts_context; struct perf_event_context; /* @@ -1272,12 +1271,6 @@ struct task_struct { struct list_head ptraced; struct list_head ptrace_entry; - /* - * This is the tracer handle for the ptrace BTS extension. - * This field actually belongs to the ptracer task. - */ - struct bts_context *bts; - /* PID/PID hash table linkage. */ struct pid_link pids[PIDTYPE_MAX]; struct list_head thread_group; @@ -2123,10 +2116,8 @@ extern void set_task_comm(struct task_struct *tsk, char *from); extern char *get_task_comm(char *to, struct task_struct *tsk); #ifdef CONFIG_SMP -extern void wait_task_context_switch(struct task_struct *p); extern unsigned long wait_task_inactive(struct task_struct *, long match_state); #else -static inline void wait_task_context_switch(struct task_struct *p) {} static inline unsigned long wait_task_inactive(struct task_struct *p, long match_state) { diff --git a/kernel/fork.c b/kernel/fork.c index 4799c5f..d67f1db 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1108,9 +1108,6 @@ static struct task_struct *copy_process(unsigned long clone_flags, p->memcg_batch.do_batch = 0; p->memcg_batch.memcg = NULL; #endif - - p->bts = NULL; - p->stack_start = stack_start; /* Perform scheduler related setup. Assign this task to a CPU. */ diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 42ad8ae..9fb5123 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -76,7 +76,6 @@ void __ptrace_unlink(struct task_struct *child) child->parent = child->real_parent; list_del_init(&child->ptrace_entry); - arch_ptrace_untrace(child); if (task_is_traced(child)) ptrace_untrace(child); } diff --git a/kernel/sched.c b/kernel/sched.c index 9ab3cd7..117b7ca 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -2077,49 +2077,6 @@ migrate_task(struct task_struct *p, int dest_cpu, struct migration_req *req) } /* - * wait_task_context_switch - wait for a thread to complete at least one - * context switch. - * - * @p must not be current. - */ -void wait_task_context_switch(struct task_struct *p) -{ - unsigned long nvcsw, nivcsw, flags; - int running; - struct rq *rq; - - nvcsw = p->nvcsw; - nivcsw = p->nivcsw; - for (;;) { - /* - * The runqueue is assigned before the actual context - * switch. We need to take the runqueue lock. - * - * We could check initially without the lock but it is - * very likely that we need to take the lock in every - * iteration. - */ - rq = task_rq_lock(p, &flags); - running = task_running(rq, p); - task_rq_unlock(rq, &flags); - - if (likely(!running)) - break; - /* - * The switch count is incremented before the actual - * context switch. We thus wait for two switches to be - * sure at least one completed. - */ - if ((p->nvcsw - nvcsw) > 1) - break; - if ((p->nivcsw - nivcsw) > 1) - break; - - cpu_relax(); - } -} - -/* * wait_task_inactive - wait for a thread to unschedule. * * If @match_state is nonzero, it's the @p->state value just checked and diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index 13e13d4..8b1797c 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig @@ -44,9 +44,6 @@ config HAVE_FTRACE_MCOUNT_RECORD help See Documentation/trace/ftrace-design.txt -config HAVE_HW_BRANCH_TRACER - bool - config HAVE_SYSCALL_TRACEPOINTS bool help @@ -374,14 +371,6 @@ config STACK_TRACER Say N if unsure. -config HW_BRANCH_TRACER - depends on HAVE_HW_BRANCH_TRACER - bool "Trace hw branches" - select GENERIC_TRACER - help - This tracer records all branches on the system in a circular - buffer, giving access to the last N branches for each cpu. - config KMEMTRACE bool "Trace SLAB allocations" select GENERIC_TRACER diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile index 78edc64..ffb1a5b 100644 --- a/kernel/trace/Makefile +++ b/kernel/trace/Makefile @@ -41,7 +41,6 @@ obj-$(CONFIG_MMIOTRACE) += trace_mmiotrace.o obj-$(CONFIG_BOOT_TRACER) += trace_boot.o obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += trace_functions_graph.o obj-$(CONFIG_TRACE_BRANCH_PROFILING) += trace_branch.o -obj-$(CONFIG_HW_BRANCH_TRACER) += trace_hw_branches.o obj-$(CONFIG_KMEMTRACE) += kmemtrace.o obj-$(CONFIG_WORKQUEUE_TRACER) += trace_workqueue.o obj-$(CONFIG_BLK_DEV_IO_TRACE) += blktrace.o diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 2825ef2..bec2c97 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -34,7 +34,6 @@ enum trace_type { TRACE_GRAPH_RET, TRACE_GRAPH_ENT, TRACE_USER_STACK, - TRACE_HW_BRANCHES, TRACE_KMEM_ALLOC, TRACE_KMEM_FREE, TRACE_BLK, @@ -229,7 +228,6 @@ extern void __ftrace_bad_type(void); TRACE_GRAPH_ENT); \ IF_ASSIGN(var, ent, struct ftrace_graph_ret_entry, \ TRACE_GRAPH_RET); \ - IF_ASSIGN(var, ent, struct hw_branch_entry, TRACE_HW_BRANCHES);\ IF_ASSIGN(var, ent, struct kmemtrace_alloc_entry, \ TRACE_KMEM_ALLOC); \ IF_ASSIGN(var, ent, struct kmemtrace_free_entry, \ @@ -467,8 +465,6 @@ extern int trace_selftest_startup_sysprof(struct tracer *trace, struct trace_array *tr); extern int trace_selftest_startup_branch(struct tracer *trace, struct trace_array *tr); -extern int trace_selftest_startup_hw_branches(struct tracer *trace, - struct trace_array *tr); extern int trace_selftest_startup_ksym(struct tracer *trace, struct trace_array *tr); #endif /* CONFIG_FTRACE_STARTUP_TEST */ diff --git a/kernel/trace/trace_entries.h b/kernel/trace/trace_entries.h index c16a08f..dc008c1 100644 --- a/kernel/trace/trace_entries.h +++ b/kernel/trace/trace_entries.h @@ -318,18 +318,6 @@ FTRACE_ENTRY(branch, trace_branch, __entry->func, __entry->file, __entry->correct) ); -FTRACE_ENTRY(hw_branch, hw_branch_entry, - - TRACE_HW_BRANCHES, - - F_STRUCT( - __field( u64, from ) - __field( u64, to ) - ), - - F_printk("from: %llx to: %llx", __entry->from, __entry->to) -); - FTRACE_ENTRY(kmem_alloc, kmemtrace_alloc_entry, TRACE_KMEM_ALLOC, diff --git a/kernel/trace/trace_hw_branches.c b/kernel/trace/trace_hw_branches.c deleted file mode 100644 index 7b97000..0000000 --- a/kernel/trace/trace_hw_branches.c +++ /dev/null @@ -1,312 +0,0 @@ -/* - * h/w branch tracer for x86 based on BTS - * - * Copyright (C) 2008-2009 Intel Corporation. - * Markus Metzger , 2008-2009 - */ -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "trace_output.h" -#include "trace.h" - - -#define BTS_BUFFER_SIZE (1 << 13) - -static DEFINE_PER_CPU(struct bts_tracer *, hwb_tracer); -static DEFINE_PER_CPU(unsigned char[BTS_BUFFER_SIZE], hwb_buffer); - -#define this_tracer per_cpu(hwb_tracer, smp_processor_id()) - -static int trace_hw_branches_enabled __read_mostly; -static int trace_hw_branches_suspended __read_mostly; -static struct trace_array *hw_branch_trace __read_mostly; - - -static void bts_trace_init_cpu(int cpu) -{ - per_cpu(hwb_tracer, cpu) = - ds_request_bts_cpu(cpu, per_cpu(hwb_buffer, cpu), - BTS_BUFFER_SIZE, NULL, (size_t)-1, - BTS_KERNEL); - - if (IS_ERR(per_cpu(hwb_tracer, cpu))) - per_cpu(hwb_tracer, cpu) = NULL; -} - -static int bts_trace_init(struct trace_array *tr) -{ - int cpu; - - hw_branch_trace = tr; - trace_hw_branches_enabled = 0; - - get_online_cpus(); - for_each_online_cpu(cpu) { - bts_trace_init_cpu(cpu); - - if (likely(per_cpu(hwb_tracer, cpu))) - trace_hw_branches_enabled = 1; - } - trace_hw_branches_suspended = 0; - put_online_cpus(); - - /* If we could not enable tracing on a single cpu, we fail. */ - return trace_hw_branches_enabled ? 0 : -EOPNOTSUPP; -} - -static void bts_trace_reset(struct trace_array *tr) -{ - int cpu; - - get_online_cpus(); - for_each_online_cpu(cpu) { - if (likely(per_cpu(hwb_tracer, cpu))) { - ds_release_bts(per_cpu(hwb_tracer, cpu)); - per_cpu(hwb_tracer, cpu) = NULL; - } - } - trace_hw_branches_enabled = 0; - trace_hw_branches_suspended = 0; - put_online_cpus(); -} - -static void bts_trace_start(struct trace_array *tr) -{ - int cpu; - - get_online_cpus(); - for_each_online_cpu(cpu) - if (likely(per_cpu(hwb_tracer, cpu))) - ds_resume_bts(per_cpu(hwb_tracer, cpu)); - trace_hw_branches_suspended = 0; - put_online_cpus(); -} - -static void bts_trace_stop(struct trace_array *tr) -{ - int cpu; - - get_online_cpus(); - for_each_online_cpu(cpu) - if (likely(per_cpu(hwb_tracer, cpu))) - ds_suspend_bts(per_cpu(hwb_tracer, cpu)); - trace_hw_branches_suspended = 1; - put_online_cpus(); -} - -static int __cpuinit bts_hotcpu_handler(struct notifier_block *nfb, - unsigned long action, void *hcpu) -{ - int cpu = (long)hcpu; - - switch (action) { - case CPU_ONLINE: - case CPU_DOWN_FAILED: - /* The notification is sent with interrupts enabled. */ - if (trace_hw_branches_enabled) { - bts_trace_init_cpu(cpu); - - if (trace_hw_branches_suspended && - likely(per_cpu(hwb_tracer, cpu))) - ds_suspend_bts(per_cpu(hwb_tracer, cpu)); - } - break; - - case CPU_DOWN_PREPARE: - /* The notification is sent with interrupts enabled. */ - if (likely(per_cpu(hwb_tracer, cpu))) { - ds_release_bts(per_cpu(hwb_tracer, cpu)); - per_cpu(hwb_tracer, cpu) = NULL; - } - } - - return NOTIFY_DONE; -} - -static struct notifier_block bts_hotcpu_notifier __cpuinitdata = { - .notifier_call = bts_hotcpu_handler -}; - -static void bts_trace_print_header(struct seq_file *m) -{ - seq_puts(m, "# CPU# TO <- FROM\n"); -} - -static enum print_line_t bts_trace_print_line(struct trace_iterator *iter) -{ - unsigned long symflags = TRACE_ITER_SYM_OFFSET; - struct trace_entry *entry = iter->ent; - struct trace_seq *seq = &iter->seq; - struct hw_branch_entry *it; - - trace_assign_type(it, entry); - - if (entry->type == TRACE_HW_BRANCHES) { - if (trace_seq_printf(seq, "%4d ", iter->cpu) && - seq_print_ip_sym(seq, it->to, symflags) && - trace_seq_printf(seq, "\t <- ") && - seq_print_ip_sym(seq, it->from, symflags) && - trace_seq_printf(seq, "\n")) - return TRACE_TYPE_HANDLED; - return TRACE_TYPE_PARTIAL_LINE; - } - return TRACE_TYPE_UNHANDLED; -} - -void trace_hw_branch(u64 from, u64 to) -{ - struct ftrace_event_call *call = &event_hw_branch; - struct trace_array *tr = hw_branch_trace; - struct ring_buffer_event *event; - struct ring_buffer *buf; - struct hw_branch_entry *entry; - unsigned long irq1; - int cpu; - - if (unlikely(!tr)) - return; - - if (unlikely(!trace_hw_branches_enabled)) - return; - - local_irq_save(irq1); - cpu = raw_smp_processor_id(); - if (atomic_inc_return(&tr->data[cpu]->disabled) != 1) - goto out; - - buf = tr->buffer; - event = trace_buffer_lock_reserve(buf, TRACE_HW_BRANCHES, - sizeof(*entry), 0, 0); - if (!event) - goto out; - entry = ring_buffer_event_data(event); - tracing_generic_entry_update(&entry->ent, 0, from); - entry->ent.type = TRACE_HW_BRANCHES; - entry->from = from; - entry->to = to; - if (!filter_check_discard(call, entry, buf, event)) - trace_buffer_unlock_commit(buf, event, 0, 0); - - out: - atomic_dec(&tr->data[cpu]->disabled); - local_irq_restore(irq1); -} - -static void trace_bts_at(const struct bts_trace *trace, void *at) -{ - struct bts_struct bts; - int err = 0; - - WARN_ON_ONCE(!trace->read); - if (!trace->read) - return; - - err = trace->read(this_tracer, at, &bts); - if (err < 0) - return; - - switch (bts.qualifier) { - case BTS_BRANCH: - trace_hw_branch(bts.variant.lbr.from, bts.variant.lbr.to); - break; - } -} - -/* - * Collect the trace on the current cpu and write it into the ftrace buffer. - * - * pre: tracing must be suspended on the current cpu - */ -static void trace_bts_cpu(void *arg) -{ - struct trace_array *tr = (struct trace_array *)arg; - const struct bts_trace *trace; - unsigned char *at; - - if (unlikely(!tr)) - return; - - if (unlikely(atomic_read(&tr->data[raw_smp_processor_id()]->disabled))) - return; - - if (unlikely(!this_tracer)) - return; - - trace = ds_read_bts(this_tracer); - if (!trace) - return; - - for (at = trace->ds.top; (void *)at < trace->ds.end; - at += trace->ds.size) - trace_bts_at(trace, at); - - for (at = trace->ds.begin; (void *)at < trace->ds.top; - at += trace->ds.size) - trace_bts_at(trace, at); -} - -static void trace_bts_prepare(struct trace_iterator *iter) -{ - int cpu; - - get_online_cpus(); - for_each_online_cpu(cpu) - if (likely(per_cpu(hwb_tracer, cpu))) - ds_suspend_bts(per_cpu(hwb_tracer, cpu)); - /* - * We need to collect the trace on the respective cpu since ftrace - * implicitly adds the record for the current cpu. - * Once that is more flexible, we could collect the data from any cpu. - */ - on_each_cpu(trace_bts_cpu, iter->tr, 1); - - for_each_online_cpu(cpu) - if (likely(per_cpu(hwb_tracer, cpu))) - ds_resume_bts(per_cpu(hwb_tracer, cpu)); - put_online_cpus(); -} - -static void trace_bts_close(struct trace_iterator *iter) -{ - tracing_reset_online_cpus(iter->tr); -} - -void trace_hw_branch_oops(void) -{ - if (this_tracer) { - ds_suspend_bts_noirq(this_tracer); - trace_bts_cpu(hw_branch_trace); - ds_resume_bts_noirq(this_tracer); - } -} - -struct tracer bts_tracer __read_mostly = -{ - .name = "hw-branch-tracer", - .init = bts_trace_init, - .reset = bts_trace_reset, - .print_header = bts_trace_print_header, - .print_line = bts_trace_print_line, - .start = bts_trace_start, - .stop = bts_trace_stop, - .open = trace_bts_prepare, - .close = trace_bts_close, -#ifdef CONFIG_FTRACE_SELFTEST - .selftest = trace_selftest_startup_hw_branches, -#endif /* CONFIG_FTRACE_SELFTEST */ -}; - -__init static int init_bts_trace(void) -{ - register_hotcpu_notifier(&bts_hotcpu_notifier); - return register_tracer(&bts_tracer); -} -device_initcall(init_bts_trace); diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c index 280fea4..a7084e7 100644 --- a/kernel/trace/trace_selftest.c +++ b/kernel/trace/trace_selftest.c @@ -16,7 +16,6 @@ static inline int trace_valid_entry(struct trace_entry *entry) case TRACE_BRANCH: case TRACE_GRAPH_ENT: case TRACE_GRAPH_RET: - case TRACE_HW_BRANCHES: case TRACE_KSYM: return 1; } @@ -754,62 +753,6 @@ trace_selftest_startup_branch(struct tracer *trace, struct trace_array *tr) } #endif /* CONFIG_BRANCH_TRACER */ -#ifdef CONFIG_HW_BRANCH_TRACER -int -trace_selftest_startup_hw_branches(struct tracer *trace, - struct trace_array *tr) -{ - struct trace_iterator *iter; - struct tracer tracer; - unsigned long count; - int ret; - - if (!trace->open) { - printk(KERN_CONT "missing open function..."); - return -1; - } - - ret = tracer_init(trace, tr); - if (ret) { - warn_failed_init_tracer(trace, ret); - return ret; - } - - /* - * The hw-branch tracer needs to collect the trace from the various - * cpu trace buffers - before tracing is stopped. - */ - iter = kzalloc(sizeof(*iter), GFP_KERNEL); - if (!iter) - return -ENOMEM; - - memcpy(&tracer, trace, sizeof(tracer)); - - iter->trace = &tracer; - iter->tr = tr; - iter->pos = -1; - mutex_init(&iter->mutex); - - trace->open(iter); - - mutex_destroy(&iter->mutex); - kfree(iter); - - tracing_stop(); - - ret = trace_test_buffer(tr, &count); - trace->reset(tr); - tracing_start(); - - if (!ret && !count) { - printk(KERN_CONT "no entries found.."); - ret = -1; - } - - return ret; -} -#endif /* CONFIG_HW_BRANCH_TRACER */ - #ifdef CONFIG_KSYM_TRACER static int ksym_selftest_dummy; diff --git a/mm/mlock.c b/mm/mlock.c index 8f4e2df..3f82720 100644 --- a/mm/mlock.c +++ b/mm/mlock.c @@ -607,44 +607,3 @@ void user_shm_unlock(size_t size, struct user_struct *user) spin_unlock(&shmlock_user_lock); free_uid(user); } - -int account_locked_memory(struct mm_struct *mm, struct rlimit *rlim, - size_t size) -{ - unsigned long lim, vm, pgsz; - int error = -ENOMEM; - - pgsz = PAGE_ALIGN(size) >> PAGE_SHIFT; - - down_write(&mm->mmap_sem); - - lim = ACCESS_ONCE(rlim[RLIMIT_AS].rlim_cur) >> PAGE_SHIFT; - vm = mm->total_vm + pgsz; - if (lim < vm) - goto out; - - lim = ACCESS_ONCE(rlim[RLIMIT_MEMLOCK].rlim_cur) >> PAGE_SHIFT; - vm = mm->locked_vm + pgsz; - if (lim < vm) - goto out; - - mm->total_vm += pgsz; - mm->locked_vm += pgsz; - - error = 0; - out: - up_write(&mm->mmap_sem); - return error; -} - -void refund_locked_memory(struct mm_struct *mm, size_t size) -{ - unsigned long pgsz = PAGE_ALIGN(size) >> PAGE_SHIFT; - - down_write(&mm->mmap_sem); - - mm->total_vm -= pgsz; - mm->locked_vm -= pgsz; - - up_write(&mm->mmap_sem); -} -- cgit v0.10.2 From ea8e61b7bbc4a2faef77db34eb2db2a2c2372ff6 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 25 Mar 2010 14:51:51 +0100 Subject: x86, ptrace: Fix block-step Implement ptrace-block-step using TIF_BLOCKSTEP which will set DEBUGCTLMSR_BTF when set for a task while preserving any other DEBUGCTLMSR bits. Signed-off-by: Peter Zijlstra LKML-Reference: <20100325135414.017536066@chello.nl> Signed-off-by: Ingo Molnar diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 5bec21a..32428b4 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -799,7 +799,7 @@ extern void cpu_init(void); static inline unsigned long get_debugctlmsr(void) { - unsigned long debugctlmsr = 0; + unsigned long debugctlmsr = 0; #ifndef CONFIG_X86_DEBUGCTLMSR if (boot_cpu_data.x86 < 6) @@ -807,7 +807,7 @@ static inline unsigned long get_debugctlmsr(void) #endif rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctlmsr); - return debugctlmsr; + return debugctlmsr; } static inline void update_debugctlmsr(unsigned long debugctlmsr) diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h index dc85e12..d017ed55 100644 --- a/arch/x86/include/asm/thread_info.h +++ b/arch/x86/include/asm/thread_info.h @@ -92,6 +92,7 @@ struct thread_info { #define TIF_IO_BITMAP 22 /* uses I/O bitmap */ #define TIF_FREEZE 23 /* is freezing for suspend */ #define TIF_FORCED_TF 24 /* true if TF in eflags artificially */ +#define TIF_BLOCKSTEP 25 /* set when we want DEBUGCTLMSR_BTF */ #define TIF_LAZY_MMU_UPDATES 27 /* task is updating the mmu lazily */ #define TIF_SYSCALL_TRACEPOINT 28 /* syscall tracepoint instrumentation */ @@ -113,6 +114,7 @@ struct thread_info { #define _TIF_IO_BITMAP (1 << TIF_IO_BITMAP) #define _TIF_FREEZE (1 << TIF_FREEZE) #define _TIF_FORCED_TF (1 << TIF_FORCED_TF) +#define _TIF_BLOCKSTEP (1 << TIF_BLOCKSTEP) #define _TIF_LAZY_MMU_UPDATES (1 << TIF_LAZY_MMU_UPDATES) #define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT) @@ -143,7 +145,7 @@ struct thread_info { /* flags to check in __switch_to() */ #define _TIF_WORK_CTXSW \ - (_TIF_IO_BITMAP|_TIF_NOTSC) + (_TIF_IO_BITMAP|_TIF_NOTSC|_TIF_BLOCKSTEP) #define _TIF_WORK_CTXSW_PREV (_TIF_WORK_CTXSW|_TIF_USER_RETURN_NOTIFY) #define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW|_TIF_DEBUG) diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c index 7a880ad..f2f56c0 100644 --- a/arch/x86/kernel/kprobes.c +++ b/arch/x86/kernel/kprobes.c @@ -422,12 +422,22 @@ static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs, static void __kprobes clear_btf(void) { - /* XXX */ + if (test_thread_flag(TIF_BLOCKSTEP)) { + unsigned long debugctl = get_debugctlmsr(); + + debugctl &= ~DEBUGCTLMSR_BTF; + update_debugctlmsr(debugctl); + } } static void __kprobes restore_btf(void) { - /* XXX */ + if (test_thread_flag(TIF_BLOCKSTEP)) { + unsigned long debugctl = get_debugctlmsr(); + + debugctl |= DEBUGCTLMSR_BTF; + update_debugctlmsr(debugctl); + } } void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 1a60beb..8328009 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -195,6 +195,17 @@ void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, prev = &prev_p->thread; next = &next_p->thread; + if (test_tsk_thread_flag(prev_p, TIF_BLOCKSTEP) ^ + test_tsk_thread_flag(next_p, TIF_BLOCKSTEP)) { + unsigned long debugctl = get_debugctlmsr(); + + debugctl &= ~DEBUGCTLMSR_BTF; + if (test_tsk_thread_flag(next_p, TIF_BLOCKSTEP)) + debugctl |= DEBUGCTLMSR_BTF; + + update_debugctlmsr(debugctl); + } + if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^ test_tsk_thread_flag(next_p, TIF_NOTSC)) { /* prev and next are different */ diff --git a/arch/x86/kernel/step.c b/arch/x86/kernel/step.c index 7beba07..58de45e 100644 --- a/arch/x86/kernel/step.c +++ b/arch/x86/kernel/step.c @@ -169,9 +169,19 @@ static void enable_step(struct task_struct *child, bool block) * So noone should try to use debugger block stepping in a program * that uses user-mode single stepping itself. */ - if (!enable_single_step(child)) - return; - /* XXX */ + if (enable_single_step(child) && block) { + unsigned long debugctl = get_debugctlmsr(); + + debugctl |= DEBUGCTLMSR_BTF; + update_debugctlmsr(debugctl); + set_tsk_thread_flag(child, TIF_BLOCKSTEP); + } else if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) { + unsigned long debugctl = get_debugctlmsr(); + + debugctl &= ~DEBUGCTLMSR_BTF; + update_debugctlmsr(debugctl); + clear_tsk_thread_flag(child, TIF_BLOCKSTEP); + } } void user_enable_single_step(struct task_struct *child) @@ -189,7 +199,13 @@ void user_disable_single_step(struct task_struct *child) /* * Make sure block stepping (BTF) is disabled. */ - /* XXX */ + if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) { + unsigned long debugctl = get_debugctlmsr(); + + debugctl &= ~DEBUGCTLMSR_BTF; + update_debugctlmsr(debugctl); + clear_tsk_thread_flag(child, TIF_BLOCKSTEP); + } /* Always clear TIF_SINGLESTEP... */ clear_tsk_thread_flag(child, TIF_SINGLESTEP); diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index e3da5d7..36f1bd9 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -544,6 +544,11 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) /* DR6 may or may not be cleared by the CPU */ set_debugreg(0, 6); + /* + * The processor cleared BTF, so don't mark that we need it set. + */ + clear_tsk_thread_flag(tsk, TIF_BLOCKSTEP); + /* Store the virtualized DR6 value */ tsk->thread.debugreg6 = dr6; -- cgit v0.10.2 From 11164cd4f6dab326a88bdf27f2f8f7c11977e91a Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 26 Mar 2010 14:08:44 +0100 Subject: perf, x86: Add Nehelem PMU programming errata workaround Implement the workaround for Intel Errata AAK100 and AAP53. Also, remove the Core-i7 name for Nehalem events since there are also Westmere based i7 chips. Signed-off-by: Peter Zijlstra Cc: Stephane Eranian LKML-Reference: <1269608924.12097.147.camel@laptop> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index f571f51..6f66d4a 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -184,7 +184,7 @@ struct x86_pmu { int version; int (*handle_irq)(struct pt_regs *); void (*disable_all)(void); - void (*enable_all)(void); + void (*enable_all)(int added); void (*enable)(struct perf_event *); void (*disable)(struct perf_event *); int (*hw_config)(struct perf_event_attr *attr, struct hw_perf_event *hwc); @@ -576,7 +576,7 @@ void hw_perf_disable(void) x86_pmu.disable_all(); } -static void x86_pmu_enable_all(void) +static void x86_pmu_enable_all(int added) { struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); int idx; @@ -784,7 +784,7 @@ void hw_perf_enable(void) struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); struct perf_event *event; struct hw_perf_event *hwc; - int i; + int i, added = cpuc->n_added; if (!x86_pmu_initialized()) return; @@ -836,7 +836,7 @@ void hw_perf_enable(void) cpuc->enabled = 1; barrier(); - x86_pmu.enable_all(); + x86_pmu.enable_all(added); } static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc) diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 044b843..676aac2 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -483,7 +483,7 @@ static void intel_pmu_disable_all(void) intel_pmu_lbr_disable_all(); } -static void intel_pmu_enable_all(void) +static void intel_pmu_enable_all(int added) { struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); @@ -502,6 +502,40 @@ static void intel_pmu_enable_all(void) } } +/* + * Workaround for: + * Intel Errata AAK100 (model 26) + * Intel Errata AAP53 (model 30) + * + * These chips need to be 'reset' when adding counters by programming + * the magic three (non counting) events 0x4300D2, 0x4300B1 and 0x4300B5 + * either in sequence on the same PMC or on different PMCs. + */ +static void intel_pmu_nhm_enable_all(int added) +{ + if (added) { + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + int i; + + wrmsrl(MSR_ARCH_PERFMON_EVENTSEL0 + 0, 0x4300D2); + wrmsrl(MSR_ARCH_PERFMON_EVENTSEL0 + 1, 0x4300B1); + wrmsrl(MSR_ARCH_PERFMON_EVENTSEL0 + 2, 0x4300B5); + + wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0x3); + wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0x0); + + for (i = 0; i < 3; i++) { + struct perf_event *event = cpuc->events[i]; + + if (!event) + continue; + + __x86_pmu_enable_event(&event->hw); + } + } + intel_pmu_enable_all(added); +} + static inline u64 intel_pmu_get_status(void) { u64 status; @@ -658,7 +692,7 @@ static int intel_pmu_handle_irq(struct pt_regs *regs) intel_pmu_drain_bts_buffer(); status = intel_pmu_get_status(); if (!status) { - intel_pmu_enable_all(); + intel_pmu_enable_all(0); return 0; } @@ -707,7 +741,7 @@ again: goto again; done: - intel_pmu_enable_all(); + intel_pmu_enable_all(0); return 1; } @@ -920,7 +954,8 @@ static __init int intel_pmu_init(void) intel_pmu_lbr_init_nhm(); x86_pmu.event_constraints = intel_nehalem_event_constraints; - pr_cont("Nehalem/Corei7 events, "); + x86_pmu.enable_all = intel_pmu_nhm_enable_all; + pr_cont("Nehalem events, "); break; case 28: /* Atom */ diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index f8fe069..0d1be36 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c @@ -535,7 +535,7 @@ static void p4_pmu_enable_event(struct perf_event *event) (cccr & ~P4_CCCR_RESERVED) | P4_CCCR_ENABLE); } -static void p4_pmu_enable_all(void) +static void p4_pmu_enable_all(int added) { struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); int idx; diff --git a/arch/x86/kernel/cpu/perf_event_p6.c b/arch/x86/kernel/cpu/perf_event_p6.c index 6ff4d01d..877182c 100644 --- a/arch/x86/kernel/cpu/perf_event_p6.c +++ b/arch/x86/kernel/cpu/perf_event_p6.c @@ -66,7 +66,7 @@ static void p6_pmu_disable_all(void) wrmsrl(MSR_P6_EVNTSEL0, val); } -static void p6_pmu_enable_all(void) +static void p6_pmu_enable_all(int added) { unsigned long val; -- cgit v0.10.2 From 1fb2f77c037624601fd214fb7c29faa84cd7bdd7 Mon Sep 17 00:00:00 2001 From: Henrik Kretzschmar Date: Fri, 26 Mar 2010 20:38:35 +0100 Subject: debugobjects: Section mismatch cleanup This patch marks two functions, which only get called at initialization, as __init. Here is also interesting, that modpost doesn't catch here the right function name. WARNING: lib/built-in.o(.text+0x585f): Section mismatch in reference from the function T.506() to the variable .init.data:obj The function T.506() references the variable __initdata obj. This is often because T.506 lacks a __initdata annotation or the annotation of obj is wrong. Signed-off-by: Henrik Kretzschmar LKML-Reference: <1269632315-19403-1-git-send-email-henne@nachtwindheim.de> Signed-off-by: Thomas Gleixner diff --git a/lib/debugobjects.c b/lib/debugobjects.c index a9a8996..c4ecd3c 100644 --- a/lib/debugobjects.c +++ b/lib/debugobjects.c @@ -773,7 +773,7 @@ static int __init fixup_free(void *addr, enum debug_obj_state state) } } -static int +static int __init check_results(void *addr, enum debug_obj_state state, int fixups, int warnings) { struct debug_bucket *db; @@ -916,7 +916,7 @@ void __init debug_objects_early_init(void) /* * Convert the statically allocated objects to dynamic ones: */ -static int debug_objects_replace_static_objects(void) +static int __init debug_objects_replace_static_objects(void) { struct debug_bucket *db = obj_hash; struct hlist_node *node, *tmp; -- cgit v0.10.2 From 6ae6650232ddcf2f50e8817acd63cde37cf1d093 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Mon, 29 Mar 2010 15:24:54 +0900 Subject: sh: tlb debugfs support. Export the status of the utlb and itlb entries through debugfs. Signed-off-by: Matt Fleming Signed-off-by: Paul Mundt diff --git a/arch/sh/include/cpu-sh4/cpu/mmu_context.h b/arch/sh/include/cpu-sh4/cpu/mmu_context.h index 5963124..2941be6 100644 --- a/arch/sh/include/cpu-sh4/cpu/mmu_context.h +++ b/arch/sh/include/cpu-sh4/cpu/mmu_context.h @@ -19,10 +19,17 @@ #define MMUCR 0xFF000010 /* MMU Control Register */ +#define MMU_TLB_ENTRY_SHIFT 8 + #define MMU_ITLB_ADDRESS_ARRAY 0xF2000000 #define MMU_ITLB_ADDRESS_ARRAY2 0xF2800000 +#define MMU_ITLB_DATA_ARRAY 0xF3000000 +#define MMU_ITLB_DATA_ARRAY2 0xF3800000 + #define MMU_UTLB_ADDRESS_ARRAY 0xF6000000 #define MMU_UTLB_ADDRESS_ARRAY2 0xF6800000 +#define MMU_UTLB_DATA_ARRAY 0xF7000000 +#define MMU_UTLB_DATA_ARRAY2 0xF7800000 #define MMU_PAGE_ASSOC_BIT 0x80 #define MMUCR_TI (1<<2) diff --git a/arch/sh/mm/Makefile b/arch/sh/mm/Makefile index 3dc8a8a..c73018a 100644 --- a/arch/sh/mm/Makefile +++ b/arch/sh/mm/Makefile @@ -18,13 +18,14 @@ mmu-$(CONFIG_MMU) := extable_$(BITS).o fault_$(BITS).o \ ioremap.o kmap.o pgtable.o tlbflush_$(BITS).o obj-y += $(mmu-y) -obj-$(CONFIG_DEBUG_FS) += asids-debugfs.o -ifdef CONFIG_DEBUG_FS -obj-$(CONFIG_CPU_SH4) += cache-debugfs.o +debugfs-y := asids-debugfs.o +ifndef CONFIG_CACHE_OFF +debugfs-$(CONFIG_CPU_SH4) += cache-debugfs.o endif ifdef CONFIG_MMU +debugfs-$(CONFIG_CPU_SH4) += tlb-debugfs.o tlb-$(CONFIG_CPU_SH3) := tlb-sh3.o tlb-$(CONFIG_CPU_SH4) := tlb-sh4.o tlb-urb.o tlb-$(CONFIG_CPU_SH5) := tlb-sh5.o @@ -32,6 +33,7 @@ tlb-$(CONFIG_CPU_HAS_PTEAEX) := tlb-pteaex.o tlb-urb.o obj-y += $(tlb-y) endif +obj-$(CONFIG_DEBUG_FS) += $(debugfs-y) obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o obj-$(CONFIG_PMB) += pmb.o obj-$(CONFIG_NUMA) += numa.o diff --git a/arch/sh/mm/tlb-debugfs.c b/arch/sh/mm/tlb-debugfs.c new file mode 100644 index 0000000..229bf75 --- /dev/null +++ b/arch/sh/mm/tlb-debugfs.c @@ -0,0 +1,179 @@ +/* + * arch/sh/mm/tlb-debugfs.c + * + * debugfs ops for SH-4 ITLB/UTLBs. + * + * Copyright (C) 2010 Matt Fleming + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include +#include + +enum tlb_type { + TLB_TYPE_ITLB, + TLB_TYPE_UTLB, +}; + +static struct { + int bits; + const char *size; +} tlb_sizes[] = { + { 0x0, " 1KB" }, + { 0x1, " 4KB" }, + { 0x2, " 8KB" }, + { 0x4, " 64KB" }, + { 0x5, "256KB" }, + { 0x7, " 1MB" }, + { 0x8, " 4MB" }, + { 0xc, " 64MB" }, +}; + +static int tlb_seq_show(struct seq_file *file, void *iter) +{ + unsigned int tlb_type = (unsigned int)file->private; + unsigned long addr1, addr2, data1, data2; + unsigned long flags; + unsigned long mmucr; + unsigned int nentries, entry; + unsigned int urb; + + mmucr = __raw_readl(MMUCR); + if ((mmucr & 0x1) == 0) { + seq_printf(file, "address translation disabled\n"); + return 0; + } + + if (tlb_type == TLB_TYPE_ITLB) { + addr1 = MMU_ITLB_ADDRESS_ARRAY; + addr2 = MMU_ITLB_ADDRESS_ARRAY2; + data1 = MMU_ITLB_DATA_ARRAY; + data2 = MMU_ITLB_DATA_ARRAY2; + nentries = 4; + } else { + addr1 = MMU_UTLB_ADDRESS_ARRAY; + addr2 = MMU_UTLB_ADDRESS_ARRAY2; + data1 = MMU_UTLB_DATA_ARRAY; + data2 = MMU_UTLB_DATA_ARRAY2; + nentries = 64; + } + + local_irq_save(flags); + jump_to_uncached(); + + urb = (mmucr & MMUCR_URB) >> MMUCR_URB_SHIFT; + + /* Make the "entry >= urb" test fail. */ + if (urb == 0) + urb = MMUCR_URB_NENTRIES + 1; + + if (tlb_type == TLB_TYPE_ITLB) { + addr1 = MMU_ITLB_ADDRESS_ARRAY; + addr2 = MMU_ITLB_ADDRESS_ARRAY2; + data1 = MMU_ITLB_DATA_ARRAY; + data2 = MMU_ITLB_DATA_ARRAY2; + nentries = 4; + } else { + addr1 = MMU_UTLB_ADDRESS_ARRAY; + addr2 = MMU_UTLB_ADDRESS_ARRAY2; + data1 = MMU_UTLB_DATA_ARRAY; + data2 = MMU_UTLB_DATA_ARRAY2; + nentries = 64; + } + + seq_printf(file, "entry: vpn ppn asid size valid wired\n"); + + for (entry = 0; entry < nentries; entry++) { + unsigned long vpn, ppn, asid, size; + unsigned long valid; + unsigned long val; + const char *sz = " ?"; + int i; + + val = __raw_readl(addr1 | (entry << MMU_TLB_ENTRY_SHIFT)); + ctrl_barrier(); + vpn = val & 0xfffffc00; + valid = val & 0x100; + + val = __raw_readl(addr2 | (entry << MMU_TLB_ENTRY_SHIFT)); + ctrl_barrier(); + asid = val & MMU_CONTEXT_ASID_MASK; + + val = __raw_readl(data1 | (entry << MMU_TLB_ENTRY_SHIFT)); + ctrl_barrier(); + ppn = (val & 0x0ffffc00) << 4; + + val = __raw_readl(data2 | (entry << MMU_TLB_ENTRY_SHIFT)); + ctrl_barrier(); + size = (val & 0xf0) >> 4; + + for (i = 0; i < ARRAY_SIZE(tlb_sizes); i++) { + if (tlb_sizes[i].bits == size) + break; + } + + if (i != ARRAY_SIZE(tlb_sizes)) + sz = tlb_sizes[i].size; + + seq_printf(file, "%2d: 0x%08lx 0x%08lx %5lu %s %s %s\n", + entry, vpn, ppn, asid, + sz, valid ? "V" : "-", + (urb <= entry) ? "W" : "-"); + } + + back_to_cached(); + local_irq_restore(flags); + + return 0; +} + +static int tlb_debugfs_open(struct inode *inode, struct file *file) +{ + return single_open(file, tlb_seq_show, inode->i_private); +} + +static const struct file_operations tlb_debugfs_fops = { + .owner = THIS_MODULE, + .open = tlb_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int __init tlb_debugfs_init(void) +{ + struct dentry *itlb, *utlb; + + itlb = debugfs_create_file("itlb", S_IRUSR, sh_debugfs_root, + (unsigned int *)TLB_TYPE_ITLB, + &tlb_debugfs_fops); + if (unlikely(!itlb)) + return -ENOMEM; + if (IS_ERR(itlb)) + return PTR_ERR(itlb); + + utlb = debugfs_create_file("utlb", S_IRUSR, sh_debugfs_root, + (unsigned int *)TLB_TYPE_UTLB, + &tlb_debugfs_fops); + if (unlikely(!utlb)) { + debugfs_remove(itlb); + return -ENOMEM; + } + + if (IS_ERR(utlb)) { + debugfs_remove(itlb); + return PTR_ERR(utlb); + } + + return 0; +} +module_init(tlb_debugfs_init); + +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From bd05086bbe3f241cd552068f9ceba9e19c6ce427 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 29 Mar 2010 15:51:35 +0900 Subject: driver core: Convert to kasprintf() for early dev_name(). This is just a simple refactoring patch on top of the early dev_name() support, converting from kstrdup() to kasprintf() as suggested by Kay. Signed-off-by: Paul Mundt diff --git a/drivers/base/platform.c b/drivers/base/platform.c index d2d4926..f2377f3 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -1245,19 +1245,20 @@ static int __init early_platform_driver_probe_id(char *class_str, * rest of the driver core is initialized. */ if (!match->dev.init_name) { - char buf[32]; - if (match->id != -1) - snprintf(buf, sizeof(buf), "%s.%d", - match->name, match->id); + match->dev.init_name = + kasprintf(GFP_KERNEL, "%s.%d", + match->name, + match->id); else - snprintf(buf, sizeof(buf), "%s", - match->name); + match->dev.init_name = + kasprintf(GFP_KERNEL, "%s", + match->name); - match->dev.init_name = kstrdup(buf, GFP_KERNEL); if (!match->dev.init_name) return -ENOMEM; } + if (epdrv->pdrv->probe(match)) pr_warning("%s: unable to probe %s early.\n", class_str, match->name); -- cgit v0.10.2 From c2a25e819717ea34e8f682d67a3fa76f4893395b Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 29 Mar 2010 16:55:43 +0900 Subject: clocksource: Deprecate clock string across the SH drivers. We want to get rid of the clock string from platform data entirely, depending on the clkdev-based clock lookup to do the right thing for us instead. This converts all of the SH drivers to request their associated function clocks directly, and if there is no match for that then we fall back on the legacy lookup while warning about it. After all of the outstanding CPUs have been converted to clkdev lookups the clock string will be killed off completely. Signed-off-by: Paul Mundt diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index a1d3811..c5f6617 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -608,11 +608,15 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL; /* get hold of clock */ - p->clk = clk_get(&p->pdev->dev, cfg->clk); + p->clk = clk_get(&p->pdev->dev, "cmt_fck"); if (IS_ERR(p->clk)) { - dev_err(&p->pdev->dev, "cannot get clock\n"); - ret = PTR_ERR(p->clk); - goto err1; + dev_warn(&p->pdev->dev, "using deprecated clock lookup\n"); + p->clk = clk_get(&p->pdev->dev, cfg->clk); + if (IS_ERR(p->clk)) { + dev_err(&p->pdev->dev, "cannot get clock\n"); + ret = PTR_ERR(p->clk); + goto err1; + } } if (resource_size(res) == 6) { diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c index 8ce3555..b11882e 100644 --- a/drivers/clocksource/sh_mtu2.c +++ b/drivers/clocksource/sh_mtu2.c @@ -283,11 +283,15 @@ static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev) p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL; /* get hold of clock */ - p->clk = clk_get(&p->pdev->dev, cfg->clk); + p->clk = clk_get(&p->pdev->dev, "mtu2_fck"); if (IS_ERR(p->clk)) { - dev_err(&p->pdev->dev, "cannot get clock\n"); - ret = PTR_ERR(p->clk); - goto err1; + dev_warn(&p->pdev->dev, "using deprecated clock lookup\n"); + p->clk = clk_get(&p->pdev->dev, cfg->clk); + if (IS_ERR(p->clk)) { + dev_err(&p->pdev->dev, "cannot get clock\n"); + ret = PTR_ERR(p->clk); + goto err1; + } } return sh_mtu2_register(p, (char *)dev_name(&p->pdev->dev), diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c index 3423945..6b62283 100644 --- a/drivers/clocksource/sh_tmu.c +++ b/drivers/clocksource/sh_tmu.c @@ -387,11 +387,15 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev) p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL; /* get hold of clock */ - p->clk = clk_get(&p->pdev->dev, cfg->clk); + p->clk = clk_get(&p->pdev->dev, "tmu_fck"); if (IS_ERR(p->clk)) { - dev_err(&p->pdev->dev, "cannot get clock\n"); - ret = PTR_ERR(p->clk); - goto err1; + dev_warn(&p->pdev->dev, "using deprecated clock lookup\n"); + p->clk = clk_get(&p->pdev->dev, cfg->clk); + if (IS_ERR(p->clk)) { + dev_err(&p->pdev->dev, "cannot get clock\n"); + ret = PTR_ERR(p->clk); + goto err1; + } } return sh_tmu_register(p, (char *)dev_name(&p->pdev->dev), -- cgit v0.10.2 From e21d2aa76e1fc91cbf18c4b593d32112d954fab5 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 29 Mar 2010 17:03:15 +0900 Subject: sh: sh7786 clkdev lookups. This plugs in clkdev lookups for the SH7786 clocks and migrates off of clock string usage for the TMU clocks. Previously the TMU clocks were aliased to the peripheral clock, so this gets the driver actually toggling the proper clocks now as well. Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c index 85e8d57..c4a84bb 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include #include @@ -120,12 +122,78 @@ static struct clk mstp_clks[] = { SH_CLK_MSTP32("ether_fck", -1, NULL, MSTPCR1, 2, 0), }; +static struct clk_lookup lookups[] = { + { + /* TMU0 */ + .dev_id = "sh_tmu.0", + .con_id = "tmu_fck", + .clk = &mstp_clks[17], /* tmu012_fck */ + }, { + /* TMU1 */ + .dev_id = "sh_tmu.1", + .con_id = "tmu_fck", + .clk = &mstp_clks[17], + }, { + /* TMU2 */ + .dev_id = "sh_tmu.2", + .con_id = "tmu_fck", + .clk = &mstp_clks[17], + }, { + /* TMU3 */ + .dev_id = "sh_tmu.3", + .con_id = "tmu_fck", + .clk = &mstp_clks[16], /* tmu345_fck */ + }, { + /* TMU4 */ + .dev_id = "sh_tmu.4", + .con_id = "tmu_fck", + .clk = &mstp_clks[16], + }, { + /* TMU5 */ + .dev_id = "sh_tmu.5", + .con_id = "tmu_fck", + .clk = &mstp_clks[16], + }, { + /* TMU6 */ + .dev_id = "sh_tmu.6", + .con_id = "tmu_fck", + .clk = &mstp_clks[15], /* tmu678_fck */ + }, { + /* TMU7 */ + .dev_id = "sh_tmu.7", + .con_id = "tmu_fck", + .clk = &mstp_clks[15], + }, { + /* TMU8 */ + .dev_id = "sh_tmu.8", + .con_id = "tmu_fck", + .clk = &mstp_clks[15], + }, { + /* TMU9 */ + .dev_id = "sh_tmu.9", + .con_id = "tmu_fck", + .clk = &mstp_clks[14], /* tmu9_11_fck */ + }, { + /* TMU10 */ + .dev_id = "sh_tmu.10", + .con_id = "tmu_fck", + .clk = &mstp_clks[14], + }, { + /* TMU11 */ + .dev_id = "sh_tmu.11", + .con_id = "tmu_fck", + .clk = &mstp_clks[14], + } +}; + int __init arch_clk_init(void) { int i, ret = 0; for (i = 0; i < ARRAY_SIZE(clks); i++) ret |= clk_register(clks[i]); + for (i = 0; i < ARRAY_SIZE(lookups); i++) + clkdev_add(&lookups[i]); if (!ret) ret = sh_clk_div4_register(div4_clks, ARRAY_SIZE(div4_clks), diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c index 542ced8..f559990 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c @@ -119,7 +119,6 @@ static struct platform_device scif5_device = { static struct sh_timer_config tmu0_platform_data = { .channel_offset = 0x04, .timer_bit = 0, - .clk = "peripheral_clk", .clockevent_rating = 200, }; @@ -148,7 +147,6 @@ static struct platform_device tmu0_device = { static struct sh_timer_config tmu1_platform_data = { .channel_offset = 0x10, .timer_bit = 1, - .clk = "peripheral_clk", .clocksource_rating = 200, }; @@ -177,7 +175,6 @@ static struct platform_device tmu1_device = { static struct sh_timer_config tmu2_platform_data = { .channel_offset = 0x1c, .timer_bit = 2, - .clk = "peripheral_clk", }; static struct resource tmu2_resources[] = { @@ -205,7 +202,6 @@ static struct platform_device tmu2_device = { static struct sh_timer_config tmu3_platform_data = { .channel_offset = 0x04, .timer_bit = 0, - .clk = "peripheral_clk", }; static struct resource tmu3_resources[] = { @@ -233,7 +229,6 @@ static struct platform_device tmu3_device = { static struct sh_timer_config tmu4_platform_data = { .channel_offset = 0x10, .timer_bit = 1, - .clk = "peripheral_clk", }; static struct resource tmu4_resources[] = { @@ -261,7 +256,6 @@ static struct platform_device tmu4_device = { static struct sh_timer_config tmu5_platform_data = { .channel_offset = 0x1c, .timer_bit = 2, - .clk = "peripheral_clk", }; static struct resource tmu5_resources[] = { @@ -289,7 +283,6 @@ static struct platform_device tmu5_device = { static struct sh_timer_config tmu6_platform_data = { .channel_offset = 0x04, .timer_bit = 0, - .clk = "peripheral_clk", }; static struct resource tmu6_resources[] = { @@ -317,7 +310,6 @@ static struct platform_device tmu6_device = { static struct sh_timer_config tmu7_platform_data = { .channel_offset = 0x10, .timer_bit = 1, - .clk = "peripheral_clk", }; static struct resource tmu7_resources[] = { @@ -345,7 +337,6 @@ static struct platform_device tmu7_device = { static struct sh_timer_config tmu8_platform_data = { .channel_offset = 0x1c, .timer_bit = 2, - .clk = "peripheral_clk", }; static struct resource tmu8_resources[] = { @@ -373,7 +364,6 @@ static struct platform_device tmu8_device = { static struct sh_timer_config tmu9_platform_data = { .channel_offset = 0x04, .timer_bit = 0, - .clk = "peripheral_clk", }; static struct resource tmu9_resources[] = { @@ -401,7 +391,6 @@ static struct platform_device tmu9_device = { static struct sh_timer_config tmu10_platform_data = { .channel_offset = 0x10, .timer_bit = 1, - .clk = "peripheral_clk", }; static struct resource tmu10_resources[] = { @@ -429,7 +418,6 @@ static struct platform_device tmu10_device = { static struct sh_timer_config tmu11_platform_data = { .channel_offset = 0x1c, .timer_bit = 2, - .clk = "peripheral_clk", }; static struct resource tmu11_resources[] = { -- cgit v0.10.2 From c55fbdd3f97a468d51cbdb03bb7c9c7287fbda2f Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 29 Mar 2010 17:10:06 +0900 Subject: sh: sh7785 clkdev lookups. Convert to TMU clock lookups for SH7785. Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c index 6061c73..28de049 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c @@ -3,7 +3,7 @@ * * SH7785 support for the clock framework * - * Copyright (C) 2007 - 2009 Paul Mundt + * Copyright (C) 2007 - 2010 Paul Mundt * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -113,12 +114,48 @@ static struct clk mstp_clks[] = { SH_CLK_MSTP32("gdta_fck", -1, NULL, MSTPCR1, 0, 0), }; +static struct clk_lookup lookups[] = { + { + /* TMU0 */ + .dev_id = "sh_tmu.0", + .con_id = "tmu_fck", + .clk = &mstp_clks[13], /* tmu012_fck */ + }, { + /* TMU1 */ + .dev_id = "sh_tmu.1", + .con_id = "tmu_fck", + .clk = &mstp_clks[13], + }, { + /* TMU2 */ + .dev_id = "sh_tmu.2", + .con_id = "tmu_fck", + .clk = &mstp_clks[13], + }, { + /* TMU3 */ + .dev_id = "sh_tmu.3", + .con_id = "tmu_fck", + .clk = &mstp_clks[12], /* tmu345_fck */ + }, { + /* TMU4 */ + .dev_id = "sh_tmu.4", + .con_id = "tmu_fck", + .clk = &mstp_clks[12], + }, { + /* TMU5 */ + .dev_id = "sh_tmu.5", + .con_id = "tmu_fck", + .clk = &mstp_clks[12], + }, +}; + int __init arch_clk_init(void) { int i, ret = 0; for (i = 0; i < ARRAY_SIZE(clks); i++) ret |= clk_register(clks[i]); + for (i = 0; i < ARRAY_SIZE(lookups); i++) + clkdev_add(&lookups[i]); if (!ret) ret = sh_clk_div4_register(div4_clks, ARRAY_SIZE(div4_clks), diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c index 76afe57..07bb2d4 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c @@ -113,7 +113,6 @@ static struct platform_device scif5_device = { static struct sh_timer_config tmu0_platform_data = { .channel_offset = 0x04, .timer_bit = 0, - .clk = "tmu012_fck", .clockevent_rating = 200, }; @@ -142,7 +141,6 @@ static struct platform_device tmu0_device = { static struct sh_timer_config tmu1_platform_data = { .channel_offset = 0x10, .timer_bit = 1, - .clk = "tmu012_fck", .clocksource_rating = 200, }; @@ -171,7 +169,6 @@ static struct platform_device tmu1_device = { static struct sh_timer_config tmu2_platform_data = { .channel_offset = 0x1c, .timer_bit = 2, - .clk = "tmu012_fck", }; static struct resource tmu2_resources[] = { @@ -199,7 +196,6 @@ static struct platform_device tmu2_device = { static struct sh_timer_config tmu3_platform_data = { .channel_offset = 0x04, .timer_bit = 0, - .clk = "tmu345_fck", }; static struct resource tmu3_resources[] = { @@ -227,7 +223,6 @@ static struct platform_device tmu3_device = { static struct sh_timer_config tmu4_platform_data = { .channel_offset = 0x10, .timer_bit = 1, - .clk = "tmu345_fck", }; static struct resource tmu4_resources[] = { @@ -255,7 +250,6 @@ static struct platform_device tmu4_device = { static struct sh_timer_config tmu5_platform_data = { .channel_offset = 0x1c, .timer_bit = 2, - .clk = "tmu345_fck", }; static struct resource tmu5_resources[] = { -- cgit v0.10.2 From 0776d602abe61871d27accd8e3bcb225a96f4a9f Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 29 Mar 2010 17:22:50 +0900 Subject: sh: provide some clock lookup aliases for legacy CPG parts. For the CPUs that have not yet been converted off of legacy CPG we provide some pclk aliases in order to make driver migration easier. Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/clock-cpg.c b/arch/sh/kernel/cpu/clock-cpg.c index eed5eaf..17a73ad 100644 --- a/arch/sh/kernel/cpu/clock-cpg.c +++ b/arch/sh/kernel/cpu/clock-cpg.c @@ -338,6 +338,11 @@ int __init __deprecated cpg_clk_init(void) ret |= clk_register(clk); } + clk_add_alias("tmu_fck", NULL, "peripheral_clk", NULL); + clk_add_alias("mtu2_fck", NULL, "peripheral_clk", NULL); + clk_add_alias("cmt_fck", NULL, "peripheral_clk", NULL); + clk_add_alias("sci_ick", NULL, "peripheral_clk", NULL); + return ret; } -- cgit v0.10.2 From 4dc50a068ad8fbbd2dd6dd5ac8ac2652589ba046 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 29 Mar 2010 17:25:03 +0900 Subject: sh: Kill off timer clock strings for legacy CPG parts. Now with the lookup aliases in place there is no longer any need to provide the clock string, kill it off for all legacy CPG CPUs. Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh2/setup-sh7619.c b/arch/sh/kernel/cpu/sh2/setup-sh7619.c index 9b96457..c363851 100644 --- a/arch/sh/kernel/cpu/sh2/setup-sh7619.c +++ b/arch/sh/kernel/cpu/sh2/setup-sh7619.c @@ -130,7 +130,6 @@ static struct platform_device eth_device = { static struct sh_timer_config cmt0_platform_data = { .channel_offset = 0x02, .timer_bit = 0, - .clk = "peripheral_clk", .clockevent_rating = 125, .clocksource_rating = 0, /* disabled due to code generation issues */ }; @@ -160,7 +159,6 @@ static struct platform_device cmt0_device = { static struct sh_timer_config cmt1_platform_data = { .channel_offset = 0x08, .timer_bit = 1, - .clk = "peripheral_clk", .clockevent_rating = 125, .clocksource_rating = 0, /* disabled due to code generation issues */ }; diff --git a/arch/sh/kernel/cpu/sh2a/setup-mxg.c b/arch/sh/kernel/cpu/sh2a/setup-mxg.c index 5301450..6c96ea0 100644 --- a/arch/sh/kernel/cpu/sh2a/setup-mxg.c +++ b/arch/sh/kernel/cpu/sh2a/setup-mxg.c @@ -117,7 +117,6 @@ static DECLARE_INTC_DESC(intc_desc, "mxg", vectors, groups, static struct sh_timer_config mtu2_0_platform_data = { .channel_offset = -0x80, .timer_bit = 0, - .clk = "peripheral_clk", .clockevent_rating = 200, }; @@ -146,7 +145,6 @@ static struct platform_device mtu2_0_device = { static struct sh_timer_config mtu2_1_platform_data = { .channel_offset = -0x100, .timer_bit = 1, - .clk = "peripheral_clk", .clockevent_rating = 200, }; @@ -175,7 +173,6 @@ static struct platform_device mtu2_1_device = { static struct sh_timer_config mtu2_2_platform_data = { .channel_offset = 0x80, .timer_bit = 2, - .clk = "peripheral_clk", .clockevent_rating = 200, }; diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7201.c b/arch/sh/kernel/cpu/sh2a/setup-sh7201.c index 5b07ab5..d08bf4c 100644 --- a/arch/sh/kernel/cpu/sh2a/setup-sh7201.c +++ b/arch/sh/kernel/cpu/sh2a/setup-sh7201.c @@ -320,7 +320,6 @@ static struct platform_device rtc_device = { static struct sh_timer_config mtu2_0_platform_data = { .channel_offset = -0x80, .timer_bit = 0, - .clk = "peripheral_clk", .clockevent_rating = 200, }; @@ -349,7 +348,6 @@ static struct platform_device mtu2_0_device = { static struct sh_timer_config mtu2_1_platform_data = { .channel_offset = -0x100, .timer_bit = 1, - .clk = "peripheral_clk", .clockevent_rating = 200, }; @@ -378,7 +376,6 @@ static struct platform_device mtu2_1_device = { static struct sh_timer_config mtu2_2_platform_data = { .channel_offset = 0x80, .timer_bit = 2, - .clk = "peripheral_clk", .clockevent_rating = 200, }; diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7203.c b/arch/sh/kernel/cpu/sh2a/setup-sh7203.c index 433ac53..832f401 100644 --- a/arch/sh/kernel/cpu/sh2a/setup-sh7203.c +++ b/arch/sh/kernel/cpu/sh2a/setup-sh7203.c @@ -236,7 +236,6 @@ static struct platform_device scif3_device = { static struct sh_timer_config cmt0_platform_data = { .channel_offset = 0x02, .timer_bit = 0, - .clk = "peripheral_clk", .clockevent_rating = 125, .clocksource_rating = 0, /* disabled due to code generation issues */ }; @@ -266,7 +265,6 @@ static struct platform_device cmt0_device = { static struct sh_timer_config cmt1_platform_data = { .channel_offset = 0x08, .timer_bit = 1, - .clk = "peripheral_clk", .clockevent_rating = 125, .clocksource_rating = 0, /* disabled due to code generation issues */ }; @@ -296,7 +294,6 @@ static struct platform_device cmt1_device = { static struct sh_timer_config mtu2_0_platform_data = { .channel_offset = -0x80, .timer_bit = 0, - .clk = "peripheral_clk", .clockevent_rating = 200, }; @@ -325,7 +322,6 @@ static struct platform_device mtu2_0_device = { static struct sh_timer_config mtu2_1_platform_data = { .channel_offset = -0x100, .timer_bit = 1, - .clk = "peripheral_clk", .clockevent_rating = 200, }; diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c index 8caecb4..dc47b04 100644 --- a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c +++ b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c @@ -196,7 +196,6 @@ static struct platform_device scif3_device = { static struct sh_timer_config cmt0_platform_data = { .channel_offset = 0x02, .timer_bit = 0, - .clk = "peripheral_clk", .clockevent_rating = 125, .clocksource_rating = 0, /* disabled due to code generation issues */ }; @@ -226,7 +225,6 @@ static struct platform_device cmt0_device = { static struct sh_timer_config cmt1_platform_data = { .channel_offset = 0x08, .timer_bit = 1, - .clk = "peripheral_clk", .clockevent_rating = 125, .clocksource_rating = 0, /* disabled due to code generation issues */ }; @@ -256,7 +254,6 @@ static struct platform_device cmt1_device = { static struct sh_timer_config mtu2_0_platform_data = { .channel_offset = -0x80, .timer_bit = 0, - .clk = "peripheral_clk", .clockevent_rating = 200, }; @@ -285,7 +282,6 @@ static struct platform_device mtu2_0_device = { static struct sh_timer_config mtu2_1_platform_data = { .channel_offset = -0x100, .timer_bit = 1, - .clk = "peripheral_clk", .clockevent_rating = 200, }; @@ -314,7 +310,6 @@ static struct platform_device mtu2_1_device = { static struct sh_timer_config mtu2_2_platform_data = { .channel_offset = 0x80, .timer_bit = 2, - .clk = "peripheral_clk", .clockevent_rating = 200, }; diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7705.c b/arch/sh/kernel/cpu/sh3/setup-sh7705.c index 5e45fb7..baadd7f 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh7705.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh7705.c @@ -126,7 +126,6 @@ static struct platform_device rtc_device = { static struct sh_timer_config tmu0_platform_data = { .channel_offset = 0x02, .timer_bit = 0, - .clk = "peripheral_clk", .clockevent_rating = 200, }; @@ -155,7 +154,6 @@ static struct platform_device tmu0_device = { static struct sh_timer_config tmu1_platform_data = { .channel_offset = 0xe, .timer_bit = 1, - .clk = "peripheral_clk", .clocksource_rating = 200, }; @@ -184,7 +182,6 @@ static struct platform_device tmu1_device = { static struct sh_timer_config tmu2_platform_data = { .channel_offset = 0x1a, .timer_bit = 2, - .clk = "peripheral_clk", }; static struct resource tmu2_resources[] = { diff --git a/arch/sh/kernel/cpu/sh3/setup-sh770x.c b/arch/sh/kernel/cpu/sh3/setup-sh770x.c index 9adb853..3cf8c8e 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh770x.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh770x.c @@ -159,7 +159,6 @@ static struct platform_device scif2_device = { static struct sh_timer_config tmu0_platform_data = { .channel_offset = 0x02, .timer_bit = 0, - .clk = "peripheral_clk", .clockevent_rating = 200, }; @@ -188,7 +187,6 @@ static struct platform_device tmu0_device = { static struct sh_timer_config tmu1_platform_data = { .channel_offset = 0xe, .timer_bit = 1, - .clk = "peripheral_clk", .clocksource_rating = 200, }; @@ -217,7 +215,6 @@ static struct platform_device tmu1_device = { static struct sh_timer_config tmu2_platform_data = { .channel_offset = 0x1a, .timer_bit = 2, - .clk = "peripheral_clk", }; static struct resource tmu2_resources[] = { diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7710.c b/arch/sh/kernel/cpu/sh3/setup-sh7710.c index 2e581e3..b0c2fb4 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh7710.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh7710.c @@ -129,7 +129,6 @@ static struct platform_device scif1_device = { static struct sh_timer_config tmu0_platform_data = { .channel_offset = 0x02, .timer_bit = 0, - .clk = "peripheral_clk", .clockevent_rating = 200, }; @@ -158,7 +157,6 @@ static struct platform_device tmu0_device = { static struct sh_timer_config tmu1_platform_data = { .channel_offset = 0xe, .timer_bit = 1, - .clk = "peripheral_clk", .clocksource_rating = 200, }; @@ -187,7 +185,6 @@ static struct platform_device tmu1_device = { static struct sh_timer_config tmu2_platform_data = { .channel_offset = 0x1a, .timer_bit = 2, - .clk = "peripheral_clk", }; static struct resource tmu2_resources[] = { diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7720.c b/arch/sh/kernel/cpu/sh3/setup-sh7720.c index 9a006e1..24b1713 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh7720.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh7720.c @@ -132,7 +132,6 @@ static struct platform_device usbf_device = { static struct sh_timer_config cmt0_platform_data = { .channel_offset = 0x10, .timer_bit = 0, - .clk = "peripheral_clk", .clockevent_rating = 125, .clocksource_rating = 125, }; @@ -162,7 +161,6 @@ static struct platform_device cmt0_device = { static struct sh_timer_config cmt1_platform_data = { .channel_offset = 0x20, .timer_bit = 1, - .clk = "peripheral_clk", }; static struct resource cmt1_resources[] = { @@ -190,7 +188,6 @@ static struct platform_device cmt1_device = { static struct sh_timer_config cmt2_platform_data = { .channel_offset = 0x30, .timer_bit = 2, - .clk = "peripheral_clk", }; static struct resource cmt2_resources[] = { @@ -218,7 +215,6 @@ static struct platform_device cmt2_device = { static struct sh_timer_config cmt3_platform_data = { .channel_offset = 0x40, .timer_bit = 3, - .clk = "peripheral_clk", }; static struct resource cmt3_resources[] = { @@ -246,7 +242,6 @@ static struct platform_device cmt3_device = { static struct sh_timer_config cmt4_platform_data = { .channel_offset = 0x50, .timer_bit = 4, - .clk = "peripheral_clk", }; static struct resource cmt4_resources[] = { @@ -274,7 +269,6 @@ static struct platform_device cmt4_device = { static struct sh_timer_config tmu0_platform_data = { .channel_offset = 0x02, .timer_bit = 0, - .clk = "peripheral_clk", .clockevent_rating = 200, }; @@ -303,7 +297,6 @@ static struct platform_device tmu0_device = { static struct sh_timer_config tmu1_platform_data = { .channel_offset = 0xe, .timer_bit = 1, - .clk = "peripheral_clk", .clocksource_rating = 200, }; @@ -332,7 +325,6 @@ static struct platform_device tmu1_device = { static struct sh_timer_config tmu2_platform_data = { .channel_offset = 0x1a, .timer_bit = 2, - .clk = "peripheral_clk", }; static struct resource tmu2_resources[] = { diff --git a/arch/sh/kernel/cpu/sh4/setup-sh4-202.c b/arch/sh/kernel/cpu/sh4/setup-sh4-202.c index 223d066..e916b18 100644 --- a/arch/sh/kernel/cpu/sh4/setup-sh4-202.c +++ b/arch/sh/kernel/cpu/sh4/setup-sh4-202.c @@ -33,7 +33,6 @@ static struct platform_device scif0_device = { static struct sh_timer_config tmu0_platform_data = { .channel_offset = 0x04, .timer_bit = 0, - .clk = "peripheral_clk", .clockevent_rating = 200, }; @@ -62,7 +61,6 @@ static struct platform_device tmu0_device = { static struct sh_timer_config tmu1_platform_data = { .channel_offset = 0x10, .timer_bit = 1, - .clk = "peripheral_clk", .clocksource_rating = 200, }; @@ -91,7 +89,6 @@ static struct platform_device tmu1_device = { static struct sh_timer_config tmu2_platform_data = { .channel_offset = 0x1c, .timer_bit = 2, - .clk = "peripheral_clk", }; static struct resource tmu2_resources[] = { diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7750.c b/arch/sh/kernel/cpu/sh4/setup-sh7750.c index 2f337b1..911d196 100644 --- a/arch/sh/kernel/cpu/sh4/setup-sh7750.c +++ b/arch/sh/kernel/cpu/sh4/setup-sh7750.c @@ -68,7 +68,6 @@ static struct platform_device scif1_device = { static struct sh_timer_config tmu0_platform_data = { .channel_offset = 0x04, .timer_bit = 0, - .clk = "peripheral_clk", .clockevent_rating = 200, }; @@ -97,7 +96,6 @@ static struct platform_device tmu0_device = { static struct sh_timer_config tmu1_platform_data = { .channel_offset = 0x10, .timer_bit = 1, - .clk = "peripheral_clk", .clocksource_rating = 200, }; @@ -126,7 +124,6 @@ static struct platform_device tmu1_device = { static struct sh_timer_config tmu2_platform_data = { .channel_offset = 0x1c, .timer_bit = 2, - .clk = "peripheral_clk", }; static struct resource tmu2_resources[] = { @@ -159,7 +156,6 @@ static struct platform_device tmu2_device = { static struct sh_timer_config tmu3_platform_data = { .channel_offset = 0x04, .timer_bit = 0, - .clk = "peripheral_clk", }; static struct resource tmu3_resources[] = { @@ -187,7 +183,6 @@ static struct platform_device tmu3_device = { static struct sh_timer_config tmu4_platform_data = { .channel_offset = 0x10, .timer_bit = 1, - .clk = "peripheral_clk", }; static struct resource tmu4_resources[] = { diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7760.c b/arch/sh/kernel/cpu/sh4/setup-sh7760.c index fa43da0..48ea8fe 100644 --- a/arch/sh/kernel/cpu/sh4/setup-sh7760.c +++ b/arch/sh/kernel/cpu/sh4/setup-sh7760.c @@ -189,7 +189,6 @@ static struct platform_device scif3_device = { static struct sh_timer_config tmu0_platform_data = { .channel_offset = 0x04, .timer_bit = 0, - .clk = "peripheral_clk", .clockevent_rating = 200, }; @@ -218,7 +217,6 @@ static struct platform_device tmu0_device = { static struct sh_timer_config tmu1_platform_data = { .channel_offset = 0x10, .timer_bit = 1, - .clk = "peripheral_clk", .clocksource_rating = 200, }; @@ -247,7 +245,6 @@ static struct platform_device tmu1_device = { static struct sh_timer_config tmu2_platform_data = { .channel_offset = 0x1c, .timer_bit = 2, - .clk = "peripheral_clk", }; static struct resource tmu2_resources[] = { diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c index 25eddf2..444aca9 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c @@ -65,7 +65,6 @@ static struct platform_device scif4_device = { static struct sh_timer_config tmu0_platform_data = { .channel_offset = 0x04, .timer_bit = 0, - .clk = "peripheral_clk", .clockevent_rating = 200, }; @@ -94,7 +93,6 @@ static struct platform_device tmu0_device = { static struct sh_timer_config tmu1_platform_data = { .channel_offset = 0x10, .timer_bit = 1, - .clk = "peripheral_clk", .clocksource_rating = 200, }; diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7763.c b/arch/sh/kernel/cpu/sh4a/setup-sh7763.c index a91263e..5b5f6b0 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7763.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7763.c @@ -133,7 +133,6 @@ static struct platform_device usbf_device = { static struct sh_timer_config tmu0_platform_data = { .channel_offset = 0x04, .timer_bit = 0, - .clk = "peripheral_clk", .clockevent_rating = 200, }; @@ -162,7 +161,6 @@ static struct platform_device tmu0_device = { static struct sh_timer_config tmu1_platform_data = { .channel_offset = 0x10, .timer_bit = 1, - .clk = "peripheral_clk", .clocksource_rating = 200, }; @@ -191,7 +189,6 @@ static struct platform_device tmu1_device = { static struct sh_timer_config tmu2_platform_data = { .channel_offset = 0x1c, .timer_bit = 2, - .clk = "peripheral_clk", }; static struct resource tmu2_resources[] = { @@ -219,7 +216,6 @@ static struct platform_device tmu2_device = { static struct sh_timer_config tmu3_platform_data = { .channel_offset = 0x04, .timer_bit = 0, - .clk = "peripheral_clk", }; static struct resource tmu3_resources[] = { @@ -247,7 +243,6 @@ static struct platform_device tmu3_device = { static struct sh_timer_config tmu4_platform_data = { .channel_offset = 0x10, .timer_bit = 1, - .clk = "peripheral_clk", }; static struct resource tmu4_resources[] = { @@ -275,7 +270,6 @@ static struct platform_device tmu4_device = { static struct sh_timer_config tmu5_platform_data = { .channel_offset = 0x1c, .timer_bit = 2, - .clk = "peripheral_clk", }; static struct resource tmu5_resources[] = { diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7770.c b/arch/sh/kernel/cpu/sh4a/setup-sh7770.c index 83a27b0..7270d7f 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7770.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7770.c @@ -167,7 +167,6 @@ static struct platform_device scif9_device = { static struct sh_timer_config tmu0_platform_data = { .channel_offset = 0x04, .timer_bit = 0, - .clk = "peripheral_clk", .clockevent_rating = 200, }; @@ -196,7 +195,6 @@ static struct platform_device tmu0_device = { static struct sh_timer_config tmu1_platform_data = { .channel_offset = 0x10, .timer_bit = 1, - .clk = "peripheral_clk", .clocksource_rating = 200, }; @@ -225,7 +223,6 @@ static struct platform_device tmu1_device = { static struct sh_timer_config tmu2_platform_data = { .channel_offset = 0x1c, .timer_bit = 2, - .clk = "peripheral_clk", }; static struct resource tmu2_resources[] = { @@ -253,7 +250,6 @@ static struct platform_device tmu2_device = { static struct sh_timer_config tmu3_platform_data = { .channel_offset = 0x04, .timer_bit = 0, - .clk = "peripheral_clk", }; static struct resource tmu3_resources[] = { @@ -281,7 +277,6 @@ static struct platform_device tmu3_device = { static struct sh_timer_config tmu4_platform_data = { .channel_offset = 0x10, .timer_bit = 1, - .clk = "peripheral_clk", }; static struct resource tmu4_resources[] = { @@ -309,7 +304,6 @@ static struct platform_device tmu4_device = { static struct sh_timer_config tmu5_platform_data = { .channel_offset = 0x1c, .timer_bit = 2, - .clk = "peripheral_clk", }; static struct resource tmu5_resources[] = { @@ -337,7 +331,6 @@ static struct platform_device tmu5_device = { static struct sh_timer_config tmu6_platform_data = { .channel_offset = 0x04, .timer_bit = 0, - .clk = "peripheral_clk", }; static struct resource tmu6_resources[] = { @@ -365,7 +358,6 @@ static struct platform_device tmu6_device = { static struct sh_timer_config tmu7_platform_data = { .channel_offset = 0x10, .timer_bit = 1, - .clk = "peripheral_clk", }; static struct resource tmu7_resources[] = { @@ -393,7 +385,6 @@ static struct platform_device tmu7_device = { static struct sh_timer_config tmu8_platform_data = { .channel_offset = 0x1c, .timer_bit = 2, - .clk = "peripheral_clk", }; static struct resource tmu8_resources[] = { diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c index f7c48e92..05fc38d 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c @@ -51,7 +51,6 @@ static struct platform_device scif1_device = { static struct sh_timer_config tmu0_platform_data = { .channel_offset = 0x04, .timer_bit = 0, - .clk = "peripheral_clk", .clockevent_rating = 200, }; @@ -80,7 +79,6 @@ static struct platform_device tmu0_device = { static struct sh_timer_config tmu1_platform_data = { .channel_offset = 0x10, .timer_bit = 1, - .clk = "peripheral_clk", .clocksource_rating = 200, }; @@ -109,7 +107,6 @@ static struct platform_device tmu1_device = { static struct sh_timer_config tmu2_platform_data = { .channel_offset = 0x1c, .timer_bit = 2, - .clk = "peripheral_clk", }; static struct resource tmu2_resources[] = { @@ -137,7 +134,6 @@ static struct platform_device tmu2_device = { static struct sh_timer_config tmu3_platform_data = { .channel_offset = 0x04, .timer_bit = 0, - .clk = "peripheral_clk", }; static struct resource tmu3_resources[] = { @@ -165,7 +161,6 @@ static struct platform_device tmu3_device = { static struct sh_timer_config tmu4_platform_data = { .channel_offset = 0x10, .timer_bit = 1, - .clk = "peripheral_clk", }; static struct resource tmu4_resources[] = { @@ -193,7 +188,6 @@ static struct platform_device tmu4_device = { static struct sh_timer_config tmu5_platform_data = { .channel_offset = 0x1c, .timer_bit = 2, - .clk = "peripheral_clk", }; static struct resource tmu5_resources[] = { diff --git a/arch/sh/kernel/cpu/sh4a/setup-shx3.c b/arch/sh/kernel/cpu/sh4a/setup-shx3.c index ba545b5..9158bc5 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-shx3.c +++ b/arch/sh/kernel/cpu/sh4a/setup-shx3.c @@ -72,7 +72,6 @@ static struct platform_device scif2_device = { static struct sh_timer_config tmu0_platform_data = { .channel_offset = 0x04, .timer_bit = 0, - .clk = "peripheral_clk", .clockevent_rating = 200, }; @@ -101,7 +100,6 @@ static struct platform_device tmu0_device = { static struct sh_timer_config tmu1_platform_data = { .channel_offset = 0x10, .timer_bit = 1, - .clk = "peripheral_clk", .clocksource_rating = 200, }; @@ -130,7 +128,6 @@ static struct platform_device tmu1_device = { static struct sh_timer_config tmu2_platform_data = { .channel_offset = 0x1c, .timer_bit = 2, - .clk = "peripheral_clk", }; static struct resource tmu2_resources[] = { @@ -158,7 +155,6 @@ static struct platform_device tmu2_device = { static struct sh_timer_config tmu3_platform_data = { .channel_offset = 0x04, .timer_bit = 0, - .clk = "peripheral_clk", }; static struct resource tmu3_resources[] = { @@ -186,7 +182,6 @@ static struct platform_device tmu3_device = { static struct sh_timer_config tmu4_platform_data = { .channel_offset = 0x10, .timer_bit = 1, - .clk = "peripheral_clk", }; static struct resource tmu4_resources[] = { @@ -214,7 +209,6 @@ static struct platform_device tmu4_device = { static struct sh_timer_config tmu5_platform_data = { .channel_offset = 0x1c, .timer_bit = 2, - .clk = "peripheral_clk", }; static struct resource tmu5_resources[] = { diff --git a/arch/sh/kernel/cpu/sh5/setup-sh5.c b/arch/sh/kernel/cpu/sh5/setup-sh5.c index c84ca20..d910666 100644 --- a/arch/sh/kernel/cpu/sh5/setup-sh5.c +++ b/arch/sh/kernel/cpu/sh5/setup-sh5.c @@ -70,7 +70,6 @@ static struct platform_device rtc_device = { static struct sh_timer_config tmu0_platform_data = { .channel_offset = 0x04, .timer_bit = 0, - .clk = "peripheral_clk", .clockevent_rating = 200, }; @@ -99,7 +98,6 @@ static struct platform_device tmu0_device = { static struct sh_timer_config tmu1_platform_data = { .channel_offset = 0x10, .timer_bit = 1, - .clk = "peripheral_clk", .clocksource_rating = 200, }; @@ -128,7 +126,6 @@ static struct platform_device tmu1_device = { static struct sh_timer_config tmu2_platform_data = { .channel_offset = 0x1c, .timer_bit = 2, - .clk = "peripheral_clk", }; static struct resource tmu2_resources[] = { -- cgit v0.10.2 From 5afdd0d93a32938752384f195fdbde06163b3c2e Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 29 Mar 2010 17:35:04 +0900 Subject: sh: sh7343 clock string death. Kills off clock string usage, using the new function clock definition instead. Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c index c541301..a63cdca 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c @@ -154,8 +154,8 @@ static struct clk mstp_clks[] = { MSTP("sh0", &div4_clks[DIV4_P], MSTPCR0, 20, 0), MSTP("hudi0", &div4_clks[DIV4_P], MSTPCR0, 19, 0), MSTP("ubc0", &div4_clks[DIV4_P], MSTPCR0, 17, 0), - MSTP("tmu0", &div4_clks[DIV4_P], MSTPCR0, 15, 0), - MSTP("cmt0", &r_clk, MSTPCR0, 14, 0), + MSTP("tmu_fck", &div4_clks[DIV4_P], MSTPCR0, 15, 0), + MSTP("cmt_fck", &r_clk, MSTPCR0, 14, 0), MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0), MSTP("mfi0", &div4_clks[DIV4_P], MSTPCR0, 11, 0), MSTP("flctl0", &div4_clks[DIV4_P], MSTPCR0, 10, 0), diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c index 6f83949..3681cafd 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c @@ -205,7 +205,6 @@ static struct platform_device jpu_device = { static struct sh_timer_config cmt_platform_data = { .channel_offset = 0x60, .timer_bit = 5, - .clk = "cmt0", .clockevent_rating = 125, .clocksource_rating = 200, }; @@ -235,7 +234,6 @@ static struct platform_device cmt_device = { static struct sh_timer_config tmu0_platform_data = { .channel_offset = 0x04, .timer_bit = 0, - .clk = "tmu0", .clockevent_rating = 200, }; @@ -264,7 +262,6 @@ static struct platform_device tmu0_device = { static struct sh_timer_config tmu1_platform_data = { .channel_offset = 0x10, .timer_bit = 1, - .clk = "tmu0", .clocksource_rating = 200, }; @@ -293,7 +290,6 @@ static struct platform_device tmu1_device = { static struct sh_timer_config tmu2_platform_data = { .channel_offset = 0x1c, .timer_bit = 2, - .clk = "tmu0", }; static struct resource tmu2_resources[] = { -- cgit v0.10.2 From 2169bc1bae5d6d996276ddbd017f9d9b582abcae Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 29 Mar 2010 17:36:41 +0900 Subject: sh: sh7366 clock string death. Kills off clock string usage, using the new function clock definition instead. Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c index e10c64f..f99db94 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c @@ -158,8 +158,8 @@ static struct clk mstp_clks[] = { MSTP("sh0", &div4_clks[DIV4_P], MSTPCR0, 20, 0), MSTP("hudi0", &div4_clks[DIV4_P], MSTPCR0, 19, 0), MSTP("ubc0", &div4_clks[DIV4_P], MSTPCR0, 17, 0), - MSTP("tmu0", &div4_clks[DIV4_P], MSTPCR0, 15, 0), - MSTP("cmt0", &r_clk, MSTPCR0, 14, 0), + MSTP("tmu_fck", &div4_clks[DIV4_P], MSTPCR0, 15, 0), + MSTP("cmt_fck", &r_clk, MSTPCR0, 14, 0), MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0), MSTP("mfi0", &div4_clks[DIV4_P], MSTPCR0, 11, 0), MSTP("flctl0", &div4_clks[DIV4_P], MSTPCR0, 10, 0), diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c index 1d897ed..8dab9e1 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c @@ -170,7 +170,6 @@ static struct platform_device veu1_device = { static struct sh_timer_config cmt_platform_data = { .channel_offset = 0x60, .timer_bit = 5, - .clk = "cmt0", .clockevent_rating = 125, .clocksource_rating = 200, }; @@ -200,7 +199,6 @@ static struct platform_device cmt_device = { static struct sh_timer_config tmu0_platform_data = { .channel_offset = 0x04, .timer_bit = 0, - .clk = "tmu0", .clockevent_rating = 200, }; @@ -229,7 +227,6 @@ static struct platform_device tmu0_device = { static struct sh_timer_config tmu1_platform_data = { .channel_offset = 0x10, .timer_bit = 1, - .clk = "tmu0", .clocksource_rating = 200, }; @@ -258,7 +255,6 @@ static struct platform_device tmu1_device = { static struct sh_timer_config tmu2_platform_data = { .channel_offset = 0x1c, .timer_bit = 2, - .clk = "tmu0", }; static struct resource tmu2_resources[] = { -- cgit v0.10.2 From 04b1731766b22cd41a0acd480e3206e93f2d5931 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 29 Mar 2010 17:37:39 +0900 Subject: sh: sh7722 clock string death. Kills off clock string usage, using the new function clock definition instead. Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c index 0732c8b..107b200 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c @@ -160,8 +160,8 @@ struct clk div6_clks[] = { static struct clk mstp_clks[] = { SH_HWBLK_CLK("uram0", -1, U_CLK, HWBLK_URAM, CLK_ENABLE_ON_INIT), SH_HWBLK_CLK("xymem0", -1, B_CLK, HWBLK_XYMEM, CLK_ENABLE_ON_INIT), - SH_HWBLK_CLK("tmu0", -1, P_CLK, HWBLK_TMU, 0), - SH_HWBLK_CLK("cmt0", -1, R_CLK, HWBLK_CMT, 0), + SH_HWBLK_CLK("tmu_fck", -1, P_CLK, HWBLK_TMU, 0), + SH_HWBLK_CLK("cmt_fck", -1, R_CLK, HWBLK_CMT, 0), SH_HWBLK_CLK("rwdt0", -1, R_CLK, HWBLK_RWDT, 0), SH_HWBLK_CLK("flctl0", -1, P_CLK, HWBLK_FLCTL, 0), SH_HWBLK_CLK("sci_fck", 0, P_CLK, HWBLK_SCIF0, 0), diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c index 847a276..dc9b30d 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c @@ -400,7 +400,6 @@ static struct platform_device jpu_device = { static struct sh_timer_config cmt_platform_data = { .channel_offset = 0x60, .timer_bit = 5, - .clk = "cmt0", .clockevent_rating = 125, .clocksource_rating = 125, }; @@ -433,7 +432,6 @@ static struct platform_device cmt_device = { static struct sh_timer_config tmu0_platform_data = { .channel_offset = 0x04, .timer_bit = 0, - .clk = "tmu0", .clockevent_rating = 200, }; @@ -465,7 +463,6 @@ static struct platform_device tmu0_device = { static struct sh_timer_config tmu1_platform_data = { .channel_offset = 0x10, .timer_bit = 1, - .clk = "tmu0", .clocksource_rating = 200, }; @@ -497,7 +494,6 @@ static struct platform_device tmu1_device = { static struct sh_timer_config tmu2_platform_data = { .channel_offset = 0x1c, .timer_bit = 2, - .clk = "tmu0", }; static struct resource tmu2_resources[] = { -- cgit v0.10.2 From f4221802ea3a28f7c16d157ac6f697d58267cb58 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 29 Mar 2010 17:45:12 +0900 Subject: sh: sh7723 clkdev lookups. Convert to TMU clock lookups for SH7723. Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c index 4d4c123..fc86c88 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include #include #include @@ -171,11 +173,11 @@ static struct clk mstp_clks[] = { SH_HWBLK_CLK("sh0", -1, SH_CLK, HWBLK_SHYWAY, CLK_ENABLE_ON_INIT), SH_HWBLK_CLK("hudi0", -1, P_CLK, HWBLK_HUDI, 0), SH_HWBLK_CLK("ubc0", -1, I_CLK, HWBLK_UBC, 0), - SH_HWBLK_CLK("tmu0", -1, P_CLK, HWBLK_TMU0, 0), - SH_HWBLK_CLK("cmt0", -1, R_CLK, HWBLK_CMT, 0), + SH_HWBLK_CLK("tmu012_fck", -1, P_CLK, HWBLK_TMU0, 0), + SH_HWBLK_CLK("cmt_fck", -1, R_CLK, HWBLK_CMT, 0), SH_HWBLK_CLK("rwdt0", -1, R_CLK, HWBLK_RWDT, 0), SH_HWBLK_CLK("dmac1", -1, B_CLK, HWBLK_DMAC1, 0), - SH_HWBLK_CLK("tmu1", -1, P_CLK, HWBLK_TMU1, 0), + SH_HWBLK_CLK("tmu345_fck", -1, P_CLK, HWBLK_TMU1, 0), SH_HWBLK_CLK("flctl0", -1, P_CLK, HWBLK_FLCTL, 0), SH_HWBLK_CLK("sci_fck", 0, P_CLK, HWBLK_SCIF0, 0), SH_HWBLK_CLK("sci_fck", 1, P_CLK, HWBLK_SCIF1, 0), @@ -211,6 +213,40 @@ static struct clk mstp_clks[] = { SH_HWBLK_CLK("lcdc0", -1, B_CLK, HWBLK_LCDC, 0), }; +static struct clk_lookup lookups[] = { + { + /* TMU0 */ + .dev_id = "sh_tmu.0", + .con_id = "tmu_fck", + .clk = &mstp_clks[11], /* tmu012_fck */ + }, { + /* TMU1 */ + .dev_id = "sh_tmu.1", + .con_id = "tmu_fck", + .clk = &mstp_clks[11], + }, { + /* TMU2 */ + .dev_id = "sh_tmu.2", + .con_id = "tmu_fck", + .clk = &mstp_clks[11], + }, { + /* TMU3 */ + .dev_id = "sh_tmu.3", + .con_id = "tmu_fck", + .clk = &mstp_clks[15], /* tmu345_fck */ + }, { + /* TMU4 */ + .dev_id = "sh_tmu.4", + .con_id = "tmu_fck", + .clk = &mstp_clks[15], + }, { + /* TMU5 */ + .dev_id = "sh_tmu.5", + .con_id = "tmu_fck", + .clk = &mstp_clks[15], + }, +}; + int __init arch_clk_init(void) { int k, ret = 0; @@ -222,7 +258,9 @@ int __init arch_clk_init(void) pll_clk.parent = &extal_clk; for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++) - ret = clk_register(main_clks[k]); + ret |= clk_register(main_clks[k]); + + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); if (!ret) ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table); diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c index 187462b..0eadefd 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c @@ -207,7 +207,6 @@ static struct platform_device veu1_device = { static struct sh_timer_config cmt_platform_data = { .channel_offset = 0x60, .timer_bit = 5, - .clk = "cmt0", .clockevent_rating = 125, .clocksource_rating = 125, }; @@ -240,7 +239,6 @@ static struct platform_device cmt_device = { static struct sh_timer_config tmu0_platform_data = { .channel_offset = 0x04, .timer_bit = 0, - .clk = "tmu0", .clockevent_rating = 200, }; @@ -272,7 +270,6 @@ static struct platform_device tmu0_device = { static struct sh_timer_config tmu1_platform_data = { .channel_offset = 0x10, .timer_bit = 1, - .clk = "tmu0", .clocksource_rating = 200, }; @@ -304,7 +301,6 @@ static struct platform_device tmu1_device = { static struct sh_timer_config tmu2_platform_data = { .channel_offset = 0x1c, .timer_bit = 2, - .clk = "tmu0", }; static struct resource tmu2_resources[] = { @@ -335,7 +331,6 @@ static struct platform_device tmu2_device = { static struct sh_timer_config tmu3_platform_data = { .channel_offset = 0x04, .timer_bit = 0, - .clk = "tmu1", }; static struct resource tmu3_resources[] = { @@ -366,7 +361,6 @@ static struct platform_device tmu3_device = { static struct sh_timer_config tmu4_platform_data = { .channel_offset = 0x10, .timer_bit = 1, - .clk = "tmu1", }; static struct resource tmu4_resources[] = { @@ -397,7 +391,6 @@ static struct platform_device tmu4_device = { static struct sh_timer_config tmu5_platform_data = { .channel_offset = 0x1c, .timer_bit = 2, - .clk = "tmu1", }; static struct resource tmu5_resources[] = { -- cgit v0.10.2 From f4cff0d0ffc0162636357d0475409ecf1304f854 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 30 Mar 2010 11:20:35 +0900 Subject: sh: sh7724 clkdev lookups. Conver to TMU clock lookups for SH7724. Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c index bcf2b97..f1583a2 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include #include #include @@ -189,11 +191,11 @@ static struct clk mstp_clks[] = { SH_HWBLK_CLK("sh0", -1, SH_CLK, HWBLK_SHYWAY, CLK_ENABLE_ON_INIT), SH_HWBLK_CLK("hudi0", -1, P_CLK, HWBLK_HUDI, 0), SH_HWBLK_CLK("ubc0", -1, I_CLK, HWBLK_UBC, 0), - SH_HWBLK_CLK("tmu0", -1, P_CLK, HWBLK_TMU0, 0), - SH_HWBLK_CLK("cmt0", -1, R_CLK, HWBLK_CMT, 0), + SH_HWBLK_CLK("tmu012_fck", -1, P_CLK, HWBLK_TMU0, 0), + SH_HWBLK_CLK("cmt_fck", -1, R_CLK, HWBLK_CMT, 0), SH_HWBLK_CLK("rwdt0", -1, R_CLK, HWBLK_RWDT, 0), SH_HWBLK_CLK("dmac1", -1, B_CLK, HWBLK_DMAC1, 0), - SH_HWBLK_CLK("tmu1", -1, P_CLK, HWBLK_TMU1, 0), + SH_HWBLK_CLK("tmu345_fck", -1, P_CLK, HWBLK_TMU1, 0), SH_HWBLK_CLK("sci_fck", 0, P_CLK, HWBLK_SCIF0, 0), SH_HWBLK_CLK("sci_fck", 1, P_CLK, HWBLK_SCIF1, 0), SH_HWBLK_CLK("sci_fck", 2, P_CLK, HWBLK_SCIF2, 0), @@ -233,6 +235,40 @@ static struct clk mstp_clks[] = { SH_HWBLK_CLK("lcdc0", -1, B_CLK, HWBLK_LCDC, 0), }; +static struct clk_lookup lookups[] = { + { + /* TMU0 */ + .dev_id = "sh_tmu.0", + .con_id = "tmu_fck", + .clk = &mstp_clks[12], /* tmu012_fck */ + }, { + /* TMU1 */ + .dev_id = "sh_tmu.1", + .con_id = "tmu_fck", + .clk = &mstp_clks[12], + }, { + /* TMU2 */ + .dev_id = "sh_tmu.2", + .con_id = "tmu_fck", + .clk = &mstp_clks[12], + }, { + /* TMU3 */ + .dev_id = "sh_tmu.3", + .con_id = "tmu_fck", + .clk = &mstp_clks[16], /* tmu345_fck */ + }, { + /* TMU4 */ + .dev_id = "sh_tmu.4", + .con_id = "tmu_fck", + .clk = &mstp_clks[16], + }, { + /* TMU5 */ + .dev_id = "sh_tmu.5", + .con_id = "tmu_fck", + .clk = &mstp_clks[16], + }, +}; + int __init arch_clk_init(void) { int k, ret = 0; @@ -246,6 +282,8 @@ int __init arch_clk_init(void) for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++) ret = clk_register(main_clks[k]); + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); + if (!ret) ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table); diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c index ee97890..8a0a4a9 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c @@ -481,7 +481,6 @@ static struct platform_device veu1_device = { static struct sh_timer_config cmt_platform_data = { .channel_offset = 0x60, .timer_bit = 5, - .clk = "cmt0", .clockevent_rating = 125, .clocksource_rating = 200, }; @@ -514,7 +513,6 @@ static struct platform_device cmt_device = { static struct sh_timer_config tmu0_platform_data = { .channel_offset = 0x04, .timer_bit = 0, - .clk = "tmu0", .clockevent_rating = 200, }; @@ -546,7 +544,6 @@ static struct platform_device tmu0_device = { static struct sh_timer_config tmu1_platform_data = { .channel_offset = 0x10, .timer_bit = 1, - .clk = "tmu0", .clocksource_rating = 200, }; @@ -578,7 +575,6 @@ static struct platform_device tmu1_device = { static struct sh_timer_config tmu2_platform_data = { .channel_offset = 0x1c, .timer_bit = 2, - .clk = "tmu0", }; static struct resource tmu2_resources[] = { @@ -610,7 +606,6 @@ static struct platform_device tmu2_device = { static struct sh_timer_config tmu3_platform_data = { .channel_offset = 0x04, .timer_bit = 0, - .clk = "tmu1", }; static struct resource tmu3_resources[] = { @@ -641,7 +636,6 @@ static struct platform_device tmu3_device = { static struct sh_timer_config tmu4_platform_data = { .channel_offset = 0x10, .timer_bit = 1, - .clk = "tmu1", }; static struct resource tmu4_resources[] = { @@ -672,7 +666,6 @@ static struct platform_device tmu4_device = { static struct sh_timer_config tmu5_platform_data = { .channel_offset = 0x1c, .timer_bit = 2, - .clk = "tmu1", }; static struct resource tmu5_resources[] = { -- cgit v0.10.2 From 4bdde044dc36ac7b01f7502394d52619af9d1927 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Wed, 24 Mar 2010 10:58:05 +0800 Subject: tracing: Convert some signal events to DEFINE_TRACE Use DECLARE_EVENT_CLASS to remove duplicate code: text data bss dec hex filename 23639 6084 8 29731 7423 kernel/signal.o.orig 22727 6084 8 28819 7093 kernel/signal.o 2 events are converted: signal_queue_overflow: signal_overflow_fail, signal_lose_info No functional change. Acked-by: Masami Hiramatsu Signed-off-by: Li Zefan LKML-Reference: <4BA97FBD.8070703@cn.fujitsu.com> Signed-off-by: Steven Rostedt diff --git a/include/trace/events/signal.h b/include/trace/events/signal.h index a510b75..814566c 100644 --- a/include/trace/events/signal.h +++ b/include/trace/events/signal.h @@ -100,18 +100,7 @@ TRACE_EVENT(signal_deliver, __entry->sa_handler, __entry->sa_flags) ); -/** - * signal_overflow_fail - called when signal queue is overflow - * @sig: signal number - * @group: signal to process group or not (bool) - * @info: pointer to struct siginfo - * - * Kernel fails to generate 'sig' signal with 'info' siginfo, because - * siginfo queue is overflow, and the signal is dropped. - * 'group' is not 0 if the signal will be sent to a process group. - * 'sig' is always one of RT signals. - */ -TRACE_EVENT(signal_overflow_fail, +DECLARE_EVENT_CLASS(signal_queue_overflow, TP_PROTO(int sig, int group, struct siginfo *info), @@ -135,6 +124,24 @@ TRACE_EVENT(signal_overflow_fail, ); /** + * signal_overflow_fail - called when signal queue is overflow + * @sig: signal number + * @group: signal to process group or not (bool) + * @info: pointer to struct siginfo + * + * Kernel fails to generate 'sig' signal with 'info' siginfo, because + * siginfo queue is overflow, and the signal is dropped. + * 'group' is not 0 if the signal will be sent to a process group. + * 'sig' is always one of RT signals. + */ +DEFINE_EVENT(signal_queue_overflow, signal_overflow_fail, + + TP_PROTO(int sig, int group, struct siginfo *info), + + TP_ARGS(sig, group, info) +); + +/** * signal_lose_info - called when siginfo is lost * @sig: signal number * @group: signal to process group or not (bool) @@ -145,28 +152,13 @@ TRACE_EVENT(signal_overflow_fail, * 'group' is not 0 if the signal will be sent to a process group. * 'sig' is always one of non-RT signals. */ -TRACE_EVENT(signal_lose_info, +DEFINE_EVENT(signal_queue_overflow, signal_lose_info, TP_PROTO(int sig, int group, struct siginfo *info), - TP_ARGS(sig, group, info), - - TP_STRUCT__entry( - __field( int, sig ) - __field( int, group ) - __field( int, errno ) - __field( int, code ) - ), - - TP_fast_assign( - __entry->sig = sig; - __entry->group = group; - TP_STORE_SIGINFO(__entry, info); - ), - - TP_printk("sig=%d group=%d errno=%d code=%d", - __entry->sig, __entry->group, __entry->errno, __entry->code) + TP_ARGS(sig, group, info) ); + #endif /* _TRACE_SIGNAL_H */ /* This part must be outside protection */ -- cgit v0.10.2 From 50354a8a28d0c91695a2d6d25b5a821bfe557a07 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Wed, 24 Mar 2010 10:58:24 +0800 Subject: tracing: Update comments Make some comments consistent with the code. Signed-off-by: Li Zefan LKML-Reference: <4BA97FD0.7090202@cn.fujitsu.com> Signed-off-by: Steven Rostedt diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h index ea6f9d4..75dd778 100644 --- a/include/trace/ftrace.h +++ b/include/trace/ftrace.h @@ -154,9 +154,11 @@ * * field = (typeof(field))entry; * - * p = get_cpu_var(ftrace_event_seq); + * p = &get_cpu_var(ftrace_event_seq); * trace_seq_init(p); - * ret = trace_seq_printf(s, "\n"); + * ret = trace_seq_printf(s, "%s: ", ); + * if (ret) + * ret = trace_seq_printf(s, "\n"); * put_cpu(); * if (!ret) * return TRACE_TYPE_PARTIAL_LINE; @@ -450,38 +452,38 @@ perf_trace_disable_##name(struct ftrace_event_call *unused) \ * * static void ftrace_raw_event_(proto) * { + * struct ftrace_data_offsets_ __maybe_unused __data_offsets; * struct ring_buffer_event *event; * struct ftrace_raw_ *entry; <-- defined in stage 1 * struct ring_buffer *buffer; * unsigned long irq_flags; + * int __data_size; * int pc; * * local_save_flags(irq_flags); * pc = preempt_count(); * + * __data_size = ftrace_get_offsets_(&__data_offsets, args); + * * event = trace_current_buffer_lock_reserve(&buffer, * event_.id, - * sizeof(struct ftrace_raw_), + * sizeof(*entry) + __data_size, * irq_flags, pc); * if (!event) * return; * entry = ring_buffer_event_data(event); * - * ; <-- Here we assign the entries by the __field and - * __array macros. + * { ; } <-- Here we assign the entries by the __field and + * __array macros. * - * trace_current_buffer_unlock_commit(buffer, event, irq_flags, pc); + * if (!filter_current_check_discard(buffer, event_call, entry, event)) + * trace_current_buffer_unlock_commit(buffer, + * event, irq_flags, pc); * } * * static int ftrace_raw_reg_event_(struct ftrace_event_call *unused) * { - * int ret; - * - * ret = register_trace_(ftrace_raw_event_); - * if (!ret) - * pr_info("event trace: Could not activate trace point " - * "probe to "); - * return ret; + * return register_trace_(ftrace_raw_event_); * } * * static void ftrace_unreg_event_(struct ftrace_event_call *unused) @@ -493,6 +495,8 @@ perf_trace_disable_##name(struct ftrace_event_call *unused) \ * .trace = ftrace_raw_output_, <-- stage 2 * }; * + * static const char print_fmt_[] = ; + * * static struct ftrace_event_call __used * __attribute__((__aligned__(4))) * __attribute__((section("_ftrace_events"))) event_ = { @@ -501,6 +505,8 @@ perf_trace_disable_##name(struct ftrace_event_call *unused) \ * .raw_init = trace_event_raw_init, * .regfunc = ftrace_reg_event_, * .unregfunc = ftrace_unreg_event_, + * .print_fmt = print_fmt_, + * .define_fields = ftrace_define_fields_, * } * */ @@ -569,7 +575,6 @@ ftrace_raw_event_id_##call(struct ftrace_event_call *event_call, \ return; \ entry = ring_buffer_event_data(event); \ \ - \ tstruct \ \ { assign; } \ -- cgit v0.10.2 From ae832d1e03ac9bf09fb8a07fb37908ab40c7cd0e Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Wed, 24 Mar 2010 10:57:43 +0800 Subject: tracing: Remove side effect from module tracepoints that caused a GPF Remove the @refcnt argument, because it has side-effects, and arguments with side-effects are not skipped by the jump over disabled instrumentation and are executed even when the tracepoint is disabled. This was also causing a GPF as found by Randy Dunlap: Subject: 2.6.33 GP fault only when built with tracing LKML-Reference: <4BA2B69D.3000309@oracle.com> Note, the current 2.6.34-rc has a fix for the actual cause of the GPF, but this fixes one of its triggers. Tested-by: Randy Dunlap Acked-by: Mathieu Desnoyers Signed-off-by: Li Zefan LKML-Reference: <4BA97FA7.6040406@cn.fujitsu.com> Signed-off-by: Steven Rostedt diff --git a/include/linux/module.h b/include/linux/module.h index 5e869ff..393ec39 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -460,8 +460,7 @@ static inline void __module_get(struct module *module) if (module) { preempt_disable(); __this_cpu_inc(module->refptr->count); - trace_module_get(module, _THIS_IP_, - __this_cpu_read(module->refptr->count)); + trace_module_get(module, _THIS_IP_); preempt_enable(); } } @@ -475,8 +474,7 @@ static inline int try_module_get(struct module *module) if (likely(module_is_live(module))) { __this_cpu_inc(module->refptr->count); - trace_module_get(module, _THIS_IP_, - __this_cpu_read(module->refptr->count)); + trace_module_get(module, _THIS_IP_); } else ret = 0; diff --git a/include/trace/events/module.h b/include/trace/events/module.h index 4b0f48b..a585f81 100644 --- a/include/trace/events/module.h +++ b/include/trace/events/module.h @@ -53,9 +53,9 @@ TRACE_EVENT(module_free, DECLARE_EVENT_CLASS(module_refcnt, - TP_PROTO(struct module *mod, unsigned long ip, int refcnt), + TP_PROTO(struct module *mod, unsigned long ip), - TP_ARGS(mod, ip, refcnt), + TP_ARGS(mod, ip), TP_STRUCT__entry( __field( unsigned long, ip ) @@ -65,7 +65,7 @@ DECLARE_EVENT_CLASS(module_refcnt, TP_fast_assign( __entry->ip = ip; - __entry->refcnt = refcnt; + __entry->refcnt = __this_cpu_read(mod->refptr->count); __assign_str(name, mod->name); ), @@ -75,16 +75,16 @@ DECLARE_EVENT_CLASS(module_refcnt, DEFINE_EVENT(module_refcnt, module_get, - TP_PROTO(struct module *mod, unsigned long ip, int refcnt), + TP_PROTO(struct module *mod, unsigned long ip), - TP_ARGS(mod, ip, refcnt) + TP_ARGS(mod, ip) ); DEFINE_EVENT(module_refcnt, module_put, - TP_PROTO(struct module *mod, unsigned long ip, int refcnt), + TP_PROTO(struct module *mod, unsigned long ip), - TP_ARGS(mod, ip, refcnt) + TP_ARGS(mod, ip) ); TRACE_EVENT(module_request, diff --git a/kernel/module.c b/kernel/module.c index c968d36..21591ad 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -800,8 +800,7 @@ void module_put(struct module *module) preempt_disable(); __this_cpu_dec(module->refptr->count); - trace_module_put(module, _RET_IP_, - __this_cpu_read(module->refptr->count)); + trace_module_put(module, _RET_IP_); /* Maybe they're waiting for us to drop reference? */ if (unlikely(!module_is_live(module))) wake_up_process(module->waiter); -- cgit v0.10.2 From eb0c53771fb2f5f66b0edb3ebce33be4bbf1c285 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Mon, 29 Mar 2010 14:25:18 -0400 Subject: tracing: Fix compile error in module tracepoints when MODULE_UNLOAD not set If modules are configured in the build but unloading of modules is not, then the refcnt is not defined. Place the get/put module tracepoints under CONFIG_MODULE_UNLOAD since it references this field in the module structure. As a side-effect, this patch also reduces the code when MODULE_UNLOAD is not set, because these unused tracepoints are not created. Signed-off-by: Steven Rostedt diff --git a/include/trace/events/module.h b/include/trace/events/module.h index a585f81..f07b44a 100644 --- a/include/trace/events/module.h +++ b/include/trace/events/module.h @@ -51,6 +51,9 @@ TRACE_EVENT(module_free, TP_printk("%s", __get_str(name)) ); +#ifdef CONFIG_MODULE_UNLOAD +/* trace_module_get/put are only used if CONFIG_MODULE_UNLOAD is defined */ + DECLARE_EVENT_CLASS(module_refcnt, TP_PROTO(struct module *mod, unsigned long ip), @@ -86,6 +89,7 @@ DEFINE_EVENT(module_refcnt, module_put, TP_ARGS(mod, ip) ); +#endif /* CONFIG_MODULE_UNLOAD */ TRACE_EVENT(module_request, diff --git a/kernel/module.c b/kernel/module.c index 21591ad..d9e2379 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -59,8 +59,6 @@ #define CREATE_TRACE_POINTS #include -EXPORT_TRACEPOINT_SYMBOL(module_get); - #if 0 #define DEBUGP printk #else @@ -467,6 +465,9 @@ MODINFO_ATTR(srcversion); static char last_unloaded_module[MODULE_NAME_LEN+1]; #ifdef CONFIG_MODULE_UNLOAD + +EXPORT_TRACEPOINT_SYMBOL(module_get); + /* Init the unload section of the module. */ static void module_unload_init(struct module *mod) { -- cgit v0.10.2 From 66a8cb95ed04025664d1db4e952155ee1dccd048 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Wed, 31 Mar 2010 13:21:56 -0400 Subject: ring-buffer: Add place holder recording of dropped events Currently, when the ring buffer drops events, it does not record the fact that it did so. It does inform the writer that the event was dropped by returning a NULL event, but it does not put in any place holder where the event was dropped. This is not a trivial thing to add because the ring buffer mostly runs in overwrite (flight recorder) mode. That is, when the ring buffer is full, new data will overwrite old data. In a produce/consumer mode, where new data is simply dropped when the ring buffer is full, it is trivial to add the placeholder for dropped events. When there's more room to write new data, then a special event can be added to notify the reader about the dropped events. But in overwrite mode, any new write can overwrite events. A place holder can not be inserted into the ring buffer since there never may be room. A reader could also come in at anytime and miss the placeholder. Luckily, the way the ring buffer works, the read side can find out if events were lost or not, and how many events. Everytime a write takes place, if it overwrites the header page (the next read) it updates a "overrun" variable that keeps track of the number of lost events. When a reader swaps out a page from the ring buffer, it can record this number, perfom the swap, and then check to see if the number changed, and take the diff if it has, which would be the number of events dropped. This can be stored by the reader and returned to callers of the reader. Since the reader page swap will fail if the writer moved the head page since the time the reader page set up the swap, this gives room to record the overruns without worrying about races. If the reader sets up the pages, records the overrun, than performs the swap, if the swap succeeds, then the overrun variable has not been updated since the setup before the swap. For binary readers of the ring buffer, a flag is set in the header of each sub page (sub buffer) of the ring buffer. This flag is embedded in the size field of the data on the sub buffer, in the 31st bit (the size can be 32 or 64 bits depending on the architecture), but only 27 bits needs to be used for the actual size (less actually). We could add a new field in the sub buffer header to also record the number of events dropped since the last read, but this will change the format of the binary ring buffer a bit too much. Perhaps this change can be made if the information on the number of events dropped is considered important enough. Note, the notification of dropped events is only used by consuming reads or peeking at the ring buffer. Iterating over the ring buffer does not keep this information because the necessary data is only available when a page swap is made, and the iterator does not swap out pages. Cc: Robert Richter Cc: Andi Kleen Cc: Li Zefan Cc: Arnaldo Carvalho de Melo Cc: "Luis Claudio R. Goncalves" Cc: Frederic Weisbecker Signed-off-by: Steven Rostedt diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index 166b67e..7581dbe 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -186,14 +186,14 @@ int op_cpu_buffer_write_commit(struct op_entry *entry) struct op_sample *op_cpu_buffer_read_entry(struct op_entry *entry, int cpu) { struct ring_buffer_event *e; - e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL); + e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL, NULL); if (e) goto event; if (ring_buffer_swap_cpu(op_ring_buffer_read, op_ring_buffer_write, cpu)) return NULL; - e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL); + e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL, NULL); if (e) goto event; return NULL; diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h index 5fcc31e..c829776 100644 --- a/include/linux/ring_buffer.h +++ b/include/linux/ring_buffer.h @@ -120,9 +120,11 @@ int ring_buffer_write(struct ring_buffer *buffer, unsigned long length, void *data); struct ring_buffer_event * -ring_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts); +ring_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts, + unsigned long *lost_events); struct ring_buffer_event * -ring_buffer_consume(struct ring_buffer *buffer, int cpu, u64 *ts); +ring_buffer_consume(struct ring_buffer *buffer, int cpu, u64 *ts, + unsigned long *lost_events); struct ring_buffer_iter * ring_buffer_read_start(struct ring_buffer *buffer, int cpu); diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index d1187ef..8295650 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -318,6 +318,9 @@ EXPORT_SYMBOL_GPL(ring_buffer_event_data); #define TS_MASK ((1ULL << TS_SHIFT) - 1) #define TS_DELTA_TEST (~TS_MASK) +/* Flag when events were overwritten */ +#define RB_MISSED_EVENTS (1 << 31) + struct buffer_data_page { u64 time_stamp; /* page time stamp */ local_t commit; /* write committed index */ @@ -416,6 +419,12 @@ int ring_buffer_print_page_header(struct trace_seq *s) (unsigned int)sizeof(field.commit), (unsigned int)is_signed_type(long)); + ret = trace_seq_printf(s, "\tfield: int overwrite;\t" + "offset:%u;\tsize:%u;\tsigned:%u;\n", + (unsigned int)offsetof(typeof(field), commit), + 1, + (unsigned int)is_signed_type(long)); + ret = trace_seq_printf(s, "\tfield: char data;\t" "offset:%u;\tsize:%u;\tsigned:%u;\n", (unsigned int)offsetof(typeof(field), data), @@ -439,6 +448,8 @@ struct ring_buffer_per_cpu { struct buffer_page *tail_page; /* write to tail */ struct buffer_page *commit_page; /* committed pages */ struct buffer_page *reader_page; + unsigned long lost_events; + unsigned long last_overrun; local_t commit_overrun; local_t overrun; local_t entries; @@ -2835,6 +2846,7 @@ static struct buffer_page * rb_get_reader_page(struct ring_buffer_per_cpu *cpu_buffer) { struct buffer_page *reader = NULL; + unsigned long overwrite; unsigned long flags; int nr_loops = 0; int ret; @@ -2896,6 +2908,18 @@ rb_get_reader_page(struct ring_buffer_per_cpu *cpu_buffer) rb_set_list_to_head(cpu_buffer, &cpu_buffer->reader_page->list); /* + * We want to make sure we read the overruns after we set up our + * pointers to the next object. The writer side does a + * cmpxchg to cross pages which acts as the mb on the writer + * side. Note, the reader will constantly fail the swap + * while the writer is updating the pointers, so this + * guarantees that the overwrite recorded here is the one we + * want to compare with the last_overrun. + */ + smp_mb(); + overwrite = local_read(&(cpu_buffer->overrun)); + + /* * Here's the tricky part. * * We need to move the pointer past the header page. @@ -2926,6 +2950,11 @@ rb_get_reader_page(struct ring_buffer_per_cpu *cpu_buffer) cpu_buffer->reader_page = reader; rb_reset_reader_page(cpu_buffer); + if (overwrite != cpu_buffer->last_overrun) { + cpu_buffer->lost_events = overwrite - cpu_buffer->last_overrun; + cpu_buffer->last_overrun = overwrite; + } + goto again; out: @@ -3002,8 +3031,14 @@ static void rb_advance_iter(struct ring_buffer_iter *iter) rb_advance_iter(iter); } +static int rb_lost_events(struct ring_buffer_per_cpu *cpu_buffer) +{ + return cpu_buffer->lost_events; +} + static struct ring_buffer_event * -rb_buffer_peek(struct ring_buffer_per_cpu *cpu_buffer, u64 *ts) +rb_buffer_peek(struct ring_buffer_per_cpu *cpu_buffer, u64 *ts, + unsigned long *lost_events) { struct ring_buffer_event *event; struct buffer_page *reader; @@ -3055,6 +3090,8 @@ rb_buffer_peek(struct ring_buffer_per_cpu *cpu_buffer, u64 *ts) ring_buffer_normalize_time_stamp(cpu_buffer->buffer, cpu_buffer->cpu, ts); } + if (lost_events) + *lost_events = rb_lost_events(cpu_buffer); return event; default: @@ -3165,12 +3202,14 @@ static inline int rb_ok_to_lock(void) * @buffer: The ring buffer to read * @cpu: The cpu to peak at * @ts: The timestamp counter of this event. + * @lost_events: a variable to store if events were lost (may be NULL) * * This will return the event that will be read next, but does * not consume the data. */ struct ring_buffer_event * -ring_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts) +ring_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts, + unsigned long *lost_events) { struct ring_buffer_per_cpu *cpu_buffer = buffer->buffers[cpu]; struct ring_buffer_event *event; @@ -3185,7 +3224,7 @@ ring_buffer_peek(struct ring_buffer *buffer, int cpu, u64 *ts) local_irq_save(flags); if (dolock) spin_lock(&cpu_buffer->reader_lock); - event = rb_buffer_peek(cpu_buffer, ts); + event = rb_buffer_peek(cpu_buffer, ts, lost_events); if (event && event->type_len == RINGBUF_TYPE_PADDING) rb_advance_reader(cpu_buffer); if (dolock) @@ -3227,13 +3266,17 @@ ring_buffer_iter_peek(struct ring_buffer_iter *iter, u64 *ts) /** * ring_buffer_consume - return an event and consume it * @buffer: The ring buffer to get the next event from + * @cpu: the cpu to read the buffer from + * @ts: a variable to store the timestamp (may be NULL) + * @lost_events: a variable to store if events were lost (may be NULL) * * Returns the next event in the ring buffer, and that event is consumed. * Meaning, that sequential reads will keep returning a different event, * and eventually empty the ring buffer if the producer is slower. */ struct ring_buffer_event * -ring_buffer_consume(struct ring_buffer *buffer, int cpu, u64 *ts) +ring_buffer_consume(struct ring_buffer *buffer, int cpu, u64 *ts, + unsigned long *lost_events) { struct ring_buffer_per_cpu *cpu_buffer; struct ring_buffer_event *event = NULL; @@ -3254,9 +3297,11 @@ ring_buffer_consume(struct ring_buffer *buffer, int cpu, u64 *ts) if (dolock) spin_lock(&cpu_buffer->reader_lock); - event = rb_buffer_peek(cpu_buffer, ts); - if (event) + event = rb_buffer_peek(cpu_buffer, ts, lost_events); + if (event) { + cpu_buffer->lost_events = 0; rb_advance_reader(cpu_buffer); + } if (dolock) spin_unlock(&cpu_buffer->reader_lock); @@ -3405,6 +3450,9 @@ rb_reset_cpu(struct ring_buffer_per_cpu *cpu_buffer) cpu_buffer->write_stamp = 0; cpu_buffer->read_stamp = 0; + cpu_buffer->lost_events = 0; + cpu_buffer->last_overrun = 0; + rb_head_page_activate(cpu_buffer); } @@ -3684,6 +3732,7 @@ int ring_buffer_read_page(struct ring_buffer *buffer, unsigned int commit; unsigned int read; u64 save_timestamp; + int missed_events = 0; int ret = -1; if (!cpumask_test_cpu(cpu, buffer->cpumask)) @@ -3716,6 +3765,10 @@ int ring_buffer_read_page(struct ring_buffer *buffer, read = reader->read; commit = rb_page_commit(reader); + /* Check if any events were dropped */ + if (cpu_buffer->lost_events) + missed_events = 1; + /* * If this page has been partially read or * if len is not big enough to read the rest of the page or @@ -3779,6 +3832,13 @@ int ring_buffer_read_page(struct ring_buffer *buffer, } ret = read; + cpu_buffer->lost_events = 0; + /* + * Set a flag in the commit field if we lost events + */ + if (missed_events) + local_add(RB_MISSED_EVENTS, &bpage->commit); + out_unlock: spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); diff --git a/kernel/trace/ring_buffer_benchmark.c b/kernel/trace/ring_buffer_benchmark.c index df74c79..dc56556 100644 --- a/kernel/trace/ring_buffer_benchmark.c +++ b/kernel/trace/ring_buffer_benchmark.c @@ -81,7 +81,7 @@ static enum event_status read_event(int cpu) int *entry; u64 ts; - event = ring_buffer_consume(buffer, cpu, &ts); + event = ring_buffer_consume(buffer, cpu, &ts, NULL); if (!event) return EVENT_DROPPED; diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 3ec2ee6..fabb003 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -1556,7 +1556,7 @@ peek_next_entry(struct trace_iterator *iter, int cpu, u64 *ts) if (buf_iter) event = ring_buffer_iter_peek(buf_iter, ts); else - event = ring_buffer_peek(iter->tr->buffer, cpu, ts); + event = ring_buffer_peek(iter->tr->buffer, cpu, ts, NULL); ftrace_enable_cpu(); @@ -1635,7 +1635,7 @@ static void trace_consume(struct trace_iterator *iter) { /* Don't allow ftrace to trace into the ring buffers */ ftrace_disable_cpu(); - ring_buffer_consume(iter->tr->buffer, iter->cpu, &iter->ts); + ring_buffer_consume(iter->tr->buffer, iter->cpu, &iter->ts, NULL); ftrace_enable_cpu(); } diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c index e6989d9..a7f75fb 100644 --- a/kernel/trace/trace_functions_graph.c +++ b/kernel/trace/trace_functions_graph.c @@ -489,9 +489,10 @@ get_return_for_leaf(struct trace_iterator *iter, * We need to consume the current entry to see * the next one. */ - ring_buffer_consume(iter->tr->buffer, iter->cpu, NULL); + ring_buffer_consume(iter->tr->buffer, iter->cpu, + NULL, NULL); event = ring_buffer_peek(iter->tr->buffer, iter->cpu, - NULL); + NULL, NULL); } if (!event) diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c index 280fea4..e501808 100644 --- a/kernel/trace/trace_selftest.c +++ b/kernel/trace/trace_selftest.c @@ -29,7 +29,7 @@ static int trace_test_buffer_cpu(struct trace_array *tr, int cpu) struct trace_entry *entry; unsigned int loops = 0; - while ((event = ring_buffer_consume(tr->buffer, cpu, NULL))) { + while ((event = ring_buffer_consume(tr->buffer, cpu, NULL, NULL))) { entry = ring_buffer_event_data(event); /* -- cgit v0.10.2 From bc21b478425ac73f66a5ec0b375a5e0d12d609ce Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Wed, 31 Mar 2010 19:49:26 -0400 Subject: tracing: Show the lost events in the trace_pipe output Now that the ring buffer can keep track of where events are lost. Use this information to the output of trace_pipe: hackbench-3588 [001] 1326.701660: lock_acquire: ffffffff816591e0 read rcu_read_lock hackbench-3588 [001] 1326.701661: lock_acquire: ffff88003f4091f0 &(&dentry->d_lock)->rlock hackbench-3588 [001] 1326.701664: lock_release: ffff88003f4091f0 &(&dentry->d_lock)->rlock CPU:1 [LOST 673 EVENTS] hackbench-3588 [001] 1326.702711: kmem_cache_free: call_site=ffffffff81102b85 ptr=ffff880026d96738 hackbench-3588 [001] 1326.702712: lock_release: ffff88003e1480a8 &mm->mmap_sem hackbench-3588 [001] 1326.702713: lock_acquire: ffff88003e1480a8 &mm->mmap_sem Even works with the function graph tracer: 2) ! 170.098 us | } 2) 4.036 us | rcu_irq_exit(); 2) 3.657 us | idle_cpu(); 2) ! 190.301 us | } CPU:2 [LOST 2196 EVENTS] 2) 0.853 us | } /* cancel_dirty_page */ 2) | remove_from_page_cache() { 2) 1.578 us | _raw_spin_lock_irq(); 2) | __remove_from_page_cache() { Note, it does not work with the iterator "trace" file, since it requires the use of consuming the page from the ring buffer to determine how many events were lost, which the iterator does not do. Signed-off-by: Steven Rostedt diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h index c0f4b36..39e71b0 100644 --- a/include/linux/ftrace_event.h +++ b/include/linux/ftrace_event.h @@ -58,6 +58,7 @@ struct trace_iterator { /* The below is zeroed out in pipe_read */ struct trace_seq seq; struct trace_entry *ent; + unsigned long lost_events; int leftover; int cpu; u64 ts; diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index fabb003..0498beb 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -1545,7 +1545,8 @@ static void trace_iterator_increment(struct trace_iterator *iter) } static struct trace_entry * -peek_next_entry(struct trace_iterator *iter, int cpu, u64 *ts) +peek_next_entry(struct trace_iterator *iter, int cpu, u64 *ts, + unsigned long *lost_events) { struct ring_buffer_event *event; struct ring_buffer_iter *buf_iter = iter->buffer_iter[cpu]; @@ -1556,7 +1557,8 @@ peek_next_entry(struct trace_iterator *iter, int cpu, u64 *ts) if (buf_iter) event = ring_buffer_iter_peek(buf_iter, ts); else - event = ring_buffer_peek(iter->tr->buffer, cpu, ts, NULL); + event = ring_buffer_peek(iter->tr->buffer, cpu, ts, + lost_events); ftrace_enable_cpu(); @@ -1564,10 +1566,12 @@ peek_next_entry(struct trace_iterator *iter, int cpu, u64 *ts) } static struct trace_entry * -__find_next_entry(struct trace_iterator *iter, int *ent_cpu, u64 *ent_ts) +__find_next_entry(struct trace_iterator *iter, int *ent_cpu, + unsigned long *missing_events, u64 *ent_ts) { struct ring_buffer *buffer = iter->tr->buffer; struct trace_entry *ent, *next = NULL; + unsigned long lost_events, next_lost = 0; int cpu_file = iter->cpu_file; u64 next_ts = 0, ts; int next_cpu = -1; @@ -1580,7 +1584,7 @@ __find_next_entry(struct trace_iterator *iter, int *ent_cpu, u64 *ent_ts) if (cpu_file > TRACE_PIPE_ALL_CPU) { if (ring_buffer_empty_cpu(buffer, cpu_file)) return NULL; - ent = peek_next_entry(iter, cpu_file, ent_ts); + ent = peek_next_entry(iter, cpu_file, ent_ts, missing_events); if (ent_cpu) *ent_cpu = cpu_file; @@ -1592,7 +1596,7 @@ __find_next_entry(struct trace_iterator *iter, int *ent_cpu, u64 *ent_ts) if (ring_buffer_empty_cpu(buffer, cpu)) continue; - ent = peek_next_entry(iter, cpu, &ts); + ent = peek_next_entry(iter, cpu, &ts, &lost_events); /* * Pick the entry with the smallest timestamp: @@ -1601,6 +1605,7 @@ __find_next_entry(struct trace_iterator *iter, int *ent_cpu, u64 *ent_ts) next = ent; next_cpu = cpu; next_ts = ts; + next_lost = lost_events; } } @@ -1610,6 +1615,9 @@ __find_next_entry(struct trace_iterator *iter, int *ent_cpu, u64 *ent_ts) if (ent_ts) *ent_ts = next_ts; + if (missing_events) + *missing_events = next_lost; + return next; } @@ -1617,13 +1625,14 @@ __find_next_entry(struct trace_iterator *iter, int *ent_cpu, u64 *ent_ts) struct trace_entry *trace_find_next_entry(struct trace_iterator *iter, int *ent_cpu, u64 *ent_ts) { - return __find_next_entry(iter, ent_cpu, ent_ts); + return __find_next_entry(iter, ent_cpu, NULL, ent_ts); } /* Find the next real entry, and increment the iterator to the next entry */ static void *find_next_entry_inc(struct trace_iterator *iter) { - iter->ent = __find_next_entry(iter, &iter->cpu, &iter->ts); + iter->ent = __find_next_entry(iter, &iter->cpu, + &iter->lost_events, &iter->ts); if (iter->ent) trace_iterator_increment(iter); @@ -1635,7 +1644,8 @@ static void trace_consume(struct trace_iterator *iter) { /* Don't allow ftrace to trace into the ring buffers */ ftrace_disable_cpu(); - ring_buffer_consume(iter->tr->buffer, iter->cpu, &iter->ts, NULL); + ring_buffer_consume(iter->tr->buffer, iter->cpu, &iter->ts, + &iter->lost_events); ftrace_enable_cpu(); } @@ -2030,6 +2040,10 @@ static enum print_line_t print_trace_line(struct trace_iterator *iter) { enum print_line_t ret; + if (iter->lost_events) + trace_seq_printf(&iter->seq, "CPU:%d [LOST %lu EVENTS]\n", + iter->cpu, iter->lost_events); + if (iter->trace && iter->trace->print_line) { ret = iter->trace->print_line(iter); if (ret != TRACE_TYPE_UNHANDLED) -- cgit v0.10.2 From ff0ff84a0767df48d728c36510365344a7e7d582 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Wed, 31 Mar 2010 22:11:42 -0400 Subject: ring-buffer: Add lost event count to end of sub buffer Currently, binary readers of the ring buffer only know where events were lost, but not how many events were lost at that location. This information is available, but it would require adding another field to the sub buffer header to include it. But when a event can not fit at the end of a sub buffer, it is written to the next sub buffer. This means there is a good chance that the buffer may have room to hold this counter. If it does, write the counter at the end of the sub buffer and set another flag in the data size field that states that this information exists. Signed-off-by: Steven Rostedt diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 8295650..dc6d563 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -320,6 +320,8 @@ EXPORT_SYMBOL_GPL(ring_buffer_event_data); /* Flag when events were overwritten */ #define RB_MISSED_EVENTS (1 << 31) +/* Missed count stored at end */ +#define RB_MISSED_STORED (1 << 30) struct buffer_data_page { u64 time_stamp; /* page time stamp */ @@ -340,6 +342,7 @@ struct buffer_page { local_t write; /* index for next write */ unsigned read; /* index for next read */ local_t entries; /* entries on this page */ + unsigned long real_end; /* real end of data */ struct buffer_data_page *page; /* Actual data page */ }; @@ -1770,6 +1773,13 @@ rb_reset_tail(struct ring_buffer_per_cpu *cpu_buffer, kmemcheck_annotate_bitfield(event, bitfield); /* + * Save the original length to the meta data. + * This will be used by the reader to add lost event + * counter. + */ + tail_page->real_end = tail; + + /* * If this event is bigger than the minimum size, then * we need to be careful that we don't subtract the * write counter enough to allow another writer to slip @@ -2888,6 +2898,7 @@ rb_get_reader_page(struct ring_buffer_per_cpu *cpu_buffer) local_set(&cpu_buffer->reader_page->write, 0); local_set(&cpu_buffer->reader_page->entries, 0); local_set(&cpu_buffer->reader_page->page->commit, 0); + cpu_buffer->reader_page->real_end = 0; spin: /* @@ -3728,11 +3739,11 @@ int ring_buffer_read_page(struct ring_buffer *buffer, struct ring_buffer_event *event; struct buffer_data_page *bpage; struct buffer_page *reader; + unsigned long missed_events; unsigned long flags; unsigned int commit; unsigned int read; u64 save_timestamp; - int missed_events = 0; int ret = -1; if (!cpumask_test_cpu(cpu, buffer->cpumask)) @@ -3766,8 +3777,7 @@ int ring_buffer_read_page(struct ring_buffer *buffer, commit = rb_page_commit(reader); /* Check if any events were dropped */ - if (cpu_buffer->lost_events) - missed_events = 1; + missed_events = cpu_buffer->lost_events; /* * If this page has been partially read or @@ -3829,6 +3839,14 @@ int ring_buffer_read_page(struct ring_buffer *buffer, local_set(&reader->entries, 0); reader->read = 0; *data_page = bpage; + + /* + * Use the real_end for the data size, + * This gives us a chance to store the lost events + * on the page. + */ + if (reader->real_end) + local_set(&bpage->commit, reader->real_end); } ret = read; @@ -3836,8 +3854,19 @@ int ring_buffer_read_page(struct ring_buffer *buffer, /* * Set a flag in the commit field if we lost events */ - if (missed_events) + if (missed_events) { + commit = local_read(&bpage->commit); + + /* If there is room at the end of the page to save the + * missed events, then record it there. + */ + if (BUF_PAGE_SIZE - commit >= sizeof(missed_events)) { + memcpy(&bpage->data[commit], &missed_events, + sizeof(missed_events)); + local_add(RB_MISSED_STORED, &bpage->commit); + } local_add(RB_MISSED_EVENTS, &bpage->commit); + } out_unlock: spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); -- cgit v0.10.2 From 085ea739adf107b5a5d131f3625e517ff4a5181e Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Fri, 2 Apr 2010 12:50:39 -0400 Subject: perf probe: Fix --line syntax help and document Just fix typos. --line option accepts ':START-END' syntax, not ':START:END'. Signed-off-by: Masami Hiramatsu Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Frederic Weisbecker Cc: systemtap Cc: DLE LKML-Reference: <20100402165038.23551.62590.stgit@localhost6.localdomain6> Signed-off-by: Ingo Molnar diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt index 0f944b3..bb671b3 100644 --- a/tools/perf/Documentation/perf-probe.txt +++ b/tools/perf/Documentation/perf-probe.txt @@ -85,7 +85,7 @@ LINE SYNTAX ----------- Line range is descripted by following syntax. - "FUNC[:RLN[+NUM|:RLN2]]|SRC:ALN[+NUM|:ALN2]" + "FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]" FUNC specifies the function name of showing lines. 'RLN' is the start line number from function entry line, and 'RLN2' is the end line number. As same as diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index cf2ffa5..b3ba25a 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c @@ -167,7 +167,7 @@ static const struct option options[] = { " with existing name"), #ifdef DWARF_SUPPORT OPT_CALLBACK('L', "line", NULL, - "FUNC[:RLN[+NUM|:RLN2]]|SRC:ALN[+NUM|:ALN2]", + "FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]", "Show source code lines.", opt_show_lines), OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, "file", "vmlinux pathname"), -- cgit v0.10.2 From c9e385826d4f1ca5a72005ab8503598f791a8dc0 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Fri, 2 Apr 2010 12:50:45 -0400 Subject: perf probe: Fix not to return non-matched file Fix cu_find_realpath() not to return the last file path if that is not matched to input pattern. Signed-off-by: Masami Hiramatsu Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Frederic Weisbecker Cc: systemtap Cc: DLE LKML-Reference: <20100402165045.23551.47780.stgit@localhost6.localdomain6> Signed-off-by: Ingo Molnar diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index db52ec2..b44132e 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -183,6 +183,8 @@ static const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname) if (strtailcmp(src, fname) == 0) break; } + if (i == nfiles) + return NULL; return src; } -- cgit v0.10.2 From 12e5a7ae475ccb2733d740ffb95d9ca0a18392da Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Fri, 2 Apr 2010 12:50:53 -0400 Subject: perf probe: Correct error message for non-structure type perf probe outputs incorrect error message when it is called with non-existent field on a non-data structure local variable. # perf probe vfs_read 'count.hoge' Fatal: Structure on a register is not supported yet. # perf probe vfs_read 'count->hoge' Fatal: Semantic error: hoge must be referred by '.' This corrects the messsage. # perf probe vfs_read 'count.hoge' Fatal: count is not a data structure. # perf probe vfs_read 'count->hoge' Fatal: count is not a data structure. Signed-off-by: Masami Hiramatsu Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Frederic Weisbecker Cc: systemtap Cc: DLE LKML-Reference: <20100402165052.23551.75866.stgit@localhost6.localdomain6> Signed-off-by: Ingo Molnar diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index b44132e..59b0115 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -429,12 +429,20 @@ static void convert_variable_fields(Dwarf_Die *vr_die, const char *varname, if (die_get_real_type(&type, &type) == NULL) die("Failed to get a type information of %s.", varname); + /* Verify it is a data structure */ + if (dwarf_tag(&type) != DW_TAG_structure_type) + die("%s is not a data structure.", varname); + ref = xzalloc(sizeof(struct kprobe_trace_arg_ref)); if (*ref_ptr) (*ref_ptr)->next = ref; else *ref_ptr = ref; } else { + /* Verify it is a data structure */ + if (dwarf_tag(&type) != DW_TAG_structure_type) + die("%s is not a data structure.", varname); + if (field->ref) die("Semantic error: %s must be referred by '.'", field->name); @@ -442,10 +450,6 @@ static void convert_variable_fields(Dwarf_Die *vr_die, const char *varname, die("Structure on a register is not supported yet."); } - /* Verify it is a data structure */ - if (dwarf_tag(&type) != DW_TAG_structure_type) - die("%s is not a data structure.", varname); - if (die_find_member(&type, field->name, &member) == NULL) die("%s(tyep:%s) has no member %s.", varname, dwarf_diename(&type), field->name); -- cgit v0.10.2 From 75ec5a245c7763c397f31ec8964d0a46c54a7386 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Fri, 2 Apr 2010 12:50:59 -0400 Subject: perf probe: Fix to close dwarf when failing to analyze it Fix to close libdw routine when failing to analyze it in find_perf_probe_point(). Signed-off-by: Masami Hiramatsu Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Frederic Weisbecker Cc: systemtap Cc: DLE LKML-Reference: <20100402165059.23551.95587.stgit@localhost6.localdomain6> Signed-off-by: Ingo Molnar diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 59b0115..a851377 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -818,8 +818,10 @@ int find_perf_probe_point(int fd, unsigned long addr, return -ENOENT; /* Find cu die */ - if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr, &cudie)) - return -EINVAL; + if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr, &cudie)) { + ret = -EINVAL; + goto end; + } /* Find a corresponding line */ line = dwarf_getsrc_die(&cudie, (Dwarf_Addr)addr); -- cgit v0.10.2 From 948b1bb89a44561560531394c18da4a99215f772 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Mon, 29 Mar 2010 18:36:50 +0200 Subject: perf, x86: Undo some some *_counter* -> *_event* renames The big rename: cdd6c48 perf: Do the big rename: Performance Counters -> Performance Events accidentally renamed some members of stucts that were named after registers in the spec. To avoid confusion this patch reverts some changes. The related specs are MSR descriptions in AMD's BKDGs and the ARCHITECTURAL PERFORMANCE MONITORING section in the Intel 64 and IA-32 Architectures Software Developer's Manuals. This patch does: $ sed -i -e 's:num_events:num_counters:g' \ arch/x86/include/asm/perf_event.h \ arch/x86/kernel/cpu/perf_event_amd.c \ arch/x86/kernel/cpu/perf_event.c \ arch/x86/kernel/cpu/perf_event_intel.c \ arch/x86/kernel/cpu/perf_event_p6.c \ arch/x86/kernel/cpu/perf_event_p4.c \ arch/x86/oprofile/op_model_ppro.c $ sed -i -e 's:event_bits:cntval_bits:g' -e 's:event_mask:cntval_mask:g' \ arch/x86/kernel/cpu/perf_event_amd.c \ arch/x86/kernel/cpu/perf_event.c \ arch/x86/kernel/cpu/perf_event_intel.c \ arch/x86/kernel/cpu/perf_event_p6.c \ arch/x86/kernel/cpu/perf_event_p4.c Signed-off-by: Robert Richter Signed-off-by: Peter Zijlstra LKML-Reference: <1269880612-25800-2-git-send-email-robert.richter@amd.com> Signed-off-by: Ingo Molnar diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h index 124dddd..987bf67 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h @@ -67,7 +67,7 @@ union cpuid10_eax { struct { unsigned int version_id:8; - unsigned int num_events:8; + unsigned int num_counters:8; unsigned int bit_width:8; unsigned int mask_length:8; } split; @@ -76,7 +76,7 @@ union cpuid10_eax { union cpuid10_edx { struct { - unsigned int num_events_fixed:4; + unsigned int num_counters_fixed:4; unsigned int reserved:28; } split; unsigned int full; diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index b534356..9daaa1e 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -195,10 +195,10 @@ struct x86_pmu { u64 (*event_map)(int); u64 (*raw_event)(u64); int max_events; - int num_events; - int num_events_fixed; - int event_bits; - u64 event_mask; + int num_counters; + int num_counters_fixed; + int cntval_bits; + u64 cntval_mask; int apic; u64 max_period; struct event_constraint * @@ -268,7 +268,7 @@ static u64 x86_perf_event_update(struct perf_event *event) { struct hw_perf_event *hwc = &event->hw; - int shift = 64 - x86_pmu.event_bits; + int shift = 64 - x86_pmu.cntval_bits; u64 prev_raw_count, new_raw_count; int idx = hwc->idx; s64 delta; @@ -320,12 +320,12 @@ static bool reserve_pmc_hardware(void) if (nmi_watchdog == NMI_LOCAL_APIC) disable_lapic_nmi_watchdog(); - for (i = 0; i < x86_pmu.num_events; i++) { + for (i = 0; i < x86_pmu.num_counters; i++) { if (!reserve_perfctr_nmi(x86_pmu.perfctr + i)) goto perfctr_fail; } - for (i = 0; i < x86_pmu.num_events; i++) { + for (i = 0; i < x86_pmu.num_counters; i++) { if (!reserve_evntsel_nmi(x86_pmu.eventsel + i)) goto eventsel_fail; } @@ -336,7 +336,7 @@ eventsel_fail: for (i--; i >= 0; i--) release_evntsel_nmi(x86_pmu.eventsel + i); - i = x86_pmu.num_events; + i = x86_pmu.num_counters; perfctr_fail: for (i--; i >= 0; i--) @@ -352,7 +352,7 @@ static void release_pmc_hardware(void) { int i; - for (i = 0; i < x86_pmu.num_events; i++) { + for (i = 0; i < x86_pmu.num_counters; i++) { release_perfctr_nmi(x86_pmu.perfctr + i); release_evntsel_nmi(x86_pmu.eventsel + i); } @@ -547,7 +547,7 @@ static void x86_pmu_disable_all(void) struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); int idx; - for (idx = 0; idx < x86_pmu.num_events; idx++) { + for (idx = 0; idx < x86_pmu.num_counters; idx++) { u64 val; if (!test_bit(idx, cpuc->active_mask)) @@ -582,7 +582,7 @@ static void x86_pmu_enable_all(int added) struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); int idx; - for (idx = 0; idx < x86_pmu.num_events; idx++) { + for (idx = 0; idx < x86_pmu.num_counters; idx++) { struct perf_event *event = cpuc->events[idx]; u64 val; @@ -657,14 +657,14 @@ static int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign) * assign events to counters starting with most * constrained events. */ - wmax = x86_pmu.num_events; + wmax = x86_pmu.num_counters; /* * when fixed event counters are present, * wmax is incremented by 1 to account * for one more choice */ - if (x86_pmu.num_events_fixed) + if (x86_pmu.num_counters_fixed) wmax++; for (w = 1, num = n; num && w <= wmax; w++) { @@ -714,7 +714,7 @@ static int collect_events(struct cpu_hw_events *cpuc, struct perf_event *leader, struct perf_event *event; int n, max_count; - max_count = x86_pmu.num_events + x86_pmu.num_events_fixed; + max_count = x86_pmu.num_counters + x86_pmu.num_counters_fixed; /* current number of events already accepted */ n = cpuc->n_events; @@ -904,7 +904,7 @@ x86_perf_event_set_period(struct perf_event *event) atomic64_set(&hwc->prev_count, (u64)-left); wrmsrl(hwc->event_base + idx, - (u64)(-left) & x86_pmu.event_mask); + (u64)(-left) & x86_pmu.cntval_mask); perf_event_update_userpage(event); @@ -987,7 +987,7 @@ void perf_event_print_debug(void) unsigned long flags; int cpu, idx; - if (!x86_pmu.num_events) + if (!x86_pmu.num_counters) return; local_irq_save(flags); @@ -1011,7 +1011,7 @@ void perf_event_print_debug(void) } pr_info("CPU#%d: active: %016llx\n", cpu, *(u64 *)cpuc->active_mask); - for (idx = 0; idx < x86_pmu.num_events; idx++) { + for (idx = 0; idx < x86_pmu.num_counters; idx++) { rdmsrl(x86_pmu.eventsel + idx, pmc_ctrl); rdmsrl(x86_pmu.perfctr + idx, pmc_count); @@ -1024,7 +1024,7 @@ void perf_event_print_debug(void) pr_info("CPU#%d: gen-PMC%d left: %016llx\n", cpu, idx, prev_left); } - for (idx = 0; idx < x86_pmu.num_events_fixed; idx++) { + for (idx = 0; idx < x86_pmu.num_counters_fixed; idx++) { rdmsrl(MSR_ARCH_PERFMON_FIXED_CTR0 + idx, pmc_count); pr_info("CPU#%d: fixed-PMC%d count: %016llx\n", @@ -1089,7 +1089,7 @@ static int x86_pmu_handle_irq(struct pt_regs *regs) cpuc = &__get_cpu_var(cpu_hw_events); - for (idx = 0; idx < x86_pmu.num_events; idx++) { + for (idx = 0; idx < x86_pmu.num_counters; idx++) { if (!test_bit(idx, cpuc->active_mask)) continue; @@ -1097,7 +1097,7 @@ static int x86_pmu_handle_irq(struct pt_regs *regs) hwc = &event->hw; val = x86_perf_event_update(event); - if (val & (1ULL << (x86_pmu.event_bits - 1))) + if (val & (1ULL << (x86_pmu.cntval_bits - 1))) continue; /* @@ -1401,46 +1401,46 @@ void __init init_hw_perf_events(void) if (x86_pmu.quirks) x86_pmu.quirks(); - if (x86_pmu.num_events > X86_PMC_MAX_GENERIC) { + if (x86_pmu.num_counters > X86_PMC_MAX_GENERIC) { WARN(1, KERN_ERR "hw perf events %d > max(%d), clipping!", - x86_pmu.num_events, X86_PMC_MAX_GENERIC); - x86_pmu.num_events = X86_PMC_MAX_GENERIC; + x86_pmu.num_counters, X86_PMC_MAX_GENERIC); + x86_pmu.num_counters = X86_PMC_MAX_GENERIC; } - x86_pmu.intel_ctrl = (1 << x86_pmu.num_events) - 1; - perf_max_events = x86_pmu.num_events; + x86_pmu.intel_ctrl = (1 << x86_pmu.num_counters) - 1; + perf_max_events = x86_pmu.num_counters; - if (x86_pmu.num_events_fixed > X86_PMC_MAX_FIXED) { + if (x86_pmu.num_counters_fixed > X86_PMC_MAX_FIXED) { WARN(1, KERN_ERR "hw perf events fixed %d > max(%d), clipping!", - x86_pmu.num_events_fixed, X86_PMC_MAX_FIXED); - x86_pmu.num_events_fixed = X86_PMC_MAX_FIXED; + x86_pmu.num_counters_fixed, X86_PMC_MAX_FIXED); + x86_pmu.num_counters_fixed = X86_PMC_MAX_FIXED; } x86_pmu.intel_ctrl |= - ((1LL << x86_pmu.num_events_fixed)-1) << X86_PMC_IDX_FIXED; + ((1LL << x86_pmu.num_counters_fixed)-1) << X86_PMC_IDX_FIXED; perf_events_lapic_init(); register_die_notifier(&perf_event_nmi_notifier); unconstrained = (struct event_constraint) - __EVENT_CONSTRAINT(0, (1ULL << x86_pmu.num_events) - 1, - 0, x86_pmu.num_events); + __EVENT_CONSTRAINT(0, (1ULL << x86_pmu.num_counters) - 1, + 0, x86_pmu.num_counters); if (x86_pmu.event_constraints) { for_each_event_constraint(c, x86_pmu.event_constraints) { if (c->cmask != INTEL_ARCH_FIXED_MASK) continue; - c->idxmsk64 |= (1ULL << x86_pmu.num_events) - 1; - c->weight += x86_pmu.num_events; + c->idxmsk64 |= (1ULL << x86_pmu.num_counters) - 1; + c->weight += x86_pmu.num_counters; } } pr_info("... version: %d\n", x86_pmu.version); - pr_info("... bit width: %d\n", x86_pmu.event_bits); - pr_info("... generic registers: %d\n", x86_pmu.num_events); - pr_info("... value mask: %016Lx\n", x86_pmu.event_mask); + pr_info("... bit width: %d\n", x86_pmu.cntval_bits); + pr_info("... generic registers: %d\n", x86_pmu.num_counters); + pr_info("... value mask: %016Lx\n", x86_pmu.cntval_mask); pr_info("... max period: %016Lx\n", x86_pmu.max_period); - pr_info("... fixed-purpose events: %d\n", x86_pmu.num_events_fixed); + pr_info("... fixed-purpose events: %d\n", x86_pmu.num_counters_fixed); pr_info("... event mask: %016Lx\n", x86_pmu.intel_ctrl); perf_cpu_notifier(x86_pmu_notifier); diff --git a/arch/x86/kernel/cpu/perf_event_amd.c b/arch/x86/kernel/cpu/perf_event_amd.c index 285623b..7753a5c 100644 --- a/arch/x86/kernel/cpu/perf_event_amd.c +++ b/arch/x86/kernel/cpu/perf_event_amd.c @@ -165,7 +165,7 @@ static void amd_put_event_constraints(struct cpu_hw_events *cpuc, * be removed on one CPU at a time AND PMU is disabled * when we come here */ - for (i = 0; i < x86_pmu.num_events; i++) { + for (i = 0; i < x86_pmu.num_counters; i++) { if (nb->owners[i] == event) { cmpxchg(nb->owners+i, event, NULL); break; @@ -215,7 +215,7 @@ amd_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event) struct hw_perf_event *hwc = &event->hw; struct amd_nb *nb = cpuc->amd_nb; struct perf_event *old = NULL; - int max = x86_pmu.num_events; + int max = x86_pmu.num_counters; int i, j, k = -1; /* @@ -293,7 +293,7 @@ static struct amd_nb *amd_alloc_nb(int cpu, int nb_id) /* * initialize all possible NB constraints */ - for (i = 0; i < x86_pmu.num_events; i++) { + for (i = 0; i < x86_pmu.num_counters; i++) { __set_bit(i, nb->event_constraints[i].idxmsk); nb->event_constraints[i].weight = 1; } @@ -385,9 +385,9 @@ static __initconst struct x86_pmu amd_pmu = { .event_map = amd_pmu_event_map, .raw_event = amd_pmu_raw_event, .max_events = ARRAY_SIZE(amd_perfmon_event_map), - .num_events = 4, - .event_bits = 48, - .event_mask = (1ULL << 48) - 1, + .num_counters = 4, + .cntval_bits = 48, + .cntval_mask = (1ULL << 48) - 1, .apic = 1, /* use highest bit to detect overflow */ .max_period = (1ULL << 47) - 1, diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 676aac2..cc4d90a 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -653,20 +653,20 @@ static void intel_pmu_reset(void) unsigned long flags; int idx; - if (!x86_pmu.num_events) + if (!x86_pmu.num_counters) return; local_irq_save(flags); printk("clearing PMU state on CPU#%d\n", smp_processor_id()); - for (idx = 0; idx < x86_pmu.num_events; idx++) { + for (idx = 0; idx < x86_pmu.num_counters; idx++) { checking_wrmsrl(x86_pmu.eventsel + idx, 0ull); checking_wrmsrl(x86_pmu.perfctr + idx, 0ull); } - for (idx = 0; idx < x86_pmu.num_events_fixed; idx++) { + for (idx = 0; idx < x86_pmu.num_counters_fixed; idx++) checking_wrmsrl(MSR_ARCH_PERFMON_FIXED_CTR0 + idx, 0ull); - } + if (ds) ds->bts_index = ds->bts_buffer_base; @@ -901,16 +901,16 @@ static __init int intel_pmu_init(void) x86_pmu = intel_pmu; x86_pmu.version = version; - x86_pmu.num_events = eax.split.num_events; - x86_pmu.event_bits = eax.split.bit_width; - x86_pmu.event_mask = (1ULL << eax.split.bit_width) - 1; + x86_pmu.num_counters = eax.split.num_counters; + x86_pmu.cntval_bits = eax.split.bit_width; + x86_pmu.cntval_mask = (1ULL << eax.split.bit_width) - 1; /* * Quirk: v2 perfmon does not report fixed-purpose events, so * assume at least 3 events: */ if (version > 1) - x86_pmu.num_events_fixed = max((int)edx.split.num_events_fixed, 3); + x86_pmu.num_counters_fixed = max((int)edx.split.num_counters_fixed, 3); /* * v2 and above have a perf capabilities MSR diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index 0d1be36..4139100 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c @@ -483,7 +483,7 @@ static void p4_pmu_disable_all(void) struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); int idx; - for (idx = 0; idx < x86_pmu.num_events; idx++) { + for (idx = 0; idx < x86_pmu.num_counters; idx++) { struct perf_event *event = cpuc->events[idx]; if (!test_bit(idx, cpuc->active_mask)) continue; @@ -540,7 +540,7 @@ static void p4_pmu_enable_all(int added) struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); int idx; - for (idx = 0; idx < x86_pmu.num_events; idx++) { + for (idx = 0; idx < x86_pmu.num_counters; idx++) { struct perf_event *event = cpuc->events[idx]; if (!test_bit(idx, cpuc->active_mask)) continue; @@ -562,7 +562,7 @@ static int p4_pmu_handle_irq(struct pt_regs *regs) cpuc = &__get_cpu_var(cpu_hw_events); - for (idx = 0; idx < x86_pmu.num_events; idx++) { + for (idx = 0; idx < x86_pmu.num_counters; idx++) { if (!test_bit(idx, cpuc->active_mask)) continue; @@ -579,7 +579,7 @@ static int p4_pmu_handle_irq(struct pt_regs *regs) p4_pmu_clear_cccr_ovf(hwc); val = x86_perf_event_update(event); - if (val & (1ULL << (x86_pmu.event_bits - 1))) + if (val & (1ULL << (x86_pmu.cntval_bits - 1))) continue; /* @@ -794,10 +794,10 @@ static __initconst struct x86_pmu p4_pmu = { * though leave it restricted at moment assuming * HT is on */ - .num_events = ARCH_P4_MAX_CCCR, + .num_counters = ARCH_P4_MAX_CCCR, .apic = 1, - .event_bits = 40, - .event_mask = (1ULL << 40) - 1, + .cntval_bits = 40, + .cntval_mask = (1ULL << 40) - 1, .max_period = (1ULL << 39) - 1, .hw_config = p4_hw_config, .schedule_events = p4_pmu_schedule_events, diff --git a/arch/x86/kernel/cpu/perf_event_p6.c b/arch/x86/kernel/cpu/perf_event_p6.c index 877182c..b26fbc7e 100644 --- a/arch/x86/kernel/cpu/perf_event_p6.c +++ b/arch/x86/kernel/cpu/perf_event_p6.c @@ -119,7 +119,7 @@ static __initconst struct x86_pmu p6_pmu = { .apic = 1, .max_period = (1ULL << 31) - 1, .version = 0, - .num_events = 2, + .num_counters = 2, /* * Events have 40 bits implemented. However they are designed such * that bits [32-39] are sign extensions of bit 31. As such the @@ -127,8 +127,8 @@ static __initconst struct x86_pmu p6_pmu = { * * See IA-32 Intel Architecture Software developer manual Vol 3B */ - .event_bits = 32, - .event_mask = (1ULL << 32) - 1, + .cntval_bits = 32, + .cntval_mask = (1ULL << 32) - 1, .get_event_constraints = x86_get_event_constraints, .event_constraints = p6_event_constraints, }; diff --git a/arch/x86/oprofile/op_model_ppro.c b/arch/x86/oprofile/op_model_ppro.c index 2bf90fa..c8abc4d 100644 --- a/arch/x86/oprofile/op_model_ppro.c +++ b/arch/x86/oprofile/op_model_ppro.c @@ -239,11 +239,11 @@ static void arch_perfmon_setup_counters(void) if (eax.split.version_id == 0 && current_cpu_data.x86 == 6 && current_cpu_data.x86_model == 15) { eax.split.version_id = 2; - eax.split.num_events = 2; + eax.split.num_counters = 2; eax.split.bit_width = 40; } - num_counters = eax.split.num_events; + num_counters = eax.split.num_counters; op_arch_perfmon_spec.num_counters = num_counters; op_arch_perfmon_spec.num_controls = num_counters; -- cgit v0.10.2 From a098f4484bc7dae23f5b62360954007b99b64600 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 30 Mar 2010 11:28:21 +0200 Subject: perf, x86: implement ARCH_PERFMON_EVENTSEL bit masks ARCH_PERFMON_EVENTSEL bit masks are often used in the kernel. This patch adds macros for the bit masks and removes local defines. The function intel_pmu_raw_event() becomes x86_pmu_raw_event() which is generic for x86 models and same also for p6. Duplicate code is removed. Signed-off-by: Robert Richter Signed-off-by: Peter Zijlstra LKML-Reference: <20100330092821.GH11907@erda.amd.com> Signed-off-by: Ingo Molnar diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h index 987bf67..f6d43db 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h @@ -18,39 +18,31 @@ #define MSR_ARCH_PERFMON_EVENTSEL0 0x186 #define MSR_ARCH_PERFMON_EVENTSEL1 0x187 -#define ARCH_PERFMON_EVENTSEL_ENABLE (1 << 22) -#define ARCH_PERFMON_EVENTSEL_ANY (1 << 21) -#define ARCH_PERFMON_EVENTSEL_INT (1 << 20) -#define ARCH_PERFMON_EVENTSEL_OS (1 << 17) -#define ARCH_PERFMON_EVENTSEL_USR (1 << 16) - -/* - * Includes eventsel and unit mask as well: - */ - - -#define INTEL_ARCH_EVTSEL_MASK 0x000000FFULL -#define INTEL_ARCH_UNIT_MASK 0x0000FF00ULL -#define INTEL_ARCH_EDGE_MASK 0x00040000ULL -#define INTEL_ARCH_INV_MASK 0x00800000ULL -#define INTEL_ARCH_CNT_MASK 0xFF000000ULL -#define INTEL_ARCH_EVENT_MASK (INTEL_ARCH_UNIT_MASK|INTEL_ARCH_EVTSEL_MASK) - -/* - * filter mask to validate fixed counter events. - * the following filters disqualify for fixed counters: - * - inv - * - edge - * - cnt-mask - * The other filters are supported by fixed counters. - * The any-thread option is supported starting with v3. - */ -#define INTEL_ARCH_FIXED_MASK \ - (INTEL_ARCH_CNT_MASK| \ - INTEL_ARCH_INV_MASK| \ - INTEL_ARCH_EDGE_MASK|\ - INTEL_ARCH_UNIT_MASK|\ - INTEL_ARCH_EVENT_MASK) +#define ARCH_PERFMON_EVENTSEL_EVENT 0x000000FFULL +#define ARCH_PERFMON_EVENTSEL_UMASK 0x0000FF00ULL +#define ARCH_PERFMON_EVENTSEL_USR (1ULL << 16) +#define ARCH_PERFMON_EVENTSEL_OS (1ULL << 17) +#define ARCH_PERFMON_EVENTSEL_EDGE (1ULL << 18) +#define ARCH_PERFMON_EVENTSEL_INT (1ULL << 20) +#define ARCH_PERFMON_EVENTSEL_ANY (1ULL << 21) +#define ARCH_PERFMON_EVENTSEL_ENABLE (1ULL << 22) +#define ARCH_PERFMON_EVENTSEL_INV (1ULL << 23) +#define ARCH_PERFMON_EVENTSEL_CMASK 0xFF000000ULL + +#define AMD64_EVENTSEL_EVENT \ + (ARCH_PERFMON_EVENTSEL_EVENT | (0x0FULL << 32)) +#define INTEL_ARCH_EVENT_MASK \ + (ARCH_PERFMON_EVENTSEL_UMASK | ARCH_PERFMON_EVENTSEL_EVENT) + +#define X86_RAW_EVENT_MASK \ + (ARCH_PERFMON_EVENTSEL_EVENT | \ + ARCH_PERFMON_EVENTSEL_UMASK | \ + ARCH_PERFMON_EVENTSEL_EDGE | \ + ARCH_PERFMON_EVENTSEL_INV | \ + ARCH_PERFMON_EVENTSEL_CMASK) +#define AMD64_RAW_EVENT_MASK \ + (X86_RAW_EVENT_MASK | \ + AMD64_EVENTSEL_EVENT) #define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL 0x3c #define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK (0x00 << 8) diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 9daaa1e..1dd42c1 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -143,13 +143,21 @@ struct cpu_hw_events { * Constraint on the Event code. */ #define INTEL_EVENT_CONSTRAINT(c, n) \ - EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVTSEL_MASK) + EVENT_CONSTRAINT(c, n, ARCH_PERFMON_EVENTSEL_EVENT) /* * Constraint on the Event code + UMask + fixed-mask + * + * filter mask to validate fixed counter events. + * the following filters disqualify for fixed counters: + * - inv + * - edge + * - cnt-mask + * The other filters are supported by fixed counters. + * The any-thread option is supported starting with v3. */ #define FIXED_EVENT_CONSTRAINT(c, n) \ - EVENT_CONSTRAINT(c, (1ULL << (32+n)), INTEL_ARCH_FIXED_MASK) + EVENT_CONSTRAINT(c, (1ULL << (32+n)), X86_RAW_EVENT_MASK) /* * Constraint on the Event code + UMask @@ -437,6 +445,11 @@ static int x86_hw_config(struct perf_event_attr *attr, struct hw_perf_event *hwc return 0; } +static u64 x86_pmu_raw_event(u64 hw_event) +{ + return hw_event & X86_RAW_EVENT_MASK; +} + /* * Setup the hardware configuration for a given attr_type */ @@ -1427,7 +1440,7 @@ void __init init_hw_perf_events(void) if (x86_pmu.event_constraints) { for_each_event_constraint(c, x86_pmu.event_constraints) { - if (c->cmask != INTEL_ARCH_FIXED_MASK) + if (c->cmask != X86_RAW_EVENT_MASK) continue; c->idxmsk64 |= (1ULL << x86_pmu.num_counters) - 1; diff --git a/arch/x86/kernel/cpu/perf_event_amd.c b/arch/x86/kernel/cpu/perf_event_amd.c index 7753a5c..37e9517 100644 --- a/arch/x86/kernel/cpu/perf_event_amd.c +++ b/arch/x86/kernel/cpu/perf_event_amd.c @@ -113,20 +113,7 @@ static u64 amd_pmu_event_map(int hw_event) static u64 amd_pmu_raw_event(u64 hw_event) { -#define K7_EVNTSEL_EVENT_MASK 0xF000000FFULL -#define K7_EVNTSEL_UNIT_MASK 0x00000FF00ULL -#define K7_EVNTSEL_EDGE_MASK 0x000040000ULL -#define K7_EVNTSEL_INV_MASK 0x000800000ULL -#define K7_EVNTSEL_REG_MASK 0x0FF000000ULL - -#define K7_EVNTSEL_MASK \ - (K7_EVNTSEL_EVENT_MASK | \ - K7_EVNTSEL_UNIT_MASK | \ - K7_EVNTSEL_EDGE_MASK | \ - K7_EVNTSEL_INV_MASK | \ - K7_EVNTSEL_REG_MASK) - - return hw_event & K7_EVNTSEL_MASK; + return hw_event & AMD64_RAW_EVENT_MASK; } /* diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index cc4d90a..dfdd6f9 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -452,24 +452,6 @@ static __initconst u64 atom_hw_cache_event_ids }, }; -static u64 intel_pmu_raw_event(u64 hw_event) -{ -#define CORE_EVNTSEL_EVENT_MASK 0x000000FFULL -#define CORE_EVNTSEL_UNIT_MASK 0x0000FF00ULL -#define CORE_EVNTSEL_EDGE_MASK 0x00040000ULL -#define CORE_EVNTSEL_INV_MASK 0x00800000ULL -#define CORE_EVNTSEL_REG_MASK 0xFF000000ULL - -#define CORE_EVNTSEL_MASK \ - (INTEL_ARCH_EVTSEL_MASK | \ - INTEL_ARCH_UNIT_MASK | \ - INTEL_ARCH_EDGE_MASK | \ - INTEL_ARCH_INV_MASK | \ - INTEL_ARCH_CNT_MASK) - - return hw_event & CORE_EVNTSEL_MASK; -} - static void intel_pmu_disable_all(void) { struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); @@ -788,7 +770,7 @@ static __initconst struct x86_pmu core_pmu = { .eventsel = MSR_ARCH_PERFMON_EVENTSEL0, .perfctr = MSR_ARCH_PERFMON_PERFCTR0, .event_map = intel_pmu_event_map, - .raw_event = intel_pmu_raw_event, + .raw_event = x86_pmu_raw_event, .max_events = ARRAY_SIZE(intel_perfmon_event_map), .apic = 1, /* @@ -827,7 +809,7 @@ static __initconst struct x86_pmu intel_pmu = { .eventsel = MSR_ARCH_PERFMON_EVENTSEL0, .perfctr = MSR_ARCH_PERFMON_PERFCTR0, .event_map = intel_pmu_event_map, - .raw_event = intel_pmu_raw_event, + .raw_event = x86_pmu_raw_event, .max_events = ARRAY_SIZE(intel_perfmon_event_map), .apic = 1, /* diff --git a/arch/x86/kernel/cpu/perf_event_p6.c b/arch/x86/kernel/cpu/perf_event_p6.c index b26fbc7e..03c139a 100644 --- a/arch/x86/kernel/cpu/perf_event_p6.c +++ b/arch/x86/kernel/cpu/perf_event_p6.c @@ -27,24 +27,6 @@ static u64 p6_pmu_event_map(int hw_event) */ #define P6_NOP_EVENT 0x0000002EULL -static u64 p6_pmu_raw_event(u64 hw_event) -{ -#define P6_EVNTSEL_EVENT_MASK 0x000000FFULL -#define P6_EVNTSEL_UNIT_MASK 0x0000FF00ULL -#define P6_EVNTSEL_EDGE_MASK 0x00040000ULL -#define P6_EVNTSEL_INV_MASK 0x00800000ULL -#define P6_EVNTSEL_REG_MASK 0xFF000000ULL - -#define P6_EVNTSEL_MASK \ - (P6_EVNTSEL_EVENT_MASK | \ - P6_EVNTSEL_UNIT_MASK | \ - P6_EVNTSEL_EDGE_MASK | \ - P6_EVNTSEL_INV_MASK | \ - P6_EVNTSEL_REG_MASK) - - return hw_event & P6_EVNTSEL_MASK; -} - static struct event_constraint p6_event_constraints[] = { INTEL_EVENT_CONSTRAINT(0xc1, 0x1), /* FLOPS */ @@ -114,7 +96,7 @@ static __initconst struct x86_pmu p6_pmu = { .eventsel = MSR_P6_EVNTSEL0, .perfctr = MSR_P6_PERFCTR0, .event_map = p6_pmu_event_map, - .raw_event = p6_pmu_raw_event, + .raw_event = x86_pmu_raw_event, .max_events = ARRAY_SIZE(p6_perfmon_event_map), .apic = 1, .max_period = (1ULL << 31) - 1, -- cgit v0.10.2 From b4cdc5c264b35c67007800dec3928e9547a9d70b Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 30 Mar 2010 17:00:06 +0200 Subject: perf, x86: Fix up the ANY flag stuff Stephane noticed that the ANY flag was in generic arch code, and Cyrill reported that it broke the P4 code. Solve this by merging x86_pmu::raw_event into x86_pmu::hw_config and provide intel_pmu and amd_pmu specific versions of this callback. The intel_pmu one deals with the ANY flag, the amd_pmu adds the few extra event bits AMD64 has. Reported-by: Stephane Eranian Reported-by: Cyrill Gorcunov Acked-by: Robert Richter Acked-by: Cyrill Gorcunov Acked-by: Stephane Eranian Signed-off-by: Peter Zijlstra LKML-Reference: <1269968113.5258.442.camel@laptop> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 1dd42c1..65e9c5e 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -196,12 +196,11 @@ struct x86_pmu { void (*enable_all)(int added); void (*enable)(struct perf_event *); void (*disable)(struct perf_event *); - int (*hw_config)(struct perf_event_attr *attr, struct hw_perf_event *hwc); + int (*hw_config)(struct perf_event *event); int (*schedule_events)(struct cpu_hw_events *cpuc, int n, int *assign); unsigned eventsel; unsigned perfctr; u64 (*event_map)(int); - u64 (*raw_event)(u64); int max_events; int num_counters; int num_counters_fixed; @@ -426,28 +425,26 @@ set_ext_hw_attr(struct hw_perf_event *hwc, struct perf_event_attr *attr) return 0; } -static int x86_hw_config(struct perf_event_attr *attr, struct hw_perf_event *hwc) +static int x86_pmu_hw_config(struct perf_event *event) { /* * Generate PMC IRQs: * (keep 'enabled' bit clear for now) */ - hwc->config = ARCH_PERFMON_EVENTSEL_INT; + event->hw.config = ARCH_PERFMON_EVENTSEL_INT; /* * Count user and OS events unless requested not to */ - if (!attr->exclude_user) - hwc->config |= ARCH_PERFMON_EVENTSEL_USR; - if (!attr->exclude_kernel) - hwc->config |= ARCH_PERFMON_EVENTSEL_OS; + if (!event->attr.exclude_user) + event->hw.config |= ARCH_PERFMON_EVENTSEL_USR; + if (!event->attr.exclude_kernel) + event->hw.config |= ARCH_PERFMON_EVENTSEL_OS; - return 0; -} + if (event->attr.type == PERF_TYPE_RAW) + event->hw.config |= event->attr.config & X86_RAW_EVENT_MASK; -static u64 x86_pmu_raw_event(u64 hw_event) -{ - return hw_event & X86_RAW_EVENT_MASK; + return 0; } /* @@ -489,7 +486,7 @@ static int __hw_perf_event_init(struct perf_event *event) hwc->last_tag = ~0ULL; /* Processor specifics */ - err = x86_pmu.hw_config(attr, hwc); + err = x86_pmu.hw_config(event); if (err) return err; @@ -508,16 +505,8 @@ static int __hw_perf_event_init(struct perf_event *event) return -EOPNOTSUPP; } - /* - * Raw hw_event type provide the config in the hw_event structure - */ - if (attr->type == PERF_TYPE_RAW) { - hwc->config |= x86_pmu.raw_event(attr->config); - if ((hwc->config & ARCH_PERFMON_EVENTSEL_ANY) && - perf_paranoid_cpu() && !capable(CAP_SYS_ADMIN)) - return -EACCES; + if (attr->type == PERF_TYPE_RAW) return 0; - } if (attr->type == PERF_TYPE_HW_CACHE) return set_ext_hw_attr(hwc, attr); diff --git a/arch/x86/kernel/cpu/perf_event_amd.c b/arch/x86/kernel/cpu/perf_event_amd.c index 37e9517..bbd7339 100644 --- a/arch/x86/kernel/cpu/perf_event_amd.c +++ b/arch/x86/kernel/cpu/perf_event_amd.c @@ -111,9 +111,19 @@ static u64 amd_pmu_event_map(int hw_event) return amd_perfmon_event_map[hw_event]; } -static u64 amd_pmu_raw_event(u64 hw_event) +static int amd_pmu_hw_config(struct perf_event *event) { - return hw_event & AMD64_RAW_EVENT_MASK; + int ret = x86_pmu_hw_config(event); + + if (ret) + return ret; + + if (event->attr.type != PERF_TYPE_RAW) + return 0; + + event->hw.config |= event->attr.config & AMD64_RAW_EVENT_MASK; + + return 0; } /* @@ -365,12 +375,11 @@ static __initconst struct x86_pmu amd_pmu = { .enable_all = x86_pmu_enable_all, .enable = x86_pmu_enable_event, .disable = x86_pmu_disable_event, - .hw_config = x86_hw_config, + .hw_config = amd_pmu_hw_config, .schedule_events = x86_schedule_events, .eventsel = MSR_K7_EVNTSEL0, .perfctr = MSR_K7_PERFCTR0, .event_map = amd_pmu_event_map, - .raw_event = amd_pmu_raw_event, .max_events = ARRAY_SIZE(amd_perfmon_event_map), .num_counters = 4, .cntval_bits = 48, diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index dfdd6f9..30bf10c 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -758,6 +758,30 @@ intel_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event return x86_get_event_constraints(cpuc, event); } +static int intel_pmu_hw_config(struct perf_event *event) +{ + int ret = x86_pmu_hw_config(event); + + if (ret) + return ret; + + if (event->attr.type != PERF_TYPE_RAW) + return 0; + + if (!(event->attr.config & ARCH_PERFMON_EVENTSEL_ANY)) + return 0; + + if (x86_pmu.version < 3) + return -EINVAL; + + if (perf_paranoid_cpu() && !capable(CAP_SYS_ADMIN)) + return -EACCES; + + event->hw.config |= ARCH_PERFMON_EVENTSEL_ANY; + + return 0; +} + static __initconst struct x86_pmu core_pmu = { .name = "core", .handle_irq = x86_pmu_handle_irq, @@ -765,12 +789,11 @@ static __initconst struct x86_pmu core_pmu = { .enable_all = x86_pmu_enable_all, .enable = x86_pmu_enable_event, .disable = x86_pmu_disable_event, - .hw_config = x86_hw_config, + .hw_config = x86_pmu_hw_config, .schedule_events = x86_schedule_events, .eventsel = MSR_ARCH_PERFMON_EVENTSEL0, .perfctr = MSR_ARCH_PERFMON_PERFCTR0, .event_map = intel_pmu_event_map, - .raw_event = x86_pmu_raw_event, .max_events = ARRAY_SIZE(intel_perfmon_event_map), .apic = 1, /* @@ -804,12 +827,11 @@ static __initconst struct x86_pmu intel_pmu = { .enable_all = intel_pmu_enable_all, .enable = intel_pmu_enable_event, .disable = intel_pmu_disable_event, - .hw_config = x86_hw_config, + .hw_config = intel_pmu_hw_config, .schedule_events = x86_schedule_events, .eventsel = MSR_ARCH_PERFMON_EVENTSEL0, .perfctr = MSR_ARCH_PERFMON_PERFCTR0, .event_map = intel_pmu_event_map, - .raw_event = x86_pmu_raw_event, .max_events = ARRAY_SIZE(intel_perfmon_event_map), .apic = 1, /* diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index 4139100..acd237d 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c @@ -419,20 +419,7 @@ static u64 p4_pmu_event_map(int hw_event) return config; } -/* - * We don't control raw events so it's up to the caller - * to pass sane values (and we don't count the thread number - * on HT machine but allow HT-compatible specifics to be - * passed on) - */ -static u64 p4_pmu_raw_event(u64 hw_event) -{ - return hw_event & - (p4_config_pack_escr(P4_ESCR_MASK_HT) | - p4_config_pack_cccr(P4_CCCR_MASK_HT)); -} - -static int p4_hw_config(struct perf_event_attr *attr, struct hw_perf_event *hwc) +static int p4_hw_config(struct perf_event *event) { int cpu = raw_smp_processor_id(); u32 escr, cccr; @@ -444,11 +431,29 @@ static int p4_hw_config(struct perf_event_attr *attr, struct hw_perf_event *hwc) */ cccr = p4_default_cccr_conf(cpu); - escr = p4_default_escr_conf(cpu, attr->exclude_kernel, attr->exclude_user); - hwc->config = p4_config_pack_escr(escr) | p4_config_pack_cccr(cccr); + escr = p4_default_escr_conf(cpu, event->attr.exclude_kernel, + event->attr.exclude_user); + event->hw.config = p4_config_pack_escr(escr) | + p4_config_pack_cccr(cccr); if (p4_ht_active() && p4_ht_thread(cpu)) - hwc->config = p4_set_ht_bit(hwc->config); + event->hw.config = p4_set_ht_bit(event->hw.config); + + if (event->attr.type != PERF_TYPE_RAW) + return 0; + + /* + * We don't control raw events so it's up to the caller + * to pass sane values (and we don't count the thread number + * on HT machine but allow HT-compatible specifics to be + * passed on) + * + * XXX: HT wide things should check perf_paranoid_cpu() && + * CAP_SYS_ADMIN + */ + event->hw.config |= event->attr.config & + (p4_config_pack_escr(P4_ESCR_MASK_HT) | + p4_config_pack_cccr(P4_CCCR_MASK_HT)); return 0; } @@ -785,7 +790,6 @@ static __initconst struct x86_pmu p4_pmu = { .eventsel = MSR_P4_BPU_CCCR0, .perfctr = MSR_P4_BPU_PERFCTR0, .event_map = p4_pmu_event_map, - .raw_event = p4_pmu_raw_event, .max_events = ARRAY_SIZE(p4_general_events), .get_event_constraints = x86_get_event_constraints, /* diff --git a/arch/x86/kernel/cpu/perf_event_p6.c b/arch/x86/kernel/cpu/perf_event_p6.c index 03c139a..9123e8e 100644 --- a/arch/x86/kernel/cpu/perf_event_p6.c +++ b/arch/x86/kernel/cpu/perf_event_p6.c @@ -91,12 +91,11 @@ static __initconst struct x86_pmu p6_pmu = { .enable_all = p6_pmu_enable_all, .enable = p6_pmu_enable_event, .disable = p6_pmu_disable_event, - .hw_config = x86_hw_config, + .hw_config = x86_pmu_hw_config, .schedule_events = x86_schedule_events, .eventsel = MSR_P6_EVNTSEL0, .perfctr = MSR_P6_PERFCTR0, .event_map = p6_pmu_event_map, - .raw_event = x86_pmu_raw_event, .max_events = ARRAY_SIZE(p6_perfmon_event_map), .apic = 1, .max_period = (1ULL << 31) - 1, -- cgit v0.10.2 From caaa8be3b6707cb9664e573a28b00f845ce9f32e Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 29 Mar 2010 13:09:53 +0200 Subject: perf, x86: Fix __initconst vs const All variables that have __initconst should also be const. Suggested-by: Stephen Rothwell Signed-off-by: Peter Zijlstra LKML-Reference: Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event_amd.c b/arch/x86/kernel/cpu/perf_event_amd.c index bbd7339..611df11 100644 --- a/arch/x86/kernel/cpu/perf_event_amd.c +++ b/arch/x86/kernel/cpu/perf_event_amd.c @@ -2,7 +2,7 @@ static DEFINE_RAW_SPINLOCK(amd_nb_lock); -static __initconst u64 amd_hw_cache_event_ids +static __initconst const u64 amd_hw_cache_event_ids [PERF_COUNT_HW_CACHE_MAX] [PERF_COUNT_HW_CACHE_OP_MAX] [PERF_COUNT_HW_CACHE_RESULT_MAX] = @@ -368,7 +368,7 @@ static void amd_pmu_cpu_dead(int cpu) raw_spin_unlock(&amd_nb_lock); } -static __initconst struct x86_pmu amd_pmu = { +static __initconst const struct x86_pmu amd_pmu = { .name = "AMD", .handle_irq = x86_pmu_handle_irq, .disable_all = x86_pmu_disable_all, diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 30bf10c..1957e3f 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -88,7 +88,7 @@ static u64 intel_pmu_event_map(int hw_event) return intel_perfmon_event_map[hw_event]; } -static __initconst u64 westmere_hw_cache_event_ids +static __initconst const u64 westmere_hw_cache_event_ids [PERF_COUNT_HW_CACHE_MAX] [PERF_COUNT_HW_CACHE_OP_MAX] [PERF_COUNT_HW_CACHE_RESULT_MAX] = @@ -179,7 +179,7 @@ static __initconst u64 westmere_hw_cache_event_ids }, }; -static __initconst u64 nehalem_hw_cache_event_ids +static __initconst const u64 nehalem_hw_cache_event_ids [PERF_COUNT_HW_CACHE_MAX] [PERF_COUNT_HW_CACHE_OP_MAX] [PERF_COUNT_HW_CACHE_RESULT_MAX] = @@ -270,7 +270,7 @@ static __initconst u64 nehalem_hw_cache_event_ids }, }; -static __initconst u64 core2_hw_cache_event_ids +static __initconst const u64 core2_hw_cache_event_ids [PERF_COUNT_HW_CACHE_MAX] [PERF_COUNT_HW_CACHE_OP_MAX] [PERF_COUNT_HW_CACHE_RESULT_MAX] = @@ -361,7 +361,7 @@ static __initconst u64 core2_hw_cache_event_ids }, }; -static __initconst u64 atom_hw_cache_event_ids +static __initconst const u64 atom_hw_cache_event_ids [PERF_COUNT_HW_CACHE_MAX] [PERF_COUNT_HW_CACHE_OP_MAX] [PERF_COUNT_HW_CACHE_RESULT_MAX] = @@ -782,7 +782,7 @@ static int intel_pmu_hw_config(struct perf_event *event) return 0; } -static __initconst struct x86_pmu core_pmu = { +static __initconst const struct x86_pmu core_pmu = { .name = "core", .handle_irq = x86_pmu_handle_irq, .disable_all = x86_pmu_disable_all, @@ -820,7 +820,7 @@ static void intel_pmu_cpu_dying(int cpu) fini_debug_store_on_cpu(cpu); } -static __initconst struct x86_pmu intel_pmu = { +static __initconst const struct x86_pmu intel_pmu = { .name = "Intel", .handle_irq = intel_pmu_handle_irq, .disable_all = intel_pmu_disable_all, diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index acd237d..15367cc 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c @@ -287,7 +287,7 @@ static struct p4_event_bind p4_event_bind_map[] = { p4_config_pack_cccr(cache_event | \ P4_CCCR_ESEL(P4_OPCODE_ESEL(P4_OPCODE(event)))) -static __initconst u64 p4_hw_cache_event_ids +static __initconst const u64 p4_hw_cache_event_ids [PERF_COUNT_HW_CACHE_MAX] [PERF_COUNT_HW_CACHE_OP_MAX] [PERF_COUNT_HW_CACHE_RESULT_MAX] = @@ -780,7 +780,7 @@ done: return num ? -ENOSPC : 0; } -static __initconst struct x86_pmu p4_pmu = { +static __initconst const struct x86_pmu p4_pmu = { .name = "Netburst P4/Xeon", .handle_irq = p4_pmu_handle_irq, .disable_all = p4_pmu_disable_all, diff --git a/arch/x86/kernel/cpu/perf_event_p6.c b/arch/x86/kernel/cpu/perf_event_p6.c index 9123e8e..34ba07b 100644 --- a/arch/x86/kernel/cpu/perf_event_p6.c +++ b/arch/x86/kernel/cpu/perf_event_p6.c @@ -84,7 +84,7 @@ static void p6_pmu_enable_event(struct perf_event *event) (void)checking_wrmsrl(hwc->config_base + hwc->idx, val); } -static __initconst struct x86_pmu p6_pmu = { +static __initconst const struct x86_pmu p6_pmu = { .name = "p6", .handle_irq = x86_pmu_handle_irq, .disable_all = p6_pmu_disable_all, -- cgit v0.10.2 From 40b91cd10f000b4c4934e48e2e5c0bec66def144 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 29 Mar 2010 16:37:17 +0200 Subject: perf, x86: Add Nehalem programming quirk to Westmere According to the Xeon-5600 errata the Westmere suffers the same PMU programming bug as the original Nehalem did. Signed-off-by: Peter Zijlstra LKML-Reference: Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 1957e3f..f168b40 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -488,6 +488,7 @@ static void intel_pmu_enable_all(int added) * Workaround for: * Intel Errata AAK100 (model 26) * Intel Errata AAP53 (model 30) + * Intel Errata BD53 (model 44) * * These chips need to be 'reset' when adding counters by programming * the magic three (non counting) events 0x4300D2, 0x4300B1 and 0x4300B5 @@ -980,6 +981,7 @@ static __init int intel_pmu_init(void) intel_pmu_lbr_init_nhm(); x86_pmu.event_constraints = intel_westmere_event_constraints; + x86_pmu.enable_all = intel_pmu_nhm_enable_all; pr_cont("Westmere events, "); break; -- cgit v0.10.2 From 32bd7eb5a7f4596c8440dd9440322fe9e686634d Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Wed, 24 Mar 2010 13:17:19 +0800 Subject: sched: Remove remaining USER_SCHED code This is left over from commit 7c9414385e ("sched: Remove USER_SCHED"") Signed-off-by: Li Zefan Acked-by: Dhaval Giani Signed-off-by: Peter Zijlstra Cc: David Howells LKML-Reference: <4BA9A05F.7010407@cn.fujitsu.com> Signed-off-by: Ingo Molnar diff --git a/init/Kconfig b/init/Kconfig index eb77e8c..5fe94b8 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -604,8 +604,7 @@ config RT_GROUP_SCHED default n help This feature lets you explicitly allocate real CPU bandwidth - to users or control groups (depending on the "Basis for grouping tasks" - setting below. If enabled, it will also make it impossible to + to task groups. If enabled, it will also make it impossible to schedule realtime tasks for non-root users until you allocate realtime bandwidth for them. See Documentation/scheduler/sched-rt-group.txt for more information. diff --git a/kernel/capability.c b/kernel/capability.c index 9e4697e..2f05303 100644 --- a/kernel/capability.c +++ b/kernel/capability.c @@ -15,7 +15,6 @@ #include #include #include -#include "cred-internals.h" /* * Leveraged for setting/resetting capabilities diff --git a/kernel/cred-internals.h b/kernel/cred-internals.h deleted file mode 100644 index 2dc4fc2..0000000 --- a/kernel/cred-internals.h +++ /dev/null @@ -1,21 +0,0 @@ -/* Internal credentials stuff - * - * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public Licence - * as published by the Free Software Foundation; either version - * 2 of the Licence, or (at your option) any later version. - */ - -/* - * user.c - */ -static inline void sched_switch_user(struct task_struct *p) -{ -#ifdef CONFIG_USER_SCHED - sched_move_task(p); -#endif /* CONFIG_USER_SCHED */ -} - diff --git a/kernel/cred.c b/kernel/cred.c index 1b1129d..19d3ccc 100644 --- a/kernel/cred.c +++ b/kernel/cred.c @@ -16,7 +16,6 @@ #include #include #include -#include "cred-internals.h" #if 0 #define kdebug(FMT, ...) \ @@ -557,8 +556,6 @@ int commit_creds(struct cred *new) atomic_dec(&old->user->processes); alter_cred_subscribers(old, -2); - sched_switch_user(task); - /* send notifications */ if (new->uid != old->uid || new->euid != old->euid || diff --git a/kernel/exit.c b/kernel/exit.c index cce59cb..84dc4b2 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -55,7 +55,6 @@ #include #include #include -#include "cred-internals.h" static void exit_mm(struct task_struct * tsk); diff --git a/kernel/sched_debug.c b/kernel/sched_debug.c index 8a46a71..0932c5c 100644 --- a/kernel/sched_debug.c +++ b/kernel/sched_debug.c @@ -173,11 +173,6 @@ void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq) task_group_path(tg, path, sizeof(path)); SEQ_printf(m, "\ncfs_rq[%d]:%s\n", cpu, path); -#elif defined(CONFIG_USER_SCHED) && defined(CONFIG_FAIR_GROUP_SCHED) - { - uid_t uid = cfs_rq->tg->uid; - SEQ_printf(m, "\ncfs_rq[%d] for UID: %u\n", cpu, uid); - } #else SEQ_printf(m, "\ncfs_rq[%d]:\n", cpu); #endif diff --git a/kernel/user.c b/kernel/user.c index ec3b222..8e1c8c0 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -16,7 +16,6 @@ #include #include #include -#include "cred-internals.h" struct user_namespace init_user_ns = { .kref = { @@ -137,9 +136,7 @@ struct user_struct *alloc_uid(struct user_namespace *ns, uid_t uid) struct hlist_head *hashent = uidhashentry(ns, uid); struct user_struct *up, *new; - /* Make uid_hash_find() + uids_user_create() + uid_hash_insert() - * atomic. - */ + /* Make uid_hash_find() + uid_hash_insert() atomic. */ spin_lock_irq(&uidhash_lock); up = uid_hash_find(uid, hashent); spin_unlock_irq(&uidhash_lock); @@ -161,11 +158,6 @@ struct user_struct *alloc_uid(struct user_namespace *ns, uid_t uid) spin_lock_irq(&uidhash_lock); up = uid_hash_find(uid, hashent); if (up) { - /* This case is not possible when CONFIG_USER_SCHED - * is defined, since we serialize alloc_uid() using - * uids_mutex. Hence no need to call - * sched_destroy_user() or remove_user_sysfs_dir(). - */ key_put(new->uid_keyring); key_put(new->session_keyring); kmem_cache_free(uid_cachep, new); -- cgit v0.10.2 From 25c2d55c00c6097e6792ebf21e31342f23b9b768 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Wed, 24 Mar 2010 13:17:50 +0800 Subject: sched: Remove USER_SCHED from documentation USER_SCHED has been removed, so update the documentation accordingly. Signed-off-by: Li Zefan Signed-off-by: Peter Zijlstra Acked-by: Serge E. Hallyn LKML-Reference: <4BA9A07E.8070508@cn.fujitsu.com> Signed-off-by: Ingo Molnar diff --git a/Documentation/scheduler/sched-design-CFS.txt b/Documentation/scheduler/sched-design-CFS.txt index 6f33593..8239ebb 100644 --- a/Documentation/scheduler/sched-design-CFS.txt +++ b/Documentation/scheduler/sched-design-CFS.txt @@ -211,7 +211,7 @@ provide fair CPU time to each such task group. For example, it may be desirable to first provide fair CPU time to each user on the system and then to each task belonging to a user. -CONFIG_GROUP_SCHED strives to achieve exactly that. It lets tasks to be +CONFIG_CGROUP_SCHED strives to achieve exactly that. It lets tasks to be grouped and divides CPU time fairly among such groups. CONFIG_RT_GROUP_SCHED permits to group real-time (i.e., SCHED_FIFO and @@ -220,38 +220,11 @@ SCHED_RR) tasks. CONFIG_FAIR_GROUP_SCHED permits to group CFS (i.e., SCHED_NORMAL and SCHED_BATCH) tasks. -At present, there are two (mutually exclusive) mechanisms to group tasks for -CPU bandwidth control purposes: - - - Based on user id (CONFIG_USER_SCHED) - - With this option, tasks are grouped according to their user id. - - - Based on "cgroup" pseudo filesystem (CONFIG_CGROUP_SCHED) - - This options needs CONFIG_CGROUPS to be defined, and lets the administrator + These options need CONFIG_CGROUPS to be defined, and let the administrator create arbitrary groups of tasks, using the "cgroup" pseudo filesystem. See Documentation/cgroups/cgroups.txt for more information about this filesystem. -Only one of these options to group tasks can be chosen and not both. - -When CONFIG_USER_SCHED is defined, a directory is created in sysfs for each new -user and a "cpu_share" file is added in that directory. - - # cd /sys/kernel/uids - # cat 512/cpu_share # Display user 512's CPU share - 1024 - # echo 2048 > 512/cpu_share # Modify user 512's CPU share - # cat 512/cpu_share # Display user 512's CPU share - 2048 - # - -CPU bandwidth between two users is divided in the ratio of their CPU shares. -For example: if you would like user "root" to get twice the bandwidth of user -"guest," then set the cpu_share for both the users such that "root"'s cpu_share -is twice "guest"'s cpu_share. - -When CONFIG_CGROUP_SCHED is defined, a "cpu.shares" file is created for each +When CONFIG_FAIR_GROUP_SCHED is defined, a "cpu.shares" file is created for each group created using the pseudo filesystem. See example steps below to create task groups and modify their CPU share using the "cgroups" pseudo filesystem. @@ -273,24 +246,3 @@ task groups and modify their CPU share using the "cgroups" pseudo filesystem. # #Launch gmplayer (or your favourite movie player) # echo > multimedia/tasks - -8. Implementation note: user namespaces - -User namespaces are intended to be hierarchical. But they are currently -only partially implemented. Each of those has ramifications for CFS. - -First, since user namespaces are hierarchical, the /sys/kernel/uids -presentation is inadequate. Eventually we will likely want to use sysfs -tagging to provide private views of /sys/kernel/uids within each user -namespace. - -Second, the hierarchical nature is intended to support completely -unprivileged use of user namespaces. So if using user groups, then -we want the users in a user namespace to be children of the user -who created it. - -That is currently unimplemented. So instead, every user in a new -user namespace will receive 1024 shares just like any user in the -initial user namespace. Note that at the moment creation of a new -user namespace requires each of CAP_SYS_ADMIN, CAP_SETUID, and -CAP_SETGID. diff --git a/Documentation/scheduler/sched-rt-group.txt b/Documentation/scheduler/sched-rt-group.txt index 86eabe6..605b0d4 100644 --- a/Documentation/scheduler/sched-rt-group.txt +++ b/Documentation/scheduler/sched-rt-group.txt @@ -126,23 +126,12 @@ priority! 2.3 Basis for grouping tasks ---------------------------- -There are two compile-time settings for allocating CPU bandwidth. These are -configured using the "Basis for grouping tasks" multiple choice menu under -General setup > Group CPU Scheduler: - -a. CONFIG_USER_SCHED (aka "Basis for grouping tasks" = "user id") - -This lets you use the virtual files under -"/sys/kernel/uids//cpu_rt_runtime_us" to control he CPU time reserved for -each user . - -The other option is: - -.o CONFIG_CGROUP_SCHED (aka "Basis for grouping tasks" = "Control groups") +Enabling CONFIG_RT_GROUP_SCHED lets you explicitly allocate real +CPU bandwidth to task groups. This uses the /cgroup virtual file system and "/cgroup//cpu.rt_runtime_us" to control the CPU time reserved for each -control group instead. +control group. For more information on working with control groups, you should read Documentation/cgroups/cgroups.txt as well. @@ -161,8 +150,7 @@ For now, this can be simplified to just the following (but see Future plans): =============== There is work in progress to make the scheduling period for each group -("/sys/kernel/uids//cpu_rt_period_us" or -"/cgroup//cpu.rt_period_us" respectively) configurable as well. +("/cgroup//cpu.rt_period_us") configurable as well. The constraint on the period is that a subgroup must have a smaller or equal period to its parent. But realistically its not very useful _yet_ -- cgit v0.10.2 From 897f0b3c3ff40b443c84e271bef19bd6ae885195 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Mon, 15 Mar 2010 10:10:03 +0100 Subject: sched: Kill the broken and deadlockable cpuset_lock/cpuset_cpus_allowed_locked code This patch just states the fact the cpusets/cpuhotplug interaction is broken and removes the deadlockable code which only pretends to work. - cpuset_lock() doesn't really work. It is needed for cpuset_cpus_allowed_locked() but we can't take this lock in try_to_wake_up()->select_fallback_rq() path. - cpuset_lock() is deadlockable. Suppose that a task T bound to CPU takes callback_mutex. If cpu_down(CPU) happens before T drops callback_mutex stop_machine() preempts T, then migration_call(CPU_DEAD) tries to take cpuset_lock() and hangs forever because CPU is already dead and thus T can't be scheduled. - cpuset_cpus_allowed_locked() is deadlockable too. It takes task_lock() which is not irq-safe, but try_to_wake_up() can be called from irq. Kill them, and change select_fallback_rq() to use cpu_possible_mask, like we currently do without CONFIG_CPUSETS. Also, with or without this patch, with or without CONFIG_CPUSETS, the callers of select_fallback_rq() can race with each other or with set_cpus_allowed() pathes. The subsequent patches try to to fix these problems. Signed-off-by: Oleg Nesterov Signed-off-by: Peter Zijlstra LKML-Reference: <20100315091003.GA9123@redhat.com> Signed-off-by: Ingo Molnar diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h index a5740fc..eeaaee7 100644 --- a/include/linux/cpuset.h +++ b/include/linux/cpuset.h @@ -21,8 +21,6 @@ extern int number_of_cpusets; /* How many cpusets are defined in system? */ extern int cpuset_init(void); extern void cpuset_init_smp(void); extern void cpuset_cpus_allowed(struct task_struct *p, struct cpumask *mask); -extern void cpuset_cpus_allowed_locked(struct task_struct *p, - struct cpumask *mask); extern nodemask_t cpuset_mems_allowed(struct task_struct *p); #define cpuset_current_mems_allowed (current->mems_allowed) void cpuset_init_current_mems_allowed(void); @@ -69,9 +67,6 @@ struct seq_file; extern void cpuset_task_status_allowed(struct seq_file *m, struct task_struct *task); -extern void cpuset_lock(void); -extern void cpuset_unlock(void); - extern int cpuset_mem_spread_node(void); static inline int cpuset_do_page_mem_spread(void) @@ -105,11 +100,6 @@ static inline void cpuset_cpus_allowed(struct task_struct *p, { cpumask_copy(mask, cpu_possible_mask); } -static inline void cpuset_cpus_allowed_locked(struct task_struct *p, - struct cpumask *mask) -{ - cpumask_copy(mask, cpu_possible_mask); -} static inline nodemask_t cpuset_mems_allowed(struct task_struct *p) { @@ -157,9 +147,6 @@ static inline void cpuset_task_status_allowed(struct seq_file *m, { } -static inline void cpuset_lock(void) {} -static inline void cpuset_unlock(void) {} - static inline int cpuset_mem_spread_node(void) { return 0; diff --git a/kernel/cpuset.c b/kernel/cpuset.c index d109467..9a747f5 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -2182,19 +2182,10 @@ void __init cpuset_init_smp(void) void cpuset_cpus_allowed(struct task_struct *tsk, struct cpumask *pmask) { mutex_lock(&callback_mutex); - cpuset_cpus_allowed_locked(tsk, pmask); - mutex_unlock(&callback_mutex); -} - -/** - * cpuset_cpus_allowed_locked - return cpus_allowed mask from a tasks cpuset. - * Must be called with callback_mutex held. - **/ -void cpuset_cpus_allowed_locked(struct task_struct *tsk, struct cpumask *pmask) -{ task_lock(tsk); guarantee_online_cpus(task_cs(tsk), pmask); task_unlock(tsk); + mutex_unlock(&callback_mutex); } void cpuset_init_current_mems_allowed(void) @@ -2383,22 +2374,6 @@ int __cpuset_node_allowed_hardwall(int node, gfp_t gfp_mask) } /** - * cpuset_lock - lock out any changes to cpuset structures - * - * The out of memory (oom) code needs to mutex_lock cpusets - * from being changed while it scans the tasklist looking for a - * task in an overlapping cpuset. Expose callback_mutex via this - * cpuset_lock() routine, so the oom code can lock it, before - * locking the task list. The tasklist_lock is a spinlock, so - * must be taken inside callback_mutex. - */ - -void cpuset_lock(void) -{ - mutex_lock(&callback_mutex); -} - -/** * cpuset_unlock - release lock on cpuset changes * * Undo the lock taken in a previous cpuset_lock() call. diff --git a/kernel/sched.c b/kernel/sched.c index 52b7efd2..c0b3ebc 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -2296,11 +2296,9 @@ static int select_fallback_rq(int cpu, struct task_struct *p) return dest_cpu; /* No more Mr. Nice Guy. */ - if (dest_cpu >= nr_cpu_ids) { - rcu_read_lock(); - cpuset_cpus_allowed_locked(p, &p->cpus_allowed); - rcu_read_unlock(); - dest_cpu = cpumask_any_and(cpu_active_mask, &p->cpus_allowed); + if (unlikely(dest_cpu >= nr_cpu_ids)) { + cpumask_copy(&p->cpus_allowed, cpu_possible_mask); + dest_cpu = cpumask_any(cpu_active_mask); /* * Don't tell them about moving exiting tasks or @@ -5866,7 +5864,6 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu) case CPU_DEAD: case CPU_DEAD_FROZEN: - cpuset_lock(); /* around calls to cpuset_cpus_allowed_lock() */ migrate_live_tasks(cpu); rq = cpu_rq(cpu); kthread_stop(rq->migration_thread); @@ -5879,7 +5876,6 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu) rq->idle->sched_class = &idle_sched_class; migrate_dead_tasks(cpu); raw_spin_unlock_irq(&rq->lock); - cpuset_unlock(); migrate_nr_uninterruptible(rq); BUG_ON(rq->nr_running != 0); calc_global_load_remove(rq); -- cgit v0.10.2 From 1445c08d06c5594895b4fae952ef8a457e89c390 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Mon, 15 Mar 2010 10:10:10 +0100 Subject: sched: move_task_off_dead_cpu(): Take rq->lock around select_fallback_rq() move_task_off_dead_cpu()->select_fallback_rq() reads/updates ->cpus_allowed lockless. We can race with set_cpus_allowed() running in parallel. Change it to take rq->lock around select_fallback_rq(). Note that it is not trivial to move this spin_lock() into select_fallback_rq(), we must recheck the task was not migrated after we take the lock and other callers do not need this lock. To avoid the races with other callers of select_fallback_rq() which rely on TASK_WAKING, we also check p->state != TASK_WAKING and do nothing otherwise. The owner of TASK_WAKING must update ->cpus_allowed and choose the correct CPU anyway, and the subsequent __migrate_task() is just meaningless because p->se.on_rq must be false. Alternatively, we could change select_task_rq() to take rq->lock right after it calls sched_class->select_task_rq(), but this looks a bit ugly. Also, change it to not assume irqs are disabled and absorb __migrate_task_irq(). Signed-off-by: Oleg Nesterov Signed-off-by: Peter Zijlstra LKML-Reference: <20100315091010.GA9131@redhat.com> Signed-off-by: Ingo Molnar diff --git a/kernel/sched.c b/kernel/sched.c index c0b3ebc..27774b5 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -5448,29 +5448,29 @@ static int migration_thread(void *data) } #ifdef CONFIG_HOTPLUG_CPU - -static int __migrate_task_irq(struct task_struct *p, int src_cpu, int dest_cpu) -{ - int ret; - - local_irq_disable(); - ret = __migrate_task(p, src_cpu, dest_cpu); - local_irq_enable(); - return ret; -} - /* * Figure out where task on dead CPU should go, use force if necessary. */ static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *p) { - int dest_cpu; - + struct rq *rq = cpu_rq(dead_cpu); + int needs_cpu, uninitialized_var(dest_cpu); + unsigned long flags; again: - dest_cpu = select_fallback_rq(dead_cpu, p); + local_irq_save(flags); + + raw_spin_lock(&rq->lock); + needs_cpu = (task_cpu(p) == dead_cpu) && (p->state != TASK_WAKING); + if (needs_cpu) + dest_cpu = select_fallback_rq(dead_cpu, p); + raw_spin_unlock(&rq->lock); /* It can have affinity changed while we were choosing. */ - if (unlikely(!__migrate_task_irq(p, dead_cpu, dest_cpu))) + if (needs_cpu) + needs_cpu = !__migrate_task(p, dead_cpu, dest_cpu); + local_irq_restore(flags); + + if (unlikely(needs_cpu)) goto again; } -- cgit v0.10.2 From c1804d547dc098363443667609c272d1e4d15ee8 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Mon, 15 Mar 2010 10:10:14 +0100 Subject: sched: move_task_off_dead_cpu(): Remove retry logic The previous patch preserved the retry logic, but it looks unneeded. __migrate_task() can only fail if we raced with migration after we dropped the lock, but in this case the caller of set_cpus_allowed/etc must initiate migration itself if ->on_rq == T. We already fixed p->cpus_allowed, the changes in active/online masks must be visible to racer, it should migrate the task to online cpu correctly. Signed-off-by: Oleg Nesterov Signed-off-by: Peter Zijlstra LKML-Reference: <20100315091014.GA9138@redhat.com> Signed-off-by: Ingo Molnar diff --git a/kernel/sched.c b/kernel/sched.c index 27774b5..f475c60 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -5456,7 +5456,7 @@ static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *p) struct rq *rq = cpu_rq(dead_cpu); int needs_cpu, uninitialized_var(dest_cpu); unsigned long flags; -again: + local_irq_save(flags); raw_spin_lock(&rq->lock); @@ -5464,14 +5464,13 @@ again: if (needs_cpu) dest_cpu = select_fallback_rq(dead_cpu, p); raw_spin_unlock(&rq->lock); - - /* It can have affinity changed while we were choosing. */ + /* + * It can only fail if we race with set_cpus_allowed(), + * in the racer should migrate the task anyway. + */ if (needs_cpu) - needs_cpu = !__migrate_task(p, dead_cpu, dest_cpu); + __migrate_task(p, dead_cpu, dest_cpu); local_irq_restore(flags); - - if (unlikely(needs_cpu)) - goto again; } /* -- cgit v0.10.2 From 30da688ef6b76e01969b00608202fff1eed2accc Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Mon, 15 Mar 2010 10:10:19 +0100 Subject: sched: sched_exec(): Remove the select_fallback_rq() logic sched_exec()->select_task_rq() reads/updates ->cpus_allowed lockless. This can race with other CPUs updating our ->cpus_allowed, and this looks meaningless to me. The task is current and running, it must have online cpus in ->cpus_allowed, the fallback mode is bogus. And, if ->sched_class returns the "wrong" cpu, this likely means we raced with set_cpus_allowed() which was called for reason, why should sched_exec() retry and call ->select_task_rq() again? Change the code to call sched_class->select_task_rq() directly and do nothing if the returned cpu is wrong after re-checking under rq->lock. From now task_struct->cpus_allowed is always stable under TASK_WAKING, select_fallback_rq() is always called under rq-lock or the caller or the caller owns TASK_WAKING (select_task_rq). Signed-off-by: Oleg Nesterov Signed-off-by: Peter Zijlstra LKML-Reference: <20100315091019.GA9141@redhat.com> Signed-off-by: Ingo Molnar diff --git a/kernel/sched.c b/kernel/sched.c index f475c60..165b532 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -2280,6 +2280,9 @@ void task_oncpu_function_call(struct task_struct *p, } #ifdef CONFIG_SMP +/* + * ->cpus_allowed is protected by either TASK_WAKING or rq->lock held. + */ static int select_fallback_rq(int cpu, struct task_struct *p) { int dest_cpu; @@ -2316,12 +2319,7 @@ static int select_fallback_rq(int cpu, struct task_struct *p) } /* - * Gets called from 3 sites (exec, fork, wakeup), since it is called without - * holding rq->lock we need to ensure ->cpus_allowed is stable, this is done - * by: - * - * exec: is unstable, retry loop - * fork & wake-up: serialize ->cpus_allowed against TASK_WAKING + * The caller (fork, wakeup) owns TASK_WAKING, ->cpus_allowed is stable. */ static inline int select_task_rq(struct task_struct *p, int sd_flags, int wake_flags) @@ -3076,9 +3074,8 @@ void sched_exec(void) unsigned long flags; struct rq *rq; -again: this_cpu = get_cpu(); - dest_cpu = select_task_rq(p, SD_BALANCE_EXEC, 0); + dest_cpu = p->sched_class->select_task_rq(p, SD_BALANCE_EXEC, 0); if (dest_cpu == this_cpu) { put_cpu(); return; @@ -3086,18 +3083,12 @@ again: rq = task_rq_lock(p, &flags); put_cpu(); - /* * select_task_rq() can race against ->cpus_allowed */ - if (!cpumask_test_cpu(dest_cpu, &p->cpus_allowed) - || unlikely(!cpu_active(dest_cpu))) { - task_rq_unlock(rq, &flags); - goto again; - } - - /* force the process onto the specified CPU */ - if (migrate_task(p, dest_cpu, &req)) { + if (cpumask_test_cpu(dest_cpu, &p->cpus_allowed) && + likely(cpu_active(dest_cpu)) && + migrate_task(p, dest_cpu, &req)) { /* Need to wait for migration thread (might exit: take ref). */ struct task_struct *mt = rq->migration_thread; -- cgit v0.10.2 From 6a1bdc1b577ebcb65f6603c57f8347309bc4ab13 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Mon, 15 Mar 2010 10:10:23 +0100 Subject: sched: _cpu_down(): Don't play with current->cpus_allowed _cpu_down() changes the current task's affinity and then recovers it at the end. The problems are well known: we can't restore old_allowed if it was bound to the now-dead-cpu, and we can race with the userspace which can change cpu-affinity during unplug. _cpu_down() should not play with current->cpus_allowed at all. Instead, take_cpu_down() can migrate the caller of _cpu_down() after __cpu_disable() removes the dying cpu from cpu_online_mask. Signed-off-by: Oleg Nesterov Acked-by: Rafael J. Wysocki Signed-off-by: Peter Zijlstra LKML-Reference: <20100315091023.GA9148@redhat.com> Signed-off-by: Ingo Molnar diff --git a/include/linux/sched.h b/include/linux/sched.h index 43c9451..8bea407 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1843,6 +1843,7 @@ extern void sched_clock_idle_sleep_event(void); extern void sched_clock_idle_wakeup_event(u64 delta_ns); #ifdef CONFIG_HOTPLUG_CPU +extern void move_task_off_dead_cpu(int dead_cpu, struct task_struct *p); extern void idle_task_exit(void); #else static inline void idle_task_exit(void) {} diff --git a/kernel/cpu.c b/kernel/cpu.c index f8cced2..8d340fa 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -163,6 +163,7 @@ static inline void check_for_tasks(int cpu) } struct take_cpu_down_param { + struct task_struct *caller; unsigned long mod; void *hcpu; }; @@ -171,6 +172,7 @@ struct take_cpu_down_param { static int __ref take_cpu_down(void *_param) { struct take_cpu_down_param *param = _param; + unsigned int cpu = (unsigned long)param->hcpu; int err; /* Ensure this CPU doesn't handle any more interrupts. */ @@ -181,6 +183,8 @@ static int __ref take_cpu_down(void *_param) raw_notifier_call_chain(&cpu_chain, CPU_DYING | param->mod, param->hcpu); + if (task_cpu(param->caller) == cpu) + move_task_off_dead_cpu(cpu, param->caller); /* Force idle task to run as soon as we yield: it should immediately notice cpu is offline and die quickly. */ sched_idle_next(); @@ -191,10 +195,10 @@ static int __ref take_cpu_down(void *_param) static int __ref _cpu_down(unsigned int cpu, int tasks_frozen) { int err, nr_calls = 0; - cpumask_var_t old_allowed; void *hcpu = (void *)(long)cpu; unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0; struct take_cpu_down_param tcd_param = { + .caller = current, .mod = mod, .hcpu = hcpu, }; @@ -205,9 +209,6 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen) if (!cpu_online(cpu)) return -EINVAL; - if (!alloc_cpumask_var(&old_allowed, GFP_KERNEL)) - return -ENOMEM; - cpu_hotplug_begin(); set_cpu_active(cpu, false); err = __raw_notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE | mod, @@ -224,10 +225,6 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen) goto out_release; } - /* Ensure that we are not runnable on dying cpu */ - cpumask_copy(old_allowed, ¤t->cpus_allowed); - set_cpus_allowed_ptr(current, cpu_active_mask); - err = __stop_machine(take_cpu_down, &tcd_param, cpumask_of(cpu)); if (err) { set_cpu_active(cpu, true); @@ -236,7 +233,7 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen) hcpu) == NOTIFY_BAD) BUG(); - goto out_allowed; + goto out_release; } BUG_ON(cpu_online(cpu)); @@ -254,8 +251,6 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen) check_for_tasks(cpu); -out_allowed: - set_cpus_allowed_ptr(current, old_allowed); out_release: cpu_hotplug_done(); if (!err) { @@ -263,7 +258,6 @@ out_release: hcpu) == NOTIFY_BAD) BUG(); } - free_cpumask_var(old_allowed); return err; } diff --git a/kernel/sched.c b/kernel/sched.c index 165b532..11119de 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -5442,7 +5442,7 @@ static int migration_thread(void *data) /* * Figure out where task on dead CPU should go, use force if necessary. */ -static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *p) +void move_task_off_dead_cpu(int dead_cpu, struct task_struct *p) { struct rq *rq = cpu_rq(dead_cpu); int needs_cpu, uninitialized_var(dest_cpu); -- cgit v0.10.2 From 9084bb8246ea935b98320554229e2f371f7f52fa Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Mon, 15 Mar 2010 10:10:27 +0100 Subject: sched: Make select_fallback_rq() cpuset friendly Introduce cpuset_cpus_allowed_fallback() helper to fix the cpuset problems with select_fallback_rq(). It can be called from any context and can't use any cpuset locks including task_lock(). It is called when the task doesn't have online cpus in ->cpus_allowed but ttwu/etc must be able to find a suitable cpu. I am not proud of this patch. Everything which needs such a fat comment can't be good even if correct. But I'd prefer to not change the locking rules in the code I hardly understand, and in any case I believe this simple change make the code much more correct compared to deadlocks we currently have. Signed-off-by: Oleg Nesterov Signed-off-by: Peter Zijlstra LKML-Reference: <20100315091027.GA9155@redhat.com> Signed-off-by: Ingo Molnar diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h index eeaaee7..a73454a 100644 --- a/include/linux/cpuset.h +++ b/include/linux/cpuset.h @@ -21,6 +21,7 @@ extern int number_of_cpusets; /* How many cpusets are defined in system? */ extern int cpuset_init(void); extern void cpuset_init_smp(void); extern void cpuset_cpus_allowed(struct task_struct *p, struct cpumask *mask); +extern int cpuset_cpus_allowed_fallback(struct task_struct *p); extern nodemask_t cpuset_mems_allowed(struct task_struct *p); #define cpuset_current_mems_allowed (current->mems_allowed) void cpuset_init_current_mems_allowed(void); @@ -101,6 +102,12 @@ static inline void cpuset_cpus_allowed(struct task_struct *p, cpumask_copy(mask, cpu_possible_mask); } +static inline int cpuset_cpus_allowed_fallback(struct task_struct *p) +{ + cpumask_copy(&p->cpus_allowed, cpu_possible_mask); + return cpumask_any(cpu_active_mask); +} + static inline nodemask_t cpuset_mems_allowed(struct task_struct *p) { return node_possible_map; diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 9a747f5..9a50c5f 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -2188,6 +2188,48 @@ void cpuset_cpus_allowed(struct task_struct *tsk, struct cpumask *pmask) mutex_unlock(&callback_mutex); } +int cpuset_cpus_allowed_fallback(struct task_struct *tsk) +{ + const struct cpuset *cs; + int cpu; + + rcu_read_lock(); + cs = task_cs(tsk); + if (cs) + cpumask_copy(&tsk->cpus_allowed, cs->cpus_allowed); + rcu_read_unlock(); + + /* + * We own tsk->cpus_allowed, nobody can change it under us. + * + * But we used cs && cs->cpus_allowed lockless and thus can + * race with cgroup_attach_task() or update_cpumask() and get + * the wrong tsk->cpus_allowed. However, both cases imply the + * subsequent cpuset_change_cpumask()->set_cpus_allowed_ptr() + * which takes task_rq_lock(). + * + * If we are called after it dropped the lock we must see all + * changes in tsk_cs()->cpus_allowed. Otherwise we can temporary + * set any mask even if it is not right from task_cs() pov, + * the pending set_cpus_allowed_ptr() will fix things. + */ + + cpu = cpumask_any_and(&tsk->cpus_allowed, cpu_active_mask); + if (cpu >= nr_cpu_ids) { + /* + * Either tsk->cpus_allowed is wrong (see above) or it + * is actually empty. The latter case is only possible + * if we are racing with remove_tasks_in_empty_cpuset(). + * Like above we can temporary set any mask and rely on + * set_cpus_allowed_ptr() as synchronization point. + */ + cpumask_copy(&tsk->cpus_allowed, cpu_possible_mask); + cpu = cpumask_any(cpu_active_mask); + } + + return cpu; +} + void cpuset_init_current_mems_allowed(void) { nodes_setall(current->mems_allowed); diff --git a/kernel/sched.c b/kernel/sched.c index 11119de..9a38c7a 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -2300,9 +2300,7 @@ static int select_fallback_rq(int cpu, struct task_struct *p) /* No more Mr. Nice Guy. */ if (unlikely(dest_cpu >= nr_cpu_ids)) { - cpumask_copy(&p->cpus_allowed, cpu_possible_mask); - dest_cpu = cpumask_any(cpu_active_mask); - + dest_cpu = cpuset_cpus_allowed_fallback(p); /* * Don't tell them about moving exiting tasks or * kernel threads (both mm NULL), since they never -- cgit v0.10.2 From 0017d735092844118bef006696a750a0e4ef6ebd Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 24 Mar 2010 18:34:10 +0100 Subject: sched: Fix TASK_WAKING vs fork deadlock Oleg noticed a few races with the TASK_WAKING usage on fork. - since TASK_WAKING is basically a spinlock, it should be IRQ safe - since we set TASK_WAKING (*) without holding rq->lock it could be there still is a rq->lock holder, thereby not actually providing full serialization. (*) in fact we clear PF_STARTING, which in effect enables TASK_WAKING. Cure the second issue by not setting TASK_WAKING in sched_fork(), but only temporarily in wake_up_new_task() while calling select_task_rq(). Cure the first by holding rq->lock around the select_task_rq() call, this will disable IRQs, this however requires that we push down the rq->lock release into select_task_rq_fair()'s cgroup stuff. Because select_task_rq_fair() still needs to drop the rq->lock we cannot fully get rid of TASK_WAKING. Reported-by: Oleg Nesterov Signed-off-by: Peter Zijlstra LKML-Reference: Signed-off-by: Ingo Molnar diff --git a/include/linux/sched.h b/include/linux/sched.h index 8bea407..fb6c188 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1046,7 +1046,8 @@ struct sched_class { void (*put_prev_task) (struct rq *rq, struct task_struct *p); #ifdef CONFIG_SMP - int (*select_task_rq)(struct task_struct *p, int sd_flag, int flags); + int (*select_task_rq)(struct rq *rq, struct task_struct *p, + int sd_flag, int flags); void (*pre_schedule) (struct rq *this_rq, struct task_struct *task); void (*post_schedule) (struct rq *this_rq); diff --git a/kernel/sched.c b/kernel/sched.c index 9a38c7a..dcd1773 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -916,14 +916,10 @@ static inline void finish_lock_switch(struct rq *rq, struct task_struct *prev) /* * Check whether the task is waking, we use this to synchronize against * ttwu() so that task_cpu() reports a stable number. - * - * We need to make an exception for PF_STARTING tasks because the fork - * path might require task_rq_lock() to work, eg. it can call - * set_cpus_allowed_ptr() from the cpuset clone_ns code. */ static inline int task_is_waking(struct task_struct *p) { - return unlikely((p->state == TASK_WAKING) && !(p->flags & PF_STARTING)); + return unlikely(p->state == TASK_WAKING); } /* @@ -2320,9 +2316,9 @@ static int select_fallback_rq(int cpu, struct task_struct *p) * The caller (fork, wakeup) owns TASK_WAKING, ->cpus_allowed is stable. */ static inline -int select_task_rq(struct task_struct *p, int sd_flags, int wake_flags) +int select_task_rq(struct rq *rq, struct task_struct *p, int sd_flags, int wake_flags) { - int cpu = p->sched_class->select_task_rq(p, sd_flags, wake_flags); + int cpu = p->sched_class->select_task_rq(rq, p, sd_flags, wake_flags); /* * In order not to call set_task_cpu() on a blocking task we need @@ -2393,17 +2389,10 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, if (p->sched_class->task_waking) p->sched_class->task_waking(rq, p); - __task_rq_unlock(rq); - - cpu = select_task_rq(p, SD_BALANCE_WAKE, wake_flags); - if (cpu != orig_cpu) { - /* - * Since we migrate the task without holding any rq->lock, - * we need to be careful with task_rq_lock(), since that - * might end up locking an invalid rq. - */ + cpu = select_task_rq(rq, p, SD_BALANCE_WAKE, wake_flags); + if (cpu != orig_cpu) set_task_cpu(p, cpu); - } + __task_rq_unlock(rq); rq = cpu_rq(cpu); raw_spin_lock(&rq->lock); @@ -2530,11 +2519,11 @@ void sched_fork(struct task_struct *p, int clone_flags) __sched_fork(p); /* - * We mark the process as waking here. This guarantees that + * We mark the process as running here. This guarantees that * nobody will actually run it, and a signal or other external * event cannot wake it up and insert it on the runqueue either. */ - p->state = TASK_WAKING; + p->state = TASK_RUNNING; /* * Revert to default priority/policy on fork if requested. @@ -2601,28 +2590,25 @@ void wake_up_new_task(struct task_struct *p, unsigned long clone_flags) int cpu __maybe_unused = get_cpu(); #ifdef CONFIG_SMP + rq = task_rq_lock(p, &flags); + p->state = TASK_WAKING; + /* * Fork balancing, do it here and not earlier because: * - cpus_allowed can change in the fork path * - any previously selected cpu might disappear through hotplug * - * We still have TASK_WAKING but PF_STARTING is gone now, meaning - * ->cpus_allowed is stable, we have preemption disabled, meaning - * cpu_online_mask is stable. + * We set TASK_WAKING so that select_task_rq() can drop rq->lock + * without people poking at ->cpus_allowed. */ - cpu = select_task_rq(p, SD_BALANCE_FORK, 0); + cpu = select_task_rq(rq, p, SD_BALANCE_FORK, 0); set_task_cpu(p, cpu); -#endif - - /* - * Since the task is not on the rq and we still have TASK_WAKING set - * nobody else will migrate this task. - */ - rq = cpu_rq(cpu); - raw_spin_lock_irqsave(&rq->lock, flags); - BUG_ON(p->state != TASK_WAKING); p->state = TASK_RUNNING; + task_rq_unlock(rq, &flags); +#endif + + rq = task_rq_lock(p, &flags); activate_task(rq, p, 0); trace_sched_wakeup_new(rq, p, 1); check_preempt_curr(rq, p, WF_FORK); @@ -3068,19 +3054,15 @@ void sched_exec(void) { struct task_struct *p = current; struct migration_req req; - int dest_cpu, this_cpu; unsigned long flags; struct rq *rq; - - this_cpu = get_cpu(); - dest_cpu = p->sched_class->select_task_rq(p, SD_BALANCE_EXEC, 0); - if (dest_cpu == this_cpu) { - put_cpu(); - return; - } + int dest_cpu; rq = task_rq_lock(p, &flags); - put_cpu(); + dest_cpu = p->sched_class->select_task_rq(rq, p, SD_BALANCE_EXEC, 0); + if (dest_cpu == smp_processor_id()) + goto unlock; + /* * select_task_rq() can race against ->cpus_allowed */ @@ -3098,6 +3080,7 @@ void sched_exec(void) return; } +unlock: task_rq_unlock(rq, &flags); } diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 49ad993..8a5e763 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -1423,7 +1423,8 @@ select_idle_sibling(struct task_struct *p, struct sched_domain *sd, int target) * * preempt must be disabled. */ -static int select_task_rq_fair(struct task_struct *p, int sd_flag, int wake_flags) +static int +select_task_rq_fair(struct rq *rq, struct task_struct *p, int sd_flag, int wake_flags) { struct sched_domain *tmp, *affine_sd = NULL, *sd = NULL; int cpu = smp_processor_id(); @@ -1521,8 +1522,11 @@ static int select_task_rq_fair(struct task_struct *p, int sd_flag, int wake_flag cpumask_weight(sched_domain_span(sd)))) tmp = affine_sd; - if (tmp) + if (tmp) { + raw_spin_unlock(&rq->lock); update_shares(tmp); + raw_spin_lock(&rq->lock); + } } #endif diff --git a/kernel/sched_idletask.c b/kernel/sched_idletask.c index a8a6d8a..5af709f 100644 --- a/kernel/sched_idletask.c +++ b/kernel/sched_idletask.c @@ -6,7 +6,8 @@ */ #ifdef CONFIG_SMP -static int select_task_rq_idle(struct task_struct *p, int sd_flag, int flags) +static int +select_task_rq_idle(struct rq *rq, struct task_struct *p, int sd_flag, int flags) { return task_cpu(p); /* IDLE tasks as never migrated */ } diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index 012d69b..fde895f 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c @@ -948,10 +948,9 @@ static void yield_task_rt(struct rq *rq) #ifdef CONFIG_SMP static int find_lowest_rq(struct task_struct *task); -static int select_task_rq_rt(struct task_struct *p, int sd_flag, int flags) +static int +select_task_rq_rt(struct rq *rq, struct task_struct *p, int sd_flag, int flags) { - struct rq *rq = task_rq(p); - if (sd_flag != SD_BALANCE_WAKE) return smp_processor_id(); -- cgit v0.10.2 From 65cc8e4859ff29a9ddc989c88557d6059834c2a2 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 25 Mar 2010 21:05:16 +0100 Subject: sched: Optimize task_rq_lock() Now that we hold the rq->lock over set_task_cpu() again, we can do away with most of the TASK_WAKING checks and reduce them again to set_cpus_allowed_ptr(). Removes some conditionals from scheduling hot-paths. Signed-off-by: Peter Zijlstra Cc: Oleg Nesterov LKML-Reference: Signed-off-by: Ingo Molnar diff --git a/kernel/sched.c b/kernel/sched.c index dcd1773..51d336e 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -914,8 +914,8 @@ static inline void finish_lock_switch(struct rq *rq, struct task_struct *prev) #endif /* __ARCH_WANT_UNLOCKED_CTXSW */ /* - * Check whether the task is waking, we use this to synchronize against - * ttwu() so that task_cpu() reports a stable number. + * Check whether the task is waking, we use this to synchronize ->cpus_allowed + * against ttwu(). */ static inline int task_is_waking(struct task_struct *p) { @@ -932,11 +932,9 @@ static inline struct rq *__task_rq_lock(struct task_struct *p) struct rq *rq; for (;;) { - while (task_is_waking(p)) - cpu_relax(); rq = task_rq(p); raw_spin_lock(&rq->lock); - if (likely(rq == task_rq(p) && !task_is_waking(p))) + if (likely(rq == task_rq(p))) return rq; raw_spin_unlock(&rq->lock); } @@ -953,12 +951,10 @@ static struct rq *task_rq_lock(struct task_struct *p, unsigned long *flags) struct rq *rq; for (;;) { - while (task_is_waking(p)) - cpu_relax(); local_irq_save(*flags); rq = task_rq(p); raw_spin_lock(&rq->lock); - if (likely(rq == task_rq(p) && !task_is_waking(p))) + if (likely(rq == task_rq(p))) return rq; raw_spin_unlock_irqrestore(&rq->lock, *flags); } @@ -5262,7 +5258,18 @@ int set_cpus_allowed_ptr(struct task_struct *p, const struct cpumask *new_mask) struct rq *rq; int ret = 0; + /* + * Serialize against TASK_WAKING so that ttwu() and wunt() can + * drop the rq->lock and still rely on ->cpus_allowed. + */ +again: + while (task_is_waking(p)) + cpu_relax(); rq = task_rq_lock(p, &flags); + if (task_is_waking(p)) { + task_rq_unlock(rq, &flags); + goto again; + } if (!cpumask_intersects(new_mask, cpu_active_mask)) { ret = -EINVAL; -- cgit v0.10.2 From cc87f76a601d2d256118f7bab15e35254356ae21 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 26 Mar 2010 12:22:14 +0100 Subject: sched: Fix nr_uninterruptible count The cpuload calculation in calc_load_account_active() assumes rq->nr_uninterruptible will not change on an offline cpu after migrate_nr_uninterruptible(). However the recent migrate on wakeup changes broke that and would result in decrementing the offline cpu's rq->nr_uninterruptible. Fix this by accounting the nr_uninterruptible on the waking cpu. Signed-off-by: Peter Zijlstra LKML-Reference: Signed-off-by: Ingo Molnar diff --git a/kernel/sched.c b/kernel/sched.c index 51d336e..14c8d2a 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -2378,8 +2378,12 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, * * First fix up the nr_uninterruptible count: */ - if (task_contributes_to_load(p)) - rq->nr_uninterruptible--; + if (task_contributes_to_load(p)) { + if (likely(cpu_online(orig_cpu))) + rq->nr_uninterruptible--; + else + this_rq()->nr_uninterruptible--; + } p->state = TASK_WAKING; if (p->sched_class->task_waking) -- cgit v0.10.2 From 371fd7e7a56a5c136d31aa980011bd2f131c3ef5 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 24 Mar 2010 16:38:48 +0100 Subject: sched: Add enqueue/dequeue flags In order to reduce the dependency on TASK_WAKING rework the enqueue interface to support a proper flags field. Replace the int wakeup, bool head arguments with an int flags argument and create the following flags: ENQUEUE_WAKEUP - the enqueue is a wakeup of a sleeping task, ENQUEUE_WAKING - the enqueue has relative vruntime due to having sched_class::task_waking() called, ENQUEUE_HEAD - the waking task should be places on the head of the priority queue (where appropriate). For symmetry also convert sched_class::dequeue() to a flags scheme. Signed-off-by: Peter Zijlstra LKML-Reference: Signed-off-by: Ingo Molnar diff --git a/include/linux/sched.h b/include/linux/sched.h index fb6c188..e3e900f 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1032,12 +1032,17 @@ struct sched_domain; #define WF_SYNC 0x01 /* waker goes to sleep after wakup */ #define WF_FORK 0x02 /* child wakeup after fork */ +#define ENQUEUE_WAKEUP 1 +#define ENQUEUE_WAKING 2 +#define ENQUEUE_HEAD 4 + +#define DEQUEUE_SLEEP 1 + struct sched_class { const struct sched_class *next; - void (*enqueue_task) (struct rq *rq, struct task_struct *p, int wakeup, - bool head); - void (*dequeue_task) (struct rq *rq, struct task_struct *p, int sleep); + void (*enqueue_task) (struct rq *rq, struct task_struct *p, int flags); + void (*dequeue_task) (struct rq *rq, struct task_struct *p, int flags); void (*yield_task) (struct rq *rq); void (*check_preempt_curr) (struct rq *rq, struct task_struct *p, int flags); diff --git a/kernel/sched.c b/kernel/sched.c index 14c8d2a..4a57e96 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1877,44 +1877,43 @@ static void update_avg(u64 *avg, u64 sample) *avg += diff >> 3; } -static void -enqueue_task(struct rq *rq, struct task_struct *p, int wakeup, bool head) +static void enqueue_task(struct rq *rq, struct task_struct *p, int flags) { update_rq_clock(rq); sched_info_queued(p); - p->sched_class->enqueue_task(rq, p, wakeup, head); + p->sched_class->enqueue_task(rq, p, flags); p->se.on_rq = 1; } -static void dequeue_task(struct rq *rq, struct task_struct *p, int sleep) +static void dequeue_task(struct rq *rq, struct task_struct *p, int flags) { update_rq_clock(rq); sched_info_dequeued(p); - p->sched_class->dequeue_task(rq, p, sleep); + p->sched_class->dequeue_task(rq, p, flags); p->se.on_rq = 0; } /* * activate_task - move a task to the runqueue. */ -static void activate_task(struct rq *rq, struct task_struct *p, int wakeup) +static void activate_task(struct rq *rq, struct task_struct *p, int flags) { if (task_contributes_to_load(p)) rq->nr_uninterruptible--; - enqueue_task(rq, p, wakeup, false); + enqueue_task(rq, p, flags); inc_nr_running(rq); } /* * deactivate_task - remove a task from the runqueue. */ -static void deactivate_task(struct rq *rq, struct task_struct *p, int sleep) +static void deactivate_task(struct rq *rq, struct task_struct *p, int flags) { if (task_contributes_to_load(p)) rq->nr_uninterruptible++; - dequeue_task(rq, p, sleep); + dequeue_task(rq, p, flags); dec_nr_running(rq); } @@ -2353,6 +2352,7 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, { int cpu, orig_cpu, this_cpu, success = 0; unsigned long flags; + unsigned long en_flags = ENQUEUE_WAKEUP; struct rq *rq; this_cpu = get_cpu(); @@ -2386,8 +2386,10 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, } p->state = TASK_WAKING; - if (p->sched_class->task_waking) + if (p->sched_class->task_waking) { p->sched_class->task_waking(rq, p); + en_flags |= ENQUEUE_WAKING; + } cpu = select_task_rq(rq, p, SD_BALANCE_WAKE, wake_flags); if (cpu != orig_cpu) @@ -2432,7 +2434,7 @@ out_activate: schedstat_inc(p, se.statistics.nr_wakeups_local); else schedstat_inc(p, se.statistics.nr_wakeups_remote); - activate_task(rq, p, 1); + activate_task(rq, p, en_flags); success = 1; out_running: @@ -3623,7 +3625,7 @@ need_resched_nonpreemptible: if (unlikely(signal_pending_state(prev->state, prev))) prev->state = TASK_RUNNING; else - deactivate_task(rq, prev, 1); + deactivate_task(rq, prev, DEQUEUE_SLEEP); switch_count = &prev->nvcsw; } @@ -4193,7 +4195,7 @@ void rt_mutex_setprio(struct task_struct *p, int prio) if (running) p->sched_class->set_curr_task(rq); if (on_rq) { - enqueue_task(rq, p, 0, oldprio < prio); + enqueue_task(rq, p, oldprio < prio ? ENQUEUE_HEAD : 0); check_class_changed(rq, p, prev_class, oldprio, running); } @@ -4236,7 +4238,7 @@ void set_user_nice(struct task_struct *p, long nice) delta = p->prio - old_prio; if (on_rq) { - enqueue_task(rq, p, 0, false); + enqueue_task(rq, p, 0); /* * If the task increased its priority or is running and * lowered its priority, then reschedule its CPU: @@ -8180,7 +8182,7 @@ void sched_move_task(struct task_struct *tsk) if (unlikely(running)) tsk->sched_class->set_curr_task(rq); if (on_rq) - enqueue_task(rq, tsk, 0, false); + enqueue_task(rq, tsk, 0); task_rq_unlock(rq, &flags); } diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 8a5e763..88d3053 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -757,9 +757,6 @@ place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int initial) se->vruntime = vruntime; } -#define ENQUEUE_WAKEUP 1 -#define ENQUEUE_MIGRATE 2 - static void enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags) { @@ -767,7 +764,7 @@ enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags) * Update the normalized vruntime before updating min_vruntime * through callig update_curr(). */ - if (!(flags & ENQUEUE_WAKEUP) || (flags & ENQUEUE_MIGRATE)) + if (!(flags & ENQUEUE_WAKEUP) || (flags & ENQUEUE_WAKING)) se->vruntime += cfs_rq->min_vruntime; /* @@ -803,7 +800,7 @@ static void clear_buddies(struct cfs_rq *cfs_rq, struct sched_entity *se) } static void -dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep) +dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags) { /* * Update run-time statistics of the 'current'. @@ -811,7 +808,7 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep) update_curr(cfs_rq); update_stats_dequeue(cfs_rq, se); - if (sleep) { + if (flags & DEQUEUE_SLEEP) { #ifdef CONFIG_SCHEDSTATS if (entity_is_task(se)) { struct task_struct *tsk = task_of(se); @@ -836,7 +833,7 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep) * update can refer to the ->curr item and we need to reflect this * movement in our normalized position. */ - if (!sleep) + if (!(flags & DEQUEUE_SLEEP)) se->vruntime -= cfs_rq->min_vruntime; } @@ -1045,16 +1042,10 @@ static inline void hrtick_update(struct rq *rq) * then put the task into the rbtree: */ static void -enqueue_task_fair(struct rq *rq, struct task_struct *p, int wakeup, bool head) +enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags) { struct cfs_rq *cfs_rq; struct sched_entity *se = &p->se; - int flags = 0; - - if (wakeup) - flags |= ENQUEUE_WAKEUP; - if (p->state == TASK_WAKING) - flags |= ENQUEUE_MIGRATE; for_each_sched_entity(se) { if (se->on_rq) @@ -1072,18 +1063,18 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int wakeup, bool head) * decreased. We remove the task from the rbtree and * update the fair scheduling stats: */ -static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int sleep) +static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int flags) { struct cfs_rq *cfs_rq; struct sched_entity *se = &p->se; for_each_sched_entity(se) { cfs_rq = cfs_rq_of(se); - dequeue_entity(cfs_rq, se, sleep); + dequeue_entity(cfs_rq, se, flags); /* Don't dequeue parent if it has other entities besides us */ if (cfs_rq->load.weight) break; - sleep = 1; + flags |= DEQUEUE_SLEEP; } hrtick_update(rq); diff --git a/kernel/sched_idletask.c b/kernel/sched_idletask.c index 5af709f..bea2b8f 100644 --- a/kernel/sched_idletask.c +++ b/kernel/sched_idletask.c @@ -33,7 +33,7 @@ static struct task_struct *pick_next_task_idle(struct rq *rq) * message if some code attempts to do it: */ static void -dequeue_task_idle(struct rq *rq, struct task_struct *p, int sleep) +dequeue_task_idle(struct rq *rq, struct task_struct *p, int flags) { raw_spin_unlock_irq(&rq->lock); printk(KERN_ERR "bad: scheduling from the idle thread!\n"); diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index fde895f..8afb953 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c @@ -888,20 +888,20 @@ static void dequeue_rt_entity(struct sched_rt_entity *rt_se) * Adding/removing a task to/from a priority array: */ static void -enqueue_task_rt(struct rq *rq, struct task_struct *p, int wakeup, bool head) +enqueue_task_rt(struct rq *rq, struct task_struct *p, int flags) { struct sched_rt_entity *rt_se = &p->rt; - if (wakeup) + if (flags & ENQUEUE_WAKEUP) rt_se->timeout = 0; - enqueue_rt_entity(rt_se, head); + enqueue_rt_entity(rt_se, flags & ENQUEUE_HEAD); if (!task_current(rq, p) && p->rt.nr_cpus_allowed > 1) enqueue_pushable_task(rq, p); } -static void dequeue_task_rt(struct rq *rq, struct task_struct *p, int sleep) +static void dequeue_task_rt(struct rq *rq, struct task_struct *p, int flags) { struct sched_rt_entity *rt_se = &p->rt; -- cgit v0.10.2 From c6e718ff8cdcf5e7855077687720b37c4a07650a Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 26 Mar 2010 12:11:06 -0300 Subject: perf symbols: Move more map_groups methods to map.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While writing a standalone test app that uses the symbol system to find kernel space symbols I noticed these also need to be moved. Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 09e09e7..de31901 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -658,7 +658,7 @@ print_entries: if (h->ms.map == NULL && verbose > 1) { __map_groups__fprintf_maps(&h->thread->mg, - MAP__FUNCTION, fp); + MAP__FUNCTION, verbose, fp); fprintf(fp, "%.10s end\n", graph_dotted_line); } } diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 9f2963f..e21f980 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -1,4 +1,5 @@ #include "symbol.h" +#include #include #include #include @@ -234,6 +235,37 @@ u64 map__objdump_2ip(struct map *map, u64 addr) return ip; } +void map_groups__init(struct map_groups *self) +{ + int i; + for (i = 0; i < MAP__NR_TYPES; ++i) { + self->maps[i] = RB_ROOT; + INIT_LIST_HEAD(&self->removed_maps[i]); + } +} + +void map_groups__flush(struct map_groups *self) +{ + int type; + + for (type = 0; type < MAP__NR_TYPES; type++) { + struct rb_root *root = &self->maps[type]; + struct rb_node *next = rb_first(root); + + while (next) { + struct map *pos = rb_entry(next, struct map, rb_node); + next = rb_next(&pos->rb_node); + rb_erase(&pos->rb_node, root); + /* + * We may have references to this map, for + * instance in some hist_entry instances, so + * just move them to a separate list. + */ + list_add_tail(&pos->node, &self->removed_maps[pos->type]); + } + } +} + struct symbol *map_groups__find_symbol(struct map_groups *self, enum map_type type, u64 addr, symbol_filter_t filter) @@ -246,6 +278,142 @@ struct symbol *map_groups__find_symbol(struct map_groups *self, return NULL; } +size_t __map_groups__fprintf_maps(struct map_groups *self, + enum map_type type, int verbose, FILE *fp) +{ + size_t printed = fprintf(fp, "%s:\n", map_type__name[type]); + struct rb_node *nd; + + for (nd = rb_first(&self->maps[type]); nd; nd = rb_next(nd)) { + struct map *pos = rb_entry(nd, struct map, rb_node); + printed += fprintf(fp, "Map:"); + printed += map__fprintf(pos, fp); + if (verbose > 2) { + printed += dso__fprintf(pos->dso, type, fp); + printed += fprintf(fp, "--\n"); + } + } + + return printed; +} + +size_t map_groups__fprintf_maps(struct map_groups *self, int verbose, FILE *fp) +{ + size_t printed = 0, i; + for (i = 0; i < MAP__NR_TYPES; ++i) + printed += __map_groups__fprintf_maps(self, i, verbose, fp); + return printed; +} + +static size_t __map_groups__fprintf_removed_maps(struct map_groups *self, + enum map_type type, + int verbose, FILE *fp) +{ + struct map *pos; + size_t printed = 0; + + list_for_each_entry(pos, &self->removed_maps[type], node) { + printed += fprintf(fp, "Map:"); + printed += map__fprintf(pos, fp); + if (verbose > 1) { + printed += dso__fprintf(pos->dso, type, fp); + printed += fprintf(fp, "--\n"); + } + } + return printed; +} + +static size_t map_groups__fprintf_removed_maps(struct map_groups *self, + int verbose, FILE *fp) +{ + size_t printed = 0, i; + for (i = 0; i < MAP__NR_TYPES; ++i) + printed += __map_groups__fprintf_removed_maps(self, i, verbose, fp); + return printed; +} + +size_t map_groups__fprintf(struct map_groups *self, int verbose, FILE *fp) +{ + size_t printed = map_groups__fprintf_maps(self, verbose, fp); + printed += fprintf(fp, "Removed maps:\n"); + return printed + map_groups__fprintf_removed_maps(self, verbose, fp); +} + +int map_groups__fixup_overlappings(struct map_groups *self, struct map *map, + int verbose, FILE *fp) +{ + struct rb_root *root = &self->maps[map->type]; + struct rb_node *next = rb_first(root); + + while (next) { + struct map *pos = rb_entry(next, struct map, rb_node); + next = rb_next(&pos->rb_node); + + if (!map__overlap(pos, map)) + continue; + + if (verbose >= 2) { + fputs("overlapping maps:\n", fp); + map__fprintf(map, fp); + map__fprintf(pos, fp); + } + + rb_erase(&pos->rb_node, root); + /* + * We may have references to this map, for instance in some + * hist_entry instances, so just move them to a separate + * list. + */ + list_add_tail(&pos->node, &self->removed_maps[map->type]); + /* + * Now check if we need to create new maps for areas not + * overlapped by the new map: + */ + if (map->start > pos->start) { + struct map *before = map__clone(pos); + + if (before == NULL) + return -ENOMEM; + + before->end = map->start - 1; + map_groups__insert(self, before); + if (verbose >= 2) + map__fprintf(before, fp); + } + + if (map->end < pos->end) { + struct map *after = map__clone(pos); + + if (after == NULL) + return -ENOMEM; + + after->start = map->end + 1; + map_groups__insert(self, after); + if (verbose >= 2) + map__fprintf(after, fp); + } + } + + return 0; +} + +/* + * XXX This should not really _copy_ te maps, but refcount them. + */ +int map_groups__clone(struct map_groups *self, + struct map_groups *parent, enum map_type type) +{ + struct rb_node *nd; + for (nd = rb_first(&parent->maps[type]); nd; nd = rb_next(nd)) { + struct map *map = rb_entry(nd, struct map, rb_node); + struct map *new = map__clone(map); + if (new == NULL) + return -ENOMEM; + map_groups__insert(self, new); + } + return 0; +} + static u64 map__reloc_map_ip(struct map *map, u64 ip) { return ip + (s64)map->pgoff; diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index 6a703fa..4e7a11d 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h @@ -97,11 +97,14 @@ struct map_groups { }; size_t __map_groups__fprintf_maps(struct map_groups *self, - enum map_type type, FILE *fp); + enum map_type type, int verbose, FILE *fp); void maps__insert(struct rb_root *maps, struct map *map); struct map *maps__find(struct rb_root *maps, u64 addr); void map_groups__init(struct map_groups *self); -size_t map_groups__fprintf_maps(struct map_groups *self, FILE *fp); +int map_groups__clone(struct map_groups *self, + struct map_groups *parent, enum map_type type); +size_t map_groups__fprintf(struct map_groups *self, int verbose, FILE *fp); +size_t map_groups__fprintf_maps(struct map_groups *self, int verbose, FILE *fp); static inline void map_groups__insert(struct map_groups *self, struct map *map) { @@ -125,6 +128,9 @@ static inline struct symbol *map_groups__find_function(struct map_groups *self, return map_groups__find_symbol(self, MAP__FUNCTION, addr, filter); } +int map_groups__fixup_overlappings(struct map_groups *self, struct map *map, + int verbose, FILE *fp); + struct map *map_groups__find_by_name(struct map_groups *self, enum map_type type, const char *name); int __map_groups__create_kernel_maps(struct map_groups *self, @@ -134,5 +140,6 @@ int map_groups__create_kernel_maps(struct map_groups *self, struct map *vmlinux_maps[MAP__NR_TYPES]); struct map *map_groups__new_module(struct map_groups *self, u64 start, const char *filename); +void map_groups__flush(struct map_groups *self); #endif /* __PERF_MAP_H */ diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index 9bbe27d..1f7ecd4 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c @@ -38,15 +38,6 @@ failure: return ret; } -void map_groups__init(struct map_groups *self) -{ - int i; - for (i = 0; i < MAP__NR_TYPES; ++i) { - self->maps[i] = RB_ROOT; - INIT_LIST_HEAD(&self->removed_maps[i]); - } -} - static struct thread *thread__new(pid_t pid) { struct thread *self = zalloc(sizeof(*self)); @@ -62,28 +53,6 @@ static struct thread *thread__new(pid_t pid) return self; } -static void map_groups__flush(struct map_groups *self) -{ - int type; - - for (type = 0; type < MAP__NR_TYPES; type++) { - struct rb_root *root = &self->maps[type]; - struct rb_node *next = rb_first(root); - - while (next) { - struct map *pos = rb_entry(next, struct map, rb_node); - next = rb_next(&pos->rb_node); - rb_erase(&pos->rb_node, root); - /* - * We may have references to this map, for - * instance in some hist_entry instances, so - * just move them to a separate list. - */ - list_add_tail(&pos->node, &self->removed_maps[pos->type]); - } - } -} - int thread__set_comm(struct thread *self, const char *comm) { int err; @@ -110,69 +79,10 @@ int thread__comm_len(struct thread *self) return self->comm_len; } -size_t __map_groups__fprintf_maps(struct map_groups *self, - enum map_type type, FILE *fp) -{ - size_t printed = fprintf(fp, "%s:\n", map_type__name[type]); - struct rb_node *nd; - - for (nd = rb_first(&self->maps[type]); nd; nd = rb_next(nd)) { - struct map *pos = rb_entry(nd, struct map, rb_node); - printed += fprintf(fp, "Map:"); - printed += map__fprintf(pos, fp); - if (verbose > 2) { - printed += dso__fprintf(pos->dso, type, fp); - printed += fprintf(fp, "--\n"); - } - } - - return printed; -} - -size_t map_groups__fprintf_maps(struct map_groups *self, FILE *fp) -{ - size_t printed = 0, i; - for (i = 0; i < MAP__NR_TYPES; ++i) - printed += __map_groups__fprintf_maps(self, i, fp); - return printed; -} - -static size_t __map_groups__fprintf_removed_maps(struct map_groups *self, - enum map_type type, FILE *fp) -{ - struct map *pos; - size_t printed = 0; - - list_for_each_entry(pos, &self->removed_maps[type], node) { - printed += fprintf(fp, "Map:"); - printed += map__fprintf(pos, fp); - if (verbose > 1) { - printed += dso__fprintf(pos->dso, type, fp); - printed += fprintf(fp, "--\n"); - } - } - return printed; -} - -static size_t map_groups__fprintf_removed_maps(struct map_groups *self, FILE *fp) -{ - size_t printed = 0, i; - for (i = 0; i < MAP__NR_TYPES; ++i) - printed += __map_groups__fprintf_removed_maps(self, i, fp); - return printed; -} - -static size_t map_groups__fprintf(struct map_groups *self, FILE *fp) -{ - size_t printed = map_groups__fprintf_maps(self, fp); - printed += fprintf(fp, "Removed maps:\n"); - return printed + map_groups__fprintf_removed_maps(self, fp); -} - static size_t thread__fprintf(struct thread *self, FILE *fp) { return fprintf(fp, "Thread %d %s\n", self->pid, self->comm) + - map_groups__fprintf(&self->mg, fp); + map_groups__fprintf(&self->mg, verbose, fp); } struct thread *perf_session__findnew(struct perf_session *self, pid_t pid) @@ -214,87 +124,12 @@ struct thread *perf_session__findnew(struct perf_session *self, pid_t pid) return th; } -static int map_groups__fixup_overlappings(struct map_groups *self, - struct map *map) -{ - struct rb_root *root = &self->maps[map->type]; - struct rb_node *next = rb_first(root); - - while (next) { - struct map *pos = rb_entry(next, struct map, rb_node); - next = rb_next(&pos->rb_node); - - if (!map__overlap(pos, map)) - continue; - - if (verbose >= 2) { - fputs("overlapping maps:\n", stderr); - map__fprintf(map, stderr); - map__fprintf(pos, stderr); - } - - rb_erase(&pos->rb_node, root); - /* - * We may have references to this map, for instance in some - * hist_entry instances, so just move them to a separate - * list. - */ - list_add_tail(&pos->node, &self->removed_maps[map->type]); - /* - * Now check if we need to create new maps for areas not - * overlapped by the new map: - */ - if (map->start > pos->start) { - struct map *before = map__clone(pos); - - if (before == NULL) - return -ENOMEM; - - before->end = map->start - 1; - map_groups__insert(self, before); - if (verbose >= 2) - map__fprintf(before, stderr); - } - - if (map->end < pos->end) { - struct map *after = map__clone(pos); - - if (after == NULL) - return -ENOMEM; - - after->start = map->end + 1; - map_groups__insert(self, after); - if (verbose >= 2) - map__fprintf(after, stderr); - } - } - - return 0; -} - void thread__insert_map(struct thread *self, struct map *map) { - map_groups__fixup_overlappings(&self->mg, map); + map_groups__fixup_overlappings(&self->mg, map, verbose, stderr); map_groups__insert(&self->mg, map); } -/* - * XXX This should not really _copy_ te maps, but refcount them. - */ -static int map_groups__clone(struct map_groups *self, - struct map_groups *parent, enum map_type type) -{ - struct rb_node *nd; - for (nd = rb_first(&parent->maps[type]); nd; nd = rb_next(nd)) { - struct map *map = rb_entry(nd, struct map, rb_node); - struct map *new = map__clone(map); - if (new == NULL) - return -ENOMEM; - map_groups__insert(self, new); - } - return 0; -} - int thread__fork(struct thread *self, struct thread *parent) { int i; -- cgit v0.10.2 From 7e5e1b1404c30db5f6bc3f5203b6c21c1d244f99 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 26 Mar 2010 12:30:40 -0300 Subject: perf symbols: map_groups__find_symbol must return the map too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tools need to know from which map in the map_group a symbol was resolved to, so that, for isntance, we can annotate kernel modules symbols by getting its precise name, etc. Also add the _by_name variants for completeness. Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index 924a951..32edb6a 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c @@ -369,7 +369,8 @@ static void __print_result(struct rb_root *root, struct perf_session *session, if (is_caller) { addr = data->call_site; if (!raw_ip) - sym = map_groups__find_function(&session->kmaps, addr, NULL); + sym = map_groups__find_function(&session->kmaps, + addr, NULL, NULL); } else addr = data->ptr; diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index e21f980..37913b2 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -268,12 +268,38 @@ void map_groups__flush(struct map_groups *self) struct symbol *map_groups__find_symbol(struct map_groups *self, enum map_type type, u64 addr, + struct map **mapp, symbol_filter_t filter) { struct map *map = map_groups__find(self, type, addr); - if (map != NULL) + if (map != NULL) { + if (mapp != NULL) + *mapp = map; return map__find_symbol(map, map->map_ip(map, addr), filter); + } + + return NULL; +} + +struct symbol *map_groups__find_symbol_by_name(struct map_groups *self, + enum map_type type, + const char *name, + struct map **mapp, + symbol_filter_t filter) +{ + struct rb_node *nd; + + for (nd = rb_first(&self->maps[type]); nd; nd = rb_next(nd)) { + struct map *pos = rb_entry(nd, struct map, rb_node); + struct symbol *sym = map__find_symbol_by_name(pos, name, filter); + + if (sym == NULL) + continue; + if (mapp != NULL) + *mapp = pos; + return sym; + } return NULL; } diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index 4e7a11d..2031278 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h @@ -119,13 +119,28 @@ static inline struct map *map_groups__find(struct map_groups *self, struct symbol *map_groups__find_symbol(struct map_groups *self, enum map_type type, u64 addr, + struct map **mapp, symbol_filter_t filter); -static inline struct symbol *map_groups__find_function(struct map_groups *self, - u64 addr, - symbol_filter_t filter) +struct symbol *map_groups__find_symbol_by_name(struct map_groups *self, + enum map_type type, + const char *name, + struct map **mapp, + symbol_filter_t filter); + +static inline +struct symbol *map_groups__find_function(struct map_groups *self, u64 addr, + struct map **mapp, symbol_filter_t filter) +{ + return map_groups__find_symbol(self, MAP__FUNCTION, addr, mapp, filter); +} + +static inline +struct symbol *map_groups__find_function_by_name(struct map_groups *self, + const char *name, struct map **mapp, + symbol_filter_t filter) { - return map_groups__find_symbol(self, MAP__FUNCTION, addr, filter); + return map_groups__find_symbol_by_name(self, MAP__FUNCTION, name, mapp, filter); } int map_groups__fixup_overlappings(struct map_groups *self, struct map *map, -- cgit v0.10.2 From 5f4d3f8816461300ce54505c9117bf85b3044aa0 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 26 Mar 2010 21:16:22 -0300 Subject: perf report: Add progress bars MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For when we are processing the events and inserting the entries in the browser. Experimentation here: naming "ui_something" we may be treading into creating a TUI/GUI set of routines that can then be implemented in terms of multiple backends. Also the time it takes for adding things to the "browser" takes, visually (I guess I should do some profiling here ;-) ), more time than for processing the events... That means we probably need to create a custom hist_entry browser, so that we reuse the structures we have in place instead of duplicating them in newt. But progress was made and at least we can see something while long files are being loaded, that must be one of UI 101 bullet points :-) Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 6ab1698..3819185 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -303,13 +303,14 @@ static int __cmd_report(void) next = rb_first(&session->stats_by_id); while (next) { struct event_stat_id *stats; + u64 nr_hists; stats = rb_entry(next, struct event_stat_id, rb_node); perf_session__collapse_resort(&stats->hists); - perf_session__output_resort(&stats->hists, stats->stats.total); - + nr_hists = perf_session__output_resort(&stats->hists, + stats->stats.total); if (use_browser) - perf_session__browse_hists(&stats->hists, + perf_session__browse_hists(&stats->hists, nr_hists, stats->stats.total, help); else { if (rb_first(&session->stats_by_id) == diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h index 0172edf..5cb0a1b 100644 --- a/tools/perf/util/debug.h +++ b/tools/perf/util/debug.h @@ -10,13 +10,29 @@ extern int dump_trace; int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); void trace_event(event_t *event); +struct ui_progress; + #ifdef NO_NEWT_SUPPORT static inline int browser__show_help(const char *format __used, va_list ap __used) { return 0; } + +static inline struct ui_progress *ui_progress__new(const char *title __used, + u64 total __used) +{ + return (struct ui_progress *)1; +} + +static inline void ui_progress__update(struct ui_progress *self __used, + u64 curr __used) {} + +static inline void ui_progress__delete(struct ui_progress *self __used) {} #else int browser__show_help(const char *format, va_list ap); +struct ui_progress *ui_progress__new(const char *title, u64 total); +void ui_progress__update(struct ui_progress *self, u64 curr); +void ui_progress__delete(struct ui_progress *self); #endif #endif /* __PERF_DEBUG_H */ diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index de31901..a46d093 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -185,12 +185,13 @@ static void perf_session__insert_output_hist_entry(struct rb_root *root, rb_insert_color(&he->rb_node, root); } -void perf_session__output_resort(struct rb_root *hists, u64 total_samples) +u64 perf_session__output_resort(struct rb_root *hists, u64 total_samples) { struct rb_root tmp; struct rb_node *next; struct hist_entry *n; u64 min_callchain_hits; + u64 nr_hists = 0; min_callchain_hits = total_samples * (callchain_param.min_percent / 100); @@ -205,9 +206,11 @@ void perf_session__output_resort(struct rb_root *hists, u64 total_samples) rb_erase(&n->rb_node, hists); perf_session__insert_output_hist_entry(&tmp, n, min_callchain_hits); + ++nr_hists; } *hists = tmp; + return nr_hists; } static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin) diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index fe366ce..da6a8c1 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -25,7 +25,7 @@ size_t hist_entry__fprintf(struct hist_entry *self, u64 session_total); void hist_entry__free(struct hist_entry *); -void perf_session__output_resort(struct rb_root *hists, u64 total_samples); +u64 perf_session__output_resort(struct rb_root *hists, u64 total_samples); void perf_session__collapse_resort(struct rb_root *hists); size_t perf_session__fprintf_hists(struct rb_root *hists, struct perf_session *pair, diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index e99bcc8..b0210ae 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -12,6 +12,72 @@ #include "sort.h" #include "symbol.h" +struct ui_progress { + newtComponent form, scale; +}; + +struct ui_progress *ui_progress__new(const char *title, u64 total) +{ + struct ui_progress *self = malloc(sizeof(*self)); + + if (self != NULL) { + int cols; + newtGetScreenSize(&cols, NULL); + cols -= 4; + newtCenteredWindow(cols, 1, title); + self->form = newtForm(NULL, NULL, 0); + if (self->form == NULL) + goto out_free_self; + self->scale = newtScale(0, 0, cols, total); + if (self->scale == NULL) + goto out_free_form; + newtFormAddComponents(self->form, self->scale, NULL); + newtRefresh(); + } + + return self; + +out_free_form: + newtFormDestroy(self->form); +out_free_self: + free(self); + return NULL; +} + +void ui_progress__update(struct ui_progress *self, u64 curr) +{ + newtScaleSet(self->scale, curr); + newtRefresh(); +} + +void ui_progress__delete(struct ui_progress *self) +{ + newtFormDestroy(self->form); + newtPopWindow(); + free(self); +} + +static char browser__last_msg[1024]; + +int browser__show_help(const char *format, va_list ap) +{ + int ret; + static int backlog; + + ret = vsnprintf(browser__last_msg + backlog, + sizeof(browser__last_msg) - backlog, format, ap); + backlog += ret; + + if (browser__last_msg[backlog - 1] == '\n') { + newtPopHelpLine(); + newtPushHelpLine(browser__last_msg); + newtRefresh(); + backlog = 0; + } + + return ret; +} + static void newt_form__set_exit_keys(newtComponent self) { newtFormAddHotKey(self, NEWT_KEY_ESCAPE); @@ -364,8 +430,8 @@ static void perf_session__selection(newtComponent self, void *data) *symbol_ptr = newt__symbol_tree_get_current(self); } -void perf_session__browse_hists(struct rb_root *hists, u64 session_total, - const char *helpline) +int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, + u64 session_total, const char *helpline) { struct sort_entry *se; struct rb_node *nd; @@ -378,6 +444,12 @@ void perf_session__browse_hists(struct rb_root *hists, u64 session_total, newtComponent form, tree; struct newtExitStruct es; const struct map_symbol *selection; + u64 curr_hist = 0; + struct ui_progress *progress; + + progress = ui_progress__new("Adding entries to the browser...", nr_hists); + if (progress == NULL) + return -1; snprintf(str, sizeof(str), "Samples: %Ld", session_total); newtDrawRootText(0, 0, str); @@ -419,8 +491,13 @@ void perf_session__browse_hists(struct rb_root *hists, u64 session_total, max_len = len; if (symbol_conf.use_callchain) hist_entry__append_callchain_browser(h, tree, session_total, idx++); + ++curr_hist; + if (curr_hist % 5) + ui_progress__update(progress, curr_hist); } + ui_progress__delete(progress); + if (max_len > cols) max_len = cols - 3; @@ -480,27 +557,7 @@ do_annotate: newtFormDestroy(form); newtPopWindow(); -} - -static char browser__last_msg[1024]; - -int browser__show_help(const char *format, va_list ap) -{ - int ret; - static int backlog; - - ret = vsnprintf(browser__last_msg + backlog, - sizeof(browser__last_msg) - backlog, format, ap); - backlog += ret; - - if (browser__last_msg[backlog - 1] == '\n') { - newtPopHelpLine(); - newtPushHelpLine(browser__last_msg); - newtRefresh(); - backlog = 0; - } - - return ret; + return 0; } void setup_browser(void) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 76b4ac6..32765cd 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -397,6 +397,10 @@ int __perf_session__process_events(struct perf_session *self, event_t *event; uint32_t size; char *buf; + struct ui_progress *progress = ui_progress__new("Processing events...", + self->size); + if (progress == NULL) + return -1; perf_event_ops__fill_defaults(ops); @@ -425,6 +429,7 @@ remap: more: event = (event_t *)(buf + head); + ui_progress__update(progress, offset); if (self->header.needs_swap) perf_event_header__bswap(&event->header); @@ -475,6 +480,7 @@ more: done: err = 0; out_err: + ui_progress__delete(progress); return err; } diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 631f815..6a15dae 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -88,11 +88,15 @@ static inline struct map * } #ifdef NO_NEWT_SUPPORT -static inline void perf_session__browse_hists(struct rb_root *hists __used, +static inline int perf_session__browse_hists(struct rb_root *hists __used, + u64 nr_hists __used, u64 session_total __used, - const char *helpline __used) {} + const char *helpline __used) +{ + return 0; +} #else -void perf_session__browse_hists(struct rb_root *hists, u64 session_total, - const char *helpline); +int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, + u64 session_total, const char *helpline); #endif #endif /* __PERF_SESSION_H */ -- cgit v0.10.2 From 8b2c551f9635bf1c5c2d38de300137998915478f Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 27 Mar 2010 11:43:36 -0300 Subject: perf tools: Use -o $(BITBUCKET) in one more case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As described in 1703f2c some gcc versions has issues using /dev/null, so use the mechanism used elsewhere. Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 6903645..120736c 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -542,7 +542,7 @@ PYTHON_EMBED_LDOPTS = `python-config --ldflags 2>/dev/null` PYTHON_EMBED_CCOPTS = `python-config --cflags 2>/dev/null` endif -ifneq ($(shell sh -c "(echo '\#include '; echo 'int main(void) { Py_Initialize(); return 0; }') | $(CC) -x c - $(PYTHON_EMBED_CCOPTS) -o /dev/null $(PYTHON_EMBED_LDOPTS) > /dev/null 2>&1 && echo y"), y) +ifneq ($(shell sh -c "(echo '\#include '; echo 'int main(void) { Py_Initialize(); return 0; }') | $(CC) -x c - $(PYTHON_EMBED_CCOPTS) -o $(BITBUCKET) $(PYTHON_EMBED_LDOPTS) > /dev/null 2>&1 && echo y"), y) BASIC_CFLAGS += -DNO_LIBPYTHON else ALL_LDFLAGS += $(PYTHON_EMBED_LDOPTS) -- cgit v0.10.2 From c29ede615fd35a640e771fbbb1778e915fac43a7 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 27 Mar 2010 14:30:45 -0300 Subject: perf tools: Allow specifying O= to build files in a separate directory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoiding polluting the source tree with build files. Reported-by: Steven Rostedt Cc: Steven Rostedt Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 120736c..93029c0 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -1,3 +1,7 @@ +ifeq ("$(origin O)", "command line") + OUTPUT := $(O)/ +endif + # The default target of this Makefile is... all:: @@ -153,9 +157,13 @@ all:: # # Define NO_DWARF if you do not want debug-info analysis feature at all. -PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE - @$(SHELL_PATH) util/PERF-VERSION-GEN --include PERF-VERSION-FILE +$(shell sh -c 'mkdir -p $(OUTPUT)scripts/python/Perf-Trace-Util/' 2> /dev/null) +$(shell sh -c 'mkdir -p $(OUTPUT)util/scripting-engines/' 2> /dev/null) +$(shell sh -c 'mkdir $(OUTPUT)bench' 2> /dev/null) + +$(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE + @$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT) +-include $(OUTPUT)PERF-VERSION-FILE uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') uname_M := $(shell sh -c 'uname -m 2>/dev/null || echo not') @@ -310,7 +318,7 @@ PROGRAMS += $(EXTRA_PROGRAMS) # # Single 'perf' binary right now: # -PROGRAMS += perf +PROGRAMS += $(OUTPUT)perf # List built-in command $C whose implementation cmd_$C() is not in # builtin-$C.o but is linked in as part of some other command. @@ -320,7 +328,7 @@ PROGRAMS += perf ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS) # what 'all' will build but not install in perfexecdir -OTHER_PROGRAMS = perf$X +OTHER_PROGRAMS = $(OUTPUT)perf$X # Set paths to tools early so that they can be used for version tests. ifndef SHELL_PATH @@ -332,7 +340,7 @@ endif export PERL_PATH -LIB_FILE=libperf.a +LIB_FILE=$(OUTPUT)libperf.a LIB_H += ../../include/linux/perf_event.h LIB_H += ../../include/linux/rbtree.h @@ -393,77 +401,77 @@ LIB_H += util/probe-finder.h LIB_H += util/probe-event.h LIB_H += util/cpumap.h -LIB_OBJS += util/abspath.o -LIB_OBJS += util/alias.o -LIB_OBJS += util/build-id.o -LIB_OBJS += util/config.o -LIB_OBJS += util/ctype.o -LIB_OBJS += util/debugfs.o -LIB_OBJS += util/environment.o -LIB_OBJS += util/event.o -LIB_OBJS += util/exec_cmd.o -LIB_OBJS += util/help.o -LIB_OBJS += util/levenshtein.o -LIB_OBJS += util/parse-options.o -LIB_OBJS += util/parse-events.o -LIB_OBJS += util/path.o -LIB_OBJS += util/rbtree.o -LIB_OBJS += util/bitmap.o -LIB_OBJS += util/hweight.o -LIB_OBJS += util/find_next_bit.o -LIB_OBJS += util/run-command.o -LIB_OBJS += util/quote.o -LIB_OBJS += util/strbuf.o -LIB_OBJS += util/string.o -LIB_OBJS += util/strlist.o -LIB_OBJS += util/usage.o -LIB_OBJS += util/wrapper.o -LIB_OBJS += util/sigchain.o -LIB_OBJS += util/symbol.o -LIB_OBJS += util/color.o -LIB_OBJS += util/pager.o -LIB_OBJS += util/header.o -LIB_OBJS += util/callchain.o -LIB_OBJS += util/values.o -LIB_OBJS += util/debug.o -LIB_OBJS += util/map.o -LIB_OBJS += util/session.o -LIB_OBJS += util/thread.o -LIB_OBJS += util/trace-event-parse.o -LIB_OBJS += util/trace-event-read.o -LIB_OBJS += util/trace-event-info.o -LIB_OBJS += util/trace-event-scripting.o -LIB_OBJS += util/svghelper.o -LIB_OBJS += util/sort.o -LIB_OBJS += util/hist.o -LIB_OBJS += util/probe-event.o -LIB_OBJS += util/util.o -LIB_OBJS += util/cpumap.o - -BUILTIN_OBJS += builtin-annotate.o - -BUILTIN_OBJS += builtin-bench.o +LIB_OBJS += $(OUTPUT)util/abspath.o +LIB_OBJS += $(OUTPUT)util/alias.o +LIB_OBJS += $(OUTPUT)util/build-id.o +LIB_OBJS += $(OUTPUT)util/config.o +LIB_OBJS += $(OUTPUT)util/ctype.o +LIB_OBJS += $(OUTPUT)util/debugfs.o +LIB_OBJS += $(OUTPUT)util/environment.o +LIB_OBJS += $(OUTPUT)util/event.o +LIB_OBJS += $(OUTPUT)util/exec_cmd.o +LIB_OBJS += $(OUTPUT)util/help.o +LIB_OBJS += $(OUTPUT)util/levenshtein.o +LIB_OBJS += $(OUTPUT)util/parse-options.o +LIB_OBJS += $(OUTPUT)util/parse-events.o +LIB_OBJS += $(OUTPUT)util/path.o +LIB_OBJS += $(OUTPUT)util/rbtree.o +LIB_OBJS += $(OUTPUT)util/bitmap.o +LIB_OBJS += $(OUTPUT)util/hweight.o +LIB_OBJS += $(OUTPUT)util/find_next_bit.o +LIB_OBJS += $(OUTPUT)util/run-command.o +LIB_OBJS += $(OUTPUT)util/quote.o +LIB_OBJS += $(OUTPUT)util/strbuf.o +LIB_OBJS += $(OUTPUT)util/string.o +LIB_OBJS += $(OUTPUT)util/strlist.o +LIB_OBJS += $(OUTPUT)util/usage.o +LIB_OBJS += $(OUTPUT)util/wrapper.o +LIB_OBJS += $(OUTPUT)util/sigchain.o +LIB_OBJS += $(OUTPUT)util/symbol.o +LIB_OBJS += $(OUTPUT)util/color.o +LIB_OBJS += $(OUTPUT)util/pager.o +LIB_OBJS += $(OUTPUT)util/header.o +LIB_OBJS += $(OUTPUT)util/callchain.o +LIB_OBJS += $(OUTPUT)util/values.o +LIB_OBJS += $(OUTPUT)util/debug.o +LIB_OBJS += $(OUTPUT)util/map.o +LIB_OBJS += $(OUTPUT)util/session.o +LIB_OBJS += $(OUTPUT)util/thread.o +LIB_OBJS += $(OUTPUT)util/trace-event-parse.o +LIB_OBJS += $(OUTPUT)util/trace-event-read.o +LIB_OBJS += $(OUTPUT)util/trace-event-info.o +LIB_OBJS += $(OUTPUT)util/trace-event-scripting.o +LIB_OBJS += $(OUTPUT)util/svghelper.o +LIB_OBJS += $(OUTPUT)util/sort.o +LIB_OBJS += $(OUTPUT)util/hist.o +LIB_OBJS += $(OUTPUT)util/probe-event.o +LIB_OBJS += $(OUTPUT)util/util.o +LIB_OBJS += $(OUTPUT)util/cpumap.o + +BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o + +BUILTIN_OBJS += $(OUTPUT)builtin-bench.o # Benchmark modules -BUILTIN_OBJS += bench/sched-messaging.o -BUILTIN_OBJS += bench/sched-pipe.o -BUILTIN_OBJS += bench/mem-memcpy.o - -BUILTIN_OBJS += builtin-diff.o -BUILTIN_OBJS += builtin-help.o -BUILTIN_OBJS += builtin-sched.o -BUILTIN_OBJS += builtin-buildid-list.o -BUILTIN_OBJS += builtin-buildid-cache.o -BUILTIN_OBJS += builtin-list.o -BUILTIN_OBJS += builtin-record.o -BUILTIN_OBJS += builtin-report.o -BUILTIN_OBJS += builtin-stat.o -BUILTIN_OBJS += builtin-timechart.o -BUILTIN_OBJS += builtin-top.o -BUILTIN_OBJS += builtin-trace.o -BUILTIN_OBJS += builtin-probe.o -BUILTIN_OBJS += builtin-kmem.o -BUILTIN_OBJS += builtin-lock.o +BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o +BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o +BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o + +BUILTIN_OBJS += $(OUTPUT)builtin-diff.o +BUILTIN_OBJS += $(OUTPUT)builtin-help.o +BUILTIN_OBJS += $(OUTPUT)builtin-sched.o +BUILTIN_OBJS += $(OUTPUT)builtin-buildid-list.o +BUILTIN_OBJS += $(OUTPUT)builtin-buildid-cache.o +BUILTIN_OBJS += $(OUTPUT)builtin-list.o +BUILTIN_OBJS += $(OUTPUT)builtin-record.o +BUILTIN_OBJS += $(OUTPUT)builtin-report.o +BUILTIN_OBJS += $(OUTPUT)builtin-stat.o +BUILTIN_OBJS += $(OUTPUT)builtin-timechart.o +BUILTIN_OBJS += $(OUTPUT)builtin-top.o +BUILTIN_OBJS += $(OUTPUT)builtin-trace.o +BUILTIN_OBJS += $(OUTPUT)builtin-probe.o +BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o +BUILTIN_OBJS += $(OUTPUT)builtin-lock.o PERFLIBS = $(LIB_FILE) @@ -494,6 +502,10 @@ ifeq ($(uname_S),Darwin) PTHREAD_LIBS = endif +ifneq ($(OUTPUT),) + BASIC_CFLAGS += -I$(OUTPUT) +endif + ifeq ($(shell sh -c "(echo '\#include '; echo 'int main(void) { Elf * elf = elf_begin(0, ELF_C_READ, 0); return (long)elf; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y) ifneq ($(shell sh -c "(echo '\#include '; echo 'int main(void) { const char * version = gnu_get_libc_version(); return (long)version; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y) msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static); @@ -512,7 +524,7 @@ else ifndef NO_DWARF BASIC_CFLAGS += -I/usr/include/elfutils -DDWARF_SUPPORT EXTLIBS += -lelf -ldw - LIB_OBJS += util/probe-finder.o + LIB_OBJS += $(OUTPUT)util/probe-finder.o endif endif @@ -521,7 +533,7 @@ ifneq ($(shell sh -c "(echo '\#include '; echo 'int main(void) { newtIni BASIC_CFLAGS += -DNO_NEWT_SUPPORT else EXTLIBS += -lnewt - LIB_OBJS += util/newt.o + LIB_OBJS += $(OUTPUT)util/newt.o endif ifndef NO_LIBPERL @@ -533,8 +545,8 @@ ifneq ($(shell sh -c "(echo '\#include '; echo '\#include '; e BASIC_CFLAGS += -DNO_LIBPERL else ALL_LDFLAGS += $(PERL_EMBED_LDOPTS) - LIB_OBJS += util/scripting-engines/trace-event-perl.o - LIB_OBJS += scripts/perl/Perf-Trace-Util/Context.o + LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-perl.o + LIB_OBJS += $(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o endif ifndef NO_LIBPYTHON @@ -546,8 +558,8 @@ ifneq ($(shell sh -c "(echo '\#include '; echo 'int main(void) { Py_In BASIC_CFLAGS += -DNO_LIBPYTHON else ALL_LDFLAGS += $(PYTHON_EMBED_LDOPTS) - LIB_OBJS += util/scripting-engines/trace-event-python.o - LIB_OBJS += scripts/python/Perf-Trace-Util/Context.o + LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-python.o + LIB_OBJS += $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o endif ifdef NO_DEMANGLE @@ -618,53 +630,53 @@ ifdef NO_C99_FORMAT endif ifdef SNPRINTF_RETURNS_BOGUS COMPAT_CFLAGS += -DSNPRINTF_RETURNS_BOGUS - COMPAT_OBJS += compat/snprintf.o + COMPAT_OBJS += $(OUTPUT)compat/snprintf.o endif ifdef FREAD_READS_DIRECTORIES COMPAT_CFLAGS += -DFREAD_READS_DIRECTORIES - COMPAT_OBJS += compat/fopen.o + COMPAT_OBJS += $(OUTPUT)compat/fopen.o endif ifdef NO_SYMLINK_HEAD BASIC_CFLAGS += -DNO_SYMLINK_HEAD endif ifdef NO_STRCASESTR COMPAT_CFLAGS += -DNO_STRCASESTR - COMPAT_OBJS += compat/strcasestr.o + COMPAT_OBJS += $(OUTPUT)compat/strcasestr.o endif ifdef NO_STRTOUMAX COMPAT_CFLAGS += -DNO_STRTOUMAX - COMPAT_OBJS += compat/strtoumax.o + COMPAT_OBJS += $(OUTPUT)compat/strtoumax.o endif ifdef NO_STRTOULL COMPAT_CFLAGS += -DNO_STRTOULL endif ifdef NO_SETENV COMPAT_CFLAGS += -DNO_SETENV - COMPAT_OBJS += compat/setenv.o + COMPAT_OBJS += $(OUTPUT)compat/setenv.o endif ifdef NO_MKDTEMP COMPAT_CFLAGS += -DNO_MKDTEMP - COMPAT_OBJS += compat/mkdtemp.o + COMPAT_OBJS += $(OUTPUT)compat/mkdtemp.o endif ifdef NO_UNSETENV COMPAT_CFLAGS += -DNO_UNSETENV - COMPAT_OBJS += compat/unsetenv.o + COMPAT_OBJS += $(OUTPUT)compat/unsetenv.o endif ifdef NO_SYS_SELECT_H BASIC_CFLAGS += -DNO_SYS_SELECT_H endif ifdef NO_MMAP COMPAT_CFLAGS += -DNO_MMAP - COMPAT_OBJS += compat/mmap.o + COMPAT_OBJS += $(OUTPUT)compat/mmap.o else ifdef USE_WIN32_MMAP COMPAT_CFLAGS += -DUSE_WIN32_MMAP - COMPAT_OBJS += compat/win32mmap.o + COMPAT_OBJS += $(OUTPUT)compat/win32mmap.o endif endif ifdef NO_PREAD COMPAT_CFLAGS += -DNO_PREAD - COMPAT_OBJS += compat/pread.o + COMPAT_OBJS += $(OUTPUT)compat/pread.o endif ifdef NO_FAST_WORKING_DIRECTORY BASIC_CFLAGS += -DNO_FAST_WORKING_DIRECTORY @@ -686,10 +698,10 @@ else endif endif ifdef NO_INET_NTOP - LIB_OBJS += compat/inet_ntop.o + LIB_OBJS += $(OUTPUT)compat/inet_ntop.o endif ifdef NO_INET_PTON - LIB_OBJS += compat/inet_pton.o + LIB_OBJS += $(OUTPUT)compat/inet_pton.o endif ifdef NO_ICONV @@ -706,15 +718,15 @@ endif ifdef PPC_SHA1 SHA1_HEADER = "ppc/sha1.h" - LIB_OBJS += ppc/sha1.o ppc/sha1ppc.o + LIB_OBJS += $(OUTPUT)ppc/sha1.o ppc/sha1ppc.o else ifdef ARM_SHA1 SHA1_HEADER = "arm/sha1.h" - LIB_OBJS += arm/sha1.o arm/sha1_arm.o + LIB_OBJS += $(OUTPUT)arm/sha1.o $(OUTPUT)arm/sha1_arm.o else ifdef MOZILLA_SHA1 SHA1_HEADER = "mozilla-sha1/sha1.h" - LIB_OBJS += mozilla-sha1/sha1.o + LIB_OBJS += $(OUTPUT)mozilla-sha1/sha1.o else SHA1_HEADER = EXTLIBS += $(LIB_4_CRYPTO) @@ -726,15 +738,15 @@ ifdef NO_PERL_MAKEMAKER endif ifdef NO_HSTRERROR COMPAT_CFLAGS += -DNO_HSTRERROR - COMPAT_OBJS += compat/hstrerror.o + COMPAT_OBJS += $(OUTPUT)compat/hstrerror.o endif ifdef NO_MEMMEM COMPAT_CFLAGS += -DNO_MEMMEM - COMPAT_OBJS += compat/memmem.o + COMPAT_OBJS += $(OUTPUT)compat/memmem.o endif ifdef INTERNAL_QSORT COMPAT_CFLAGS += -DINTERNAL_QSORT - COMPAT_OBJS += compat/qsort.o + COMPAT_OBJS += $(OUTPUT)compat/qsort.o endif ifdef RUNTIME_PREFIX COMPAT_CFLAGS += -DRUNTIME_PREFIX @@ -814,7 +826,7 @@ export TAR INSTALL DESTDIR SHELL_PATH SHELL = $(SHELL_PATH) -all:: .perf.dev.null shell_compatibility_test $(ALL_PROGRAMS) $(BUILT_INS) $(OTHER_PROGRAMS) PERF-BUILD-OPTIONS +all:: .perf.dev.null shell_compatibility_test $(ALL_PROGRAMS) $(BUILT_INS) $(OTHER_PROGRAMS) $(OUTPUT)PERF-BUILD-OPTIONS ifneq (,$X) $(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) perf$X)), test '$p' -ef '$p$X' || $(RM) '$p';) endif @@ -826,39 +838,39 @@ please_set_SHELL_PATH_to_a_more_modern_shell: shell_compatibility_test: please_set_SHELL_PATH_to_a_more_modern_shell -strip: $(PROGRAMS) perf$X - $(STRIP) $(STRIP_OPTS) $(PROGRAMS) perf$X +strip: $(PROGRAMS) $(OUTPUT)perf$X + $(STRIP) $(STRIP_OPTS) $(PROGRAMS) $(OUTPUT)perf$X -perf.o: perf.c common-cmds.h PERF-CFLAGS +$(OUTPUT)perf.o: perf.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS $(QUIET_CC)$(CC) -DPERF_VERSION='"$(PERF_VERSION)"' \ '-DPERF_HTML_PATH="$(htmldir_SQ)"' \ - $(ALL_CFLAGS) -c $(filter %.c,$^) + $(ALL_CFLAGS) -c $(filter %.c,$^) -o $@ -perf$X: perf.o $(BUILTIN_OBJS) $(PERFLIBS) - $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ perf.o \ +$(OUTPUT)perf$X: $(OUTPUT)perf.o $(BUILTIN_OBJS) $(PERFLIBS) + $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(OUTPUT)perf.o \ $(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS) -builtin-help.o: builtin-help.c common-cmds.h PERF-CFLAGS - $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) \ +$(OUTPUT)builtin-help.o: builtin-help.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS + $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \ '-DPERF_HTML_PATH="$(htmldir_SQ)"' \ '-DPERF_MAN_PATH="$(mandir_SQ)"' \ '-DPERF_INFO_PATH="$(infodir_SQ)"' $< -builtin-timechart.o: builtin-timechart.c common-cmds.h PERF-CFLAGS - $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) \ +$(OUTPUT)builtin-timechart.o: builtin-timechart.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS + $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \ '-DPERF_HTML_PATH="$(htmldir_SQ)"' \ '-DPERF_MAN_PATH="$(mandir_SQ)"' \ '-DPERF_INFO_PATH="$(infodir_SQ)"' $< -$(BUILT_INS): perf$X +$(BUILT_INS): $(OUTPUT)perf$X $(QUIET_BUILT_IN)$(RM) $@ && \ ln perf$X $@ 2>/dev/null || \ ln -s perf$X $@ 2>/dev/null || \ cp perf$X $@ -common-cmds.h: util/generate-cmdlist.sh command-list.txt +$(OUTPUT)common-cmds.h: util/generate-cmdlist.sh command-list.txt -common-cmds.h: $(wildcard Documentation/perf-*.txt) +$(OUTPUT)common-cmds.h: $(wildcard Documentation/perf-*.txt) $(QUIET_GEN). util/generate-cmdlist.sh > $@+ && mv $@+ $@ $(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh @@ -870,7 +882,7 @@ $(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh -e 's/@@NO_CURL@@/$(NO_CURL)/g' \ $@.sh >$@+ && \ chmod +x $@+ && \ - mv $@+ $@ + mv $@+ $(OUTPUT)$@ configure: configure.ac $(QUIET_GEN)$(RM) $@ $<+ && \ @@ -880,60 +892,60 @@ configure: configure.ac $(RM) $<+ # These can record PERF_VERSION -perf.o perf.spec \ +$(OUTPUT)perf.o perf.spec \ $(patsubst %.sh,%,$(SCRIPT_SH)) \ $(patsubst %.perl,%,$(SCRIPT_PERL)) \ - : PERF-VERSION-FILE + : $(OUTPUT)PERF-VERSION-FILE -%.o: %.c PERF-CFLAGS - $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) $< -%.s: %.c PERF-CFLAGS +$(OUTPUT)%.o: %.c $(OUTPUT)PERF-CFLAGS + $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $< +$(OUTPUT)%.s: %.c $(OUTPUT)PERF-CFLAGS $(QUIET_CC)$(CC) -S $(ALL_CFLAGS) $< -%.o: %.S - $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) $< +$(OUTPUT)%.o: %.S + $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $< -util/exec_cmd.o: util/exec_cmd.c PERF-CFLAGS - $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) \ +$(OUTPUT)util/exec_cmd.o: util/exec_cmd.c $(OUTPUT)PERF-CFLAGS + $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \ '-DPERF_EXEC_PATH="$(perfexecdir_SQ)"' \ '-DBINDIR="$(bindir_relative_SQ)"' \ '-DPREFIX="$(prefix_SQ)"' \ $< -builtin-init-db.o: builtin-init-db.c PERF-CFLAGS - $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DDEFAULT_PERF_TEMPLATE_DIR='"$(template_dir_SQ)"' $< +$(OUTPUT)builtin-init-db.o: builtin-init-db.c $(OUTPUT)PERF-CFLAGS + $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DDEFAULT_PERF_TEMPLATE_DIR='"$(template_dir_SQ)"' $< -util/config.o: util/config.c PERF-CFLAGS - $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< +$(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS + $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< -util/rbtree.o: ../../lib/rbtree.c PERF-CFLAGS - $(QUIET_CC)$(CC) -o util/rbtree.o -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< +$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS + $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< # some perf warning policies can't fit to lib/bitmap.c, eg: it warns about variable shadowing # from that comes from kernel headers wrapping. KBITMAP_FLAGS=`echo $(ALL_CFLAGS) | sed s/-Wshadow// | sed s/-Wswitch-default// | sed s/-Wextra//` -util/bitmap.o: ../../lib/bitmap.c PERF-CFLAGS - $(QUIET_CC)$(CC) -o util/bitmap.o -c $(KBITMAP_FLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< +$(OUTPUT)util/bitmap.o: ../../lib/bitmap.c $(OUTPUT)PERF-CFLAGS + $(QUIET_CC)$(CC) -o $@ -c $(KBITMAP_FLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< -util/hweight.o: ../../lib/hweight.c PERF-CFLAGS - $(QUIET_CC)$(CC) -o util/hweight.o -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< +$(OUTPUT)util/hweight.o: ../../lib/hweight.c $(OUTPUT)PERF-CFLAGS + $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< -util/find_next_bit.o: ../../lib/find_next_bit.c PERF-CFLAGS - $(QUIET_CC)$(CC) -o util/find_next_bit.o -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< +$(OUTPUT)util/find_next_bit.o: ../../lib/find_next_bit.c $(OUTPUT)PERF-CFLAGS + $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< -util/scripting-engines/trace-event-perl.o: util/scripting-engines/trace-event-perl.c PERF-CFLAGS - $(QUIET_CC)$(CC) -o util/scripting-engines/trace-event-perl.o -c $(ALL_CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $< +$(OUTPUT)util/scripting-engines/trace-event-perl.o: util/scripting-engines/trace-event-perl.c $(OUTPUT)PERF-CFLAGS + $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $< -scripts/perl/Perf-Trace-Util/Context.o: scripts/perl/Perf-Trace-Util/Context.c PERF-CFLAGS - $(QUIET_CC)$(CC) -o scripts/perl/Perf-Trace-Util/Context.o -c $(ALL_CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs $< +$(OUTPUT)scripts/perl/Perf-Trace-Util/Context.o: scripts/perl/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS + $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs $< -util/scripting-engines/trace-event-python.o: util/scripting-engines/trace-event-python.c PERF-CFLAGS - $(QUIET_CC)$(CC) -o util/scripting-engines/trace-event-python.o -c $(ALL_CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $< +$(OUTPUT)util/scripting-engines/trace-event-python.o: util/scripting-engines/trace-event-python.c $(OUTPUT)PERF-CFLAGS + $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $< -scripts/python/Perf-Trace-Util/Context.o: scripts/python/Perf-Trace-Util/Context.c PERF-CFLAGS - $(QUIET_CC)$(CC) -o scripts/python/Perf-Trace-Util/Context.o -c $(ALL_CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs $< +$(OUTPUT)scripts/python/Perf-Trace-Util/Context.o: scripts/python/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS + $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs $< -perf-%$X: %.o $(PERFLIBS) +$(OUTPUT)perf-%$X: %.o $(PERFLIBS) $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS) $(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H) @@ -974,17 +986,17 @@ cscope: TRACK_CFLAGS = $(subst ','\'',$(ALL_CFLAGS)):\ $(bindir_SQ):$(perfexecdir_SQ):$(template_dir_SQ):$(prefix_SQ) -PERF-CFLAGS: .FORCE-PERF-CFLAGS +$(OUTPUT)PERF-CFLAGS: .FORCE-PERF-CFLAGS @FLAGS='$(TRACK_CFLAGS)'; \ - if test x"$$FLAGS" != x"`cat PERF-CFLAGS 2>/dev/null`" ; then \ + if test x"$$FLAGS" != x"`cat $(OUTPUT)PERF-CFLAGS 2>/dev/null`" ; then \ echo 1>&2 " * new build flags or prefix"; \ - echo "$$FLAGS" >PERF-CFLAGS; \ + echo "$$FLAGS" >$(OUTPUT)PERF-CFLAGS; \ fi # We need to apply sq twice, once to protect from the shell -# that runs PERF-BUILD-OPTIONS, and then again to protect it +# that runs $(OUTPUT)PERF-BUILD-OPTIONS, and then again to protect it # and the first level quoting from the shell that runs "echo". -PERF-BUILD-OPTIONS: .FORCE-PERF-BUILD-OPTIONS +$(OUTPUT)PERF-BUILD-OPTIONS: .FORCE-PERF-BUILD-OPTIONS @echo SHELL_PATH=\''$(subst ','\'',$(SHELL_PATH_SQ))'\' >$@ @echo TAR=\''$(subst ','\'',$(subst ','\'',$(TAR)))'\' >>$@ @echo NO_CURL=\''$(subst ','\'',$(subst ','\'',$(NO_CURL)))'\' >>$@ @@ -1005,7 +1017,7 @@ all:: $(TEST_PROGRAMS) export NO_SVN_TESTS -check: common-cmds.h +check: $(OUTPUT)common-cmds.h if sparse; \ then \ for i in *.c */*.c; \ @@ -1039,10 +1051,10 @@ export perfexec_instdir install: all $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)' - $(INSTALL) perf$X '$(DESTDIR_SQ)$(bindir_SQ)' + $(INSTALL) $(OUTPUT)perf$X '$(DESTDIR_SQ)$(bindir_SQ)' $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace' $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin' - $(INSTALL) perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' + $(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' $(INSTALL) scripts/perl/Perf-Trace-Util/lib/Perf/Trace/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace' $(INSTALL) scripts/perl/*.pl -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl' $(INSTALL) scripts/perl/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin' @@ -1056,7 +1068,7 @@ ifdef BUILT_INS $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' $(INSTALL) $(BUILT_INS) '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' ifneq (,$X) - $(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) perf$X)), $(RM) '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/$p';) + $(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) $(OUTPUT)perf$X)), $(RM) '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/$p';) endif endif @@ -1140,14 +1152,14 @@ clean: $(RM) *.o */*.o */*/*.o */*/*/*.o $(LIB_FILE) $(RM) $(ALL_PROGRAMS) $(BUILT_INS) perf$X $(RM) $(TEST_PROGRAMS) - $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo common-cmds.h TAGS tags cscope* + $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(RM) -r autom4te.cache $(RM) config.log config.mak.autogen config.mak.append config.status config.cache $(RM) -r $(PERF_TARNAME) .doc-tmp-dir $(RM) $(PERF_TARNAME).tar.gz perf-core_$(PERF_VERSION)-*.tar.gz $(RM) $(htmldocs).tar.gz $(manpages).tar.gz $(MAKE) -C Documentation/ clean - $(RM) PERF-VERSION-FILE PERF-CFLAGS PERF-BUILD-OPTIONS + $(RM) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)PERF-BUILD-OPTIONS .PHONY: all install clean strip .PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell diff --git a/tools/perf/util/PERF-VERSION-GEN b/tools/perf/util/PERF-VERSION-GEN index 54552a0..49ece79 100755 --- a/tools/perf/util/PERF-VERSION-GEN +++ b/tools/perf/util/PERF-VERSION-GEN @@ -1,6 +1,10 @@ #!/bin/sh -GVF=PERF-VERSION-FILE +if [ $# -eq 1 ] ; then + OUTPUT=$1 +fi + +GVF=${OUTPUT}PERF-VERSION-FILE DEF_VER=v0.0.2.PERF LF=' -- cgit v0.10.2 From 70162138c91b040da3162fe1f34fe8aaf6506f10 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 30 Mar 2010 18:27:39 -0300 Subject: perf record: Add a fallback to the reference relocation symbol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Usually "_text" is enough, but I received reports that its not always available, so fallback to "_stext" for the symbol we use to check if we need to apply any relocation to all the symbols in the kernel symtab, for when, for instance, kexec is being used. Reported-by: Darren Hart Cc: Darren Hart Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 60ecdd3..80dc444 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -575,6 +575,9 @@ static int __cmd_record(int argc, const char **argv) err = event__synthesize_kernel_mmap(process_synthesized_event, session, "_text"); + if (err < 0) + err = event__synthesize_kernel_mmap(process_synthesized_event, + session, "_stext"); if (err < 0) { pr_err("Couldn't record kernel reference relocation symbol.\n"); return err; -- cgit v0.10.2 From a4e3b956a820162b7c1d616117b4f23b6017f504 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 31 Mar 2010 11:33:40 -0300 Subject: perf hist: Replace ->print() routines by ->snprintf() equivalents MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Then hist_entry__fprintf will just us the newly introduced hist_entry__snprintf, add the newline and fprintf it to the supplied FILE descriptor. This allows us to remove the use_browser checking in the color_printf routines, that now got color_snprintf variants too. The newt TUI browser (and other GUIs that may come in the future) don't have to worry about stdio specific stuff in the strings they get from the se->snprintf routines and instead use whatever means to do the equivalent. Also the newt TUI browser don't have to use the fmemopen() hack, instead it can use the se->snprintf routines directly. For now tho use the hist_entry__snprintf routine to reduce the patch size. Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c index 9da0191..e191eb9 100644 --- a/tools/perf/util/color.c +++ b/tools/perf/util/color.c @@ -166,6 +166,31 @@ int perf_color_default_config(const char *var, const char *value, void *cb) return perf_default_config(var, value, cb); } +static int __color_vsnprintf(char *bf, size_t size, const char *color, + const char *fmt, va_list args, const char *trail) +{ + int r = 0; + + /* + * Auto-detect: + */ + if (perf_use_color_default < 0) { + if (isatty(1) || pager_in_use()) + perf_use_color_default = 1; + else + perf_use_color_default = 0; + } + + if (perf_use_color_default && *color) + r += snprintf(bf, size, "%s", color); + r += vsnprintf(bf + r, size - r, fmt, args); + if (perf_use_color_default && *color) + r += snprintf(bf + r, size - r, "%s", PERF_COLOR_RESET); + if (trail) + r += snprintf(bf + r, size - r, "%s", trail); + return r; +} + static int __color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args, const char *trail) { @@ -191,11 +216,28 @@ static int __color_vfprintf(FILE *fp, const char *color, const char *fmt, return r; } +int color_vsnprintf(char *bf, size_t size, const char *color, + const char *fmt, va_list args) +{ + return __color_vsnprintf(bf, size, color, fmt, args, NULL); +} + int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args) { return __color_vfprintf(fp, color, fmt, args, NULL); } +int color_snprintf(char *bf, size_t size, const char *color, + const char *fmt, ...) +{ + va_list args; + int r; + + va_start(args, fmt); + r = color_vsnprintf(bf, size, color, fmt, args); + va_end(args); + return r; +} int color_fprintf(FILE *fp, const char *color, const char *fmt, ...) { @@ -203,10 +245,7 @@ int color_fprintf(FILE *fp, const char *color, const char *fmt, ...) int r; va_start(args, fmt); - if (use_browser) - r = vfprintf(fp, fmt, args); - else - r = color_vfprintf(fp, color, fmt, args); + r = color_vfprintf(fp, color, fmt, args); va_end(args); return r; } @@ -277,3 +316,9 @@ int percent_color_fprintf(FILE *fp, const char *fmt, double percent) return r; } + +int percent_color_snprintf(char *bf, size_t size, const char *fmt, double percent) +{ + const char *color = get_percent_color(percent); + return color_snprintf(bf, size, color, fmt, percent); +} diff --git a/tools/perf/util/color.h b/tools/perf/util/color.h index 24e8809..dea082b 100644 --- a/tools/perf/util/color.h +++ b/tools/perf/util/color.h @@ -32,10 +32,14 @@ int perf_color_default_config(const char *var, const char *value, void *cb); int perf_config_colorbool(const char *var, const char *value, int stdout_is_tty); void color_parse(const char *value, const char *var, char *dst); void color_parse_mem(const char *value, int len, const char *var, char *dst); +int color_vsnprintf(char *bf, size_t size, const char *color, + const char *fmt, va_list args); int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args); int color_fprintf(FILE *fp, const char *color, const char *fmt, ...); +int color_snprintf(char *bf, size_t size, const char *color, const char *fmt, ...); int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...); int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf); +int percent_color_snprintf(char *bf, size_t size, const char *fmt, double percent); int percent_color_fprintf(FILE *fp, const char *fmt, double percent); const char *get_percent_color(double percent); diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index a46d093..f079491 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -455,16 +455,17 @@ static size_t hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self, return ret; } -size_t hist_entry__fprintf(struct hist_entry *self, +int hist_entry__snprintf(struct hist_entry *self, + char *s, size_t size, struct perf_session *pair_session, bool show_displacement, - long displacement, FILE *fp, + long displacement, bool color, u64 session_total) { struct sort_entry *se; u64 count, total; const char *sep = symbol_conf.field_sep; - size_t ret; + int ret; if (symbol_conf.exclude_other && !self->parent) return 0; @@ -477,17 +478,22 @@ size_t hist_entry__fprintf(struct hist_entry *self, total = session_total; } - if (total) - ret = percent_color_fprintf(fp, sep ? "%.2f" : " %6.2f%%", - (count * 100.0) / total); - else - ret = fprintf(fp, sep ? "%lld" : "%12lld ", count); + if (total) { + if (color) + ret = percent_color_snprintf(s, size, + sep ? "%.2f" : " %6.2f%%", + (count * 100.0) / total); + else + ret = snprintf(s, size, sep ? "%.2f" : " %6.2f%%", + (count * 100.0) / total); + } else + ret = snprintf(s, size, sep ? "%lld" : "%12lld ", count); if (symbol_conf.show_nr_samples) { if (sep) - ret += fprintf(fp, "%c%lld", *sep, count); + ret += snprintf(s + ret, size - ret, "%c%lld", *sep, count); else - ret += fprintf(fp, "%11lld", count); + ret += snprintf(s + ret, size - ret, "%11lld", count); } if (pair_session) { @@ -507,9 +513,9 @@ size_t hist_entry__fprintf(struct hist_entry *self, snprintf(bf, sizeof(bf), " "); if (sep) - ret += fprintf(fp, "%c%s", *sep, bf); + ret += snprintf(s + ret, size - ret, "%c%s", *sep, bf); else - ret += fprintf(fp, "%11.11s", bf); + ret += snprintf(s + ret, size - ret, "%11.11s", bf); if (show_displacement) { if (displacement) @@ -518,9 +524,9 @@ size_t hist_entry__fprintf(struct hist_entry *self, snprintf(bf, sizeof(bf), " "); if (sep) - ret += fprintf(fp, "%c%s", *sep, bf); + ret += snprintf(s + ret, size - ret, "%c%s", *sep, bf); else - ret += fprintf(fp, "%6.6s", bf); + ret += snprintf(s + ret, size - ret, "%6.6s", bf); } } @@ -528,11 +534,25 @@ size_t hist_entry__fprintf(struct hist_entry *self, if (se->elide) continue; - ret += fprintf(fp, "%s", sep ?: " "); - ret += se->print(fp, self, se->width ? *se->width : 0); + ret += snprintf(s + ret, size - ret, "%s", sep ?: " "); + ret += se->snprintf(self, s + ret, size - ret, + se->width ? *se->width : 0); } - return ret + fprintf(fp, "\n"); + return ret; +} + +int hist_entry__fprintf(struct hist_entry *self, + struct perf_session *pair_session, + bool show_displacement, + long displacement, FILE *fp, + u64 session_total) +{ + char bf[512]; + hist_entry__snprintf(self, bf, sizeof(bf), pair_session, + show_displacement, displacement, + true, session_total); + return fprintf(fp, "%s\n", bf); } static size_t hist_entry__fprintf_callchain(struct hist_entry *self, FILE *fp, diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index da6a8c1..ad17f0a 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -18,11 +18,16 @@ struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists, u64 count, bool *hit); extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *); extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *); -size_t hist_entry__fprintf(struct hist_entry *self, +int hist_entry__fprintf(struct hist_entry *self, struct perf_session *pair_session, bool show_displacement, long displacement, FILE *fp, u64 session_total); +int hist_entry__snprintf(struct hist_entry *self, + char *bf, size_t size, + struct perf_session *pair_session, + bool show_displacement, long displacement, + bool color, u64 session_total); void hist_entry__free(struct hist_entry *); u64 perf_session__output_resort(struct rb_root *hists, u64 total_samples); diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index b0210ae..edd628f 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -294,60 +294,17 @@ static void hist_entry__append_callchain_browser(struct hist_entry *self, } } -/* - * FIXME: get lib/string.c linked with perf somehow - */ -static char *skip_spaces(const char *str) -{ - while (isspace(*str)) - ++str; - return (char *)str; -} - -static char *strim(char *s) -{ - size_t size; - char *end; - - s = skip_spaces(s); - size = strlen(s); - if (!size) - return s; - - end = s + size - 1; - while (end >= s && isspace(*end)) - end--; - *(end + 1) = '\0'; - - return s; -} - static size_t hist_entry__append_browser(struct hist_entry *self, newtComponent tree, u64 total) { - char bf[1024], *s; - FILE *fp; + char s[256]; + size_t ret; if (symbol_conf.exclude_other && !self->parent) return 0; - fp = fmemopen(bf, sizeof(bf), "w"); - if (fp == NULL) - return 0; - - hist_entry__fprintf(self, NULL, false, 0, fp, total); - fclose(fp); - - /* - * FIXME: We shouldn't need to trim, as the printing routines shouldn't - * add spaces it in the first place, the stdio output routines should - * call a __snprintf method instead of the current __print (that - * actually is a __fprintf) one, but get the raw string and _then_ add - * the newline, as this is a detail of stdio printing, not needed in - * other UIs, e.g. newt. - */ - s = strim(bf); - + ret = hist_entry__snprintf(self, s, sizeof(s), NULL, + false, 0, false, total); if (symbol_conf.use_callchain) { int indexes[2]; @@ -357,7 +314,7 @@ static size_t hist_entry__append_browser(struct hist_entry *self, } else newtListboxAppendEntry(tree, s, &self->ms); - return strlen(s); + return ret; } static void map_symbol__annotate_browser(const struct map_symbol *self) diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 9b80c13..31329a1 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -18,10 +18,21 @@ char * field_sep; LIST_HEAD(hist_entry__sort_list); +static int hist_entry__thread_snprintf(struct hist_entry *self, char *bf, + size_t size, unsigned int width); +static int hist_entry__comm_snprintf(struct hist_entry *self, char *bf, + size_t size, unsigned int width); +static int hist_entry__dso_snprintf(struct hist_entry *self, char *bf, + size_t size, unsigned int width); +static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf, + size_t size, unsigned int width); +static int hist_entry__parent_snprintf(struct hist_entry *self, char *bf, + size_t size, unsigned int width); + struct sort_entry sort_thread = { .header = "Command: Pid", .cmp = sort__thread_cmp, - .print = sort__thread_print, + .snprintf = hist_entry__thread_snprintf, .width = &threads__col_width, }; @@ -29,27 +40,27 @@ struct sort_entry sort_comm = { .header = "Command", .cmp = sort__comm_cmp, .collapse = sort__comm_collapse, - .print = sort__comm_print, + .snprintf = hist_entry__comm_snprintf, .width = &comms__col_width, }; struct sort_entry sort_dso = { .header = "Shared Object", .cmp = sort__dso_cmp, - .print = sort__dso_print, + .snprintf = hist_entry__dso_snprintf, .width = &dsos__col_width, }; struct sort_entry sort_sym = { .header = "Symbol", .cmp = sort__sym_cmp, - .print = sort__sym_print, + .snprintf = hist_entry__sym_snprintf, }; struct sort_entry sort_parent = { .header = "Parent symbol", .cmp = sort__parent_cmp, - .print = sort__parent_print, + .snprintf = hist_entry__parent_snprintf, .width = &parent_symbol__col_width, }; @@ -85,45 +96,38 @@ sort__thread_cmp(struct hist_entry *left, struct hist_entry *right) return right->thread->pid - left->thread->pid; } -int repsep_fprintf(FILE *fp, const char *fmt, ...) +static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...) { int n; va_list ap; va_start(ap, fmt); - if (!field_sep) - n = vfprintf(fp, fmt, ap); - else { - char *bf = NULL; - n = vasprintf(&bf, fmt, ap); - if (n > 0) { - char *sep = bf; - - while (1) { - sep = strchr(sep, *field_sep); - if (sep == NULL) - break; - *sep = '.'; - } + n = vsnprintf(bf, size, fmt, ap); + if (field_sep && n > 0) { + char *sep = bf; + + while (1) { + sep = strchr(sep, *field_sep); + if (sep == NULL) + break; + *sep = '.'; } - fputs(bf, fp); - free(bf); } va_end(ap); return n; } -size_t -sort__thread_print(FILE *fp, struct hist_entry *self, unsigned int width) +static int hist_entry__thread_snprintf(struct hist_entry *self, char *bf, + size_t size, unsigned int width) { - return repsep_fprintf(fp, "%*s:%5d", width - 6, + return repsep_snprintf(bf, size, "%*s:%5d", width, self->thread->comm ?: "", self->thread->pid); } -size_t -sort__comm_print(FILE *fp, struct hist_entry *self, unsigned int width) +static int hist_entry__comm_snprintf(struct hist_entry *self, char *bf, + size_t size, unsigned int width) { - return repsep_fprintf(fp, "%*s", width, self->thread->comm); + return repsep_snprintf(bf, size, "%*s", width, self->thread->comm); } /* --sort dso */ @@ -149,16 +153,16 @@ sort__dso_cmp(struct hist_entry *left, struct hist_entry *right) return strcmp(dso_name_l, dso_name_r); } -size_t -sort__dso_print(FILE *fp, struct hist_entry *self, unsigned int width) +static int hist_entry__dso_snprintf(struct hist_entry *self, char *bf, + size_t size, unsigned int width) { if (self->ms.map && self->ms.map->dso) { const char *dso_name = !verbose ? self->ms.map->dso->short_name : self->ms.map->dso->long_name; - return repsep_fprintf(fp, "%-*s", width, dso_name); + return repsep_snprintf(bf, size, "%-*s", width, dso_name); } - return repsep_fprintf(fp, "%*llx", width, (u64)self->ip); + return repsep_snprintf(bf, size, "%*Lx", width, self->ip); } /* --sort symbol */ @@ -177,22 +181,22 @@ sort__sym_cmp(struct hist_entry *left, struct hist_entry *right) return (int64_t)(ip_r - ip_l); } - -size_t -sort__sym_print(FILE *fp, struct hist_entry *self, unsigned int width __used) +static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf, + size_t size, unsigned int width __used) { size_t ret = 0; if (verbose) { char o = self->ms.map ? dso__symtab_origin(self->ms.map->dso) : '!'; - ret += repsep_fprintf(fp, "%#018llx %c ", (u64)self->ip, o); + ret += repsep_snprintf(bf, size, "%#018llx %c ", self->ip, o); } - ret += repsep_fprintf(fp, "[%c] ", self->level); + ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", self->level); if (self->ms.sym) - ret += repsep_fprintf(fp, "%s", self->ms.sym->name); + ret += repsep_snprintf(bf + ret, size - ret, "%s", + self->ms.sym->name); else - ret += repsep_fprintf(fp, "%#016llx", (u64)self->ip); + ret += repsep_snprintf(bf + ret, size - ret, "%#016llx", self->ip); return ret; } @@ -231,10 +235,10 @@ sort__parent_cmp(struct hist_entry *left, struct hist_entry *right) return strcmp(sym_l->name, sym_r->name); } -size_t -sort__parent_print(FILE *fp, struct hist_entry *self, unsigned int width) +static int hist_entry__parent_snprintf(struct hist_entry *self, char *bf, + size_t size, unsigned int width) { - return repsep_fprintf(fp, "%-*s", width, + return repsep_snprintf(bf, size, "%-*s", width, self->parent ? self->parent->name : "[other]"); } diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index 5985686..439ec5f 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h @@ -76,7 +76,8 @@ struct sort_entry { int64_t (*cmp)(struct hist_entry *, struct hist_entry *); int64_t (*collapse)(struct hist_entry *, struct hist_entry *); - size_t (*print)(FILE *fp, struct hist_entry *, unsigned int width); + int (*snprintf)(struct hist_entry *self, char *bf, size_t size, + unsigned int width); unsigned int *width; bool elide; }; @@ -86,7 +87,6 @@ extern struct list_head hist_entry__sort_list; void setup_sorting(const char * const usagestr[], const struct option *opts); -extern int repsep_fprintf(FILE *fp, const char *fmt, ...); extern size_t sort__thread_print(FILE *, struct hist_entry *, unsigned int); extern size_t sort__comm_print(FILE *, struct hist_entry *, unsigned int); extern size_t sort__dso_print(FILE *, struct hist_entry *, unsigned int); -- cgit v0.10.2 From e727ca73f85d4c5be3547eda674168219d1c22d8 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 1 Apr 2010 19:12:13 -0300 Subject: perf kmem: Resolve kernel symbols again MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Due to the assumption in perf_session__new that the kernel maps would be created using the fake PERF_RECORD_MMAP event in a perf.data file 'perf kmem --stat caller', that doesn't have such event, ends up not being able to resolve the kernel addresses. Fix it by calling perf_session__create_kernel_maps() in __cmd_kmem(). LKML-Reference: Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index 32edb6a..7cbb5eb 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c @@ -489,6 +489,9 @@ static int __cmd_kmem(void) if (session == NULL) return -ENOMEM; + if (perf_session__create_kernel_maps(session) < 0) + goto out_delete; + if (!perf_session__has_traces(session, "kmem record")) goto out_delete; diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 32765cd..9da5e72 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -52,11 +52,6 @@ out_close: return -1; } -static inline int perf_session__create_kernel_maps(struct perf_session *self) -{ - return map_groups__create_kernel_maps(&self->kmaps, self->vmlinux_maps); -} - struct perf_session *perf_session__new(const char *filename, int mode, bool force) { size_t len = filename ? strlen(filename) + 1 : 0; diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 6a15dae..dffaff5 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -80,6 +80,11 @@ static inline int __perf_session__create_kernel_maps(struct perf_session *self, self->vmlinux_maps, kernel); } +static inline int perf_session__create_kernel_maps(struct perf_session *self) +{ + return map_groups__create_kernel_maps(&self->kmaps, self->vmlinux_maps); +} + static inline struct map * perf_session__new_module_map(struct perf_session *self, u64 start, const char *filename) -- cgit v0.10.2 From 71cf8b8ff7d6a79af086be9e4c72628da9d62d58 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 1 Apr 2010 21:24:38 -0300 Subject: perf kmem: Fixup the symbol address before using it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We get absolute addresses in the events, but relative ones from the symbol subsystem, so calculate the absolute address by asking for the map where the symbol was found, that has the place where the DSO was actually loaded. For the core kernel this poses no problems if the kernel is not relocated by things like kexec, or if we use /proc/kallsyms, but for modules we were getting really large, negative offsets. LKML-Reference: Cc: Frédéric Weisbecker Cc: Li Zefan Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index 7cbb5eb..513aa8a 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c @@ -363,6 +363,7 @@ static void __print_result(struct rb_root *root, struct perf_session *session, struct alloc_stat *data = rb_entry(next, struct alloc_stat, node); struct symbol *sym = NULL; + struct map *map; char buf[BUFSIZ]; u64 addr; @@ -370,13 +371,13 @@ static void __print_result(struct rb_root *root, struct perf_session *session, addr = data->call_site; if (!raw_ip) sym = map_groups__find_function(&session->kmaps, - addr, NULL, NULL); + addr, &map, NULL); } else addr = data->ptr; if (sym != NULL) snprintf(buf, sizeof(buf), "%s+%Lx", sym->name, - addr - sym->start); + addr - map->unmap_ip(map, sym->start)); else snprintf(buf, sizeof(buf), "%#Lx", addr); printf(" %-34s |", buf); -- cgit v0.10.2 From b9fb93047756c5e4129dfda7591612de61b0e877 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 2 Apr 2010 09:50:42 -0300 Subject: perf hist: Only allocate callchain_node if processing callchains MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The struct callchain_node size is 120 bytes, that are never used when there are no callchains or '-g none' is specified, so conditionally allocate it, reducing sizeof(struct hist_entry) from 210 bytes to only 96, greatly speeding the non-callchain processing. LKML-Reference: Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 3819185..1fb13e5 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -110,8 +110,8 @@ static int perf_session__add_hist_entry(struct perf_session *self, if (symbol_conf.use_callchain) { if (!hit) - callchain_init(&he->callchain); - err = append_chain(&he->callchain, data->callchain, syms); + callchain_init(he->callchain); + err = append_chain(he->callchain, data->callchain, syms); free(syms); if (err) diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index f079491..18cf8b3 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -50,7 +50,8 @@ struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists, p = &(*p)->rb_right; } - he = malloc(sizeof(*he)); + he = malloc(sizeof(*he) + (symbol_conf.use_callchain ? + sizeof(struct callchain_node) : 0)); if (!he) return NULL; *he = entry; @@ -168,7 +169,7 @@ static void perf_session__insert_output_hist_entry(struct rb_root *root, struct hist_entry *iter; if (symbol_conf.use_callchain) - callchain_param.sort(&he->sorted_chain, &he->callchain, + callchain_param.sort(&he->sorted_chain, he->callchain, min_callchain_hits, &callchain_param); while (*p != NULL) { diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index 439ec5f..5bf2b74 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h @@ -49,12 +49,12 @@ struct hist_entry { u64 ip; char level; struct symbol *parent; - struct callchain_node callchain; union { unsigned long position; struct hist_entry *pair; struct rb_root sorted_chain; }; + struct callchain_node callchain[0]; }; enum sort_type { -- cgit v0.10.2 From ad5b217b152d99ca3922153500c619d9758dd87a Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 2 Apr 2010 10:04:18 -0300 Subject: perf session: Remove one more exit() call from library code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Return NULL instead and make the caller propagate the error. LKML-Reference: Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 1fb13e5..6767f10 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -89,9 +89,12 @@ static int perf_session__add_hist_entry(struct perf_session *self, struct event_stat_id *stats; struct perf_event_attr *attr; - if ((sort__has_parent || symbol_conf.use_callchain) && data->callchain) + if ((sort__has_parent || symbol_conf.use_callchain) && data->callchain) { syms = perf_session__resolve_callchain(self, al->thread, data->callchain, &parent); + if (syms == NULL) + return -ENOMEM; + } attr = perf_header__find_attr(data->id, &self->header); if (attr) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 9da5e72..ddf288f 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -118,16 +118,11 @@ struct map_symbol *perf_session__resolve_callchain(struct perf_session *self, struct symbol **parent) { u8 cpumode = PERF_RECORD_MISC_USER; - struct map_symbol *syms = NULL; unsigned int i; + struct map_symbol *syms = calloc(chain->nr, sizeof(*syms)); - if (symbol_conf.use_callchain) { - syms = calloc(chain->nr, sizeof(*syms)); - if (!syms) { - fprintf(stderr, "Can't allocate memory for symbols\n"); - exit(-1); - } - } + if (!syms) + return NULL; for (i = 0; i < chain->nr; i++) { u64 ip = chain->ips[i]; -- cgit v0.10.2 From 2aefa4f733f2c5ce51dd2316ffecb258463fde71 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 2 Apr 2010 12:30:57 -0300 Subject: perf tools: sort_dimension__add shouldn't die MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Propagate error instead. LKML-Reference: Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 6767f10..b13a7e2 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -473,7 +473,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __used) setup_sorting(report_usage, options); if (parent_pattern != default_parent_pattern) { - sort_dimension__add("parent"); + if (sort_dimension__add("parent") < 0) + return -1; sort_parent.elide = 1; } else symbol_conf.exclude_other = false; diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 31329a1..9d24d4b 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -264,9 +264,8 @@ int sort_dimension__add(const char *tok) char err[BUFSIZ]; regerror(ret, &parent_regex, err, sizeof(err)); - fprintf(stderr, "Invalid regex: %s\n%s", - parent_pattern, err); - exit(-1); + pr_err("Invalid regex: %s\n%s", parent_pattern, err); + return -EINVAL; } sort__has_parent = 1; } -- cgit v0.10.2 From e206d556c5793ac5e28c0aaba2e07432e5f9a098 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 3 Apr 2010 10:19:26 -0300 Subject: perf tools: Move the prototypes in util/string.h to util.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So that we avoid conflict with libc's string.h header. Reviewed-by: KOSAKI Motohiro Suggested-by: KOSAKI Motohiro Cc: KOSAKI Motohiro Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 93029c0..9f5a47e 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -385,7 +385,6 @@ LIB_H += util/header.h LIB_H += util/help.h LIB_H += util/session.h LIB_H += util/strbuf.h -LIB_H += util/string.h LIB_H += util/strlist.h LIB_H += util/svghelper.h LIB_H += util/run-command.h diff --git a/tools/perf/bench/mem-memcpy.c b/tools/perf/bench/mem-memcpy.c index 8977317..52e646e 100644 --- a/tools/perf/bench/mem-memcpy.c +++ b/tools/perf/bench/mem-memcpy.c @@ -10,7 +10,6 @@ #include "../perf.h" #include "../util/util.h" #include "../util/parse-options.h" -#include "../util/string.h" #include "../util/header.h" #include "bench.h" diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 887e8e0..ee0d917 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -14,7 +14,6 @@ #include "util/cache.h" #include #include "util/symbol.h" -#include "util/string.h" #include "perf.h" #include "util/debug.h" diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 80dc444..dc61f1b 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -15,7 +15,6 @@ #include "util/util.h" #include "util/parse-options.h" #include "util/parse-events.h" -#include "util/string.h" #include "util/header.h" #include "util/event.h" diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index b13a7e2..6615e09 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -14,7 +14,6 @@ #include "util/cache.h" #include #include "util/symbol.h" -#include "util/string.h" #include "util/callchain.h" #include "util/strlist.h" #include "util/values.h" diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index 0d4d8ff..266e7aa 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c @@ -21,7 +21,6 @@ #include "util/cache.h" #include #include "util/symbol.h" -#include "util/string.h" #include "util/callchain.h" #include "util/strlist.h" diff --git a/tools/perf/perf.c b/tools/perf/perf.c index 2826e70..d4be55b 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c @@ -13,7 +13,6 @@ #include "util/quote.h" #include "util/run-command.h" #include "util/parse-events.h" -#include "util/string.h" #include "util/debugfs.h" bool use_browser; diff --git a/tools/perf/util/string.h b/tools/perf/util/string.h deleted file mode 100644 index 7005824..0000000 --- a/tools/perf/util/string.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef __PERF_STRING_H_ -#define __PERF_STRING_H_ - -#include -#include "types.h" - -s64 perf_atoll(const char *str); -char **argv_split(const char *str, int *argcp); -void argv_free(char **argv); -bool strglobmatch(const char *str, const char *pat); -bool strlazymatch(const char *str, const char *pat); - -#define _STR(x) #x -#define STR(x) _STR(x) - -#endif /* __PERF_STRING_H */ diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 5270108..fbf45d1 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -42,12 +42,14 @@ #define _ALL_SOURCE 1 #define _GNU_SOURCE 1 #define _BSD_SOURCE 1 +#define HAS_BOOL #include #include #include #include #include +#include #include #include #include @@ -78,6 +80,7 @@ #include #include #include "../../../include/linux/magic.h" +#include "types.h" #ifndef NO_ICONV @@ -415,4 +418,13 @@ void git_qsort(void *base, size_t nmemb, size_t size, int mkdir_p(char *path, mode_t mode); int copyfile(const char *from, const char *to); +s64 perf_atoll(const char *str); +char **argv_split(const char *str, int *argcp); +void argv_free(char **argv); +bool strglobmatch(const char *str, const char *pat); +bool strlazymatch(const char *str, const char *pat); + +#define _STR(x) #x +#define STR(x) _STR(x) + #endif -- cgit v0.10.2 From 4af8b35db6634dd1e0d616de689582b6c93550af Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Sat, 3 Apr 2010 22:53:31 +1100 Subject: perf symbols: Fill in pgoff in mmap synthesized events When we synthesize mmap events we need to fill in the pgoff field. I wasn't able to test this completely since I couldn't find an executable region with a non 0 offset. We will see it when we start doing data profiling. Signed-off-by: Anton Blanchard Cc: David Miller Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: <20100403115331.GK5594@kryten> Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 052eaec..571fb25 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -130,6 +130,7 @@ static int event__synthesize_mmap_events(pid_t pid, pid_t tgid, continue; pbf += n + 3; if (*pbf == 'x') { /* vm_exec */ + u64 vm_pgoff; char *execname = strchr(bf, '/'); /* Catch VDSO */ @@ -139,6 +140,14 @@ static int event__synthesize_mmap_events(pid_t pid, pid_t tgid, if (execname == NULL) continue; + pbf += 3; + n = hex2u64(pbf, &vm_pgoff); + /* pgoff is in bytes, not pages */ + if (n >= 0) + ev.mmap.pgoff = vm_pgoff << getpagesize(); + else + ev.mmap.pgoff = 0; + size = strlen(execname); execname[size - 1] = '\0'; /* Remove \n */ memcpy(ev.mmap.filename, execname, size); -- cgit v0.10.2 From fb6b893180faec03e1d32149ef5cc412df9714df Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 3 Apr 2010 11:04:55 -0300 Subject: perf newt: Remove useless column width calculation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Not used in the TUI interface. Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index edd628f..a2ba3ff 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -390,11 +390,8 @@ static void perf_session__selection(newtComponent self, void *data) int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, u64 session_total, const char *helpline) { - struct sort_entry *se; struct rb_node *nd; char seq[] = "."; - unsigned int width; - char *col_width = symbol_conf.col_width_list_str; int rows, cols, idx; int max_len = 0; char str[1024]; @@ -423,23 +420,6 @@ int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, newtComponentAddCallback(tree, perf_session__selection, &selection); - list_for_each_entry(se, &hist_entry__sort_list, list) { - if (se->elide) - continue; - width = strlen(se->header); - if (se->width) { - if (symbol_conf.col_width_list_str) { - if (col_width) { - *se->width = atoi(col_width); - col_width = strchr(col_width, ','); - if (col_width) - ++col_width; - } - } - *se->width = max(*se->width, width); - } - } - idx = 0; for (nd = rb_first(hists); nd; nd = rb_next(nd)) { struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); -- cgit v0.10.2 From e65713ea1e61e92d28284a55df2aa039ebe10003 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 3 Apr 2010 11:25:56 -0300 Subject: perf newt: Move the hist browser population bits to separare function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Next patches will use that when applying filtes to then repopulate the browser with the narrowed vision. Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index a2ba3ff..509d921 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -381,53 +381,69 @@ static const void *newt__symbol_tree_get_current(newtComponent self) return newtListboxGetCurrent(self); } -static void perf_session__selection(newtComponent self, void *data) +static void hist_browser__selection(newtComponent self, void *data) { const struct map_symbol **symbol_ptr = data; *symbol_ptr = newt__symbol_tree_get_current(self); } -int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, - u64 session_total, const char *helpline) +struct hist_browser { + newtComponent form, tree; + const struct map_symbol *selection; +}; + +static struct hist_browser *hist_browser__new(void) +{ + struct hist_browser *self = malloc(sizeof(*self)); + + if (self != NULL) { + char seq[] = "."; + int rows; + + newtGetScreenSize(NULL, &rows); + + if (symbol_conf.use_callchain) + self->tree = newtCheckboxTreeMulti(0, 0, rows - 5, seq, + NEWT_FLAG_SCROLL); + else + self->tree = newtListbox(0, 0, rows - 5, + (NEWT_FLAG_SCROLL | + NEWT_FLAG_RETURNEXIT)); + newtComponentAddCallback(self->tree, hist_browser__selection, + &self->selection); + } + + return self; +} + +static void hist_browser__delete(struct hist_browser *self) +{ + newtFormDestroy(self->form); + newtPopWindow(); + free(self); +} + +static int hist_browser__populate(struct hist_browser *self, struct rb_root *hists, + u64 nr_hists, u64 session_total) { + int max_len = 0, idx, cols, rows; + struct ui_progress *progress; struct rb_node *nd; - char seq[] = "."; - int rows, cols, idx; - int max_len = 0; - char str[1024]; - newtComponent form, tree; - struct newtExitStruct es; - const struct map_symbol *selection; u64 curr_hist = 0; - struct ui_progress *progress; progress = ui_progress__new("Adding entries to the browser...", nr_hists); if (progress == NULL) return -1; - snprintf(str, sizeof(str), "Samples: %Ld", session_total); - newtDrawRootText(0, 0, str); - newtPushHelpLine(helpline); - - newtGetScreenSize(&cols, &rows); - - if (symbol_conf.use_callchain) - tree = newtCheckboxTreeMulti(0, 0, rows - 5, seq, - NEWT_FLAG_SCROLL); - else - tree = newtListbox(0, 0, rows - 5, (NEWT_FLAG_SCROLL | - NEWT_FLAG_RETURNEXIT)); - - newtComponentAddCallback(tree, perf_session__selection, &selection); - idx = 0; for (nd = rb_first(hists); nd; nd = rb_next(nd)) { struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); - int len = hist_entry__append_browser(h, tree, session_total); + int len = hist_entry__append_browser(h, self->tree, session_total); if (len > max_len) max_len = len; if (symbol_conf.use_callchain) - hist_entry__append_callchain_browser(h, tree, session_total, idx++); + hist_entry__append_callchain_browser(h, self->tree, + session_total, idx++); ++curr_hist; if (curr_hist % 5) ui_progress__update(progress, curr_hist); @@ -435,27 +451,50 @@ int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, ui_progress__delete(progress); + newtGetScreenSize(&cols, &rows); + if (max_len > cols) max_len = cols - 3; if (!symbol_conf.use_callchain) - newtListboxSetWidth(tree, max_len); + newtListboxSetWidth(self->tree, max_len); newtCenteredWindow(max_len + (symbol_conf.use_callchain ? 5 : 0), rows - 5, "Report"); - form = newt_form__new(); - newtFormAddHotKey(form, 'A'); - newtFormAddHotKey(form, 'a'); - newtFormAddHotKey(form, NEWT_KEY_RIGHT); - newtFormAddComponents(form, tree, NULL); - selection = newt__symbol_tree_get_current(tree); + self->form = newt_form__new(); + newtFormAddHotKey(self->form, 'A'); + newtFormAddHotKey(self->form, 'a'); + newtFormAddHotKey(self->form, NEWT_KEY_RIGHT); + newtFormAddComponents(self->form, self->tree, NULL); + self->selection = newt__symbol_tree_get_current(self->tree); + + return 0; +} + +int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, + u64 session_total, const char *helpline) +{ + struct newtExitStruct es; + char str[1024]; + int err = -1; + struct hist_browser *browser = hist_browser__new(); + + if (browser == NULL) + return -1; + + snprintf(str, sizeof(str), "Samples: %Ld", session_total); + newtDrawRootText(0, 0, str); + newtPushHelpLine(helpline); + + if (hist_browser__populate(browser, hists, nr_hists, session_total) < 0) + goto out; while (1) { char annotate[512]; const char *options[2]; int nr_options = 0, choice = 0; - newtFormRun(form, &es); + newtFormRun(browser->form, &es); if (es.reason == NEWT_EXIT_HOTKEY) { if (toupper(es.u.key) == 'A') goto do_annotate; @@ -469,9 +508,9 @@ int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, } } - if (selection->sym != NULL) { + if (browser->selection->sym != NULL) { snprintf(annotate, sizeof(annotate), - "Annotate %s", selection->sym->name); + "Annotate %s", browser->selection->sym->name); options[nr_options++] = annotate; } @@ -480,21 +519,21 @@ int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, if (choice == nr_options - 1) break; do_annotate: - if (selection->sym != NULL && choice >= 0) { - if (selection->map->dso->origin == DSO__ORIG_KERNEL) { + if (browser->selection->sym != NULL && choice >= 0) { + if (browser->selection->map->dso->origin == DSO__ORIG_KERNEL) { newtPopHelpLine(); newtPushHelpLine("No vmlinux file found, can't " "annotate with just a " "kallsyms file"); continue; } - map_symbol__annotate_browser(selection); + map_symbol__annotate_browser(browser->selection); } } - - newtFormDestroy(form); - newtPopWindow(); - return 0; + err = 0; +out: + hist_browser__delete(browser); + return err; } void setup_browser(void) -- cgit v0.10.2 From 533c46c31c0e82f19dbb087c77d85eaccd6fefdb Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 3 Apr 2010 11:54:35 -0300 Subject: perf newt: Pass the input_name to perf_session__browse_hists MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So that it can use it in the 'perf annotate' command line, otherwise it'll use the default and not the specified -i filename passed to 'perf report'. Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 6615e09..e93c69a 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -313,7 +313,8 @@ static int __cmd_report(void) stats->stats.total); if (use_browser) perf_session__browse_hists(&stats->hists, nr_hists, - stats->stats.total, help); + stats->stats.total, help, + input_name); else { if (rb_first(&session->stats_by_id) == rb_last(&session->stats_by_id)) diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index 509d921..c93bc2a 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -317,7 +317,8 @@ static size_t hist_entry__append_browser(struct hist_entry *self, return ret; } -static void map_symbol__annotate_browser(const struct map_symbol *self) +static void map_symbol__annotate_browser(const struct map_symbol *self, + const char *input_name) { FILE *fp; int cols, rows; @@ -331,8 +332,8 @@ static void map_symbol__annotate_browser(const struct map_symbol *self) if (self->sym == NULL) return; - if (asprintf(&str, "perf annotate -d \"%s\" %s 2>&1 | expand", - self->map->dso->name, self->sym->name) < 0) + if (asprintf(&str, "perf annotate -i \"%s\" -d \"%s\" %s 2>&1 | expand", + input_name, self->map->dso->name, self->sym->name) < 0) return; fp = popen(str, "r"); @@ -472,7 +473,8 @@ static int hist_browser__populate(struct hist_browser *self, struct rb_root *his } int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, - u64 session_total, const char *helpline) + u64 session_total, const char *helpline, + const char *input_name) { struct newtExitStruct es; char str[1024]; @@ -527,7 +529,8 @@ do_annotate: "kallsyms file"); continue; } - map_symbol__annotate_browser(browser->selection); + map_symbol__annotate_browser(browser->selection, + input_name); } } err = 0; diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index dffaff5..27f4c2d 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -96,12 +96,14 @@ static inline struct map * static inline int perf_session__browse_hists(struct rb_root *hists __used, u64 nr_hists __used, u64 session_total __used, - const char *helpline __used) + const char *helpline __used, + const char *input_name __used) { return 0; } #else int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, - u64 session_total, const char *helpline); + u64 session_total, const char *helpline, + const char *input_name); #endif #endif /* __PERF_SESSION_H */ -- cgit v0.10.2 From 83753190c136901c916df267703937e60f24b8b8 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 3 Apr 2010 16:30:44 -0300 Subject: perf newt: Add a "Zoom into foo.so DSO" and reverse operations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clicking on -> will bring as one of the popup menu options a "Zoom into CURRENT DSO", i.e. CURRENT will be replaced by the name of the DSO in the current line. Choosing this option will filter out all samples that didn't took place in a symbol in this DSO. After that the option reverts to "Zoom out of CURRENT DSO", to allow going back to the more compreensive view, not filtered by DSO. Future similar operations will include zooming into a particular thread, COMM, CPU, "last minute", "last N usecs", etc. Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index c93bc2a..bbf725d 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -94,7 +94,7 @@ static newtComponent newt_form__new(void) return self; } -static int popup_menu(int argc, const char *argv[]) +static int popup_menu(int argc, char * const argv[]) { struct newtExitStruct es; int i, rc = -1, max_len = 5; @@ -397,22 +397,8 @@ static struct hist_browser *hist_browser__new(void) { struct hist_browser *self = malloc(sizeof(*self)); - if (self != NULL) { - char seq[] = "."; - int rows; - - newtGetScreenSize(NULL, &rows); - - if (symbol_conf.use_callchain) - self->tree = newtCheckboxTreeMulti(0, 0, rows - 5, seq, - NEWT_FLAG_SCROLL); - else - self->tree = newtListbox(0, 0, rows - 5, - (NEWT_FLAG_SCROLL | - NEWT_FLAG_RETURNEXIT)); - newtComponentAddCallback(self->tree, hist_browser__selection, - &self->selection); - } + if (self != NULL) + self->form = NULL; return self; } @@ -431,6 +417,30 @@ static int hist_browser__populate(struct hist_browser *self, struct rb_root *his struct ui_progress *progress; struct rb_node *nd; u64 curr_hist = 0; + char seq[] = "."; + char str[256]; + + if (self->form) { + newtFormDestroy(self->form); + newtPopWindow(); + } + + snprintf(str, sizeof(str), "Samples: %Ld ", + session_total); + newtDrawRootText(0, 0, str); + + newtGetScreenSize(NULL, &rows); + + if (symbol_conf.use_callchain) + self->tree = newtCheckboxTreeMulti(0, 0, rows - 5, seq, + NEWT_FLAG_SCROLL); + else + self->tree = newtListbox(0, 0, rows - 5, + (NEWT_FLAG_SCROLL | + NEWT_FLAG_RETURNEXIT)); + + newtComponentAddCallback(self->tree, hist_browser__selection, + &self->selection); progress = ui_progress__new("Adding entries to the browser...", nr_hists); if (progress == NULL) @@ -439,7 +449,12 @@ static int hist_browser__populate(struct hist_browser *self, struct rb_root *his idx = 0; for (nd = rb_first(hists); nd; nd = rb_next(nd)) { struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); - int len = hist_entry__append_browser(h, self->tree, session_total); + int len; + + if (h->filtered) + continue; + + len = hist_entry__append_browser(h, self->tree, session_total); if (len > max_len) max_len = len; if (symbol_conf.use_callchain) @@ -463,6 +478,9 @@ static int hist_browser__populate(struct hist_browser *self, struct rb_root *his newtCenteredWindow(max_len + (symbol_conf.use_callchain ? 5 : 0), rows - 5, "Report"); self->form = newt_form__new(); + if (self->form == NULL) + return -1; + newtFormAddHotKey(self->form, 'A'); newtFormAddHotKey(self->form, 'a'); newtFormAddHotKey(self->form, NEWT_KEY_RIGHT); @@ -472,29 +490,50 @@ static int hist_browser__populate(struct hist_browser *self, struct rb_root *his return 0; } +static u64 hists__filter_by_dso(struct rb_root *hists, struct dso *dso, + u64 *session_total) +{ + struct rb_node *nd; + u64 nr_hists = 0; + + *session_total = 0; + + for (nd = rb_first(hists); nd; nd = rb_next(nd)) { + struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); + + if (dso != NULL && (h->ms.map == NULL || h->ms.map->dso != dso)) { + h->filtered = true; + continue; + } + h->filtered = false; + ++nr_hists; + *session_total += h->count; + } + + return nr_hists; +} + int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, u64 session_total, const char *helpline, const char *input_name) { struct newtExitStruct es; - char str[1024]; + bool dso_filtered = false; int err = -1; struct hist_browser *browser = hist_browser__new(); if (browser == NULL) return -1; - snprintf(str, sizeof(str), "Samples: %Ld", session_total); - newtDrawRootText(0, 0, str); newtPushHelpLine(helpline); if (hist_browser__populate(browser, hists, nr_hists, session_total) < 0) goto out; while (1) { - char annotate[512]; - const char *options[2]; - int nr_options = 0, choice = 0; + char *options[16]; + int nr_options = 0, choice = 0, i, + annotate = -2, zoom_dso = -2; newtFormRun(browser->form, &es); if (es.reason == NEWT_EXIT_HOTKEY) { @@ -510,18 +549,29 @@ int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, } } - if (browser->selection->sym != NULL) { - snprintf(annotate, sizeof(annotate), - "Annotate %s", browser->selection->sym->name); - options[nr_options++] = annotate; - } + if (browser->selection->sym != NULL && + asprintf(&options[nr_options], "Annotate %s", + browser->selection->sym->name) > 0) + annotate = nr_options++; + + if (browser->selection->map != NULL && + asprintf(&options[nr_options], "Zoom %s %s DSO", + dso_filtered ? "out of" : "into", + (browser->selection->map->dso->kernel ? "the Kernel" : + browser->selection->map->dso->short_name)) > 0) + zoom_dso = nr_options++; + + options[nr_options++] = (char *)"Exit"; - options[nr_options++] = "Exit"; choice = popup_menu(nr_options, options); + + for (i = 0; i < nr_options - 1; ++i) + free(options[i]); + if (choice == nr_options - 1) break; do_annotate: - if (browser->selection->sym != NULL && choice >= 0) { + if (choice == annotate) { if (browser->selection->map->dso->origin == DSO__ORIG_KERNEL) { newtPopHelpLine(); newtPushHelpLine("No vmlinux file found, can't " @@ -531,6 +581,13 @@ do_annotate: } map_symbol__annotate_browser(browser->selection, input_name); + } if (choice == zoom_dso) { + hists__filter_by_dso(hists, + dso_filtered ? NULL : browser->selection->map->dso, + &session_total); + dso_filtered = !dso_filtered; + if (hist_browser__populate(browser, hists, nr_hists, session_total) < 0) + goto out; } } err = 0; diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index 5bf2b74..dce79d3 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h @@ -48,7 +48,8 @@ struct hist_entry { struct map_symbol ms; u64 ip; char level; - struct symbol *parent; + bool filtered; + struct symbol *parent; union { unsigned long position; struct hist_entry *pair; -- cgit v0.10.2 From a5e29aca02fcecd086ac160ea29244cae6b4305e Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 3 Apr 2010 22:44:37 -0300 Subject: perf TUI: Add a "Zoom into COMM(PID) thread" and reverse operations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now one can press the right arrow key and in addition to being able to filter by DSO, filter out by thread too, or a combination of both filters. With this one can start collecting events for the whole system, then focus on a subset of the collected data quickly. Cc: Avi Kivity Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index bbf725d..6d6e022 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -490,6 +490,11 @@ static int hist_browser__populate(struct hist_browser *self, struct rb_root *his return 0; } +enum hist_filter { + HIST_FILTER__DSO, + HIST_FILTER__THREAD, +}; + static u64 hists__filter_by_dso(struct rb_root *hists, struct dso *dso, u64 *session_total) { @@ -502,10 +507,10 @@ static u64 hists__filter_by_dso(struct rb_root *hists, struct dso *dso, struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); if (dso != NULL && (h->ms.map == NULL || h->ms.map->dso != dso)) { - h->filtered = true; + h->filtered |= (1 << HIST_FILTER__DSO); continue; } - h->filtered = false; + h->filtered &= ~(1 << HIST_FILTER__DSO); ++nr_hists; *session_total += h->count; } @@ -513,12 +518,54 @@ static u64 hists__filter_by_dso(struct rb_root *hists, struct dso *dso, return nr_hists; } +static u64 hists__filter_by_thread(struct rb_root *hists, const struct thread *thread, + u64 *session_total) +{ + struct rb_node *nd; + u64 nr_hists = 0; + + *session_total = 0; + + for (nd = rb_first(hists); nd; nd = rb_next(nd)) { + struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); + + if (thread != NULL && h->thread != thread) { + h->filtered |= (1 << HIST_FILTER__THREAD); + continue; + } + h->filtered &= ~(1 << HIST_FILTER__THREAD); + ++nr_hists; + *session_total += h->count; + } + + return nr_hists; +} + +static struct thread *hist_browser__selected_thread(struct hist_browser *self) +{ + int *indexes; + + if (!symbol_conf.use_callchain) + goto out; + + indexes = newtCheckboxTreeFindItem(self->tree, (void *)self->selection); + if (indexes) { + bool is_hist_entry = indexes[1] == NEWT_ARG_LAST; + free(indexes); + if (is_hist_entry) + goto out; + } + return NULL; +out: + return *(struct thread **)(self->selection + 1); +} + int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, u64 session_total, const char *helpline, const char *input_name) { struct newtExitStruct es; - bool dso_filtered = false; + bool dso_filtered = false, thread_filtered = false; int err = -1; struct hist_browser *browser = hist_browser__new(); @@ -531,9 +578,10 @@ int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, goto out; while (1) { + const struct thread *thread; char *options[16]; int nr_options = 0, choice = 0, i, - annotate = -2, zoom_dso = -2; + annotate = -2, zoom_dso = -2, zoom_thread = -2; newtFormRun(browser->form, &es); if (es.reason == NEWT_EXIT_HOTKEY) { @@ -561,6 +609,13 @@ int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, browser->selection->map->dso->short_name)) > 0) zoom_dso = nr_options++; + thread = hist_browser__selected_thread(browser); + if (thread != NULL && + asprintf(&options[nr_options], "Zoom %s %s(%d) thread", + (thread_filtered ? "out of" : "into"), + (thread->comm_set ? thread->comm : ""), thread->pid) > 0) + zoom_thread = nr_options++; + options[nr_options++] = (char *)"Exit"; choice = popup_menu(nr_options, options); @@ -570,6 +625,9 @@ int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, if (choice == nr_options - 1) break; + + if (choice == -1) + continue; do_annotate: if (choice == annotate) { if (browser->selection->map->dso->origin == DSO__ORIG_KERNEL) { @@ -581,13 +639,21 @@ do_annotate: } map_symbol__annotate_browser(browser->selection, input_name); - } if (choice == zoom_dso) { - hists__filter_by_dso(hists, - dso_filtered ? NULL : browser->selection->map->dso, - &session_total); + } else if (choice == zoom_dso) { + nr_hists = hists__filter_by_dso(hists, + (dso_filtered ? NULL : + browser->selection->map->dso), + &session_total); dso_filtered = !dso_filtered; if (hist_browser__populate(browser, hists, nr_hists, session_total) < 0) goto out; + } else if (choice == zoom_thread) { + nr_hists = hists__filter_by_thread(hists, + (thread_filtered ? NULL : thread), + &session_total); + thread_filtered = !thread_filtered; + if (hist_browser__populate(browser, hists, nr_hists, session_total) < 0) + goto out; } } err = 0; diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index dce79d3..6d7b4be 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h @@ -44,11 +44,16 @@ extern enum sort_type sort__first_dimension; struct hist_entry { struct rb_node rb_node; u64 count; - struct thread *thread; + /* + * XXX WARNING! + * thread _has_ to come after ms, see + * hist_browser__selected_thread in util/newt.c + */ struct map_symbol ms; + struct thread *thread; u64 ip; char level; - bool filtered; + u8 filtered; struct symbol *parent; union { unsigned long position; -- cgit v0.10.2 From 6f4dee06fbf0133917f3d76fa3fb50e18b10c1f5 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Thu, 18 Mar 2010 23:47:01 +0100 Subject: perf: Drop the frame reliablity check It is useless now that we have a pure stack frame walker, as given addr are always reliable. Signed-off-by: Frederic Weisbecker Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 65e9c5e..353a174 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -1602,8 +1602,7 @@ static void backtrace_address(void *data, unsigned long addr, int reliable) { struct perf_callchain_entry *entry = data; - if (reliable) - callchain_store(entry, addr); + callchain_store(entry, addr); } static const struct stacktrace_ops backtrace_ops = { -- cgit v0.10.2 From 6cc8a7c1d8560c042f486b23318a6291569ab96b Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Fri, 19 Mar 2010 01:23:53 +0100 Subject: perf: Fetch hot regs from the template caller Trace events can be defined from a template using DECLARE_EVENT_CLASS/DEFINE_EVENT or directly with TRACE_EVENT. In both cases we have a template tracepoint handler, used to record the trace, to which we pass our ftrace event instance. In the function level, if the class is named "foo" and the event is named "blah", we have the following chain of calls: perf_trace_blah() -> perf_trace_templ_foo() In the case we have several events sharing the class "blah", we'll have multiple users of perf_trace_templ_foo(), and it won't be inlined by the compiler. This is usually what happens with the DECLARE_EVENT_CLASS/DEFINE_EVENT based definition. But if perf_trace_blah() is the only caller of perf_trace_templ_foo() there are fair chances that it will be inlined. The problem is that we fetch the regs from perf_trace_templ_foo() after we rewinded the frame pointer to the second caller, we want to reach the caller of perf_trace_blah() to get the right source of the event. And we do this by always assuming that perf_trace_templ_foo() is not inlined. But as shown above this is not always true. And if it is inlined we miss the first caller, losing the most important level of precision. We get: 61.31% ls [kernel.kallsyms] [k] do_softirq | --- do_softirq irq_exit do_IRQ common_interrupt | |--25.00%-- tty_buffer_request_room Instead of: 61.31% ls [kernel.kallsyms] [k] __do_softirq | --- __do_softirq do_softirq irq_exit do_IRQ common_interrupt | |--25.00%-- tty_buffer_request_room To fix this, we fetch the regs from perf_trace_blah() rather than perf_trace_templ_foo() so that we don't have to deal with inlining surprises. That also bring us the advantage of having the true source of the event even if we don't have frame pointers. Signed-off-by: Frederic Weisbecker Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Ingo Molnar diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h index ea6f9d4..882c648 100644 --- a/include/trace/ftrace.h +++ b/include/trace/ftrace.h @@ -758,13 +758,12 @@ __attribute__((section("_ftrace_events"))) event_##call = { \ #define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \ static notrace void \ perf_trace_templ_##call(struct ftrace_event_call *event_call, \ - proto) \ + struct pt_regs *__regs, proto) \ { \ struct ftrace_data_offsets_##call __maybe_unused __data_offsets;\ struct ftrace_raw_##call *entry; \ u64 __addr = 0, __count = 1; \ unsigned long irq_flags; \ - struct pt_regs *__regs; \ int __entry_size; \ int __data_size; \ int rctx; \ @@ -785,20 +784,22 @@ perf_trace_templ_##call(struct ftrace_event_call *event_call, \ \ { assign; } \ \ - __regs = &__get_cpu_var(perf_trace_regs); \ - perf_fetch_caller_regs(__regs, 2); \ - \ perf_trace_buf_submit(entry, __entry_size, rctx, __addr, \ __count, irq_flags, __regs); \ } #undef DEFINE_EVENT -#define DEFINE_EVENT(template, call, proto, args) \ -static notrace void perf_trace_##call(proto) \ -{ \ - struct ftrace_event_call *event_call = &event_##call; \ - \ - perf_trace_templ_##template(event_call, args); \ +#define DEFINE_EVENT(template, call, proto, args) \ +static notrace void perf_trace_##call(proto) \ +{ \ + struct ftrace_event_call *event_call = &event_##call; \ + struct pt_regs *__regs = &get_cpu_var(perf_trace_regs); \ + \ + perf_fetch_caller_regs(__regs, 1); \ + \ + perf_trace_templ_##template(event_call, __regs, args); \ + \ + put_cpu_var(perf_trace_regs); \ } #undef DEFINE_EVENT_PRINT -- cgit v0.10.2 From 3326c1ceee234e63160852720d48be8a8f7a6d08 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 23 Mar 2010 19:09:33 +0100 Subject: perf_event: Make perf fd non seekable Perf_event does not need seeking, so prevent it in order to get rid of default_llseek, which uses the BKL. Signed-off-by: Arnd Bergmann Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Ingo Molnar [drop the nonseekable_open, not needed for anon inodes] Signed-off-by: Frederic Weisbecker diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 63fbce1..4aa50ff 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -2645,6 +2645,7 @@ static int perf_fasync(int fd, struct file *filp, int on) } static const struct file_operations perf_fops = { + .llseek = no_llseek, .release = perf_release, .read = perf_read, .poll = perf_poll, -- cgit v0.10.2 From 8141d0050d76e5695011b5ab577ec66fb51a998c Mon Sep 17 00:00:00 2001 From: Hitoshi Mitake Date: Sun, 4 Apr 2010 17:13:18 +0900 Subject: perf: Swap inclusion order of util.h and string.h in util/string.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently util/string.c includes headers in this order: string.h, util.h But this causes a build error because __USE_GNU definition is needed for strndup() definition: % make -j touch .perf.dev.null CC util/string.o cc1: warnings being treated as errors util/string.c: In function ‘argv_split’: util/string.c:171: error: implicit declaration of function ‘strndup’ util/string.c:171: error: incompatible implicit declaration of built-in function ‘strndup’ So this patch swaps the headers inclusion order. util.h defines _GNU_SOURCE, and /usr/include/features.h defines __USE_GNU as 1 if _GNU_SOURCE is defined. Signed-off-by: Hitoshi Mitake Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo LKML-Reference: <1270368798-27232-1-git-send-email-mitake@dcl.info.waseda.ac.jp> Signed-off-by: Frederic Weisbecker diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c index d438924..0409fc7 100644 --- a/tools/perf/util/string.c +++ b/tools/perf/util/string.c @@ -1,5 +1,5 @@ -#include "string.h" #include "util.h" +#include "string.h" #define K 1024LL /* -- cgit v0.10.2 From aa27497c2fb4c7f57706099bd489e683e5cc3e3b Mon Sep 17 00:00:00 2001 From: Lai Jiangshan Date: Mon, 5 Apr 2010 17:11:05 +0800 Subject: tracing: Fix uninitialized variable of tracing/trace output Because a local variable is not initialized, I got these when I did 'cat tracing/trace'. (not trace_pipe): CPU:0 [LOST 18446744071579453134 EVENTS] ps-3099 [000] 560.770221: lock_acquire: ffff880030865010 &(&dentry->d_lock)->rlock CPU:0 [LOST 18446744071579453134 EVENTS] ps-3099 [000] 560.770221: lock_release: ffff880030865010 &(&dentry->d_lock)->rlock CPU:0 [LOST 18446612133255294080 EVENTS] ps-3099 [000] 560.770221: lock_acquire: ffff880030865010 &(&dentry->d_lock)->rlock CPU:0 [LOST 18446744071579453134 EVENTS] ps-3099 [000] 560.770222: lock_release: ffff880030865010 &(&dentry->d_lock)->rlock CPU:0 [LOST 18446744071579453134 EVENTS] ps-3099 [000] 560.770222: lock_release: ffffffff816cfb98 dcache_lock See peek_next_entry(), it does not set *lost_events when we 'cat tracing/trace' Signed-off-by: Lai Jiangshan LKML-Reference: <4BB9A929.2000303@cn.fujitsu.com> Signed-off-by: Steven Rostedt diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 0498beb..b9be232 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -1571,7 +1571,7 @@ __find_next_entry(struct trace_iterator *iter, int *ent_cpu, { struct ring_buffer *buffer = iter->tr->buffer; struct trace_entry *ent, *next = NULL; - unsigned long lost_events, next_lost = 0; + unsigned long lost_events = 0, next_lost = 0; int cpu_file = iter->cpu_file; u64 next_ts = 0, ts; int next_cpu = -1; -- cgit v0.10.2 From bd6d29c25bb1a24a4c160ec5de43e0004e01f72b Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Tue, 6 Apr 2010 00:10:17 +0200 Subject: lockstat: Make lockstat counting per cpu Locking statistics are implemented using global atomic variables. This is usually fine unless some path write them very often. This is the case for the function and function graph tracers that disable irqs for each entry saved (except if the function tracer is in preempt disabled only mode). And calls to local_irq_save/restore() increment hardirqs_on_events and hardirqs_off_events stats (or similar stats for redundant versions). Incrementing these global vars for each function ends up in too much cache bouncing if lockstats are enabled. To solve this, implement the debug_atomic_*() operations using per cpu vars. -v2: Use per_cpu() instead of get_cpu_var() to fetch the desired cpu vars on debug_atomic_read() -v3: Store the stats in a structure. No need for local_t as we are NMI/irq safe. -v4: Fix tons of build errors. I thought I had tested it but I probably forgot to select the relevant config. Suggested-by: Steven Rostedt Signed-off-by: Frederic Weisbecker Cc: Peter Zijlstra Cc: Steven Rostedt LKML-Reference: <1270505417-8144-1-git-send-regression-fweisbec@gmail.com> Signed-off-by: Ingo Molnar Cc: Peter Zijlstra Cc: Steven Rostedt diff --git a/kernel/lockdep.c b/kernel/lockdep.c index 0c30d04..069af02 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c @@ -430,20 +430,7 @@ static struct stack_trace lockdep_init_trace = { /* * Various lockdep statistics: */ -atomic_t chain_lookup_hits; -atomic_t chain_lookup_misses; -atomic_t hardirqs_on_events; -atomic_t hardirqs_off_events; -atomic_t redundant_hardirqs_on; -atomic_t redundant_hardirqs_off; -atomic_t softirqs_on_events; -atomic_t softirqs_off_events; -atomic_t redundant_softirqs_on; -atomic_t redundant_softirqs_off; -atomic_t nr_unused_locks; -atomic_t nr_cyclic_checks; -atomic_t nr_find_usage_forwards_checks; -atomic_t nr_find_usage_backwards_checks; +DEFINE_PER_CPU(struct lockdep_stats, lockdep_stats); #endif /* @@ -758,7 +745,7 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force) return NULL; } class = lock_classes + nr_lock_classes++; - debug_atomic_inc(&nr_unused_locks); + debug_atomic_inc(nr_unused_locks); class->key = key; class->name = lock->name; class->subclass = subclass; @@ -1215,7 +1202,7 @@ check_noncircular(struct lock_list *root, struct lock_class *target, { int result; - debug_atomic_inc(&nr_cyclic_checks); + debug_atomic_inc(nr_cyclic_checks); result = __bfs_forwards(root, target, class_equal, target_entry); @@ -1252,7 +1239,7 @@ find_usage_forwards(struct lock_list *root, enum lock_usage_bit bit, { int result; - debug_atomic_inc(&nr_find_usage_forwards_checks); + debug_atomic_inc(nr_find_usage_forwards_checks); result = __bfs_forwards(root, (void *)bit, usage_match, target_entry); @@ -1275,7 +1262,7 @@ find_usage_backwards(struct lock_list *root, enum lock_usage_bit bit, { int result; - debug_atomic_inc(&nr_find_usage_backwards_checks); + debug_atomic_inc(nr_find_usage_backwards_checks); result = __bfs_backwards(root, (void *)bit, usage_match, target_entry); @@ -1835,7 +1822,7 @@ static inline int lookup_chain_cache(struct task_struct *curr, list_for_each_entry(chain, hash_head, entry) { if (chain->chain_key == chain_key) { cache_hit: - debug_atomic_inc(&chain_lookup_hits); + debug_atomic_inc(chain_lookup_hits); if (very_verbose(class)) printk("\nhash chain already cached, key: " "%016Lx tail class: [%p] %s\n", @@ -1900,7 +1887,7 @@ cache_hit: chain_hlocks[chain->base + j] = class - lock_classes; } list_add_tail_rcu(&chain->entry, hash_head); - debug_atomic_inc(&chain_lookup_misses); + debug_atomic_inc(chain_lookup_misses); inc_chains(); return 1; @@ -2321,7 +2308,7 @@ void trace_hardirqs_on_caller(unsigned long ip) return; if (unlikely(curr->hardirqs_enabled)) { - debug_atomic_inc(&redundant_hardirqs_on); + debug_atomic_inc(redundant_hardirqs_on); return; } /* we'll do an OFF -> ON transition: */ @@ -2348,7 +2335,7 @@ void trace_hardirqs_on_caller(unsigned long ip) curr->hardirq_enable_ip = ip; curr->hardirq_enable_event = ++curr->irq_events; - debug_atomic_inc(&hardirqs_on_events); + debug_atomic_inc(hardirqs_on_events); } EXPORT_SYMBOL(trace_hardirqs_on_caller); @@ -2380,9 +2367,9 @@ void trace_hardirqs_off_caller(unsigned long ip) curr->hardirqs_enabled = 0; curr->hardirq_disable_ip = ip; curr->hardirq_disable_event = ++curr->irq_events; - debug_atomic_inc(&hardirqs_off_events); + debug_atomic_inc(hardirqs_off_events); } else - debug_atomic_inc(&redundant_hardirqs_off); + debug_atomic_inc(redundant_hardirqs_off); } EXPORT_SYMBOL(trace_hardirqs_off_caller); @@ -2406,7 +2393,7 @@ void trace_softirqs_on(unsigned long ip) return; if (curr->softirqs_enabled) { - debug_atomic_inc(&redundant_softirqs_on); + debug_atomic_inc(redundant_softirqs_on); return; } @@ -2416,7 +2403,7 @@ void trace_softirqs_on(unsigned long ip) curr->softirqs_enabled = 1; curr->softirq_enable_ip = ip; curr->softirq_enable_event = ++curr->irq_events; - debug_atomic_inc(&softirqs_on_events); + debug_atomic_inc(softirqs_on_events); /* * We are going to turn softirqs on, so set the * usage bit for all held locks, if hardirqs are @@ -2446,10 +2433,10 @@ void trace_softirqs_off(unsigned long ip) curr->softirqs_enabled = 0; curr->softirq_disable_ip = ip; curr->softirq_disable_event = ++curr->irq_events; - debug_atomic_inc(&softirqs_off_events); + debug_atomic_inc(softirqs_off_events); DEBUG_LOCKS_WARN_ON(!softirq_count()); } else - debug_atomic_inc(&redundant_softirqs_off); + debug_atomic_inc(redundant_softirqs_off); } static void __lockdep_trace_alloc(gfp_t gfp_mask, unsigned long flags) @@ -2654,7 +2641,7 @@ static int mark_lock(struct task_struct *curr, struct held_lock *this, return 0; break; case LOCK_USED: - debug_atomic_dec(&nr_unused_locks); + debug_atomic_dec(nr_unused_locks); break; default: if (!debug_locks_off_graph_unlock()) @@ -2760,7 +2747,7 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass, if (!class) return 0; } - debug_atomic_inc((atomic_t *)&class->ops); + atomic_inc((atomic_t *)&class->ops); if (very_verbose(class)) { printk("\nacquire class [%p] %s", class->key, class->name); if (class->name_version > 1) diff --git a/kernel/lockdep_internals.h b/kernel/lockdep_internals.h index a2ee95a..8d7d4b6 100644 --- a/kernel/lockdep_internals.h +++ b/kernel/lockdep_internals.h @@ -110,29 +110,61 @@ lockdep_count_backward_deps(struct lock_class *class) #endif #ifdef CONFIG_DEBUG_LOCKDEP + +#include /* - * Various lockdep statistics: + * Various lockdep statistics. + * We want them per cpu as they are often accessed in fast path + * and we want to avoid too much cache bouncing. */ -extern atomic_t chain_lookup_hits; -extern atomic_t chain_lookup_misses; -extern atomic_t hardirqs_on_events; -extern atomic_t hardirqs_off_events; -extern atomic_t redundant_hardirqs_on; -extern atomic_t redundant_hardirqs_off; -extern atomic_t softirqs_on_events; -extern atomic_t softirqs_off_events; -extern atomic_t redundant_softirqs_on; -extern atomic_t redundant_softirqs_off; -extern atomic_t nr_unused_locks; -extern atomic_t nr_cyclic_checks; -extern atomic_t nr_cyclic_check_recursions; -extern atomic_t nr_find_usage_forwards_checks; -extern atomic_t nr_find_usage_forwards_recursions; -extern atomic_t nr_find_usage_backwards_checks; -extern atomic_t nr_find_usage_backwards_recursions; -# define debug_atomic_inc(ptr) atomic_inc(ptr) -# define debug_atomic_dec(ptr) atomic_dec(ptr) -# define debug_atomic_read(ptr) atomic_read(ptr) +struct lockdep_stats { + int chain_lookup_hits; + int chain_lookup_misses; + int hardirqs_on_events; + int hardirqs_off_events; + int redundant_hardirqs_on; + int redundant_hardirqs_off; + int softirqs_on_events; + int softirqs_off_events; + int redundant_softirqs_on; + int redundant_softirqs_off; + int nr_unused_locks; + int nr_cyclic_checks; + int nr_cyclic_check_recursions; + int nr_find_usage_forwards_checks; + int nr_find_usage_forwards_recursions; + int nr_find_usage_backwards_checks; + int nr_find_usage_backwards_recursions; +}; + +DECLARE_PER_CPU(struct lockdep_stats, lockdep_stats); + +#define debug_atomic_inc(ptr) { \ + struct lockdep_stats *__cpu_lockdep_stats; \ + \ + WARN_ON_ONCE(!irqs_disabled()); \ + __cpu_lockdep_stats = &__get_cpu_var(lockdep_stats); \ + __cpu_lockdep_stats->ptr++; \ +} + +#define debug_atomic_dec(ptr) { \ + struct lockdep_stats *__cpu_lockdep_stats; \ + \ + WARN_ON_ONCE(!irqs_disabled()); \ + __cpu_lockdep_stats = &__get_cpu_var(lockdep_stats); \ + __cpu_lockdep_stats->ptr--; \ +} + +#define debug_atomic_read(ptr) ({ \ + struct lockdep_stats *__cpu_lockdep_stats; \ + unsigned long long __total = 0; \ + int __cpu; \ + for_each_possible_cpu(__cpu) { \ + __cpu_lockdep_stats = &per_cpu(lockdep_stats, __cpu); \ + __total += __cpu_lockdep_stats->ptr; \ + } \ + __total; \ +}) #else # define debug_atomic_inc(ptr) do { } while (0) # define debug_atomic_dec(ptr) do { } while (0) diff --git a/kernel/lockdep_proc.c b/kernel/lockdep_proc.c index d4aba4f..59b76c8 100644 --- a/kernel/lockdep_proc.c +++ b/kernel/lockdep_proc.c @@ -184,34 +184,34 @@ static const struct file_operations proc_lockdep_chains_operations = { static void lockdep_stats_debug_show(struct seq_file *m) { #ifdef CONFIG_DEBUG_LOCKDEP - unsigned int hi1 = debug_atomic_read(&hardirqs_on_events), - hi2 = debug_atomic_read(&hardirqs_off_events), - hr1 = debug_atomic_read(&redundant_hardirqs_on), - hr2 = debug_atomic_read(&redundant_hardirqs_off), - si1 = debug_atomic_read(&softirqs_on_events), - si2 = debug_atomic_read(&softirqs_off_events), - sr1 = debug_atomic_read(&redundant_softirqs_on), - sr2 = debug_atomic_read(&redundant_softirqs_off); - - seq_printf(m, " chain lookup misses: %11u\n", - debug_atomic_read(&chain_lookup_misses)); - seq_printf(m, " chain lookup hits: %11u\n", - debug_atomic_read(&chain_lookup_hits)); - seq_printf(m, " cyclic checks: %11u\n", - debug_atomic_read(&nr_cyclic_checks)); - seq_printf(m, " find-mask forwards checks: %11u\n", - debug_atomic_read(&nr_find_usage_forwards_checks)); - seq_printf(m, " find-mask backwards checks: %11u\n", - debug_atomic_read(&nr_find_usage_backwards_checks)); - - seq_printf(m, " hardirq on events: %11u\n", hi1); - seq_printf(m, " hardirq off events: %11u\n", hi2); - seq_printf(m, " redundant hardirq ons: %11u\n", hr1); - seq_printf(m, " redundant hardirq offs: %11u\n", hr2); - seq_printf(m, " softirq on events: %11u\n", si1); - seq_printf(m, " softirq off events: %11u\n", si2); - seq_printf(m, " redundant softirq ons: %11u\n", sr1); - seq_printf(m, " redundant softirq offs: %11u\n", sr2); + unsigned long long hi1 = debug_atomic_read(hardirqs_on_events), + hi2 = debug_atomic_read(hardirqs_off_events), + hr1 = debug_atomic_read(redundant_hardirqs_on), + hr2 = debug_atomic_read(redundant_hardirqs_off), + si1 = debug_atomic_read(softirqs_on_events), + si2 = debug_atomic_read(softirqs_off_events), + sr1 = debug_atomic_read(redundant_softirqs_on), + sr2 = debug_atomic_read(redundant_softirqs_off); + + seq_printf(m, " chain lookup misses: %11llu\n", + debug_atomic_read(chain_lookup_misses)); + seq_printf(m, " chain lookup hits: %11llu\n", + debug_atomic_read(chain_lookup_hits)); + seq_printf(m, " cyclic checks: %11llu\n", + debug_atomic_read(nr_cyclic_checks)); + seq_printf(m, " find-mask forwards checks: %11llu\n", + debug_atomic_read(nr_find_usage_forwards_checks)); + seq_printf(m, " find-mask backwards checks: %11llu\n", + debug_atomic_read(nr_find_usage_backwards_checks)); + + seq_printf(m, " hardirq on events: %11llu\n", hi1); + seq_printf(m, " hardirq off events: %11llu\n", hi2); + seq_printf(m, " redundant hardirq ons: %11llu\n", hr1); + seq_printf(m, " redundant hardirq offs: %11llu\n", hr2); + seq_printf(m, " softirq on events: %11llu\n", si1); + seq_printf(m, " softirq off events: %11llu\n", si2); + seq_printf(m, " redundant softirq ons: %11llu\n", sr1); + seq_printf(m, " redundant softirq offs: %11llu\n", sr2); #endif } @@ -263,7 +263,7 @@ static int lockdep_stats_show(struct seq_file *m, void *v) #endif } #ifdef CONFIG_DEBUG_LOCKDEP - DEBUG_LOCKS_WARN_ON(debug_atomic_read(&nr_unused_locks) != nr_unused); + DEBUG_LOCKS_WARN_ON(debug_atomic_read(nr_unused_locks) != nr_unused); #endif seq_printf(m, " lock-classes: %11lu [max: %lu]\n", nr_lock_classes, MAX_LOCKDEP_KEYS); -- cgit v0.10.2 From 6549981bc54777c37eccf987e227aff47022ab7c Mon Sep 17 00:00:00 2001 From: Stephane Chatty Date: Tue, 6 Apr 2010 22:22:58 +0200 Subject: HID: fix N-trig touch panel with recent firmware Added an init message that avoids device freeze with recent firmware. Signed-off-by: Stephane Chatty Tested-by: Rafi Rubin Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c index 9b24fc5..513db0a 100644 --- a/drivers/hid/hid-ntrig.c +++ b/drivers/hid/hid-ntrig.c @@ -1,8 +1,8 @@ /* * HID driver for N-Trig touchscreens * - * Copyright (c) 2008 Rafi Rubin - * Copyright (c) 2009 Stephane Chatty + * Copyright (c) 2008-2010 Rafi Rubin + * Copyright (c) 2009-2010 Stephane Chatty * */ @@ -15,6 +15,8 @@ #include #include +#include +#include "usbhid/usbhid.h" #include #include @@ -286,6 +288,7 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id) struct ntrig_data *nd; struct hid_input *hidinput; struct input_dev *input; + struct hid_report *report; if (id->driver_data) hdev->quirks |= HID_QUIRK_MULTI_INPUT; @@ -349,6 +352,11 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id) } } + report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[0x0a]; + if (report) + usbhid_submit_report(hdev, report, USB_DIR_OUT); + + return 0; err_free: kfree(nd); -- cgit v0.10.2 From 1527bc8b928dd1399c3d3467dd47d9ede210978a Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 1 Feb 2010 15:03:07 +0100 Subject: bitops: Optimize hweight() by making use of compile-time evaluation Rename the extisting runtime hweight() implementations to __arch_hweight(), rename the compile-time versions to __const_hweight() and then have hweight() pick between them. Suggested-by: H. Peter Anvin Signed-off-by: Peter Zijlstra LKML-Reference: <20100318111929.GB11152@aftab> Acked-by: H. Peter Anvin LKML-Reference: <1265028224.24455.154.camel@laptop> Signed-off-by: H. Peter Anvin diff --git a/arch/alpha/include/asm/bitops.h b/arch/alpha/include/asm/bitops.h index 15f3ae2..296da1d 100644 --- a/arch/alpha/include/asm/bitops.h +++ b/arch/alpha/include/asm/bitops.h @@ -405,29 +405,31 @@ static inline int fls(int x) #if defined(CONFIG_ALPHA_EV6) && defined(CONFIG_ALPHA_EV67) /* Whee. EV67 can calculate it directly. */ -static inline unsigned long hweight64(unsigned long w) +static inline unsigned long __arch_hweight64(unsigned long w) { return __kernel_ctpop(w); } -static inline unsigned int hweight32(unsigned int w) +static inline unsigned int __arch_weight32(unsigned int w) { - return hweight64(w); + return __arch_hweight64(w); } -static inline unsigned int hweight16(unsigned int w) +static inline unsigned int __arch_hweight16(unsigned int w) { - return hweight64(w & 0xffff); + return __arch_hweight64(w & 0xffff); } -static inline unsigned int hweight8(unsigned int w) +static inline unsigned int __arch_hweight8(unsigned int w) { - return hweight64(w & 0xff); + return __arch_hweight64(w & 0xff); } #else -#include +#include #endif +#include + #endif /* __KERNEL__ */ #include diff --git a/arch/ia64/include/asm/bitops.h b/arch/ia64/include/asm/bitops.h index 6ebc229..9da3df6 100644 --- a/arch/ia64/include/asm/bitops.h +++ b/arch/ia64/include/asm/bitops.h @@ -437,17 +437,18 @@ __fls (unsigned long x) * hweightN: returns the hamming weight (i.e. the number * of bits set) of a N-bit word */ -static __inline__ unsigned long -hweight64 (unsigned long x) +static __inline__ unsigned long __arch_hweight64(unsigned long x) { unsigned long result; result = ia64_popcnt(x); return result; } -#define hweight32(x) (unsigned int) hweight64((x) & 0xfffffffful) -#define hweight16(x) (unsigned int) hweight64((x) & 0xfffful) -#define hweight8(x) (unsigned int) hweight64((x) & 0xfful) +#define __arch_hweight32(x) ((unsigned int) __arch_hweight64((x) & 0xfffffffful)) +#define __arch_hweight16(x) ((unsigned int) __arch_hweight64((x) & 0xfffful)) +#define __arch_hweight8(x) ((unsigned int) __arch_hweight64((x) & 0xfful)) + +#include #endif /* __KERNEL__ */ diff --git a/arch/sparc/include/asm/bitops_64.h b/arch/sparc/include/asm/bitops_64.h index e72ac9c..766121a 100644 --- a/arch/sparc/include/asm/bitops_64.h +++ b/arch/sparc/include/asm/bitops_64.h @@ -44,7 +44,7 @@ extern void change_bit(unsigned long nr, volatile unsigned long *addr); #ifdef ULTRA_HAS_POPULATION_COUNT -static inline unsigned int hweight64(unsigned long w) +static inline unsigned int __arch_hweight64(unsigned long w) { unsigned int res; @@ -52,7 +52,7 @@ static inline unsigned int hweight64(unsigned long w) return res; } -static inline unsigned int hweight32(unsigned int w) +static inline unsigned int __arch_hweight32(unsigned int w) { unsigned int res; @@ -60,7 +60,7 @@ static inline unsigned int hweight32(unsigned int w) return res; } -static inline unsigned int hweight16(unsigned int w) +static inline unsigned int __arch_hweight16(unsigned int w) { unsigned int res; @@ -68,7 +68,7 @@ static inline unsigned int hweight16(unsigned int w) return res; } -static inline unsigned int hweight8(unsigned int w) +static inline unsigned int __arch_hweight8(unsigned int w) { unsigned int res; @@ -78,9 +78,10 @@ static inline unsigned int hweight8(unsigned int w) #else -#include +#include #endif +#include #include #endif /* __KERNEL__ */ diff --git a/include/asm-generic/bitops/arch_hweight.h b/include/asm-generic/bitops/arch_hweight.h new file mode 100644 index 0000000..3a7be84 --- /dev/null +++ b/include/asm-generic/bitops/arch_hweight.h @@ -0,0 +1,11 @@ +#ifndef _ASM_GENERIC_BITOPS_ARCH_HWEIGHT_H_ +#define _ASM_GENERIC_BITOPS_ARCH_HWEIGHT_H_ + +#include + +extern unsigned int __arch_hweight32(unsigned int w); +extern unsigned int __arch_hweight16(unsigned int w); +extern unsigned int __arch_hweight8(unsigned int w); +extern unsigned long __arch_hweight64(__u64 w); + +#endif /* _ASM_GENERIC_BITOPS_HWEIGHT_H_ */ diff --git a/include/asm-generic/bitops/const_hweight.h b/include/asm-generic/bitops/const_hweight.h new file mode 100644 index 0000000..fa2a50b --- /dev/null +++ b/include/asm-generic/bitops/const_hweight.h @@ -0,0 +1,42 @@ +#ifndef _ASM_GENERIC_BITOPS_CONST_HWEIGHT_H_ +#define _ASM_GENERIC_BITOPS_CONST_HWEIGHT_H_ + +/* + * Compile time versions of __arch_hweightN() + */ +#define __const_hweight8(w) \ + ( (!!((w) & (1ULL << 0))) + \ + (!!((w) & (1ULL << 1))) + \ + (!!((w) & (1ULL << 2))) + \ + (!!((w) & (1ULL << 3))) + \ + (!!((w) & (1ULL << 4))) + \ + (!!((w) & (1ULL << 5))) + \ + (!!((w) & (1ULL << 6))) + \ + (!!((w) & (1ULL << 7))) ) + +#define __const_hweight16(w) (__const_hweight8(w) + __const_hweight8((w) >> 8 )) +#define __const_hweight32(w) (__const_hweight16(w) + __const_hweight16((w) >> 16)) +#define __const_hweight64(w) (__const_hweight32(w) + __const_hweight32((w) >> 32)) + +/* + * Generic interface. + */ +#define hweight8(w) (__builtin_constant_p(w) ? __const_hweight8(w) : __arch_hweight8(w)) +#define hweight16(w) (__builtin_constant_p(w) ? __const_hweight16(w) : __arch_hweight16(w)) +#define hweight32(w) (__builtin_constant_p(w) ? __const_hweight32(w) : __arch_hweight32(w)) +#define hweight64(w) (__builtin_constant_p(w) ? __const_hweight64(w) : __arch_hweight64(w)) + +/* + * Interface for known constant arguments + */ +#define HWEIGHT8(w) (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_hweight8(w)) +#define HWEIGHT16(w) (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_hweight16(w)) +#define HWEIGHT32(w) (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_hweight32(w)) +#define HWEIGHT64(w) (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_hweight64(w)) + +/* + * Type invariant interface to the compile time constant hweight functions. + */ +#define HWEIGHT(w) HWEIGHT64((u64)w) + +#endif /* _ASM_GENERIC_BITOPS_CONST_HWEIGHT_H_ */ diff --git a/include/asm-generic/bitops/hweight.h b/include/asm-generic/bitops/hweight.h index fbbc383..a94d651 100644 --- a/include/asm-generic/bitops/hweight.h +++ b/include/asm-generic/bitops/hweight.h @@ -1,11 +1,7 @@ #ifndef _ASM_GENERIC_BITOPS_HWEIGHT_H_ #define _ASM_GENERIC_BITOPS_HWEIGHT_H_ -#include - -extern unsigned int hweight32(unsigned int w); -extern unsigned int hweight16(unsigned int w); -extern unsigned int hweight8(unsigned int w); -extern unsigned long hweight64(__u64 w); +#include +#include #endif /* _ASM_GENERIC_BITOPS_HWEIGHT_H_ */ diff --git a/include/linux/bitops.h b/include/linux/bitops.h index b793898..c55d5bc 100644 --- a/include/linux/bitops.h +++ b/include/linux/bitops.h @@ -47,31 +47,6 @@ static inline unsigned long hweight_long(unsigned long w) return sizeof(w) == 4 ? hweight32(w) : hweight64(w); } -/* - * Clearly slow versions of the hweightN() functions, their benefit is - * of course compile time evaluation of constant arguments. - */ -#define HWEIGHT8(w) \ - ( BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + \ - (!!((w) & (1ULL << 0))) + \ - (!!((w) & (1ULL << 1))) + \ - (!!((w) & (1ULL << 2))) + \ - (!!((w) & (1ULL << 3))) + \ - (!!((w) & (1ULL << 4))) + \ - (!!((w) & (1ULL << 5))) + \ - (!!((w) & (1ULL << 6))) + \ - (!!((w) & (1ULL << 7))) ) - -#define HWEIGHT16(w) (HWEIGHT8(w) + HWEIGHT8((w) >> 8)) -#define HWEIGHT32(w) (HWEIGHT16(w) + HWEIGHT16((w) >> 16)) -#define HWEIGHT64(w) (HWEIGHT32(w) + HWEIGHT32((w) >> 32)) - -/* - * Type invariant version that simply casts things to the - * largest type. - */ -#define HWEIGHT(w) HWEIGHT64((u64)(w)) - /** * rol32 - rotate a 32-bit value left * @word: value to rotate diff --git a/lib/hweight.c b/lib/hweight.c index 63ee4eb..a6927e7 100644 --- a/lib/hweight.c +++ b/lib/hweight.c @@ -9,7 +9,7 @@ * The Hamming Weight of a number is the total number of bits set in it. */ -unsigned int hweight32(unsigned int w) +unsigned int __arch_hweight32(unsigned int w) { #ifdef ARCH_HAS_FAST_MULTIPLIER w -= (w >> 1) & 0x55555555; @@ -24,29 +24,30 @@ unsigned int hweight32(unsigned int w) return (res + (res >> 16)) & 0x000000FF; #endif } -EXPORT_SYMBOL(hweight32); +EXPORT_SYMBOL(__arch_hweight32); -unsigned int hweight16(unsigned int w) +unsigned int __arch_hweight16(unsigned int w) { unsigned int res = w - ((w >> 1) & 0x5555); res = (res & 0x3333) + ((res >> 2) & 0x3333); res = (res + (res >> 4)) & 0x0F0F; return (res + (res >> 8)) & 0x00FF; } -EXPORT_SYMBOL(hweight16); +EXPORT_SYMBOL(__arch_hweight16); -unsigned int hweight8(unsigned int w) +unsigned int __arch_hweight8(unsigned int w) { unsigned int res = w - ((w >> 1) & 0x55); res = (res & 0x33) + ((res >> 2) & 0x33); return (res + (res >> 4)) & 0x0F; } -EXPORT_SYMBOL(hweight8); +EXPORT_SYMBOL(__arch_hweight8); -unsigned long hweight64(__u64 w) +unsigned long __arch_hweight64(__u64 w) { #if BITS_PER_LONG == 32 - return hweight32((unsigned int)(w >> 32)) + hweight32((unsigned int)w); + return __arch_hweight32((unsigned int)(w >> 32)) + + __arch_hweight32((unsigned int)w); #elif BITS_PER_LONG == 64 #ifdef ARCH_HAS_FAST_MULTIPLIER w -= (w >> 1) & 0x5555555555555555ul; @@ -63,4 +64,4 @@ unsigned long hweight64(__u64 w) #endif #endif } -EXPORT_SYMBOL(hweight64); +EXPORT_SYMBOL(__arch_hweight64); -- cgit v0.10.2 From d61931d89be506372d01a90d1755f6d0a9fafe2d Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Fri, 5 Mar 2010 17:34:46 +0100 Subject: x86: Add optimized popcnt variants Add support for the hardware version of the Hamming weight function, popcnt, present in CPUs which advertize it under CPUID, Function 0x0000_0001_ECX[23]. On CPUs which don't support it, we fallback to the default lib/hweight.c sw versions. A synthetic benchmark comparing popcnt with __sw_hweight64 showed almost a 3x speedup on a F10h machine. Signed-off-by: Borislav Petkov LKML-Reference: <20100318112015.GC11152@aftab> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 0eacb1f..89d8c54 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -238,6 +238,11 @@ config X86_32_LAZY_GS def_bool y depends on X86_32 && !CC_STACKPROTECTOR +config ARCH_HWEIGHT_CFLAGS + string + default "-fcall-saved-ecx -fcall-saved-edx" if X86_32 + default "-fcall-saved-rdi -fcall-saved-rsi -fcall-saved-rdx -fcall-saved-rcx -fcall-saved-r8 -fcall-saved-r9 -fcall-saved-r10 -fcall-saved-r11" if X86_64 + config KTIME_SCALAR def_bool X86_32 source "init/Kconfig" diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h index b09ec55..67dae51 100644 --- a/arch/x86/include/asm/alternative.h +++ b/arch/x86/include/asm/alternative.h @@ -39,9 +39,6 @@ #define LOCK_PREFIX "" #endif -/* This must be included *after* the definition of LOCK_PREFIX */ -#include - struct alt_instr { u8 *instr; /* original instruction */ u8 *replacement; @@ -96,6 +93,12 @@ static inline int alternatives_text_reserved(void *start, void *end) ".previous" /* + * This must be included *after* the definition of ALTERNATIVE due to + * + */ +#include + +/* * Alternative instructions for different CPU types or capabilities. * * This allows to use optimized instructions even on generic binary diff --git a/arch/x86/include/asm/arch_hweight.h b/arch/x86/include/asm/arch_hweight.h new file mode 100644 index 0000000..d1fc3c2 --- /dev/null +++ b/arch/x86/include/asm/arch_hweight.h @@ -0,0 +1,59 @@ +#ifndef _ASM_X86_HWEIGHT_H +#define _ASM_X86_HWEIGHT_H + +#ifdef CONFIG_64BIT +/* popcnt %rdi, %rax */ +#define POPCNT ".byte 0xf3,0x48,0x0f,0xb8,0xc7" +#define REG_IN "D" +#define REG_OUT "a" +#else +/* popcnt %eax, %eax */ +#define POPCNT ".byte 0xf3,0x0f,0xb8,0xc0" +#define REG_IN "a" +#define REG_OUT "a" +#endif + +/* + * __sw_hweightXX are called from within the alternatives below + * and callee-clobbered registers need to be taken care of. See + * ARCH_HWEIGHT_CFLAGS in for the respective + * compiler switches. + */ +static inline unsigned int __arch_hweight32(unsigned int w) +{ + unsigned int res = 0; + + asm (ALTERNATIVE("call __sw_hweight32", POPCNT, X86_FEATURE_POPCNT) + : "="REG_OUT (res) + : REG_IN (w)); + + return res; +} + +static inline unsigned int __arch_hweight16(unsigned int w) +{ + return __arch_hweight32(w & 0xffff); +} + +static inline unsigned int __arch_hweight8(unsigned int w) +{ + return __arch_hweight32(w & 0xff); +} + +static inline unsigned long __arch_hweight64(__u64 w) +{ + unsigned long res = 0; + +#ifdef CONFIG_X86_32 + return __arch_hweight32((u32)w) + + __arch_hweight32((u32)(w >> 32)); +#else + asm (ALTERNATIVE("call __sw_hweight64", POPCNT, X86_FEATURE_POPCNT) + : "="REG_OUT (res) + : REG_IN (w)); +#endif /* CONFIG_X86_32 */ + + return res; +} + +#endif diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h index 02b47a6..545776e 100644 --- a/arch/x86/include/asm/bitops.h +++ b/arch/x86/include/asm/bitops.h @@ -444,7 +444,9 @@ static inline int fls(int x) #define ARCH_HAS_FAST_MULTIPLIER 1 -#include +#include + +#include #endif /* __KERNEL__ */ diff --git a/include/asm-generic/bitops/arch_hweight.h b/include/asm-generic/bitops/arch_hweight.h index 3a7be84..9a81c1e 100644 --- a/include/asm-generic/bitops/arch_hweight.h +++ b/include/asm-generic/bitops/arch_hweight.h @@ -3,9 +3,23 @@ #include -extern unsigned int __arch_hweight32(unsigned int w); -extern unsigned int __arch_hweight16(unsigned int w); -extern unsigned int __arch_hweight8(unsigned int w); -extern unsigned long __arch_hweight64(__u64 w); +inline unsigned int __arch_hweight32(unsigned int w) +{ + return __sw_hweight32(w); +} +inline unsigned int __arch_hweight16(unsigned int w) +{ + return __sw_hweight16(w); +} + +inline unsigned int __arch_hweight8(unsigned int w) +{ + return __sw_hweight8(w); +} + +inline unsigned long __arch_hweight64(__u64 w) +{ + return __sw_hweight64(w); +} #endif /* _ASM_GENERIC_BITOPS_HWEIGHT_H_ */ diff --git a/lib/Makefile b/lib/Makefile index 2e152ae..abe63a8 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -39,7 +39,10 @@ lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o lib-$(CONFIG_GENERIC_FIND_FIRST_BIT) += find_next_bit.o lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o obj-$(CONFIG_GENERIC_FIND_LAST_BIT) += find_last_bit.o + +CFLAGS_hweight.o = $(subst $(quote),,$(CONFIG_ARCH_HWEIGHT_CFLAGS)) obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o + obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o obj-$(CONFIG_BTREE) += btree.o obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o diff --git a/lib/hweight.c b/lib/hweight.c index a6927e7..3c79d50 100644 --- a/lib/hweight.c +++ b/lib/hweight.c @@ -9,7 +9,7 @@ * The Hamming Weight of a number is the total number of bits set in it. */ -unsigned int __arch_hweight32(unsigned int w) +unsigned int __sw_hweight32(unsigned int w) { #ifdef ARCH_HAS_FAST_MULTIPLIER w -= (w >> 1) & 0x55555555; @@ -24,30 +24,30 @@ unsigned int __arch_hweight32(unsigned int w) return (res + (res >> 16)) & 0x000000FF; #endif } -EXPORT_SYMBOL(__arch_hweight32); +EXPORT_SYMBOL(__sw_hweight32); -unsigned int __arch_hweight16(unsigned int w) +unsigned int __sw_hweight16(unsigned int w) { unsigned int res = w - ((w >> 1) & 0x5555); res = (res & 0x3333) + ((res >> 2) & 0x3333); res = (res + (res >> 4)) & 0x0F0F; return (res + (res >> 8)) & 0x00FF; } -EXPORT_SYMBOL(__arch_hweight16); +EXPORT_SYMBOL(__sw_hweight16); -unsigned int __arch_hweight8(unsigned int w) +unsigned int __sw_hweight8(unsigned int w) { unsigned int res = w - ((w >> 1) & 0x55); res = (res & 0x33) + ((res >> 2) & 0x33); return (res + (res >> 4)) & 0x0F; } -EXPORT_SYMBOL(__arch_hweight8); +EXPORT_SYMBOL(__sw_hweight8); -unsigned long __arch_hweight64(__u64 w) +unsigned long __sw_hweight64(__u64 w) { #if BITS_PER_LONG == 32 - return __arch_hweight32((unsigned int)(w >> 32)) + - __arch_hweight32((unsigned int)w); + return __sw_hweight32((unsigned int)(w >> 32)) + + __sw_hweight32((unsigned int)w); #elif BITS_PER_LONG == 64 #ifdef ARCH_HAS_FAST_MULTIPLIER w -= (w >> 1) & 0x5555555555555555ul; @@ -64,4 +64,4 @@ unsigned long __arch_hweight64(__u64 w) #endif #endif } -EXPORT_SYMBOL(__arch_hweight64); +EXPORT_SYMBOL(__sw_hweight64); diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index f9bdf26..cbcd654 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -245,3 +245,7 @@ quiet_cmd_lzo = LZO $@ cmd_lzo = (cat $(filter-out FORCE,$^) | \ lzop -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \ (rm -f $@ ; false) + +# misc stuff +# --------------------------------------------------------------------------- +quote:=" -- cgit v0.10.2 From 99dc5c0ca953fb154a3c75ebc6801e0a3c2fe3fe Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 7 Apr 2010 17:08:32 +0900 Subject: sh: Disable MMUCR_AT for SH-4 nommu. Presently address translation is default-enabled regardless of whether CONFIG_MMU is set or not in the SH-4 case, this fixes it up, and also makes the control init word a bit more readable in the process. Signed-off-by: Paul Mundt diff --git a/arch/sh/include/cpu-sh4/cpu/mmu_context.h b/arch/sh/include/cpu-sh4/cpu/mmu_context.h index 2941be6..e46ec70 100644 --- a/arch/sh/include/cpu-sh4/cpu/mmu_context.h +++ b/arch/sh/include/cpu-sh4/cpu/mmu_context.h @@ -32,7 +32,13 @@ #define MMU_UTLB_DATA_ARRAY2 0xF7800000 #define MMU_PAGE_ASSOC_BIT 0x80 -#define MMUCR_TI (1<<2) +#ifdef CONFIG_MMU +#define MMUCR_AT (1 << 0) +#else +#define MMUCR_AT (0) +#endif + +#define MMUCR_TI (1 << 2) #define MMUCR_URB 0x00FC0000 #define MMUCR_URB_SHIFT 18 @@ -65,7 +71,8 @@ #endif #define MMU_NTLB_ENTRIES 64 -#define MMU_CONTROL_INIT (0x05|MMUCR_SQMD|MMUCR_ME|MMUCR_SE|MMUCR_AEX) +#define MMU_CONTROL_INIT (MMUCR_AT | MMUCR_TI | MMUCR_SQMD | \ + MMUCR_ME | MMUCR_SE | MMUCR_AEX) #define TRA 0xff000020 #define EXPEVT 0xff000024 -- cgit v0.10.2 From c0858552c088616c18879c347d9e0daa98cf2b15 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Wed, 7 Apr 2010 12:10:29 +0200 Subject: HID: ntrig: explain firmware quirk Commit 6549981bc54777c ("HID: fix N-trig touch panel with recent firmware") adds a quirk that is needed for devices with more recent firmware so that they become operational. As it's not directly obvious from the code why is it needed, a comment is worthwile. Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c index 513db0a..a418f9e 100644 --- a/drivers/hid/hid-ntrig.c +++ b/drivers/hid/hid-ntrig.c @@ -352,7 +352,8 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id) } } - report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[0x0a]; + /* This is needed for devices with more recent firmware versions */ + report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[0x0a]; if (report) usbhid_submit_report(hdev, report, USB_DIR_OUT); -- cgit v0.10.2 From 1ce31b255cf8b06470dfbd469055b6fd8d2274bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Doursenaud?= Date: Thu, 8 Apr 2010 13:40:52 +0200 Subject: HID: add support for cymotion master solar keyboard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Support the solar version of the Cherry's cymotion keyboard line using existing cherry driver. Signed-off-by: Raphaël Doursenaud Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-cherry.c b/drivers/hid/hid-cherry.c index 7e597d7..24663a8 100644 --- a/drivers/hid/hid-cherry.c +++ b/drivers/hid/hid-cherry.c @@ -59,6 +59,7 @@ static int ch_input_mapping(struct hid_device *hdev, struct hid_input *hi, static const struct hid_device_id ch_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) }, { } }; MODULE_DEVICE_TABLE(hid, ch_devices); diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 2e2aa75..d25152b 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1296,6 +1296,7 @@ static const struct hid_device_id hid_blacklist[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 797e064..09d2764 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -131,6 +131,7 @@ #define USB_VENDOR_ID_CHERRY 0x046a #define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023 +#define USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR 0x0027 #define USB_VENDOR_ID_CHIC 0x05fe #define USB_DEVICE_ID_CHIC_GAMEPAD 0x0014 -- cgit v0.10.2 From 6e7ab4c649eb7ed403d970b8eda32ca3745e8024 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 5 Apr 2010 12:02:18 -0300 Subject: perf TUI: Show filters on the title and add help line about how to zoom out MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Suggested-by: Ingo Molnar Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index 6d6e022..c0e71aa 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -411,7 +411,7 @@ static void hist_browser__delete(struct hist_browser *self) } static int hist_browser__populate(struct hist_browser *self, struct rb_root *hists, - u64 nr_hists, u64 session_total) + u64 nr_hists, u64 session_total, const char *title) { int max_len = 0, idx, cols, rows; struct ui_progress *progress; @@ -476,7 +476,7 @@ static int hist_browser__populate(struct hist_browser *self, struct rb_root *his newtListboxSetWidth(self->tree, max_len); newtCenteredWindow(max_len + (symbol_conf.use_callchain ? 5 : 0), - rows - 5, "Report"); + rows - 5, title); self->form = newt_form__new(); if (self->form == NULL) return -1; @@ -495,7 +495,7 @@ enum hist_filter { HIST_FILTER__THREAD, }; -static u64 hists__filter_by_dso(struct rb_root *hists, struct dso *dso, +static u64 hists__filter_by_dso(struct rb_root *hists, const struct dso *dso, u64 *session_total) { struct rb_node *nd; @@ -560,25 +560,47 @@ out: return *(struct thread **)(self->selection + 1); } +static int hist_browser__title(char *bf, size_t size, const char *input_name, + const struct dso *dso, const struct thread *thread) +{ + int printed = 0; + + if (thread) + printed += snprintf(bf + printed, size - printed, + "Thread: %s(%d)", + (thread->comm_set ? thread->comm : ""), + thread->pid); + if (dso) + printed += snprintf(bf + printed, size - printed, + "%sDSO: %s", thread ? " " : "", + dso->short_name); + return printed ?: snprintf(bf, size, "Report: %s", input_name); +} + int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, u64 session_total, const char *helpline, const char *input_name) { + struct hist_browser *browser = hist_browser__new(); + const struct thread *thread_filter = NULL; + const struct dso *dso_filter = NULL; struct newtExitStruct es; - bool dso_filtered = false, thread_filtered = false; + char msg[160]; int err = -1; - struct hist_browser *browser = hist_browser__new(); if (browser == NULL) return -1; newtPushHelpLine(helpline); - if (hist_browser__populate(browser, hists, nr_hists, session_total) < 0) + hist_browser__title(msg, sizeof(msg), input_name, + dso_filter, thread_filter); + if (hist_browser__populate(browser, hists, nr_hists, session_total, msg) < 0) goto out; while (1) { const struct thread *thread; + const struct dso *dso; char *options[16]; int nr_options = 0, choice = 0, i, annotate = -2, zoom_dso = -2, zoom_thread = -2; @@ -602,20 +624,21 @@ int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, browser->selection->sym->name) > 0) annotate = nr_options++; - if (browser->selection->map != NULL && - asprintf(&options[nr_options], "Zoom %s %s DSO", - dso_filtered ? "out of" : "into", - (browser->selection->map->dso->kernel ? "the Kernel" : - browser->selection->map->dso->short_name)) > 0) - zoom_dso = nr_options++; - thread = hist_browser__selected_thread(browser); if (thread != NULL && asprintf(&options[nr_options], "Zoom %s %s(%d) thread", - (thread_filtered ? "out of" : "into"), - (thread->comm_set ? thread->comm : ""), thread->pid) > 0) + (thread_filter ? "out of" : "into"), + (thread->comm_set ? thread->comm : ""), + thread->pid) > 0) zoom_thread = nr_options++; + dso = browser->selection->map ? browser->selection->map->dso : NULL; + if (dso != NULL && + asprintf(&options[nr_options], "Zoom %s %s DSO", + (dso_filter ? "out of" : "into"), + (dso->kernel ? "the Kernel" : dso->short_name)) > 0) + zoom_dso = nr_options++; + options[nr_options++] = (char *)"Exit"; choice = popup_menu(nr_options, options); @@ -637,22 +660,39 @@ do_annotate: "kallsyms file"); continue; } - map_symbol__annotate_browser(browser->selection, - input_name); + map_symbol__annotate_browser(browser->selection, input_name); } else if (choice == zoom_dso) { - nr_hists = hists__filter_by_dso(hists, - (dso_filtered ? NULL : - browser->selection->map->dso), - &session_total); - dso_filtered = !dso_filtered; - if (hist_browser__populate(browser, hists, nr_hists, session_total) < 0) + if (dso_filter) { + newtPopHelpLine(); + dso_filter = NULL; + } else { + snprintf(msg, sizeof(msg), + "To zoom out press -> + \"Zoom out of %s DSO\"", + dso->kernel ? "the Kernel" : dso->short_name); + newtPushHelpLine(msg); + dso_filter = dso; + } + nr_hists = hists__filter_by_dso(hists, dso_filter, &session_total); + hist_browser__title(msg, sizeof(msg), input_name, + dso_filter, thread_filter); + if (hist_browser__populate(browser, hists, nr_hists, session_total, msg) < 0) goto out; } else if (choice == zoom_thread) { - nr_hists = hists__filter_by_thread(hists, - (thread_filtered ? NULL : thread), - &session_total); - thread_filtered = !thread_filtered; - if (hist_browser__populate(browser, hists, nr_hists, session_total) < 0) + if (thread_filter) { + newtPopHelpLine(); + thread_filter = NULL; + } else { + snprintf(msg, sizeof(msg), + "To zoom out press -> + \"Zoom out of %s(%d) thread\"", + (thread->comm_set ? thread->comm : ""), + thread->pid); + newtPushHelpLine(msg); + thread_filter = thread; + } + nr_hists = hists__filter_by_thread(hists, thread_filter, &session_total); + hist_browser__title(msg, sizeof(msg), input_name, + dso_filter, thread_filter); + if (hist_browser__populate(browser, hists, nr_hists, session_total, msg) < 0) goto out; } } -- cgit v0.10.2 From c0ed55d2e4f600335193612725c0d7c8211a7a4a Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 5 Apr 2010 12:04:23 -0300 Subject: perf TUI: Move "Yes" button to before "No" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Esc + Enter should be enough warning to avoid accidentaly exiting from the browser. Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index c0e71aa..7a123a9 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -132,7 +132,7 @@ static bool dialog_yesno(const char *msg) { /* newtWinChoice should really be accepting const char pointers... */ char yes[] = "Yes", no[] = "No"; - return newtWinChoice(NULL, no, yes, (char *)msg) == 2; + return newtWinChoice(NULL, yes, no, (char *)msg) == 1; } /* -- cgit v0.10.2 From eed05fe70f96b04ebeb218b07ae8898e605f9b23 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 5 Apr 2010 12:53:45 -0300 Subject: perf tools: Reorganize some structs to save space MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using 'pahole --packable' I found some structs that could be reorganized to eliminate alignment holes, in some cases getting them to be cacheline multiples. [acme@doppio linux-2.6-tip]$ codiff perf.old ~/bin/perf builtin-annotate.c: struct perf_session | -8 struct perf_header | -8 2 structs changed builtin-diff.c: struct sample_data | -8 1 struct changed diff__process_sample_event | -8 1 function changed, 8 bytes removed, diff: -8 builtin-sched.c: struct sched_atom | -8 1 struct changed builtin-timechart.c: struct per_pid | -8 1 struct changed cmd_timechart | -16 1 function changed, 16 bytes removed, diff: -16 builtin-probe.c: struct perf_probe_point | -8 struct perf_probe_event | -8 2 structs changed opt_add_probe_event | -3 1 function changed, 3 bytes removed, diff: -3 util/probe-finder.c: struct probe_finder | -8 1 struct changed find_kprobe_trace_events | -16 1 function changed, 16 bytes removed, diff: -16 /home/acme/bin/perf: 4 functions changed, 43 bytes removed, diff: -43 [acme@doppio linux-2.6-tip]$ Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 4f5a03e..5e59c0c 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -68,10 +68,10 @@ enum sched_event_type { struct sched_atom { enum sched_event_type type; + int specific_wait; u64 timestamp; u64 duration; unsigned long nr; - int specific_wait; sem_t *wait_sem; struct task_desc *wakee; }; diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index 266e7aa..369c1b4 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c @@ -77,8 +77,6 @@ struct per_pid { struct per_pidcomm *all; struct per_pidcomm *current; - - int painted; }; diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index a33b949..7f7cf85 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -68,11 +68,11 @@ struct sample_data { u64 addr; u64 id; u64 stream_id; - u32 cpu; u64 period; - struct ip_callchain *callchain; + u32 cpu; u32 raw_size; void *raw_data; + struct ip_callchain *callchain; }; #define BUILD_ID_SIZE 20 diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index 82a6af7..c059f08 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h @@ -47,13 +47,13 @@ int perf_file_header__read(struct perf_file_header *self, struct perf_header { int frozen; int attrs, size; + bool needs_swap; struct perf_header_attr **attr; s64 attr_offset; u64 data_offset; u64 data_size; u64 event_offset; u64 event_size; - bool needs_swap; DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS); }; diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h index cd308b0..9d99fc2 100644 --- a/tools/perf/util/probe-event.h +++ b/tools/perf/util/probe-event.h @@ -40,9 +40,9 @@ struct perf_probe_point { char *file; /* File path */ char *function; /* Function name */ int line; /* Line number */ + bool retprobe; /* Return probe flag */ char *lazy_line; /* Lazy matching pattern */ unsigned long offset; /* Offset from function entry */ - bool retprobe; /* Return probe flag */ }; /* Perf probe probing argument field chain */ diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h index 3564f22..2a27132 100644 --- a/tools/perf/util/probe-finder.h +++ b/tools/perf/util/probe-finder.h @@ -31,13 +31,13 @@ extern int find_line_range(int fd, struct line_range *lr); struct probe_finder { struct perf_probe_event *pev; /* Target probe event */ - int ntevs; /* number of trace events */ struct kprobe_trace_event *tevs; /* Result trace events */ + int ntevs; /* number of trace events */ /* For function searching */ + int lno; /* Line number */ Dwarf_Addr addr; /* Address */ const char *fname; /* Real file name */ - int lno; /* Line number */ Dwarf_Die cu_die; /* Current CU */ struct list_head lcache; /* Line cache for lazy match */ -- cgit v0.10.2 From f0e9c4fcefa42b5d28b915768dab81a7fdbbc00c Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 31 Mar 2010 11:30:56 -0700 Subject: perf bench: fix spello Fix spello in user message. Cc: Peter Zijlstra , Cc: Paul Mackerra s LKML-Reference: <20100331113056.2c7df509.randy.dunlap@oracle.com> Signed-off-by: Randy Dunlap diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c index 4f77c7c..d9ab3ce 100644 --- a/tools/perf/bench/sched-pipe.c +++ b/tools/perf/bench/sched-pipe.c @@ -93,7 +93,7 @@ int bench_sched_pipe(int argc, const char **argv, switch (bench_format) { case BENCH_FORMAT_DEFAULT: - printf("# Extecuted %d pipe operations between two tasks\n\n", + printf("# Executed %d pipe operations between two tasks\n\n", loops); result_usec = diff.tv_sec * 1000000; -- cgit v0.10.2 From 854c5548dfad017920a36201d40449fdbad90bfb Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 31 Mar 2010 11:31:00 -0700 Subject: perf: cleanup some Documentation Correct typos in perf bench & perf sched help text. Cc: Peter Zijlstra , Cc: Paul Mackerras LKML-Reference: <20100331113100.cc898487.randy.dunlap@oracle.com> Signed-off-by: Randy Dunlap diff --git a/tools/perf/Documentation/perf-bench.txt b/tools/perf/Documentation/perf-bench.txt index ae525ac..0181ddd 100644 --- a/tools/perf/Documentation/perf-bench.txt +++ b/tools/perf/Documentation/perf-bench.txt @@ -19,12 +19,12 @@ COMMON OPTIONS -f:: --format=:: Specify format style. -Current available format styles are, +Current available format styles are: 'default':: Default style. This is mainly for human reading. --------------------- -% perf bench sched pipe # with no style specify +% perf bench sched pipe # with no style specified (executing 1000000 pipe operations between two tasks) Total time:5.855 sec 5.855061 usecs/op @@ -79,7 +79,7 @@ options (20 sender and receiver processes per group) Total time:0.308 sec -% perf bench sched messaging -t -g 20 # be multi-thread,with 20 groups +% perf bench sched messaging -t -g 20 # be multi-thread, with 20 groups (20 sender and receiver threads per group) (20 groups == 800 threads run) diff --git a/tools/perf/Documentation/perf-sched.txt b/tools/perf/Documentation/perf-sched.txt index 1ce7919..8417644 100644 --- a/tools/perf/Documentation/perf-sched.txt +++ b/tools/perf/Documentation/perf-sched.txt @@ -12,7 +12,7 @@ SYNOPSIS DESCRIPTION ----------- -There's four variants of perf sched: +There are four variants of perf sched: 'perf sched record ' to record the scheduling events of an arbitrary workload. @@ -27,7 +27,7 @@ There's four variants of perf sched: via perf sched record. (this is done by starting up mockup threads that mimic the workload based on the events in the trace. These threads can then replay the timings (CPU runtime and sleep patterns) - of the workload as it occured when it was recorded - and can repeat + of the workload as it occurred when it was recorded - and can repeat it a number of times, measuring its performance.) OPTIONS -- cgit v0.10.2 From e9e94e3bd862d31777335722e747e97d9821bc1d Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 5 Apr 2010 18:01:10 -0300 Subject: perf trace: Ignore "overwrite" field if present in /events/header_page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit That is not used in perf where we have the LOST events. Without this patch we get: [root@doppio ~]# perf lock report | head -3 Warning: Error: expected 'data' but read 'overwrite' So, to make the same perf command work with kernels with and without this field, introduce variants for the parsing routines to not warn the user in such case. Discussed-with: Steven Rostedt Cc: Frédéric Weisbecker Cc: Hitoshi Mitake Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index 9b3c20f..3b81250 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c @@ -37,6 +37,8 @@ int header_page_ts_offset; int header_page_ts_size; int header_page_size_offset; int header_page_size_size; +int header_page_overwrite_offset; +int header_page_overwrite_size; int header_page_data_offset; int header_page_data_size; @@ -628,23 +630,32 @@ static int test_type(enum event_type type, enum event_type expect) return 0; } -static int test_type_token(enum event_type type, char *token, - enum event_type expect, const char *expect_tok) +static int __test_type_token(enum event_type type, char *token, + enum event_type expect, const char *expect_tok, + bool warn) { if (type != expect) { - warning("Error: expected type %d but read %d", - expect, type); + if (warn) + warning("Error: expected type %d but read %d", + expect, type); return -1; } if (strcmp(token, expect_tok) != 0) { - warning("Error: expected '%s' but read '%s'", - expect_tok, token); + if (warn) + warning("Error: expected '%s' but read '%s'", + expect_tok, token); return -1; } return 0; } +static int test_type_token(enum event_type type, char *token, + enum event_type expect, const char *expect_tok) +{ + return __test_type_token(type, token, expect, expect_tok, true); +} + static int __read_expect_type(enum event_type expect, char **tok, int newline_ok) { enum event_type type; @@ -661,7 +672,8 @@ static int read_expect_type(enum event_type expect, char **tok) return __read_expect_type(expect, tok, 1); } -static int __read_expected(enum event_type expect, const char *str, int newline_ok) +static int __read_expected(enum event_type expect, const char *str, + int newline_ok, bool warn) { enum event_type type; char *token; @@ -672,21 +684,26 @@ static int __read_expected(enum event_type expect, const char *str, int newline_ else type = read_token_item(&token); - ret = test_type_token(type, token, expect, str); + ret = __test_type_token(type, token, expect, str, warn); free_token(token); return ret; } +static int read_expected_warn(enum event_type expect, const char *str, bool warn) +{ + return __read_expected(expect, str, 1, warn); +} + static int read_expected(enum event_type expect, const char *str) { - return __read_expected(expect, str, 1); + return __read_expected(expect, str, 1, true); } static int read_expected_item(enum event_type expect, const char *str) { - return __read_expected(expect, str, 0); + return __read_expected(expect, str, 0, true); } static char *event_read_name(void) @@ -3088,7 +3105,7 @@ static void print_args(struct print_arg *args) } static void parse_header_field(const char *field, - int *offset, int *size) + int *offset, int *size, bool warn) { char *token; int type; @@ -3103,7 +3120,7 @@ static void parse_header_field(const char *field, goto fail; free_token(token); - if (read_expected(EVENT_ITEM, field) < 0) + if (read_expected_warn(EVENT_ITEM, field, warn) < 0) return; if (read_expected(EVENT_OP, ";") < 0) return; @@ -3160,11 +3177,13 @@ int parse_header_page(char *buf, unsigned long size) init_input_buf(buf, size); parse_header_field("timestamp", &header_page_ts_offset, - &header_page_ts_size); + &header_page_ts_size, true); parse_header_field("commit", &header_page_size_offset, - &header_page_size_size); + &header_page_size_size, true); + parse_header_field("overwrite", &header_page_overwrite_offset, + &header_page_overwrite_size, false); parse_header_field("data", &header_page_data_offset, - &header_page_data_size); + &header_page_data_size, true); return 0; } -- cgit v0.10.2 From 53e5b5c215ce8372250e227f2c9acf9892de8434 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 9 Apr 2010 13:33:54 -0300 Subject: perf tools: Fix perl support installation when O= is used MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to create the $O/scripts/perl/Perf-Trace-Util/ directory too. Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Makefile b/tools/perf/Makefile index f578b05..57b3569 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -158,6 +158,7 @@ all:: # Define NO_DWARF if you do not want debug-info analysis feature at all. $(shell sh -c 'mkdir -p $(OUTPUT)scripts/python/Perf-Trace-Util/' 2> /dev/null) +$(shell sh -c 'mkdir -p $(OUTPUT)scripts/perl/Perf-Trace-Util/' 2> /dev/null) $(shell sh -c 'mkdir -p $(OUTPUT)util/scripting-engines/' 2> /dev/null) $(shell sh -c 'mkdir $(OUTPUT)bench' 2> /dev/null) -- cgit v0.10.2 From 5958f1d5d722df7a9e5d129676614a8e5219bacd Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Wed, 31 Mar 2010 21:56:41 +0200 Subject: x86, cpu: Add AMD core boosting feature flag to /proc/cpuinfo By semi-popular demand, this adds the Core Performance Boost feature flag to /proc/cpuinfo. Possible use case for this is userspace tools like cpufreq-aperf, for example, so that they don't have to jump through hoops of accessing "/dev/cpu/%d/cpuid" in order to check for CPB hw support, or call cpuid from userspace. Signed-off-by: Borislav Petkov LKML-Reference: <1270065406-1814-2-git-send-email-bp@amd64.org> Reviewed-by: Thomas Renninger Signed-off-by: H. Peter Anvin diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 0cd82d0..630e623 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -161,6 +161,7 @@ */ #define X86_FEATURE_IDA (7*32+ 0) /* Intel Dynamic Acceleration */ #define X86_FEATURE_ARAT (7*32+ 1) /* Always Running APIC Timer */ +#define X86_FEATURE_CPB (7*32+ 2) /* AMD Core Performance Boost */ /* Virtualization flags: Linux defined */ #define X86_FEATURE_TPR_SHADOW (8*32+ 0) /* Intel TPR Shadow */ diff --git a/arch/x86/kernel/cpu/addon_cpuid_features.c b/arch/x86/kernel/cpu/addon_cpuid_features.c index 97ad79c..ead2a1c 100644 --- a/arch/x86/kernel/cpu/addon_cpuid_features.c +++ b/arch/x86/kernel/cpu/addon_cpuid_features.c @@ -30,8 +30,9 @@ void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c) const struct cpuid_bit *cb; static const struct cpuid_bit __cpuinitconst cpuid_bits[] = { - { X86_FEATURE_IDA, CR_EAX, 1, 0x00000006 }, - { X86_FEATURE_ARAT, CR_EAX, 2, 0x00000006 }, + { X86_FEATURE_IDA, CR_EAX, 1, 0x00000006 }, + { X86_FEATURE_ARAT, CR_EAX, 2, 0x00000006 }, + { X86_FEATURE_CPB, CR_EDX, 9, 0x80000007 }, { X86_FEATURE_NPT, CR_EDX, 0, 0x8000000a }, { X86_FEATURE_LBRV, CR_EDX, 1, 0x8000000a }, { X86_FEATURE_SVML, CR_EDX, 2, 0x8000000a }, -- cgit v0.10.2 From 73860c6b2fd159a35637e233d735e36887c266ad Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Wed, 31 Mar 2010 21:56:42 +0200 Subject: powernow-k8: Add core performance boost support Starting with F10h, revE, AMD processors add support for a dynamic core boosting feature called Core Performance Boost. When a specific condition is present, a subset of the cores on a system are boosted beyond their P0 operating frequency to speed up the performance of single-threaded applications. In the normal case, the system comes out of reset with core boosting enabled. This patch adds a sysfs knob with which core boosting can be switched on or off for benchmarking purposes. While at it, make the CPB code hotplug-aware so that taking cores offline wouldn't interfere with boosting the remaining online cores. Furthermore, add cpu_online_mask hotplug protection as suggested by Andrew. Finally, cleanup the driver init codepath and update copyrights. Signed-off-by: Borislav Petkov LKML-Reference: <1270065406-1814-3-git-send-email-bp@amd64.org> Reviewed-by: Thomas Renninger Signed-off-by: H. Peter Anvin diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c index d360b56..74ca34b 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c @@ -1,6 +1,5 @@ - /* - * (c) 2003-2006 Advanced Micro Devices, Inc. + * (c) 2003-2010 Advanced Micro Devices, Inc. * Your use of this code is subject to the terms and conditions of the * GNU general public license version 2. See "COPYING" or * http://www.gnu.org/licenses/gpl.html @@ -54,6 +53,10 @@ static DEFINE_PER_CPU(struct powernow_k8_data *, powernow_data); static int cpu_family = CPU_OPTERON; +/* core performance boost */ +static bool cpb_capable, cpb_enabled; +static struct msr __percpu *msrs; + #ifndef CONFIG_SMP static inline const struct cpumask *cpu_core_mask(int cpu) { @@ -1393,8 +1396,77 @@ out: return khz; } +static void _cpb_toggle_msrs(bool t) +{ + int cpu; + + get_online_cpus(); + + rdmsr_on_cpus(cpu_online_mask, MSR_K7_HWCR, msrs); + + for_each_cpu(cpu, cpu_online_mask) { + struct msr *reg = per_cpu_ptr(msrs, cpu); + if (t) + reg->l &= ~BIT(25); + else + reg->l |= BIT(25); + } + wrmsr_on_cpus(cpu_online_mask, MSR_K7_HWCR, msrs); + + put_online_cpus(); +} + +/* + * Switch on/off core performance boosting. + * + * 0=disable + * 1=enable. + */ +static void cpb_toggle(bool t) +{ + if (!cpb_capable) + return; + + if (t && !cpb_enabled) { + cpb_enabled = true; + _cpb_toggle_msrs(t); + printk(KERN_INFO PFX "Core Boosting enabled.\n"); + } else if (!t && cpb_enabled) { + cpb_enabled = false; + _cpb_toggle_msrs(t); + printk(KERN_INFO PFX "Core Boosting disabled.\n"); + } +} + +static ssize_t store_cpb(struct cpufreq_policy *policy, const char *buf, + size_t count) +{ + int ret = -EINVAL; + unsigned long val = 0; + + ret = strict_strtoul(buf, 10, &val); + if (!ret && (val == 0 || val == 1) && cpb_capable) + cpb_toggle(val); + else + return -EINVAL; + + return count; +} + +static ssize_t show_cpb(struct cpufreq_policy *policy, char *buf) +{ + return sprintf(buf, "%u\n", cpb_enabled); +} + +#define define_one_rw(_name) \ +static struct freq_attr _name = \ +__ATTR(_name, 0644, show_##_name, store_##_name) + +define_one_rw(cpb); + static struct freq_attr *powernow_k8_attr[] = { &cpufreq_freq_attr_scaling_available_freqs, + &cpb, NULL, }; @@ -1410,10 +1482,51 @@ static struct cpufreq_driver cpufreq_amd64_driver = { .attr = powernow_k8_attr, }; +/* + * Clear the boost-disable flag on the CPU_DOWN path so that this cpu + * cannot block the remaining ones from boosting. On the CPU_UP path we + * simply keep the boost-disable flag in sync with the current global + * state. + */ +static int __cpuinit cpb_notify(struct notifier_block *nb, unsigned long action, + void *hcpu) +{ + unsigned cpu = (long)hcpu; + u32 lo, hi; + + switch (action) { + case CPU_UP_PREPARE: + case CPU_UP_PREPARE_FROZEN: + + if (!cpb_enabled) { + rdmsr_on_cpu(cpu, MSR_K7_HWCR, &lo, &hi); + lo |= BIT(25); + wrmsr_on_cpu(cpu, MSR_K7_HWCR, lo, hi); + } + break; + + case CPU_DOWN_PREPARE: + case CPU_DOWN_PREPARE_FROZEN: + rdmsr_on_cpu(cpu, MSR_K7_HWCR, &lo, &hi); + lo &= ~BIT(25); + wrmsr_on_cpu(cpu, MSR_K7_HWCR, lo, hi); + break; + + default: + break; + } + + return NOTIFY_OK; +} + +static struct notifier_block __cpuinitdata cpb_nb = { + .notifier_call = cpb_notify, +}; + /* driver entry point for init */ static int __cpuinit powernowk8_init(void) { - unsigned int i, supported_cpus = 0; + unsigned int i, supported_cpus = 0, cpu; for_each_online_cpu(i) { int rc; @@ -1422,15 +1535,36 @@ static int __cpuinit powernowk8_init(void) supported_cpus++; } - if (supported_cpus == num_online_cpus()) { - printk(KERN_INFO PFX "Found %d %s " - "processors (%d cpu cores) (" VERSION ")\n", - num_online_nodes(), - boot_cpu_data.x86_model_id, supported_cpus); - return cpufreq_register_driver(&cpufreq_amd64_driver); + if (supported_cpus != num_online_cpus()) + return -ENODEV; + + printk(KERN_INFO PFX "Found %d %s (%d cpu cores) (" VERSION ")\n", + num_online_nodes(), boot_cpu_data.x86_model_id, supported_cpus); + + if (boot_cpu_has(X86_FEATURE_CPB)) { + + cpb_capable = true; + + register_cpu_notifier(&cpb_nb); + + msrs = msrs_alloc(); + if (!msrs) { + printk(KERN_ERR "%s: Error allocating msrs!\n", __func__); + return -ENOMEM; + } + + rdmsr_on_cpus(cpu_online_mask, MSR_K7_HWCR, msrs); + + for_each_cpu(cpu, cpu_online_mask) { + struct msr *reg = per_cpu_ptr(msrs, cpu); + cpb_enabled |= !(!!(reg->l & BIT(25))); + } + + printk(KERN_INFO PFX "Core Performance Boosting: %s.\n", + (cpb_enabled ? "on" : "off")); } - return -ENODEV; + return cpufreq_register_driver(&cpufreq_amd64_driver); } /* driver entry point for term */ @@ -1438,6 +1572,13 @@ static void __exit powernowk8_exit(void) { dprintk("exit\n"); + if (boot_cpu_has(X86_FEATURE_CPB)) { + msrs_free(msrs); + msrs = NULL; + + unregister_cpu_notifier(&cpb_nb); + } + cpufreq_unregister_driver(&cpufreq_amd64_driver); } diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.h b/arch/x86/kernel/cpu/cpufreq/powernow-k8.h index 02ce824..df3529b 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.h +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.h @@ -5,7 +5,6 @@ * http://www.gnu.org/licenses/gpl.html */ - enum pstate { HW_PSTATE_INVALID = 0xff, HW_PSTATE_0 = 0, @@ -55,7 +54,6 @@ struct powernow_k8_data { struct cpumask *available_cores; }; - /* processor's cpuid instruction support */ #define CPUID_PROCESSOR_SIGNATURE 1 /* function 1 */ #define CPUID_XFAM 0x0ff00000 /* extended family */ -- cgit v0.10.2 From d65ad45cd82a0db9544469b8c54f5dc5cafbb2d8 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Wed, 31 Mar 2010 21:56:43 +0200 Subject: x86: Unify APERF/MPERF support Initialize this CPUID flag feature in common code. It could be made a standalone function later, maybe, if more functionality is duplicated. Signed-off-by: Borislav Petkov LKML-Reference: <1270065406-1814-4-git-send-email-bp@amd64.org> Reviewed-by: Thomas Renninger Signed-off-by: H. Peter Anvin diff --git a/arch/x86/kernel/cpu/addon_cpuid_features.c b/arch/x86/kernel/cpu/addon_cpuid_features.c index ead2a1c..fd1fc19 100644 --- a/arch/x86/kernel/cpu/addon_cpuid_features.c +++ b/arch/x86/kernel/cpu/addon_cpuid_features.c @@ -54,6 +54,14 @@ void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c) if (regs[cb->reg] & (1 << cb->bit)) set_cpu_cap(c, cb->feature); } + + /* + * common AMD/Intel features + */ + if (c->cpuid_level >= 6) { + if (cpuid_ecx(6) & 0x1) + set_cpu_cap(c, X86_FEATURE_APERFMPERF); + } } /* leaf 0xb SMT level */ diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 7e1cca1..3830258 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -352,12 +352,6 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) set_cpu_cap(c, X86_FEATURE_ARCH_PERFMON); } - if (c->cpuid_level > 6) { - unsigned ecx = cpuid_ecx(6); - if (ecx & 0x01) - set_cpu_cap(c, X86_FEATURE_APERFMPERF); - } - if (cpu_has_xmm2) set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC); if (cpu_has_ds) { -- cgit v0.10.2 From a2fed573f065e526bfd5cbf26e5491973d9e9aaa Mon Sep 17 00:00:00 2001 From: Mark Langsdorf Date: Thu, 18 Mar 2010 18:41:46 +0100 Subject: x86, cpufreq: Add APERF/MPERF support for AMD processors Starting with model 10 of Family 0x10, AMD processors may have support for APERF/MPERF. Add support for identifying it and using it within cpufreq. Move the APERF/MPERF functions out of the acpi-cpufreq code and into their own file so they can easily be shared. Signed-off-by: Mark Langsdorf LKML-Reference: <20100401141956.GA1930@aftab> Signed-off-by: Borislav Petkov Reviewed-by: Thomas Renninger Signed-off-by: H. Peter Anvin diff --git a/arch/x86/kernel/cpu/cpufreq/Makefile b/arch/x86/kernel/cpu/cpufreq/Makefile index 1840c0a..bd54bf6 100644 --- a/arch/x86/kernel/cpu/cpufreq/Makefile +++ b/arch/x86/kernel/cpu/cpufreq/Makefile @@ -2,8 +2,8 @@ # K8 systems. ACPI is preferred to all other hardware-specific drivers. # speedstep-* is preferred over p4-clockmod. -obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o -obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o +obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o mperf.o +obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o mperf.o obj-$(CONFIG_X86_PCC_CPUFREQ) += pcc-cpufreq.o obj-$(CONFIG_X86_POWERNOW_K6) += powernow-k6.o obj-$(CONFIG_X86_POWERNOW_K7) += powernow-k7.o diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c index 1b1920f..dc68e5c 100644 --- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -45,6 +45,7 @@ #include #include #include +#include "mperf.h" #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \ "acpi-cpufreq", msg) @@ -70,8 +71,6 @@ struct acpi_cpufreq_data { static DEFINE_PER_CPU(struct acpi_cpufreq_data *, acfreq_data); -static DEFINE_PER_CPU(struct aperfmperf, acfreq_old_perf); - /* acpi_perf_data is a pointer to percpu data. */ static struct acpi_processor_performance *acpi_perf_data; @@ -239,45 +238,6 @@ static u32 get_cur_val(const struct cpumask *mask) return cmd.val; } -/* Called via smp_call_function_single(), on the target CPU */ -static void read_measured_perf_ctrs(void *_cur) -{ - struct aperfmperf *am = _cur; - - get_aperfmperf(am); -} - -/* - * Return the measured active (C0) frequency on this CPU since last call - * to this function. - * Input: cpu number - * Return: Average CPU frequency in terms of max frequency (zero on error) - * - * We use IA32_MPERF and IA32_APERF MSRs to get the measured performance - * over a period of time, while CPU is in C0 state. - * IA32_MPERF counts at the rate of max advertised frequency - * IA32_APERF counts at the rate of actual CPU frequency - * Only IA32_APERF/IA32_MPERF ratio is architecturally defined and - * no meaning should be associated with absolute values of these MSRs. - */ -static unsigned int get_measured_perf(struct cpufreq_policy *policy, - unsigned int cpu) -{ - struct aperfmperf perf; - unsigned long ratio; - unsigned int retval; - - if (smp_call_function_single(cpu, read_measured_perf_ctrs, &perf, 1)) - return 0; - - ratio = calc_aperfmperf_ratio(&per_cpu(acfreq_old_perf, cpu), &perf); - per_cpu(acfreq_old_perf, cpu) = perf; - - retval = (policy->cpuinfo.max_freq * ratio) >> APERFMPERF_SHIFT; - - return retval; -} - static unsigned int get_cur_freq_on_cpu(unsigned int cpu) { struct acpi_cpufreq_data *data = per_cpu(acfreq_data, cpu); @@ -701,7 +661,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) /* Check for APERF/MPERF support in hardware */ if (cpu_has(c, X86_FEATURE_APERFMPERF)) - acpi_cpufreq_driver.getavg = get_measured_perf; + acpi_cpufreq_driver.getavg = cpufreq_get_measured_perf; dprintk("CPU%u - ACPI performance management activated.\n", cpu); for (i = 0; i < perf->state_count; i++) diff --git a/arch/x86/kernel/cpu/cpufreq/mperf.c b/arch/x86/kernel/cpu/cpufreq/mperf.c new file mode 100644 index 0000000..911e193 --- /dev/null +++ b/arch/x86/kernel/cpu/cpufreq/mperf.c @@ -0,0 +1,51 @@ +#include +#include +#include +#include +#include +#include + +#include "mperf.h" + +static DEFINE_PER_CPU(struct aperfmperf, acfreq_old_perf); + +/* Called via smp_call_function_single(), on the target CPU */ +static void read_measured_perf_ctrs(void *_cur) +{ + struct aperfmperf *am = _cur; + + get_aperfmperf(am); +} + +/* + * Return the measured active (C0) frequency on this CPU since last call + * to this function. + * Input: cpu number + * Return: Average CPU frequency in terms of max frequency (zero on error) + * + * We use IA32_MPERF and IA32_APERF MSRs to get the measured performance + * over a period of time, while CPU is in C0 state. + * IA32_MPERF counts at the rate of max advertised frequency + * IA32_APERF counts at the rate of actual CPU frequency + * Only IA32_APERF/IA32_MPERF ratio is architecturally defined and + * no meaning should be associated with absolute values of these MSRs. + */ +unsigned int cpufreq_get_measured_perf(struct cpufreq_policy *policy, + unsigned int cpu) +{ + struct aperfmperf perf; + unsigned long ratio; + unsigned int retval; + + if (smp_call_function_single(cpu, read_measured_perf_ctrs, &perf, 1)) + return 0; + + ratio = calc_aperfmperf_ratio(&per_cpu(acfreq_old_perf, cpu), &perf); + per_cpu(acfreq_old_perf, cpu) = perf; + + retval = (policy->cpuinfo.max_freq * ratio) >> APERFMPERF_SHIFT; + + return retval; +} +EXPORT_SYMBOL_GPL(cpufreq_get_measured_perf); +MODULE_LICENSE("GPL"); diff --git a/arch/x86/kernel/cpu/cpufreq/mperf.h b/arch/x86/kernel/cpu/cpufreq/mperf.h new file mode 100644 index 0000000..5dbf295 --- /dev/null +++ b/arch/x86/kernel/cpu/cpufreq/mperf.h @@ -0,0 +1,9 @@ +/* + * (c) 2010 Advanced Micro Devices, Inc. + * Your use of this code is subject to the terms and conditions of the + * GNU general public license version 2. See "COPYING" or + * http://www.gnu.org/licenses/gpl.html + */ + +unsigned int cpufreq_get_measured_perf(struct cpufreq_policy *policy, + unsigned int cpu); diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c index 74ca34b..52fce63 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c @@ -45,6 +45,7 @@ #define PFX "powernow-k8: " #define VERSION "version 2.20.00" #include "powernow-k8.h" +#include "mperf.h" /* serialize freq changes */ static DEFINE_MUTEX(fidvid_mutex); @@ -57,6 +58,8 @@ static int cpu_family = CPU_OPTERON; static bool cpb_capable, cpb_enabled; static struct msr __percpu *msrs; +static struct cpufreq_driver cpufreq_amd64_driver; + #ifndef CONFIG_SMP static inline const struct cpumask *cpu_core_mask(int cpu) { @@ -1251,6 +1254,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) struct powernow_k8_data *data; struct init_on_cpu init_on_cpu; int rc; + struct cpuinfo_x86 *c = &cpu_data(pol->cpu); if (!cpu_online(pol->cpu)) return -ENODEV; @@ -1325,6 +1329,10 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) return -EINVAL; } + /* Check for APERF/MPERF support in hardware */ + if (cpu_has(c, X86_FEATURE_APERFMPERF)) + cpufreq_amd64_driver.getavg = cpufreq_get_measured_perf; + cpufreq_frequency_table_get_attr(data->powernow_table, pol->cpu); if (cpu_family == CPU_HW_PSTATE) -- cgit v0.10.2 From 679370641e3675633cad222449262abbe93a4a2a Mon Sep 17 00:00:00 2001 From: Mark Langsdorf Date: Wed, 31 Mar 2010 21:56:45 +0200 Subject: powernow-k8: Fix frequency reporting With F10, model 10, all valid frequencies are in the ACPI _PST table. Cc: # 33.x 32.x Signed-off-by: Mark Langsdorf LKML-Reference: <1270065406-1814-6-git-send-email-bp@amd64.org> Signed-off-by: Borislav Petkov Reviewed-by: Thomas Renninger Signed-off-by: H. Peter Anvin diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c index 52fce63..6f3dc8f 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c @@ -935,7 +935,8 @@ static int fill_powernow_table_pstate(struct powernow_k8_data *data, powernow_table[i].index = index; /* Frequency may be rounded for these */ - if (boot_cpu_data.x86 == 0x10 || boot_cpu_data.x86 == 0x11) { + if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10) + || boot_cpu_data.x86 == 0x11) { powernow_table[i].frequency = freq_from_fid_did(lo & 0x3f, (lo >> 6) & 7); } else -- cgit v0.10.2 From 6dad2a29646ce3792c40cfc52d77e9b65a7bb143 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Wed, 31 Mar 2010 21:56:46 +0200 Subject: cpufreq: Unify sysfs attribute definition macros Multiple modules used to define those which are with identical functionality and were needlessly replicated among the different cpufreq drivers. Push them into the header and remove duplication. Signed-off-by: Borislav Petkov LKML-Reference: <1270065406-1814-7-git-send-email-bp@amd64.org> Reviewed-by: Thomas Renninger Signed-off-by: H. Peter Anvin diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 2d5d575..e02e417 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -662,32 +662,20 @@ static ssize_t show_bios_limit(struct cpufreq_policy *policy, char *buf) return sprintf(buf, "%u\n", policy->cpuinfo.max_freq); } -#define define_one_ro(_name) \ -static struct freq_attr _name = \ -__ATTR(_name, 0444, show_##_name, NULL) - -#define define_one_ro0400(_name) \ -static struct freq_attr _name = \ -__ATTR(_name, 0400, show_##_name, NULL) - -#define define_one_rw(_name) \ -static struct freq_attr _name = \ -__ATTR(_name, 0644, show_##_name, store_##_name) - -define_one_ro0400(cpuinfo_cur_freq); -define_one_ro(cpuinfo_min_freq); -define_one_ro(cpuinfo_max_freq); -define_one_ro(cpuinfo_transition_latency); -define_one_ro(scaling_available_governors); -define_one_ro(scaling_driver); -define_one_ro(scaling_cur_freq); -define_one_ro(bios_limit); -define_one_ro(related_cpus); -define_one_ro(affected_cpus); -define_one_rw(scaling_min_freq); -define_one_rw(scaling_max_freq); -define_one_rw(scaling_governor); -define_one_rw(scaling_setspeed); +cpufreq_freq_attr_ro_perm(cpuinfo_cur_freq, 0400); +cpufreq_freq_attr_ro(cpuinfo_min_freq); +cpufreq_freq_attr_ro(cpuinfo_max_freq); +cpufreq_freq_attr_ro(cpuinfo_transition_latency); +cpufreq_freq_attr_ro(scaling_available_governors); +cpufreq_freq_attr_ro(scaling_driver); +cpufreq_freq_attr_ro(scaling_cur_freq); +cpufreq_freq_attr_ro(bios_limit); +cpufreq_freq_attr_ro(related_cpus); +cpufreq_freq_attr_ro(affected_cpus); +cpufreq_freq_attr_rw(scaling_min_freq); +cpufreq_freq_attr_rw(scaling_max_freq); +cpufreq_freq_attr_rw(scaling_governor); +cpufreq_freq_attr_rw(scaling_setspeed); static struct attribute *default_attrs[] = { &cpuinfo_min_freq.attr, diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index 599a40b..ce5248e 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -178,12 +178,8 @@ static ssize_t show_sampling_rate_min(struct kobject *kobj, return sprintf(buf, "%u\n", min_sampling_rate); } -#define define_one_ro(_name) \ -static struct global_attr _name = \ -__ATTR(_name, 0444, show_##_name, NULL) - -define_one_ro(sampling_rate_max); -define_one_ro(sampling_rate_min); +define_one_global_ro(sampling_rate_max); +define_one_global_ro(sampling_rate_min); /* cpufreq_conservative Governor Tunables */ #define show_one(file_name, object) \ @@ -221,12 +217,8 @@ show_one_old(freq_step); show_one_old(sampling_rate_min); show_one_old(sampling_rate_max); -#define define_one_ro_old(object, _name) \ -static struct freq_attr object = \ -__ATTR(_name, 0444, show_##_name##_old, NULL) - -define_one_ro_old(sampling_rate_min_old, sampling_rate_min); -define_one_ro_old(sampling_rate_max_old, sampling_rate_max); +cpufreq_freq_attr_ro_old(sampling_rate_min); +cpufreq_freq_attr_ro_old(sampling_rate_max); /*** delete after deprecation time ***/ @@ -364,16 +356,12 @@ static ssize_t store_freq_step(struct kobject *a, struct attribute *b, return count; } -#define define_one_rw(_name) \ -static struct global_attr _name = \ -__ATTR(_name, 0644, show_##_name, store_##_name) - -define_one_rw(sampling_rate); -define_one_rw(sampling_down_factor); -define_one_rw(up_threshold); -define_one_rw(down_threshold); -define_one_rw(ignore_nice_load); -define_one_rw(freq_step); +define_one_global_rw(sampling_rate); +define_one_global_rw(sampling_down_factor); +define_one_global_rw(up_threshold); +define_one_global_rw(down_threshold); +define_one_global_rw(ignore_nice_load); +define_one_global_rw(freq_step); static struct attribute *dbs_attributes[] = { &sampling_rate_max.attr, @@ -409,16 +397,12 @@ write_one_old(down_threshold); write_one_old(ignore_nice_load); write_one_old(freq_step); -#define define_one_rw_old(object, _name) \ -static struct freq_attr object = \ -__ATTR(_name, 0644, show_##_name##_old, store_##_name##_old) - -define_one_rw_old(sampling_rate_old, sampling_rate); -define_one_rw_old(sampling_down_factor_old, sampling_down_factor); -define_one_rw_old(up_threshold_old, up_threshold); -define_one_rw_old(down_threshold_old, down_threshold); -define_one_rw_old(ignore_nice_load_old, ignore_nice_load); -define_one_rw_old(freq_step_old, freq_step); +cpufreq_freq_attr_rw_old(sampling_rate); +cpufreq_freq_attr_rw_old(sampling_down_factor); +cpufreq_freq_attr_rw_old(up_threshold); +cpufreq_freq_attr_rw_old(down_threshold); +cpufreq_freq_attr_rw_old(ignore_nice_load); +cpufreq_freq_attr_rw_old(freq_step); static struct attribute *dbs_attributes_old[] = { &sampling_rate_max_old.attr, diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index bd444dc..c00b25f 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -234,12 +234,8 @@ static ssize_t show_sampling_rate_min(struct kobject *kobj, return sprintf(buf, "%u\n", min_sampling_rate); } -#define define_one_ro(_name) \ -static struct global_attr _name = \ -__ATTR(_name, 0444, show_##_name, NULL) - -define_one_ro(sampling_rate_max); -define_one_ro(sampling_rate_min); +define_one_global_ro(sampling_rate_max); +define_one_global_ro(sampling_rate_min); /* cpufreq_ondemand Governor Tunables */ #define show_one(file_name, object) \ @@ -274,12 +270,8 @@ show_one_old(powersave_bias); show_one_old(sampling_rate_min); show_one_old(sampling_rate_max); -#define define_one_ro_old(object, _name) \ -static struct freq_attr object = \ -__ATTR(_name, 0444, show_##_name##_old, NULL) - -define_one_ro_old(sampling_rate_min_old, sampling_rate_min); -define_one_ro_old(sampling_rate_max_old, sampling_rate_max); +cpufreq_freq_attr_ro_old(sampling_rate_min); +cpufreq_freq_attr_ro_old(sampling_rate_max); /*** delete after deprecation time ***/ @@ -376,14 +368,10 @@ static ssize_t store_powersave_bias(struct kobject *a, struct attribute *b, return count; } -#define define_one_rw(_name) \ -static struct global_attr _name = \ -__ATTR(_name, 0644, show_##_name, store_##_name) - -define_one_rw(sampling_rate); -define_one_rw(up_threshold); -define_one_rw(ignore_nice_load); -define_one_rw(powersave_bias); +define_one_global_rw(sampling_rate); +define_one_global_rw(up_threshold); +define_one_global_rw(ignore_nice_load); +define_one_global_rw(powersave_bias); static struct attribute *dbs_attributes[] = { &sampling_rate_max.attr, @@ -415,14 +403,10 @@ write_one_old(up_threshold); write_one_old(ignore_nice_load); write_one_old(powersave_bias); -#define define_one_rw_old(object, _name) \ -static struct freq_attr object = \ -__ATTR(_name, 0644, show_##_name##_old, store_##_name##_old) - -define_one_rw_old(sampling_rate_old, sampling_rate); -define_one_rw_old(up_threshold_old, up_threshold); -define_one_rw_old(ignore_nice_load_old, ignore_nice_load); -define_one_rw_old(powersave_bias_old, powersave_bias); +cpufreq_freq_attr_rw_old(sampling_rate); +cpufreq_freq_attr_rw_old(up_threshold); +cpufreq_freq_attr_rw_old(ignore_nice_load); +cpufreq_freq_attr_rw_old(powersave_bias); static struct attribute *dbs_attributes_old[] = { &sampling_rate_max_old.attr, diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 4de02b1..9f15150 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -278,6 +278,27 @@ struct freq_attr { ssize_t (*store)(struct cpufreq_policy *, const char *, size_t count); }; +#define cpufreq_freq_attr_ro(_name) \ +static struct freq_attr _name = \ +__ATTR(_name, 0444, show_##_name, NULL) + +#define cpufreq_freq_attr_ro_perm(_name, _perm) \ +static struct freq_attr _name = \ +__ATTR(_name, _perm, show_##_name, NULL) + +#define cpufreq_freq_attr_ro_old(_name) \ +static struct freq_attr _name##_old = \ +__ATTR(_name, 0444, show_##_name##_old, NULL) + +#define cpufreq_freq_attr_rw(_name) \ +static struct freq_attr _name = \ +__ATTR(_name, 0644, show_##_name, store_##_name) + +#define cpufreq_freq_attr_rw_old(_name) \ +static struct freq_attr _name##_old = \ +__ATTR(_name, 0644, show_##_name##_old, store_##_name##_old) + + struct global_attr { struct attribute attr; ssize_t (*show)(struct kobject *kobj, @@ -286,6 +307,15 @@ struct global_attr { const char *c, size_t count); }; +#define define_one_global_ro(_name) \ +static struct global_attr _name = \ +__ATTR(_name, 0444, show_##_name, NULL) + +#define define_one_global_rw(_name) \ +static struct global_attr _name = \ +__ATTR(_name, 0644, show_##_name, store_##_name) + + /********************************************************************* * CPUFREQ 2.6. INTERFACE * *********************************************************************/ -- cgit v0.10.2 From 5534ecb2dda04345e8243901e0e49599228b4273 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 27 Feb 2010 19:49:37 +0100 Subject: ptrace: kill BKL in ptrace syscall The comment suggests that this usage is stale. There is no bkl in the exec path so if there is a race lurking there, the bkl in ptrace is not going to help in this regard. Overview of the possibility of "accidental" races this bkl might protect: - ptrace_traceme() is protected against task removal and concurrent read/write on current->ptrace as it locks write tasklist_lock. - arch_ptrace_attach() is serialized by ptrace_traceme() against concurrent PTRACE_TRACEME or PTRACE_ATTACH - ptrace_attach() is protected the same way ptrace_traceme() and in turn serializes arch_ptrace_attach() - ptrace_check_attach() does its own well described serializing too. There is no obvious race here. Signed-off-by: Arnd Bergmann Signed-off-by: Frederic Weisbecker Acked-by: Oleg Nesterov Acked-by: Roland McGrath Cc: Andrew Morton Cc: Roland McGrath diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 42ad8ae..5357502 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -666,10 +666,6 @@ SYSCALL_DEFINE4(ptrace, long, request, long, pid, long, addr, long, data) struct task_struct *child; long ret; - /* - * This lock_kernel fixes a subtle race with suid exec - */ - lock_kernel(); if (request == PTRACE_TRACEME) { ret = ptrace_traceme(); if (!ret) @@ -703,7 +699,6 @@ SYSCALL_DEFINE4(ptrace, long, request, long, pid, long, addr, long, data) out_put_task_struct: put_task_struct(child); out: - unlock_kernel(); return ret; } @@ -813,10 +808,6 @@ asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid, struct task_struct *child; long ret; - /* - * This lock_kernel fixes a subtle race with suid exec - */ - lock_kernel(); if (request == PTRACE_TRACEME) { ret = ptrace_traceme(); goto out; @@ -846,7 +837,6 @@ asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid, out_put_task_struct: put_task_struct(child); out: - unlock_kernel(); return ret; } #endif /* CONFIG_COMPAT */ -- cgit v0.10.2 From 050d4cc7029b73997d6821d89487b1f777d4873c Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 13 Apr 2010 10:15:56 +0900 Subject: sh: dmaengine support for SH7786 DMAC0. Hook up DMAC0 on SH7786. Signed-off-by: Paul Mundt diff --git a/arch/sh/include/cpu-sh4/cpu/dma-register.h b/arch/sh/include/cpu-sh4/cpu/dma-register.h index 55f9fec..5df4df0 100644 --- a/arch/sh/include/cpu-sh4/cpu/dma-register.h +++ b/arch/sh/include/cpu-sh4/cpu/dma-register.h @@ -23,7 +23,8 @@ #define CHCR_TS_HIGH_MASK 0 #define CHCR_TS_HIGH_SHIFT 0 #elif defined(CONFIG_CPU_SUBTYPE_SH7722) || \ - defined(CONFIG_CPU_SUBTYPE_SH7724) + defined(CONFIG_CPU_SUBTYPE_SH7724) || \ + defined(CONFIG_CPU_SUBTYPE_SH7786) #define CHCR_TS_LOW_MASK 0x00000018 #define CHCR_TS_LOW_SHIFT 3 #define CHCR_TS_HIGH_MASK 0x00300000 diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c index f559990..61e5491 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c @@ -1,7 +1,7 @@ /* * SH7786 Setup * - * Copyright (C) 2009 Renesas Solutions Corp. + * Copyright (C) 2009 - 2010 Renesas Solutions Corp. * Kuninori Morimoto * Paul Mundt * @@ -21,7 +21,9 @@ #include #include #include +#include #include +#include static struct plat_sci_port scif0_platform_data = { .mapbase = 0xffea0000, @@ -442,6 +444,83 @@ static struct platform_device tmu11_device = { .num_resources = ARRAY_SIZE(tmu11_resources), }; +static struct sh_dmae_channel dmac0_channels[] = { + { + .offset = 0, + .dmars = 0, + .dmars_bit = 0, + }, { + .offset = 0x10, + .dmars = 0, + .dmars_bit = 8, + }, { + .offset = 0x20, + .dmars = 4, + .dmars_bit = 0, + }, { + .offset = 0x30, + .dmars = 4, + .dmars_bit = 8, + }, { + .offset = 0x50, + .dmars = 8, + .dmars_bit = 0, + }, { + .offset = 0x60, + .dmars = 8, + .dmars_bit = 8, + } +}; + +static unsigned int ts_shift[] = TS_SHIFT; + +static struct sh_dmae_pdata dma0_platform_data = { + .channel = dmac0_channels, + .channel_num = ARRAY_SIZE(dmac0_channels), + .ts_low_shift = CHCR_TS_LOW_SHIFT, + .ts_low_mask = CHCR_TS_LOW_MASK, + .ts_high_shift = CHCR_TS_HIGH_SHIFT, + .ts_high_mask = CHCR_TS_HIGH_MASK, + .ts_shift = ts_shift, + .ts_shift_num = ARRAY_SIZE(ts_shift), + .dmaor_init = DMAOR_INIT, +}; + +/* Resource order important! */ +static struct resource dmac0_resources[] = { + { + /* Channel registers and DMAOR */ + .start = 0xfe008020, + .end = 0xfe00808f, + .flags = IORESOURCE_MEM, + }, { + /* DMARSx */ + .start = 0xfe009000, + .end = 0xfe00900b, + .flags = IORESOURCE_MEM, + }, { + /* DMA error IRQ */ + .start = evt2irq(0x5c0), + .end = evt2irq(0x5c0), + .flags = IORESOURCE_IRQ, + }, { + /* IRQ for channels 0-5 */ + .start = evt2irq(0x500), + .end = evt2irq(0x5a0), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device dma0_device = { + .name = "sh-dma-engine", + .id = 0, + .resource = dmac0_resources, + .num_resources = ARRAY_SIZE(dmac0_resources), + .dev = { + .platform_data = &dma0_platform_data, + }, +}; + static struct resource usb_ohci_resources[] = { [0] = { .start = 0xffe70400, @@ -489,6 +568,7 @@ static struct platform_device *sh7786_early_devices[] __initdata = { }; static struct platform_device *sh7786_devices[] __initdata = { + &dma0_device, &usb_ohci_device, }; -- cgit v0.10.2 From 0ded75428605213641897d6b8d8e9cf9fdb6eb8d Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 13 Apr 2010 10:16:34 +0900 Subject: sh: intc: Provide sysdev name for intc controllers. Presently the sysdevs are simply numbered based on the list position, without having any direct way of figuring out which controller these are actually mapping to. This provides a name attr for mapping out the chip name. Signed-off-by: Paul Mundt diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c index f438505..b605f7e 100644 --- a/drivers/sh/intc.c +++ b/drivers/sh/intc.c @@ -1034,6 +1034,18 @@ err0: return -ENOMEM; } +static ssize_t +show_intc_name(struct sys_device *dev, struct sysdev_attribute *attr, char *buf) +{ + struct intc_desc_int *d; + + d = container_of(dev, struct intc_desc_int, sysdev); + + return sprintf(buf, "%s\n", d->chip.name); +} + +static SYSDEV_ATTR(name, S_IRUGO, show_intc_name, NULL); + static int intc_suspend(struct sys_device *dev, pm_message_t state) { struct intc_desc_int *d; @@ -1098,8 +1110,12 @@ static int __init register_intc_sysdevs(void) d->sysdev.id = id; d->sysdev.cls = &intc_sysdev_class; error = sysdev_register(&d->sysdev); + if (error == 0) + error = sysdev_create_file(&d->sysdev, + &attr_name); if (error) break; + id++; } } -- cgit v0.10.2 From 12129fea50edcd696a9556523b058d6c445f21d8 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 13 Apr 2010 13:49:54 +0900 Subject: sh: intc: Tidy up loglevel mismatches. The printk loglevels are all over the place, make them a bit more coherent, and add some registration notification while we're at it. Signed-off-by: Paul Mundt diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c index b605f7e..65e1582 100644 --- a/drivers/sh/intc.c +++ b/drivers/sh/intc.c @@ -860,6 +860,9 @@ int __init register_intc_controller(struct intc_desc *desc) struct intc_desc_int *d; struct resource *res; + pr_info("intc: Registered controller '%s' with %u IRQs\n", + desc->name, hw->nr_vectors); + d = kzalloc(sizeof(*d), GFP_NOWAIT); if (!d) goto err0; @@ -974,7 +977,7 @@ int __init register_intc_controller(struct intc_desc *desc) irq_desc = irq_to_desc_alloc_node(irq, numa_node_id()); if (unlikely(!irq_desc)) { - pr_info("can't get irq_desc for %d\n", irq); + pr_err("can't get irq_desc for %d\n", irq); continue; } @@ -994,7 +997,7 @@ int __init register_intc_controller(struct intc_desc *desc) */ irq_desc = irq_to_desc_alloc_node(irq2, numa_node_id()); if (unlikely(!irq_desc)) { - pr_info("can't get irq_desc for %d\n", irq2); + pr_err("can't get irq_desc for %d\n", irq2); continue; } @@ -1121,7 +1124,7 @@ static int __init register_intc_sysdevs(void) } if (error) - pr_warning("intc: sysdev registration error\n"); + pr_err("intc: sysdev registration error\n"); return error; } @@ -1154,7 +1157,7 @@ unsigned int create_irq_nr(unsigned int irq_want, int node) desc = irq_to_desc_alloc_node(new, node); if (unlikely(!desc)) { - pr_info("can't get irq_desc for %d\n", new); + pr_err("can't get irq_desc for %d\n", new); goto out_unlock; } -- cgit v0.10.2 From 43b8774dc409ea5d9369b978e2e7bc79289f0522 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 13 Apr 2010 14:43:03 +0900 Subject: sh: intc: userimask support. This adds support for hardware-assisted userspace irq masking for special priority levels. Due to the SR.IMASK interactivity, only some platforms implement this in hardware (including but not limited to SH-4A interrupt controllers, and ARM-based SH-Mobile CPUs). Each CPU needs to wire this up on its own, for now only SH7786 is wired up as an example. Signed-off-by: Paul Mundt diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 8d90564..ba86bfb 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -732,6 +732,8 @@ config GUSA_RB LLSC, this should be more efficient than the other alternative of disabling interrupts around the atomic sequence. +source "drivers/sh/Kconfig" + endmenu menu "Boot options" diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c index 61e5491..235edf8 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -907,6 +908,7 @@ static DECLARE_INTC_DESC(intc_desc_irl4567, "sh7786-irl4567", vectors_irl4567, #define INTC_INTMSK2 INTMSK2 #define INTC_INTMSKCLR1 CnINTMSKCLR1 #define INTC_INTMSKCLR2 INTMSKCLR2 +#define INTC_USERIMASK 0xfe411000 void __init plat_irq_setup(void) { @@ -921,6 +923,7 @@ void __init plat_irq_setup(void) __raw_writel(__raw_readl(INTC_ICR0) & ~0x00c00000, INTC_ICR0); register_intc_controller(&intc_desc); + register_intc_userimask(INTC_USERIMASK); } void __init plat_irq_setup_pins(int mode) diff --git a/drivers/sh/Kconfig b/drivers/sh/Kconfig new file mode 100644 index 0000000..22c3cda --- /dev/null +++ b/drivers/sh/Kconfig @@ -0,0 +1,13 @@ +config INTC_USERIMASK + bool "Userspace interrupt masking support" + depends on ARCH_SHMOBILE || (SUPERH && CPU_SH4A) + help + This enables support for hardware-assisted userspace hardirq + masking. + + SH-4A and newer interrupt blocks all support a special shadowed + page with all non-masking registers obscured when mapped in to + userspace. This is primarily for use by userspace device + drivers that are using special priority levels. + + If in doubt, say N. diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c index 65e1582..77d10ac 100644 --- a/drivers/sh/intc.c +++ b/drivers/sh/intc.c @@ -27,6 +27,7 @@ #include #include #include +#include #define _INTC_MK(fn, mode, addr_e, addr_d, width, shift) \ ((shift) | ((width) << 5) | ((fn) << 9) | ((mode) << 13) | \ @@ -94,7 +95,8 @@ static DEFINE_SPINLOCK(vector_lock); #define SMP_NR(d, x) 1 #endif -static unsigned int intc_prio_level[NR_IRQS]; /* for now */ +static unsigned int intc_prio_level[NR_IRQS]; /* for now */ +static unsigned int default_prio_level = 2; /* 2 - 16 */ static unsigned long ack_handle[NR_IRQS]; static inline struct intc_desc_int *get_intc_desc(unsigned int irq) @@ -787,7 +789,7 @@ static void __init intc_register_irq(struct intc_desc *desc, /* set priority level * - this needs to be at least 2 for 5-bit priorities on 7780 */ - intc_prio_level[irq] = 2; + intc_prio_level[irq] = default_prio_level; /* enable secondary masking method if present */ if (data[!primary]) @@ -1037,6 +1039,64 @@ err0: return -ENOMEM; } +#ifdef CONFIG_INTC_USERIMASK +static void __iomem *uimask; + +int register_intc_userimask(unsigned long addr) +{ + if (unlikely(uimask)) + return -EBUSY; + + uimask = ioremap_nocache(addr, SZ_4K); + if (unlikely(!uimask)) + return -ENOMEM; + + pr_info("intc: userimask support registered for levels 0 -> %d\n", + default_prio_level - 1); + + return 0; +} + +static ssize_t +show_intc_userimask(struct sysdev_class *cls, + struct sysdev_class_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", (__raw_readl(uimask) >> 4) & 0xf); +} + +static ssize_t +store_intc_userimask(struct sysdev_class *cls, + struct sysdev_class_attribute *attr, + const char *buf, size_t count) +{ + unsigned long level; + + level = simple_strtoul(buf, NULL, 10); + + /* + * Minimal acceptable IRQ levels are in the 2 - 16 range, but + * these are chomped so as to not interfere with normal IRQs. + * + * Level 1 is a special case on some CPUs in that it's not + * directly settable, but given that USERIMASK cuts off below a + * certain level, we don't care about this limitation here. + * Level 0 on the other hand equates to user masking disabled. + * + * We use default_prio_level as a cut off so that only special + * case opt-in IRQs can be mangled. + */ + if (level >= default_prio_level) + return -EINVAL; + + __raw_writel(0xa5 << 24 | level << 4, uimask); + + return count; +} + +static SYSDEV_CLASS_ATTR(userimask, S_IRUSR | S_IWUSR, + show_intc_userimask, store_intc_userimask); +#endif + static ssize_t show_intc_name(struct sys_device *dev, struct sysdev_attribute *attr, char *buf) { @@ -1108,6 +1168,11 @@ static int __init register_intc_sysdevs(void) int id = 0; error = sysdev_class_register(&intc_sysdev_class); +#ifdef CONFIG_INTC_USERIMASK + if (!error && uimask) + error = sysdev_class_create_file(&intc_sysdev_class, + &attr_userimask); +#endif if (!error) { list_for_each_entry(d, &intc_list, list) { d->sysdev.id = id; diff --git a/include/linux/sh_intc.h b/include/linux/sh_intc.h index 01d8168..f0e8cca 100644 --- a/include/linux/sh_intc.h +++ b/include/linux/sh_intc.h @@ -99,6 +99,15 @@ struct intc_desc symbol __initdata = { \ int __init register_intc_controller(struct intc_desc *desc); int intc_set_priority(unsigned int irq, unsigned int prio); +#ifdef CONFIG_INTC_USERIMASK +int register_intc_userimask(unsigned long addr); +#else +static inline int register_intc_userimask(unsigned long addr) +{ + return 0; +} +#endif + int reserve_irq_vector(unsigned int irq); void reserve_irq_legacy(void); -- cgit v0.10.2 From 2170c5a8ae4b952e517e7b0565528914ddc11320 Mon Sep 17 00:00:00 2001 From: Rafi Rubin Date: Fri, 9 Apr 2010 17:58:25 -0400 Subject: HID: ntrig: Emit TOUCH with DOUBLETAP for single touch I squelched TipSwitch in a recent patch which resulted in the loss of Touch events for single touch firmwares. This patch just puts Touch back in for single touch, and bundles it with DoubleTap (like the multitouch code). The two events are used to convey the same message to different drivers. Signed-off-by: Rafi Rubin Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c index a418f9e..58ba0d3 100644 --- a/drivers/hid/hid-ntrig.c +++ b/drivers/hid/hid-ntrig.c @@ -173,6 +173,8 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field, if (!nd->reading_mt) { input_report_key(input, BTN_TOOL_DOUBLETAP, (nd->confidence != 0)); + input_report_key(input, BTN_TOUCH, + (nd->confidence != 0)); input_event(input, EV_ABS, ABS_X, nd->x); input_event(input, EV_ABS, ABS_Y, nd->y); } -- cgit v0.10.2 From c05556421742eb47f80301767653a4bcb19de9de Mon Sep 17 00:00:00 2001 From: Ian Munsie Date: Tue, 13 Apr 2010 18:37:33 +1000 Subject: perf: Fix endianness argument compatibility with OPT_BOOLEAN() and introduce OPT_INCR() Parsing an option from the command line with OPT_BOOLEAN on a bool data type would not work on a big-endian machine due to the manner in which the boolean was being cast into an int and incremented. For example, running 'perf probe --list' on a PowerPC machine would fail to properly set the list_events bool and would therefore print out the usage information and terminate. This patch makes OPT_BOOLEAN work as expected with a bool datatype. For cases where the original OPT_BOOLEAN was intentionally being used to increment an int each time it was passed in on the command line, this patch introduces OPT_INCR with the old behaviour of OPT_BOOLEAN (the verbose variable is currently the only such example of this). I have reviewed every use of OPT_BOOLEAN to verify that a true C99 bool was passed. Where integers were used, I verified that they were only being used for boolean logic and changed them to bools to ensure that they would not be mistakenly used as ints. The major exception was the verbose variable which now uses OPT_INCR instead of OPT_BOOLEAN. Signed-off-by: Ian Munsie Acked-by: David S. Miller Cc: # NOTE: wont apply to .3[34].x cleanly, please backport Cc: Git development list Cc: Ian Munsie Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo Cc: KOSAKI Motohiro Cc: Hitoshi Mitake Cc: Rusty Russell Cc: Frederic Weisbecker Cc: Eric B Munson Cc: Valdis.Kletnieks@vt.edu Cc: WANG Cong Cc: Thiago Farina Cc: Masami Hiramatsu Cc: Xiao Guangrong Cc: Jaswinder Singh Rajput Cc: Arjan van de Ven Cc: OGAWA Hirofumi Cc: Mike Galbraith Cc: Tom Zanussi Cc: Anton Blanchard Cc: John Kacur Cc: Li Zefan Cc: Steven Rostedt LKML-Reference: <1271147857-11604-1-git-send-email-imunsie@au.ibm.com> Signed-off-by: Ingo Molnar diff --git a/tools/perf/bench/mem-memcpy.c b/tools/perf/bench/mem-memcpy.c index 52e646e..38dae74 100644 --- a/tools/perf/bench/mem-memcpy.c +++ b/tools/perf/bench/mem-memcpy.c @@ -23,7 +23,7 @@ static const char *length_str = "1MB"; static const char *routine = "default"; -static int use_clock = 0; +static bool use_clock = false; static int clock_fd; static const struct option options[] = { diff --git a/tools/perf/bench/sched-messaging.c b/tools/perf/bench/sched-messaging.c index 81cee78..da1b2e9 100644 --- a/tools/perf/bench/sched-messaging.c +++ b/tools/perf/bench/sched-messaging.c @@ -31,9 +31,9 @@ #define DATASIZE 100 -static int use_pipes = 0; +static bool use_pipes = false; static unsigned int loops = 100; -static unsigned int thread_mode = 0; +static bool thread_mode = false; static unsigned int num_groups = 10; struct sender_context { diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index ee0d917..06eaebe 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -28,11 +28,11 @@ static char const *input_name = "perf.data"; -static int force; +static bool force; -static int full_paths; +static bool full_paths; -static int print_line; +static bool print_line; struct sym_hist { u64 sum; @@ -595,7 +595,7 @@ static const struct option options[] = { OPT_STRING('s', "symbol", &sym_hist_filter, "symbol", "symbol to annotate"), OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), - OPT_BOOLEAN('v', "verbose", &verbose, + OPT_INCR('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"), OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, "dump raw trace in ASCII"), diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c index 30a05f5..f8e3d18 100644 --- a/tools/perf/builtin-buildid-cache.c +++ b/tools/perf/builtin-buildid-cache.c @@ -27,7 +27,7 @@ static const struct option buildid_cache_options[] = { "file list", "file(s) to add"), OPT_STRING('r', "remove", &remove_name_list_str, "file list", "file(s) to remove"), - OPT_BOOLEAN('v', "verbose", &verbose, "be more verbose"), + OPT_INCR('v', "verbose", &verbose, "be more verbose"), OPT_END() }; diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c index d0675c0..af2ad8b 100644 --- a/tools/perf/builtin-buildid-list.c +++ b/tools/perf/builtin-buildid-list.c @@ -16,7 +16,7 @@ #include "util/symbol.h" static char const *input_name = "perf.data"; -static int force; +static bool force; static bool with_hits; static const char * const buildid_list_usage[] = { @@ -29,7 +29,7 @@ static const struct option options[] = { OPT_STRING('i', "input", &input_name, "file", "input file name"), OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), - OPT_BOOLEAN('v', "verbose", &verbose, + OPT_INCR('v', "verbose", &verbose, "be more verbose"), OPT_END() }; diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 1ea15d8..3a1d94d 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -19,7 +19,7 @@ static char const *input_old = "perf.data.old", *input_new = "perf.data"; static char diff__default_sort_order[] = "dso,symbol"; -static int force; +static bool force; static bool show_displacement; static int perf_session__add_hist_entry(struct perf_session *self, @@ -188,7 +188,7 @@ static const char * const diff_usage[] = { }; static const struct option options[] = { - OPT_BOOLEAN('v', "verbose", &verbose, + OPT_INCR('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"), OPT_BOOLEAN('m', "displacement", &show_displacement, "Show position displacement relative to baseline"), diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c index 215b584..81e3ecc 100644 --- a/tools/perf/builtin-help.c +++ b/tools/perf/builtin-help.c @@ -29,7 +29,7 @@ enum help_format { HELP_FORMAT_WEB, }; -static int show_all = 0; +static bool show_all = false; static enum help_format help_format = HELP_FORMAT_MAN; static struct option builtin_help_options[] = { OPT_BOOLEAN('a', "all", &show_all, "print all available commands"), diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index e12c844..6c38e4f 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c @@ -744,7 +744,7 @@ static const char * const lock_usage[] = { static const struct option lock_options[] = { OPT_STRING('i', "input", &input_name, "file", "input file name"), - OPT_BOOLEAN('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"), + OPT_INCR('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"), OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, "dump raw trace in ASCII"), OPT_END() }; diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index b3ba25a..bfc47ff 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c @@ -133,7 +133,7 @@ static const char * const probe_usage[] = { }; static const struct option options[] = { - OPT_BOOLEAN('v', "verbose", &verbose, + OPT_INCR('v', "verbose", &verbose, "be more verbose (show parsed arguments, etc)"), OPT_BOOLEAN('l', "list", ¶ms.list_events, "list up current probe events"), diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index dc61f1b..9a95136 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -38,22 +38,22 @@ static int output; static const char *output_name = "perf.data"; static int group = 0; static unsigned int realtime_prio = 0; -static int raw_samples = 0; -static int system_wide = 0; +static bool raw_samples = false; +static bool system_wide = false; static int profile_cpu = -1; static pid_t target_pid = -1; static pid_t target_tid = -1; static pid_t *all_tids = NULL; static int thread_num = 0; static pid_t child_pid = -1; -static int inherit = 1; -static int force = 0; -static int append_file = 0; -static int call_graph = 0; -static int inherit_stat = 0; -static int no_samples = 0; -static int sample_address = 0; -static int multiplex = 0; +static bool inherit = true; +static bool force = false; +static bool append_file = false; +static bool call_graph = false; +static bool inherit_stat = false; +static bool no_samples = false; +static bool sample_address = false; +static bool multiplex = false; static int multiplex_fd = -1; static long samples = 0; @@ -465,7 +465,7 @@ static int __cmd_record(int argc, const char **argv) rename(output_name, oldname); } } else { - append_file = 0; + append_file = false; } flags = O_CREAT|O_RDWR; @@ -701,7 +701,7 @@ static const struct option options[] = { "number of mmap data pages"), OPT_BOOLEAN('g', "call-graph", &call_graph, "do call-graph (stack chain/backtrace) recording"), - OPT_BOOLEAN('v', "verbose", &verbose, + OPT_INCR('v', "verbose", &verbose, "be more verbose (show counter open errors, etc)"), OPT_BOOLEAN('s', "stat", &inherit_stat, "per thread counts"), diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index e93c69a..daee082 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -32,11 +32,11 @@ static char const *input_name = "perf.data"; -static int force; +static bool force; static bool hide_unresolved; static bool dont_use_callchains; -static int show_threads; +static bool show_threads; static struct perf_read_values show_threads_values; static char default_pretty_printing_style[] = "normal"; @@ -418,7 +418,7 @@ static const char * const report_usage[] = { static const struct option options[] = { OPT_STRING('i', "input", &input_name, "file", "input file name"), - OPT_BOOLEAN('v', "verbose", &verbose, + OPT_INCR('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"), OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, "dump raw trace in ASCII"), diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 5e59c0c..09ddc8e 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -1790,7 +1790,7 @@ static const char * const sched_usage[] = { static const struct option sched_options[] = { OPT_STRING('i', "input", &input_name, "file", "input file name"), - OPT_BOOLEAN('v', "verbose", &verbose, + OPT_INCR('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"), OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, "dump raw trace in ASCII"), @@ -1805,7 +1805,7 @@ static const char * const latency_usage[] = { static const struct option latency_options[] = { OPT_STRING('s', "sort", &sort_order, "key[,key2...]", "sort by key(s): runtime, switch, avg, max"), - OPT_BOOLEAN('v', "verbose", &verbose, + OPT_INCR('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"), OPT_INTEGER('C', "CPU", &profile_cpu, "CPU to profile on"), @@ -1822,7 +1822,7 @@ static const char * const replay_usage[] = { static const struct option replay_options[] = { OPT_INTEGER('r', "repeat", &replay_repeat, "repeat the workload replay N times (-1: infinite)"), - OPT_BOOLEAN('v', "verbose", &verbose, + OPT_INCR('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"), OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, "dump raw trace in ASCII"), diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 1036ca7..e619ac8 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -67,19 +67,19 @@ static struct perf_event_attr default_attrs[] = { }; -static int system_wide = 0; +static bool system_wide = false; static unsigned int nr_cpus = 0; static int run_idx = 0; static int run_count = 1; -static int inherit = 1; -static int scale = 1; +static bool inherit = true; +static bool scale = true; static pid_t target_pid = -1; static pid_t target_tid = -1; static pid_t *all_tids = NULL; static int thread_num = 0; static pid_t child_pid = -1; -static int null_run = 0; +static bool null_run = false; static int *fd[MAX_NR_CPUS][MAX_COUNTERS]; @@ -528,7 +528,7 @@ static const struct option options[] = { "system-wide collection from all CPUs"), OPT_BOOLEAN('c', "scale", &scale, "scale/normalize counters"), - OPT_BOOLEAN('v', "verbose", &verbose, + OPT_INCR('v', "verbose", &verbose, "be more verbose (show counter open errors, etc)"), OPT_INTEGER('r', "repeat", &run_count, "repeat command and print average + stddev (max: 100)"), diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index 369c1b4..96f4a09 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c @@ -42,7 +42,7 @@ static u64 turbo_frequency; static u64 first_time, last_time; -static int power_only; +static bool power_only; struct per_pid; diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 4abdd9b..40f24dd 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -57,7 +57,7 @@ static int *fd[MAX_NR_CPUS][MAX_COUNTERS]; -static int system_wide = 0; +static bool system_wide = false; static int default_interval = 0; @@ -68,18 +68,18 @@ static int target_pid = -1; static int target_tid = -1; static pid_t *all_tids = NULL; static int thread_num = 0; -static int inherit = 0; +static bool inherit = false; static int profile_cpu = -1; static int nr_cpus = 0; static unsigned int realtime_prio = 0; -static int group = 0; +static bool group = false; static unsigned int page_size; static unsigned int mmap_pages = 16; static int freq = 1000; /* 1 KHz */ static int delay_secs = 2; -static int zero = 0; -static int dump_symtab = 0; +static bool zero = false; +static bool dump_symtab = false; static bool hide_kernel_symbols = false; static bool hide_user_symbols = false; @@ -854,7 +854,7 @@ static void handle_keypress(int c) display_weighted = ~display_weighted; break; case 'z': - zero = ~zero; + zero = !zero; break; default: break; @@ -1335,7 +1335,7 @@ static const struct option options[] = { "display this many functions"), OPT_BOOLEAN('U', "hide_user_symbols", &hide_user_symbols, "hide user symbols"), - OPT_BOOLEAN('v', "verbose", &verbose, + OPT_INCR('v', "verbose", &verbose, "be more verbose (show counter open errors, etc)"), OPT_END() }; diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 407041d..8fc50d8 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -505,7 +505,7 @@ static const char * const trace_usage[] = { static const struct option options[] = { OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, "dump raw trace in ASCII"), - OPT_BOOLEAN('v', "verbose", &verbose, + OPT_INCR('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"), OPT_BOOLEAN('L', "Latency", &latency_format, "show latency attributes (irqs/preemption disabled, etc)"), diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c index 033d66d..dd824cf 100644 --- a/tools/perf/util/debug.c +++ b/tools/perf/util/debug.c @@ -13,7 +13,7 @@ #include "util.h" int verbose = 0; -int dump_trace = 0; +bool dump_trace = false; int eprintf(int level, const char *fmt, ...) { diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h index 5cb0a1b..047ac33 100644 --- a/tools/perf/util/debug.h +++ b/tools/perf/util/debug.h @@ -2,10 +2,11 @@ #ifndef __PERF_DEBUG_H #define __PERF_DEBUG_H +#include #include "event.h" extern int verbose; -extern int dump_trace; +extern bool dump_trace; int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); void trace_event(event_t *event); diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c index 79dfa0c..ed88764 100644 --- a/tools/perf/util/parse-options.c +++ b/tools/perf/util/parse-options.c @@ -49,6 +49,7 @@ static int get_value(struct parse_opt_ctx_t *p, break; /* FALLTHROUGH */ case OPTION_BOOLEAN: + case OPTION_INCR: case OPTION_BIT: case OPTION_SET_INT: case OPTION_SET_PTR: @@ -73,6 +74,10 @@ static int get_value(struct parse_opt_ctx_t *p, return 0; case OPTION_BOOLEAN: + *(bool *)opt->value = unset ? false : true; + return 0; + + case OPTION_INCR: *(int *)opt->value = unset ? 0 : *(int *)opt->value + 1; return 0; @@ -478,6 +483,7 @@ int usage_with_options_internal(const char * const *usagestr, case OPTION_GROUP: case OPTION_BIT: case OPTION_BOOLEAN: + case OPTION_INCR: case OPTION_SET_INT: case OPTION_SET_PTR: case OPTION_LONG: diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h index 948805a..b2da725 100644 --- a/tools/perf/util/parse-options.h +++ b/tools/perf/util/parse-options.h @@ -8,7 +8,8 @@ enum parse_opt_type { OPTION_GROUP, /* options with no arguments */ OPTION_BIT, - OPTION_BOOLEAN, /* _INCR would have been a better name */ + OPTION_BOOLEAN, + OPTION_INCR, OPTION_SET_INT, OPTION_SET_PTR, /* options with arguments (usually) */ @@ -95,6 +96,7 @@ struct option { #define OPT_GROUP(h) { .type = OPTION_GROUP, .help = (h) } #define OPT_BIT(s, l, v, h, b) { .type = OPTION_BIT, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (b) } #define OPT_BOOLEAN(s, l, v, h) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = (v), .help = (h) } +#define OPT_INCR(s, l, v, h) { .type = OPTION_INCR, .short_name = (s), .long_name = (l), .value = (v), .help = (h) } #define OPT_SET_INT(s, l, v, h, i) { .type = OPTION_SET_INT, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (i) } #define OPT_SET_PTR(s, l, v, h, p) { .type = OPTION_SET_PTR, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (p) } #define OPT_INTEGER(s, l, v, h) { .type = OPTION_INTEGER, .short_name = (s), .long_name = (l), .value = (v), .help = (h) } diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index 3b81250..17d6d66 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c @@ -42,7 +42,7 @@ int header_page_overwrite_size; int header_page_data_offset; int header_page_data_size; -int latency_format; +bool latency_format; static char *input_buf; static unsigned long long input_buf_ptr; diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h index c3269b9..81f2fd2 100644 --- a/tools/perf/util/trace-event.h +++ b/tools/perf/util/trace-event.h @@ -1,6 +1,7 @@ #ifndef __PERF_TRACE_EVENTS_H #define __PERF_TRACE_EVENTS_H +#include #include "parse-events.h" #define __unused __attribute__((unused)) @@ -241,7 +242,7 @@ extern int header_page_size_size; extern int header_page_data_offset; extern int header_page_data_size; -extern int latency_format; +extern bool latency_format; int parse_header_page(char *buf, unsigned long size); int trace_parse_common_type(void *data); -- cgit v0.10.2 From 8dc58101f2c838355d44402aa77646649d10dbec Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Thu, 1 Apr 2010 23:59:15 -0500 Subject: perf: Add pipe-specific header read/write and event processing code This patch makes several changes to allow the perf event stream to be sent and received over a pipe: - adds pipe-specific versions of the header read/write code - adds pipe-specific version of the event processing code - adds a range of event types to be used for header or other pseudo events, above the range used by the kernel - checks the return value of event handlers, which they can use to skip over large events during event processing rather than actually reading them into event objects. - unifies the multiple do_read() functions and updates its users. Note that none of these changes affect the existing perf data file format or processing - this code only comes into play if perf output is sent to stdout (or is read from stdin). Signed-off-by: Tom Zanussi Acked-by: Thomas Gleixner Cc: fweisbec@gmail.com Cc: rostedt@goodmis.org Cc: k-keiichi@bx.jp.nec.com Cc: acme@ghostprotocols.net LKML-Reference: <1270184365-8281-2-git-send-email-tzanussi@gmail.com> Signed-off-by: Ingo Molnar diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 9a95136..d060fc5 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -487,7 +487,7 @@ static int __cmd_record(int argc, const char **argv) } if (!file_new) { - err = perf_header__read(&session->header, output); + err = perf_header__read(session, output); if (err < 0) return err; } diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 7f7cf85..5c1eba6 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -83,6 +83,10 @@ struct build_id_event { char filename[]; }; +enum perf_header_event_type { /* above any possible kernel type */ + PERF_RECORD_HEADER_MAX = 64, +}; + typedef union event_union { struct perf_event_header header; struct ip_event ip; diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 6c9aa16..8d05337 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -427,6 +427,25 @@ out_free: return err; } +int perf_header__write_pipe(int fd) +{ + struct perf_pipe_file_header f_header; + int err; + + f_header = (struct perf_pipe_file_header){ + .magic = PERF_MAGIC, + .size = sizeof(f_header), + }; + + err = do_write(fd, &f_header, sizeof(f_header)); + if (err < 0) { + pr_debug("failed to write perf pipe header\n"); + return err; + } + + return 0; +} + int perf_header__write(struct perf_header *self, int fd, bool at_exit) { struct perf_file_header f_header; @@ -518,25 +537,10 @@ int perf_header__write(struct perf_header *self, int fd, bool at_exit) return 0; } -static int do_read(int fd, void *buf, size_t size) -{ - while (size) { - int ret = read(fd, buf, size); - - if (ret <= 0) - return -1; - - size -= ret; - buf += ret; - } - - return 0; -} - static int perf_header__getbuffer64(struct perf_header *self, int fd, void *buf, size_t size) { - if (do_read(fd, buf, size)) + if (do_read(fd, buf, size) <= 0) return -1; if (self->needs_swap) @@ -592,7 +596,7 @@ int perf_file_header__read(struct perf_file_header *self, { lseek(fd, 0, SEEK_SET); - if (do_read(fd, self, sizeof(*self)) || + if (do_read(fd, self, sizeof(*self)) <= 0 || memcmp(&self->magic, __perf_magic, sizeof(self->magic))) return -1; @@ -662,13 +666,51 @@ static int perf_file_section__process(struct perf_file_section *self, return 0; } -int perf_header__read(struct perf_header *self, int fd) +static int perf_file_header__read_pipe(struct perf_pipe_file_header *self, + struct perf_header *ph, int fd) { + if (do_read(fd, self, sizeof(*self)) <= 0 || + memcmp(&self->magic, __perf_magic, sizeof(self->magic))) + return -1; + + if (self->size != sizeof(*self)) { + u64 size = bswap_64(self->size); + + if (size != sizeof(*self)) + return -1; + + ph->needs_swap = true; + } + + return 0; +} + +static int perf_header__read_pipe(struct perf_session *session, int fd) +{ + struct perf_header *self = &session->header; + struct perf_pipe_file_header f_header; + + if (perf_file_header__read_pipe(&f_header, self, fd) < 0) { + pr_debug("incompatible file format\n"); + return -EINVAL; + } + + session->fd = fd; + + return 0; +} + +int perf_header__read(struct perf_session *session, int fd) +{ + struct perf_header *self = &session->header; struct perf_file_header f_header; struct perf_file_attr f_attr; u64 f_id; int nr_attrs, nr_ids, i, j; + if (session->fd_pipe) + return perf_header__read_pipe(session, fd); + if (perf_file_header__read(&f_header, self, fd) < 0) { pr_debug("incompatible file format\n"); return -EINVAL; diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index c059f08..6562ece 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h @@ -39,6 +39,11 @@ struct perf_file_header { DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS); }; +struct perf_pipe_file_header { + u64 magic; + u64 size; +}; + struct perf_header; int perf_file_header__read(struct perf_file_header *self, @@ -60,8 +65,9 @@ struct perf_header { int perf_header__init(struct perf_header *self); void perf_header__exit(struct perf_header *self); -int perf_header__read(struct perf_header *self, int fd); +int perf_header__read(struct perf_session *session, int fd); int perf_header__write(struct perf_header *self, int fd, bool at_exit); +int perf_header__write_pipe(int fd); int perf_header__add_attr(struct perf_header *self, struct perf_header_attr *attr); diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index ddf288f..2c1277c 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -14,6 +14,16 @@ static int perf_session__open(struct perf_session *self, bool force) { struct stat input_stat; + if (!strcmp(self->filename, "-")) { + self->fd_pipe = true; + self->fd = STDIN_FILENO; + + if (perf_header__read(self, self->fd) < 0) + pr_err("incompatible file format"); + + return 0; + } + self->fd = open(self->filename, O_RDONLY); if (self->fd < 0) { pr_err("failed to open file: %s", self->filename); @@ -38,7 +48,7 @@ static int perf_session__open(struct perf_session *self, bool force) goto out_close; } - if (perf_header__read(&self->header, self->fd) < 0) { + if (perf_header__read(self, self->fd) < 0) { pr_err("incompatible file format"); goto out_close; } @@ -52,6 +62,11 @@ out_close: return -1; } +void perf_session__update_sample_type(struct perf_session *self) +{ + self->sample_type = perf_header__sample_type(&self->header); +} + struct perf_session *perf_session__new(const char *filename, int mode, bool force) { size_t len = filename ? strlen(filename) + 1 : 0; @@ -85,7 +100,7 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc goto out_delete; } - self->sample_type = perf_header__sample_type(&self->header); + perf_session__update_sample_type(self); out: return self; out_free: @@ -200,14 +215,17 @@ static const char *event__name[] = { [PERF_RECORD_SAMPLE] = "SAMPLE", }; -unsigned long event__total[PERF_RECORD_MAX]; +unsigned long event__total[PERF_RECORD_HEADER_MAX]; void event__print_totals(void) { int i; - for (i = 0; i < PERF_RECORD_MAX; ++i) + for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) { + if (!event__name[i]) + continue; pr_info("%10s events: %10ld\n", event__name[i], event__total[i]); + } } void mem_bswap_64(void *src, int byte_size) @@ -271,7 +289,7 @@ static event__swap_op event__swap_ops[] = { [PERF_RECORD_LOST] = event__all64_swap, [PERF_RECORD_READ] = event__read_swap, [PERF_RECORD_SAMPLE] = event__all64_swap, - [PERF_RECORD_MAX] = NULL, + [PERF_RECORD_HEADER_MAX] = NULL, }; static int perf_session__process_event(struct perf_session *self, @@ -281,7 +299,7 @@ static int perf_session__process_event(struct perf_session *self, { trace_event(event); - if (event->header.type < PERF_RECORD_MAX) { + if (event->header.type < PERF_RECORD_HEADER_MAX) { dump_printf("%#Lx [%#x]: PERF_RECORD_%s", offset + head, event->header.size, event__name[event->header.type]); @@ -376,6 +394,101 @@ static struct thread *perf_session__register_idle_thread(struct perf_session *se return thread; } +int do_read(int fd, void *buf, size_t size) +{ + void *buf_start = buf; + + while (size) { + int ret = read(fd, buf, size); + + if (ret <= 0) + return ret; + + size -= ret; + buf += ret; + } + + return buf - buf_start; +} + +#define session_done() (*(volatile int *)(&session_done)) +volatile int session_done; + +static int __perf_session__process_pipe_events(struct perf_session *self, + struct perf_event_ops *ops) +{ + event_t event; + uint32_t size; + int skip = 0; + u64 head; + int err; + void *p; + + perf_event_ops__fill_defaults(ops); + + head = 0; +more: + err = do_read(self->fd, &event, sizeof(struct perf_event_header)); + if (err <= 0) { + if (err == 0) + goto done; + + pr_err("failed to read event header\n"); + goto out_err; + } + + if (self->header.needs_swap) + perf_event_header__bswap(&event.header); + + size = event.header.size; + if (size == 0) + size = 8; + + p = &event; + p += sizeof(struct perf_event_header); + + err = do_read(self->fd, p, size - sizeof(struct perf_event_header)); + if (err <= 0) { + if (err == 0) { + pr_err("unexpected end of event stream\n"); + goto done; + } + + pr_err("failed to read event data\n"); + goto out_err; + } + + if (size == 0 || + (skip = perf_session__process_event(self, &event, ops, + 0, head)) < 0) { + dump_printf("%#Lx [%#x]: skipping unknown header type: %d\n", + head, event.header.size, event.header.type); + /* + * assume we lost track of the stream, check alignment, and + * increment a single u64 in the hope to catch on again 'soon'. + */ + if (unlikely(head & 7)) + head &= ~7ULL; + + size = 8; + } + + head += size; + + dump_printf("\n%#Lx [%#x]: event: %d\n", + head, event.header.size, event.header.type); + + if (skip > 0) + head += skip; + + if (!session_done()) + goto more; +done: + err = 0; +out_err: + return err; +} + int __perf_session__process_events(struct perf_session *self, u64 data_offset, u64 data_size, u64 file_size, struct perf_event_ops *ops) @@ -499,9 +612,13 @@ out_getcwd_err: self->cwdlen = strlen(self->cwd); } - err = __perf_session__process_events(self, self->header.data_offset, - self->header.data_size, - self->size, ops); + if (!self->fd_pipe) + err = __perf_session__process_events(self, + self->header.data_offset, + self->header.data_size, + self->size, ops); + else + err = __perf_session__process_pipe_events(self, ops); out_err: return err; } diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 27f4c2d..5f78911 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -27,6 +27,7 @@ struct perf_session { u64 sample_type; struct ref_reloc_sym ref_reloc_sym; int fd; + bool fd_pipe; int cwdlen; char *cwd; char filename[0]; @@ -92,6 +93,9 @@ static inline struct map * return map_groups__new_module(&self->kmaps, start, filename); } +int do_read(int fd, void *buf, size_t size); +void perf_session__update_sample_type(struct perf_session *self); + #ifdef NO_NEWT_SUPPORT static inline int perf_session__browse_hists(struct rb_root *hists __used, u64 nr_hists __used, -- cgit v0.10.2 From 529870e37473a9fc609078f03cc5b4148cf06a87 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Thu, 1 Apr 2010 23:59:16 -0500 Subject: perf record: Introduce special handling for pipe output Adds special treatment for stdout - if the user specifies '-o -' to perf record, the intent is that the event stream be written to stdout rather than to a disk file. Also, redirect stdout of forked child to stderr - in pipe mode, stdout of the forked child interferes with the stdout perf stream, so redirect it to stderr where it can still be seen but won't be mixed in with the perf output. Signed-off-by: Tom Zanussi Acked-by: Thomas Gleixner Cc: fweisbec@gmail.com Cc: rostedt@goodmis.org Cc: k-keiichi@bx.jp.nec.com Cc: acme@ghostprotocols.net LKML-Reference: <1270184365-8281-3-git-send-email-tzanussi@gmail.com> Signed-off-by: Ingo Molnar diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index d060fc5..d4464f7 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -35,6 +35,7 @@ static unsigned int page_size; static unsigned int mmap_pages = 128; static int freq = 1000; static int output; +static int pipe_output = 0; static const char *output_name = "perf.data"; static int group = 0; static unsigned int realtime_prio = 0; @@ -449,7 +450,9 @@ static int __cmd_record(int argc, const char **argv) exit(-1); } - if (!stat(output_name, &st) && st.st_size) { + if (!strcmp(output_name, "-")) + pipe_output = 1; + else if (!stat(output_name, &st) && st.st_size) { if (!force) { if (!append_file) { pr_err("Error, output file %s exists, use -A " @@ -474,7 +477,10 @@ static int __cmd_record(int argc, const char **argv) else flags |= O_TRUNC; - output = open(output_name, flags, S_IRUSR|S_IWUSR); + if (pipe_output) + output = STDOUT_FILENO; + else + output = open(output_name, flags, S_IRUSR | S_IWUSR); if (output < 0) { perror("failed to create output file"); exit(-1); @@ -513,6 +519,8 @@ static int __cmd_record(int argc, const char **argv) } if (!child_pid) { + if (pipe_output) + dup2(2, 1); close(child_ready_pipe[0]); close(go_pipe[1]); fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC); @@ -564,7 +572,11 @@ static int __cmd_record(int argc, const char **argv) open_counters(cpumap[i]); } - if (file_new) { + if (pipe_output) { + err = perf_header__write_pipe(output); + if (err < 0) + return err; + } else if (file_new) { err = perf_header__write(&session->header, output, false); if (err < 0) return err; -- cgit v0.10.2 From 46656ac7fb3252f8a3db29b18638e0e8067849ba Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Thu, 1 Apr 2010 23:59:17 -0500 Subject: perf report: Introduce special handling for pipe input Adds special treatment for stdin - if the user specifies '-i -' to perf report, the intent is that the event stream be written to stdin rather than from a disk file. The actual handling of the '-' filename is done by the session; this just adds a signal handler to stop reporting, and turns off interference by the pager. Signed-off-by: Tom Zanussi Acked-by: Thomas Gleixner Cc: fweisbec@gmail.com Cc: rostedt@goodmis.org Cc: k-keiichi@bx.jp.nec.com Cc: acme@ghostprotocols.net LKML-Reference: <1270184365-8281-4-git-send-email-tzanussi@gmail.com> Signed-off-by: Ingo Molnar diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index daee082..00b358f 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -269,6 +269,13 @@ static struct perf_event_ops event_ops = { .read = process_read_event, }; +extern volatile int session_done; + +static void sig_handler(int sig __attribute__((__unused__))) +{ + session_done = 1; +} + static int __cmd_report(void) { int ret = -EINVAL; @@ -276,6 +283,8 @@ static int __cmd_report(void) struct rb_node *next; const char *help = "For a higher level overview, try: perf report --sort comm,dso"; + signal(SIGINT, sig_handler); + session = perf_session__new(input_name, O_RDONLY, force); if (session == NULL) return -ENOMEM; @@ -465,7 +474,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __used) { argc = parse_options(argc, argv, options, report_usage, 0); - setup_browser(); + if (strcmp(input_name, "-") != 0) + setup_browser(); if (symbol__init() < 0) return -1; -- cgit v0.10.2 From c239da3b4b55dbb8f30bcb8d1a0d63fc44a567c3 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Thu, 1 Apr 2010 23:59:18 -0500 Subject: perf trace: Introduce special handling for pipe input Adds special treatment for stdin - if the user specifies '-i -' to perf trace, the intent is that the event stream be read from stdin rather than from a disk file. The actual handling of the '-' filename is done by the session; this just adds a signal handler to stop reporting, and turns off interference by the pager. Signed-off-by: Tom Zanussi Acked-by: Thomas Gleixner Cc: fweisbec@gmail.com Cc: rostedt@goodmis.org Cc: k-keiichi@bx.jp.nec.com Cc: acme@ghostprotocols.net LKML-Reference: <1270184365-8281-5-git-send-email-tzanussi@gmail.com> Signed-off-by: Ingo Molnar diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 8fc50d8..c681e85 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -106,8 +106,17 @@ static struct perf_event_ops event_ops = { .comm = event__process_comm, }; +extern volatile int session_done; + +static void sig_handler(int sig __unused) +{ + session_done = 1; +} + static int __cmd_trace(struct perf_session *session) { + signal(SIGINT, sig_handler); + return perf_session__process_events(session, &event_ops); } @@ -580,7 +589,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used) if (session == NULL) return -ENOMEM; - if (!perf_session__has_traces(session, "record -R")) + if (strcmp(input_name, "-") && + !perf_session__has_traces(session, "record -R")) return -EINVAL; if (generate_script_lang) { -- cgit v0.10.2 From 2c46dbb517a10b18d459e6ceffefde5bfb290cf6 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Thu, 1 Apr 2010 23:59:19 -0500 Subject: perf: Convert perf header attrs into attr events Bypasses the attr perf header code and replaces it with a synthesized event and processing function that accomplishes the same thing, used when reading/writing perf data to/from a pipe. Making the attrs into events allows them to be streamed over a pipe along with the rest of the header data (in later patches). It also paves the way to allowing events to be added and removed from perf sessions dynamically. Signed-off-by: Tom Zanussi Acked-by: Thomas Gleixner Cc: fweisbec@gmail.com Cc: rostedt@goodmis.org Cc: k-keiichi@bx.jp.nec.com Cc: acme@ghostprotocols.net LKML-Reference: <1270184365-8281-6-git-send-email-tzanussi@gmail.com> Signed-off-by: Ingo Molnar diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index d4464f7..289d9cf 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -584,6 +584,16 @@ static int __cmd_record(int argc, const char **argv) post_processing_offset = lseek(output, 0, SEEK_CUR); + if (pipe_output) { + err = event__synthesize_attrs(&session->header, + process_synthesized_event, + session); + if (err < 0) { + pr_err("Couldn't synthesize attrs.\n"); + return err; + } + } + err = event__synthesize_kernel_mmap(process_synthesized_event, session, "_text"); if (err < 0) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 00b358f..f0486ce 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -267,6 +267,7 @@ static struct perf_event_ops event_ops = { .fork = event__process_task, .lost = event__process_lost, .read = process_read_event, + .attr = event__process_attr, }; extern volatile int session_done; diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index c681e85..e30eac6 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -104,6 +104,7 @@ static int process_sample_event(event_t *event, struct perf_session *session) static struct perf_event_ops event_ops = { .sample = process_sample_event, .comm = event__process_comm, + .attr = event__process_attr, }; extern volatile int session_done; diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 5c1eba6..b4fbf25 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -84,7 +84,14 @@ struct build_id_event { }; enum perf_header_event_type { /* above any possible kernel type */ - PERF_RECORD_HEADER_MAX = 64, + PERF_RECORD_HEADER_ATTR = 64, + PERF_RECORD_HEADER_MAX +}; + +struct attr_event { + struct perf_event_header header; + struct perf_event_attr attr; + u64 id[]; }; typedef union event_union { @@ -96,6 +103,7 @@ typedef union event_union { struct lost_event lost; struct read_event read; struct sample_event sample; + struct attr_event attr; } event_t; struct events_stats { diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 8d05337..e361739 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -807,3 +807,82 @@ perf_header__find_attr(u64 id, struct perf_header *header) return NULL; } + +int event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id, + event__handler_t process, + struct perf_session *session) +{ + event_t *ev; + size_t size; + int err; + + size = sizeof(struct perf_event_attr); + size = ALIGN(size, sizeof(u64)); + size += sizeof(struct perf_event_header); + size += ids * sizeof(u64); + + ev = malloc(size); + + ev->attr.attr = *attr; + memcpy(ev->attr.id, id, ids * sizeof(u64)); + + ev->attr.header.type = PERF_RECORD_HEADER_ATTR; + ev->attr.header.size = size; + + err = process(ev, session); + + free(ev); + + return err; +} + +int event__synthesize_attrs(struct perf_header *self, + event__handler_t process, + struct perf_session *session) +{ + struct perf_header_attr *attr; + int i, err = 0; + + for (i = 0; i < self->attrs; i++) { + attr = self->attr[i]; + + err = event__synthesize_attr(&attr->attr, attr->ids, attr->id, + process, session); + if (err) { + pr_debug("failed to create perf header attribute\n"); + return err; + } + } + + return err; +} + +int event__process_attr(event_t *self, struct perf_session *session) +{ + struct perf_header_attr *attr; + unsigned int i, ids, n_ids; + + attr = perf_header_attr__new(&self->attr.attr); + if (attr == NULL) + return -ENOMEM; + + ids = self->header.size; + ids -= (void *)&self->attr.id - (void *)self; + n_ids = ids / sizeof(u64); + + for (i = 0; i < n_ids; i++) { + if (perf_header_attr__add_id(attr, self->attr.id[i]) < 0) { + perf_header_attr__delete(attr); + return -ENOMEM; + } + } + + if (perf_header__add_attr(&session->header, attr) < 0) { + perf_header_attr__delete(attr); + return -ENOMEM; + } + + perf_session__update_sample_type(session); + + return 0; +} diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index 6562ece..e916ac5 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h @@ -95,4 +95,12 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, const char *name, bool is_kallsyms); int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir); +int event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id, + event__handler_t process, + struct perf_session *session); +int event__synthesize_attrs(struct perf_header *self, + event__handler_t process, + struct perf_session *session); +int event__process_attr(event_t *self, struct perf_session *session); + #endif /* __PERF_HEADER_H */ diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 2c1277c..bc81864 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -200,6 +200,8 @@ static void perf_event_ops__fill_defaults(struct perf_event_ops *handler) handler->throttle = process_event_stub; if (handler->unthrottle == NULL) handler->unthrottle = process_event_stub; + if (handler->attr == NULL) + handler->attr = process_event_stub; } static const char *event__name[] = { @@ -213,6 +215,7 @@ static const char *event__name[] = { [PERF_RECORD_FORK] = "FORK", [PERF_RECORD_READ] = "READ", [PERF_RECORD_SAMPLE] = "SAMPLE", + [PERF_RECORD_HEADER_ATTR] = "ATTR", }; unsigned long event__total[PERF_RECORD_HEADER_MAX]; @@ -279,6 +282,26 @@ static void event__read_swap(event_t *self) self->read.id = bswap_64(self->read.id); } +static void event__attr_swap(event_t *self) +{ + size_t size; + + self->attr.attr.type = bswap_32(self->attr.attr.type); + self->attr.attr.size = bswap_32(self->attr.attr.size); + self->attr.attr.config = bswap_64(self->attr.attr.config); + self->attr.attr.sample_period = bswap_64(self->attr.attr.sample_period); + self->attr.attr.sample_type = bswap_64(self->attr.attr.sample_type); + self->attr.attr.read_format = bswap_64(self->attr.attr.read_format); + self->attr.attr.wakeup_events = bswap_32(self->attr.attr.wakeup_events); + self->attr.attr.bp_type = bswap_32(self->attr.attr.bp_type); + self->attr.attr.bp_addr = bswap_64(self->attr.attr.bp_addr); + self->attr.attr.bp_len = bswap_64(self->attr.attr.bp_len); + + size = self->header.size; + size -= (void *)&self->attr.id - (void *)self; + mem_bswap_64(self->attr.id, size); +} + typedef void (*event__swap_op)(event_t *self); static event__swap_op event__swap_ops[] = { @@ -289,6 +312,7 @@ static event__swap_op event__swap_ops[] = { [PERF_RECORD_LOST] = event__all64_swap, [PERF_RECORD_READ] = event__read_swap, [PERF_RECORD_SAMPLE] = event__all64_swap, + [PERF_RECORD_HEADER_ATTR] = event__attr_swap, [PERF_RECORD_HEADER_MAX] = NULL, }; @@ -329,6 +353,8 @@ static int perf_session__process_event(struct perf_session *self, return ops->throttle(event, self); case PERF_RECORD_UNTHROTTLE: return ops->unthrottle(event, self); + case PERF_RECORD_HEADER_ATTR: + return ops->attr(event, self); default: self->unknown_events++; return -1; diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 5f78911..45a1374 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -44,7 +44,8 @@ struct perf_event_ops { lost, read, throttle, - unthrottle; + unthrottle, + attr; }; struct perf_session *perf_session__new(const char *filename, int mode, bool force); -- cgit v0.10.2 From cd19a035f3b63fee6dcbdb5371c4b22276f7dc8c Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Thu, 1 Apr 2010 23:59:20 -0500 Subject: perf: Convert perf event types into event type events Bypasses the event type perf header code and replaces it with a synthesized event and processing function that accomplishes the same thing, used when reading/writing perf data to/from a pipe. Signed-off-by: Tom Zanussi Acked-by: Thomas Gleixner Cc: fweisbec@gmail.com Cc: rostedt@goodmis.org Cc: k-keiichi@bx.jp.nec.com Cc: acme@ghostprotocols.net LKML-Reference: <1270184365-8281-7-git-send-email-tzanussi@gmail.com> Signed-off-by: Ingo Molnar diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 289d9cf..c4c1322 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -592,6 +592,13 @@ static int __cmd_record(int argc, const char **argv) pr_err("Couldn't synthesize attrs.\n"); return err; } + + err = event__synthesize_event_types(process_synthesized_event, + session); + if (err < 0) { + pr_err("Couldn't synthesize event_types.\n"); + return err; + } } err = event__synthesize_kernel_mmap(process_synthesized_event, diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index f0486ce..e59d012 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -268,6 +268,7 @@ static struct perf_event_ops event_ops = { .lost = event__process_lost, .read = process_read_event, .attr = event__process_attr, + .event_type = event__process_event_type, }; extern volatile int session_done; diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index e30eac6..eb884a7 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -105,6 +105,7 @@ static struct perf_event_ops event_ops = { .sample = process_sample_event, .comm = event__process_comm, .attr = event__process_attr, + .event_type = event__process_event_type, }; extern volatile int session_done; diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index b4fbf25..c720fe0 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -85,6 +85,7 @@ struct build_id_event { enum perf_header_event_type { /* above any possible kernel type */ PERF_RECORD_HEADER_ATTR = 64, + PERF_RECORD_HEADER_EVENT_TYPE = 65, PERF_RECORD_HEADER_MAX }; @@ -94,6 +95,18 @@ struct attr_event { u64 id[]; }; +#define MAX_EVENT_NAME 64 + +struct perf_trace_event_type { + u64 event_id; + char name[MAX_EVENT_NAME]; +}; + +struct event_type_event { + struct perf_event_header header; + struct perf_trace_event_type event_type; +}; + typedef union event_union { struct perf_event_header header; struct ip_event ip; @@ -104,6 +117,7 @@ typedef union event_union { struct read_event read; struct sample_event sample; struct attr_event attr; + struct event_type_event event_type; } event_t; struct events_stats { diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index e361739..4463799 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -99,13 +99,6 @@ int perf_header__add_attr(struct perf_header *self, return 0; } -#define MAX_EVENT_NAME 64 - -struct perf_trace_event_type { - u64 event_id; - char name[MAX_EVENT_NAME]; -}; - static int event_count; static struct perf_trace_event_type *events; @@ -886,3 +879,58 @@ int event__process_attr(event_t *self, struct perf_session *session) return 0; } + +int event__synthesize_event_type(u64 event_id, char *name, + event__handler_t process, + struct perf_session *session) +{ + event_t ev; + size_t size = 0; + int err = 0; + + memset(&ev, 0, sizeof(ev)); + + ev.event_type.event_type.event_id = event_id; + memset(ev.event_type.event_type.name, 0, MAX_EVENT_NAME); + strncpy(ev.event_type.event_type.name, name, MAX_EVENT_NAME - 1); + + ev.event_type.header.type = PERF_RECORD_HEADER_EVENT_TYPE; + size = strlen(name); + size = ALIGN(size, sizeof(u64)); + ev.event_type.header.size = sizeof(ev.event_type) - + (sizeof(ev.event_type.event_type.name) - size); + + err = process(&ev, session); + + return err; +} + +int event__synthesize_event_types(event__handler_t process, + struct perf_session *session) +{ + struct perf_trace_event_type *type; + int i, err = 0; + + for (i = 0; i < event_count; i++) { + type = &events[i]; + + err = event__synthesize_event_type(type->event_id, type->name, + process, session); + if (err) { + pr_debug("failed to create perf header event type\n"); + return err; + } + } + + return err; +} + +int event__process_event_type(event_t *self, + struct perf_session *session __unused) +{ + if (perf_header__push_event(self->event_type.event_type.event_id, + self->event_type.event_type.name) < 0) + return -ENOMEM; + + return 0; +} diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index e916ac5..afeb618 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h @@ -103,4 +103,13 @@ int event__synthesize_attrs(struct perf_header *self, struct perf_session *session); int event__process_attr(event_t *self, struct perf_session *session); +int event__synthesize_event_type(u64 event_id, char *name, + event__handler_t process, + struct perf_session *session); +int event__synthesize_event_types(event__handler_t process, + struct perf_session *session); +int event__process_event_type(event_t *self, + struct perf_session *session); + + #endif /* __PERF_HEADER_H */ diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index bc81864..96c4629 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -202,6 +202,8 @@ static void perf_event_ops__fill_defaults(struct perf_event_ops *handler) handler->unthrottle = process_event_stub; if (handler->attr == NULL) handler->attr = process_event_stub; + if (handler->event_type == NULL) + handler->event_type = process_event_stub; } static const char *event__name[] = { @@ -216,6 +218,7 @@ static const char *event__name[] = { [PERF_RECORD_READ] = "READ", [PERF_RECORD_SAMPLE] = "SAMPLE", [PERF_RECORD_HEADER_ATTR] = "ATTR", + [PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE", }; unsigned long event__total[PERF_RECORD_HEADER_MAX]; @@ -302,6 +305,12 @@ static void event__attr_swap(event_t *self) mem_bswap_64(self->attr.id, size); } +static void event__event_type_swap(event_t *self) +{ + self->event_type.event_type.event_id = + bswap_64(self->event_type.event_type.event_id); +} + typedef void (*event__swap_op)(event_t *self); static event__swap_op event__swap_ops[] = { @@ -313,6 +322,7 @@ static event__swap_op event__swap_ops[] = { [PERF_RECORD_READ] = event__read_swap, [PERF_RECORD_SAMPLE] = event__all64_swap, [PERF_RECORD_HEADER_ATTR] = event__attr_swap, + [PERF_RECORD_HEADER_EVENT_TYPE] = event__event_type_swap, [PERF_RECORD_HEADER_MAX] = NULL, }; @@ -355,6 +365,8 @@ static int perf_session__process_event(struct perf_session *self, return ops->unthrottle(event, self); case PERF_RECORD_HEADER_ATTR: return ops->attr(event, self); + case PERF_RECORD_HEADER_EVENT_TYPE: + return ops->event_type(event, self); default: self->unknown_events++; return -1; diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 45a1374..0dac1f4 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -45,7 +45,8 @@ struct perf_event_ops { read, throttle, unthrottle, - attr; + attr, + event_type; }; struct perf_session *perf_session__new(const char *filename, int mode, bool force); -- cgit v0.10.2 From 9215545e99d8c0b27323df2de504f4294bf5e407 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Thu, 1 Apr 2010 23:59:21 -0500 Subject: perf: Convert perf tracing data into a tracing_data event Bypasses the tracing_data perf header code and replaces it with a synthesized event and processing function that accomplishes the same thing, used when reading/writing perf data to/from a pipe. The tracing data is pretty large, and this patch doesn't attempt to break it down into component events. The tracing_data event itself doesn't actually contain the tracing data, rather it arranges for the event processing code to skip over it after it's read, using the skip return value added to the event processing loop in a previous patch. Signed-off-by: Tom Zanussi Acked-by: Thomas Gleixner Cc: fweisbec@gmail.com Cc: rostedt@goodmis.org Cc: k-keiichi@bx.jp.nec.com Cc: acme@ghostprotocols.net LKML-Reference: <1270184365-8281-8-git-send-email-tzanussi@gmail.com> Signed-off-by: Ingo Molnar diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index c4c1322..3775abe 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -104,6 +104,11 @@ static void mmap_write_tail(struct mmap_data *md, unsigned long tail) pc->data_tail = tail; } +static void advance_output(size_t size) +{ + bytes_written += size; +} + static void write_output(void *buf, size_t size) { while (size) { @@ -599,6 +604,17 @@ static int __cmd_record(int argc, const char **argv) pr_err("Couldn't synthesize event_types.\n"); return err; } + + err = event__synthesize_tracing_data(output, attrs, + nr_counters, + process_synthesized_event, + session); + if (err <= 0) { + pr_err("Couldn't record tracing data.\n"); + return err; + } + + advance_output(err); } err = event__synthesize_kernel_mmap(process_synthesized_event, diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index e59d012..76f03a7 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -269,6 +269,7 @@ static struct perf_event_ops event_ops = { .read = process_read_event, .attr = event__process_attr, .event_type = event__process_event_type, + .tracing_data = event__process_tracing_data, }; extern volatile int session_done; diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index eb884a7..1509744 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -106,6 +106,7 @@ static struct perf_event_ops event_ops = { .comm = event__process_comm, .attr = event__process_attr, .event_type = event__process_event_type, + .tracing_data = event__process_tracing_data, }; extern volatile int session_done; diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index c720fe0..b896a17 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -86,6 +86,7 @@ struct build_id_event { enum perf_header_event_type { /* above any possible kernel type */ PERF_RECORD_HEADER_ATTR = 64, PERF_RECORD_HEADER_EVENT_TYPE = 65, + PERF_RECORD_HEADER_TRACING_DATA = 66, PERF_RECORD_HEADER_MAX }; @@ -107,6 +108,11 @@ struct event_type_event { struct perf_trace_event_type event_type; }; +struct tracing_data_event { + struct perf_event_header header; + u32 size; +}; + typedef union event_union { struct perf_event_header header; struct ip_event ip; @@ -118,6 +124,7 @@ typedef union event_union { struct sample_event sample; struct attr_event attr; struct event_type_event event_type; + struct tracing_data_event tracing_data; } event_t; struct events_stats { diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 4463799..c6874ec 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -934,3 +934,55 @@ int event__process_event_type(event_t *self, return 0; } + +int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs, + int nb_events, + event__handler_t process, + struct perf_session *session __unused) +{ + event_t ev; + ssize_t size = 0, aligned_size = 0, padding; + int err = 0; + + memset(&ev, 0, sizeof(ev)); + + ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA; + size = read_tracing_data_size(fd, pattrs, nb_events); + if (size <= 0) + return size; + aligned_size = ALIGN(size, sizeof(u64)); + padding = aligned_size - size; + ev.tracing_data.header.size = sizeof(ev.tracing_data); + ev.tracing_data.size = aligned_size; + + process(&ev, session); + + err = read_tracing_data(fd, pattrs, nb_events); + write_padded(fd, NULL, 0, padding); + + return aligned_size; +} + +int event__process_tracing_data(event_t *self, + struct perf_session *session) +{ + ssize_t size_read, padding, size = self->tracing_data.size; + off_t offset = lseek(session->fd, 0, SEEK_CUR); + char buf[BUFSIZ]; + + /* setup for reading amidst mmap */ + lseek(session->fd, offset + sizeof(struct tracing_data_event), + SEEK_SET); + + size_read = trace_report(session->fd); + + padding = ALIGN(size_read, sizeof(u64)) - size_read; + + if (read(session->fd, buf, padding) < 0) + die("reading input file"); + + if (size_read + padding != size) + die("tracing data size mismatch"); + + return size_read + padding; +} diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index afeb618..3ed3d98 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h @@ -111,5 +111,11 @@ int event__synthesize_event_types(event__handler_t process, int event__process_event_type(event_t *self, struct perf_session *session); +int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs, + int nb_events, + event__handler_t process, + struct perf_session *session); +int event__process_tracing_data(event_t *self, + struct perf_session *session); #endif /* __PERF_HEADER_H */ diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 96c4629..1516c40 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -204,6 +204,8 @@ static void perf_event_ops__fill_defaults(struct perf_event_ops *handler) handler->attr = process_event_stub; if (handler->event_type == NULL) handler->event_type = process_event_stub; + if (handler->tracing_data == NULL) + handler->tracing_data = process_event_stub; } static const char *event__name[] = { @@ -219,6 +221,7 @@ static const char *event__name[] = { [PERF_RECORD_SAMPLE] = "SAMPLE", [PERF_RECORD_HEADER_ATTR] = "ATTR", [PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE", + [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA", }; unsigned long event__total[PERF_RECORD_HEADER_MAX]; @@ -311,6 +314,11 @@ static void event__event_type_swap(event_t *self) bswap_64(self->event_type.event_type.event_id); } +static void event__tracing_data_swap(event_t *self) +{ + self->tracing_data.size = bswap_32(self->tracing_data.size); +} + typedef void (*event__swap_op)(event_t *self); static event__swap_op event__swap_ops[] = { @@ -323,6 +331,7 @@ static event__swap_op event__swap_ops[] = { [PERF_RECORD_SAMPLE] = event__all64_swap, [PERF_RECORD_HEADER_ATTR] = event__attr_swap, [PERF_RECORD_HEADER_EVENT_TYPE] = event__event_type_swap, + [PERF_RECORD_HEADER_TRACING_DATA] = event__tracing_data_swap, [PERF_RECORD_HEADER_MAX] = NULL, }; @@ -367,6 +376,10 @@ static int perf_session__process_event(struct perf_session *self, return ops->attr(event, self); case PERF_RECORD_HEADER_EVENT_TYPE: return ops->event_type(event, self); + case PERF_RECORD_HEADER_TRACING_DATA: + /* setup for reading amidst mmap */ + lseek(self->fd, offset + head, SEEK_SET); + return ops->tracing_data(event, self); default: self->unknown_events++; return -1; diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 0dac1f4..0739ebb 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -46,7 +46,8 @@ struct perf_event_ops { throttle, unthrottle, attr, - event_type; + event_type, + tracing_data; }; struct perf_session *perf_session__new(const char *filename, int mode, bool force); diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c index 5ea8973..30cd9b5 100644 --- a/tools/perf/util/trace-event-info.c +++ b/tools/perf/util/trace-event-info.c @@ -154,10 +154,17 @@ static void put_tracing_file(char *file) free(file); } +static ssize_t calc_data_size; + static ssize_t write_or_die(const void *buf, size_t len) { int ret; + if (calc_data_size) { + calc_data_size += len; + return len; + } + ret = write(output_fd, buf, len); if (ret < 0) die("writing to '%s'", output_file); @@ -526,3 +533,20 @@ int read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events) return 0; } + +ssize_t read_tracing_data_size(int fd, struct perf_event_attr *pattrs, + int nb_events) +{ + ssize_t size; + int err = 0; + + calc_data_size = 1; + err = read_tracing_data(fd, pattrs, nb_events); + size = calc_data_size - 1; + calc_data_size = 0; + + if (err < 0) + return err; + + return size; +} diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c index 7cd1193..44889c9 100644 --- a/tools/perf/util/trace-event-read.c +++ b/tools/perf/util/trace-event-read.c @@ -50,14 +50,37 @@ static int long_size; static unsigned long page_size; +static ssize_t calc_data_size; + +static int do_read(int fd, void *buf, int size) +{ + int rsize = size; + + while (size) { + int ret = read(fd, buf, size); + + if (ret <= 0) + return -1; + + size -= ret; + buf += ret; + } + + return rsize; +} + static int read_or_die(void *data, int size) { int r; - r = read(input_fd, data, size); - if (r != size) + r = do_read(input_fd, data, size); + if (r <= 0) die("reading input file (size expected=%d received=%d)", size, r); + + if (calc_data_size) + calc_data_size += r; + return r; } @@ -82,56 +105,28 @@ static char *read_string(void) char buf[BUFSIZ]; char *str = NULL; int size = 0; - int i; off_t r; + char c; for (;;) { - r = read(input_fd, buf, BUFSIZ); + r = read(input_fd, &c, 1); if (r < 0) die("reading input file"); if (!r) die("no data"); - for (i = 0; i < r; i++) { - if (!buf[i]) - break; - } - if (i < r) - break; + buf[size++] = c; - if (str) { - size += BUFSIZ; - str = realloc(str, size); - if (!str) - die("malloc of size %d", size); - memcpy(str + (size - BUFSIZ), buf, BUFSIZ); - } else { - size = BUFSIZ; - str = malloc_or_die(size); - memcpy(str, buf, size); - } + if (!c) + break; } - /* trailing \0: */ - i++; - - /* move the file descriptor to the end of the string */ - r = lseek(input_fd, -(r - i), SEEK_CUR); - if (r == (off_t)-1) - die("lseek"); - - if (str) { - size += i; - str = realloc(str, size); - if (!str) - die("malloc of size %d", size); - memcpy(str + (size - i), buf, i); - } else { - size = i; - str = malloc_or_die(i); - memcpy(str, buf, i); - } + if (calc_data_size) + calc_data_size += size; + + str = malloc_or_die(size); + memcpy(str, buf, size); return str; } @@ -459,7 +454,7 @@ struct record *trace_read_data(int cpu) return data; } -void trace_report(int fd) +ssize_t trace_report(int fd) { char buf[BUFSIZ]; char test[] = { 23, 8, 68 }; @@ -467,6 +462,9 @@ void trace_report(int fd) int show_version = 0; int show_funcs = 0; int show_printk = 0; + ssize_t size; + + calc_data_size = 1; input_fd = fd; @@ -499,14 +497,17 @@ void trace_report(int fd) read_proc_kallsyms(); read_ftrace_printk(); + size = calc_data_size - 1; + calc_data_size = 0; + if (show_funcs) { print_funcs(); - return; + return size; } if (show_printk) { print_printk(); - return; + return size; } - return; + return size; } diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h index 81f2fd2..1f45d46 100644 --- a/tools/perf/util/trace-event.h +++ b/tools/perf/util/trace-event.h @@ -163,7 +163,7 @@ struct record *trace_read_data(int cpu); void parse_set_info(int nr_cpus, int long_sz); -void trace_report(int fd); +ssize_t trace_report(int fd); void *malloc_or_die(unsigned int size); @@ -259,6 +259,8 @@ void *raw_field_ptr(struct event *event, const char *name, void *data); unsigned long long eval_flag(const char *flag); int read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events); +ssize_t read_tracing_data_size(int fd, struct perf_event_attr *pattrs, + int nb_events); /* taken from kernel/trace/trace.h */ enum trace_flag_type { -- cgit v0.10.2 From c7929e4727e8ff2d6fc8327188820e3b1c2f1dc3 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Thu, 1 Apr 2010 23:59:22 -0500 Subject: perf: Convert perf header build_ids into build_id events Bypasses the build_id perf header code and replaces it with a synthesized event and processing function that accomplishes the same thing, used when reading/writing perf data to/from a pipe. Signed-off-by: Tom Zanussi Acked-by: Thomas Gleixner Cc: fweisbec@gmail.com Cc: rostedt@goodmis.org Cc: k-keiichi@bx.jp.nec.com Cc: acme@ghostprotocols.net LKML-Reference: <1270184365-8281-9-git-send-email-tzanussi@gmail.com> Signed-off-by: Ingo Molnar diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 3775abe..0bde31b 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -426,10 +426,19 @@ static int process_buildids(void) static void atexit_header(void) { - session->header.data_size += bytes_written; + if (!pipe_output) { + session->header.data_size += bytes_written; - process_buildids(); - perf_header__write(&session->header, output, true); + process_buildids(); + perf_header__write(&session->header, output, true); + } else { + int err; + + err = event__synthesize_build_ids(process_synthesized_event, + session); + if (err < 0) + pr_err("Couldn't synthesize build ids.\n"); + } } static int __cmd_record(int argc, const char **argv) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 76f03a7..7da5fb3 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -270,6 +270,7 @@ static struct perf_event_ops event_ops = { .attr = event__process_attr, .event_type = event__process_event_type, .tracing_data = event__process_tracing_data, + .build_id = event__process_build_id, }; extern volatile int session_done; diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 1509744..1ee1e30 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -107,6 +107,7 @@ static struct perf_event_ops event_ops = { .attr = event__process_attr, .event_type = event__process_event_type, .tracing_data = event__process_tracing_data, + .build_id = event__process_build_id, }; extern volatile int session_done; diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index b896a17..e5740ea 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -87,6 +87,7 @@ enum perf_header_event_type { /* above any possible kernel type */ PERF_RECORD_HEADER_ATTR = 64, PERF_RECORD_HEADER_EVENT_TYPE = 65, PERF_RECORD_HEADER_TRACING_DATA = 66, + PERF_RECORD_HEADER_BUILD_ID = 67, PERF_RECORD_HEADER_MAX }; @@ -125,6 +126,7 @@ typedef union event_union { struct attr_event attr; struct event_type_event event_type; struct tracing_data_event tracing_data; + struct build_id_event build_id; } event_t; struct events_stats { diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index c6874ec..628173b 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -986,3 +986,93 @@ int event__process_tracing_data(event_t *self, return size_read + padding; } + +int event__synthesize_build_id(struct dso *pos, u16 misc, + event__handler_t process, + struct perf_session *session) +{ + event_t ev; + size_t len; + int err = 0; + + if (!pos->hit) + return err; + + memset(&ev, 0, sizeof(ev)); + + len = pos->long_name_len + 1; + len = ALIGN(len, NAME_ALIGN); + memcpy(&ev.build_id.build_id, pos->build_id, sizeof(pos->build_id)); + ev.build_id.header.type = PERF_RECORD_HEADER_BUILD_ID; + ev.build_id.header.misc = misc; + ev.build_id.header.size = sizeof(ev.build_id) + len; + memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len); + + err = process(&ev, session); + + return err; +} + +static int __event_synthesize_build_ids(struct list_head *head, u16 misc, + event__handler_t process, + struct perf_session *session) +{ + struct dso *pos; + + dsos__for_each_with_build_id(pos, head) { + int err; + if (!pos->hit) + continue; + + err = event__synthesize_build_id(pos, misc, process, session); + if (err < 0) + return err; + } + + return 0; +} + +int event__synthesize_build_ids(event__handler_t process, + struct perf_session *session) +{ + int err; + + if (!dsos__read_build_ids(true)) + return 0; + + err = __event_synthesize_build_ids(&dsos__kernel, + PERF_RECORD_MISC_KERNEL, + process, session); + if (err == 0) + err = __event_synthesize_build_ids(&dsos__user, + PERF_RECORD_MISC_USER, + process, session); + + if (err < 0) { + pr_debug("failed to synthesize build ids\n"); + return err; + } + + dsos__cache_build_ids(); + + return 0; +} + +int event__process_build_id(event_t *self, + struct perf_session *session __unused) +{ + struct list_head *head = &dsos__user; + struct dso *dso; + + if (self->build_id.header.misc & PERF_RECORD_MISC_KERNEL) + head = &dsos__kernel; + + dso = __dsos__findnew(head, self->build_id.filename); + if (dso != NULL) { + dso__set_build_id(dso, &self->build_id.build_id); + if (head == &dsos__kernel && self->build_id.filename[0] == '[') + dso->kernel = 1; + } + + return 0; +} diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index 3ed3d98..4214e23 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h @@ -118,4 +118,11 @@ int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs, int event__process_tracing_data(event_t *self, struct perf_session *session); +int event__synthesize_build_id(struct dso *pos, u16 misc, + event__handler_t process, + struct perf_session *session); +int event__synthesize_build_ids(event__handler_t process, + struct perf_session *session); +int event__process_build_id(event_t *self, struct perf_session *session); + #endif /* __PERF_HEADER_H */ diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 1516c40..0fdf3eb 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -206,6 +206,8 @@ static void perf_event_ops__fill_defaults(struct perf_event_ops *handler) handler->event_type = process_event_stub; if (handler->tracing_data == NULL) handler->tracing_data = process_event_stub; + if (handler->build_id == NULL) + handler->build_id = process_event_stub; } static const char *event__name[] = { @@ -222,6 +224,7 @@ static const char *event__name[] = { [PERF_RECORD_HEADER_ATTR] = "ATTR", [PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE", [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA", + [PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID", }; unsigned long event__total[PERF_RECORD_HEADER_MAX]; @@ -332,6 +335,7 @@ static event__swap_op event__swap_ops[] = { [PERF_RECORD_HEADER_ATTR] = event__attr_swap, [PERF_RECORD_HEADER_EVENT_TYPE] = event__event_type_swap, [PERF_RECORD_HEADER_TRACING_DATA] = event__tracing_data_swap, + [PERF_RECORD_HEADER_BUILD_ID] = NULL, [PERF_RECORD_HEADER_MAX] = NULL, }; @@ -380,6 +384,8 @@ static int perf_session__process_event(struct perf_session *self, /* setup for reading amidst mmap */ lseek(self->fd, offset + head, SEEK_SET); return ops->tracing_data(event, self); + case PERF_RECORD_HEADER_BUILD_ID: + return ops->build_id(event, self); default: self->unknown_events++; return -1; diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 0739ebb..0ac14d4 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -47,7 +47,8 @@ struct perf_event_ops { unthrottle, attr, event_type, - tracing_data; + tracing_data, + build_id; }; struct perf_session *perf_session__new(const char *filename, int mode, bool force); -- cgit v0.10.2 From 47902f3611b392209e2a412bf7ec02dca95e666d Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Thu, 1 Apr 2010 23:59:23 -0500 Subject: perf trace/scripting: Add rwtop and sctop scripts A couple of scripts, one in Python and the other in Perl, that demonstrate 'live mode' tracing. For each, the output of the perf event stream is fed continuously to the script, which continuously aggregates the data and reports the current results every 3 seconds, or at the optionally specified interval. After the current results are displayed, the aggregations are cleared and the cycle begins anew. To run the scripts, simply pipe the output of the 'perf trace record' step as input to the corresponding 'perf trace report' step, using '-' as the filename to -o and -i: $ perf trace record sctop -o - | perf trace report sctop -i - Also adds clear_term() utility functions to the Util.pm and Util.py utility modules, for use by any script to clear the screen. Signed-off-by: Tom Zanussi Acked-by: Thomas Gleixner Cc: fweisbec@gmail.com Cc: rostedt@goodmis.org Cc: k-keiichi@bx.jp.nec.com Cc: acme@ghostprotocols.net LKML-Reference: <1270184365-8281-10-git-send-email-tzanussi@gmail.com> Signed-off-by: Ingo Molnar diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Util.pm b/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Util.pm index f869c48..d94b40c 100644 --- a/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Util.pm +++ b/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Util.pm @@ -15,6 +15,7 @@ our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT = qw( avg nsecs nsecs_secs nsecs_nsecs nsecs_usecs print_nsecs +clear_term ); our $VERSION = '0.01'; @@ -55,6 +56,11 @@ sub nsecs_str { return $str; } +sub clear_term +{ + print "\x1b[H\x1b[2J"; +} + 1; __END__ =head1 NAME diff --git a/tools/perf/scripts/perl/bin/rwtop-record b/tools/perf/scripts/perl/bin/rwtop-record new file mode 100644 index 0000000..63976bf --- /dev/null +++ b/tools/perf/scripts/perl/bin/rwtop-record @@ -0,0 +1,2 @@ +#!/bin/bash +perf record -c 1 -f -a -M -R -e syscalls:sys_enter_read -e syscalls:sys_exit_read -e syscalls:sys_enter_write -e syscalls:sys_exit_write $@ diff --git a/tools/perf/scripts/perl/bin/rwtop-report b/tools/perf/scripts/perl/bin/rwtop-report new file mode 100644 index 0000000..93e698c --- /dev/null +++ b/tools/perf/scripts/perl/bin/rwtop-report @@ -0,0 +1,23 @@ +#!/bin/bash +# description: system-wide r/w top +# args: [interval] +n_args=0 +for i in "$@" +do + if expr match "$i" "-" > /dev/null ; then + break + fi + n_args=$(( $n_args + 1 )) +done +if [ "$n_args" -gt 1 ] ; then + echo "usage: rwtop-report [interval]" + exit +fi +if [ "$n_args" -gt 0 ] ; then + interval=$1 + shift +fi +perf trace $@ -s ~/libexec/perf-core/scripts/perl/rwtop.pl $interval + + + diff --git a/tools/perf/scripts/perl/rwtop.pl b/tools/perf/scripts/perl/rwtop.pl new file mode 100644 index 0000000..ec2ab49 --- /dev/null +++ b/tools/perf/scripts/perl/rwtop.pl @@ -0,0 +1,177 @@ +#!/usr/bin/perl -w +# (c) 2010, Tom Zanussi +# Licensed under the terms of the GNU GPL License version 2 + +# read/write top +# +# Periodically displays system-wide r/w call activity, broken down by +# pid. If an [interval] arg is specified, the display will be +# refreshed every [interval] seconds. The default interval is 3 +# seconds. + +use 5.010000; +use strict; +use warnings; + +use lib "$ENV{'PERF_EXEC_PATH'}/scripts/perl/Perf-Trace-Util/lib"; +use lib "./Perf-Trace-Util/lib"; +use Perf::Trace::Core; +use Perf::Trace::Util; + +my $default_interval = 3; +my $nlines = 20; +my $print_thread; + +my %reads; +my %writes; + +my $interval = shift; +if (!$interval) { + $interval = $default_interval; +} + +sub syscalls::sys_exit_read +{ + my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs, + $common_pid, $common_comm, + $nr, $ret) = @_; + + if ($ret > 0) { + $reads{$common_pid}{bytes_read} += $ret; + } else { + if (!defined ($reads{$common_pid}{bytes_read})) { + $reads{$common_pid}{bytes_read} = 0; + } + $reads{$common_pid}{errors}{$ret}++; + } +} + +sub syscalls::sys_enter_read +{ + my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs, + $common_pid, $common_comm, + $nr, $fd, $buf, $count) = @_; + + $reads{$common_pid}{bytes_requested} += $count; + $reads{$common_pid}{total_reads}++; + $reads{$common_pid}{comm} = $common_comm; +} + +sub syscalls::sys_exit_write +{ + my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs, + $common_pid, $common_comm, + $nr, $ret) = @_; + + if ($ret <= 0) { + $writes{$common_pid}{errors}{$ret}++; + } +} + +sub syscalls::sys_enter_write +{ + my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs, + $common_pid, $common_comm, + $nr, $fd, $buf, $count) = @_; + + $writes{$common_pid}{bytes_written} += $count; + $writes{$common_pid}{total_writes}++; + $writes{$common_pid}{comm} = $common_comm; +} + +sub trace_begin +{ + $SIG{ALRM} = \&print_totals; + alarm 1; +} + +sub trace_end +{ + print_unhandled(); + print_totals(); +} + +sub print_totals +{ + my $count; + + $count = 0; + + clear_term(); + + printf("\nread counts by pid:\n\n"); + + printf("%6s %20s %10s %10s %10s\n", "pid", "comm", + "# reads", "bytes_req", "bytes_read"); + printf("%6s %-20s %10s %10s %10s\n", "------", "--------------------", + "----------", "----------", "----------"); + + foreach my $pid (sort {$reads{$b}{bytes_read} <=> + $reads{$a}{bytes_read}} keys %reads) { + my $comm = $reads{$pid}{comm}; + my $total_reads = $reads{$pid}{total_reads}; + my $bytes_requested = $reads{$pid}{bytes_requested}; + my $bytes_read = $reads{$pid}{bytes_read}; + + printf("%6s %-20s %10s %10s %10s\n", $pid, $comm, + $total_reads, $bytes_requested, $bytes_read); + + if (++$count == $nlines) { + last; + } + } + + $count = 0; + + printf("\nwrite counts by pid:\n\n"); + + printf("%6s %20s %10s %13s\n", "pid", "comm", + "# writes", "bytes_written"); + printf("%6s %-20s %10s %13s\n", "------", "--------------------", + "----------", "-------------"); + + foreach my $pid (sort {$writes{$b}{bytes_written} <=> + $writes{$a}{bytes_written}} keys %writes) { + my $comm = $writes{$pid}{comm}; + my $total_writes = $writes{$pid}{total_writes}; + my $bytes_written = $writes{$pid}{bytes_written}; + + printf("%6s %-20s %10s %13s\n", $pid, $comm, + $total_writes, $bytes_written); + + if (++$count == $nlines) { + last; + } + } + + %reads = (); + %writes = (); + alarm $interval; +} + +my %unhandled; + +sub print_unhandled +{ + if ((scalar keys %unhandled) == 0) { + return; + } + + print "\nunhandled events:\n\n"; + + printf("%-40s %10s\n", "event", "count"); + printf("%-40s %10s\n", "----------------------------------------", + "-----------"); + + foreach my $event_name (keys %unhandled) { + printf("%-40s %10d\n", $event_name, $unhandled{$event_name}); + } +} + +sub trace_unhandled +{ + my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs, + $common_pid, $common_comm) = @_; + + $unhandled{$event_name}++; +} diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py index 83e9143..9689bc0 100644 --- a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py +++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py @@ -23,3 +23,6 @@ def nsecs_nsecs(nsecs): def nsecs_str(nsecs): str = "%5u.%09u" % (nsecs_secs(nsecs), nsecs_nsecs(nsecs)), return str + +def clear_term(): + print("\x1b[H\x1b[2J") diff --git a/tools/perf/scripts/python/bin/sctop-record b/tools/perf/scripts/python/bin/sctop-record new file mode 100644 index 0000000..27ccffa --- /dev/null +++ b/tools/perf/scripts/python/bin/sctop-record @@ -0,0 +1,2 @@ +#!/bin/bash +perf record -c 1 -f -a -M -R -e raw_syscalls:sys_enter $@ diff --git a/tools/perf/scripts/python/bin/sctop-report b/tools/perf/scripts/python/bin/sctop-report new file mode 100644 index 0000000..b01c842 --- /dev/null +++ b/tools/perf/scripts/python/bin/sctop-report @@ -0,0 +1,24 @@ +#!/bin/bash +# description: syscall top +# args: [comm] [interval] +n_args=0 +for i in "$@" +do + if expr match "$i" "-" > /dev/null ; then + break + fi + n_args=$(( $n_args + 1 )) +done +if [ "$n_args" -gt 2 ] ; then + echo "usage: sctop-report [comm] [interval]" + exit +fi +if [ "$n_args" -gt 1 ] ; then + comm=$1 + interval=$2 + shift 2 +elif [ "$n_args" -gt 0 ] ; then + interval=$1 + shift +fi +perf trace $@ -s ~/libexec/perf-core/scripts/python/sctop.py $comm $interval diff --git a/tools/perf/scripts/python/sctop.py b/tools/perf/scripts/python/sctop.py new file mode 100644 index 0000000..6cafad4 --- /dev/null +++ b/tools/perf/scripts/python/sctop.py @@ -0,0 +1,78 @@ +# system call top +# (c) 2010, Tom Zanussi +# Licensed under the terms of the GNU GPL License version 2 +# +# Periodically displays system-wide system call totals, broken down by +# syscall. If a [comm] arg is specified, only syscalls called by +# [comm] are displayed. If an [interval] arg is specified, the display +# will be refreshed every [interval] seconds. The default interval is +# 3 seconds. + +import thread +import time +import os +import sys + +sys.path.append(os.environ['PERF_EXEC_PATH'] + \ + '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') + +from perf_trace_context import * +from Core import * +from Util import * + +usage = "perf trace -s syscall-counts.py [comm] [interval]\n"; + +for_comm = None +default_interval = 3 +interval = default_interval + +if len(sys.argv) > 3: + sys.exit(usage) + +if len(sys.argv) > 2: + for_comm = sys.argv[1] + interval = int(sys.argv[2]) +elif len(sys.argv) > 1: + try: + interval = int(sys.argv[1]) + except ValueError: + for_comm = sys.argv[1] + interval = default_interval + +syscalls = autodict() + +def trace_begin(): + thread.start_new_thread(print_syscall_totals, (interval,)) + pass + +def raw_syscalls__sys_enter(event_name, context, common_cpu, + common_secs, common_nsecs, common_pid, common_comm, + id, args): + if for_comm is not None: + if common_comm != for_comm: + return + try: + syscalls[id] += 1 + except TypeError: + syscalls[id] = 1 + +def print_syscall_totals(interval): + while 1: + clear_term() + if for_comm is not None: + print "\nsyscall events for %s:\n\n" % (for_comm), + else: + print "\nsyscall events:\n\n", + + print "%-40s %10s\n" % ("event", "count"), + print "%-40s %10s\n" % ("----------------------------------------", \ + "----------"), + + for id, val in sorted(syscalls.iteritems(), key = lambda(k, v): (v, k), \ + reverse = True): + try: + print "%-40d %10d\n" % (id, val), + except TypeError: + pass + syscalls.clear() + time.sleep(interval) -- cgit v0.10.2 From 00b21a01935892a2b97613f10300434998f45093 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Thu, 1 Apr 2010 23:59:24 -0500 Subject: perf trace/scripting: Enable scripting shell scripts for live mode It should be possible to run any perf trace script in 'live mode'. This requires being able to pass in e.g. '-i -' or other args, which the current shell scripts aren't equipped to handle. In a few cases, there are required or optional args that also need special handling. This patch makes changes the current set of shell scripts as necessary. Signed-off-by: Tom Zanussi Acked-by: Thomas Gleixner Cc: fweisbec@gmail.com Cc: rostedt@goodmis.org Cc: k-keiichi@bx.jp.nec.com Cc: acme@ghostprotocols.net LKML-Reference: <1270184365-8281-11-git-send-email-tzanussi@gmail.com> Signed-off-by: Ingo Molnar diff --git a/tools/perf/scripts/perl/bin/failed-syscalls-record b/tools/perf/scripts/perl/bin/failed-syscalls-record index f8885d3..6ad9b8f 100644 --- a/tools/perf/scripts/perl/bin/failed-syscalls-record +++ b/tools/perf/scripts/perl/bin/failed-syscalls-record @@ -1,2 +1,2 @@ #!/bin/bash -perf record -c 1 -f -a -M -R -e raw_syscalls:sys_exit +perf record -c 1 -f -a -M -R -e raw_syscalls:sys_exit $@ diff --git a/tools/perf/scripts/perl/bin/failed-syscalls-report b/tools/perf/scripts/perl/bin/failed-syscalls-report index 8bfc660..f634608 100644 --- a/tools/perf/scripts/perl/bin/failed-syscalls-report +++ b/tools/perf/scripts/perl/bin/failed-syscalls-report @@ -1,4 +1,10 @@ #!/bin/bash # description: system-wide failed syscalls # args: [comm] -perf trace -s ~/libexec/perf-core/scripts/perl/failed-syscalls.pl $1 +if [ $# -gt 0 ] ; then + if ! expr match "$1" "-" ; then + comm=$1 + shift + fi +fi +perf trace $@ -s ~/libexec/perf-core/scripts/perl/failed-syscalls.pl $comm diff --git a/tools/perf/scripts/perl/bin/rw-by-file-record b/tools/perf/scripts/perl/bin/rw-by-file-record index b25056e..a828679 100644 --- a/tools/perf/scripts/perl/bin/rw-by-file-record +++ b/tools/perf/scripts/perl/bin/rw-by-file-record @@ -1,2 +1,3 @@ #!/bin/bash -perf record -c 1 -f -a -M -R -e syscalls:sys_enter_read -e syscalls:sys_enter_write +perf record -c 1 -f -a -M -R -e syscalls:sys_enter_read -e syscalls:sys_enter_write $@ + diff --git a/tools/perf/scripts/perl/bin/rw-by-file-report b/tools/perf/scripts/perl/bin/rw-by-file-report index eddb9cc..d83070b 100644 --- a/tools/perf/scripts/perl/bin/rw-by-file-report +++ b/tools/perf/scripts/perl/bin/rw-by-file-report @@ -1,7 +1,13 @@ #!/bin/bash # description: r/w activity for a program, by file # args: -perf trace -s ~/libexec/perf-core/scripts/perl/rw-by-file.pl $1 +if [ $# -lt 1 ] ; then + echo "usage: rw-by-file " + exit +fi +comm=$1 +shift +perf trace $@ -s ~/libexec/perf-core/scripts/perl/rw-by-file.pl $comm diff --git a/tools/perf/scripts/perl/bin/rw-by-pid-record b/tools/perf/scripts/perl/bin/rw-by-pid-record index 8903979..63976bf 100644 --- a/tools/perf/scripts/perl/bin/rw-by-pid-record +++ b/tools/perf/scripts/perl/bin/rw-by-pid-record @@ -1,2 +1,2 @@ #!/bin/bash -perf record -c 1 -f -a -M -R -e syscalls:sys_enter_read -e syscalls:sys_exit_read -e syscalls:sys_enter_write -e syscalls:sys_exit_write +perf record -c 1 -f -a -M -R -e syscalls:sys_enter_read -e syscalls:sys_exit_read -e syscalls:sys_enter_write -e syscalls:sys_exit_write $@ diff --git a/tools/perf/scripts/perl/bin/rw-by-pid-report b/tools/perf/scripts/perl/bin/rw-by-pid-report index 7f44c25..7ef4698 100644 --- a/tools/perf/scripts/perl/bin/rw-by-pid-report +++ b/tools/perf/scripts/perl/bin/rw-by-pid-report @@ -1,6 +1,6 @@ #!/bin/bash # description: system-wide r/w activity -perf trace -s ~/libexec/perf-core/scripts/perl/rw-by-pid.pl +perf trace $@ -s ~/libexec/perf-core/scripts/perl/rw-by-pid.pl diff --git a/tools/perf/scripts/perl/bin/wakeup-latency-record b/tools/perf/scripts/perl/bin/wakeup-latency-record index 6abedda..9c0cf58 100644 --- a/tools/perf/scripts/perl/bin/wakeup-latency-record +++ b/tools/perf/scripts/perl/bin/wakeup-latency-record @@ -1,5 +1,5 @@ #!/bin/bash -perf record -c 1 -f -a -M -R -e sched:sched_switch -e sched:sched_wakeup +perf record -c 1 -f -a -M -R -e sched:sched_switch -e sched:sched_wakeup $@ diff --git a/tools/perf/scripts/perl/bin/wakeup-latency-report b/tools/perf/scripts/perl/bin/wakeup-latency-report index fce3adc..a0d898f 100644 --- a/tools/perf/scripts/perl/bin/wakeup-latency-report +++ b/tools/perf/scripts/perl/bin/wakeup-latency-report @@ -1,6 +1,6 @@ #!/bin/bash # description: system-wide min/max/avg wakeup latency -perf trace -s ~/libexec/perf-core/scripts/perl/wakeup-latency.pl +perf trace $@ -s ~/libexec/perf-core/scripts/perl/wakeup-latency.pl diff --git a/tools/perf/scripts/perl/bin/workqueue-stats-record b/tools/perf/scripts/perl/bin/workqueue-stats-record index fce6637..c2a1a94 100644 --- a/tools/perf/scripts/perl/bin/workqueue-stats-record +++ b/tools/perf/scripts/perl/bin/workqueue-stats-record @@ -1,2 +1,2 @@ #!/bin/bash -perf record -c 1 -f -a -M -R -e workqueue:workqueue_creation -e workqueue:workqueue_destruction -e workqueue:workqueue_execution -e workqueue:workqueue_insertion +perf record -c 1 -f -a -M -R -e workqueue:workqueue_creation -e workqueue:workqueue_destruction -e workqueue:workqueue_execution -e workqueue:workqueue_insertion $@ diff --git a/tools/perf/scripts/perl/bin/workqueue-stats-report b/tools/perf/scripts/perl/bin/workqueue-stats-report index 71cfbd1..3508113 100644 --- a/tools/perf/scripts/perl/bin/workqueue-stats-report +++ b/tools/perf/scripts/perl/bin/workqueue-stats-report @@ -1,6 +1,6 @@ #!/bin/bash # description: workqueue stats (ins/exe/create/destroy) -perf trace -s ~/libexec/perf-core/scripts/perl/workqueue-stats.pl +perf trace $@ -s ~/libexec/perf-core/scripts/perl/workqueue-stats.pl diff --git a/tools/perf/scripts/python/bin/failed-syscalls-by-pid-record b/tools/perf/scripts/python/bin/failed-syscalls-by-pid-record index f8885d3..6ad9b8f 100644 --- a/tools/perf/scripts/python/bin/failed-syscalls-by-pid-record +++ b/tools/perf/scripts/python/bin/failed-syscalls-by-pid-record @@ -1,2 +1,2 @@ #!/bin/bash -perf record -c 1 -f -a -M -R -e raw_syscalls:sys_exit +perf record -c 1 -f -a -M -R -e raw_syscalls:sys_exit $@ diff --git a/tools/perf/scripts/python/bin/failed-syscalls-by-pid-report b/tools/perf/scripts/python/bin/failed-syscalls-by-pid-report index 1e0c0a8..8c128ef 100644 --- a/tools/perf/scripts/python/bin/failed-syscalls-by-pid-report +++ b/tools/perf/scripts/python/bin/failed-syscalls-by-pid-report @@ -1,4 +1,10 @@ #!/bin/bash # description: system-wide failed syscalls, by pid # args: [comm] -perf trace -s ~/libexec/perf-core/scripts/python/failed-syscalls-by-pid.py $1 +if [ $# -gt 0 ] ; then + if ! expr match "$1" "-" ; then + comm=$1 + shift + fi +fi +perf trace $@ -s ~/libexec/perf-core/scripts/python/failed-syscalls-by-pid.py $comm diff --git a/tools/perf/scripts/python/bin/syscall-counts-by-pid-record b/tools/perf/scripts/python/bin/syscall-counts-by-pid-record index 45a8c50..27ccffa 100644 --- a/tools/perf/scripts/python/bin/syscall-counts-by-pid-record +++ b/tools/perf/scripts/python/bin/syscall-counts-by-pid-record @@ -1,2 +1,2 @@ #!/bin/bash -perf record -c 1 -f -a -M -R -e raw_syscalls:sys_enter +perf record -c 1 -f -a -M -R -e raw_syscalls:sys_enter $@ diff --git a/tools/perf/scripts/python/bin/syscall-counts-by-pid-report b/tools/perf/scripts/python/bin/syscall-counts-by-pid-report index f8044d1..c53362e 100644 --- a/tools/perf/scripts/python/bin/syscall-counts-by-pid-report +++ b/tools/perf/scripts/python/bin/syscall-counts-by-pid-report @@ -1,4 +1,10 @@ #!/bin/bash # description: system-wide syscall counts, by pid # args: [comm] -perf trace -s ~/libexec/perf-core/scripts/python/syscall-counts-by-pid.py $1 +if [ $# -gt 0 ] ; then + if ! expr match "$1" "-" ; then + comm=$1 + shift + fi +fi +perf trace $@ -s ~/libexec/perf-core/scripts/python/syscall-counts-by-pid.py $comm diff --git a/tools/perf/scripts/python/bin/syscall-counts-record b/tools/perf/scripts/python/bin/syscall-counts-record index 45a8c50..27ccffa 100644 --- a/tools/perf/scripts/python/bin/syscall-counts-record +++ b/tools/perf/scripts/python/bin/syscall-counts-record @@ -1,2 +1,2 @@ #!/bin/bash -perf record -c 1 -f -a -M -R -e raw_syscalls:sys_enter +perf record -c 1 -f -a -M -R -e raw_syscalls:sys_enter $@ diff --git a/tools/perf/scripts/python/bin/syscall-counts-report b/tools/perf/scripts/python/bin/syscall-counts-report index a366aa61..8c21552 100644 --- a/tools/perf/scripts/python/bin/syscall-counts-report +++ b/tools/perf/scripts/python/bin/syscall-counts-report @@ -1,4 +1,10 @@ #!/bin/bash # description: system-wide syscall counts # args: [comm] -perf trace -s ~/libexec/perf-core/scripts/python/syscall-counts.py $1 +if [ $# -gt 0 ] ; then + if ! expr match "$1" "-" ; then + comm=$1 + shift + fi +fi +perf trace $@ -s ~/libexec/perf-core/scripts/python/syscall-counts.py $comm -- cgit v0.10.2 From a0cccc2e8e9fb16cbed3a117b30e3fbac3092ee3 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Thu, 1 Apr 2010 23:59:25 -0500 Subject: perf trace: Invoke live mode automatically if record/report not specified Currently, live mode is invoked by explicitly invoking the record and report sides and connecting them with a pipe e.g. $ perf trace record rwtop -o - | perf trace report rwtop 5 -i - In terms of usability, it's not that bad, but it does require the user to type and remember more than necessary. This patch allows the user to accomplish the same thing without specifying the separate record/report steps or the pipe. So the same command as above can be accomplished more simply as: $ perf trace rwtop 5 Notice that the '-i -' and '-o -' aren't required in this case - they're added internally, and that any extra arguments are passed along to the report script (but not to the record script). The overall effect is that any of the scripts listed in 'perf trace -l' can now be used directly in live mode, with the expected arguments, by simply specifying the script and args to 'perf trace'. Signed-off-by: Tom Zanussi Acked-by: Thomas Gleixner Cc: fweisbec@gmail.com Cc: rostedt@goodmis.org Cc: k-keiichi@bx.jp.nec.com Cc: acme@ghostprotocols.net LKML-Reference: <1270184365-8281-12-git-send-email-tzanussi@gmail.com> Signed-off-by: Ingo Molnar diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 1ee1e30..2eefb33 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -561,6 +561,65 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used) suffix = REPORT_SUFFIX; } + if (!suffix && argc >= 2 && strncmp(argv[1], "-", strlen("-")) != 0) { + char *record_script_path, *report_script_path; + int live_pipe[2]; + pid_t pid; + + record_script_path = get_script_path(argv[1], RECORD_SUFFIX); + if (!record_script_path) { + fprintf(stderr, "record script not found\n"); + return -1; + } + + report_script_path = get_script_path(argv[1], REPORT_SUFFIX); + if (!report_script_path) { + fprintf(stderr, "report script not found\n"); + return -1; + } + + if (pipe(live_pipe) < 0) { + perror("failed to create pipe"); + exit(-1); + } + + pid = fork(); + if (pid < 0) { + perror("failed to fork"); + exit(-1); + } + + if (!pid) { + dup2(live_pipe[1], 1); + close(live_pipe[0]); + + __argv = malloc(5 * sizeof(const char *)); + __argv[0] = "/bin/sh"; + __argv[1] = record_script_path; + __argv[2] = "-o"; + __argv[3] = "-"; + __argv[4] = NULL; + + execvp("/bin/sh", (char **)__argv); + exit(-1); + } + + dup2(live_pipe[0], 0); + close(live_pipe[1]); + + __argv = malloc((argc + 3) * sizeof(const char *)); + __argv[0] = "/bin/sh"; + __argv[1] = report_script_path; + for (i = 2; i < argc; i++) + __argv[i] = argv[i]; + __argv[i++] = "-i"; + __argv[i++] = "-"; + __argv[i++] = NULL; + + execvp("/bin/sh", (char **)__argv); + exit(-1); + } + if (suffix) { script_path = get_script_path(argv[2], suffix); if (!script_path) { -- cgit v0.10.2 From b0c4c898833250ed143e615c32ea1be0e2155fdc Mon Sep 17 00:00:00 2001 From: Hartley Sweeten Date: Fri, 2 Apr 2010 18:04:47 +0100 Subject: ARM: 6025/1: vic: factor out common init code This factors out the common initialization code for the two vic vendors into easier maintainable functions. Tested-by: Linus Walleij Tested-by: Alessandro Rubini Cc: Andrea Gallo Cc: Ben Dooks Signed-off-by: H Hartley Sweeten Signed-off-by: Russell King diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c index 1cf999a..ba65f6e 100644 --- a/arch/arm/common/vic.c +++ b/arch/arm/common/vic.c @@ -266,13 +266,53 @@ static int vic_set_wake(unsigned int irq, unsigned int on) #endif /* CONFIG_PM */ static struct irq_chip vic_chip = { - .name = "VIC", - .ack = vic_ack_irq, - .mask = vic_mask_irq, - .unmask = vic_unmask_irq, - .set_wake = vic_set_wake, + .name = "VIC", + .ack = vic_ack_irq, + .mask = vic_mask_irq, + .unmask = vic_unmask_irq, + .set_wake = vic_set_wake, }; +static void __init vic_disable(void __iomem *base) +{ + writel(0, base + VIC_INT_SELECT); + writel(0, base + VIC_INT_ENABLE); + writel(~0, base + VIC_INT_ENABLE_CLEAR); + writel(0, base + VIC_IRQ_STATUS); + writel(0, base + VIC_ITCR); + writel(~0, base + VIC_INT_SOFT_CLEAR); +} + +static void __init vic_clear_interrupts(void __iomem *base) +{ + unsigned int i; + + writel(0, base + VIC_PL190_VECT_ADDR); + for (i = 0; i < 19; i++) { + unsigned int value; + + value = readl(base + VIC_PL190_VECT_ADDR); + writel(value, base + VIC_PL190_VECT_ADDR); + } +} + +static void __init vic_set_irq_sources(void __iomem *base, + unsigned int irq_start, u32 vic_sources) +{ + unsigned int i; + + for (i = 0; i < 32; i++) { + if (vic_sources & (1 << i)) { + unsigned int irq = irq_start + i; + + set_irq_chip(irq, &vic_chip); + set_irq_chip_data(irq, base); + set_irq_handler(irq, handle_level_irq); + set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); + } + } +} + /* * The PL190 cell from ARM has been modified by ST to handle 64 interrupts. * The original cell has 32 interrupts, while the modified one has 64, @@ -287,13 +327,7 @@ static void __init vic_init_st(void __iomem *base, unsigned int irq_start, int vic_2nd_block = ((unsigned long)base & ~PAGE_MASK) != 0; /* Disable all interrupts initially. */ - - writel(0, base + VIC_INT_SELECT); - writel(0, base + VIC_INT_ENABLE); - writel(~0, base + VIC_INT_ENABLE_CLEAR); - writel(0, base + VIC_IRQ_STATUS); - writel(0, base + VIC_ITCR); - writel(~0, base + VIC_INT_SOFT_CLEAR); + vic_disable(base); /* * Make sure we clear all existing interrupts. The vector registers @@ -302,13 +336,8 @@ static void __init vic_init_st(void __iomem *base, unsigned int irq_start, * the second base address, which is 0x20 in the page */ if (vic_2nd_block) { - writel(0, base + VIC_PL190_VECT_ADDR); - for (i = 0; i < 19; i++) { - unsigned int value; + vic_clear_interrupts(base); - value = readl(base + VIC_PL190_VECT_ADDR); - writel(value, base + VIC_PL190_VECT_ADDR); - } /* ST has 16 vectors as well, but we don't enable them by now */ for (i = 0; i < 16; i++) { void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4); @@ -318,16 +347,7 @@ static void __init vic_init_st(void __iomem *base, unsigned int irq_start, writel(32, base + VIC_PL190_DEF_VECT_ADDR); } - for (i = 0; i < 32; i++) { - if (vic_sources & (1 << i)) { - unsigned int irq = irq_start + i; - - set_irq_chip(irq, &vic_chip); - set_irq_chip_data(irq, base); - set_irq_handler(irq, handle_level_irq); - set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); - } - } + vic_set_irq_sources(base, irq_start, vic_sources); } /** @@ -365,37 +385,14 @@ void __init vic_init(void __iomem *base, unsigned int irq_start, } /* Disable all interrupts initially. */ + vic_disable(base); - writel(0, base + VIC_INT_SELECT); - writel(0, base + VIC_INT_ENABLE); - writel(~0, base + VIC_INT_ENABLE_CLEAR); - writel(0, base + VIC_IRQ_STATUS); - writel(0, base + VIC_ITCR); - writel(~0, base + VIC_INT_SOFT_CLEAR); - - /* - * Make sure we clear all existing interrupts - */ - writel(0, base + VIC_PL190_VECT_ADDR); - for (i = 0; i < 19; i++) { - unsigned int value; - - value = readl(base + VIC_PL190_VECT_ADDR); - writel(value, base + VIC_PL190_VECT_ADDR); - } + /* Make sure we clear all existing interrupts */ + vic_clear_interrupts(base); vic_init2(base); - for (i = 0; i < 32; i++) { - if (vic_sources & (1 << i)) { - unsigned int irq = irq_start + i; - - set_irq_chip(irq, &vic_chip); - set_irq_chip_data(irq, base); - set_irq_handler(irq, handle_level_irq); - set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); - } - } + vic_set_irq_sources(base, irq_start, vic_sources); vic_pm_register(base, irq_start, resume_sources); } -- cgit v0.10.2 From b370e082e7c4bd47195b2ec117ceeadd9286d8c0 Mon Sep 17 00:00:00 2001 From: Hartley Sweeten Date: Thu, 18 Mar 2010 18:04:06 +0100 Subject: ARM: 5992/1: ep93xx: pass platform startup data as __initdata A number of the peripherals for the ep93xx are registered at startup using platform_data that is passed from the board init code to the core code. This data is then copied to a local static variable in the core code. Since the data is copied, the original data can be marked as __initdata and discarded after startup is complete. This adds the __initdata tag to all the appropriate data in the various ep93xx board init's. Specifically, all the struct ep93xx_eth_data, struct ep93xxfb_mach_info, and struct i2c_gpio_platform_data. Also, document the various registration functions and note what data should be marked as __initdata. While here, also cleanup a couple over zealous whitespace tabs. Signed-off-by: H Hartley Sweeten Acked-by: Ryan Mallon Signed-off-by: Russell King diff --git a/arch/arm/mach-ep93xx/adssphere.c b/arch/arm/mach-ep93xx/adssphere.c index caf6d51..3a1a855 100644 --- a/arch/arm/mach-ep93xx/adssphere.c +++ b/arch/arm/mach-ep93xx/adssphere.c @@ -41,7 +41,7 @@ static struct platform_device adssphere_flash = { .resource = &adssphere_flash_resource, }; -static struct ep93xx_eth_data adssphere_eth_data = { +static struct ep93xx_eth_data __initdata adssphere_eth_data = { .phy_id = 1, }; diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 90fb591..5b1d836 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -330,6 +330,10 @@ static struct platform_device ep93xx_ohci_device = { .resource = ep93xx_ohci_resources, }; + +/************************************************************************* + * EP93xx ethernet peripheral handling + *************************************************************************/ static struct ep93xx_eth_data ep93xx_eth_data; static struct resource ep93xx_eth_resource[] = { @@ -354,6 +358,12 @@ static struct platform_device ep93xx_eth_device = { .resource = ep93xx_eth_resource, }; +/** + * ep93xx_register_eth - Register the built-in ethernet platform device. + * @data: platform specific ethernet configuration (__initdata) + * @copy_addr: flag indicating that the MAC address should be copied + * from the IndAd registers (as programmed by the bootloader) + */ void __init ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr) { if (copy_addr) @@ -370,11 +380,19 @@ void __init ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr) static struct i2c_gpio_platform_data ep93xx_i2c_data; static struct platform_device ep93xx_i2c_device = { - .name = "i2c-gpio", - .id = 0, - .dev.platform_data = &ep93xx_i2c_data, + .name = "i2c-gpio", + .id = 0, + .dev = { + .platform_data = &ep93xx_i2c_data, + }, }; +/** + * ep93xx_register_i2c - Register the i2c platform device. + * @data: platform specific i2c-gpio configuration (__initdata) + * @devices: platform specific i2c bus device information (__initdata) + * @num: the number of devices on the i2c bus + */ void __init ep93xx_register_i2c(struct i2c_gpio_platform_data *data, struct i2c_board_info *devices, int num) { @@ -404,11 +422,11 @@ void __init ep93xx_register_i2c(struct i2c_gpio_platform_data *data, *************************************************************************/ static struct gpio_led ep93xx_led_pins[] = { { - .name = "platform:grled", - .gpio = EP93XX_GPIO_LINE_GRLED, + .name = "platform:grled", + .gpio = EP93XX_GPIO_LINE_GRLED, }, { - .name = "platform:rdled", - .gpio = EP93XX_GPIO_LINE_RDLED, + .name = "platform:rdled", + .gpio = EP93XX_GPIO_LINE_RDLED, }, }; @@ -528,7 +546,7 @@ static struct platform_device ep93xx_fb_device = { .name = "ep93xx-fb", .id = -1, .dev = { - .platform_data = &ep93xxfb_data, + .platform_data = &ep93xxfb_data, .coherent_dma_mask = DMA_BIT_MASK(32), .dma_mask = &ep93xx_fb_device.dev.coherent_dma_mask, }, @@ -536,6 +554,10 @@ static struct platform_device ep93xx_fb_device = { .resource = ep93xx_fb_resource, }; +/** + * ep93xx_register_fb - Register the framebuffer platform device. + * @data: platform specific framebuffer configuration (__initdata) + */ void __init ep93xx_register_fb(struct ep93xxfb_mach_info *data) { ep93xxfb_data = *data; @@ -546,6 +568,8 @@ void __init ep93xx_register_fb(struct ep93xxfb_mach_info *data) /************************************************************************* * EP93xx matrix keypad peripheral handling *************************************************************************/ +static struct ep93xx_keypad_platform_data ep93xx_keypad_data; + static struct resource ep93xx_keypad_resource[] = { { .start = EP93XX_KEY_MATRIX_PHYS_BASE, @@ -559,15 +583,22 @@ static struct resource ep93xx_keypad_resource[] = { }; static struct platform_device ep93xx_keypad_device = { - .name = "ep93xx-keypad", - .id = -1, - .num_resources = ARRAY_SIZE(ep93xx_keypad_resource), - .resource = ep93xx_keypad_resource, + .name = "ep93xx-keypad", + .id = -1, + .dev = { + .platform_data = &ep93xx_keypad_data, + }, + .num_resources = ARRAY_SIZE(ep93xx_keypad_resource), + .resource = ep93xx_keypad_resource, }; +/** + * ep93xx_register_keypad - Register the keypad platform device. + * @data: platform specific keypad configuration (__initdata) + */ void __init ep93xx_register_keypad(struct ep93xx_keypad_platform_data *data) { - ep93xx_keypad_device.dev.platform_data = data; + ep93xx_keypad_data = *data; platform_device_register(&ep93xx_keypad_device); } diff --git a/arch/arm/mach-ep93xx/edb93xx.c b/arch/arm/mach-ep93xx/edb93xx.c index d22d67a..3884182 100644 --- a/arch/arm/mach-ep93xx/edb93xx.c +++ b/arch/arm/mach-ep93xx/edb93xx.c @@ -74,7 +74,7 @@ static void __init edb93xx_register_flash(void) } } -static struct ep93xx_eth_data edb93xx_eth_data = { +static struct ep93xx_eth_data __initdata edb93xx_eth_data = { .phy_id = 1, }; @@ -82,7 +82,7 @@ static struct ep93xx_eth_data edb93xx_eth_data = { /************************************************************************* * EDB93xx i2c peripheral handling *************************************************************************/ -static struct i2c_gpio_platform_data edb93xx_i2c_gpio_data = { +static struct i2c_gpio_platform_data __initdata edb93xx_i2c_gpio_data = { .sda_pin = EP93XX_GPIO_LINE_EEDAT, .sda_is_open_drain = 0, .scl_pin = EP93XX_GPIO_LINE_EECLK, diff --git a/arch/arm/mach-ep93xx/gesbc9312.c b/arch/arm/mach-ep93xx/gesbc9312.c index 3da7ca8..a809618 100644 --- a/arch/arm/mach-ep93xx/gesbc9312.c +++ b/arch/arm/mach-ep93xx/gesbc9312.c @@ -41,7 +41,7 @@ static struct platform_device gesbc9312_flash = { .resource = &gesbc9312_flash_resource, }; -static struct ep93xx_eth_data gesbc9312_eth_data = { +static struct ep93xx_eth_data __initdata gesbc9312_eth_data = { .phy_id = 1, }; diff --git a/arch/arm/mach-ep93xx/micro9.c b/arch/arm/mach-ep93xx/micro9.c index c33360e8..1cc911b 100644 --- a/arch/arm/mach-ep93xx/micro9.c +++ b/arch/arm/mach-ep93xx/micro9.c @@ -80,7 +80,7 @@ static void __init micro9_register_flash(void) /************************************************************************* * Micro9 Ethernet *************************************************************************/ -static struct ep93xx_eth_data micro9_eth_data = { +static struct ep93xx_eth_data __initdata micro9_eth_data = { .phy_id = 0x1f, }; diff --git a/arch/arm/mach-ep93xx/simone.c b/arch/arm/mach-ep93xx/simone.c index cd93990..388aec9 100644 --- a/arch/arm/mach-ep93xx/simone.c +++ b/arch/arm/mach-ep93xx/simone.c @@ -49,17 +49,17 @@ static struct platform_device simone_flash = { }, }; -static struct ep93xx_eth_data simone_eth_data = { +static struct ep93xx_eth_data __initdata simone_eth_data = { .phy_id = 1, }; -static struct ep93xxfb_mach_info simone_fb_info = { +static struct ep93xxfb_mach_info __initdata simone_fb_info = { .num_modes = EP93XXFB_USE_MODEDB, .bpp = 16, .flags = EP93XXFB_USE_SDCSN0 | EP93XXFB_PCLK_FALLING, }; -static struct i2c_gpio_platform_data simone_i2c_gpio_data = { +static struct i2c_gpio_platform_data __initdata simone_i2c_gpio_data = { .sda_pin = EP93XX_GPIO_LINE_EEDAT, .sda_is_open_drain = 0, .scl_pin = EP93XX_GPIO_LINE_EECLK, diff --git a/arch/arm/mach-ep93xx/snappercl15.c b/arch/arm/mach-ep93xx/snappercl15.c index 51134b0..38deaee 100644 --- a/arch/arm/mach-ep93xx/snappercl15.c +++ b/arch/arm/mach-ep93xx/snappercl15.c @@ -125,11 +125,11 @@ static struct platform_device snappercl15_nand_device = { .num_resources = ARRAY_SIZE(snappercl15_nand_resource), }; -static struct ep93xx_eth_data snappercl15_eth_data = { +static struct ep93xx_eth_data __initdata snappercl15_eth_data = { .phy_id = 1, }; -static struct i2c_gpio_platform_data snappercl15_i2c_gpio_data = { +static struct i2c_gpio_platform_data __initdata snappercl15_i2c_gpio_data = { .sda_pin = EP93XX_GPIO_LINE_EEDAT, .sda_is_open_drain = 0, .scl_pin = EP93XX_GPIO_LINE_EECLK, @@ -145,7 +145,7 @@ static struct i2c_board_info __initdata snappercl15_i2c_data[] = { }, }; -static struct ep93xxfb_mach_info snappercl15_fb_info = { +static struct ep93xxfb_mach_info __initdata snappercl15_fb_info = { .num_modes = EP93XXFB_USE_MODEDB, .bpp = 16, }; diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c index fac1ec7..9553031 100644 --- a/arch/arm/mach-ep93xx/ts72xx.c +++ b/arch/arm/mach-ep93xx/ts72xx.c @@ -186,7 +186,7 @@ static struct platform_device ts72xx_wdt_device = { .resource = ts72xx_wdt_resources, }; -static struct ep93xx_eth_data ts72xx_eth_data = { +static struct ep93xx_eth_data __initdata ts72xx_eth_data = { .phy_id = 1, }; -- cgit v0.10.2 From 99e6a23adfadc2da2006f3715c4332c3bf502c07 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Sat, 27 Mar 2010 12:05:14 +0100 Subject: ARM: 5998/1: ep93xx: added chip revision reading function Added a new function: ep93xx_chip_revision() which reads chip revision from the sysconfig register. Signed-off-by: Mika Westerberg Acked-by: H Hartley Sweeten Signed-off-by: Russell King diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 5b1d836..8d3f77e 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -222,6 +222,20 @@ void ep93xx_devcfg_set_clear(unsigned int set_bits, unsigned int clear_bits) } EXPORT_SYMBOL(ep93xx_devcfg_set_clear); +/** + * ep93xx_chip_revision() - returns the EP93xx chip revision + * + * See for more information. + */ +unsigned int ep93xx_chip_revision(void) +{ + unsigned int v; + + v = __raw_readl(EP93XX_SYSCON_SYSCFG); + v &= EP93XX_SYSCON_SYSCFG_REV_MASK; + v >>= EP93XX_SYSCON_SYSCFG_REV_SHIFT; + return v; +} /************************************************************************* * EP93xx peripheral handling diff --git a/arch/arm/mach-ep93xx/include/mach/platform.h b/arch/arm/mach-ep93xx/include/mach/platform.h index c6dc14db..b663390 100644 --- a/arch/arm/mach-ep93xx/include/mach/platform.h +++ b/arch/arm/mach-ep93xx/include/mach/platform.h @@ -33,6 +33,14 @@ static inline void ep93xx_devcfg_clear_bits(unsigned int bits) ep93xx_devcfg_set_clear(0x00, bits); } +#define EP93XX_CHIP_REV_D0 3 +#define EP93XX_CHIP_REV_D1 4 +#define EP93XX_CHIP_REV_E0 5 +#define EP93XX_CHIP_REV_E1 6 +#define EP93XX_CHIP_REV_E2 7 + +unsigned int ep93xx_chip_revision(void); + void ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr); void ep93xx_register_i2c(struct i2c_gpio_platform_data *data, struct i2c_board_info *devices, int num); -- cgit v0.10.2 From 9b404b7cc3b066c57078b87f475562c37a74b814 Mon Sep 17 00:00:00 2001 From: Christian Glindkamp Date: Tue, 13 Apr 2010 14:55:10 +0100 Subject: ARM: 6054/1: AT91: taskit PortuxG20 and Stamp9G20 board support Both boards share the same board file, as the PortuxG20 is basically an SBC based on the Stamp9G20. Signed-off-by: Christian Glindkamp Acked-by: Andrew Victor Signed-off-by: Russell King diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 2db43a5..2c27300 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -360,6 +360,19 @@ config MACH_CPU9G20 Select this if you are using a Eukrea Electromatique's CPU9G20 Board +config MACH_PORTUXG20 + bool "taskit PortuxG20" + help + Select this if you are using taskit's PortuxG20. + + +config MACH_STAMP9G20 + bool "taskit Stamp9G20 CPU module" + help + Select this if you are using taskit's Stamp9G20 CPU module on its + evaluation board. + + endif # ---------------------------------------------------------- diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 027dd57..1df9ee1 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -63,6 +63,8 @@ obj-$(CONFIG_MACH_AT91SAM9RLEK) += board-sam9rlek.o obj-$(CONFIG_MACH_AT91SAM9G20EK) += board-sam9g20ek.o obj-$(CONFIG_MACH_AT91SAM9G20EK_2MMC) += board-sam9g20ek-2slot-mmc.o obj-$(CONFIG_MACH_CPU9G20) += board-cpu9krea.o +obj-$(CONFIG_MACH_STAMP9G20) += board-stamp9g20.o +obj-$(CONFIG_MACH_PORTUXG20) += board-stamp9g20.o # AT91SAM9G45 board-specific support obj-$(CONFIG_MACH_AT91SAM9G45EKES) += board-sam9m10g45ek.o diff --git a/arch/arm/mach-at91/board-stamp9g20.c b/arch/arm/mach-at91/board-stamp9g20.c new file mode 100644 index 0000000..8795827 --- /dev/null +++ b/arch/arm/mach-at91/board-stamp9g20.c @@ -0,0 +1,315 @@ +/* + * Copyright (C) 2010 Christian Glindkamp + * taskit GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "sam9_smc.h" +#include "generic.h" + + +static void __init portuxg20_map_io(void) +{ + /* Initialize processor: 18.432 MHz crystal */ + at91sam9260_initialize(18432000); + + /* DGBU on ttyS0. (Rx & Tx only) */ + at91_register_uart(0, 0, 0); + + /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */ + at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS + | ATMEL_UART_DTR | ATMEL_UART_DSR + | ATMEL_UART_DCD | ATMEL_UART_RI); + + /* USART1 on ttyS2. (Rx, Tx, CTS, RTS) */ + at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS); + + /* USART2 on ttyS3. (Rx, Tx, CTS, RTS) */ + at91_register_uart(AT91SAM9260_ID_US2, 3, ATMEL_UART_CTS | ATMEL_UART_RTS); + + /* USART4 on ttyS5. (Rx, Tx only) */ + at91_register_uart(AT91SAM9260_ID_US4, 5, 0); + + /* USART5 on ttyS6. (Rx, Tx only) */ + at91_register_uart(AT91SAM9260_ID_US5, 6, 0); + + /* set serial console to ttyS0 (ie, DBGU) */ + at91_set_serial_console(0); +} + +static void __init stamp9g20_map_io(void) +{ + /* Initialize processor: 18.432 MHz crystal */ + at91sam9260_initialize(18432000); + + /* DGBU on ttyS0. (Rx & Tx only) */ + at91_register_uart(0, 0, 0); + + /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */ + at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS + | ATMEL_UART_DTR | ATMEL_UART_DSR + | ATMEL_UART_DCD | ATMEL_UART_RI); + + /* set serial console to ttyS0 (ie, DBGU) */ + at91_set_serial_console(0); +} + +static void __init init_irq(void) +{ + at91sam9260_init_interrupts(NULL); +} + + +/* + * NAND flash + */ +static struct atmel_nand_data __initdata nand_data = { + .ale = 21, + .cle = 22, + .rdy_pin = AT91_PIN_PC13, + .enable_pin = AT91_PIN_PC14, + .bus_width_16 = 0, +}; + +static struct sam9_smc_config __initdata nand_smc_config = { + .ncs_read_setup = 0, + .nrd_setup = 2, + .ncs_write_setup = 0, + .nwe_setup = 2, + + .ncs_read_pulse = 4, + .nrd_pulse = 4, + .ncs_write_pulse = 4, + .nwe_pulse = 4, + + .read_cycle = 7, + .write_cycle = 7, + + .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8, + .tdf_cycles = 3, +}; + +static void __init add_device_nand(void) +{ + /* configure chip-select 3 (NAND) */ + sam9_smc_configure(3, &nand_smc_config); + + at91_add_device_nand(&nand_data); +} + + +/* + * MCI (SD/MMC) + * det_pin, wp_pin and vcc_pin are not connected + */ +#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE) +static struct mci_platform_data __initdata mmc_data = { + .slot[0] = { + .bus_width = 4, + }, +}; +#else +static struct at91_mmc_data __initdata mmc_data = { + .slot_b = 0, + .wire4 = 1, +}; +#endif + + +/* + * USB Host port + */ +static struct at91_usbh_data __initdata usbh_data = { + .ports = 2, +}; + + +/* + * USB Device port + */ +static struct at91_udc_data __initdata portuxg20_udc_data = { + .vbus_pin = AT91_PIN_PC7, + .pullup_pin = 0, /* pull-up driven by UDC */ +}; + +static struct at91_udc_data __initdata stamp9g20_udc_data = { + .vbus_pin = AT91_PIN_PA22, + .pullup_pin = 0, /* pull-up driven by UDC */ +}; + + +/* + * MACB Ethernet device + */ +static struct at91_eth_data __initdata macb_data = { + .phy_irq_pin = AT91_PIN_PA28, + .is_rmii = 1, +}; + + +/* + * LEDs + */ +static struct gpio_led portuxg20_leds[] = { + { + .name = "LED2", + .gpio = AT91_PIN_PC5, + .default_trigger = "none", + }, { + .name = "LED3", + .gpio = AT91_PIN_PC4, + .default_trigger = "none", + }, { + .name = "LED4", + .gpio = AT91_PIN_PC10, + .default_trigger = "heartbeat", + } +}; + +static struct gpio_led stamp9g20_leds[] = { + { + .name = "D8", + .gpio = AT91_PIN_PB18, + .active_low = 1, + .default_trigger = "none", + }, { + .name = "D9", + .gpio = AT91_PIN_PB19, + .active_low = 1, + .default_trigger = "none", + }, { + .name = "D10", + .gpio = AT91_PIN_PB20, + .active_low = 1, + .default_trigger = "heartbeat", + } +}; + + +/* + * SPI devices + */ +static struct spi_board_info portuxg20_spi_devices[] = { + { + .modalias = "spidev", + .chip_select = 0, + .max_speed_hz = 1 * 1000 * 1000, + .bus_num = 0, + }, { + .modalias = "spidev", + .chip_select = 0, + .max_speed_hz = 1 * 1000 * 1000, + .bus_num = 1, + }, +}; + + +/* + * Dallas 1-Wire + */ +static struct w1_gpio_platform_data w1_gpio_pdata = { + .pin = AT91_PIN_PA29, + .is_open_drain = 1, +}; + +static struct platform_device w1_device = { + .name = "w1-gpio", + .id = -1, + .dev.platform_data = &w1_gpio_pdata, +}; + +void add_w1(void) +{ + at91_set_GPIO_periph(w1_gpio_pdata.pin, 1); + at91_set_multi_drive(w1_gpio_pdata.pin, 1); + platform_device_register(&w1_device); +} + + +static void __init generic_board_init(void) +{ + /* Serial */ + at91_add_device_serial(); + /* NAND */ + add_device_nand(); + /* MMC */ +#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE) + at91_add_device_mci(0, &mmc_data); +#else + at91_add_device_mmc(0, &mmc_data); +#endif + /* USB Host */ + at91_add_device_usbh(&usbh_data); + /* Ethernet */ + at91_add_device_eth(&macb_data); + /* I2C */ + at91_add_device_i2c(NULL, 0); + /* W1 */ + add_w1(); +} + +static void __init portuxg20_board_init(void) +{ + generic_board_init(); + /* SPI */ + at91_add_device_spi(portuxg20_spi_devices, ARRAY_SIZE(portuxg20_spi_devices)); + /* USB Device */ + at91_add_device_udc(&portuxg20_udc_data); + /* LEDs */ + at91_gpio_leds(portuxg20_leds, ARRAY_SIZE(portuxg20_leds)); +} + +static void __init stamp9g20_board_init(void) +{ + generic_board_init(); + /* USB Device */ + at91_add_device_udc(&stamp9g20_udc_data); + /* LEDs */ + at91_gpio_leds(stamp9g20_leds, ARRAY_SIZE(stamp9g20_leds)); +} + +MACHINE_START(PORTUXG20, "taskit PortuxG20") + /* Maintainer: taskit GmbH */ + .phys_io = AT91_BASE_SYS, + .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, + .boot_params = AT91_SDRAM_BASE + 0x100, + .timer = &at91sam926x_timer, + .map_io = portuxg20_map_io, + .init_irq = init_irq, + .init_machine = portuxg20_board_init, +MACHINE_END + +MACHINE_START(STAMP9G20, "taskit Stamp9G20") + /* Maintainer: taskit GmbH */ + .phys_io = AT91_BASE_SYS, + .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, + .boot_params = AT91_SDRAM_BASE + 0x100, + .timer = &at91sam926x_timer, + .map_io = stamp9g20_map_io, + .init_irq = init_irq, + .init_machine = stamp9g20_board_init, +MACHINE_END -- cgit v0.10.2 From 67be0b8dbaffc5ecdcc4dae3c8824a5197204c55 Mon Sep 17 00:00:00 2001 From: Christian Glindkamp Date: Tue, 13 Apr 2010 14:55:27 +0100 Subject: ARM: 6055/1: AT91: add defconfig for taskit PortuxG20 and Stamp9G20 Support for both boards can easily be built into one kernel image, so there is no need to add one defconfig for each of them. Signed-off-by: Christian Glindkamp Acked-by: Andrew Victor Signed-off-by: Russell King diff --git a/arch/arm/configs/stamp9g20_defconfig b/arch/arm/configs/stamp9g20_defconfig new file mode 100644 index 0000000..06a8293 --- /dev/null +++ b/arch/arm/configs/stamp9g20_defconfig @@ -0,0 +1,1456 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.34-rc1 +# Wed Mar 17 16:38:03 2010 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_HAVE_PROC_CPU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_CONSTRUCTORS=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_BZIP2 is not set +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +# CONFIG_TREE_RCU is not set +CONFIG_TREE_PREEMPT_RCU=y +# CONFIG_TINY_RCU is not set +# CONFIG_RCU_TRACE is not set +CONFIG_RCU_FANOUT=32 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +# CONFIG_SYSFS_DEPRECATED_V2 is not set +# CONFIG_RELAY is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +# CONFIG_NET_NS is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +CONFIG_RD_LZO=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +# CONFIG_PERF_EVENTS is not set +# CONFIG_PERF_COUNTERS is not set +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_COMPAT_BRK=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_CLK=y + +# +# GCOV-based kernel profiling +# +# CONFIG_SLOW_WORK is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_BLOCK=y +# CONFIG_LBDAF is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_DEADLINE is not set +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_INLINE_SPIN_TRYLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK is not set +# CONFIG_INLINE_SPIN_LOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK_IRQ is not set +# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set +# CONFIG_INLINE_SPIN_UNLOCK is not set +# CONFIG_INLINE_SPIN_UNLOCK_BH is not set +# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set +# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_READ_TRYLOCK is not set +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set +# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set +# CONFIG_INLINE_READ_UNLOCK is not set +# CONFIG_INLINE_READ_UNLOCK_BH is not set +# CONFIG_INLINE_READ_UNLOCK_IRQ is not set +# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_WRITE_TRYLOCK is not set +# CONFIG_INLINE_WRITE_LOCK is not set +# CONFIG_INLINE_WRITE_LOCK_BH is not set +# CONFIG_INLINE_WRITE_LOCK_IRQ is not set +# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set +# CONFIG_INLINE_WRITE_UNLOCK is not set +# CONFIG_INLINE_WRITE_UNLOCK_BH is not set +# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set +# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set +# CONFIG_MUTEX_SPIN_ON_OWNER is not set +CONFIG_FREEZER=y + +# +# System Type +# +CONFIG_MMU=y +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +CONFIG_ARCH_AT91=y +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_STMP3XXX is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_NOMADIK is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_DOVE is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_NUC93X is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5PC1XX is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_BCMRING is not set +# CONFIG_ARCH_U8500 is not set +CONFIG_HAVE_AT91_USART3=y +CONFIG_HAVE_AT91_USART4=y +CONFIG_HAVE_AT91_USART5=y + +# +# Atmel AT91 System-on-Chip +# +# CONFIG_ARCH_AT91RM9200 is not set +# CONFIG_ARCH_AT91SAM9260 is not set +# CONFIG_ARCH_AT91SAM9261 is not set +# CONFIG_ARCH_AT91SAM9G10 is not set +# CONFIG_ARCH_AT91SAM9263 is not set +# CONFIG_ARCH_AT91SAM9RL is not set +CONFIG_ARCH_AT91SAM9G20=y +# CONFIG_ARCH_AT91SAM9G45 is not set +# CONFIG_ARCH_AT91CAP9 is not set +# CONFIG_ARCH_AT572D940HF is not set +# CONFIG_ARCH_AT91X40 is not set +CONFIG_AT91_PMC_UNIT=y + +# +# AT91SAM9G20 Board Type +# +# CONFIG_MACH_AT91SAM9G20EK is not set +# CONFIG_MACH_AT91SAM9G20EK_2MMC is not set +# CONFIG_MACH_CPU9G20 is not set +CONFIG_MACH_PORTUXG20=y +CONFIG_MACH_STAMP9G20=y + +# +# AT91 Board Options +# + +# +# AT91 Feature Selections +# +CONFIG_AT91_PROGRAMMABLE_CLOCKS=y +CONFIG_AT91_SLOW_CLOCK=y +CONFIG_AT91_TIMER_HZ=100 +CONFIG_AT91_EARLY_DBGU=y +# CONFIG_AT91_EARLY_USART0 is not set +# CONFIG_AT91_EARLY_USART1 is not set +# CONFIG_AT91_EARLY_USART2 is not set +# CONFIG_AT91_EARLY_USART3 is not set +# CONFIG_AT91_EARLY_USART4 is not set +# CONFIG_AT91_EARLY_USART5 is not set + +# +# Processor Type +# +CONFIG_CPU_ARM926T=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5TJ=y +CONFIG_CPU_PABRT_LEGACY=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set +# CONFIG_CPU_CACHE_ROUND_ROBIN is not set +CONFIG_ARM_L1_CACHE_SHIFT=5 + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y +CONFIG_HZ=100 +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +# CONFIG_HIGHMEM is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=999999 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw" +# CONFIG_XIP_KERNEL is not set +CONFIG_KEXEC=y +CONFIG_ATAGS_PROC=y + +# +# CPU Power Management +# +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +# CONFIG_VFP is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +CONFIG_PM_SLEEP=y +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +# CONFIG_APM_EMULATION is not set +# CONFIG_PM_RUNTIME is not set +CONFIG_PM_OPS=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_WIRELESS is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_DEVTMPFS is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_TESTS is not set +CONFIG_MTD_CONCAT=y +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +CONFIG_MTD_DATAFLASH=y +# CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set +# CONFIG_MTD_DATAFLASH_OTP is not set +# CONFIG_MTD_M25P80 is not set +# CONFIG_MTD_SST25L is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_SMC is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +# CONFIG_MTD_NAND_GPIO is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +CONFIG_MTD_NAND_ATMEL=y +# CONFIG_MTD_NAND_ATMEL_ECC_HW is not set +CONFIG_MTD_NAND_ATMEL_ECC_SOFT=y +# CONFIG_MTD_NAND_ATMEL_ECC_NONE is not set +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_ALAUDA is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set + +# +# DRBD disabled because PROC_FS, INET or CONNECTOR not selected +# +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=8192 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MG_DISK is not set +# CONFIG_MISC_DEVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +# CONFIG_SCSI_LOWLEVEL is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +CONFIG_MACB=y +# CONFIG_AX88796 is not set +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set +# CONFIG_ENC28J60 is not set +# CONFIG_ETHOC is not set +# CONFIG_SMC911X is not set +# CONFIG_SMSC911X is not set +# CONFIG_DNET is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set +# CONFIG_KS8842 is not set +# CONFIG_KS8851 is not set +# CONFIG_KS8851_MLL is not set +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set +# CONFIG_WLAN is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set +# CONFIG_INPUT_SPARSEKMAP is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=320 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_ATMEL=y +CONFIG_SERIAL_ATMEL_CONSOLE=y +CONFIG_SERIAL_ATMEL_PDC=y +# CONFIG_SERIAL_ATMEL_TTYAT is not set +# CONFIG_SERIAL_MAX3100 is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_ALGOBIT=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_DESIGNWARE is not set +CONFIG_I2C_GPIO=y +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_STUB is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +CONFIG_SPI=y +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +CONFIG_SPI_ATMEL=y +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +CONFIG_SPI_SPIDEV=y +# CONFIG_SPI_TLE62X0 is not set + +# +# PPS support +# +# CONFIG_PPS is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO expanders: +# +# CONFIG_GPIO_IT8761E is not set + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_ADP5588 is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set + +# +# AC97 GPIO expanders: +# +CONFIG_W1=y + +# +# 1-wire Bus Masters +# +# CONFIG_W1_MASTER_DS2490 is not set +# CONFIG_W1_MASTER_DS2482 is not set +# CONFIG_W1_MASTER_DS1WM is not set +CONFIG_W1_MASTER_GPIO=y + +# +# 1-wire Slaves +# +CONFIG_W1_SLAVE_THERM=y +# CONFIG_W1_SLAVE_SMEM is not set +CONFIG_W1_SLAVE_DS2431=y +# CONFIG_W1_SLAVE_DS2433 is not set +# CONFIG_W1_SLAVE_DS2760 is not set +# CONFIG_W1_SLAVE_BQ27000 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_MAX63XX_WATCHDOG is not set +CONFIG_AT91SAM9X_WATCHDOG=y + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_TPS65010 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_MC13783 is not set +# CONFIG_AB3100_CORE is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_AB4500_CORE is not set +# CONFIG_REGULATOR is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_SOUND is not set +# CONFIG_HID_SUPPORT is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_DEVICE_CLASS is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set +CONFIG_USB_MON=y +# CONFIG_USB_WUSB is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HWA_HCD is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_GADGET_MUSB_HDRC is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_ISIGHTFW is not set +CONFIG_USB_GADGET=m +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GADGET_SELECTED=y +CONFIG_USB_GADGET_AT91=y +CONFIG_USB_AT91=m +# CONFIG_USB_GADGET_ATMEL_USBA is not set +# CONFIG_USB_GADGET_FSL_USB2 is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_PXA25X is not set +# CONFIG_USB_GADGET_R8A66597 is not set +# CONFIG_USB_GADGET_PXA27X is not set +# CONFIG_USB_GADGET_S3C_HSOTG is not set +# CONFIG_USB_GADGET_IMX is not set +# CONFIG_USB_GADGET_S3C2410 is not set +# CONFIG_USB_GADGET_M66592 is not set +# CONFIG_USB_GADGET_AMD5536UDC is not set +# CONFIG_USB_GADGET_FSL_QE is not set +# CONFIG_USB_GADGET_CI13XXX is not set +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_LANGWELL is not set +# CONFIG_USB_GADGET_DUMMY_HCD is not set +# CONFIG_USB_GADGET_DUALSPEED is not set +CONFIG_USB_ZERO=m +# CONFIG_USB_AUDIO is not set +CONFIG_USB_ETH=m +CONFIG_USB_ETH_RNDIS=y +# CONFIG_USB_ETH_EEM is not set +# CONFIG_USB_GADGETFS is not set +CONFIG_USB_FILE_STORAGE=m +# CONFIG_USB_FILE_STORAGE_TEST is not set +# CONFIG_USB_MASS_STORAGE is not set +CONFIG_USB_G_SERIAL=m +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_G_NOKIA is not set +# CONFIG_USB_G_MULTI is not set + +# +# OTG and related infrastructure +# +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_ULPI is not set +# CONFIG_NOP_USB_XCEIV is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_AT91 is not set +CONFIG_MMC_ATMELMCI=y +# CONFIG_MMC_SPI is not set +# CONFIG_MEMSTICK is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# +# CONFIG_LEDS_PCA9532 is not set +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_GPIO_PLATFORM=y +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_LT3593 is not set + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +# CONFIG_LEDS_TRIGGER_GPIO is not set +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y + +# +# iptables trigger is under Netfilter config (LED target) +# +# CONFIG_ACCESSIBILITY is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_PCF2123 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# +CONFIG_RTC_DRV_AT91SAM9=y +CONFIG_RTC_DRV_AT91SAM9_RTT=0 +CONFIG_RTC_DRV_AT91SAM9_GPBR=0 +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set + +# +# TI VLYNQ +# +# CONFIG_STAGING is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +# CONFIG_EXT4_FS is not set +CONFIG_JBD=y +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +# CONFIG_MSDOS_FS is not set +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +CONFIG_NLS_CODEPAGE_850=y +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +CONFIG_NLS_ISO8859_15=y +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=y +# CONFIG_DLM is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_KERNEL is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_FRAME_POINTER=y +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_ARM_UNWIND is not set +# CONFIG_DEBUG_USER is not set +# CONFIG_OC_ETM is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_DEFAULT_SECURITY_SELINUX is not set +# CONFIG_DEFAULT_SECURITY_SMACK is not set +# CONFIG_DEFAULT_SECURITY_TOMOYO is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +# CONFIG_CRYPTO is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_DECOMPRESS_LZO=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_NLATTR=y +CONFIG_GENERIC_ATOMIC64=y -- cgit v0.10.2 From a7e9c45219b2d40a80fbd1b7337cbecab85be2bd Mon Sep 17 00:00:00 2001 From: viresh kumar Date: Thu, 1 Apr 2010 12:30:19 +0100 Subject: ARM: 6010/1: ST SPEAr: Added basic header files for SPEAr3xx machine family Reviewed-by: Linus Walleij Signed-off-by: Viresh Kumar Signed-off-by: Russell King diff --git a/arch/arm/mach-spear3xx/include/mach/debug-macro.S b/arch/arm/mach-spear3xx/include/mach/debug-macro.S new file mode 100644 index 0000000..590519f --- /dev/null +++ b/arch/arm/mach-spear3xx/include/mach/debug-macro.S @@ -0,0 +1,14 @@ +/* + * arch/arm/mach-spear3xx/include/mach/debug-macro.S + * + * Debugging macro include header spear3xx machine family + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include diff --git a/arch/arm/mach-spear3xx/include/mach/entry-macro.S b/arch/arm/mach-spear3xx/include/mach/entry-macro.S new file mode 100644 index 0000000..947625d --- /dev/null +++ b/arch/arm/mach-spear3xx/include/mach/entry-macro.S @@ -0,0 +1,46 @@ +/* + * arch/arm/mach-spear3xx/include/mach/entry-macro.S + * + * Low-level IRQ helper macros for SPEAr3xx machine family + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include + + .macro disable_fiq + .endm + + .macro get_irqnr_preamble, base, tmp + .endm + + .macro arch_ret_to_user, tmp1, tmp2 + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + ldr \base, =VA_SPEAR3XX_ML1_VIC_BASE + ldr \irqstat, [\base, #VIC_IRQ_STATUS] @ get status + teq \irqstat, #0 + beq 1001f @ this will set/reset + @ zero register + /* + * Following code will find bit position of least significang + * bit set in irqstat, using following equation + * least significant bit set in n = (n & ~(n-1)) + */ + sub \tmp, \irqstat, #1 @ tmp = irqstat - 1 + mvn \tmp, \tmp @ tmp = ~tmp + and \irqstat, \irqstat, \tmp @ irqstat &= tmp + /* Now, irqstat is = bit no. of 1st bit set in vic irq status */ + clz \tmp, \irqstat @ tmp = leading zeros + rsb \irqnr, \tmp, #0x1F @ irqnr = 32 - tmp - 1 + +1001: /* EQ will be set if no irqs pending */ + .endm diff --git a/arch/arm/mach-spear3xx/include/mach/generic.h b/arch/arm/mach-spear3xx/include/mach/generic.h new file mode 100644 index 0000000..aeea845 --- /dev/null +++ b/arch/arm/mach-spear3xx/include/mach/generic.h @@ -0,0 +1,58 @@ +/* + * arch/arm/mach-spear3xx/generic.h + * + * SPEAr3XX machine family generic header file + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __MACH_GENERIC_H +#define __MACH_GENERIC_H + +#include +#include +#include +#include +#include + +/* + * Each GPT has 2 timer channels + * Following GPT channels will be used as clock source and clockevent + */ +#define SPEAR_GPT0_BASE SPEAR3XX_ML1_TMR_BASE +#define SPEAR_GPT0_CHAN0_IRQ IRQ_CPU_GPT1_1 +#define SPEAR_GPT0_CHAN1_IRQ IRQ_CPU_GPT1_2 + +/* Add spear3xx family device structure declarations here */ +extern struct amba_device gpio_device; +extern struct amba_device uart_device; +extern struct sys_timer spear_sys_timer; + +/* Add spear3xx family function declarations here */ +void __init spear3xx_map_io(void); +void __init spear3xx_init_irq(void); +void __init spear3xx_init(void); +void __init spear300_init(void); +void __init spear310_init(void); +void __init spear320_init(void); +void __init clk_init(void); + +/* Add spear300 machine device structure declarations here */ +#ifdef CONFIG_MACH_SPEAR300 +extern struct amba_device gpio1_device; +#endif /* CONFIG_MACH_SPEAR300 */ + +/* Add spear310 machine device structure declarations here */ +#ifdef CONFIG_MACH_SPEAR310 +#endif /* CONFIG_MACH_SPEAR310 */ + +/* Add spear320 machine device structure declarations here */ +#ifdef CONFIG_MACH_SPEAR320 +#endif /* CONFIG_MACH_SPEAR320 */ + +#endif /* __MACH_GENERIC_H */ diff --git a/arch/arm/mach-spear3xx/include/mach/gpio.h b/arch/arm/mach-spear3xx/include/mach/gpio.h new file mode 100644 index 0000000..451b208 --- /dev/null +++ b/arch/arm/mach-spear3xx/include/mach/gpio.h @@ -0,0 +1,19 @@ +/* + * arch/arm/mach-spear3xx/include/mach/gpio.h + * + * GPIO macros for SPEAr3xx machine family + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __MACH_GPIO_H +#define __MACH_GPIO_H + +#include + +#endif /* __MACH_GPIO_H */ diff --git a/arch/arm/mach-spear3xx/include/mach/hardware.h b/arch/arm/mach-spear3xx/include/mach/hardware.h new file mode 100644 index 0000000..4a86e6a --- /dev/null +++ b/arch/arm/mach-spear3xx/include/mach/hardware.h @@ -0,0 +1,20 @@ +/* + * arch/arm/mach-spear3xx/include/mach/hardware.h + * + * Hardware definitions for SPEAr3xx machine family + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __MACH_HARDWARE_H +#define __MACH_HARDWARE_H + +/* Vitual to physical translation of statically mapped space */ +#define IO_ADDRESS(x) (x | 0xF0000000) + +#endif /* __MACH_HARDWARE_H */ diff --git a/arch/arm/mach-spear3xx/include/mach/io.h b/arch/arm/mach-spear3xx/include/mach/io.h new file mode 100644 index 0000000..30cff8a --- /dev/null +++ b/arch/arm/mach-spear3xx/include/mach/io.h @@ -0,0 +1,19 @@ +/* + * arch/arm/mach-spear3xx/include/mach/io.h + * + * IO definitions for SPEAr3xx machine family + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __MACH_IO_H +#define __MACH_IO_H + +#include + +#endif /* __MACH_IO_H */ diff --git a/arch/arm/mach-spear3xx/include/mach/irqs.h b/arch/arm/mach-spear3xx/include/mach/irqs.h new file mode 100644 index 0000000..fe980e0 --- /dev/null +++ b/arch/arm/mach-spear3xx/include/mach/irqs.h @@ -0,0 +1,65 @@ +/* + * arch/arm/mach-spear3xx/include/mach/irqs.h + * + * IRQ helper macros for SPEAr3xx machine family + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __MACH_IRQS_H +#define __MACH_IRQS_H + +/* IRQ definitions */ +#define IRQ_HW_ACCEL_MOD_0 0 +#define IRQ_INTRCOMM_RAS_ARM 1 +#define IRQ_CPU_GPT1_1 2 +#define IRQ_CPU_GPT1_2 3 +#define IRQ_BASIC_GPT1_1 4 +#define IRQ_BASIC_GPT1_2 5 +#define IRQ_BASIC_GPT2_1 6 +#define IRQ_BASIC_GPT2_2 7 +#define IRQ_BASIC_DMA 8 +#define IRQ_BASIC_SMI 9 +#define IRQ_BASIC_RTC 10 +#define IRQ_BASIC_GPIO 11 +#define IRQ_BASIC_WDT 12 +#define IRQ_DDR_CONTROLLER 13 +#define IRQ_SYS_ERROR 14 +#define IRQ_WAKEUP_RCV 15 +#define IRQ_JPEG 16 +#define IRQ_IRDA 17 +#define IRQ_ADC 18 +#define IRQ_UART 19 +#define IRQ_SSP 20 +#define IRQ_I2C 21 +#define IRQ_MAC_1 22 +#define IRQ_MAC_2 23 +#define IRQ_USB_DEV 24 +#define IRQ_USB_H_OHCI_0 25 +#define IRQ_USB_H_EHCI_0 26 +#define IRQ_USB_H_EHCI_1 IRQ_USB_H_EHCI_0 +#define IRQ_USB_H_OHCI_1 27 +#define IRQ_GEN_RAS_1 28 +#define IRQ_GEN_RAS_2 29 +#define IRQ_GEN_RAS_3 30 +#define IRQ_HW_ACCEL_MOD_1 31 +#define IRQ_VIC_END 32 + +#define SPEAR_GPIO_INT_BASE IRQ_VIC_END + +#ifdef CONFIG_MACH_SPEAR300 +#define SPEAR_GPIO1_INT_BASE (SPEAR_GPIO_INT_BASE + 8) +#define SPEAR_GPIO_INT_END (SPEAR_GPIO1_INT_BASE + 8) +#else +#define SPEAR_GPIO_INT_END (SPEAR_GPIO_INT_BASE + 8) +#endif + +#define VIRTUAL_IRQS (SPEAR_GPIO_INT_END - IRQ_VIC_END) +#define NR_IRQS (IRQ_VIC_END + VIRTUAL_IRQS) + +#endif /* __MACH_IRQS_H */ diff --git a/arch/arm/mach-spear3xx/include/mach/memory.h b/arch/arm/mach-spear3xx/include/mach/memory.h new file mode 100644 index 0000000..5173522 --- /dev/null +++ b/arch/arm/mach-spear3xx/include/mach/memory.h @@ -0,0 +1,19 @@ +/* + * arch/arm/mach-spear3xx/include/mach/memory.h + * + * Memory map for SPEAr3xx machine family + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __MACH_MEMORY_H +#define __MACH_MEMORY_H + +#include + +#endif /* __MACH_MEMORY_H */ diff --git a/arch/arm/mach-spear3xx/include/mach/misc_regs.h b/arch/arm/mach-spear3xx/include/mach/misc_regs.h new file mode 100755 index 0000000..38d767a --- /dev/null +++ b/arch/arm/mach-spear3xx/include/mach/misc_regs.h @@ -0,0 +1,163 @@ +/* + * arch/arm/mach-spear3xx/include/mach/misc_regs.h + * + * Miscellaneous registers definitions for SPEAr3xx machine family + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __MACH_MISC_REGS_H +#define __MACH_MISC_REGS_H + +#include + +#define MISC_BASE VA_SPEAR3XX_ICM3_MISC_REG_BASE + +#define SOC_CFG_CTR ((unsigned int *)(MISC_BASE + 0x000)) +#define DIAG_CFG_CTR ((unsigned int *)(MISC_BASE + 0x004)) +#define PLL1_CTR ((unsigned int *)(MISC_BASE + 0x008)) +#define PLL1_FRQ ((unsigned int *)(MISC_BASE + 0x00C)) +#define PLL1_MOD ((unsigned int *)(MISC_BASE + 0x010)) +#define PLL2_CTR ((unsigned int *)(MISC_BASE + 0x014)) +/* PLL_CTR register masks */ +#define PLL_ENABLE 2 +#define PLL_MODE_SHIFT 4 +#define PLL_MODE_MASK 0x3 +#define PLL_MODE_NORMAL 0 +#define PLL_MODE_FRACTION 1 +#define PLL_MODE_DITH_DSB 2 +#define PLL_MODE_DITH_SSB 3 + +#define PLL2_FRQ ((unsigned int *)(MISC_BASE + 0x018)) +/* PLL FRQ register masks */ +#define PLL_DIV_N_SHIFT 0 +#define PLL_DIV_N_MASK 0xFF +#define PLL_DIV_P_SHIFT 8 +#define PLL_DIV_P_MASK 0x7 +#define PLL_NORM_FDBK_M_SHIFT 24 +#define PLL_NORM_FDBK_M_MASK 0xFF +#define PLL_DITH_FDBK_M_SHIFT 16 +#define PLL_DITH_FDBK_M_MASK 0xFFFF + +#define PLL2_MOD ((unsigned int *)(MISC_BASE + 0x01C)) +#define PLL_CLK_CFG ((unsigned int *)(MISC_BASE + 0x020)) +#define CORE_CLK_CFG ((unsigned int *)(MISC_BASE + 0x024)) +/* CORE CLK CFG register masks */ +#define PLL_HCLK_RATIO_SHIFT 10 +#define PLL_HCLK_RATIO_MASK 0x3 +#define HCLK_PCLK_RATIO_SHIFT 8 +#define HCLK_PCLK_RATIO_MASK 0x3 + +#define PERIP_CLK_CFG ((unsigned int *)(MISC_BASE + 0x028)) +/* PERIP_CLK_CFG register masks */ +#define UART_CLK_SHIFT 4 +#define UART_CLK_MASK 0x1 +#define FIRDA_CLK_SHIFT 5 +#define FIRDA_CLK_MASK 0x3 +#define GPT0_CLK_SHIFT 8 +#define GPT1_CLK_SHIFT 11 +#define GPT2_CLK_SHIFT 12 +#define GPT_CLK_MASK 0x1 +#define AUX_CLK_PLL3_MASK 0 +#define AUX_CLK_PLL1_MASK 1 + +#define PERIP1_CLK_ENB ((unsigned int *)(MISC_BASE + 0x02C)) +/* PERIP1_CLK_ENB register masks */ +#define UART_CLK_ENB 3 +#define SSP_CLK_ENB 5 +#define I2C_CLK_ENB 7 +#define JPEG_CLK_ENB 8 +#define FIRDA_CLK_ENB 10 +#define GPT1_CLK_ENB 11 +#define GPT2_CLK_ENB 12 +#define ADC_CLK_ENB 15 +#define RTC_CLK_ENB 17 +#define GPIO_CLK_ENB 18 +#define DMA_CLK_ENB 19 +#define SMI_CLK_ENB 21 +#define GMAC_CLK_ENB 23 +#define USBD_CLK_ENB 24 +#define USBH_CLK_ENB 25 +#define C3_CLK_ENB 31 + +#define SOC_CORE_ID ((unsigned int *)(MISC_BASE + 0x030)) +#define RAS_CLK_ENB ((unsigned int *)(MISC_BASE + 0x034)) +#define PERIP1_SOF_RST ((unsigned int *)(MISC_BASE + 0x038)) +/* PERIP1_SOF_RST register masks */ +#define JPEG_SOF_RST 8 + +#define SOC_USER_ID ((unsigned int *)(MISC_BASE + 0x03C)) +#define RAS_SOF_RST ((unsigned int *)(MISC_BASE + 0x040)) +#define PRSC1_CLK_CFG ((unsigned int *)(MISC_BASE + 0x044)) +#define PRSC2_CLK_CFG ((unsigned int *)(MISC_BASE + 0x048)) +#define PRSC3_CLK_CFG ((unsigned int *)(MISC_BASE + 0x04C)) +/* gpt synthesizer register masks */ +#define GPT_MSCALE_SHIFT 0 +#define GPT_MSCALE_MASK 0xFFF +#define GPT_NSCALE_SHIFT 12 +#define GPT_NSCALE_MASK 0xF + +#define AMEM_CLK_CFG ((unsigned int *)(MISC_BASE + 0x050)) +#define EXPI_CLK_CFG ((unsigned int *)(MISC_BASE + 0x054)) +#define CLCD_CLK_SYNT ((unsigned int *)(MISC_BASE + 0x05C)) +#define FIRDA_CLK_SYNT ((unsigned int *)(MISC_BASE + 0x060)) +#define UART_CLK_SYNT ((unsigned int *)(MISC_BASE + 0x064)) +#define GMAC_CLK_SYNT ((unsigned int *)(MISC_BASE + 0x068)) +#define RAS1_CLK_SYNT ((unsigned int *)(MISC_BASE + 0x06C)) +#define RAS2_CLK_SYNT ((unsigned int *)(MISC_BASE + 0x070)) +#define RAS3_CLK_SYNT ((unsigned int *)(MISC_BASE + 0x074)) +#define RAS4_CLK_SYNT ((unsigned int *)(MISC_BASE + 0x078)) +/* aux clk synthesiser register masks for irda to ras4 */ +#define AUX_EQ_SEL_SHIFT 30 +#define AUX_EQ_SEL_MASK 1 +#define AUX_EQ1_SEL 0 +#define AUX_EQ2_SEL 1 +#define AUX_XSCALE_SHIFT 16 +#define AUX_XSCALE_MASK 0xFFF +#define AUX_YSCALE_SHIFT 0 +#define AUX_YSCALE_MASK 0xFFF + +#define ICM1_ARB_CFG ((unsigned int *)(MISC_BASE + 0x07C)) +#define ICM2_ARB_CFG ((unsigned int *)(MISC_BASE + 0x080)) +#define ICM3_ARB_CFG ((unsigned int *)(MISC_BASE + 0x084)) +#define ICM4_ARB_CFG ((unsigned int *)(MISC_BASE + 0x088)) +#define ICM5_ARB_CFG ((unsigned int *)(MISC_BASE + 0x08C)) +#define ICM6_ARB_CFG ((unsigned int *)(MISC_BASE + 0x090)) +#define ICM7_ARB_CFG ((unsigned int *)(MISC_BASE + 0x094)) +#define ICM8_ARB_CFG ((unsigned int *)(MISC_BASE + 0x098)) +#define ICM9_ARB_CFG ((unsigned int *)(MISC_BASE + 0x09C)) +#define DMA_CHN_CFG ((unsigned int *)(MISC_BASE + 0x0A0)) +#define USB2_PHY_CFG ((unsigned int *)(MISC_BASE + 0x0A4)) +#define GMAC_CFG_CTR ((unsigned int *)(MISC_BASE + 0x0A8)) +#define EXPI_CFG_CTR ((unsigned int *)(MISC_BASE + 0x0AC)) +#define PRC1_LOCK_CTR ((unsigned int *)(MISC_BASE + 0x0C0)) +#define PRC2_LOCK_CTR ((unsigned int *)(MISC_BASE + 0x0C4)) +#define PRC3_LOCK_CTR ((unsigned int *)(MISC_BASE + 0x0C8)) +#define PRC4_LOCK_CTR ((unsigned int *)(MISC_BASE + 0x0CC)) +#define PRC1_IRQ_CTR ((unsigned int *)(MISC_BASE + 0x0D0)) +#define PRC2_IRQ_CTR ((unsigned int *)(MISC_BASE + 0x0D4)) +#define PRC3_IRQ_CTR ((unsigned int *)(MISC_BASE + 0x0D8)) +#define PRC4_IRQ_CTR ((unsigned int *)(MISC_BASE + 0x0DC)) +#define PWRDOWN_CFG_CTR ((unsigned int *)(MISC_BASE + 0x0E0)) +#define COMPSSTL_1V8_CFG ((unsigned int *)(MISC_BASE + 0x0E4)) +#define COMPSSTL_2V5_CFG ((unsigned int *)(MISC_BASE + 0x0E8)) +#define COMPCOR_3V3_CFG ((unsigned int *)(MISC_BASE + 0x0EC)) +#define SSTLPAD_CFG_CTR ((unsigned int *)(MISC_BASE + 0x0F0)) +#define BIST1_CFG_CTR ((unsigned int *)(MISC_BASE + 0x0F4)) +#define BIST2_CFG_CTR ((unsigned int *)(MISC_BASE + 0x0F8)) +#define BIST3_CFG_CTR ((unsigned int *)(MISC_BASE + 0x0FC)) +#define BIST4_CFG_CTR ((unsigned int *)(MISC_BASE + 0x100)) +#define BIST5_CFG_CTR ((unsigned int *)(MISC_BASE + 0x104)) +#define BIST1_STS_RES ((unsigned int *)(MISC_BASE + 0x108)) +#define BIST2_STS_RES ((unsigned int *)(MISC_BASE + 0x10C)) +#define BIST3_STS_RES ((unsigned int *)(MISC_BASE + 0x110)) +#define BIST4_STS_RES ((unsigned int *)(MISC_BASE + 0x114)) +#define BIST5_STS_RES ((unsigned int *)(MISC_BASE + 0x118)) +#define SYSERR_CFG_CTR ((unsigned int *)(MISC_BASE + 0x11C)) + +#endif /* __MACH_MISC_REGS_H */ diff --git a/arch/arm/mach-spear3xx/include/mach/spear.h b/arch/arm/mach-spear3xx/include/mach/spear.h new file mode 100644 index 0000000..dcca856 --- /dev/null +++ b/arch/arm/mach-spear3xx/include/mach/spear.h @@ -0,0 +1,144 @@ +/* + * arch/arm/mach-spear3xx/include/mach/spear.h + * + * SPEAr3xx Machine family specific definition + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __MACH_SPEAR3XX_H +#define __MACH_SPEAR3XX_H + +#include +#include +#include +#include + +#define SPEAR3XX_ML_SDRAM_BASE 0x00000000 +#define SPEAR3XX_ML_SDRAM_SIZE 0x40000000 + +#define SPEAR3XX_ICM9_BASE 0xC0000000 +#define SPEAR3XX_ICM9_SIZE 0x10000000 + +/* ICM1 - Low speed connection */ +#define SPEAR3XX_ICM1_2_BASE 0xD0000000 +#define SPEAR3XX_ICM1_2_SIZE 0x10000000 + +#define SPEAR3XX_ICM1_UART_BASE 0xD0000000 +#define VA_SPEAR3XX_ICM1_UART_BASE IO_ADDRESS(SPEAR3XX_ICM1_UART_BASE) +#define SPEAR3XX_ICM1_UART_SIZE 0x00080000 + +#define SPEAR3XX_ICM1_ADC_BASE 0xD0080000 +#define SPEAR3XX_ICM1_ADC_SIZE 0x00080000 + +#define SPEAR3XX_ICM1_SSP_BASE 0xD0100000 +#define SPEAR3XX_ICM1_SSP_SIZE 0x00080000 + +#define SPEAR3XX_ICM1_I2C_BASE 0xD0180000 +#define SPEAR3XX_ICM1_I2C_SIZE 0x00080000 + +#define SPEAR3XX_ICM1_JPEG_BASE 0xD0800000 +#define SPEAR3XX_ICM1_JPEG_SIZE 0x00800000 + +#define SPEAR3XX_ICM1_IRDA_BASE 0xD1000000 +#define SPEAR3XX_ICM1_IRDA_SIZE 0x00080000 + +#define SPEAR3XX_ICM1_SRAM_BASE 0xD2800000 +#define SPEAR3XX_ICM1_SRAM_SIZE 0x05800000 + +/* ICM2 - Application Subsystem */ +#define SPEAR3XX_ICM2_HWACCEL0_BASE 0xD8800000 +#define SPEAR3XX_ICM2_HWACCEL0_SIZE 0x00800000 + +#define SPEAR3XX_ICM2_HWACCEL1_BASE 0xD9000000 +#define SPEAR3XX_ICM2_HWACCEL1_SIZE 0x00800000 + +/* ICM4 - High Speed Connection */ +#define SPEAR3XX_ICM4_BASE 0xE0000000 +#define SPEAR3XX_ICM4_SIZE 0x08000000 + +#define SPEAR3XX_ICM4_MII_BASE 0xE0800000 +#define SPEAR3XX_ICM4_MII_SIZE 0x00800000 + +#define SPEAR3XX_ICM4_USBD_FIFO_BASE 0xE1000000 +#define SPEAR3XX_ICM4_USBD_FIFO_SIZE 0x00100000 + +#define SPEAR3XX_ICM4_USBD_CSR_BASE 0xE1100000 +#define SPEAR3XX_ICM4_USBD_CSR_SIZE 0x00100000 + +#define SPEAR3XX_ICM4_USBD_PLDT_BASE 0xE1200000 +#define SPEAR3XX_ICM4_USBD_PLDT_SIZE 0x00100000 + +#define SPEAR3XX_ICM4_USB_EHCI0_1_BASE 0xE1800000 +#define SPEAR3XX_ICM4_USB_EHCI0_1_SIZE 0x00100000 + +#define SPEAR3XX_ICM4_USB_OHCI0_BASE 0xE1900000 +#define SPEAR3XX_ICM4_USB_OHCI0_SIZE 0x00100000 + +#define SPEAR3XX_ICM4_USB_OHCI1_BASE 0xE2100000 +#define SPEAR3XX_ICM4_USB_OHCI1_SIZE 0x00100000 + +#define SPEAR3XX_ICM4_USB_ARB_BASE 0xE2800000 +#define SPEAR3XX_ICM4_USB_ARB_SIZE 0x00010000 + +/* ML1 - Multi Layer CPU Subsystem */ +#define SPEAR3XX_ICM3_ML1_2_BASE 0xF0000000 +#define SPEAR3XX_ICM3_ML1_2_SIZE 0x0F000000 + +#define SPEAR3XX_ML1_TMR_BASE 0xF0000000 +#define SPEAR3XX_ML1_TMR_SIZE 0x00100000 + +#define SPEAR3XX_ML1_VIC_BASE 0xF1100000 +#define VA_SPEAR3XX_ML1_VIC_BASE IO_ADDRESS(SPEAR3XX_ML1_VIC_BASE) +#define SPEAR3XX_ML1_VIC_SIZE 0x00100000 + +/* ICM3 - Basic Subsystem */ +#define SPEAR3XX_ICM3_SMEM_BASE 0xF8000000 +#define SPEAR3XX_ICM3_SMEM_SIZE 0x04000000 + +#define SPEAR3XX_ICM3_SMI_CTRL_BASE 0xFC000000 +#define SPEAR3XX_ICM3_SMI_CTRL_SIZE 0x00200000 + +#define SPEAR3XX_ICM3_DMA_BASE 0xFC400000 +#define SPEAR3XX_ICM3_DMA_SIZE 0x00200000 + +#define SPEAR3XX_ICM3_SDRAM_CTRL_BASE 0xFC600000 +#define SPEAR3XX_ICM3_SDRAM_CTRL_SIZE 0x00200000 + +#define SPEAR3XX_ICM3_TMR0_BASE 0xFC800000 +#define SPEAR3XX_ICM3_TMR0_SIZE 0x00080000 + +#define SPEAR3XX_ICM3_WDT_BASE 0xFC880000 +#define SPEAR3XX_ICM3_WDT_SIZE 0x00080000 + +#define SPEAR3XX_ICM3_RTC_BASE 0xFC900000 +#define SPEAR3XX_ICM3_RTC_SIZE 0x00080000 + +#define SPEAR3XX_ICM3_GPIO_BASE 0xFC980000 +#define SPEAR3XX_ICM3_GPIO_SIZE 0x00080000 + +#define SPEAR3XX_ICM3_SYS_CTRL_BASE 0xFCA00000 +#define VA_SPEAR3XX_ICM3_SYS_CTRL_BASE IO_ADDRESS(SPEAR3XX_ICM3_SYS_CTRL_BASE) +#define SPEAR3XX_ICM3_SYS_CTRL_SIZE 0x00080000 + +#define SPEAR3XX_ICM3_MISC_REG_BASE 0xFCA80000 +#define VA_SPEAR3XX_ICM3_MISC_REG_BASE IO_ADDRESS(SPEAR3XX_ICM3_MISC_REG_BASE) +#define SPEAR3XX_ICM3_MISC_REG_SIZE 0x00080000 + +#define SPEAR3XX_ICM3_TMR1_BASE 0xFCB00000 +#define SPEAR3XX_ICM3_TMR1_SIZE 0x00080000 + +/* Debug uart for linux, will be used for debug and uncompress messages */ +#define SPEAR_DBG_UART_BASE SPEAR3XX_ICM1_UART_BASE +#define VA_SPEAR_DBG_UART_BASE VA_SPEAR3XX_ICM1_UART_BASE + +/* Sysctl base for spear platform */ +#define SPEAR_SYS_CTRL_BASE SPEAR3XX_ICM3_SYS_CTRL_BASE +#define VA_SPEAR_SYS_CTRL_BASE VA_SPEAR3XX_ICM3_SYS_CTRL_BASE + +#endif /* __MACH_SPEAR3XX_H */ diff --git a/arch/arm/mach-spear3xx/include/mach/spear300.h b/arch/arm/mach-spear3xx/include/mach/spear300.h new file mode 100644 index 0000000..40c16f3 --- /dev/null +++ b/arch/arm/mach-spear3xx/include/mach/spear300.h @@ -0,0 +1,67 @@ +/* + * arch/arm/mach-spear3xx/include/mach/spear300.h + * + * SPEAr300 Machine specific definition + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifdef CONFIG_MACH_SPEAR300 + +#ifndef __MACH_SPEAR300_H +#define __MACH_SPEAR300_H + +/* Base address of various IPs */ +#define SPEAR300_TELECOM_BASE 0x50000000 +#define SPEAR300_TELECOM_SIZE 0x10000000 + +#define SPEAR300_CLCD_BASE 0x60000000 +#define SPEAR300_CLCD_SIZE 0x10000000 + +#define SPEAR300_SDIO_BASE 0x70000000 +#define SPEAR300_SDIO_SIZE 0x10000000 + +#define SPEAR300_NAND_0_BASE 0x80000000 +#define SPEAR300_NAND_0_SIZE 0x04000000 + +#define SPEAR300_NAND_1_BASE 0x84000000 +#define SPEAR300_NAND_1_SIZE 0x04000000 + +#define SPEAR300_NAND_2_BASE 0x88000000 +#define SPEAR300_NAND_2_SIZE 0x04000000 + +#define SPEAR300_NAND_3_BASE 0x8c000000 +#define SPEAR300_NAND_3_SIZE 0x04000000 + +#define SPEAR300_NOR_0_BASE 0x90000000 +#define SPEAR300_NOR_0_SIZE 0x01000000 + +#define SPEAR300_NOR_1_BASE 0x91000000 +#define SPEAR300_NOR_1_SIZE 0x01000000 + +#define SPEAR300_NOR_2_BASE 0x92000000 +#define SPEAR300_NOR_2_SIZE 0x01000000 + +#define SPEAR300_NOR_3_BASE 0x93000000 +#define SPEAR300_NOR_3_SIZE 0x01000000 + +#define SPEAR300_FSMC_BASE 0x94000000 +#define SPEAR300_FSMC_SIZE 0x05000000 + +#define SPEAR300_SOC_CONFIG_BASE 0x99000000 +#define SPEAR300_SOC_CONFIG_SIZE 0x00000008 + +#define SPEAR300_KEYBOARD_BASE 0xA0000000 +#define SPEAR300_KEYBOARD_SIZE 0x09000000 + +#define SPEAR300_GPIO_BASE 0xA9000000 +#define SPEAR300_GPIO_SIZE 0x07000000 + +#endif /* __MACH_SPEAR300_H */ + +#endif /* CONFIG_MACH_SPEAR300 */ diff --git a/arch/arm/mach-spear3xx/include/mach/spear310.h b/arch/arm/mach-spear3xx/include/mach/spear310.h new file mode 100644 index 0000000..d4f58d6 --- /dev/null +++ b/arch/arm/mach-spear3xx/include/mach/spear310.h @@ -0,0 +1,46 @@ +/* + * arch/arm/mach-spear3xx/include/mach/spear310.h + * + * SPEAr310 Machine specific definition + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifdef CONFIG_MACH_SPEAR310 + +#ifndef __MACH_SPEAR310_H +#define __MACH_SPEAR310_H + +#define SPEAR310_NAND_BASE 0x40000000 +#define SPEAR310_NAND_SIZE 0x04000000 + +#define SPEAR310_FSMC_BASE 0x44000000 +#define SPEAR310_FSMC_SIZE 0x01000000 + +#define SPEAR310_UART1_BASE 0xB2000000 +#define SPEAR310_UART2_BASE 0xB2080000 +#define SPEAR310_UART3_BASE 0xB2100000 +#define SPEAR310_UART4_BASE 0xB2180000 +#define SPEAR310_UART5_BASE 0xB2200000 +#define SPEAR310_UART_SIZE 0x00080000 + +#define SPEAR310_HDLC_BASE 0xB2800000 +#define SPEAR310_HDLC_SIZE 0x00800000 + +#define SPEAR310_RS485_0_BASE 0xB3000000 +#define SPEAR310_RS485_0_SIZE 0x00800000 + +#define SPEAR310_RS485_1_BASE 0xB3800000 +#define SPEAR310_RS485_1_SIZE 0x00800000 + +#define SPEAR310_SOC_CONFIG_BASE 0xB4000000 +#define SPEAR310_SOC_CONFIG_SIZE 0x00000070 + +#endif /* __MACH_SPEAR310_H */ + +#endif /* CONFIG_MACH_SPEAR310 */ diff --git a/arch/arm/mach-spear3xx/include/mach/spear320.h b/arch/arm/mach-spear3xx/include/mach/spear320.h new file mode 100644 index 0000000..e8ad2ed --- /dev/null +++ b/arch/arm/mach-spear3xx/include/mach/spear320.h @@ -0,0 +1,70 @@ +/* + * arch/arm/mach-spear3xx/include/mach/spear320.h + * + * SPEAr320 Machine specific definition + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifdef CONFIG_MACH_SPEAR320 + +#ifndef __MACH_SPEAR320_H +#define __MACH_SPEAR320_H + +#define SPEAR320_EMI_CTRL_BASE 0x40000000 +#define SPEAR320_EMI_CTRL_SIZE 0x08000000 + +#define SPEAR320_FSMC_BASE 0x4C000000 +#define SPEAR320_FSMC_SIZE 0x01000000 + +#define SPEAR320_I2S_BASE 0x60000000 +#define SPEAR320_I2S_SIZE 0x10000000 + +#define SPEAR320_SDIO_BASE 0x70000000 +#define SPEAR320_SDIO_SIZE 0x10000000 + +#define SPEAR320_CLCD_BASE 0x90000000 +#define SPEAR320_CLCD_SIZE 0x10000000 + +#define SPEAR320_PAR_PORT_BASE 0xA0000000 +#define SPEAR320_PAR_PORT_SIZE 0x01000000 + +#define SPEAR320_CAN0_BASE 0xA1000000 +#define SPEAR320_CAN0_SIZE 0x01000000 + +#define SPEAR320_CAN1_BASE 0xA2000000 +#define SPEAR320_CAN1_SIZE 0x01000000 + +#define SPEAR320_UART1_BASE 0xA3000000 +#define SPEAR320_UART2_BASE 0xA4000000 +#define SPEAR320_UART_SIZE 0x01000000 + +#define SPEAR320_SSP0_BASE 0xA5000000 +#define SPEAR320_SSP0_SIZE 0x01000000 + +#define SPEAR320_SSP1_BASE 0xA6000000 +#define SPEAR320_SSP1_SIZE 0x01000000 + +#define SPEAR320_I2C_BASE 0xA7000000 +#define SPEAR320_I2C_SIZE 0x01000000 + +#define SPEAR320_PWM_BASE 0xA8000000 +#define SPEAR320_PWM_SIZE 0x01000000 + +#define SPEAR320_SMII0_BASE 0xAA000000 +#define SPEAR320_SMII0_SIZE 0x01000000 + +#define SPEAR320_SMII1_BASE 0xAB000000 +#define SPEAR320_SMII1_SIZE 0x01000000 + +#define SPEAR320_SOC_CONFIG_BASE 0xB4000000 +#define SPEAR320_SOC_CONFIG_SIZE 0x00000070 + +#endif /* __MACH_SPEAR320_H */ + +#endif /* CONFIG_MACH_SPEAR320 */ diff --git a/arch/arm/mach-spear3xx/include/mach/system.h b/arch/arm/mach-spear3xx/include/mach/system.h new file mode 100644 index 0000000..92cee63 --- /dev/null +++ b/arch/arm/mach-spear3xx/include/mach/system.h @@ -0,0 +1,19 @@ +/* + * arch/arm/mach-spear3xx/include/mach/system.h + * + * SPEAr3xx Machine family specific architecture functions + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __MACH_SYSTEM_H +#define __MACH_SYSTEM_H + +#include + +#endif /* __MACH_SYSTEM_H */ diff --git a/arch/arm/mach-spear3xx/include/mach/timex.h b/arch/arm/mach-spear3xx/include/mach/timex.h new file mode 100644 index 0000000..a38cc9d --- /dev/null +++ b/arch/arm/mach-spear3xx/include/mach/timex.h @@ -0,0 +1,19 @@ +/* + * arch/arm/mach-spear3xx/include/mach/timex.h + * + * SPEAr3XX machine family specific timex definitions + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __MACH_TIMEX_H +#define __MACH_TIMEX_H + +#include + +#endif /* __MACH_TIMEX_H */ diff --git a/arch/arm/mach-spear3xx/include/mach/uncompress.h b/arch/arm/mach-spear3xx/include/mach/uncompress.h new file mode 100644 index 0000000..53ba8bb --- /dev/null +++ b/arch/arm/mach-spear3xx/include/mach/uncompress.h @@ -0,0 +1,19 @@ +/* + * arch/arm/mach-spear3xx/include/mach/uncompress.h + * + * Serial port stubs for kernel decompress status messages + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __MACH_UNCOMPRESS_H +#define __MACH_UNCOMPRESS_H + +#include + +#endif /* __MACH_UNCOMPRESS_H */ diff --git a/arch/arm/mach-spear3xx/include/mach/vmalloc.h b/arch/arm/mach-spear3xx/include/mach/vmalloc.h new file mode 100644 index 0000000..df977b3 --- /dev/null +++ b/arch/arm/mach-spear3xx/include/mach/vmalloc.h @@ -0,0 +1,19 @@ +/* + * arch/arm/mach-spear3xx/include/mach/vmalloc.h + * + * Defining Vmalloc area for SPEAr3xx machine family + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __MACH_VMALLOC_H +#define __MACH_VMALLOC_H + +#include + +#endif /* __MACH_VMALLOC_H */ -- cgit v0.10.2 From 3f10940e4fb69d312602078f2c5234206797ca31 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 10 Apr 2010 16:46:21 +0200 Subject: x86/microcode: Use nonseekable_open() No need to seek on this file, so prevent it outright so we can avoid using default_llseek - removes one more BKL usage. Signed-off-by: Arnd Bergmann [drop useless llseek = no_llseek and smp_lock.h inclusion] Signed-off-by: Frederic Weisbecker Cc: Arnd Bergmann Cc: H. Peter Anvin Cc: Dmitry Adamushko LKML-Reference: <1270910781-8786-1-git-send-regression-fweisbec@gmail.com> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c index cceb5bc..2cd8c54 100644 --- a/arch/x86/kernel/microcode_core.c +++ b/arch/x86/kernel/microcode_core.c @@ -201,9 +201,9 @@ static int do_microcode_update(const void __user *buf, size_t size) return error; } -static int microcode_open(struct inode *unused1, struct file *unused2) +static int microcode_open(struct inode *inode, struct file *file) { - return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; + return capable(CAP_SYS_RAWIO) ? nonseekable_open(inode, file) : -EPERM; } static ssize_t microcode_write(struct file *file, const char __user *buf, -- cgit v0.10.2 From e024c3d50c53999d15e3b8a21e0abbbf74c32140 Mon Sep 17 00:00:00 2001 From: viresh kumar Date: Thu, 1 Apr 2010 12:30:31 +0100 Subject: ARM: 6011/1: ST SPEAr: Added basic header files for SPEAr6xx machine family Reviewed-by: Linus Walleij Signed-off-by: Viresh Kumar Signed-off-by: Rajeev Kumar Signed-off-by: Russell King diff --git a/arch/arm/mach-spear6xx/include/mach/debug-macro.S b/arch/arm/mach-spear6xx/include/mach/debug-macro.S new file mode 100644 index 0000000..0f3ea39 --- /dev/null +++ b/arch/arm/mach-spear6xx/include/mach/debug-macro.S @@ -0,0 +1,14 @@ +/* + * arch/arm/mach-spear6xx/include/mach/debug-macro.S + * + * Debugging macro include header for SPEAr6xx machine family + * + * Copyright (C) 2009 ST Microelectronics + * Rajeev Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include diff --git a/arch/arm/mach-spear6xx/include/mach/entry-macro.S b/arch/arm/mach-spear6xx/include/mach/entry-macro.S new file mode 100644 index 0000000..9eaecae --- /dev/null +++ b/arch/arm/mach-spear6xx/include/mach/entry-macro.S @@ -0,0 +1,55 @@ +/* + * arch/arm/mach-spear6xx/include/mach/entry-macro.S + * + * Low-level IRQ helper macros for SPEAr6xx machine family + * + * Copyright (C) 2009 ST Microelectronics + * Rajeev Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include + + .macro disable_fiq + .endm + + .macro get_irqnr_preamble, base, tmp + .endm + + .macro arch_ret_to_user, tmp1, tmp2 + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + ldr \base, =VA_SPEAR6XX_CPU_VIC_PRI_BASE + ldr \irqstat, [\base, #VIC_IRQ_STATUS] @ get status + mov \irqnr, #0 + teq \irqstat, #0 + bne 1001f + ldr \base, =VA_SPEAR6XX_CPU_VIC_SEC_BASE + ldr \irqstat, [\base, #VIC_IRQ_STATUS] @ get status + teq \irqstat, #0 + beq 1002f @ this will set/reset + @ zero register + mov \irqnr, #32 +1001: + /* + * Following code will find bit position of least significang + * bit set in irqstat, using following equation + * least significant bit set in n = (n & ~(n-1)) + */ + sub \tmp, \irqstat, #1 @ tmp = irqstat - 1 + mvn \tmp, \tmp @ tmp = ~tmp + and \irqstat, \irqstat, \tmp @ irqstat &= tmp + /* Now, irqstat is = bit no. of 1st bit set in vic irq status */ + clz \tmp, \irqstat @ tmp = leading zeros + + rsb \tmp, \tmp, #0x1F @ tmp = 32 - tmp - 1 + add \irqnr, \irqnr, \tmp + +1002: /* EQ will be set if no irqs pending */ + .endm diff --git a/arch/arm/mach-spear6xx/include/mach/generic.h b/arch/arm/mach-spear6xx/include/mach/generic.h new file mode 100644 index 0000000..16205a5 --- /dev/null +++ b/arch/arm/mach-spear6xx/include/mach/generic.h @@ -0,0 +1,45 @@ +/* + * arch/arm/mach-spear6xx/include/mach/generic.h + * + * SPEAr6XX machine family specific generic header file + * + * Copyright (C) 2009 ST Microelectronics + * Rajeev Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __MACH_GENERIC_H +#define __MACH_GENERIC_H + +#include +#include +#include +#include +#include + +/* + * Each GPT has 2 timer channels + * Following GPT channels will be used as clock source and clockevent + */ +#define SPEAR_GPT0_BASE SPEAR6XX_CPU_TMR_BASE +#define SPEAR_GPT0_CHAN0_IRQ IRQ_CPU_GPT1_1 +#define SPEAR_GPT0_CHAN1_IRQ IRQ_CPU_GPT1_2 + +/* Add spear6xx family device structure declarations here */ +extern struct amba_device gpio_device[]; +extern struct amba_device uart_device[]; +extern struct sys_timer spear_sys_timer; + +/* Add spear6xx family function declarations here */ +void __init spear6xx_map_io(void); +void __init spear6xx_init_irq(void); +void __init spear6xx_init(void); +void __init spear600_init(void); +void __init clk_init(void); + +/* Add spear600 machine device structure declarations here */ + +#endif /* __MACH_GENERIC_H */ diff --git a/arch/arm/mach-spear6xx/include/mach/gpio.h b/arch/arm/mach-spear6xx/include/mach/gpio.h new file mode 100644 index 0000000..3a789db --- /dev/null +++ b/arch/arm/mach-spear6xx/include/mach/gpio.h @@ -0,0 +1,19 @@ +/* + * arch/arm/mach-spear6xx/include/mach/gpio.h + * + * GPIO macros for SPEAr6xx machine family + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __MACH_GPIO_H +#define __MACH_GPIO_H + +#include + +#endif /* __MACH_GPIO_H */ diff --git a/arch/arm/mach-spear6xx/include/mach/hardware.h b/arch/arm/mach-spear6xx/include/mach/hardware.h new file mode 100644 index 0000000..7545116 --- /dev/null +++ b/arch/arm/mach-spear6xx/include/mach/hardware.h @@ -0,0 +1,21 @@ +/* + * arch/arm/mach-spear6xx/include/mach/hardware.h + * + * Hardware definitions for SPEAr6xx machine family + * + * Copyright (C) 2009 ST Microelectronics + * Rajeev Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __MACH_HARDWARE_H +#define __MACH_HARDWARE_H + +/* Vitual to physical translation of statically mapped space */ +#define IO_ADDRESS(x) (x | 0xF0000000) + +#endif /* __MACH_HARDWARE_H */ + diff --git a/arch/arm/mach-spear6xx/include/mach/io.h b/arch/arm/mach-spear6xx/include/mach/io.h new file mode 100644 index 0000000..fb7c106 --- /dev/null +++ b/arch/arm/mach-spear6xx/include/mach/io.h @@ -0,0 +1,20 @@ +/* + * arch/arm/mach-spear6xx/include/mach/io.h + * + * IO definitions for SPEAr6xx machine family + * + * Copyright (C) 2009 ST Microelectronics + * Rajeev Kumar Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __MACH_IO_H +#define __MACH_IO_H + +#include + +#endif /* __MACH_IO_H */ + diff --git a/arch/arm/mach-spear6xx/include/mach/irqs.h b/arch/arm/mach-spear6xx/include/mach/irqs.h new file mode 100644 index 0000000..08a3abc --- /dev/null +++ b/arch/arm/mach-spear6xx/include/mach/irqs.h @@ -0,0 +1,96 @@ +/* + * arch/arm/mach-spear6xx/include/mach/irqs.h + * + * IRQ helper macros for SPEAr6xx machine family + * + * Copyright (C) 2009 ST Microelectronics + * Rajeev Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __MACH_IRQS_H +#define __MACH_IRQS_H + +/* IRQ definitions */ +/* VIC 1 */ +#define IRQ_INTRCOMM_SW_IRQ 0 +#define IRQ_INTRCOMM_CPU_1 1 +#define IRQ_INTRCOMM_CPU_2 2 +#define IRQ_INTRCOMM_RAS2A11_1 3 +#define IRQ_INTRCOMM_RAS2A11_2 4 +#define IRQ_INTRCOMM_RAS2A12_1 5 +#define IRQ_INTRCOMM_RAS2A12_2 6 +#define IRQ_GEN_RAS_0 7 +#define IRQ_GEN_RAS_1 8 +#define IRQ_GEN_RAS_2 9 +#define IRQ_GEN_RAS_3 10 +#define IRQ_GEN_RAS_4 11 +#define IRQ_GEN_RAS_5 12 +#define IRQ_GEN_RAS_6 13 +#define IRQ_GEN_RAS_7 14 +#define IRQ_GEN_RAS_8 15 +#define IRQ_CPU_GPT1_1 16 +#define IRQ_CPU_GPT1_2 17 +#define IRQ_LOCAL_GPIO 18 +#define IRQ_PLL_UNLOCK 19 +#define IRQ_JPEG 20 +#define IRQ_FSMC 21 +#define IRQ_IRDA 22 +#define IRQ_RESERVED 23 +#define IRQ_UART_0 24 +#define IRQ_UART_1 25 +#define IRQ_SSP_1 26 +#define IRQ_SSP_2 27 +#define IRQ_I2C 28 +#define IRQ_GEN_RAS_9 29 +#define IRQ_GEN_RAS_10 30 +#define IRQ_GEN_RAS_11 31 + +/* VIC 2 */ +#define IRQ_APPL_GPT1_1 32 +#define IRQ_APPL_GPT1_2 33 +#define IRQ_APPL_GPT2_1 34 +#define IRQ_APPL_GPT2_2 35 +#define IRQ_APPL_GPIO 36 +#define IRQ_APPL_SSP 37 +#define IRQ_APPL_ADC 38 +#define IRQ_APPL_RESERVED 39 +#define IRQ_AHB_EXP_MASTER 40 +#define IRQ_DDR_CONTROLLER 41 +#define IRQ_BASIC_DMA 42 +#define IRQ_BASIC_RESERVED1 43 +#define IRQ_BASIC_SMI 44 +#define IRQ_BASIC_CLCD 45 +#define IRQ_EXP_AHB_1 46 +#define IRQ_EXP_AHB_2 47 +#define IRQ_BASIC_GPT1_1 48 +#define IRQ_BASIC_GPT1_2 49 +#define IRQ_BASIC_RTC 50 +#define IRQ_BASIC_GPIO 51 +#define IRQ_BASIC_WDT 52 +#define IRQ_BASIC_RESERVED 53 +#define IRQ_AHB_EXP_SLAVE 54 +#define IRQ_GMAC_1 55 +#define IRQ_GMAC_2 56 +#define IRQ_USB_DEV 57 +#define IRQ_USB_H_OHCI_0 58 +#define IRQ_USB_H_EHCI_0 59 +#define IRQ_USB_H_OHCI_1 60 +#define IRQ_USB_H_EHCI_1 61 +#define IRQ_EXP_AHB_3 62 +#define IRQ_EXP_AHB_4 63 + +#define IRQ_VIC_END 64 + +#define SPEAR_GPIO_INT_BASE IRQ_VIC_END +#define SPEAR_GPIO0_INT_BASE SPEAR_GPIO_INT_BASE +#define SPEAR_GPIO1_INT_BASE (SPEAR_GPIO0_INT_BASE + 8) +#define SPEAR_GPIO2_INT_BASE (SPEAR_GPIO1_INT_BASE + 8) +#define SPEAR_GPIO_INT_END (SPEAR_GPIO2_INT_BASE + 8) +#define VIRTUAL_IRQS (SPEAR_GPIO_INT_END - IRQ_VIC_END) +#define NR_IRQS (IRQ_VIC_END + VIRTUAL_IRQS) + +#endif /* __MACH_IRQS_H */ diff --git a/arch/arm/mach-spear6xx/include/mach/memory.h b/arch/arm/mach-spear6xx/include/mach/memory.h new file mode 100644 index 0000000..781f088 --- /dev/null +++ b/arch/arm/mach-spear6xx/include/mach/memory.h @@ -0,0 +1,19 @@ +/* + * arch/arm/mach-spear6xx/include/mach/memory.h + * + * Memory map for SPEAr6xx machine family + * + * Copyright (C) 2009 ST Microelectronics + * Rajeev Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __MACH_MEMORY_H +#define __MACH_MEMORY_H + +#include + +#endif /* __MACH_MEMORY_H */ diff --git a/arch/arm/mach-spear6xx/include/mach/misc_regs.h b/arch/arm/mach-spear6xx/include/mach/misc_regs.h new file mode 100644 index 0000000..0390803 --- /dev/null +++ b/arch/arm/mach-spear6xx/include/mach/misc_regs.h @@ -0,0 +1,173 @@ +/* + * arch/arm/mach-spear6xx/include/mach/misc_regs.h + * + * Miscellaneous registers definitions for SPEAr6xx machine family + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __MACH_MISC_REGS_H +#define __MACH_MISC_REGS_H + +#include + +#define MISC_BASE VA_SPEAR6XX_ICM3_MISC_REG_BASE + +#define SOC_CFG_CTR ((unsigned int *)(MISC_BASE + 0x000)) +#define DIAG_CFG_CTR ((unsigned int *)(MISC_BASE + 0x004)) +#define PLL1_CTR ((unsigned int *)(MISC_BASE + 0x008)) +#define PLL1_FRQ ((unsigned int *)(MISC_BASE + 0x00C)) +#define PLL1_MOD ((unsigned int *)(MISC_BASE + 0x010)) +#define PLL2_CTR ((unsigned int *)(MISC_BASE + 0x014)) +/* PLL_CTR register masks */ +#define PLL_ENABLE 2 +#define PLL_MODE_SHIFT 4 +#define PLL_MODE_MASK 0x3 +#define PLL_MODE_NORMAL 0 +#define PLL_MODE_FRACTION 1 +#define PLL_MODE_DITH_DSB 2 +#define PLL_MODE_DITH_SSB 3 + +#define PLL2_FRQ ((unsigned int *)(MISC_BASE + 0x018)) +/* PLL FRQ register masks */ +#define PLL_DIV_N_SHIFT 0 +#define PLL_DIV_N_MASK 0xFF +#define PLL_DIV_P_SHIFT 8 +#define PLL_DIV_P_MASK 0x7 +#define PLL_NORM_FDBK_M_SHIFT 24 +#define PLL_NORM_FDBK_M_MASK 0xFF +#define PLL_DITH_FDBK_M_SHIFT 16 +#define PLL_DITH_FDBK_M_MASK 0xFFFF + +#define PLL2_MOD ((unsigned int *)(MISC_BASE + 0x01C)) +#define PLL_CLK_CFG ((unsigned int *)(MISC_BASE + 0x020)) +#define CORE_CLK_CFG ((unsigned int *)(MISC_BASE + 0x024)) +/* CORE CLK CFG register masks */ +#define PLL_HCLK_RATIO_SHIFT 10 +#define PLL_HCLK_RATIO_MASK 0x3 +#define HCLK_PCLK_RATIO_SHIFT 8 +#define HCLK_PCLK_RATIO_MASK 0x3 + +#define PERIP_CLK_CFG ((unsigned int *)(MISC_BASE + 0x028)) +/* PERIP_CLK_CFG register masks */ +#define CLCD_CLK_SHIFT 2 +#define CLCD_CLK_MASK 0x3 +#define UART_CLK_SHIFT 4 +#define UART_CLK_MASK 0x1 +#define FIRDA_CLK_SHIFT 5 +#define FIRDA_CLK_MASK 0x3 +#define GPT0_CLK_SHIFT 8 +#define GPT1_CLK_SHIFT 10 +#define GPT2_CLK_SHIFT 11 +#define GPT3_CLK_SHIFT 12 +#define GPT_CLK_MASK 0x1 +#define AUX_CLK_PLL3_MASK 0 +#define AUX_CLK_PLL1_MASK 1 + +#define PERIP1_CLK_ENB ((unsigned int *)(MISC_BASE + 0x02C)) +/* PERIP1_CLK_ENB register masks */ +#define UART0_CLK_ENB 3 +#define UART1_CLK_ENB 4 +#define SSP0_CLK_ENB 5 +#define SSP1_CLK_ENB 6 +#define I2C_CLK_ENB 7 +#define JPEG_CLK_ENB 8 +#define FSMC_CLK_ENB 9 +#define FIRDA_CLK_ENB 10 +#define GPT2_CLK_ENB 11 +#define GPT3_CLK_ENB 12 +#define GPIO2_CLK_ENB 13 +#define SSP2_CLK_ENB 14 +#define ADC_CLK_ENB 15 +#define GPT1_CLK_ENB 11 +#define RTC_CLK_ENB 17 +#define GPIO1_CLK_ENB 18 +#define DMA_CLK_ENB 19 +#define SMI_CLK_ENB 21 +#define CLCD_CLK_ENB 22 +#define GMAC_CLK_ENB 23 +#define USBD_CLK_ENB 24 +#define USBH0_CLK_ENB 25 +#define USBH1_CLK_ENB 26 + +#define SOC_CORE_ID ((unsigned int *)(MISC_BASE + 0x030)) +#define RAS_CLK_ENB ((unsigned int *)(MISC_BASE + 0x034)) +#define PERIP1_SOF_RST ((unsigned int *)(MISC_BASE + 0x038)) +/* PERIP1_SOF_RST register masks */ +#define JPEG_SOF_RST 8 + +#define SOC_USER_ID ((unsigned int *)(MISC_BASE + 0x03C)) +#define RAS_SOF_RST ((unsigned int *)(MISC_BASE + 0x040)) +#define PRSC1_CLK_CFG ((unsigned int *)(MISC_BASE + 0x044)) +#define PRSC2_CLK_CFG ((unsigned int *)(MISC_BASE + 0x048)) +#define PRSC3_CLK_CFG ((unsigned int *)(MISC_BASE + 0x04C)) +/* gpt synthesizer register masks */ +#define GPT_MSCALE_SHIFT 0 +#define GPT_MSCALE_MASK 0xFFF +#define GPT_NSCALE_SHIFT 12 +#define GPT_NSCALE_MASK 0xF + +#define AMEM_CLK_CFG ((unsigned int *)(MISC_BASE + 0x050)) +#define EXPI_CLK_CFG ((unsigned int *)(MISC_BASE + 0x054)) +#define CLCD_CLK_SYNT ((unsigned int *)(MISC_BASE + 0x05C)) +#define FIRDA_CLK_SYNT ((unsigned int *)(MISC_BASE + 0x060)) +#define UART_CLK_SYNT ((unsigned int *)(MISC_BASE + 0x064)) +#define GMAC_CLK_SYNT ((unsigned int *)(MISC_BASE + 0x068)) +#define RAS1_CLK_SYNT ((unsigned int *)(MISC_BASE + 0x06C)) +#define RAS2_CLK_SYNT ((unsigned int *)(MISC_BASE + 0x070)) +#define RAS3_CLK_SYNT ((unsigned int *)(MISC_BASE + 0x074)) +#define RAS4_CLK_SYNT ((unsigned int *)(MISC_BASE + 0x078)) +/* aux clk synthesiser register masks for irda to ras4 */ +#define AUX_EQ_SEL_SHIFT 30 +#define AUX_EQ_SEL_MASK 1 +#define AUX_EQ1_SEL 0 +#define AUX_EQ2_SEL 1 +#define AUX_XSCALE_SHIFT 16 +#define AUX_XSCALE_MASK 0xFFF +#define AUX_YSCALE_SHIFT 0 +#define AUX_YSCALE_MASK 0xFFF + +#define ICM1_ARB_CFG ((unsigned int *)(MISC_BASE + 0x07C)) +#define ICM2_ARB_CFG ((unsigned int *)(MISC_BASE + 0x080)) +#define ICM3_ARB_CFG ((unsigned int *)(MISC_BASE + 0x084)) +#define ICM4_ARB_CFG ((unsigned int *)(MISC_BASE + 0x088)) +#define ICM5_ARB_CFG ((unsigned int *)(MISC_BASE + 0x08C)) +#define ICM6_ARB_CFG ((unsigned int *)(MISC_BASE + 0x090)) +#define ICM7_ARB_CFG ((unsigned int *)(MISC_BASE + 0x094)) +#define ICM8_ARB_CFG ((unsigned int *)(MISC_BASE + 0x098)) +#define ICM9_ARB_CFG ((unsigned int *)(MISC_BASE + 0x09C)) +#define DMA_CHN_CFG ((unsigned int *)(MISC_BASE + 0x0A0)) +#define USB2_PHY_CFG ((unsigned int *)(MISC_BASE + 0x0A4)) +#define GMAC_CFG_CTR ((unsigned int *)(MISC_BASE + 0x0A8)) +#define EXPI_CFG_CTR ((unsigned int *)(MISC_BASE + 0x0AC)) +#define PRC1_LOCK_CTR ((unsigned int *)(MISC_BASE + 0x0C0)) +#define PRC2_LOCK_CTR ((unsigned int *)(MISC_BASE + 0x0C4)) +#define PRC3_LOCK_CTR ((unsigned int *)(MISC_BASE + 0x0C8)) +#define PRC4_LOCK_CTR ((unsigned int *)(MISC_BASE + 0x0CC)) +#define PRC1_IRQ_CTR ((unsigned int *)(MISC_BASE + 0x0D0)) +#define PRC2_IRQ_CTR ((unsigned int *)(MISC_BASE + 0x0D4)) +#define PRC3_IRQ_CTR ((unsigned int *)(MISC_BASE + 0x0D8)) +#define PRC4_IRQ_CTR ((unsigned int *)(MISC_BASE + 0x0DC)) +#define PWRDOWN_CFG_CTR ((unsigned int *)(MISC_BASE + 0x0E0)) +#define COMPSSTL_1V8_CFG ((unsigned int *)(MISC_BASE + 0x0E4)) +#define COMPSSTL_2V5_CFG ((unsigned int *)(MISC_BASE + 0x0E8)) +#define COMPCOR_3V3_CFG ((unsigned int *)(MISC_BASE + 0x0EC)) +#define SSTLPAD_CFG_CTR ((unsigned int *)(MISC_BASE + 0x0F0)) +#define BIST1_CFG_CTR ((unsigned int *)(MISC_BASE + 0x0F4)) +#define BIST2_CFG_CTR ((unsigned int *)(MISC_BASE + 0x0F8)) +#define BIST3_CFG_CTR ((unsigned int *)(MISC_BASE + 0x0FC)) +#define BIST4_CFG_CTR ((unsigned int *)(MISC_BASE + 0x100)) +#define BIST5_CFG_CTR ((unsigned int *)(MISC_BASE + 0x104)) +#define BIST1_STS_RES ((unsigned int *)(MISC_BASE + 0x108)) +#define BIST2_STS_RES ((unsigned int *)(MISC_BASE + 0x10C)) +#define BIST3_STS_RES ((unsigned int *)(MISC_BASE + 0x110)) +#define BIST4_STS_RES ((unsigned int *)(MISC_BASE + 0x114)) +#define BIST5_STS_RES ((unsigned int *)(MISC_BASE + 0x118)) +#define SYSERR_CFG_CTR ((unsigned int *)(MISC_BASE + 0x11C)) + +#endif /* __MACH_MISC_REGS_H */ diff --git a/arch/arm/mach-spear6xx/include/mach/spear.h b/arch/arm/mach-spear6xx/include/mach/spear.h new file mode 100644 index 0000000..a835f5b --- /dev/null +++ b/arch/arm/mach-spear6xx/include/mach/spear.h @@ -0,0 +1,173 @@ +/* + * arch/arm/mach-spear6xx/include/mach/spear.h + * + * SPEAr6xx Machine family specific definition + * + * Copyright (C) 2009 ST Microelectronics + * Rajeev Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __MACH_SPEAR6XX_H +#define __MACH_SPEAR6XX_H + +#include +#include + +#define SPEAR6XX_ML_SDRAM_BASE 0x00000000 +#define SPEAR6XX_ML_SDRAM_SIZE 0x40000000 + +/* ICM1 - Low speed connection */ +#define SPEAR6XX_ICM1_BASE 0xD0000000 +#define SPEAR6XX_ICM1_SIZE 0x08000000 + +#define SPEAR6XX_ICM1_UART0_BASE 0xD0000000 +#define VA_SPEAR6XX_ICM1_UART0_BASE IO_ADDRESS(SPEAR6XX_ICM1_UART0_BASE) +#define SPEAR6XX_ICM1_UART0_SIZE 0x00080000 + +#define SPEAR6XX_ICM1_UART1_BASE 0xD0080000 +#define SPEAR6XX_ICM1_UART1_SIZE 0x00080000 + +#define SPEAR6XX_ICM1_SSP0_BASE 0xD0100000 +#define SPEAR6XX_ICM1_SSP0_SIZE 0x00080000 + +#define SPEAR6XX_ICM1_SSP1_BASE 0xD0180000 +#define SPEAR6XX_ICM1_SSP1_SIZE 0x00080000 + +#define SPEAR6XX_ICM1_I2C_BASE 0xD0200000 +#define SPEAR6XX_ICM1_I2C_SIZE 0x00080000 + +#define SPEAR6XX_ICM1_JPEG_BASE 0xD0800000 +#define SPEAR6XX_ICM1_JPEG_SIZE 0x00800000 + +#define SPEAR6XX_ICM1_IRDA_BASE 0xD1000000 +#define SPEAR6XX_ICM1_IRDA_SIZE 0x00800000 + +#define SPEAR6XX_ICM1_FSMC_BASE 0xD1800000 +#define SPEAR6XX_ICM1_FSMC_SIZE 0x00800000 + +#define SPEAR6XX_ICM1_NAND_BASE 0xD2000000 +#define SPEAR6XX_ICM1_NAND_SIZE 0x00800000 + +#define SPEAR6XX_ICM1_SRAM_BASE 0xD2800000 +#define SPEAR6XX_ICM1_SRAM_SIZE 0x00800000 + +/* ICM2 - Application Subsystem */ +#define SPEAR6XX_ICM2_BASE 0xD8000000 +#define SPEAR6XX_ICM2_SIZE 0x08000000 + +#define SPEAR6XX_ICM2_TMR0_BASE 0xD8000000 +#define SPEAR6XX_ICM2_TMR0_SIZE 0x00080000 + +#define SPEAR6XX_ICM2_TMR1_BASE 0xD8080000 +#define SPEAR6XX_ICM2_TMR1_SIZE 0x00080000 + +#define SPEAR6XX_ICM2_GPIO_BASE 0xD8100000 +#define SPEAR6XX_ICM2_GPIO_SIZE 0x00080000 + +#define SPEAR6XX_ICM2_SPI2_BASE 0xD8180000 +#define SPEAR6XX_ICM2_SPI2_SIZE 0x00080000 + +#define SPEAR6XX_ICM2_ADC_BASE 0xD8200000 +#define SPEAR6XX_ICM2_ADC_SIZE 0x00080000 + +/* ML-1, 2 - Multi Layer CPU Subsystem */ +#define SPEAR6XX_ML_CPU_BASE 0xF0000000 +#define SPEAR6XX_ML_CPU_SIZE 0x08000000 + +#define SPEAR6XX_CPU_TMR_BASE 0xF0000000 +#define SPEAR6XX_CPU_TMR_SIZE 0x00100000 + +#define SPEAR6XX_CPU_GPIO_BASE 0xF0100000 +#define SPEAR6XX_CPU_GPIO_SIZE 0x00100000 + +#define SPEAR6XX_CPU_VIC_SEC_BASE 0xF1000000 +#define VA_SPEAR6XX_CPU_VIC_SEC_BASE IO_ADDRESS(SPEAR6XX_CPU_VIC_SEC_BASE) +#define SPEAR6XX_CPU_VIC_SEC_SIZE 0x00100000 + +#define SPEAR6XX_CPU_VIC_PRI_BASE 0xF1100000 +#define VA_SPEAR6XX_CPU_VIC_PRI_BASE IO_ADDRESS(SPEAR6XX_CPU_VIC_PRI_BASE) +#define SPEAR6XX_CPU_VIC_PRI_SIZE 0x00100000 + +/* ICM3 - Basic Subsystem */ +#define SPEAR6XX_ICM3_BASE 0xF8000000 +#define SPEAR6XX_ICM3_SIZE 0x08000000 + +#define SPEAR6XX_ICM3_SMEM_BASE 0xF8000000 +#define SPEAR6XX_ICM3_SMEM_SIZE 0x04000000 + +#define SPEAR6XX_ICM3_SMI_CTRL_BASE 0xFC000000 +#define SPEAR6XX_ICM3_SMI_CTRL_SIZE 0x00200000 + +#define SPEAR6XX_ICM3_CLCD_BASE 0xFC200000 +#define SPEAR6XX_ICM3_CLCD_SIZE 0x00200000 + +#define SPEAR6XX_ICM3_DMA_BASE 0xFC400000 +#define SPEAR6XX_ICM3_DMA_SIZE 0x00200000 + +#define SPEAR6XX_ICM3_SDRAM_CTRL_BASE 0xFC600000 +#define SPEAR6XX_ICM3_SDRAM_CTRL_SIZE 0x00200000 + +#define SPEAR6XX_ICM3_TMR_BASE 0xFC800000 +#define SPEAR6XX_ICM3_TMR_SIZE 0x00080000 + +#define SPEAR6XX_ICM3_WDT_BASE 0xFC880000 +#define SPEAR6XX_ICM3_WDT_SIZE 0x00080000 + +#define SPEAR6XX_ICM3_RTC_BASE 0xFC900000 +#define SPEAR6XX_ICM3_RTC_SIZE 0x00080000 + +#define SPEAR6XX_ICM3_GPIO_BASE 0xFC980000 +#define SPEAR6XX_ICM3_GPIO_SIZE 0x00080000 + +#define SPEAR6XX_ICM3_SYS_CTRL_BASE 0xFCA00000 +#define VA_SPEAR6XX_ICM3_SYS_CTRL_BASE IO_ADDRESS(SPEAR6XX_ICM3_SYS_CTRL_BASE) +#define SPEAR6XX_ICM3_SYS_CTRL_SIZE 0x00080000 + +#define SPEAR6XX_ICM3_MISC_REG_BASE 0xFCA80000 +#define VA_SPEAR6XX_ICM3_MISC_REG_BASE IO_ADDRESS(SPEAR6XX_ICM3_MISC_REG_BASE) +#define SPEAR6XX_ICM3_MISC_REG_SIZE 0x00080000 + +/* ICM4 - High Speed Connection */ +#define SPEAR6XX_ICM4_BASE 0xE0000000 +#define SPEAR6XX_ICM4_SIZE 0x08000000 + +#define SPEAR6XX_ICM4_GMAC_BASE 0xE0800000 +#define SPEAR6XX_ICM4_GMAC_SIZE 0x00800000 + +#define SPEAR6XX_ICM4_USBD_FIFO_BASE 0xE1000000 +#define SPEAR6XX_ICM4_USBD_FIFO_SIZE 0x00100000 + +#define SPEAR6XX_ICM4_USBD_CSR_BASE 0xE1100000 +#define SPEAR6XX_ICM4_USBD_CSR_SIZE 0x00100000 + +#define SPEAR6XX_ICM4_USBD_PLDT_BASE 0xE1200000 +#define SPEAR6XX_ICM4_USBD_PLDT_SIZE 0x00100000 + +#define SPEAR6XX_ICM4_USB_EHCI0_BASE 0xE1800000 +#define SPEAR6XX_ICM4_USB_EHCI0_SIZE 0x00100000 + +#define SPEAR6XX_ICM4_USB_OHCI0_BASE 0xE1900000 +#define SPEAR6XX_ICM4_USB_OHCI0_SIZE 0x00100000 + +#define SPEAR6XX_ICM4_USB_EHCI1_BASE 0xE2000000 +#define SPEAR6XX_ICM4_USB_EHCI1_SIZE 0x00100000 + +#define SPEAR6XX_ICM4_USB_OHCI1_BASE 0xE2100000 +#define SPEAR6XX_ICM4_USB_OHCI1_SIZE 0x00100000 + +#define SPEAR6XX_ICM4_USB_ARB_BASE 0xE2800000 +#define SPEAR6XX_ICM4_USB_ARB_SIZE 0x00010000 + +/* Debug uart for linux, will be used for debug and uncompress messages */ +#define SPEAR_DBG_UART_BASE SPEAR6XX_ICM1_UART0_BASE +#define VA_SPEAR_DBG_UART_BASE VA_SPEAR6XX_ICM1_UART0_BASE + +/* Sysctl base for spear platform */ +#define SPEAR_SYS_CTRL_BASE SPEAR6XX_ICM3_SYS_CTRL_BASE +#define VA_SPEAR_SYS_CTRL_BASE VA_SPEAR6XX_ICM3_SYS_CTRL_BASE + +#endif /* __MACH_SPEAR6XX_H */ diff --git a/arch/arm/mach-spear6xx/include/mach/spear600.h b/arch/arm/mach-spear6xx/include/mach/spear600.h new file mode 100644 index 0000000..c068cc5 --- /dev/null +++ b/arch/arm/mach-spear6xx/include/mach/spear600.h @@ -0,0 +1,21 @@ +/* + * arch/arm/mach-spear66xx/include/mach/spear600.h + * + * SPEAr600 Machine specific definition + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifdef CONFIG_MACH_SPEAR600 + +#ifndef __MACH_SPEAR600_H +#define __MACH_SPEAR600_H + +#endif /* __MACH_SPEAR600_H */ + +#endif /* CONFIG_MACH_SPEAR600 */ diff --git a/arch/arm/mach-spear6xx/include/mach/system.h b/arch/arm/mach-spear6xx/include/mach/system.h new file mode 100644 index 0000000..0b1d2be --- /dev/null +++ b/arch/arm/mach-spear6xx/include/mach/system.h @@ -0,0 +1,19 @@ +/* + * arch/arm/mach-spear6xx/include/mach/system.h + * + * SPEAr6xx Machine family specific architecture functions + * + * Copyright (C) 2009 ST Microelectronics + * Rajeev Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __MACH_SYSTEM_H +#define __MACH_SYSTEM_H + +#include + +#endif /* __MACH_SYSTEM_H */ diff --git a/arch/arm/mach-spear6xx/include/mach/timex.h b/arch/arm/mach-spear6xx/include/mach/timex.h new file mode 100644 index 0000000..ac1c5b0 --- /dev/null +++ b/arch/arm/mach-spear6xx/include/mach/timex.h @@ -0,0 +1,19 @@ +/* + * arch/arm/mach-spear6xx/include/mach/timex.h + * + * SPEAr6XX machine family specific timex definitions + * + * Copyright (C) 2009 ST Microelectronics + * Rajeev Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __MACH_TIMEX_H +#define __MACH_TIMEX_H + +#include + +#endif /* __MACH_TIMEX_H */ diff --git a/arch/arm/mach-spear6xx/include/mach/uncompress.h b/arch/arm/mach-spear6xx/include/mach/uncompress.h new file mode 100644 index 0000000..77f0765 --- /dev/null +++ b/arch/arm/mach-spear6xx/include/mach/uncompress.h @@ -0,0 +1,19 @@ +/* + * arch/arm/mach-spear6xx/include/mach/uncompress.h + * + * Serial port stubs for kernel decompress status messages + * + * Copyright (C) 2009 ST Microelectronics + * Rajeev Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __MACH_UNCOMPRESS_H +#define __MACH_UNCOMPRESS_H + +#include + +#endif /* __MACH_UNCOMPRESS_H */ diff --git a/arch/arm/mach-spear6xx/include/mach/vmalloc.h b/arch/arm/mach-spear6xx/include/mach/vmalloc.h new file mode 100644 index 0000000..4a0b56c --- /dev/null +++ b/arch/arm/mach-spear6xx/include/mach/vmalloc.h @@ -0,0 +1,19 @@ +/* + * arch/arm/mach-spear6xx/include/mach/vmalloc.h + * + * Defining Vmalloc area for SPEAr6xx machine family + * + * Copyright (C) 2009 ST Microelectronics + * Rajeev Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __MACH_VMALLOC_H +#define __MACH_VMALLOC_H + +#include + +#endif /* __MACH_VMALLOC_H */ -- cgit v0.10.2 From bf976b51a32e255523c69022c1f21bf9ad527fc5 Mon Sep 17 00:00:00 2001 From: viresh kumar Date: Thu, 1 Apr 2010 12:30:42 +0100 Subject: ARM: 6012/1: ST SPEAr: Added basic header files for SPEAr platform Reviewed-by: Linus Walleij Signed-off-by: Viresh Kumar Signed-off-by: Shiraz Hashim Signed-off-by: Russell King diff --git a/arch/arm/plat-spear/include/plat/debug-macro.S b/arch/arm/plat-spear/include/plat/debug-macro.S new file mode 100644 index 0000000..1670734 --- /dev/null +++ b/arch/arm/plat-spear/include/plat/debug-macro.S @@ -0,0 +1,38 @@ +/* + * arch/arm/plat-spear/include/plat/debug-macro.S + * + * Debugging macro include header for spear platform + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include + + .macro addruart, rx + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 @ MMU enabled? + moveq \rx, =SPEAR_DBG_UART_BASE @ Physical base + movne \rx, =VA_SPEAR_DBG_UART_BASE @ Virtual base + .endm + + .macro senduart, rd, rx + strb \rd, [\rx, #UART01x_DR] @ ASC_TX_BUFFER + .endm + + .macro waituart, rd, rx +1001: ldr \rd, [\rx, #UART01x_FR] @ FLAG REGISTER + tst \rd, #UART01x_FR_TXFF @ TX_FULL + bne 1001b + .endm + + .macro busyuart, rd, rx +1002: ldr \rd, [\rx, #UART01x_FR] @ FLAG REGISTER + tst \rd, #UART011_FR_TXFE @ TX_EMPTY + beq 1002b + .endm diff --git a/arch/arm/plat-spear/include/plat/gpio.h b/arch/arm/plat-spear/include/plat/gpio.h new file mode 100644 index 0000000..b857c91 --- /dev/null +++ b/arch/arm/plat-spear/include/plat/gpio.h @@ -0,0 +1,24 @@ +/* + * arch/arm/plat-spear/include/plat/gpio.h + * + * GPIO macros for SPEAr platform + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __PLAT_GPIO_H +#define __PLAT_GPIO_H + +#include + +#define gpio_get_value __gpio_get_value +#define gpio_set_value __gpio_set_value +#define gpio_cansleep __gpio_cansleep +#define gpio_to_irq __gpio_to_irq + +#endif /* __PLAT_GPIO_H */ diff --git a/arch/arm/plat-spear/include/plat/io.h b/arch/arm/plat-spear/include/plat/io.h new file mode 100644 index 0000000..4d4ba82 --- /dev/null +++ b/arch/arm/plat-spear/include/plat/io.h @@ -0,0 +1,22 @@ +/* + * arch/arm/plat-spear/include/plat/io.h + * + * IO definitions for SPEAr platform + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __PLAT_IO_H +#define __PLAT_IO_H + +#define IO_SPACE_LIMIT 0xFFFFFFFF + +#define __io(a) __typesafe_io(a) +#define __mem_pci(a) (a) + +#endif /* __PLAT_IO_H */ diff --git a/arch/arm/plat-spear/include/plat/memory.h b/arch/arm/plat-spear/include/plat/memory.h new file mode 100644 index 0000000..27a4aba --- /dev/null +++ b/arch/arm/plat-spear/include/plat/memory.h @@ -0,0 +1,20 @@ +/* + * arch/arm/plat-spear/include/plat/memory.h + * + * Memory map for SPEAr platform + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __PLAT_MEMORY_H +#define __PLAT_MEMORY_H + +/* Physical DRAM offset */ +#define PHYS_OFFSET UL(0x00000000) + +#endif /* __PLAT_MEMORY_H */ diff --git a/arch/arm/plat-spear/include/plat/system.h b/arch/arm/plat-spear/include/plat/system.h new file mode 100644 index 0000000..55a4e40 --- /dev/null +++ b/arch/arm/plat-spear/include/plat/system.h @@ -0,0 +1,41 @@ +/* + * arch/arm/plat-spear/include/plat/system.h + * + * SPEAr platform specific architecture functions + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __PLAT_SYSTEM_H +#define __PLAT_SYSTEM_H + +#include +#include +#include + +static inline void arch_idle(void) +{ + /* + * This should do all the clock switching + * and wait for interrupt tricks + */ + cpu_do_idle(); +} + +static inline void arch_reset(char mode, const char *cmd) +{ + if (mode == 's') { + /* software reset, Jump into ROM at address 0 */ + cpu_reset(0); + } else { + /* hardware reset, Use on-chip reset capability */ + sysctl_soft_reset((void __iomem *)VA_SPEAR_SYS_CTRL_BASE); + } +} + +#endif /* __PLAT_SYSTEM_H */ diff --git a/arch/arm/plat-spear/include/plat/timex.h b/arch/arm/plat-spear/include/plat/timex.h new file mode 100644 index 0000000..914d09d --- /dev/null +++ b/arch/arm/plat-spear/include/plat/timex.h @@ -0,0 +1,19 @@ +/* + * arch/arm/plat-spear/include/plat/timex.h + * + * SPEAr platform specific timex definitions + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __PLAT_TIMEX_H +#define __PLAT_TIMEX_H + +#define CLOCK_TICK_RATE 48000000 + +#endif /* __PLAT_TIMEX_H */ diff --git a/arch/arm/plat-spear/include/plat/uncompress.h b/arch/arm/plat-spear/include/plat/uncompress.h new file mode 100644 index 0000000..99ba678 --- /dev/null +++ b/arch/arm/plat-spear/include/plat/uncompress.h @@ -0,0 +1,43 @@ +/* + * arch/arm/plat-spear/include/plat/uncompress.h + * + * Serial port stubs for kernel decompress status messages + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include + +#ifndef __PLAT_UNCOMPRESS_H +#define __PLAT_UNCOMPRESS_H +/* + * This does not append a newline + */ +static inline void putc(int c) +{ + void __iomem *base = (void __iomem *)SPEAR_DBG_UART_BASE; + + while (readl(base + UART01x_FR) & UART01x_FR_TXFF) + barrier(); + + writel(c, base + UART01x_DR); +} + +static inline void flush(void) +{ +} + +/* + * nothing to do + */ +#define arch_decomp_setup() +#define arch_decomp_wdog() + +#endif /* __PLAT_UNCOMPRESS_H */ diff --git a/arch/arm/plat-spear/include/plat/vmalloc.h b/arch/arm/plat-spear/include/plat/vmalloc.h new file mode 100644 index 0000000..09e9372 --- /dev/null +++ b/arch/arm/plat-spear/include/plat/vmalloc.h @@ -0,0 +1,19 @@ +/* + * arch/arm/plat-spear/include/plat/vmalloc.h + * + * Defining Vmalloc area for SPEAr platform + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __PLAT_VMALLOC_H +#define __PLAT_VMALLOC_H + +#define VMALLOC_END 0xF0000000 + +#endif /* __PLAT_VMALLOC_H */ -- cgit v0.10.2 From 986435e3596cbae662b86812e4563fbb6013b994 Mon Sep 17 00:00:00 2001 From: viresh kumar Date: Thu, 1 Apr 2010 12:30:49 +0100 Subject: ARM: 6013/1: ST SPEAr: Added source files for SPEAr platform Reviewed-by: Linus Walleij Signed-off-by: Viresh Kumar Signed-off-by: Shiraz Hashim Signed-off-by: Russell King diff --git a/arch/arm/plat-spear/Kconfig b/arch/arm/plat-spear/Kconfig new file mode 100644 index 0000000..1bb3dbc --- /dev/null +++ b/arch/arm/plat-spear/Kconfig @@ -0,0 +1,31 @@ +# +# SPEAr Platform configuration file +# + +if PLAT_SPEAR + +choice + prompt "ST SPEAr Family" + default ARCH_SPEAR3XX + +config ARCH_SPEAR3XX + bool "SPEAr3XX" + select ARM_VIC + select CPU_ARM926T + help + Supports for ARM's SPEAR3XX family + +config ARCH_SPEAR6XX + bool "SPEAr6XX" + select ARM_VIC + select CPU_ARM926T + help + Supports for ARM's SPEAR6XX family + +endchoice + +# Adding SPEAr machine specific configuration files +source "arch/arm/mach-spear3xx/Kconfig" +source "arch/arm/mach-spear6xx/Kconfig" + +endif diff --git a/arch/arm/plat-spear/Makefile b/arch/arm/plat-spear/Makefile new file mode 100644 index 0000000..96f9ac3 --- /dev/null +++ b/arch/arm/plat-spear/Makefile @@ -0,0 +1,6 @@ +# +# SPEAr Platform specific Makefile +# + +# Common support +obj-y := clock.o time.o diff --git a/arch/arm/plat-spear/time.c b/arch/arm/plat-spear/time.c new file mode 100644 index 0000000..a1025d3 --- /dev/null +++ b/arch/arm/plat-spear/time.c @@ -0,0 +1,292 @@ +/* + * arch/arm/plat-spear/time.c + * + * Copyright (C) 2009 ST Microelectronics + * Shiraz Hashim + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * We would use TIMER0 and TIMER1 as clockevent and clocksource. + * Timer0 and Timer1 both belong to same gpt block in cpu subbsystem. Further + * they share same functional clock. Any change in one's functional clock will + * also affect other timer. + */ + +#define CLKEVT 0 /* gpt0, channel0 as clockevent */ +#define CLKSRC 1 /* gpt0, channel1 as clocksource */ + +/* Register offsets, x is channel number */ +#define CR(x) ((x) * 0x80 + 0x80) +#define IR(x) ((x) * 0x80 + 0x84) +#define LOAD(x) ((x) * 0x80 + 0x88) +#define COUNT(x) ((x) * 0x80 + 0x8C) + +/* Reg bit definitions */ +#define CTRL_INT_ENABLE 0x0100 +#define CTRL_ENABLE 0x0020 +#define CTRL_ONE_SHOT 0x0010 + +#define CTRL_PRESCALER1 0x0 +#define CTRL_PRESCALER2 0x1 +#define CTRL_PRESCALER4 0x2 +#define CTRL_PRESCALER8 0x3 +#define CTRL_PRESCALER16 0x4 +#define CTRL_PRESCALER32 0x5 +#define CTRL_PRESCALER64 0x6 +#define CTRL_PRESCALER128 0x7 +#define CTRL_PRESCALER256 0x8 + +#define INT_STATUS 0x1 + +static __iomem void *gpt_base; +static struct clk *gpt_clk; + +static void clockevent_set_mode(enum clock_event_mode mode, + struct clock_event_device *clk_event_dev); +static int clockevent_next_event(unsigned long evt, + struct clock_event_device *clk_event_dev); + +/* + * Following clocksource_set_clock and clockevent_set_clock picked + * from arch/mips/kernel/time.c + */ + +void __init clocksource_set_clock(struct clocksource *cs, unsigned int clock) +{ + u64 temp; + u32 shift; + + /* Find a shift value */ + for (shift = 32; shift > 0; shift--) { + temp = (u64) NSEC_PER_SEC << shift; + do_div(temp, clock); + if ((temp >> 32) == 0) + break; + } + cs->shift = shift; + cs->mult = (u32) temp; +} + +void __init clockevent_set_clock(struct clock_event_device *cd, + unsigned int clock) +{ + u64 temp; + u32 shift; + + /* Find a shift value */ + for (shift = 32; shift > 0; shift--) { + temp = (u64) clock << shift; + do_div(temp, NSEC_PER_SEC); + if ((temp >> 32) == 0) + break; + } + cd->shift = shift; + cd->mult = (u32) temp; +} + +static cycle_t clocksource_read_cycles(struct clocksource *cs) +{ + return (cycle_t) readw(gpt_base + COUNT(CLKSRC)); +} + +static struct clocksource clksrc = { + .name = "tmr1", + .rating = 200, /* its a pretty decent clock */ + .read = clocksource_read_cycles, + .mask = 0xFFFF, /* 16 bits */ + .mult = 0, /* to be computed */ + .shift = 0, /* to be computed */ + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static void spear_clocksource_init(void) +{ + u32 tick_rate; + u16 val; + + /* program the prescaler (/256)*/ + writew(CTRL_PRESCALER256, gpt_base + CR(CLKSRC)); + + /* find out actual clock driving Timer */ + tick_rate = clk_get_rate(gpt_clk); + tick_rate >>= CTRL_PRESCALER256; + + writew(0xFFFF, gpt_base + LOAD(CLKSRC)); + + val = readw(gpt_base + CR(CLKSRC)); + val &= ~CTRL_ONE_SHOT; /* autoreload mode */ + val |= CTRL_ENABLE ; + writew(val, gpt_base + CR(CLKSRC)); + + clocksource_set_clock(&clksrc, tick_rate); + + /* register the clocksource */ + clocksource_register(&clksrc); +} + +static struct clock_event_device clkevt = { + .name = "tmr0", + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + .set_mode = clockevent_set_mode, + .set_next_event = clockevent_next_event, + .shift = 0, /* to be computed */ +}; + +static void clockevent_set_mode(enum clock_event_mode mode, + struct clock_event_device *clk_event_dev) +{ + u32 period; + u16 val; + + /* stop the timer */ + val = readw(gpt_base + CR(CLKEVT)); + val &= ~CTRL_ENABLE; + writew(val, gpt_base + CR(CLKEVT)); + + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + period = clk_get_rate(gpt_clk) / HZ; + period >>= CTRL_PRESCALER16; + writew(period, gpt_base + LOAD(CLKEVT)); + + val = readw(gpt_base + CR(CLKEVT)); + val &= ~CTRL_ONE_SHOT; + val |= CTRL_ENABLE | CTRL_INT_ENABLE; + writew(val, gpt_base + CR(CLKEVT)); + + break; + case CLOCK_EVT_MODE_ONESHOT: + val = readw(gpt_base + CR(CLKEVT)); + val |= CTRL_ONE_SHOT; + writew(val, gpt_base + CR(CLKEVT)); + + break; + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_RESUME: + + break; + default: + pr_err("Invalid mode requested\n"); + break; + } +} + +static int clockevent_next_event(unsigned long cycles, + struct clock_event_device *clk_event_dev) +{ + u16 val; + + writew(cycles, gpt_base + LOAD(CLKEVT)); + + val = readw(gpt_base + CR(CLKEVT)); + val |= CTRL_ENABLE | CTRL_INT_ENABLE; + writew(val, gpt_base + CR(CLKEVT)); + + return 0; +} + +static irqreturn_t spear_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = &clkevt; + + writew(INT_STATUS, gpt_base + IR(CLKEVT)); + + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +static struct irqaction spear_timer_irq = { + .name = "timer", + .flags = IRQF_DISABLED | IRQF_TIMER, + .handler = spear_timer_interrupt +}; + +static void __init spear_clockevent_init(void) +{ + u32 tick_rate; + + /* program the prescaler */ + writew(CTRL_PRESCALER16, gpt_base + CR(CLKEVT)); + + tick_rate = clk_get_rate(gpt_clk); + tick_rate >>= CTRL_PRESCALER16; + + clockevent_set_clock(&clkevt, tick_rate); + + clkevt.max_delta_ns = clockevent_delta2ns(0xfff0, + &clkevt); + clkevt.min_delta_ns = clockevent_delta2ns(3, &clkevt); + + clkevt.cpumask = cpumask_of(0); + + clockevents_register_device(&clkevt); + + setup_irq(SPEAR_GPT0_CHAN0_IRQ, &spear_timer_irq); +} + +void __init spear_setup_timer(void) +{ + struct clk *pll3_clk; + + if (!request_mem_region(SPEAR_GPT0_BASE, SZ_1K, "gpt0")) { + pr_err("%s:cannot get IO addr\n", __func__); + return; + } + + gpt_base = (void __iomem *)ioremap(SPEAR_GPT0_BASE, SZ_1K); + if (!gpt_base) { + pr_err("%s:ioremap failed for gpt\n", __func__); + goto err_mem; + } + + gpt_clk = clk_get_sys("gpt0", NULL); + if (!gpt_clk) { + pr_err("%s:couldn't get clk for gpt\n", __func__); + goto err_iomap; + } + + pll3_clk = clk_get(NULL, "pll3_48m_clk"); + if (!pll3_clk) { + pr_err("%s:couldn't get PLL3 as parent for gpt\n", __func__); + goto err_iomap; + } + + clk_set_parent(gpt_clk, pll3_clk); + + spear_clockevent_init(); + spear_clocksource_init(); + + return; + +err_iomap: + iounmap(gpt_base); + +err_mem: + release_mem_region(SPEAR_GPT0_BASE, SZ_1K); +} + +struct sys_timer spear_sys_timer = { + .init = spear_setup_timer, +}; -- cgit v0.10.2 From 8c0236fc465c71d98203bcf5609db01b9cf5f70f Mon Sep 17 00:00:00 2001 From: viresh kumar Date: Thu, 1 Apr 2010 12:30:46 +0100 Subject: ARM: 6014/1: ST SPEAr: Added clock framework for SPEAr platform and machines Clock framework for SPEAr is based upon clkdev framework for ARM Reviewed-by: Linus Walleij Signed-off-by: Viresh Kumar Signed-off-by: Russell King diff --git a/arch/arm/mach-spear3xx/clock.c b/arch/arm/mach-spear3xx/clock.c new file mode 100644 index 0000000..39f6ccf --- /dev/null +++ b/arch/arm/mach-spear3xx/clock.c @@ -0,0 +1,389 @@ +/* + * arch/arm/mach-spear3xx/clock.c + * + * SPEAr3xx machines clock framework source file + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include + +/* root clks */ +/* 32 KHz oscillator clock */ +static struct clk osc_32k_clk = { + .flags = ALWAYS_ENABLED, + .rate = 32000, +}; + +/* 24 MHz oscillator clock */ +static struct clk osc_24m_clk = { + .flags = ALWAYS_ENABLED, + .rate = 24000000, +}; + +/* clock derived from 32 KHz osc clk */ +/* rtc clock */ +static struct clk rtc_clk = { + .pclk = &osc_32k_clk, + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = RTC_CLK_ENB, + .recalc = &follow_parent, +}; + +/* clock derived from 24 MHz osc clk */ +/* pll1 configuration structure */ +static struct pll_clk_config pll1_config = { + .mode_reg = PLL1_CTR, + .cfg_reg = PLL1_FRQ, +}; + +/* PLL1 clock */ +static struct clk pll1_clk = { + .pclk = &osc_24m_clk, + .en_reg = PLL1_CTR, + .en_reg_bit = PLL_ENABLE, + .recalc = &pll1_clk_recalc, + .private_data = &pll1_config, +}; + +/* PLL3 48 MHz clock */ +static struct clk pll3_48m_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &osc_24m_clk, + .rate = 48000000, +}; + +/* watch dog timer clock */ +static struct clk wdt_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &osc_24m_clk, + .recalc = &follow_parent, +}; + +/* clock derived from pll1 clk */ +/* cpu clock */ +static struct clk cpu_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &pll1_clk, + .recalc = &follow_parent, +}; + +/* ahb configuration structure */ +static struct bus_clk_config ahb_config = { + .reg = CORE_CLK_CFG, + .mask = PLL_HCLK_RATIO_MASK, + .shift = PLL_HCLK_RATIO_SHIFT, +}; + +/* ahb clock */ +static struct clk ahb_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &pll1_clk, + .recalc = &bus_clk_recalc, + .private_data = &ahb_config, +}; + +/* uart configurations */ +static struct aux_clk_config uart_config = { + .synth_reg = UART_CLK_SYNT, +}; + +/* uart parents */ +static struct pclk_info uart_pclk_info[] = { + { + .pclk = &pll1_clk, + .pclk_mask = AUX_CLK_PLL1_MASK, + .scalable = 1, + }, { + .pclk = &pll3_48m_clk, + .pclk_mask = AUX_CLK_PLL3_MASK, + .scalable = 0, + }, +}; + +/* uart parent select structure */ +static struct pclk_sel uart_pclk_sel = { + .pclk_info = uart_pclk_info, + .pclk_count = ARRAY_SIZE(uart_pclk_info), + .pclk_sel_reg = PERIP_CLK_CFG, + .pclk_sel_mask = UART_CLK_MASK, +}; + +/* uart clock */ +static struct clk uart_clk = { + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = UART_CLK_ENB, + .pclk_sel = &uart_pclk_sel, + .pclk_sel_shift = UART_CLK_SHIFT, + .recalc = &aux_clk_recalc, + .private_data = &uart_config, +}; + +/* firda configurations */ +static struct aux_clk_config firda_config = { + .synth_reg = FIRDA_CLK_SYNT, +}; + +/* firda parents */ +static struct pclk_info firda_pclk_info[] = { + { + .pclk = &pll1_clk, + .pclk_mask = AUX_CLK_PLL1_MASK, + .scalable = 1, + }, { + .pclk = &pll3_48m_clk, + .pclk_mask = AUX_CLK_PLL3_MASK, + .scalable = 0, + }, +}; + +/* firda parent select structure */ +static struct pclk_sel firda_pclk_sel = { + .pclk_info = firda_pclk_info, + .pclk_count = ARRAY_SIZE(firda_pclk_info), + .pclk_sel_reg = PERIP_CLK_CFG, + .pclk_sel_mask = FIRDA_CLK_MASK, +}; + +/* firda clock */ +static struct clk firda_clk = { + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = FIRDA_CLK_ENB, + .pclk_sel = &firda_pclk_sel, + .pclk_sel_shift = FIRDA_CLK_SHIFT, + .recalc = &aux_clk_recalc, + .private_data = &firda_config, +}; + +/* gpt parents */ +static struct pclk_info gpt_pclk_info[] = { + { + .pclk = &pll1_clk, + .pclk_mask = AUX_CLK_PLL1_MASK, + .scalable = 1, + }, { + .pclk = &pll3_48m_clk, + .pclk_mask = AUX_CLK_PLL3_MASK, + .scalable = 0, + }, +}; + +/* gpt parent select structure */ +static struct pclk_sel gpt_pclk_sel = { + .pclk_info = gpt_pclk_info, + .pclk_count = ARRAY_SIZE(gpt_pclk_info), + .pclk_sel_reg = PERIP_CLK_CFG, + .pclk_sel_mask = GPT_CLK_MASK, +}; + +/* gpt0 configurations */ +static struct aux_clk_config gpt0_config = { + .synth_reg = PRSC1_CLK_CFG, +}; + +/* gpt0 timer clock */ +static struct clk gpt0_clk = { + .flags = ALWAYS_ENABLED, + .pclk_sel = &gpt_pclk_sel, + .pclk_sel_shift = GPT0_CLK_SHIFT, + .recalc = &gpt_clk_recalc, + .private_data = &gpt0_config, +}; + +/* gpt1 configurations */ +static struct aux_clk_config gpt1_config = { + .synth_reg = PRSC2_CLK_CFG, +}; + +/* gpt1 timer clock */ +static struct clk gpt1_clk = { + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = GPT1_CLK_ENB, + .pclk_sel = &gpt_pclk_sel, + .pclk_sel_shift = GPT1_CLK_SHIFT, + .recalc = &gpt_clk_recalc, + .private_data = &gpt1_config, +}; + +/* gpt2 configurations */ +static struct aux_clk_config gpt2_config = { + .synth_reg = PRSC3_CLK_CFG, +}; + +/* gpt2 timer clock */ +static struct clk gpt2_clk = { + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = GPT2_CLK_ENB, + .pclk_sel = &gpt_pclk_sel, + .pclk_sel_shift = GPT2_CLK_SHIFT, + .recalc = &gpt_clk_recalc, + .private_data = &gpt2_config, +}; + +/* clock derived from pll3 clk */ +/* usbh clock */ +static struct clk usbh_clk = { + .pclk = &pll3_48m_clk, + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = USBH_CLK_ENB, + .recalc = &follow_parent, +}; + +/* usbd clock */ +static struct clk usbd_clk = { + .pclk = &pll3_48m_clk, + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = USBD_CLK_ENB, + .recalc = &follow_parent, +}; + +/* clcd clock */ +static struct clk clcd_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &pll3_48m_clk, + .recalc = &follow_parent, +}; + +/* clock derived from ahb clk */ +/* apb configuration structure */ +static struct bus_clk_config apb_config = { + .reg = CORE_CLK_CFG, + .mask = HCLK_PCLK_RATIO_MASK, + .shift = HCLK_PCLK_RATIO_SHIFT, +}; + +/* apb clock */ +static struct clk apb_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &ahb_clk, + .recalc = &bus_clk_recalc, + .private_data = &apb_config, +}; + +/* i2c clock */ +static struct clk i2c_clk = { + .pclk = &ahb_clk, + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = I2C_CLK_ENB, + .recalc = &follow_parent, +}; + +/* dma clock */ +static struct clk dma_clk = { + .pclk = &ahb_clk, + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = DMA_CLK_ENB, + .recalc = &follow_parent, +}; + +/* jpeg clock */ +static struct clk jpeg_clk = { + .pclk = &ahb_clk, + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = JPEG_CLK_ENB, + .recalc = &follow_parent, +}; + +/* gmac clock */ +static struct clk gmac_clk = { + .pclk = &ahb_clk, + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = GMAC_CLK_ENB, + .recalc = &follow_parent, +}; + +/* smi clock */ +static struct clk smi_clk = { + .pclk = &ahb_clk, + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = SMI_CLK_ENB, + .recalc = &follow_parent, +}; + +/* c3 clock */ +static struct clk c3_clk = { + .pclk = &ahb_clk, + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = C3_CLK_ENB, + .recalc = &follow_parent, +}; + +/* clock derived from apb clk */ +/* adc clock */ +static struct clk adc_clk = { + .pclk = &apb_clk, + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = ADC_CLK_ENB, + .recalc = &follow_parent, +}; + +/* ssp clock */ +static struct clk ssp_clk = { + .pclk = &apb_clk, + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = SSP_CLK_ENB, + .recalc = &follow_parent, +}; + +/* gpio clock */ +static struct clk gpio_clk = { + .pclk = &apb_clk, + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = GPIO_CLK_ENB, + .recalc = &follow_parent, +}; + +/* array of all spear 3xx clock lookups */ +static struct clk_lookup spear_clk_lookups[] = { + /* root clks */ + { .con_id = "osc_32k_clk", .clk = &osc_32k_clk}, + { .con_id = "osc_24m_clk", .clk = &osc_24m_clk}, + /* clock derived from 32 KHz osc clk */ + { .dev_id = "rtc", .clk = &rtc_clk}, + /* clock derived from 24 MHz osc clk */ + { .con_id = "pll1_clk", .clk = &pll1_clk}, + { .con_id = "pll3_48m_clk", .clk = &pll3_48m_clk}, + { .dev_id = "wdt", .clk = &wdt_clk}, + /* clock derived from pll1 clk */ + { .con_id = "cpu_clk", .clk = &cpu_clk}, + { .con_id = "ahb_clk", .clk = &ahb_clk}, + { .dev_id = "uart", .clk = &uart_clk}, + { .dev_id = "firda", .clk = &firda_clk}, + { .dev_id = "gpt0", .clk = &gpt0_clk}, + { .dev_id = "gpt1", .clk = &gpt1_clk}, + { .dev_id = "gpt2", .clk = &gpt2_clk}, + /* clock derived from pll3 clk */ + { .dev_id = "usbh", .clk = &usbh_clk}, + { .dev_id = "usbd", .clk = &usbd_clk}, + { .dev_id = "clcd", .clk = &clcd_clk}, + /* clock derived from ahb clk */ + { .con_id = "apb_clk", .clk = &apb_clk}, + { .dev_id = "i2c", .clk = &i2c_clk}, + { .dev_id = "dma", .clk = &dma_clk}, + { .dev_id = "jpeg", .clk = &jpeg_clk}, + { .dev_id = "gmac", .clk = &gmac_clk}, + { .dev_id = "smi", .clk = &smi_clk}, + { .dev_id = "c3", .clk = &c3_clk}, + /* clock derived from apb clk */ + { .dev_id = "adc", .clk = &adc_clk}, + { .dev_id = "ssp", .clk = &ssp_clk}, + { .dev_id = "gpio", .clk = &gpio_clk}, +}; + +void __init clk_init(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(spear_clk_lookups); i++) + clk_register(&spear_clk_lookups[i]); + + recalc_root_clocks(); +} diff --git a/arch/arm/mach-spear3xx/include/mach/clkdev.h b/arch/arm/mach-spear3xx/include/mach/clkdev.h new file mode 100644 index 0000000..a3d0733 --- /dev/null +++ b/arch/arm/mach-spear3xx/include/mach/clkdev.h @@ -0,0 +1,19 @@ +/* + * arch/arm/mach-spear3xx/include/mach/clkdev.h + * + * Clock Dev framework definitions for SPEAr3xx machine family + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __MACH_CLKDEV_H +#define __MACH_CLKDEV_H + +#include + +#endif /* __MACH_CLKDEV_H */ diff --git a/arch/arm/mach-spear3xx/include/mach/misc_regs.h b/arch/arm/mach-spear3xx/include/mach/misc_regs.h old mode 100755 new mode 100644 diff --git a/arch/arm/mach-spear6xx/clock.c b/arch/arm/mach-spear6xx/clock.c new file mode 100644 index 0000000..13e27c7 --- /dev/null +++ b/arch/arm/mach-spear6xx/clock.c @@ -0,0 +1,483 @@ +/* + * arch/arm/mach-spear6xx/clock.c + * + * SPEAr6xx machines clock framework source file + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include + +/* root clks */ +/* 32 KHz oscillator clock */ +static struct clk osc_32k_clk = { + .flags = ALWAYS_ENABLED, + .rate = 32000, +}; + +/* 30 MHz oscillator clock */ +static struct clk osc_30m_clk = { + .flags = ALWAYS_ENABLED, + .rate = 30000000, +}; + +/* clock derived from 32 KHz osc clk */ +/* rtc clock */ +static struct clk rtc_clk = { + .pclk = &osc_32k_clk, + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = RTC_CLK_ENB, + .recalc = &follow_parent, +}; + +/* clock derived from 30 MHz osc clk */ +/* pll1 configuration structure */ +static struct pll_clk_config pll1_config = { + .mode_reg = PLL1_CTR, + .cfg_reg = PLL1_FRQ, +}; + +/* PLL1 clock */ +static struct clk pll1_clk = { + .pclk = &osc_30m_clk, + .en_reg = PLL1_CTR, + .en_reg_bit = PLL_ENABLE, + .recalc = &pll1_clk_recalc, + .private_data = &pll1_config, +}; + +/* PLL3 48 MHz clock */ +static struct clk pll3_48m_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &osc_30m_clk, + .rate = 48000000, +}; + +/* watch dog timer clock */ +static struct clk wdt_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &osc_30m_clk, + .recalc = &follow_parent, +}; + +/* clock derived from pll1 clk */ +/* cpu clock */ +static struct clk cpu_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &pll1_clk, + .recalc = &follow_parent, +}; + +/* ahb configuration structure */ +static struct bus_clk_config ahb_config = { + .reg = CORE_CLK_CFG, + .mask = PLL_HCLK_RATIO_MASK, + .shift = PLL_HCLK_RATIO_SHIFT, +}; + +/* ahb clock */ +static struct clk ahb_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &pll1_clk, + .recalc = &bus_clk_recalc, + .private_data = &ahb_config, +}; + +/* uart parents */ +static struct pclk_info uart_pclk_info[] = { + { + .pclk = &pll1_clk, + .pclk_mask = AUX_CLK_PLL1_MASK, + .scalable = 1, + }, { + .pclk = &pll3_48m_clk, + .pclk_mask = AUX_CLK_PLL3_MASK, + .scalable = 0, + }, +}; + +/* uart parent select structure */ +static struct pclk_sel uart_pclk_sel = { + .pclk_info = uart_pclk_info, + .pclk_count = ARRAY_SIZE(uart_pclk_info), + .pclk_sel_reg = PERIP_CLK_CFG, + .pclk_sel_mask = UART_CLK_MASK, +}; + +/* uart configurations */ +static struct aux_clk_config uart_config = { + .synth_reg = UART_CLK_SYNT, +}; + +/* uart0 clock */ +static struct clk uart0_clk = { + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = UART0_CLK_ENB, + .pclk_sel = &uart_pclk_sel, + .pclk_sel_shift = UART_CLK_SHIFT, + .recalc = &aux_clk_recalc, + .private_data = &uart_config, +}; + +/* uart1 clock */ +static struct clk uart1_clk = { + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = UART1_CLK_ENB, + .pclk_sel = &uart_pclk_sel, + .pclk_sel_shift = UART_CLK_SHIFT, + .recalc = &aux_clk_recalc, + .private_data = &uart_config, +}; + +/* firda configurations */ +static struct aux_clk_config firda_config = { + .synth_reg = FIRDA_CLK_SYNT, +}; + +/* firda parents */ +static struct pclk_info firda_pclk_info[] = { + { + .pclk = &pll1_clk, + .pclk_mask = AUX_CLK_PLL1_MASK, + .scalable = 1, + }, { + .pclk = &pll3_48m_clk, + .pclk_mask = AUX_CLK_PLL3_MASK, + .scalable = 0, + }, +}; + +/* firda parent select structure */ +static struct pclk_sel firda_pclk_sel = { + .pclk_info = firda_pclk_info, + .pclk_count = ARRAY_SIZE(firda_pclk_info), + .pclk_sel_reg = PERIP_CLK_CFG, + .pclk_sel_mask = FIRDA_CLK_MASK, +}; + +/* firda clock */ +static struct clk firda_clk = { + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = FIRDA_CLK_ENB, + .pclk_sel = &firda_pclk_sel, + .pclk_sel_shift = FIRDA_CLK_SHIFT, + .recalc = &aux_clk_recalc, + .private_data = &firda_config, +}; + +/* clcd configurations */ +static struct aux_clk_config clcd_config = { + .synth_reg = CLCD_CLK_SYNT, +}; + +/* clcd parents */ +static struct pclk_info clcd_pclk_info[] = { + { + .pclk = &pll1_clk, + .pclk_mask = AUX_CLK_PLL1_MASK, + .scalable = 1, + }, { + .pclk = &pll3_48m_clk, + .pclk_mask = AUX_CLK_PLL3_MASK, + .scalable = 0, + }, +}; + +/* clcd parent select structure */ +static struct pclk_sel clcd_pclk_sel = { + .pclk_info = clcd_pclk_info, + .pclk_count = ARRAY_SIZE(clcd_pclk_info), + .pclk_sel_reg = PERIP_CLK_CFG, + .pclk_sel_mask = CLCD_CLK_MASK, +}; + +/* clcd clock */ +static struct clk clcd_clk = { + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = CLCD_CLK_ENB, + .pclk_sel = &clcd_pclk_sel, + .pclk_sel_shift = CLCD_CLK_SHIFT, + .recalc = &aux_clk_recalc, + .private_data = &clcd_config, +}; + +/* gpt parents */ +static struct pclk_info gpt_pclk_info[] = { + { + .pclk = &pll1_clk, + .pclk_mask = AUX_CLK_PLL1_MASK, + .scalable = 1, + }, { + .pclk = &pll3_48m_clk, + .pclk_mask = AUX_CLK_PLL3_MASK, + .scalable = 0, + }, +}; + +/* gpt parent select structure */ +static struct pclk_sel gpt_pclk_sel = { + .pclk_info = gpt_pclk_info, + .pclk_count = ARRAY_SIZE(gpt_pclk_info), + .pclk_sel_reg = PERIP_CLK_CFG, + .pclk_sel_mask = GPT_CLK_MASK, +}; + +/* gpt0_1 configurations */ +static struct aux_clk_config gpt0_1_config = { + .synth_reg = PRSC1_CLK_CFG, +}; + +/* gpt0 ARM1 subsystem timer clock */ +static struct clk gpt0_clk = { + .flags = ALWAYS_ENABLED, + .pclk_sel = &gpt_pclk_sel, + .pclk_sel_shift = GPT0_CLK_SHIFT, + .recalc = &gpt_clk_recalc, + .private_data = &gpt0_1_config, +}; + +/* gpt1 timer clock */ +static struct clk gpt1_clk = { + .flags = ALWAYS_ENABLED, + .pclk_sel = &gpt_pclk_sel, + .pclk_sel_shift = GPT1_CLK_SHIFT, + .recalc = &gpt_clk_recalc, + .private_data = &gpt0_1_config, +}; + +/* gpt2 configurations */ +static struct aux_clk_config gpt2_config = { + .synth_reg = PRSC2_CLK_CFG, +}; + +/* gpt2 timer clock */ +static struct clk gpt2_clk = { + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = GPT2_CLK_ENB, + .pclk_sel = &gpt_pclk_sel, + .pclk_sel_shift = GPT2_CLK_SHIFT, + .recalc = &gpt_clk_recalc, + .private_data = &gpt2_config, +}; + +/* gpt3 configurations */ +static struct aux_clk_config gpt3_config = { + .synth_reg = PRSC3_CLK_CFG, +}; + +/* gpt3 timer clock */ +static struct clk gpt3_clk = { + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = GPT3_CLK_ENB, + .pclk_sel = &gpt_pclk_sel, + .pclk_sel_shift = GPT3_CLK_SHIFT, + .recalc = &gpt_clk_recalc, + .private_data = &gpt3_config, +}; + +/* clock derived from pll3 clk */ +/* usbh0 clock */ +static struct clk usbh0_clk = { + .pclk = &pll3_48m_clk, + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = USBH0_CLK_ENB, + .recalc = &follow_parent, +}; + +/* usbh1 clock */ +static struct clk usbh1_clk = { + .pclk = &pll3_48m_clk, + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = USBH1_CLK_ENB, + .recalc = &follow_parent, +}; + +/* usbd clock */ +static struct clk usbd_clk = { + .pclk = &pll3_48m_clk, + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = USBD_CLK_ENB, + .recalc = &follow_parent, +}; + +/* clock derived from ahb clk */ +/* apb configuration structure */ +static struct bus_clk_config apb_config = { + .reg = CORE_CLK_CFG, + .mask = HCLK_PCLK_RATIO_MASK, + .shift = HCLK_PCLK_RATIO_SHIFT, +}; + +/* apb clock */ +static struct clk apb_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &ahb_clk, + .recalc = &bus_clk_recalc, + .private_data = &apb_config, +}; + +/* i2c clock */ +static struct clk i2c_clk = { + .pclk = &ahb_clk, + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = I2C_CLK_ENB, + .recalc = &follow_parent, +}; + +/* dma clock */ +static struct clk dma_clk = { + .pclk = &ahb_clk, + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = DMA_CLK_ENB, + .recalc = &follow_parent, +}; + +/* jpeg clock */ +static struct clk jpeg_clk = { + .pclk = &ahb_clk, + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = JPEG_CLK_ENB, + .recalc = &follow_parent, +}; + +/* gmac clock */ +static struct clk gmac_clk = { + .pclk = &ahb_clk, + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = GMAC_CLK_ENB, + .recalc = &follow_parent, +}; + +/* smi clock */ +static struct clk smi_clk = { + .pclk = &ahb_clk, + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = SMI_CLK_ENB, + .recalc = &follow_parent, +}; + +/* fsmc clock */ +static struct clk fsmc_clk = { + .pclk = &ahb_clk, + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = FSMC_CLK_ENB, + .recalc = &follow_parent, +}; + +/* clock derived from apb clk */ +/* adc clock */ +static struct clk adc_clk = { + .pclk = &apb_clk, + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = ADC_CLK_ENB, + .recalc = &follow_parent, +}; + +/* ssp0 clock */ +static struct clk ssp0_clk = { + .pclk = &apb_clk, + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = SSP0_CLK_ENB, + .recalc = &follow_parent, +}; + +/* ssp1 clock */ +static struct clk ssp1_clk = { + .pclk = &apb_clk, + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = SSP1_CLK_ENB, + .recalc = &follow_parent, +}; + +/* ssp2 clock */ +static struct clk ssp2_clk = { + .pclk = &apb_clk, + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = SSP2_CLK_ENB, + .recalc = &follow_parent, +}; + +/* gpio0 ARM subsystem clock */ +static struct clk gpio0_clk = { + .flags = ALWAYS_ENABLED, + .pclk = &apb_clk, + .recalc = &follow_parent, +}; + +/* gpio1 clock */ +static struct clk gpio1_clk = { + .pclk = &apb_clk, + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = GPIO1_CLK_ENB, + .recalc = &follow_parent, +}; + +/* gpio2 clock */ +static struct clk gpio2_clk = { + .pclk = &apb_clk, + .en_reg = PERIP1_CLK_ENB, + .en_reg_bit = GPIO2_CLK_ENB, + .recalc = &follow_parent, +}; + +/* array of all spear 6xx clock lookups */ +static struct clk_lookup spear_clk_lookups[] = { + /* root clks */ + { .con_id = "osc_32k_clk", .clk = &osc_32k_clk}, + { .con_id = "osc_30m_clk", .clk = &osc_30m_clk}, + /* clock derived from 32 KHz os clk */ + { .dev_id = "rtc", .clk = &rtc_clk}, + /* clock derived from 30 MHz os clk */ + { .con_id = "pll1_clk", .clk = &pll1_clk}, + { .con_id = "pll3_48m_clk", .clk = &pll3_48m_clk}, + { .dev_id = "wdt", .clk = &wdt_clk}, + /* clock derived from pll1 clk */ + { .con_id = "cpu_clk", .clk = &cpu_clk}, + { .con_id = "ahb_clk", .clk = &ahb_clk}, + { .dev_id = "uart0", .clk = &uart0_clk}, + { .dev_id = "uart1", .clk = &uart1_clk}, + { .dev_id = "firda", .clk = &firda_clk}, + { .dev_id = "clcd", .clk = &clcd_clk}, + { .dev_id = "gpt0", .clk = &gpt0_clk}, + { .dev_id = "gpt1", .clk = &gpt1_clk}, + { .dev_id = "gpt2", .clk = &gpt2_clk}, + { .dev_id = "gpt3", .clk = &gpt3_clk}, + /* clock derived from pll3 clk */ + { .dev_id = "usbh0", .clk = &usbh0_clk}, + { .dev_id = "usbh1", .clk = &usbh1_clk}, + { .dev_id = "usbd", .clk = &usbd_clk}, + /* clock derived from ahb clk */ + { .con_id = "apb_clk", .clk = &apb_clk}, + { .dev_id = "i2c", .clk = &i2c_clk}, + { .dev_id = "dma", .clk = &dma_clk}, + { .dev_id = "jpeg", .clk = &jpeg_clk}, + { .dev_id = "gmac", .clk = &gmac_clk}, + { .dev_id = "smi", .clk = &smi_clk}, + { .dev_id = "fsmc", .clk = &fsmc_clk}, + /* clock derived from apb clk */ + { .dev_id = "adc", .clk = &adc_clk}, + { .dev_id = "ssp0", .clk = &ssp0_clk}, + { .dev_id = "ssp1", .clk = &ssp1_clk}, + { .dev_id = "ssp2", .clk = &ssp2_clk}, + { .dev_id = "gpio0", .clk = &gpio0_clk}, + { .dev_id = "gpio1", .clk = &gpio1_clk}, + { .dev_id = "gpio2", .clk = &gpio2_clk}, +}; + +void __init clk_init(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(spear_clk_lookups); i++) + clk_register(&spear_clk_lookups[i]); + + recalc_root_clocks(); +} diff --git a/arch/arm/mach-spear6xx/include/mach/clkdev.h b/arch/arm/mach-spear6xx/include/mach/clkdev.h new file mode 100644 index 0000000..05676bf --- /dev/null +++ b/arch/arm/mach-spear6xx/include/mach/clkdev.h @@ -0,0 +1,19 @@ +/* + * arch/arm/mach-spear6xx/include/mach/clkdev.h + * + * Clock Dev framework definitions for SPEAr6xx machine family + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __MACH_CLKDEV_H +#define __MACH_CLKDEV_H + +#include + +#endif /* __MACH_CLKDEV_H */ diff --git a/arch/arm/plat-spear/clock.c b/arch/arm/plat-spear/clock.c new file mode 100644 index 0000000..ee4f90e --- /dev/null +++ b/arch/arm/plat-spear/clock.c @@ -0,0 +1,435 @@ +/* + * arch/arm/plat-spear/clock.c + * + * Clock framework for SPEAr platform + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static DEFINE_SPINLOCK(clocks_lock); +static LIST_HEAD(root_clks); + +static void propagate_rate(struct list_head *); + +static int generic_clk_enable(struct clk *clk) +{ + unsigned int val; + + if (!clk->en_reg) + return -EFAULT; + + val = readl(clk->en_reg); + if (unlikely(clk->flags & RESET_TO_ENABLE)) + val &= ~(1 << clk->en_reg_bit); + else + val |= 1 << clk->en_reg_bit; + + writel(val, clk->en_reg); + + return 0; +} + +static void generic_clk_disable(struct clk *clk) +{ + unsigned int val; + + if (!clk->en_reg) + return; + + val = readl(clk->en_reg); + if (unlikely(clk->flags & RESET_TO_ENABLE)) + val |= 1 << clk->en_reg_bit; + else + val &= ~(1 << clk->en_reg_bit); + + writel(val, clk->en_reg); +} + +/* generic clk ops */ +static struct clkops generic_clkops = { + .enable = generic_clk_enable, + .disable = generic_clk_disable, +}; + +/* + * clk_enable - inform the system when the clock source should be running. + * @clk: clock source + * + * If the clock can not be enabled/disabled, this should return success. + * + * Returns success (0) or negative errno. + */ +int clk_enable(struct clk *clk) +{ + unsigned long flags; + int ret = 0; + + if (!clk || IS_ERR(clk)) + return -EFAULT; + + spin_lock_irqsave(&clocks_lock, flags); + if (clk->usage_count == 0) { + if (clk->ops && clk->ops->enable) + ret = clk->ops->enable(clk); + } + clk->usage_count++; + spin_unlock_irqrestore(&clocks_lock, flags); + + return ret; +} +EXPORT_SYMBOL(clk_enable); + +/* + * clk_disable - inform the system when the clock source is no longer required. + * @clk: clock source + * + * Inform the system that a clock source is no longer required by + * a driver and may be shut down. + * + * Implementation detail: if the clock source is shared between + * multiple drivers, clk_enable() calls must be balanced by the + * same number of clk_disable() calls for the clock source to be + * disabled. + */ +void clk_disable(struct clk *clk) +{ + unsigned long flags; + + if (!clk || IS_ERR(clk)) + return; + + WARN_ON(clk->usage_count == 0); + + spin_lock_irqsave(&clocks_lock, flags); + clk->usage_count--; + if (clk->usage_count == 0) { + if (clk->ops && clk->ops->disable) + clk->ops->disable(clk); + } + spin_unlock_irqrestore(&clocks_lock, flags); +} +EXPORT_SYMBOL(clk_disable); + +/** + * clk_get_rate - obtain the current clock rate (in Hz) for a clock source. + * This is only valid once the clock source has been enabled. + * @clk: clock source + */ +unsigned long clk_get_rate(struct clk *clk) +{ + unsigned long flags, rate; + + spin_lock_irqsave(&clocks_lock, flags); + rate = clk->rate; + spin_unlock_irqrestore(&clocks_lock, flags); + + return rate; +} +EXPORT_SYMBOL(clk_get_rate); + +/** + * clk_set_parent - set the parent clock source for this clock + * @clk: clock source + * @parent: parent clock source + * + * Returns success (0) or negative errno. + */ +int clk_set_parent(struct clk *clk, struct clk *parent) +{ + int i, found = 0, val = 0; + unsigned long flags; + + if (!clk || IS_ERR(clk) || !parent || IS_ERR(parent)) + return -EFAULT; + if (clk->usage_count) + return -EBUSY; + if (!clk->pclk_sel) + return -EPERM; + if (clk->pclk == parent) + return 0; + + for (i = 0; i < clk->pclk_sel->pclk_count; i++) { + if (clk->pclk_sel->pclk_info[i].pclk == parent) { + found = 1; + break; + } + } + + if (!found) + return -EINVAL; + + spin_lock_irqsave(&clocks_lock, flags); + /* reflect parent change in hardware */ + val = readl(clk->pclk_sel->pclk_sel_reg); + val &= ~(clk->pclk_sel->pclk_sel_mask << clk->pclk_sel_shift); + val |= clk->pclk_sel->pclk_info[i].pclk_mask << clk->pclk_sel_shift; + writel(val, clk->pclk_sel->pclk_sel_reg); + spin_unlock_irqrestore(&clocks_lock, flags); + + /* reflect parent change in software */ + clk->recalc(clk); + propagate_rate(&clk->children); + return 0; +} +EXPORT_SYMBOL(clk_set_parent); + +/* registers clock in platform clock framework */ +void clk_register(struct clk_lookup *cl) +{ + struct clk *clk = cl->clk; + unsigned long flags; + + if (!clk || IS_ERR(clk)) + return; + + spin_lock_irqsave(&clocks_lock, flags); + + INIT_LIST_HEAD(&clk->children); + if (clk->flags & ALWAYS_ENABLED) + clk->ops = NULL; + else if (!clk->ops) + clk->ops = &generic_clkops; + + /* root clock don't have any parents */ + if (!clk->pclk && !clk->pclk_sel) { + list_add(&clk->sibling, &root_clks); + /* add clocks with only one parent to parent's children list */ + } else if (clk->pclk && !clk->pclk_sel) { + list_add(&clk->sibling, &clk->pclk->children); + } else { + /* add clocks with > 1 parent to 1st parent's children list */ + list_add(&clk->sibling, + &clk->pclk_sel->pclk_info[0].pclk->children); + } + spin_unlock_irqrestore(&clocks_lock, flags); + + /* add clock to arm clockdev framework */ + clkdev_add(cl); +} + +/** + * propagate_rate - recalculate and propagate all clocks in list head + * + * Recalculates all root clocks in list head, which if the clock's .recalc is + * set correctly, should also propagate their rates. + */ +static void propagate_rate(struct list_head *lhead) +{ + struct clk *clkp, *_temp; + + list_for_each_entry_safe(clkp, _temp, lhead, sibling) { + if (clkp->recalc) + clkp->recalc(clkp); + propagate_rate(&clkp->children); + } +} + +/* returns current programmed clocks clock info structure */ +static struct pclk_info *pclk_info_get(struct clk *clk) +{ + unsigned int mask, i; + unsigned long flags; + struct pclk_info *info = NULL; + + spin_lock_irqsave(&clocks_lock, flags); + mask = (readl(clk->pclk_sel->pclk_sel_reg) >> clk->pclk_sel_shift) + & clk->pclk_sel->pclk_sel_mask; + + for (i = 0; i < clk->pclk_sel->pclk_count; i++) { + if (clk->pclk_sel->pclk_info[i].pclk_mask == mask) + info = &clk->pclk_sel->pclk_info[i]; + } + spin_unlock_irqrestore(&clocks_lock, flags); + + return info; +} + +/* + * Set pclk as cclk's parent and add clock sibling node to current parents + * children list + */ +static void change_parent(struct clk *cclk, struct clk *pclk) +{ + unsigned long flags; + + spin_lock_irqsave(&clocks_lock, flags); + list_del(&cclk->sibling); + list_add(&cclk->sibling, &pclk->children); + + cclk->pclk = pclk; + spin_unlock_irqrestore(&clocks_lock, flags); +} + +/* + * calculates current programmed rate of pll1 + * + * In normal mode + * rate = (2 * M[15:8] * Fin)/(N * 2^P) + * + * In Dithered mode + * rate = (2 * M[15:0] * Fin)/(256 * N * 2^P) + */ +void pll1_clk_recalc(struct clk *clk) +{ + struct pll_clk_config *config = clk->private_data; + unsigned int num = 2, den = 0, val, mode = 0; + unsigned long flags; + + spin_lock_irqsave(&clocks_lock, flags); + mode = (readl(config->mode_reg) >> PLL_MODE_SHIFT) & + PLL_MODE_MASK; + + val = readl(config->cfg_reg); + /* calculate denominator */ + den = (val >> PLL_DIV_P_SHIFT) & PLL_DIV_P_MASK; + den = 1 << den; + den *= (val >> PLL_DIV_N_SHIFT) & PLL_DIV_N_MASK; + + /* calculate numerator & denominator */ + if (!mode) { + /* Normal mode */ + num *= (val >> PLL_NORM_FDBK_M_SHIFT) & PLL_NORM_FDBK_M_MASK; + } else { + /* Dithered mode */ + num *= (val >> PLL_DITH_FDBK_M_SHIFT) & PLL_DITH_FDBK_M_MASK; + den *= 256; + } + + clk->rate = (((clk->pclk->rate/10000) * num) / den) * 10000; + spin_unlock_irqrestore(&clocks_lock, flags); +} + +/* calculates current programmed rate of ahb or apb bus */ +void bus_clk_recalc(struct clk *clk) +{ + struct bus_clk_config *config = clk->private_data; + unsigned int div; + unsigned long flags; + + spin_lock_irqsave(&clocks_lock, flags); + div = ((readl(config->reg) >> config->shift) & config->mask) + 1; + clk->rate = (unsigned long)clk->pclk->rate / div; + spin_unlock_irqrestore(&clocks_lock, flags); +} + +/* + * calculates current programmed rate of auxiliary synthesizers + * used by: UART, FIRDA + * + * Fout from synthesizer can be given from two equations: + * Fout1 = (Fin * X/Y)/2 + * Fout2 = Fin * X/Y + * + * Selection of eqn 1 or 2 is programmed in register + */ +void aux_clk_recalc(struct clk *clk) +{ + struct aux_clk_config *config = clk->private_data; + struct pclk_info *pclk_info = NULL; + unsigned int num = 1, den = 1, val, eqn; + unsigned long flags; + + /* get current programmed parent */ + pclk_info = pclk_info_get(clk); + if (!pclk_info) { + spin_lock_irqsave(&clocks_lock, flags); + clk->pclk = NULL; + clk->rate = 0; + spin_unlock_irqrestore(&clocks_lock, flags); + return; + } + + change_parent(clk, pclk_info->pclk); + + spin_lock_irqsave(&clocks_lock, flags); + if (pclk_info->scalable) { + val = readl(config->synth_reg); + + eqn = (val >> AUX_EQ_SEL_SHIFT) & AUX_EQ_SEL_MASK; + if (eqn == AUX_EQ1_SEL) + den *= 2; + + /* calculate numerator */ + num = (val >> AUX_XSCALE_SHIFT) & AUX_XSCALE_MASK; + + /* calculate denominator */ + den *= (val >> AUX_YSCALE_SHIFT) & AUX_YSCALE_MASK; + val = (((clk->pclk->rate/10000) * num) / den) * 10000; + } else + val = clk->pclk->rate; + + clk->rate = val; + spin_unlock_irqrestore(&clocks_lock, flags); +} + +/* + * calculates current programmed rate of gpt synthesizers + * Fout from synthesizer can be given from below equations: + * Fout= Fin/((2 ^ (N+1)) * (M+1)) + */ +void gpt_clk_recalc(struct clk *clk) +{ + struct aux_clk_config *config = clk->private_data; + struct pclk_info *pclk_info = NULL; + unsigned int div = 1, val; + unsigned long flags; + + pclk_info = pclk_info_get(clk); + if (!pclk_info) { + spin_lock_irqsave(&clocks_lock, flags); + clk->pclk = NULL; + clk->rate = 0; + spin_unlock_irqrestore(&clocks_lock, flags); + return; + } + + change_parent(clk, pclk_info->pclk); + + spin_lock_irqsave(&clocks_lock, flags); + if (pclk_info->scalable) { + val = readl(config->synth_reg); + div += (val >> GPT_MSCALE_SHIFT) & GPT_MSCALE_MASK; + div *= 1 << (((val >> GPT_NSCALE_SHIFT) & GPT_NSCALE_MASK) + 1); + } + + clk->rate = (unsigned long)clk->pclk->rate / div; + spin_unlock_irqrestore(&clocks_lock, flags); +} + +/* + * Used for clocks that always have same value as the parent clock divided by a + * fixed divisor + */ +void follow_parent(struct clk *clk) +{ + unsigned long flags; + + spin_lock_irqsave(&clocks_lock, flags); + clk->rate = clk->pclk->rate; + spin_unlock_irqrestore(&clocks_lock, flags); +} + +/** + * recalc_root_clocks - recalculate and propagate all root clocks + * + * Recalculates all root clocks (clocks with no parent), which if the + * clock's .recalc is set correctly, should also propagate their rates. + */ +void recalc_root_clocks(void) +{ + propagate_rate(&root_clks); +} diff --git a/arch/arm/plat-spear/include/plat/clkdev.h b/arch/arm/plat-spear/include/plat/clkdev.h new file mode 100644 index 0000000..a2d0112 --- /dev/null +++ b/arch/arm/plat-spear/include/plat/clkdev.h @@ -0,0 +1,20 @@ +/* + * arch/arm/plat-spear/include/plat/clkdev.h + * + * Clock Dev framework definitions for SPEAr platform + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __PLAT_CLKDEV_H +#define __PLAT_CLKDEV_H + +#define __clk_get(clk) ({ 1; }) +#define __clk_put(clk) do { } while (0) + +#endif /* __PLAT_CLKDEV_H */ diff --git a/arch/arm/plat-spear/include/plat/clock.h b/arch/arm/plat-spear/include/plat/clock.h new file mode 100644 index 0000000..298bafc --- /dev/null +++ b/arch/arm/plat-spear/include/plat/clock.h @@ -0,0 +1,126 @@ +/* + * arch/arm/plat-spear/include/plat/clock.h + * + * Clock framework definitions for SPEAr platform + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __PLAT_CLOCK_H +#define __PLAT_CLOCK_H + +#include +#include +#include + +/* clk structure flags */ +#define ALWAYS_ENABLED (1 << 0) /* clock always enabled */ +#define RESET_TO_ENABLE (1 << 1) /* reset register bit to enable clk */ + +/** + * struct clkops - clock operations + * @enable: pointer to clock enable function + * @disable: pointer to clock disable function + */ +struct clkops { + int (*enable) (struct clk *); + void (*disable) (struct clk *); +}; + +/** + * struct pclk_info - parents info + * @pclk: pointer to parent clk + * @pclk_mask: value to be written for selecting this parent + * @scalable: Is parent scalable (1 - YES, 0 - NO) + */ +struct pclk_info { + struct clk *pclk; + u8 pclk_mask; + u8 scalable; +}; + +/** + * struct pclk_sel - parents selection configuration + * @pclk_info: pointer to array of parent clock info + * @pclk_count: number of parents + * @pclk_sel_reg: register for selecting a parent + * @pclk_sel_mask: mask for selecting parent (can be used to clear bits also) + */ +struct pclk_sel { + struct pclk_info *pclk_info; + u8 pclk_count; + unsigned int *pclk_sel_reg; + unsigned int pclk_sel_mask; +}; + +/** + * struct clk - clock structure + * @usage_count: num of users who enabled this clock + * @flags: flags for clock properties + * @rate: programmed clock rate in Hz + * @en_reg: clk enable/disable reg + * @en_reg_bit: clk enable/disable bit + * @ops: clk enable/disable ops - generic_clkops selected if NULL + * @recalc: pointer to clock rate recalculate function + * @pclk: current parent clk + * @pclk_sel: pointer to parent selection structure + * @pclk_sel_shift: register shift for selecting parent of this clock + * @children: list for childrens or this clock + * @sibling: node for list of clocks having same parents + * @private_data: clock specific private data + */ +struct clk { + unsigned int usage_count; + unsigned int flags; + unsigned long rate; + unsigned int *en_reg; + u8 en_reg_bit; + const struct clkops *ops; + void (*recalc) (struct clk *); + + struct clk *pclk; + struct pclk_sel *pclk_sel; + unsigned int pclk_sel_shift; + + struct list_head children; + struct list_head sibling; + void *private_data; +}; + +/* pll configuration structure */ +struct pll_clk_config { + unsigned int *mode_reg; + unsigned int *cfg_reg; +}; + +/* ahb and apb bus configuration structure */ +struct bus_clk_config { + unsigned int *reg; + unsigned int mask; + unsigned int shift; +}; + +/* + * Aux clk configuration structure: applicable to GPT, UART and FIRDA + */ +struct aux_clk_config { + unsigned int *synth_reg; +}; + +/* platform specific clock functions */ +void clk_register(struct clk_lookup *cl); +void recalc_root_clocks(void); + +/* clock recalc functions */ +void follow_parent(struct clk *clk); +void pll1_clk_recalc(struct clk *clk); +void bus_clk_recalc(struct clk *clk); +void gpt_clk_recalc(struct clk *clk); +void aux_clk_recalc(struct clk *clk); + +#endif /* __PLAT_CLOCK_H */ -- cgit v0.10.2 From 8f590d4541fb678a638777ab987709217cb71365 Mon Sep 17 00:00:00 2001 From: viresh kumar Date: Thu, 1 Apr 2010 12:31:01 +0100 Subject: ARM: 6015/1: ST SPEAr: Added source files for SPEAr6xx machine family Reviewed-by: Linus Walleij Signed-off-by: Viresh Kumar Signed-off-by: Russell King diff --git a/arch/arm/mach-spear6xx/Kconfig b/arch/arm/mach-spear6xx/Kconfig new file mode 100644 index 0000000..bddba03 --- /dev/null +++ b/arch/arm/mach-spear6xx/Kconfig @@ -0,0 +1,20 @@ +# +# SPEAr6XX Machine configuration file +# + +if ARCH_SPEAR6XX + +choice + prompt "SPEAr6XX Family" + default MACH_SPEAR600 + +config MACH_SPEAR600 + bool "SPEAr600" + help + Supports ST SPEAr600 Machine +endchoice + +# Adding SPEAr6XX machine specific configuration files +source "arch/arm/mach-spear6xx/Kconfig600" + +endif #ARCH_SPEAR6XX diff --git a/arch/arm/mach-spear6xx/Kconfig600 b/arch/arm/mach-spear6xx/Kconfig600 new file mode 100644 index 0000000..9e19f65 --- /dev/null +++ b/arch/arm/mach-spear6xx/Kconfig600 @@ -0,0 +1,17 @@ +# +# SPEAr600 machine configuration file +# + +if MACH_SPEAR600 + +choice + prompt "SPEAr600 Boards" + default BOARD_SPEAR600_EVB + +config BOARD_SPEAR600_EVB + bool "SPEAr600 Evaluation Board" + help + Supports ST SPEAr600 Evaluation Board +endchoice + +endif #MACH_SPEAR600 diff --git a/arch/arm/mach-spear6xx/Makefile b/arch/arm/mach-spear6xx/Makefile new file mode 100644 index 0000000..cc1a4d8 --- /dev/null +++ b/arch/arm/mach-spear6xx/Makefile @@ -0,0 +1,12 @@ +# +# Makefile for SPEAr6XX machine series +# + +# common files +obj-y += clock.o spear6xx.o + +# spear600 specific files +obj-$(CONFIG_MACH_SPEAR600) += spear600.o + +# spear600 boards files +obj-$(CONFIG_BOARD_SPEAR600_EVB) += spear600_evb.o diff --git a/arch/arm/mach-spear6xx/Makefile.boot b/arch/arm/mach-spear6xx/Makefile.boot new file mode 100644 index 0000000..7a1f3c0 --- /dev/null +++ b/arch/arm/mach-spear6xx/Makefile.boot @@ -0,0 +1,3 @@ +zreladdr-y := 0x00008000 +params_phys-y := 0x00000100 +initrd_phys-y := 0x00800000 diff --git a/arch/arm/mach-spear6xx/spear600.c b/arch/arm/mach-spear6xx/spear600.c new file mode 100644 index 0000000..5c484c4 --- /dev/null +++ b/arch/arm/mach-spear6xx/spear600.c @@ -0,0 +1,25 @@ +/* + * arch/arm/mach-spear6xx/spear600.c + * + * SPEAr600 machine source file + * + * Copyright (C) 2009 ST Microelectronics + * Rajeev Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include + +/* Add spear600 specific devices here */ + +void __init spear600_init(void) +{ + /* call spear6xx family common init function */ + spear6xx_init(); +} diff --git a/arch/arm/mach-spear6xx/spear600_evb.c b/arch/arm/mach-spear6xx/spear600_evb.c new file mode 100644 index 0000000..daff8d0 --- /dev/null +++ b/arch/arm/mach-spear6xx/spear600_evb.c @@ -0,0 +1,51 @@ +/* + * arch/arm/mach-spear6xx/spear600_evb.c + * + * SPEAr600 evaluation board source file + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include + +static struct amba_device *amba_devs[] __initdata = { + &gpio_device[0], + &gpio_device[1], + &gpio_device[2], + &uart_device[0], + &uart_device[1], +}; + +static struct platform_device *plat_devs[] __initdata = { +}; + +static void __init spear600_evb_init(void) +{ + unsigned int i; + + /* call spear600 machine init function */ + spear600_init(); + + /* Add Platform Devices */ + platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs)); + + /* Add Amba Devices */ + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) + amba_device_register(amba_devs[i], &iomem_resource); +} + +MACHINE_START(SPEAR600, "ST-SPEAR600-EVB") + .boot_params = 0x00000100, + .map_io = spear6xx_map_io, + .init_irq = spear6xx_init_irq, + .timer = &spear_sys_timer, + .init_machine = spear600_evb_init, +MACHINE_END diff --git a/arch/arm/mach-spear6xx/spear6xx.c b/arch/arm/mach-spear6xx/spear6xx.c new file mode 100644 index 0000000..b67e571 --- /dev/null +++ b/arch/arm/mach-spear6xx/spear6xx.c @@ -0,0 +1,158 @@ +/* + * arch/arm/mach-spear6xx/spear6xx.c + * + * SPEAr6XX machines common source file + * + * Copyright (C) 2009 ST Microelectronics + * Rajeev Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Add spear6xx machines common devices here */ +/* uart device registeration */ +struct amba_device uart_device[] = { + { + .dev = { + .init_name = "uart0", + }, + .res = { + .start = SPEAR6XX_ICM1_UART0_BASE, + .end = SPEAR6XX_ICM1_UART0_BASE + + SPEAR6XX_ICM1_UART0_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + .irq = {IRQ_UART_0, NO_IRQ}, + }, { + .dev = { + .init_name = "uart1", + }, + .res = { + .start = SPEAR6XX_ICM1_UART1_BASE, + .end = SPEAR6XX_ICM1_UART1_BASE + + SPEAR6XX_ICM1_UART1_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + .irq = {IRQ_UART_1, NO_IRQ}, + } +}; + +/* gpio device registeration */ +static struct pl061_platform_data gpio_plat_data[] = { + { + .gpio_base = 0, + .irq_base = SPEAR_GPIO0_INT_BASE, + }, { + .gpio_base = 8, + .irq_base = SPEAR_GPIO1_INT_BASE, + }, { + .gpio_base = 16, + .irq_base = SPEAR_GPIO2_INT_BASE, + }, +}; + +struct amba_device gpio_device[] = { + { + .dev = { + .init_name = "gpio0", + .platform_data = &gpio_plat_data[0], + }, + .res = { + .start = SPEAR6XX_CPU_GPIO_BASE, + .end = SPEAR6XX_CPU_GPIO_BASE + + SPEAR6XX_CPU_GPIO_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + .irq = {IRQ_LOCAL_GPIO, NO_IRQ}, + }, { + .dev = { + .init_name = "gpio1", + .platform_data = &gpio_plat_data[1], + }, + .res = { + .start = SPEAR6XX_ICM3_GPIO_BASE, + .end = SPEAR6XX_ICM3_GPIO_BASE + + SPEAR6XX_ICM3_GPIO_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + .irq = {IRQ_BASIC_GPIO, NO_IRQ}, + }, { + .dev = { + .init_name = "gpio2", + .platform_data = &gpio_plat_data[2], + }, + .res = { + .start = SPEAR6XX_ICM2_GPIO_BASE, + .end = SPEAR6XX_ICM2_GPIO_BASE + + SPEAR6XX_ICM2_GPIO_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + .irq = {IRQ_APPL_GPIO, NO_IRQ}, + } +}; + +/* This will add devices, and do machine specific tasks */ +void __init spear6xx_init(void) +{ + /* nothing to do for now */ +} + +/* This will initialize vic */ +void __init spear6xx_init_irq(void) +{ + vic_init((void __iomem *)VA_SPEAR6XX_CPU_VIC_PRI_BASE, 0, ~0, 0); + vic_init((void __iomem *)VA_SPEAR6XX_CPU_VIC_SEC_BASE, 32, ~0, 0); +} + +/* Following will create static virtual/physical mappings */ +static struct map_desc spear6xx_io_desc[] __initdata = { + { + .virtual = VA_SPEAR6XX_ICM1_UART0_BASE, + .pfn = __phys_to_pfn(SPEAR6XX_ICM1_UART0_BASE), + .length = SPEAR6XX_ICM1_UART0_SIZE, + .type = MT_DEVICE + }, { + .virtual = VA_SPEAR6XX_CPU_VIC_PRI_BASE, + .pfn = __phys_to_pfn(SPEAR6XX_CPU_VIC_PRI_BASE), + .length = SPEAR6XX_CPU_VIC_PRI_SIZE, + .type = MT_DEVICE + }, { + .virtual = VA_SPEAR6XX_CPU_VIC_SEC_BASE, + .pfn = __phys_to_pfn(SPEAR6XX_CPU_VIC_SEC_BASE), + .length = SPEAR6XX_CPU_VIC_SEC_SIZE, + .type = MT_DEVICE + }, { + .virtual = VA_SPEAR6XX_ICM3_SYS_CTRL_BASE, + .pfn = __phys_to_pfn(SPEAR6XX_ICM3_SYS_CTRL_BASE), + .length = SPEAR6XX_ICM3_MISC_REG_BASE, + .type = MT_DEVICE + }, { + .virtual = VA_SPEAR6XX_ICM3_MISC_REG_BASE, + .pfn = __phys_to_pfn(SPEAR6XX_ICM3_MISC_REG_BASE), + .length = SPEAR6XX_ICM3_MISC_REG_SIZE, + .type = MT_DEVICE + }, +}; + +/* This will create static memory mapping for selected devices */ +void __init spear6xx_map_io(void) +{ + iotable_init(spear6xx_io_desc, ARRAY_SIZE(spear6xx_io_desc)); + + /* This will initialize clock framework */ + clk_init(); +} -- cgit v0.10.2 From cee37e501ea34958d6d33d75d2bd21d9c343e379 Mon Sep 17 00:00:00 2001 From: viresh kumar Date: Thu, 1 Apr 2010 12:31:05 +0100 Subject: ARM: 6016/1: ST SPEAr: Added support for SPEAr platform and machines in arch/arm/ Reviewed-by: Linus Walleij Signed-off-by: Viresh Kumar Signed-off-by: Russell King diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c5408bf..1459231 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -801,6 +801,18 @@ config ARCH_OMAP help Support for TI's OMAP platform (OMAP1 and OMAP2). +config PLAT_SPEAR + bool "ST SPEAr" + select ARM_AMBA + select ARCH_REQUIRE_GPIOLIB + select COMMON_CLKDEV + select GENERIC_CLOCKEVENTS + select GENERIC_GPIO + select GENERIC_TIME + select HAVE_CLK + help + Support for ST's SPEAr platform (SPEAr3xx, SPEAr6xx and SPEAr13xx). + endchoice # @@ -886,6 +898,7 @@ source "arch/arm/plat-samsung/Kconfig" source "arch/arm/plat-s3c24xx/Kconfig" source "arch/arm/plat-s5p/Kconfig" source "arch/arm/plat-s5pc1xx/Kconfig" +source "arch/arm/plat-spear/Kconfig" if ARCH_S3C2410 source "arch/arm/mach-s3c2400/Kconfig" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index ed820e7..b3a3518 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -178,6 +178,10 @@ machine-$(CONFIG_ARCH_VERSATILE) := versatile machine-$(CONFIG_ARCH_W90X900) := w90x900 machine-$(CONFIG_ARCH_NUC93X) := nuc93x machine-$(CONFIG_FOOTBRIDGE) := footbridge +machine-$(CONFIG_MACH_SPEAR300) := spear3xx +machine-$(CONFIG_MACH_SPEAR310) := spear3xx +machine-$(CONFIG_MACH_SPEAR320) := spear3xx +machine-$(CONFIG_MACH_SPEAR600) := spear6xx # Platform directory name. This list is sorted alphanumerically # by CONFIG_* macro name. @@ -192,6 +196,7 @@ plat-$(CONFIG_PLAT_PXA) := pxa plat-$(CONFIG_PLAT_S3C24XX) := s3c24xx samsung plat-$(CONFIG_PLAT_S5PC1XX) := s5pc1xx samsung plat-$(CONFIG_PLAT_S5P) := s5p samsung +plat-$(CONFIG_PLAT_SPEAR) := spear ifeq ($(CONFIG_ARCH_EBSA110),y) # This is what happens if you forget the IOCS16 line. -- cgit v0.10.2 From bc4e814e5d5e2851f0a0679eaad14f60abae2a6d Mon Sep 17 00:00:00 2001 From: viresh kumar Date: Thu, 1 Apr 2010 12:30:58 +0100 Subject: ARM: 6017/1: ST SPEAr: Added source files for SPEAr3xx machine family Reviewed-by: Linus Walleij Signed-off-by: Viresh Kumar Signed-off-by: Russell King diff --git a/arch/arm/mach-spear3xx/Kconfig b/arch/arm/mach-spear3xx/Kconfig new file mode 100644 index 0000000..20d1317 --- /dev/null +++ b/arch/arm/mach-spear3xx/Kconfig @@ -0,0 +1,33 @@ +# +# SPEAr3XX Machine configuration file +# + +if ARCH_SPEAR3XX + +choice + prompt "SPEAr3XX Family" + default MACH_SPEAR300 + +config MACH_SPEAR300 + bool "SPEAr300" + help + Supports ST SPEAr300 Machine + +config MACH_SPEAR310 + bool "SPEAr310" + help + Supports ST SPEAr310 Machine + +config MACH_SPEAR320 + bool "SPEAr320" + help + Supports ST SPEAr320 Machine + +endchoice + +# Adding SPEAr3XX machine specific configuration files +source "arch/arm/mach-spear3xx/Kconfig300" +source "arch/arm/mach-spear3xx/Kconfig310" +source "arch/arm/mach-spear3xx/Kconfig320" + +endif #ARCH_SPEAR3XX diff --git a/arch/arm/mach-spear3xx/Kconfig300 b/arch/arm/mach-spear3xx/Kconfig300 new file mode 100644 index 0000000..c519a05 --- /dev/null +++ b/arch/arm/mach-spear3xx/Kconfig300 @@ -0,0 +1,17 @@ +# +# SPEAr300 machine configuration file +# + +if MACH_SPEAR300 + +choice + prompt "SPEAr300 Boards" + default BOARD_SPEAR300_EVB + +config BOARD_SPEAR300_EVB + bool "SPEAr300 Evaluation Board" + help + Supports ST SPEAr300 Evaluation Board +endchoice + +endif #MACH_SPEAR300 diff --git a/arch/arm/mach-spear3xx/Kconfig310 b/arch/arm/mach-spear3xx/Kconfig310 new file mode 100644 index 0000000..60e7442 --- /dev/null +++ b/arch/arm/mach-spear3xx/Kconfig310 @@ -0,0 +1,17 @@ +# +# SPEAr310 machine configuration file +# + +if MACH_SPEAR310 + +choice + prompt "SPEAr310 Boards" + default BOARD_SPEAR310_EVB + +config BOARD_SPEAR310_EVB + bool "SPEAr310 Evaluation Board" + help + Supports ST SPEAr310 Evaluation Board +endchoice + +endif #MACH_SPEAR310 diff --git a/arch/arm/mach-spear3xx/Kconfig320 b/arch/arm/mach-spear3xx/Kconfig320 new file mode 100644 index 0000000..1c1d438 --- /dev/null +++ b/arch/arm/mach-spear3xx/Kconfig320 @@ -0,0 +1,17 @@ +# +# SPEAr320 machine configuration file +# + +if MACH_SPEAR320 + +choice + prompt "SPEAr320 Boards" + default BOARD_SPEAR320_EVB + +config BOARD_SPEAR320_EVB + bool "SPEAr320 Evaluation Board" + help + Supports ST SPEAr320 Evaluation Board +endchoice + +endif #MACH_SPEAR320 diff --git a/arch/arm/mach-spear3xx/Makefile b/arch/arm/mach-spear3xx/Makefile new file mode 100644 index 0000000..b248624 --- /dev/null +++ b/arch/arm/mach-spear3xx/Makefile @@ -0,0 +1,26 @@ +# +# Makefile for SPEAr3XX machine series +# + +# common files +obj-y += spear3xx.o clock.o + +# spear300 specific files +obj-$(CONFIG_MACH_SPEAR300) += spear300.o + +# spear300 boards files +obj-$(CONFIG_BOARD_SPEAR300_EVB) += spear300_evb.o + + +# spear310 specific files +obj-$(CONFIG_MACH_SPEAR310) += spear310.o + +# spear310 boards files +obj-$(CONFIG_BOARD_SPEAR310_EVB) += spear310_evb.o + + +# spear320 specific files +obj-$(CONFIG_MACH_SPEAR320) += spear320.o + +# spear320 boards files +obj-$(CONFIG_BOARD_SPEAR320_EVB) += spear320_evb.o diff --git a/arch/arm/mach-spear3xx/Makefile.boot b/arch/arm/mach-spear3xx/Makefile.boot new file mode 100644 index 0000000..7a1f3c0 --- /dev/null +++ b/arch/arm/mach-spear3xx/Makefile.boot @@ -0,0 +1,3 @@ +zreladdr-y := 0x00008000 +params_phys-y := 0x00000100 +initrd_phys-y := 0x00800000 diff --git a/arch/arm/mach-spear3xx/spear300.c b/arch/arm/mach-spear3xx/spear300.c new file mode 100644 index 0000000..63aca8f --- /dev/null +++ b/arch/arm/mach-spear3xx/spear300.c @@ -0,0 +1,45 @@ +/* + * arch/arm/mach-spear3xx/spear300.c + * + * SPEAr300 machine source file + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include + +/* Add spear300 specific devices here */ +/* arm gpio1 device registeration */ +static struct pl061_platform_data gpio1_plat_data = { + .gpio_base = 8, + .irq_base = SPEAR_GPIO1_INT_BASE, +}; + +struct amba_device gpio1_device = { + .dev = { + .init_name = "gpio1", + .platform_data = &gpio1_plat_data, + }, + .res = { + .start = SPEAR300_GPIO_BASE, + .end = SPEAR300_GPIO_BASE + SPEAR300_GPIO_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + .irq = {IRQ_GEN_RAS_1, NO_IRQ}, +}; + +void __init spear300_init(void) +{ + /* call spear3xx family common init function */ + spear3xx_init(); +} diff --git a/arch/arm/mach-spear3xx/spear300_evb.c b/arch/arm/mach-spear3xx/spear300_evb.c new file mode 100644 index 0000000..1272a38 --- /dev/null +++ b/arch/arm/mach-spear3xx/spear300_evb.c @@ -0,0 +1,55 @@ +/* + * arch/arm/mach-spear3xx/spear300_evb.c + * + * SPEAr300 evaluation board source file + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include + +static struct amba_device *amba_devs[] __initdata = { + /* spear3xx specific devices */ + &gpio_device, + &uart_device, + + /* spear300 specific devices */ + &gpio1_device, +}; + +static struct platform_device *plat_devs[] __initdata = { + /* spear3xx specific devices */ + + /* spear300 specific devices */ +}; + +static void __init spear300_evb_init(void) +{ + unsigned int i; + + /* call spear300 machine init function */ + spear300_init(); + + /* Add Platform Devices */ + platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs)); + + /* Add Amba Devices */ + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) + amba_device_register(amba_devs[i], &iomem_resource); +} + +MACHINE_START(SPEAR300, "ST-SPEAR300-EVB") + .boot_params = 0x00000100, + .map_io = spear3xx_map_io, + .init_irq = spear3xx_init_irq, + .timer = &spear_sys_timer, + .init_machine = spear300_evb_init, +MACHINE_END diff --git a/arch/arm/mach-spear3xx/spear310.c b/arch/arm/mach-spear3xx/spear310.c new file mode 100644 index 0000000..6eb62f9 --- /dev/null +++ b/arch/arm/mach-spear3xx/spear310.c @@ -0,0 +1,25 @@ +/* + * arch/arm/mach-spear3xx/spear310.c + * + * SPEAr310 machine source file + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include + +/* Add spear310 specific devices here */ + +void __init spear310_init(void) +{ + /* call spear3xx family common init function */ + spear3xx_init(); +} diff --git a/arch/arm/mach-spear3xx/spear310_evb.c b/arch/arm/mach-spear3xx/spear310_evb.c new file mode 100644 index 0000000..e781b2b --- /dev/null +++ b/arch/arm/mach-spear3xx/spear310_evb.c @@ -0,0 +1,54 @@ +/* + * arch/arm/mach-spear3xx/spear310_evb.c + * + * SPEAr310 evaluation board source file + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include + +static struct amba_device *amba_devs[] __initdata = { + /* spear3xx specific devices */ + &gpio_device, + &uart_device, + + /* spear310 specific devices */ +}; + +static struct platform_device *plat_devs[] __initdata = { + /* spear3xx specific devices */ + + /* spear310 specific devices */ +}; + +static void __init spear310_evb_init(void) +{ + unsigned int i; + + /* call spear310 machine init function */ + spear310_init(); + + /* Add Platform Devices */ + platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs)); + + /* Add Amba Devices */ + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) + amba_device_register(amba_devs[i], &iomem_resource); +} + +MACHINE_START(SPEAR310, "ST-SPEAR310-EVB") + .boot_params = 0x00000100, + .map_io = spear3xx_map_io, + .init_irq = spear3xx_init_irq, + .timer = &spear_sys_timer, + .init_machine = spear310_evb_init, +MACHINE_END diff --git a/arch/arm/mach-spear3xx/spear320.c b/arch/arm/mach-spear3xx/spear320.c new file mode 100644 index 0000000..72d4548 --- /dev/null +++ b/arch/arm/mach-spear3xx/spear320.c @@ -0,0 +1,25 @@ +/* + * arch/arm/mach-spear3xx/spear320.c + * + * SPEAr320 machine source file + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include + +/* Add spear320 specific devices here */ + +void __init spear320_init(void) +{ + /* call spear3xx family common init function */ + spear3xx_init(); +} diff --git a/arch/arm/mach-spear3xx/spear320_evb.c b/arch/arm/mach-spear3xx/spear320_evb.c new file mode 100644 index 0000000..85bc4d2 --- /dev/null +++ b/arch/arm/mach-spear3xx/spear320_evb.c @@ -0,0 +1,54 @@ +/* + * arch/arm/mach-spear3xx/spear320_evb.c + * + * SPEAr320 evaluation board source file + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include + +static struct amba_device *amba_devs[] __initdata = { + /* spear3xx specific devices */ + &gpio_device, + &uart_device, + + /* spear320 specific devices */ +}; + +static struct platform_device *plat_devs[] __initdata = { + /* spear3xx specific devices */ + + /* spear320 specific devices */ +}; + +static void __init spear320_evb_init(void) +{ + unsigned int i; + + /* call spear320 machine init function */ + spear320_init(); + + /* Add Platform Devices */ + platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs)); + + /* Add Amba Devices */ + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) + amba_device_register(amba_devs[i], &iomem_resource); +} + +MACHINE_START(SPEAR320, "ST-SPEAR320-EVB") + .boot_params = 0x00000100, + .map_io = spear3xx_map_io, + .init_irq = spear3xx_init_irq, + .timer = &spear_sys_timer, + .init_machine = spear320_evb_init, +MACHINE_END diff --git a/arch/arm/mach-spear3xx/spear3xx.c b/arch/arm/mach-spear3xx/spear3xx.c new file mode 100644 index 0000000..82ebcd3 --- /dev/null +++ b/arch/arm/mach-spear3xx/spear3xx.c @@ -0,0 +1,101 @@ +/* + * arch/arm/mach-spear3xx/spear3xx.c + * + * SPEAr3XX machines common source file + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Add spear3xx machines common devices here */ +/* gpio device registeration */ +static struct pl061_platform_data gpio_plat_data = { + .gpio_base = 0, + .irq_base = SPEAR_GPIO_INT_BASE, +}; + +struct amba_device gpio_device = { + .dev = { + .init_name = "gpio", + .platform_data = &gpio_plat_data, + }, + .res = { + .start = SPEAR3XX_ICM3_GPIO_BASE, + .end = SPEAR3XX_ICM3_GPIO_BASE + SPEAR3XX_ICM3_GPIO_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + .irq = {IRQ_BASIC_GPIO, NO_IRQ}, +}; + +/* uart device registeration */ +struct amba_device uart_device = { + .dev = { + .init_name = "uart", + }, + .res = { + .start = SPEAR3XX_ICM1_UART_BASE, + .end = SPEAR3XX_ICM1_UART_BASE + SPEAR3XX_ICM1_UART_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + .irq = {IRQ_UART, NO_IRQ}, +}; + +/* Do spear3xx familiy common initialization part here */ +void __init spear3xx_init(void) +{ + /* nothing to do for now */ +} + +/* This will initialize vic */ +void __init spear3xx_init_irq(void) +{ + vic_init((void __iomem *)VA_SPEAR3XX_ML1_VIC_BASE, 0, ~0, 0); +} + +/* Following will create static virtual/physical mappings */ +struct map_desc spear3xx_io_desc[] __initdata = { + { + .virtual = VA_SPEAR3XX_ICM1_UART_BASE, + .pfn = __phys_to_pfn(SPEAR3XX_ICM1_UART_BASE), + .length = SPEAR3XX_ICM1_UART_SIZE, + .type = MT_DEVICE + }, { + .virtual = VA_SPEAR3XX_ML1_VIC_BASE, + .pfn = __phys_to_pfn(SPEAR3XX_ML1_VIC_BASE), + .length = SPEAR3XX_ML1_VIC_SIZE, + .type = MT_DEVICE + }, { + .virtual = VA_SPEAR3XX_ICM3_SYS_CTRL_BASE, + .pfn = __phys_to_pfn(SPEAR3XX_ICM3_SYS_CTRL_BASE), + .length = SPEAR3XX_ICM3_SYS_CTRL_SIZE, + .type = MT_DEVICE + }, { + .virtual = VA_SPEAR3XX_ICM3_MISC_REG_BASE, + .pfn = __phys_to_pfn(SPEAR3XX_ICM3_MISC_REG_BASE), + .length = SPEAR3XX_ICM3_MISC_REG_SIZE, + .type = MT_DEVICE + }, +}; + +/* This will create static memory mapping for selected devices */ +void __init spear3xx_map_io(void) +{ + iotable_init(spear3xx_io_desc, ARRAY_SIZE(spear3xx_io_desc)); + + /* This will initialize clock framework */ + clk_init(); +} -- cgit v0.10.2 From fc0c195aa8877fd46d837c8c4a9a61386a124401 Mon Sep 17 00:00:00 2001 From: viresh kumar Date: Thu, 1 Apr 2010 12:31:21 +0100 Subject: ARM: 6018/1: ST SPEAr: Updated Maintainers and added Documentation/arm/SPEAr Reviewed-by: Linus Walleij Signed-off-by: Viresh Kumar Signed-off-by: Russell King diff --git a/Documentation/arm/00-INDEX b/Documentation/arm/00-INDEX index 82e418d..7f5fc3b 100644 --- a/Documentation/arm/00-INDEX +++ b/Documentation/arm/00-INDEX @@ -20,6 +20,8 @@ Samsung-S3C24XX - S3C24XX ARM Linux Overview Sharp-LH - Linux on Sharp LH79524 and LH7A40X System On a Chip (SOC) +SPEAr + - ST SPEAr platform Linux Overview VFP/ - Release notes for Linux Kernel Vector Floating Point support code empeg/ diff --git a/Documentation/arm/SPEAr/overview.txt b/Documentation/arm/SPEAr/overview.txt new file mode 100644 index 0000000..253a35c --- /dev/null +++ b/Documentation/arm/SPEAr/overview.txt @@ -0,0 +1,60 @@ + SPEAr ARM Linux Overview + ========================== + +Introduction +------------ + + SPEAr (Structured Processor Enhanced Architecture). + weblink : http://www.st.com/spear + + The ST Microelectronics SPEAr range of ARM9/CortexA9 System-on-Chip CPUs are + supported by the 'spear' platform of ARM Linux. Currently SPEAr300, + SPEAr310, SPEAr320 and SPEAr600 SOCs are supported. Support for the SPEAr13XX + series is in progress. + + Hierarchy in SPEAr is as follows: + + SPEAr (Platform) + - SPEAr3XX (3XX SOC series, based on ARM9) + - SPEAr300 (SOC) + - SPEAr300_EVB (Evaluation Board) + - SPEAr310 (SOC) + - SPEAr310_EVB (Evaluation Board) + - SPEAr320 (SOC) + - SPEAr320_EVB (Evaluation Board) + - SPEAr6XX (6XX SOC series, based on ARM9) + - SPEAr600 (SOC) + - SPEAr600_EVB (Evaluation Board) + - SPEAr13XX (13XX SOC series, based on ARM CORTEXA9) + - SPEAr1300 (SOC) + + Configuration + ------------- + + A generic configuration is provided for each machine, and can be used as the + default by + make spear600_defconfig + make spear300_defconfig + make spear310_defconfig + make spear320_defconfig + + Layout + ------ + + The common files for multiple machine families (SPEAr3XX, SPEAr6XX and + SPEAr13XX) are located in the platform code contained in arch/arm/plat-spear + with headers in plat/. + + Each machine series have a directory with name arch/arm/mach-spear followed by + series name. Like mach-spear3xx, mach-spear6xx and mach-spear13xx. + + Common file for machines of spear3xx family is mach-spear3xx/spear3xx.c and for + spear6xx is mach-spear6xx/spear6xx.c. mach-spear* also contain soc/machine + specific files, like spear300.c, spear310.c, spear320.c and spear600.c. + mach-spear* also contains board specific files for each machine type. + + + Document Author + --------------- + + Viresh Kumar, (c) 2010 ST Microelectronics diff --git a/MAINTAINERS b/MAINTAINERS index 382eaa4..aa18ca3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5229,6 +5229,46 @@ F: drivers/serial/sunsu.c F: drivers/serial/sunzilog.c F: drivers/serial/sunzilog.h +SPEAR PLATFORM SUPPORT +M: Viresh Kumar +W: http://www.st.com/spear +S: Maintained +F: arch/arm/plat-spear/ + +SPEAR3XX MACHINE SUPPORT +M: Viresh Kumar +W: http://www.st.com/spear +S: Maintained +F: arch/arm/mach-spear3xx/ + +SPEAR6XX MACHINE SUPPORT +M: Rajeev Kumar +W: http://www.st.com/spear +S: Maintained +F: arch/arm/mach-spear6xx/ + +SPEAR CLOCK FRAMEWORK SUPPORT +M: Viresh Kumar +W: http://www.st.com/spear +S: Maintained +F: arch/arm/mach-spear*/clock.c +F: arch/arm/mach-spear*/include/mach/clkdev.h +F: arch/arm/plat-spear/clock.c +F: arch/arm/plat-spear/include/plat/clock.h and clkdev.h + +SPEAR PAD MULTIPLEXING SUPPORT +M: Viresh Kumar +W: http://www.st.com/spear +S: Maintained +F: arch/arm/plat-spear/include/plat/padmux.h +F: arch/arm/plat-spear/padmux.c +F: arch/arm/mach-spear*/spear*xx.c +F: arch/arm/mach-spear*/include/mach/generic.h +F: arch/arm/mach-spear3xx/spear3*0.c +F: arch/arm/mach-spear3xx/spear3*0_evb.c +F: arch/arm/mach-spear6xx/spear600.c +F: arch/arm/mach-spear6xx/spear600_evb.c + SPECIALIX IO8+ MULTIPORT SERIAL CARD DRIVER M: Roger Wolff S: Supported -- cgit v0.10.2 From b77932a4d265586748f05a8c8fad7ef4174c0296 Mon Sep 17 00:00:00 2001 From: viresh kumar Date: Thu, 1 Apr 2010 12:31:17 +0100 Subject: ARM: 6019/1: ST SPEAr: Added default configuration files for SPEAr machines Reviewed-by: Linus Walleij Signed-off-by: Viresh Kumar Signed-off-by: Russell King diff --git a/arch/arm/configs/spear300_defconfig b/arch/arm/configs/spear300_defconfig new file mode 100644 index 0000000..35e64d1 --- /dev/null +++ b/arch/arm/configs/spear300_defconfig @@ -0,0 +1,773 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.32 +# Tue Mar 23 14:36:23 2010 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_CONSTRUCTORS=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set + +# +# RCU Subsystem +# +CONFIG_TREE_RCU=y +# CONFIG_TREE_PREEMPT_RCU is not set +# CONFIG_RCU_TRACE is not set +CONFIG_RCU_FANOUT=32 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=17 +# CONFIG_GROUP_SCHED is not set +# CONFIG_CGROUPS is not set +# CONFIG_SYSFS_DEPRECATED_V2 is not set +# CONFIG_RELAY is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y + +# +# Kernel Performance Events And Counters +# +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLUB_DEBUG=y +CONFIG_COMPAT_BRK=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_CLK=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +# CONFIG_SLOW_WORK is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_BLOCK=y +CONFIG_LBDAF=y +CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_FREEZER is not set + +# +# System Type +# +CONFIG_MMU=y +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_STMP3XXX is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_NOMADIK is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5PC1XX is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_BCMRING is not set +CONFIG_PLAT_SPEAR=y +CONFIG_ARCH_SPEAR3XX=y +# CONFIG_ARCH_SPEAR6XX is not set +CONFIG_MACH_SPEAR300=y +# CONFIG_MACH_SPEAR310 is not set +# CONFIG_MACH_SPEAR320 is not set +CONFIG_BOARD_SPEAR300_EVB=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM926T=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5TJ=y +CONFIG_CPU_PABRT_LEGACY=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set +# CONFIG_CPU_CACHE_ROUND_ROBIN is not set +CONFIG_ARM_L1_CACHE_SHIFT=5 +CONFIG_ARM_VIC=y +CONFIG_ARM_VIC_NR=2 +CONFIG_COMMON_CLKDEV=y + +# +# Bus support +# +CONFIG_ARM_AMBA=y +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +# CONFIG_NO_HZ is not set +# CONFIG_HIGH_RES_TIMERS is not set +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_HZ=100 +# CONFIG_AEABI is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +# CONFIG_HIGHMEM is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_HAVE_MLOCK=y +CONFIG_HAVE_MLOCKED_PAGE_BIT=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_CMDLINE="" +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +# CONFIG_FPE_NWFPE is not set +# CONFIG_FPE_FASTFPE is not set +# CONFIG_VFP is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_MISC=y + +# +# Power management options +# +# CONFIG_PM is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +# CONFIG_NET is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_DEVTMPFS is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_MTD is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +CONFIG_MISC_DEVICES=y +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_93CX6 is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +CONFIG_INPUT_FF_MEMLESS=y +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_AMBAKMI is not set +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_R3964 is not set +CONFIG_RAW_DRIVER=y +CONFIG_MAX_RAW_DEVS=8192 +# CONFIG_TCG_TPM is not set +# CONFIG_I2C is not set +# CONFIG_SPI is not set + +# +# PPS support +# +# CONFIG_PPS is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO expanders: +# +CONFIG_GPIO_PL061=y + +# +# I2C GPIO expanders: +# + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# + +# +# AC97 GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_REGULATOR is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_SOUND is not set +# CONFIG_HID_SUPPORT is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set + +# +# TI VLYNQ +# +# CONFIG_STAGING is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +# CONFIG_EXT2_FS_POSIX_ACL is not set +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +CONFIG_EXT3_FS_SECURITY=y +# CONFIG_EXT4_FS is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +# CONFIG_INOTIFY is not set +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS4_FS=m +# CONFIG_FUSE_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=m +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_DETECT_HUNG_TASK=y +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set +CONFIG_FRAME_POINTER=y +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_CPU_STALL_DETECTOR=y +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +# CONFIG_PAGE_POISONING is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_TRACING_SUPPORT=y +CONFIG_FTRACE=y +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_ENABLE_DEFAULT_TRACERS is not set +# CONFIG_BOOT_TRACER is not set +CONFIG_BRANCH_PROFILE_NONE=y +# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set +# CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_KMEMTRACE is not set +# CONFIG_WORKQUEUE_TRACER is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_ERRORS is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_LL is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +# CONFIG_CRYPTO is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_GENERIC_FIND_LAST_BIT=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +# CONFIG_CRC32 is not set +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/arm/configs/spear310_defconfig b/arch/arm/configs/spear310_defconfig new file mode 100644 index 0000000..cbbfd29 --- /dev/null +++ b/arch/arm/configs/spear310_defconfig @@ -0,0 +1,775 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.32 +# Tue Mar 23 14:37:01 2010 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_CONSTRUCTORS=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set + +# +# RCU Subsystem +# +CONFIG_TREE_RCU=y +# CONFIG_TREE_PREEMPT_RCU is not set +# CONFIG_RCU_TRACE is not set +CONFIG_RCU_FANOUT=32 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=17 +# CONFIG_GROUP_SCHED is not set +# CONFIG_CGROUPS is not set +# CONFIG_SYSFS_DEPRECATED_V2 is not set +# CONFIG_RELAY is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y + +# +# Kernel Performance Events And Counters +# +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLUB_DEBUG=y +CONFIG_COMPAT_BRK=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_CLK=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +# CONFIG_SLOW_WORK is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_BLOCK=y +CONFIG_LBDAF=y +CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_FREEZER is not set + +# +# System Type +# +CONFIG_MMU=y +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_STMP3XXX is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_NOMADIK is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5PC1XX is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_BCMRING is not set +CONFIG_PLAT_SPEAR=y +CONFIG_ARCH_SPEAR3XX=y +# CONFIG_ARCH_SPEAR6XX is not set +# CONFIG_MACH_SPEAR300 is not set +CONFIG_MACH_SPEAR310=y +# CONFIG_MACH_SPEAR320 is not set +# CONFIG_BOARD_SPEAR300_EVB is not set +CONFIG_BOARD_SPEAR310_EVB=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM926T=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5TJ=y +CONFIG_CPU_PABRT_LEGACY=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set +# CONFIG_CPU_CACHE_ROUND_ROBIN is not set +CONFIG_ARM_L1_CACHE_SHIFT=5 +CONFIG_ARM_VIC=y +CONFIG_ARM_VIC_NR=2 +CONFIG_COMMON_CLKDEV=y + +# +# Bus support +# +CONFIG_ARM_AMBA=y +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +# CONFIG_NO_HZ is not set +# CONFIG_HIGH_RES_TIMERS is not set +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_HZ=100 +# CONFIG_AEABI is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +# CONFIG_HIGHMEM is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_HAVE_MLOCK=y +CONFIG_HAVE_MLOCKED_PAGE_BIT=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_CMDLINE="" +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +# CONFIG_FPE_NWFPE is not set +# CONFIG_FPE_FASTFPE is not set +# CONFIG_VFP is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_MISC=y + +# +# Power management options +# +# CONFIG_PM is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +# CONFIG_NET is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_DEVTMPFS is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_MTD is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_MG_DISK is not set +CONFIG_MISC_DEVICES=y +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_93CX6 is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +CONFIG_INPUT_FF_MEMLESS=y +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_AMBAKMI is not set +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_R3964 is not set +CONFIG_RAW_DRIVER=y +CONFIG_MAX_RAW_DEVS=8192 +# CONFIG_TCG_TPM is not set +# CONFIG_I2C is not set +# CONFIG_SPI is not set + +# +# PPS support +# +# CONFIG_PPS is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO expanders: +# +CONFIG_GPIO_PL061=y + +# +# I2C GPIO expanders: +# + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# + +# +# AC97 GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_REGULATOR is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_SOUND is not set +# CONFIG_HID_SUPPORT is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set + +# +# TI VLYNQ +# +# CONFIG_STAGING is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +# CONFIG_EXT2_FS_POSIX_ACL is not set +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +CONFIG_EXT3_FS_SECURITY=y +# CONFIG_EXT4_FS is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +# CONFIG_INOTIFY is not set +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS4_FS=m +# CONFIG_FUSE_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=m +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_DETECT_HUNG_TASK=y +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set +CONFIG_FRAME_POINTER=y +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_CPU_STALL_DETECTOR=y +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +# CONFIG_PAGE_POISONING is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_TRACING_SUPPORT=y +CONFIG_FTRACE=y +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_ENABLE_DEFAULT_TRACERS is not set +# CONFIG_BOOT_TRACER is not set +CONFIG_BRANCH_PROFILE_NONE=y +# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set +# CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_KMEMTRACE is not set +# CONFIG_WORKQUEUE_TRACER is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_ERRORS is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_LL is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +# CONFIG_CRYPTO is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_GENERIC_FIND_LAST_BIT=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +# CONFIG_CRC32 is not set +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/arm/configs/spear320_defconfig b/arch/arm/configs/spear320_defconfig new file mode 100644 index 0000000..2ae3c11 --- /dev/null +++ b/arch/arm/configs/spear320_defconfig @@ -0,0 +1,775 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.32 +# Tue Mar 23 14:37:12 2010 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_CONSTRUCTORS=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set + +# +# RCU Subsystem +# +CONFIG_TREE_RCU=y +# CONFIG_TREE_PREEMPT_RCU is not set +# CONFIG_RCU_TRACE is not set +CONFIG_RCU_FANOUT=32 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=17 +# CONFIG_GROUP_SCHED is not set +# CONFIG_CGROUPS is not set +# CONFIG_SYSFS_DEPRECATED_V2 is not set +# CONFIG_RELAY is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y + +# +# Kernel Performance Events And Counters +# +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLUB_DEBUG=y +CONFIG_COMPAT_BRK=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_CLK=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +# CONFIG_SLOW_WORK is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_BLOCK=y +CONFIG_LBDAF=y +CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_FREEZER is not set + +# +# System Type +# +CONFIG_MMU=y +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_STMP3XXX is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_NOMADIK is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5PC1XX is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_BCMRING is not set +CONFIG_PLAT_SPEAR=y +CONFIG_ARCH_SPEAR3XX=y +# CONFIG_ARCH_SPEAR6XX is not set +# CONFIG_MACH_SPEAR300 is not set +# CONFIG_MACH_SPEAR310 is not set +CONFIG_MACH_SPEAR320=y +# CONFIG_BOARD_SPEAR300_EVB is not set +CONFIG_BOARD_SPEAR320_EVB=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM926T=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5TJ=y +CONFIG_CPU_PABRT_LEGACY=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set +# CONFIG_CPU_CACHE_ROUND_ROBIN is not set +CONFIG_ARM_L1_CACHE_SHIFT=5 +CONFIG_ARM_VIC=y +CONFIG_ARM_VIC_NR=2 +CONFIG_COMMON_CLKDEV=y + +# +# Bus support +# +CONFIG_ARM_AMBA=y +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +# CONFIG_NO_HZ is not set +# CONFIG_HIGH_RES_TIMERS is not set +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_HZ=100 +# CONFIG_AEABI is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +# CONFIG_HIGHMEM is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_HAVE_MLOCK=y +CONFIG_HAVE_MLOCKED_PAGE_BIT=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_CMDLINE="" +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +# CONFIG_FPE_NWFPE is not set +# CONFIG_FPE_FASTFPE is not set +# CONFIG_VFP is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_MISC=y + +# +# Power management options +# +# CONFIG_PM is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +# CONFIG_NET is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_DEVTMPFS is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_MTD is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_MG_DISK is not set +CONFIG_MISC_DEVICES=y +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_93CX6 is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +CONFIG_INPUT_FF_MEMLESS=y +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_AMBAKMI is not set +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_R3964 is not set +CONFIG_RAW_DRIVER=y +CONFIG_MAX_RAW_DEVS=8192 +# CONFIG_TCG_TPM is not set +# CONFIG_I2C is not set +# CONFIG_SPI is not set + +# +# PPS support +# +# CONFIG_PPS is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO expanders: +# +CONFIG_GPIO_PL061=y + +# +# I2C GPIO expanders: +# + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# + +# +# AC97 GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_REGULATOR is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_SOUND is not set +# CONFIG_HID_SUPPORT is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set + +# +# TI VLYNQ +# +# CONFIG_STAGING is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +# CONFIG_EXT2_FS_POSIX_ACL is not set +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +CONFIG_EXT3_FS_SECURITY=y +# CONFIG_EXT4_FS is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +# CONFIG_INOTIFY is not set +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS4_FS=m +# CONFIG_FUSE_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=m +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_DETECT_HUNG_TASK=y +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set +CONFIG_FRAME_POINTER=y +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_CPU_STALL_DETECTOR=y +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +# CONFIG_PAGE_POISONING is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_TRACING_SUPPORT=y +CONFIG_FTRACE=y +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_ENABLE_DEFAULT_TRACERS is not set +# CONFIG_BOOT_TRACER is not set +CONFIG_BRANCH_PROFILE_NONE=y +# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set +# CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_KMEMTRACE is not set +# CONFIG_WORKQUEUE_TRACER is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_ERRORS is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_LL is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +# CONFIG_CRYPTO is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_GENERIC_FIND_LAST_BIT=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +# CONFIG_CRC32 is not set +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/arch/arm/configs/spear600_defconfig b/arch/arm/configs/spear600_defconfig new file mode 100644 index 0000000..c85a029 --- /dev/null +++ b/arch/arm/configs/spear600_defconfig @@ -0,0 +1,760 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.32 +# Tue Mar 23 14:37:26 2010 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_CONSTRUCTORS=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set + +# +# RCU Subsystem +# +CONFIG_TREE_RCU=y +# CONFIG_TREE_PREEMPT_RCU is not set +# CONFIG_RCU_TRACE is not set +CONFIG_RCU_FANOUT=32 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=17 +# CONFIG_GROUP_SCHED is not set +# CONFIG_CGROUPS is not set +# CONFIG_SYSFS_DEPRECATED_V2 is not set +# CONFIG_RELAY is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y + +# +# Kernel Performance Events And Counters +# +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLUB_DEBUG=y +CONFIG_COMPAT_BRK=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_CLK=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +# CONFIG_SLOW_WORK is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_BLOCK=y +CONFIG_LBDAF=y +CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_FREEZER is not set + +# +# System Type +# +CONFIG_MMU=y +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_STMP3XXX is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_NOMADIK is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5PC1XX is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_BCMRING is not set +CONFIG_PLAT_SPEAR=y +# CONFIG_ARCH_SPEAR3XX is not set +CONFIG_ARCH_SPEAR6XX=y +# CONFIG_MACH_SPEAR300 is not set +# CONFIG_MACH_SPEAR310 is not set +# CONFIG_MACH_SPEAR320 is not set +# CONFIG_BOARD_SPEAR300_EVB is not set +CONFIG_MACH_SPEAR600=y +CONFIG_BOARD_SPEAR600_EVB=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM926T=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5TJ=y +CONFIG_CPU_PABRT_LEGACY=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set +# CONFIG_CPU_CACHE_ROUND_ROBIN is not set +CONFIG_ARM_L1_CACHE_SHIFT=5 +CONFIG_ARM_VIC=y +CONFIG_ARM_VIC_NR=2 +CONFIG_COMMON_CLKDEV=y + +# +# Bus support +# +CONFIG_ARM_AMBA=y +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +# CONFIG_NO_HZ is not set +# CONFIG_HIGH_RES_TIMERS is not set +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_HZ=100 +# CONFIG_AEABI is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +# CONFIG_HIGHMEM is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_HAVE_MLOCK=y +CONFIG_HAVE_MLOCKED_PAGE_BIT=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_CMDLINE="" +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +# CONFIG_FPE_NWFPE is not set +# CONFIG_FPE_FASTFPE is not set +# CONFIG_VFP is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_MISC=y +# CONFIG_ARTHUR is not set + +# +# Power management options +# +# CONFIG_PM is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +# CONFIG_NET is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_DEVTMPFS is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_MTD is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +CONFIG_MISC_DEVICES=y +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_93CX6 is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +CONFIG_INPUT_FF_MEMLESS=y +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_AMBAKMI is not set +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_R3964 is not set +CONFIG_RAW_DRIVER=y +CONFIG_MAX_RAW_DEVS=8192 +# CONFIG_TCG_TPM is not set +# CONFIG_I2C is not set +# CONFIG_SPI is not set + +# +# PPS support +# +# CONFIG_PPS is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO expanders: +# +CONFIG_GPIO_PL061=y + +# +# I2C GPIO expanders: +# + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# + +# +# AC97 GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_REGULATOR is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_HID_SUPPORT is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set + +# +# TI VLYNQ +# +# CONFIG_STAGING is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +# CONFIG_EXT2_FS_POSIX_ACL is not set +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +CONFIG_EXT3_FS_SECURITY=y +# CONFIG_EXT4_FS is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +# CONFIG_INOTIFY is not set +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS4_FS=m +# CONFIG_FUSE_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=m +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set +CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 +CONFIG_DETECT_HUNG_TASK=y +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +CONFIG_SCHED_DEBUG=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set +CONFIG_FRAME_POINTER=y +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_CPU_STALL_DETECTOR=y +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +# CONFIG_PAGE_POISONING is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_TRACING_SUPPORT=y +CONFIG_FTRACE=y +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_ENABLE_DEFAULT_TRACERS is not set +# CONFIG_BOOT_TRACER is not set +CONFIG_BRANCH_PROFILE_NONE=y +# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set +# CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_KMEMTRACE is not set +# CONFIG_WORKQUEUE_TRACER is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_ERRORS is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_LL is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +# CONFIG_CRYPTO is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_GENERIC_FIND_LAST_BIT=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +# CONFIG_CRC32 is not set +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y -- cgit v0.10.2 From 70f4c0bf9e4d067744ee453bc37c0c4adcea6e53 Mon Sep 17 00:00:00 2001 From: viresh kumar Date: Thu, 1 Apr 2010 12:31:29 +0100 Subject: ARM: 6020/1: ST SPEAr: Adding gpio pad multiplexing support GPIO Pads in spear platform are are multiplexed in various machines. This patch adds support for this pad multiplexing. Reviewed-by: Linus Walleij Signed-off-by: Viresh Kumar Signed-off-by: Russell King diff --git a/arch/arm/mach-spear3xx/include/mach/generic.h b/arch/arm/mach-spear3xx/include/mach/generic.h index aeea845..af7e02c 100644 --- a/arch/arm/mach-spear3xx/include/mach/generic.h +++ b/arch/arm/mach-spear3xx/include/mach/generic.h @@ -19,7 +19,9 @@ #include #include #include +#include +/* spear3xx declarations */ /* * Each GPT has 2 timer channels * Following GPT channels will be used as clock source and clockevent @@ -34,25 +36,170 @@ extern struct amba_device uart_device; extern struct sys_timer spear_sys_timer; /* Add spear3xx family function declarations here */ +void __init clk_init(void); void __init spear3xx_map_io(void); void __init spear3xx_init_irq(void); void __init spear3xx_init(void); -void __init spear300_init(void); -void __init spear310_init(void); -void __init spear320_init(void); -void __init clk_init(void); +void spear_pmx_init(struct pmx_driver *pmx_driver, uint base, uint size); -/* Add spear300 machine device structure declarations here */ +/* pad mux declarations */ +#define PMX_FIRDA_MASK (1 << 14) +#define PMX_I2C_MASK (1 << 13) +#define PMX_SSP_CS_MASK (1 << 12) +#define PMX_SSP_MASK (1 << 11) +#define PMX_MII_MASK (1 << 10) +#define PMX_GPIO_PIN0_MASK (1 << 9) +#define PMX_GPIO_PIN1_MASK (1 << 8) +#define PMX_GPIO_PIN2_MASK (1 << 7) +#define PMX_GPIO_PIN3_MASK (1 << 6) +#define PMX_GPIO_PIN4_MASK (1 << 5) +#define PMX_GPIO_PIN5_MASK (1 << 4) +#define PMX_UART0_MODEM_MASK (1 << 3) +#define PMX_UART0_MASK (1 << 2) +#define PMX_TIMER_3_4_MASK (1 << 1) +#define PMX_TIMER_1_2_MASK (1 << 0) + +/* pad mux devices */ +extern struct pmx_dev pmx_firda; +extern struct pmx_dev pmx_i2c; +extern struct pmx_dev pmx_ssp_cs; +extern struct pmx_dev pmx_ssp; +extern struct pmx_dev pmx_mii; +extern struct pmx_dev pmx_gpio_pin0; +extern struct pmx_dev pmx_gpio_pin1; +extern struct pmx_dev pmx_gpio_pin2; +extern struct pmx_dev pmx_gpio_pin3; +extern struct pmx_dev pmx_gpio_pin4; +extern struct pmx_dev pmx_gpio_pin5; +extern struct pmx_dev pmx_uart0_modem; +extern struct pmx_dev pmx_uart0; +extern struct pmx_dev pmx_timer_3_4; +extern struct pmx_dev pmx_timer_1_2; + +#if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320) +/* padmux plgpio devices */ +extern struct pmx_dev pmx_plgpio_0_1; +extern struct pmx_dev pmx_plgpio_2_3; +extern struct pmx_dev pmx_plgpio_4_5; +extern struct pmx_dev pmx_plgpio_6_9; +extern struct pmx_dev pmx_plgpio_10_27; +extern struct pmx_dev pmx_plgpio_28; +extern struct pmx_dev pmx_plgpio_29; +extern struct pmx_dev pmx_plgpio_30; +extern struct pmx_dev pmx_plgpio_31; +extern struct pmx_dev pmx_plgpio_32; +extern struct pmx_dev pmx_plgpio_33; +extern struct pmx_dev pmx_plgpio_34_36; +extern struct pmx_dev pmx_plgpio_37_42; +extern struct pmx_dev pmx_plgpio_43_44_47_48; +extern struct pmx_dev pmx_plgpio_45_46_49_50; +#endif + +extern struct pmx_driver pmx_driver; + +/* spear300 declarations */ #ifdef CONFIG_MACH_SPEAR300 +/* Add spear300 machine device structure declarations here */ extern struct amba_device gpio1_device; + +/* pad mux modes */ +extern struct pmx_mode nand_mode; +extern struct pmx_mode nor_mode; +extern struct pmx_mode photo_frame_mode; +extern struct pmx_mode lend_ip_phone_mode; +extern struct pmx_mode hend_ip_phone_mode; +extern struct pmx_mode lend_wifi_phone_mode; +extern struct pmx_mode hend_wifi_phone_mode; +extern struct pmx_mode ata_pabx_wi2s_mode; +extern struct pmx_mode ata_pabx_i2s_mode; +extern struct pmx_mode caml_lcdw_mode; +extern struct pmx_mode camu_lcd_mode; +extern struct pmx_mode camu_wlcd_mode; +extern struct pmx_mode caml_lcd_mode; + +/* pad mux devices */ +extern struct pmx_dev pmx_fsmc_2_chips; +extern struct pmx_dev pmx_fsmc_4_chips; +extern struct pmx_dev pmx_keyboard; +extern struct pmx_dev pmx_clcd; +extern struct pmx_dev pmx_telecom_gpio; +extern struct pmx_dev pmx_telecom_tdm; +extern struct pmx_dev pmx_telecom_spi_cs_i2c_clk; +extern struct pmx_dev pmx_telecom_camera; +extern struct pmx_dev pmx_telecom_dac; +extern struct pmx_dev pmx_telecom_i2s; +extern struct pmx_dev pmx_telecom_boot_pins; +extern struct pmx_dev pmx_telecom_sdio_4bit; +extern struct pmx_dev pmx_telecom_sdio_8bit; +extern struct pmx_dev pmx_gpio1; + +void spear300_pmx_init(void); + +/* Add spear300 machine function declarations here */ +void __init spear300_init(void); + #endif /* CONFIG_MACH_SPEAR300 */ -/* Add spear310 machine device structure declarations here */ +/* spear310 declarations */ #ifdef CONFIG_MACH_SPEAR310 +/* Add spear310 machine device structure declarations here */ + +/* pad mux devices */ +extern struct pmx_dev pmx_emi_cs_0_1_4_5; +extern struct pmx_dev pmx_emi_cs_2_3; +extern struct pmx_dev pmx_uart1; +extern struct pmx_dev pmx_uart2; +extern struct pmx_dev pmx_uart3_4_5; +extern struct pmx_dev pmx_fsmc; +extern struct pmx_dev pmx_rs485_0_1; +extern struct pmx_dev pmx_tdm0; + +void spear310_pmx_init(void); + +/* Add spear310 machine function declarations here */ +void __init spear310_init(void); + #endif /* CONFIG_MACH_SPEAR310 */ -/* Add spear320 machine device structure declarations here */ +/* spear320 declarations */ #ifdef CONFIG_MACH_SPEAR320 +/* Add spear320 machine device structure declarations here */ + +/* pad mux modes */ +extern struct pmx_mode auto_net_smii_mode; +extern struct pmx_mode auto_net_mii_mode; +extern struct pmx_mode auto_exp_mode; +extern struct pmx_mode small_printers_mode; + +/* pad mux devices */ +extern struct pmx_dev pmx_clcd; +extern struct pmx_dev pmx_emi; +extern struct pmx_dev pmx_fsmc; +extern struct pmx_dev pmx_spp; +extern struct pmx_dev pmx_sdio; +extern struct pmx_dev pmx_i2s; +extern struct pmx_dev pmx_uart1; +extern struct pmx_dev pmx_uart1_modem; +extern struct pmx_dev pmx_uart2; +extern struct pmx_dev pmx_touchscreen; +extern struct pmx_dev pmx_can; +extern struct pmx_dev pmx_sdio_led; +extern struct pmx_dev pmx_pwm0; +extern struct pmx_dev pmx_pwm1; +extern struct pmx_dev pmx_pwm2; +extern struct pmx_dev pmx_pwm3; +extern struct pmx_dev pmx_ssp1; +extern struct pmx_dev pmx_ssp2; +extern struct pmx_dev pmx_mii1; +extern struct pmx_dev pmx_smii0; +extern struct pmx_dev pmx_smii1; +extern struct pmx_dev pmx_i2c1; + +void spear320_pmx_init(void); + +/* Add spear320 machine function declarations here */ +void __init spear320_init(void); + #endif /* CONFIG_MACH_SPEAR320 */ #endif /* __MACH_GENERIC_H */ diff --git a/arch/arm/mach-spear3xx/spear300.c b/arch/arm/mach-spear3xx/spear300.c index 63aca8f..66e7fcd 100644 --- a/arch/arm/mach-spear3xx/spear300.c +++ b/arch/arm/mach-spear3xx/spear300.c @@ -18,6 +18,357 @@ #include #include +/* pad multiplexing support */ +/* muxing registers */ +#define PAD_MUX_CONFIG_REG 0x00 +#define MODE_CONFIG_REG 0x04 + +/* modes */ +#define NAND_MODE (1 << 0) +#define NOR_MODE (1 << 1) +#define PHOTO_FRAME_MODE (1 << 2) +#define LEND_IP_PHONE_MODE (1 << 3) +#define HEND_IP_PHONE_MODE (1 << 4) +#define LEND_WIFI_PHONE_MODE (1 << 5) +#define HEND_WIFI_PHONE_MODE (1 << 6) +#define ATA_PABX_WI2S_MODE (1 << 7) +#define ATA_PABX_I2S_MODE (1 << 8) +#define CAML_LCDW_MODE (1 << 9) +#define CAMU_LCD_MODE (1 << 10) +#define CAMU_WLCD_MODE (1 << 11) +#define CAML_LCD_MODE (1 << 12) +#define ALL_MODES 0x1FFF + +struct pmx_mode nand_mode = { + .id = NAND_MODE, + .name = "nand mode", + .mask = 0x00, +}; + +struct pmx_mode nor_mode = { + .id = NOR_MODE, + .name = "nor mode", + .mask = 0x01, +}; + +struct pmx_mode photo_frame_mode = { + .id = PHOTO_FRAME_MODE, + .name = "photo frame mode", + .mask = 0x02, +}; + +struct pmx_mode lend_ip_phone_mode = { + .id = LEND_IP_PHONE_MODE, + .name = "lend ip phone mode", + .mask = 0x03, +}; + +struct pmx_mode hend_ip_phone_mode = { + .id = HEND_IP_PHONE_MODE, + .name = "hend ip phone mode", + .mask = 0x04, +}; + +struct pmx_mode lend_wifi_phone_mode = { + .id = LEND_WIFI_PHONE_MODE, + .name = "lend wifi phone mode", + .mask = 0x05, +}; + +struct pmx_mode hend_wifi_phone_mode = { + .id = HEND_WIFI_PHONE_MODE, + .name = "hend wifi phone mode", + .mask = 0x06, +}; + +struct pmx_mode ata_pabx_wi2s_mode = { + .id = ATA_PABX_WI2S_MODE, + .name = "ata pabx wi2s mode", + .mask = 0x07, +}; + +struct pmx_mode ata_pabx_i2s_mode = { + .id = ATA_PABX_I2S_MODE, + .name = "ata pabx i2s mode", + .mask = 0x08, +}; + +struct pmx_mode caml_lcdw_mode = { + .id = CAML_LCDW_MODE, + .name = "caml lcdw mode", + .mask = 0x0C, +}; + +struct pmx_mode camu_lcd_mode = { + .id = CAMU_LCD_MODE, + .name = "camu lcd mode", + .mask = 0x0D, +}; + +struct pmx_mode camu_wlcd_mode = { + .id = CAMU_WLCD_MODE, + .name = "camu wlcd mode", + .mask = 0x0E, +}; + +struct pmx_mode caml_lcd_mode = { + .id = CAML_LCD_MODE, + .name = "caml lcd mode", + .mask = 0x0F, +}; + +/* devices */ +struct pmx_dev_mode pmx_fsmc_2_chips_modes[] = { + { + .ids = NAND_MODE | NOR_MODE | PHOTO_FRAME_MODE | + ATA_PABX_WI2S_MODE | ATA_PABX_I2S_MODE, + .mask = PMX_FIRDA_MASK, + }, +}; + +struct pmx_dev pmx_fsmc_2_chips = { + .name = "fsmc_2_chips", + .modes = pmx_fsmc_2_chips_modes, + .mode_count = ARRAY_SIZE(pmx_fsmc_2_chips_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_fsmc_4_chips_modes[] = { + { + .ids = NAND_MODE | NOR_MODE | PHOTO_FRAME_MODE | + ATA_PABX_WI2S_MODE | ATA_PABX_I2S_MODE, + .mask = PMX_FIRDA_MASK | PMX_UART0_MASK, + }, +}; + +struct pmx_dev pmx_fsmc_4_chips = { + .name = "fsmc_4_chips", + .modes = pmx_fsmc_4_chips_modes, + .mode_count = ARRAY_SIZE(pmx_fsmc_4_chips_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_keyboard_modes[] = { + { + .ids = LEND_IP_PHONE_MODE | HEND_IP_PHONE_MODE | + LEND_WIFI_PHONE_MODE | HEND_WIFI_PHONE_MODE | + CAML_LCDW_MODE | CAMU_LCD_MODE | CAMU_WLCD_MODE | + CAML_LCD_MODE, + .mask = 0x0, + }, +}; + +struct pmx_dev pmx_keyboard = { + .name = "keyboard", + .modes = pmx_keyboard_modes, + .mode_count = ARRAY_SIZE(pmx_keyboard_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_clcd_modes[] = { + { + .ids = PHOTO_FRAME_MODE, + .mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK , + }, { + .ids = HEND_IP_PHONE_MODE | HEND_WIFI_PHONE_MODE | + CAMU_LCD_MODE | CAML_LCD_MODE, + .mask = PMX_TIMER_3_4_MASK, + }, +}; + +struct pmx_dev pmx_clcd = { + .name = "clcd", + .modes = pmx_clcd_modes, + .mode_count = ARRAY_SIZE(pmx_clcd_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_telecom_gpio_modes[] = { + { + .ids = PHOTO_FRAME_MODE | CAMU_LCD_MODE | CAML_LCD_MODE, + .mask = PMX_MII_MASK, + }, { + .ids = LEND_IP_PHONE_MODE | LEND_WIFI_PHONE_MODE, + .mask = PMX_MII_MASK | PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK, + }, { + .ids = ATA_PABX_I2S_MODE | CAML_LCDW_MODE | CAMU_WLCD_MODE, + .mask = PMX_MII_MASK | PMX_TIMER_3_4_MASK, + }, { + .ids = HEND_IP_PHONE_MODE | HEND_WIFI_PHONE_MODE, + .mask = PMX_MII_MASK | PMX_TIMER_1_2_MASK, + }, { + .ids = ATA_PABX_WI2S_MODE, + .mask = PMX_MII_MASK | PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK + | PMX_UART0_MODEM_MASK, + }, +}; + +struct pmx_dev pmx_telecom_gpio = { + .name = "telecom_gpio", + .modes = pmx_telecom_gpio_modes, + .mode_count = ARRAY_SIZE(pmx_telecom_gpio_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_telecom_tdm_modes[] = { + { + .ids = PHOTO_FRAME_MODE | LEND_IP_PHONE_MODE | + HEND_IP_PHONE_MODE | LEND_WIFI_PHONE_MODE + | HEND_WIFI_PHONE_MODE | ATA_PABX_WI2S_MODE + | ATA_PABX_I2S_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE + | CAMU_WLCD_MODE | CAML_LCD_MODE, + .mask = PMX_UART0_MODEM_MASK | PMX_SSP_CS_MASK, + }, +}; + +struct pmx_dev pmx_telecom_tdm = { + .name = "telecom_tdm", + .modes = pmx_telecom_tdm_modes, + .mode_count = ARRAY_SIZE(pmx_telecom_tdm_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_telecom_spi_cs_i2c_clk_modes[] = { + { + .ids = LEND_IP_PHONE_MODE | HEND_IP_PHONE_MODE | + LEND_WIFI_PHONE_MODE | HEND_WIFI_PHONE_MODE + | ATA_PABX_WI2S_MODE | ATA_PABX_I2S_MODE | + CAML_LCDW_MODE | CAML_LCD_MODE, + .mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK, + }, +}; + +struct pmx_dev pmx_telecom_spi_cs_i2c_clk = { + .name = "telecom_spi_cs_i2c_clk", + .modes = pmx_telecom_spi_cs_i2c_clk_modes, + .mode_count = ARRAY_SIZE(pmx_telecom_spi_cs_i2c_clk_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_telecom_camera_modes[] = { + { + .ids = CAML_LCDW_MODE | CAML_LCD_MODE, + .mask = PMX_MII_MASK, + }, { + .ids = CAMU_LCD_MODE | CAMU_WLCD_MODE, + .mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK | PMX_MII_MASK, + }, +}; + +struct pmx_dev pmx_telecom_camera = { + .name = "telecom_camera", + .modes = pmx_telecom_camera_modes, + .mode_count = ARRAY_SIZE(pmx_telecom_camera_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_telecom_dac_modes[] = { + { + .ids = ATA_PABX_I2S_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE + | CAMU_WLCD_MODE | CAML_LCD_MODE, + .mask = PMX_TIMER_1_2_MASK, + }, +}; + +struct pmx_dev pmx_telecom_dac = { + .name = "telecom_dac", + .modes = pmx_telecom_dac_modes, + .mode_count = ARRAY_SIZE(pmx_telecom_dac_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_telecom_i2s_modes[] = { + { + .ids = LEND_IP_PHONE_MODE | HEND_IP_PHONE_MODE + | LEND_WIFI_PHONE_MODE | HEND_WIFI_PHONE_MODE | + ATA_PABX_I2S_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE + | CAMU_WLCD_MODE | CAML_LCD_MODE, + .mask = PMX_UART0_MODEM_MASK, + }, +}; + +struct pmx_dev pmx_telecom_i2s = { + .name = "telecom_i2s", + .modes = pmx_telecom_i2s_modes, + .mode_count = ARRAY_SIZE(pmx_telecom_i2s_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_telecom_boot_pins_modes[] = { + { + .ids = NAND_MODE | NOR_MODE, + .mask = PMX_UART0_MODEM_MASK | PMX_TIMER_1_2_MASK | + PMX_TIMER_3_4_MASK, + }, +}; + +struct pmx_dev pmx_telecom_boot_pins = { + .name = "telecom_boot_pins", + .modes = pmx_telecom_boot_pins_modes, + .mode_count = ARRAY_SIZE(pmx_telecom_boot_pins_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_telecom_sdio_4bit_modes[] = { + { + .ids = PHOTO_FRAME_MODE | LEND_IP_PHONE_MODE | + HEND_IP_PHONE_MODE | LEND_WIFI_PHONE_MODE | + HEND_WIFI_PHONE_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE | + CAMU_WLCD_MODE | CAML_LCD_MODE | ATA_PABX_WI2S_MODE | + ATA_PABX_I2S_MODE, + .mask = PMX_GPIO_PIN0_MASK | PMX_GPIO_PIN1_MASK | + PMX_GPIO_PIN2_MASK | PMX_GPIO_PIN3_MASK | + PMX_GPIO_PIN4_MASK | PMX_GPIO_PIN5_MASK, + }, +}; + +struct pmx_dev pmx_telecom_sdio_4bit = { + .name = "telecom_sdio_4bit", + .modes = pmx_telecom_sdio_4bit_modes, + .mode_count = ARRAY_SIZE(pmx_telecom_sdio_4bit_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_telecom_sdio_8bit_modes[] = { + { + .ids = PHOTO_FRAME_MODE | LEND_IP_PHONE_MODE | + HEND_IP_PHONE_MODE | LEND_WIFI_PHONE_MODE | + HEND_WIFI_PHONE_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE | + CAMU_WLCD_MODE | CAML_LCD_MODE, + .mask = PMX_GPIO_PIN0_MASK | PMX_GPIO_PIN1_MASK | + PMX_GPIO_PIN2_MASK | PMX_GPIO_PIN3_MASK | + PMX_GPIO_PIN4_MASK | PMX_GPIO_PIN5_MASK | PMX_MII_MASK, + }, +}; + +struct pmx_dev pmx_telecom_sdio_8bit = { + .name = "telecom_sdio_8bit", + .modes = pmx_telecom_sdio_8bit_modes, + .mode_count = ARRAY_SIZE(pmx_telecom_sdio_8bit_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_gpio1_modes[] = { + { + .ids = PHOTO_FRAME_MODE, + .mask = PMX_UART0_MODEM_MASK | PMX_TIMER_1_2_MASK | + PMX_TIMER_3_4_MASK, + }, +}; + +struct pmx_dev pmx_gpio1 = { + .name = "arm gpio1", + .modes = pmx_gpio1_modes, + .mode_count = ARRAY_SIZE(pmx_gpio1_modes), + .enb_on_reset = 1, +}; + +/* pmx driver structure */ +struct pmx_driver pmx_driver = { + .mode_reg = {.offset = MODE_CONFIG_REG, .mask = 0x0000000f}, + .mux_reg = {.offset = PAD_MUX_CONFIG_REG, .mask = 0x00007fff}, +}; + /* Add spear300 specific devices here */ /* arm gpio1 device registeration */ static struct pl061_platform_data gpio1_plat_data = { @@ -38,8 +389,15 @@ struct amba_device gpio1_device = { .irq = {IRQ_GEN_RAS_1, NO_IRQ}, }; +/* spear300 routines */ void __init spear300_init(void) { /* call spear3xx family common init function */ spear3xx_init(); } + +void spear300_pmx_init(void) +{ + spear_pmx_init(&pmx_driver, SPEAR300_SOC_CONFIG_BASE, + SPEAR300_SOC_CONFIG_SIZE); +} diff --git a/arch/arm/mach-spear3xx/spear300_evb.c b/arch/arm/mach-spear3xx/spear300_evb.c index 1272a38..bb21db1 100644 --- a/arch/arm/mach-spear3xx/spear300_evb.c +++ b/arch/arm/mach-spear3xx/spear300_evb.c @@ -16,6 +16,22 @@ #include #include +/* padmux devices to enable */ +static struct pmx_dev *pmx_devs[] = { + /* spear3xx specific devices */ + &pmx_i2c, + &pmx_ssp_cs, + &pmx_ssp, + &pmx_mii, + &pmx_uart0, + + /* spear300 specific devices */ + &pmx_fsmc_2_chips, + &pmx_clcd, + &pmx_telecom_sdio_4bit, + &pmx_gpio1, +}; + static struct amba_device *amba_devs[] __initdata = { /* spear3xx specific devices */ &gpio_device, @@ -38,6 +54,12 @@ static void __init spear300_evb_init(void) /* call spear300 machine init function */ spear300_init(); + /* padmux initialization */ + pmx_driver.mode = &photo_frame_mode; + pmx_driver.devs = pmx_devs; + pmx_driver.devs_count = ARRAY_SIZE(pmx_devs); + spear300_pmx_init(); + /* Add Platform Devices */ platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs)); diff --git a/arch/arm/mach-spear3xx/spear310.c b/arch/arm/mach-spear3xx/spear310.c index 6eb62f9..dd5a572 100644 --- a/arch/arm/mach-spear3xx/spear310.c +++ b/arch/arm/mach-spear3xx/spear310.c @@ -16,10 +16,139 @@ #include #include +/* pad multiplexing support */ +/* muxing registers */ +#define PAD_MUX_CONFIG_REG 0x08 + +/* devices */ +struct pmx_dev_mode pmx_emi_cs_0_1_4_5_modes[] = { + { + .ids = 0x00, + .mask = PMX_TIMER_3_4_MASK, + }, +}; + +struct pmx_dev pmx_emi_cs_0_1_4_5 = { + .name = "emi_cs_0_1_4_5", + .modes = pmx_emi_cs_0_1_4_5_modes, + .mode_count = ARRAY_SIZE(pmx_emi_cs_0_1_4_5_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_emi_cs_2_3_modes[] = { + { + .ids = 0x00, + .mask = PMX_TIMER_1_2_MASK, + }, +}; + +struct pmx_dev pmx_emi_cs_2_3 = { + .name = "emi_cs_2_3", + .modes = pmx_emi_cs_2_3_modes, + .mode_count = ARRAY_SIZE(pmx_emi_cs_2_3_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_uart1_modes[] = { + { + .ids = 0x00, + .mask = PMX_FIRDA_MASK, + }, +}; + +struct pmx_dev pmx_uart1 = { + .name = "uart1", + .modes = pmx_uart1_modes, + .mode_count = ARRAY_SIZE(pmx_uart1_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_uart2_modes[] = { + { + .ids = 0x00, + .mask = PMX_TIMER_1_2_MASK, + }, +}; + +struct pmx_dev pmx_uart2 = { + .name = "uart2", + .modes = pmx_uart2_modes, + .mode_count = ARRAY_SIZE(pmx_uart2_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_uart3_4_5_modes[] = { + { + .ids = 0x00, + .mask = PMX_UART0_MODEM_MASK, + }, +}; + +struct pmx_dev pmx_uart3_4_5 = { + .name = "uart3_4_5", + .modes = pmx_uart3_4_5_modes, + .mode_count = ARRAY_SIZE(pmx_uart3_4_5_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_fsmc_modes[] = { + { + .ids = 0x00, + .mask = PMX_SSP_CS_MASK, + }, +}; + +struct pmx_dev pmx_fsmc = { + .name = "fsmc", + .modes = pmx_fsmc_modes, + .mode_count = ARRAY_SIZE(pmx_fsmc_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_rs485_0_1_modes[] = { + { + .ids = 0x00, + .mask = PMX_MII_MASK, + }, +}; + +struct pmx_dev pmx_rs485_0_1 = { + .name = "rs485_0_1", + .modes = pmx_rs485_0_1_modes, + .mode_count = ARRAY_SIZE(pmx_rs485_0_1_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_tdm0_modes[] = { + { + .ids = 0x00, + .mask = PMX_MII_MASK, + }, +}; + +struct pmx_dev pmx_tdm0 = { + .name = "tdm0", + .modes = pmx_tdm0_modes, + .mode_count = ARRAY_SIZE(pmx_tdm0_modes), + .enb_on_reset = 1, +}; + +/* pmx driver structure */ +struct pmx_driver pmx_driver = { + .mux_reg = {.offset = PAD_MUX_CONFIG_REG, .mask = 0x00007fff}, +}; + /* Add spear310 specific devices here */ +/* spear310 routines */ void __init spear310_init(void) { /* call spear3xx family common init function */ spear3xx_init(); } + +void spear310_pmx_init(void) +{ + spear_pmx_init(&pmx_driver, SPEAR310_SOC_CONFIG_BASE, + SPEAR310_SOC_CONFIG_SIZE); +} diff --git a/arch/arm/mach-spear3xx/spear310_evb.c b/arch/arm/mach-spear3xx/spear310_evb.c index e781b2b..7facf66 100644 --- a/arch/arm/mach-spear3xx/spear310_evb.c +++ b/arch/arm/mach-spear3xx/spear310_evb.c @@ -16,6 +16,30 @@ #include #include +/* padmux devices to enable */ +static struct pmx_dev *pmx_devs[] = { + /* spear3xx specific devices */ + &pmx_i2c, + &pmx_ssp, + &pmx_gpio_pin0, + &pmx_gpio_pin1, + &pmx_gpio_pin2, + &pmx_gpio_pin3, + &pmx_gpio_pin4, + &pmx_gpio_pin5, + &pmx_uart0, + + /* spear310 specific devices */ + &pmx_emi_cs_0_1_4_5, + &pmx_emi_cs_2_3, + &pmx_uart1, + &pmx_uart2, + &pmx_uart3_4_5, + &pmx_fsmc, + &pmx_rs485_0_1, + &pmx_tdm0, +}; + static struct amba_device *amba_devs[] __initdata = { /* spear3xx specific devices */ &gpio_device, @@ -37,6 +61,12 @@ static void __init spear310_evb_init(void) /* call spear310 machine init function */ spear310_init(); + /* padmux initialization */ + pmx_driver.mode = NULL; + pmx_driver.devs = pmx_devs; + pmx_driver.devs_count = ARRAY_SIZE(pmx_devs); + spear310_pmx_init(); + /* Add Platform Devices */ platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs)); diff --git a/arch/arm/mach-spear3xx/spear320.c b/arch/arm/mach-spear3xx/spear320.c index 72d4548..2cedf5e 100644 --- a/arch/arm/mach-spear3xx/spear320.c +++ b/arch/arm/mach-spear3xx/spear320.c @@ -16,10 +16,384 @@ #include #include +/* pad multiplexing support */ +/* muxing registers */ +#define PAD_MUX_CONFIG_REG 0x0C +#define MODE_CONFIG_REG 0x10 + +/* modes */ +#define AUTO_NET_SMII_MODE (1 << 0) +#define AUTO_NET_MII_MODE (1 << 1) +#define AUTO_EXP_MODE (1 << 2) +#define SMALL_PRINTERS_MODE (1 << 3) +#define ALL_MODES 0xF + +struct pmx_mode auto_net_smii_mode = { + .id = AUTO_NET_SMII_MODE, + .name = "Automation Networking SMII Mode", + .mask = 0x00, +}; + +struct pmx_mode auto_net_mii_mode = { + .id = AUTO_NET_MII_MODE, + .name = "Automation Networking MII Mode", + .mask = 0x01, +}; + +struct pmx_mode auto_exp_mode = { + .id = AUTO_EXP_MODE, + .name = "Automation Expanded Mode", + .mask = 0x02, +}; + +struct pmx_mode small_printers_mode = { + .id = SMALL_PRINTERS_MODE, + .name = "Small Printers Mode", + .mask = 0x03, +}; + +/* devices */ +struct pmx_dev_mode pmx_clcd_modes[] = { + { + .ids = AUTO_NET_SMII_MODE, + .mask = 0x0, + }, +}; + +struct pmx_dev pmx_clcd = { + .name = "clcd", + .modes = pmx_clcd_modes, + .mode_count = ARRAY_SIZE(pmx_clcd_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_emi_modes[] = { + { + .ids = AUTO_EXP_MODE, + .mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK, + }, +}; + +struct pmx_dev pmx_emi = { + .name = "emi", + .modes = pmx_emi_modes, + .mode_count = ARRAY_SIZE(pmx_emi_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_fsmc_modes[] = { + { + .ids = ALL_MODES, + .mask = 0x0, + }, +}; + +struct pmx_dev pmx_fsmc = { + .name = "fsmc", + .modes = pmx_fsmc_modes, + .mode_count = ARRAY_SIZE(pmx_fsmc_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_spp_modes[] = { + { + .ids = SMALL_PRINTERS_MODE, + .mask = 0x0, + }, +}; + +struct pmx_dev pmx_spp = { + .name = "spp", + .modes = pmx_spp_modes, + .mode_count = ARRAY_SIZE(pmx_spp_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_sdio_modes[] = { + { + .ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE | + SMALL_PRINTERS_MODE, + .mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK, + }, +}; + +struct pmx_dev pmx_sdio = { + .name = "sdio", + .modes = pmx_sdio_modes, + .mode_count = ARRAY_SIZE(pmx_sdio_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_i2s_modes[] = { + { + .ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE, + .mask = PMX_UART0_MODEM_MASK, + }, +}; + +struct pmx_dev pmx_i2s = { + .name = "i2s", + .modes = pmx_i2s_modes, + .mode_count = ARRAY_SIZE(pmx_i2s_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_uart1_modes[] = { + { + .ids = ALL_MODES, + .mask = PMX_GPIO_PIN0_MASK | PMX_GPIO_PIN1_MASK, + }, +}; + +struct pmx_dev pmx_uart1 = { + .name = "uart1", + .modes = pmx_uart1_modes, + .mode_count = ARRAY_SIZE(pmx_uart1_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_uart1_modem_modes[] = { + { + .ids = AUTO_EXP_MODE, + .mask = PMX_TIMER_1_2_MASK | PMX_TIMER_3_4_MASK | + PMX_SSP_CS_MASK, + }, { + .ids = SMALL_PRINTERS_MODE, + .mask = PMX_GPIO_PIN3_MASK | PMX_GPIO_PIN4_MASK | + PMX_GPIO_PIN5_MASK | PMX_SSP_CS_MASK, + }, +}; + +struct pmx_dev pmx_uart1_modem = { + .name = "uart1_modem", + .modes = pmx_uart1_modem_modes, + .mode_count = ARRAY_SIZE(pmx_uart1_modem_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_uart2_modes[] = { + { + .ids = ALL_MODES, + .mask = PMX_FIRDA_MASK, + }, +}; + +struct pmx_dev pmx_uart2 = { + .name = "uart2", + .modes = pmx_uart2_modes, + .mode_count = ARRAY_SIZE(pmx_uart2_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_touchscreen_modes[] = { + { + .ids = AUTO_NET_SMII_MODE, + .mask = PMX_SSP_CS_MASK, + }, +}; + +struct pmx_dev pmx_touchscreen = { + .name = "touchscreen", + .modes = pmx_touchscreen_modes, + .mode_count = ARRAY_SIZE(pmx_touchscreen_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_can_modes[] = { + { + .ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE | AUTO_EXP_MODE, + .mask = PMX_GPIO_PIN2_MASK | PMX_GPIO_PIN3_MASK | + PMX_GPIO_PIN4_MASK | PMX_GPIO_PIN5_MASK, + }, +}; + +struct pmx_dev pmx_can = { + .name = "can", + .modes = pmx_can_modes, + .mode_count = ARRAY_SIZE(pmx_can_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_sdio_led_modes[] = { + { + .ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE, + .mask = PMX_SSP_CS_MASK, + }, +}; + +struct pmx_dev pmx_sdio_led = { + .name = "sdio_led", + .modes = pmx_sdio_led_modes, + .mode_count = ARRAY_SIZE(pmx_sdio_led_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_pwm0_modes[] = { + { + .ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE, + .mask = PMX_UART0_MODEM_MASK, + }, { + .ids = AUTO_EXP_MODE | SMALL_PRINTERS_MODE, + .mask = PMX_MII_MASK, + }, +}; + +struct pmx_dev pmx_pwm0 = { + .name = "pwm0", + .modes = pmx_pwm0_modes, + .mode_count = ARRAY_SIZE(pmx_pwm0_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_pwm1_modes[] = { + { + .ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE, + .mask = PMX_UART0_MODEM_MASK, + }, { + .ids = AUTO_EXP_MODE | SMALL_PRINTERS_MODE, + .mask = PMX_MII_MASK, + }, +}; + +struct pmx_dev pmx_pwm1 = { + .name = "pwm1", + .modes = pmx_pwm1_modes, + .mode_count = ARRAY_SIZE(pmx_pwm1_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_pwm2_modes[] = { + { + .ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE, + .mask = PMX_SSP_CS_MASK, + }, { + .ids = AUTO_EXP_MODE | SMALL_PRINTERS_MODE, + .mask = PMX_MII_MASK, + }, +}; + +struct pmx_dev pmx_pwm2 = { + .name = "pwm2", + .modes = pmx_pwm2_modes, + .mode_count = ARRAY_SIZE(pmx_pwm2_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_pwm3_modes[] = { + { + .ids = AUTO_EXP_MODE | SMALL_PRINTERS_MODE | AUTO_NET_SMII_MODE, + .mask = PMX_MII_MASK, + }, +}; + +struct pmx_dev pmx_pwm3 = { + .name = "pwm3", + .modes = pmx_pwm3_modes, + .mode_count = ARRAY_SIZE(pmx_pwm3_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_ssp1_modes[] = { + { + .ids = SMALL_PRINTERS_MODE | AUTO_NET_SMII_MODE, + .mask = PMX_MII_MASK, + }, +}; + +struct pmx_dev pmx_ssp1 = { + .name = "ssp1", + .modes = pmx_ssp1_modes, + .mode_count = ARRAY_SIZE(pmx_ssp1_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_ssp2_modes[] = { + { + .ids = AUTO_NET_SMII_MODE, + .mask = PMX_MII_MASK, + }, +}; + +struct pmx_dev pmx_ssp2 = { + .name = "ssp2", + .modes = pmx_ssp2_modes, + .mode_count = ARRAY_SIZE(pmx_ssp2_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_mii1_modes[] = { + { + .ids = AUTO_NET_MII_MODE, + .mask = 0x0, + }, +}; + +struct pmx_dev pmx_mii1 = { + .name = "mii1", + .modes = pmx_mii1_modes, + .mode_count = ARRAY_SIZE(pmx_mii1_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_smii0_modes[] = { + { + .ids = AUTO_NET_SMII_MODE | AUTO_EXP_MODE | SMALL_PRINTERS_MODE, + .mask = PMX_MII_MASK, + }, +}; + +struct pmx_dev pmx_smii0 = { + .name = "smii0", + .modes = pmx_smii0_modes, + .mode_count = ARRAY_SIZE(pmx_smii0_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_smii1_modes[] = { + { + .ids = AUTO_NET_SMII_MODE | SMALL_PRINTERS_MODE, + .mask = PMX_MII_MASK, + }, +}; + +struct pmx_dev pmx_smii1 = { + .name = "smii1", + .modes = pmx_smii1_modes, + .mode_count = ARRAY_SIZE(pmx_smii1_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_i2c1_modes[] = { + { + .ids = AUTO_EXP_MODE, + .mask = 0x0, + }, +}; + +struct pmx_dev pmx_i2c1 = { + .name = "i2c1", + .modes = pmx_i2c1_modes, + .mode_count = ARRAY_SIZE(pmx_i2c1_modes), + .enb_on_reset = 1, +}; + +/* pmx driver structure */ +struct pmx_driver pmx_driver = { + .mode_reg = {.offset = MODE_CONFIG_REG, .mask = 0x00000007}, + .mux_reg = {.offset = PAD_MUX_CONFIG_REG, .mask = 0x00007fff}, +}; + /* Add spear320 specific devices here */ +/* spear320 routines */ void __init spear320_init(void) { /* call spear3xx family common init function */ spear3xx_init(); } + +void spear320_pmx_init(void) +{ + spear_pmx_init(&pmx_driver, SPEAR320_SOC_CONFIG_BASE, + SPEAR320_SOC_CONFIG_SIZE); +} diff --git a/arch/arm/mach-spear3xx/spear320_evb.c b/arch/arm/mach-spear3xx/spear320_evb.c index 85bc4d2..62ac685 100644 --- a/arch/arm/mach-spear3xx/spear320_evb.c +++ b/arch/arm/mach-spear3xx/spear320_evb.c @@ -16,6 +16,27 @@ #include #include +/* padmux devices to enable */ +static struct pmx_dev *pmx_devs[] = { + /* spear3xx specific devices */ + &pmx_i2c, + &pmx_ssp, + &pmx_mii, + &pmx_uart0, + + /* spear320 specific devices */ + &pmx_fsmc, + &pmx_sdio, + &pmx_i2s, + &pmx_uart1, + &pmx_uart2, + &pmx_can, + &pmx_pwm0, + &pmx_pwm1, + &pmx_pwm2, + &pmx_mii1, +}; + static struct amba_device *amba_devs[] __initdata = { /* spear3xx specific devices */ &gpio_device, @@ -37,6 +58,12 @@ static void __init spear320_evb_init(void) /* call spear320 machine init function */ spear320_init(); + /* padmux initialization */ + pmx_driver.mode = &auto_net_mii_mode; + pmx_driver.devs = pmx_devs; + pmx_driver.devs_count = ARRAY_SIZE(pmx_devs); + spear320_pmx_init(); + /* Add Platform Devices */ platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs)); diff --git a/arch/arm/mach-spear3xx/spear3xx.c b/arch/arm/mach-spear3xx/spear3xx.c index 82ebcd3..e87313a 100644 --- a/arch/arm/mach-spear3xx/spear3xx.c +++ b/arch/arm/mach-spear3xx/spear3xx.c @@ -99,3 +99,450 @@ void __init spear3xx_map_io(void) /* This will initialize clock framework */ clk_init(); } + +/* pad multiplexing support */ +/* devices */ +struct pmx_dev_mode pmx_firda_modes[] = { + { + .ids = 0xffffffff, + .mask = PMX_FIRDA_MASK, + }, +}; + +struct pmx_dev pmx_firda = { + .name = "firda", + .modes = pmx_firda_modes, + .mode_count = ARRAY_SIZE(pmx_firda_modes), + .enb_on_reset = 0, +}; + +struct pmx_dev_mode pmx_i2c_modes[] = { + { + .ids = 0xffffffff, + .mask = PMX_I2C_MASK, + }, +}; + +struct pmx_dev pmx_i2c = { + .name = "i2c", + .modes = pmx_i2c_modes, + .mode_count = ARRAY_SIZE(pmx_i2c_modes), + .enb_on_reset = 0, +}; + +struct pmx_dev_mode pmx_ssp_cs_modes[] = { + { + .ids = 0xffffffff, + .mask = PMX_SSP_CS_MASK, + }, +}; + +struct pmx_dev pmx_ssp_cs = { + .name = "ssp_chip_selects", + .modes = pmx_ssp_cs_modes, + .mode_count = ARRAY_SIZE(pmx_ssp_cs_modes), + .enb_on_reset = 0, +}; + +struct pmx_dev_mode pmx_ssp_modes[] = { + { + .ids = 0xffffffff, + .mask = PMX_SSP_MASK, + }, +}; + +struct pmx_dev pmx_ssp = { + .name = "ssp", + .modes = pmx_ssp_modes, + .mode_count = ARRAY_SIZE(pmx_ssp_modes), + .enb_on_reset = 0, +}; + +struct pmx_dev_mode pmx_mii_modes[] = { + { + .ids = 0xffffffff, + .mask = PMX_MII_MASK, + }, +}; + +struct pmx_dev pmx_mii = { + .name = "mii", + .modes = pmx_mii_modes, + .mode_count = ARRAY_SIZE(pmx_mii_modes), + .enb_on_reset = 0, +}; + +struct pmx_dev_mode pmx_gpio_pin0_modes[] = { + { + .ids = 0xffffffff, + .mask = PMX_GPIO_PIN0_MASK, + }, +}; + +struct pmx_dev pmx_gpio_pin0 = { + .name = "gpio_pin0", + .modes = pmx_gpio_pin0_modes, + .mode_count = ARRAY_SIZE(pmx_gpio_pin0_modes), + .enb_on_reset = 0, +}; + +struct pmx_dev_mode pmx_gpio_pin1_modes[] = { + { + .ids = 0xffffffff, + .mask = PMX_GPIO_PIN1_MASK, + }, +}; + +struct pmx_dev pmx_gpio_pin1 = { + .name = "gpio_pin1", + .modes = pmx_gpio_pin1_modes, + .mode_count = ARRAY_SIZE(pmx_gpio_pin1_modes), + .enb_on_reset = 0, +}; + +struct pmx_dev_mode pmx_gpio_pin2_modes[] = { + { + .ids = 0xffffffff, + .mask = PMX_GPIO_PIN2_MASK, + }, +}; + +struct pmx_dev pmx_gpio_pin2 = { + .name = "gpio_pin2", + .modes = pmx_gpio_pin2_modes, + .mode_count = ARRAY_SIZE(pmx_gpio_pin2_modes), + .enb_on_reset = 0, +}; + +struct pmx_dev_mode pmx_gpio_pin3_modes[] = { + { + .ids = 0xffffffff, + .mask = PMX_GPIO_PIN3_MASK, + }, +}; + +struct pmx_dev pmx_gpio_pin3 = { + .name = "gpio_pin3", + .modes = pmx_gpio_pin3_modes, + .mode_count = ARRAY_SIZE(pmx_gpio_pin3_modes), + .enb_on_reset = 0, +}; + +struct pmx_dev_mode pmx_gpio_pin4_modes[] = { + { + .ids = 0xffffffff, + .mask = PMX_GPIO_PIN4_MASK, + }, +}; + +struct pmx_dev pmx_gpio_pin4 = { + .name = "gpio_pin4", + .modes = pmx_gpio_pin4_modes, + .mode_count = ARRAY_SIZE(pmx_gpio_pin4_modes), + .enb_on_reset = 0, +}; + +struct pmx_dev_mode pmx_gpio_pin5_modes[] = { + { + .ids = 0xffffffff, + .mask = PMX_GPIO_PIN5_MASK, + }, +}; + +struct pmx_dev pmx_gpio_pin5 = { + .name = "gpio_pin5", + .modes = pmx_gpio_pin5_modes, + .mode_count = ARRAY_SIZE(pmx_gpio_pin5_modes), + .enb_on_reset = 0, +}; + +struct pmx_dev_mode pmx_uart0_modem_modes[] = { + { + .ids = 0xffffffff, + .mask = PMX_UART0_MODEM_MASK, + }, +}; + +struct pmx_dev pmx_uart0_modem = { + .name = "uart0_modem", + .modes = pmx_uart0_modem_modes, + .mode_count = ARRAY_SIZE(pmx_uart0_modem_modes), + .enb_on_reset = 0, +}; + +struct pmx_dev_mode pmx_uart0_modes[] = { + { + .ids = 0xffffffff, + .mask = PMX_UART0_MASK, + }, +}; + +struct pmx_dev pmx_uart0 = { + .name = "uart0", + .modes = pmx_uart0_modes, + .mode_count = ARRAY_SIZE(pmx_uart0_modes), + .enb_on_reset = 0, +}; + +struct pmx_dev_mode pmx_timer_3_4_modes[] = { + { + .ids = 0xffffffff, + .mask = PMX_TIMER_3_4_MASK, + }, +}; + +struct pmx_dev pmx_timer_3_4 = { + .name = "timer_3_4", + .modes = pmx_timer_3_4_modes, + .mode_count = ARRAY_SIZE(pmx_timer_3_4_modes), + .enb_on_reset = 0, +}; + +struct pmx_dev_mode pmx_timer_1_2_modes[] = { + { + .ids = 0xffffffff, + .mask = PMX_TIMER_1_2_MASK, + }, +}; + +struct pmx_dev pmx_timer_1_2 = { + .name = "timer_1_2", + .modes = pmx_timer_1_2_modes, + .mode_count = ARRAY_SIZE(pmx_timer_1_2_modes), + .enb_on_reset = 0, +}; + +#if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320) +/* plgpios devices */ +struct pmx_dev_mode pmx_plgpio_0_1_modes[] = { + { + .ids = 0x00, + .mask = PMX_FIRDA_MASK, + }, +}; + +struct pmx_dev pmx_plgpio_0_1 = { + .name = "plgpio 0 and 1", + .modes = pmx_plgpio_0_1_modes, + .mode_count = ARRAY_SIZE(pmx_plgpio_0_1_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_plgpio_2_3_modes[] = { + { + .ids = 0x00, + .mask = PMX_UART0_MASK, + }, +}; + +struct pmx_dev pmx_plgpio_2_3 = { + .name = "plgpio 2 and 3", + .modes = pmx_plgpio_2_3_modes, + .mode_count = ARRAY_SIZE(pmx_plgpio_2_3_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_plgpio_4_5_modes[] = { + { + .ids = 0x00, + .mask = PMX_I2C_MASK, + }, +}; + +struct pmx_dev pmx_plgpio_4_5 = { + .name = "plgpio 4 and 5", + .modes = pmx_plgpio_4_5_modes, + .mode_count = ARRAY_SIZE(pmx_plgpio_4_5_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_plgpio_6_9_modes[] = { + { + .ids = 0x00, + .mask = PMX_SSP_MASK, + }, +}; + +struct pmx_dev pmx_plgpio_6_9 = { + .name = "plgpio 6 to 9", + .modes = pmx_plgpio_6_9_modes, + .mode_count = ARRAY_SIZE(pmx_plgpio_6_9_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_plgpio_10_27_modes[] = { + { + .ids = 0x00, + .mask = PMX_MII_MASK, + }, +}; + +struct pmx_dev pmx_plgpio_10_27 = { + .name = "plgpio 10 to 27", + .modes = pmx_plgpio_10_27_modes, + .mode_count = ARRAY_SIZE(pmx_plgpio_10_27_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_plgpio_28_modes[] = { + { + .ids = 0x00, + .mask = PMX_GPIO_PIN0_MASK, + }, +}; + +struct pmx_dev pmx_plgpio_28 = { + .name = "plgpio 28", + .modes = pmx_plgpio_28_modes, + .mode_count = ARRAY_SIZE(pmx_plgpio_28_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_plgpio_29_modes[] = { + { + .ids = 0x00, + .mask = PMX_GPIO_PIN1_MASK, + }, +}; + +struct pmx_dev pmx_plgpio_29 = { + .name = "plgpio 29", + .modes = pmx_plgpio_29_modes, + .mode_count = ARRAY_SIZE(pmx_plgpio_29_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_plgpio_30_modes[] = { + { + .ids = 0x00, + .mask = PMX_GPIO_PIN2_MASK, + }, +}; + +struct pmx_dev pmx_plgpio_30 = { + .name = "plgpio 30", + .modes = pmx_plgpio_30_modes, + .mode_count = ARRAY_SIZE(pmx_plgpio_30_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_plgpio_31_modes[] = { + { + .ids = 0x00, + .mask = PMX_GPIO_PIN3_MASK, + }, +}; + +struct pmx_dev pmx_plgpio_31 = { + .name = "plgpio 31", + .modes = pmx_plgpio_31_modes, + .mode_count = ARRAY_SIZE(pmx_plgpio_31_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_plgpio_32_modes[] = { + { + .ids = 0x00, + .mask = PMX_GPIO_PIN4_MASK, + }, +}; + +struct pmx_dev pmx_plgpio_32 = { + .name = "plgpio 32", + .modes = pmx_plgpio_32_modes, + .mode_count = ARRAY_SIZE(pmx_plgpio_32_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_plgpio_33_modes[] = { + { + .ids = 0x00, + .mask = PMX_GPIO_PIN5_MASK, + }, +}; + +struct pmx_dev pmx_plgpio_33 = { + .name = "plgpio 33", + .modes = pmx_plgpio_33_modes, + .mode_count = ARRAY_SIZE(pmx_plgpio_33_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_plgpio_34_36_modes[] = { + { + .ids = 0x00, + .mask = PMX_SSP_CS_MASK, + }, +}; + +struct pmx_dev pmx_plgpio_34_36 = { + .name = "plgpio 34 to 36", + .modes = pmx_plgpio_34_36_modes, + .mode_count = ARRAY_SIZE(pmx_plgpio_34_36_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_plgpio_37_42_modes[] = { + { + .ids = 0x00, + .mask = PMX_UART0_MODEM_MASK, + }, +}; + +struct pmx_dev pmx_plgpio_37_42 = { + .name = "plgpio 37 to 42", + .modes = pmx_plgpio_37_42_modes, + .mode_count = ARRAY_SIZE(pmx_plgpio_37_42_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_plgpio_43_44_47_48_modes[] = { + { + .ids = 0x00, + .mask = PMX_TIMER_1_2_MASK, + }, +}; + +struct pmx_dev pmx_plgpio_43_44_47_48 = { + .name = "plgpio 43, 44, 47 and 48", + .modes = pmx_plgpio_43_44_47_48_modes, + .mode_count = ARRAY_SIZE(pmx_plgpio_43_44_47_48_modes), + .enb_on_reset = 1, +}; + +struct pmx_dev_mode pmx_plgpio_45_46_49_50_modes[] = { + { + .ids = 0x00, + .mask = PMX_TIMER_3_4_MASK, + }, +}; + +struct pmx_dev pmx_plgpio_45_46_49_50 = { + .name = "plgpio 45, 46, 49 and 50", + .modes = pmx_plgpio_45_46_49_50_modes, + .mode_count = ARRAY_SIZE(pmx_plgpio_45_46_49_50_modes), + .enb_on_reset = 1, +}; + +#endif + +/* spear padmux initialization function */ +void spear_pmx_init(struct pmx_driver *pmx_driver, uint base, uint size) +{ + int ret = 0; + + /* pad mux initialization */ + pmx_driver->base = ioremap(base, size); + if (!pmx_driver->base) { + ret = -ENOMEM; + goto pmx_fail; + } + + ret = pmx_register(pmx_driver); + iounmap(pmx_driver->base); + +pmx_fail: + if (ret) + printk(KERN_ERR "padmux: registeration failed. err no: %d\n", + ret); +} diff --git a/arch/arm/plat-spear/Makefile b/arch/arm/plat-spear/Makefile index 96f9ac3..6f4ad5e 100644 --- a/arch/arm/plat-spear/Makefile +++ b/arch/arm/plat-spear/Makefile @@ -3,4 +3,4 @@ # # Common support -obj-y := clock.o time.o +obj-y := clock.o padmux.o time.o diff --git a/arch/arm/plat-spear/include/plat/padmux.h b/arch/arm/plat-spear/include/plat/padmux.h new file mode 100644 index 0000000..877f3ad --- /dev/null +++ b/arch/arm/plat-spear/include/plat/padmux.h @@ -0,0 +1,92 @@ +/* + * arch/arm/plat-spear/include/plat/padmux.h + * + * SPEAr platform specific gpio pads muxing file + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __PLAT_PADMUX_H +#define __PLAT_PADMUX_H + +#include + +/* + * struct pmx_reg: configuration structure for mode reg and mux reg + * + * offset: offset of mode reg + * mask: mask of mode reg + */ +struct pmx_reg { + u32 offset; + u32 mask; +}; + +/* + * struct pmx_dev_mode: configuration structure every group of modes of a device + * + * ids: all modes for this configuration + * mask: mask for supported mode + */ +struct pmx_dev_mode { + u32 ids; + u32 mask; +}; + +/* + * struct pmx_mode: mode definition structure + * + * name: mode name + * mask: mode mask + */ +struct pmx_mode { + char *name; + u32 id; + u32 mask; +}; + +/* + * struct pmx_dev: device definition structure + * + * name: device name + * modes: device configuration array for different modes supported + * mode_count: size of modes array + * is_active: is peripheral active/enabled + * enb_on_reset: if 1, mask bits to be cleared in reg otherwise to be set in reg + */ +struct pmx_dev { + char *name; + struct pmx_dev_mode *modes; + u8 mode_count; + bool is_active; + bool enb_on_reset; +}; + +/* + * struct pmx_driver: driver definition structure + * + * mode: mode to be set + * devs: array of pointer to pmx devices + * devs_count: ARRAY_SIZE of devs + * base: base address of soc config registers + * mode_reg: structure of mode config register + * mux_reg: structure of device mux config register + */ +struct pmx_driver { + struct pmx_mode *mode; + struct pmx_dev **devs; + u8 devs_count; + u32 *base; + struct pmx_reg mode_reg; + struct pmx_reg mux_reg; +}; + +/* pmx functions */ +int pmx_register(struct pmx_driver *driver); + +#endif /* __PLAT_PADMUX_H */ diff --git a/arch/arm/plat-spear/padmux.c b/arch/arm/plat-spear/padmux.c new file mode 100644 index 0000000..d2aab3a --- /dev/null +++ b/arch/arm/plat-spear/padmux.c @@ -0,0 +1,164 @@ +/* + * arch/arm/plat-spear/include/plat/padmux.c + * + * SPEAr platform specific gpio pads muxing source file + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include + +/* + * struct pmx: pmx definition structure + * + * base: base address of configuration registers + * mode_reg: mode configurations + * mux_reg: muxing configurations + * active_mode: pointer to current active mode + */ +struct pmx { + u32 base; + struct pmx_reg mode_reg; + struct pmx_reg mux_reg; + struct pmx_mode *active_mode; +}; + +static struct pmx *pmx; + +/** + * pmx_mode_set - Enables an multiplexing mode + * @mode - pointer to pmx mode + * + * It will set mode of operation in hardware. + * Returns -ve on Err otherwise 0 + */ +static int pmx_mode_set(struct pmx_mode *mode) +{ + u32 val; + + if (!mode->name) + return -EFAULT; + + pmx->active_mode = mode; + + val = readl(pmx->base + pmx->mode_reg.offset); + val &= ~pmx->mode_reg.mask; + val |= mode->mask & pmx->mode_reg.mask; + writel(val, pmx->base + pmx->mode_reg.offset); + + return 0; +} + +/** + * pmx_devs_enable - Enables list of devices + * @devs - pointer to pmx device array + * @count - number of devices to enable + * + * It will enable pads for all required peripherals once and only once. + * If peripheral is not supported by current mode then request is rejected. + * Conflicts between peripherals are not handled and peripherals will be + * enabled in the order they are present in pmx_dev array. + * In case of conflicts last peripheral enalbed will be present. + * Returns -ve on Err otherwise 0 + */ +static int pmx_devs_enable(struct pmx_dev **devs, u8 count) +{ + u32 val, i, mask; + + if (!count) + return -EINVAL; + + val = readl(pmx->base + pmx->mux_reg.offset); + for (i = 0; i < count; i++) { + u8 j = 0; + + if (!devs[i]->name || !devs[i]->modes) { + printk(KERN_ERR "padmux: dev name or modes is null\n"); + continue; + } + /* check if peripheral exists in active mode */ + if (pmx->active_mode) { + bool found = false; + for (j = 0; j < devs[i]->mode_count; j++) { + if (devs[i]->modes[j].ids & + pmx->active_mode->id) { + found = true; + break; + } + } + if (found == false) { + printk(KERN_ERR "%s device not available in %s"\ + "mode\n", devs[i]->name, + pmx->active_mode->name); + continue; + } + } + + /* enable peripheral */ + mask = devs[i]->modes[j].mask & pmx->mux_reg.mask; + if (devs[i]->enb_on_reset) + val &= ~mask; + else + val |= mask; + + devs[i]->is_active = true; + } + writel(val, pmx->base + pmx->mux_reg.offset); + kfree(pmx); + + /* this will ensure that multiplexing can't be changed now */ + pmx = (struct pmx *)-1; + + return 0; +} + +/** + * pmx_register - registers a platform requesting pad mux feature + * @driver - pointer to driver structure containing driver specific parameters + * + * Also this must be called only once. This will allocate memory for pmx + * structure, will call pmx_mode_set, will call pmx_devs_enable. + * Returns -ve on Err otherwise 0 + */ +int pmx_register(struct pmx_driver *driver) +{ + int ret = 0; + + if (pmx) + return -EPERM; + if (!driver->base || !driver->devs) + return -EFAULT; + + pmx = kzalloc(sizeof(*pmx), GFP_KERNEL); + if (!pmx) + return -ENOMEM; + + pmx->base = (u32)driver->base; + pmx->mode_reg.offset = driver->mode_reg.offset; + pmx->mode_reg.mask = driver->mode_reg.mask; + pmx->mux_reg.offset = driver->mux_reg.offset; + pmx->mux_reg.mask = driver->mux_reg.mask; + + /* choose mode to enable */ + if (driver->mode) { + ret = pmx_mode_set(driver->mode); + if (ret) + goto pmx_fail; + } + ret = pmx_devs_enable(driver->devs, driver->devs_count); + if (ret) + goto pmx_fail; + + return 0; + +pmx_fail: + return ret; +} -- cgit v0.10.2 From ff37f6e5910c4fd7ad42063d89c0687def665941 Mon Sep 17 00:00:00 2001 From: viresh kumar Date: Thu, 1 Apr 2010 12:49:09 +0100 Subject: ARM: 6021/1: ST SPEAr: Added ARM PrimeXsys System Controller SP810 header file Reviewed-by: Linus Walleij Signed-off-by: Viresh Kumar Signed-off-by: Russell King diff --git a/arch/arm/include/asm/hardware/sp810.h b/arch/arm/include/asm/hardware/sp810.h new file mode 100644 index 0000000..a101f10 --- /dev/null +++ b/arch/arm/include/asm/hardware/sp810.h @@ -0,0 +1,59 @@ +/* + * arch/arm/include/asm/hardware/sp810.h + * + * ARM PrimeXsys System Controller SP810 header file + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __ASM_ARM_SP810_H +#define __ASM_ARM_SP810_H + +#include + +/* sysctl registers offset */ +#define SCCTRL 0x000 +#define SCSYSSTAT 0x004 +#define SCIMCTRL 0x008 +#define SCIMSTAT 0x00C +#define SCXTALCTRL 0x010 +#define SCPLLCTRL 0x014 +#define SCPLLFCTRL 0x018 +#define SCPERCTRL0 0x01C +#define SCPERCTRL1 0x020 +#define SCPEREN 0x024 +#define SCPERDIS 0x028 +#define SCPERCLKEN 0x02C +#define SCPERSTAT 0x030 +#define SCSYSID0 0xEE0 +#define SCSYSID1 0xEE4 +#define SCSYSID2 0xEE8 +#define SCSYSID3 0xEEC +#define SCITCR 0xF00 +#define SCITIR0 0xF04 +#define SCITIR1 0xF08 +#define SCITOR 0xF0C +#define SCCNTCTRL 0xF10 +#define SCCNTDATA 0xF14 +#define SCCNTSTEP 0xF18 +#define SCPERIPHID0 0xFE0 +#define SCPERIPHID1 0xFE4 +#define SCPERIPHID2 0xFE8 +#define SCPERIPHID3 0xFEC +#define SCPCELLID0 0xFF0 +#define SCPCELLID1 0xFF4 +#define SCPCELLID2 0xFF8 +#define SCPCELLID3 0xFFC + +static inline void sysctl_soft_reset(void __iomem *base) +{ + /* writing any value to SCSYSSTAT reg will reset system */ + writel(0, base + SCSYSSTAT); +} + +#endif /* __ASM_ARM_SP810_H */ -- cgit v0.10.2 From 6e8699f7d68589e0e9ab324f598a3357bceb40bc Mon Sep 17 00:00:00 2001 From: Albin Tonnerre Date: Sat, 3 Apr 2010 11:40:28 +0100 Subject: ARM: 6026/1: ARM: Add support for LZMA-compressed kernel images This patch allows using a kernel image compressed with LZMA on ARM. Extracting the image is fairly slow, but it might be useful on machines with a very limited amount of storage, as the size benefit is quite significant (about 25% smaller with LZMA compared to GZIP) Tested-by: Martin Michlmayr Tested-by: Paulius Zaleckas Signed-off-by: Albin Tonnerre Signed-off-by: Russell King diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index bf856f4..5c8128c 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -21,6 +21,7 @@ config ARM select HAVE_GENERIC_DMA_COHERENT select HAVE_KERNEL_GZIP select HAVE_KERNEL_LZO + select HAVE_KERNEL_LZMA select HAVE_PERF_EVENTS select PERF_USE_VMALLOC help diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index 97c89e7..53faa90 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -65,6 +65,7 @@ SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/ suffix_$(CONFIG_KERNEL_GZIP) = gzip suffix_$(CONFIG_KERNEL_LZO) = lzo +suffix_$(CONFIG_KERNEL_LZMA) = lzma targets := vmlinux vmlinux.lds \ piggy.$(suffix_y) piggy.$(suffix_y).o \ diff --git a/arch/arm/boot/compressed/decompress.c b/arch/arm/boot/compressed/decompress.c index 9c09707..4c72a97 100644 --- a/arch/arm/boot/compressed/decompress.c +++ b/arch/arm/boot/compressed/decompress.c @@ -40,6 +40,10 @@ extern void error(char *); #include "../../../../lib/decompress_unlzo.c" #endif +#ifdef CONFIG_KERNEL_LZMA +#include "../../../../lib/decompress_unlzma.c" +#endif + void do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x)) { decompress(input, len, NULL, NULL, output, NULL, error); diff --git a/arch/arm/boot/compressed/piggy.lzma.S b/arch/arm/boot/compressed/piggy.lzma.S new file mode 100644 index 0000000..d7e69cf --- /dev/null +++ b/arch/arm/boot/compressed/piggy.lzma.S @@ -0,0 +1,6 @@ + .section .piggydata,#alloc + .globl input_data +input_data: + .incbin "arch/arm/boot/compressed/piggy.lzma" + .globl input_data_end +input_data_end: -- cgit v0.10.2 From f76348a360fe92063e07a8f54b0c1ea67f91e76c Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 24 Dec 2009 12:57:01 +0000 Subject: ARM: remove unnecessary cache flush This cache flush occurs when we first insert a page into the page tables, where a page did not exist previously. There can be no cache lines associated with this virtual mapping, so this cache flush is redundant. Tested-by: Mike Rapoport Tested-by: Mikael Pettersson Signed-off-by: Russell King diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c index c9b97e9..82df01a 100644 --- a/arch/arm/mm/fault-armv.c +++ b/arch/arm/mm/fault-armv.c @@ -133,8 +133,6 @@ make_coherent(struct address_space *mapping, struct vm_area_struct *vma, flush_dcache_mmap_unlock(mapping); if (aliases) do_adjust_pte(vma, addr, pfn, ptep); - else - flush_cache_page(vma, addr, pfn); } /* -- cgit v0.10.2 From e193ba290f0228453341b41ab2bbdd963259f97e Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 24 Dec 2009 18:32:13 +0000 Subject: ARM: dma: add /proc/dma support to arch/arm/kernel/dma.c We have our own private implementation for ISA-like DMA which has been missing exposure via the /proc/dma interface. Add support for this. Signed-off-by: Russell King diff --git a/arch/arm/kernel/dma.c b/arch/arm/kernel/dma.c index 7d5b9fb..2c4a185 100644 --- a/arch/arm/kernel/dma.c +++ b/arch/arm/kernel/dma.c @@ -16,6 +16,8 @@ #include #include #include +#include +#include #include @@ -264,3 +266,37 @@ int get_dma_residue(unsigned int chan) return ret; } EXPORT_SYMBOL(get_dma_residue); + +#ifdef CONFIG_PROC_FS +static int proc_dma_show(struct seq_file *m, void *v) +{ + int i; + + for (i = 0 ; i < MAX_DMA_CHANNELS ; i++) { + dma_t *dma = dma_channel(i); + if (dma && dma->lock) + seq_printf(m, "%2d: %s\n", i, dma->device_id); + } + return 0; +} + +static int proc_dma_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_dma_show, NULL); +} + +static const struct file_operations proc_dma_operations = { + .open = proc_dma_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int __init proc_dma_init(void) +{ + proc_create("dma", 0, NULL, &proc_dma_operations); + return 0; +} + +__initcall(proc_dma_init); +#endif -- cgit v0.10.2 From 8e797a7e4f588fb3b9cfe9860b00dcd3b14f8b60 Mon Sep 17 00:00:00 2001 From: Srinidhi Kasagar Date: Sat, 3 Apr 2010 19:10:45 +0100 Subject: ARM: 6027/1: ux500: enable l2x0 support This enables the l2x0 support and ensures that the secondary CPU can see the page table and secondary data at this point. Signed-off-by: srinidhi kasagar Acked-by: Linus Walleij Signed-off-by: Russell King diff --git a/arch/arm/mach-ux500/cpu-u8500.c b/arch/arm/mach-ux500/cpu-u8500.c index 5fb4466..979f1c3 100644 --- a/arch/arm/mach-ux500/cpu-u8500.c +++ b/arch/arm/mach-ux500/cpu-u8500.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -127,6 +128,7 @@ static struct map_desc u8500_io_desc[] __initdata = { __IO_DEV_DESC(U8500_GPIO2_BASE, SZ_4K), __IO_DEV_DESC(U8500_GPIO3_BASE, SZ_4K), __IO_DEV_DESC(U8500_GPIO5_BASE, SZ_4K), + __IO_DEV_DESC(U8500_L2CC_BASE, SZ_4K), }; static struct map_desc u8500ed_io_desc[] __initdata = { @@ -183,3 +185,18 @@ static void __init u8500_timer_init(void) struct sys_timer u8500_timer = { .init = u8500_timer_init, }; + +#ifdef CONFIG_CACHE_L2X0 +static int u8500_l2x0_init(void) +{ + void __iomem *l2x0_base; + + l2x0_base = __io_address(U8500_L2CC_BASE); + + /* 64KB way size, 8 way associativity, force WA */ + l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff); + + return 0; +} +early_initcall(u8500_l2x0_init); +#endif diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c index 8dfe7ca..76dd935 100644 --- a/arch/arm/mach-ux500/platsmp.c +++ b/arch/arm/mach-ux500/platsmp.c @@ -75,7 +75,8 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) * that it has been released by resetting pen_release. */ pen_release = cpu; - flush_cache_all(); + __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release)); + outer_clean_range(__pa(&pen_release), __pa(&pen_release) + 1); timeout = jiffies + (1 * HZ); while (time_before(jiffies, timeout)) { diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index c4ed9f9..22c1c83 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -754,7 +754,8 @@ config CACHE_FEROCEON_L2_WRITETHROUGH config CACHE_L2X0 bool "Enable the L2x0 outer cache controller" depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \ - REALVIEW_EB_A9MP || ARCH_MX35 || ARCH_MX31 || MACH_REALVIEW_PBX || ARCH_NOMADIK || ARCH_OMAP4 + REALVIEW_EB_A9MP || ARCH_MX35 || ARCH_MX31 || MACH_REALVIEW_PBX || \ + ARCH_NOMADIK || ARCH_OMAP4 || ARCH_U8500 default y select OUTER_CACHE help -- cgit v0.10.2 From 771dc157e06d69fcece0b2c8a29b9010345d8e9a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 8 Apr 2010 07:38:52 +0100 Subject: ARM: 6032/1: ARM: MMCI: support 8bit mode on the ST Micro version This adds support for an 8bit wide bus to the card (data lines MCIDAT0 through 7 exist) on the ST Micro version and alters the U300 platform to support this. Also add some ST_ prefix to the ST-specific registers. Signed-off-by: Linus Walleij Signed-off-by: Russell King diff --git a/arch/arm/mach-u300/mmc.c b/arch/arm/mach-u300/mmc.c index 109f5a6..ef8032d 100644 --- a/arch/arm/mach-u300/mmc.c +++ b/arch/arm/mach-u300/mmc.c @@ -105,7 +105,7 @@ int __devinit mmc_init(struct amba_device *adev) mmci_card->mmc0_plat_data.gpio_wp = -1; mmci_card->mmc0_plat_data.gpio_cd = -1; mmci_card->mmc0_plat_data.capabilities = MMC_CAP_MMC_HIGHSPEED | - MMC_CAP_SD_HIGHSPEED | MMC_CAP_4_BIT_DATA; + MMC_CAP_SD_HIGHSPEED | MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA; mmcsd_device->platform_data = (void *) &mmci_card->mmc0_plat_data; diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 84c103a..7e70c1a 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -55,14 +55,16 @@ static void mmci_set_clkreg(struct mmci_host *host, unsigned int desired) host->cclk = host->mclk / (2 * (clk + 1)); } if (host->hw_designer == AMBA_VENDOR_ST) - clk |= MCI_FCEN; /* Bug fix in ST IP block */ + clk |= MCI_ST_FCEN; /* Bug fix in ST IP block */ clk |= MCI_CLK_ENABLE; /* This hasn't proven to be worthwhile */ /* clk |= MCI_CLK_PWRSAVE; */ } if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_4) - clk |= MCI_WIDE_BUS; + clk |= MCI_4BIT_BUS; + if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_8) + clk |= MCI_ST_8BIT_BUS; writel(clk, host->base + MMCICLOCK); } diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h index 1ceb9a9..d77062e 100644 --- a/drivers/mmc/host/mmci.h +++ b/drivers/mmc/host/mmci.h @@ -25,9 +25,11 @@ #define MCI_CLK_ENABLE (1 << 8) #define MCI_CLK_PWRSAVE (1 << 9) #define MCI_CLK_BYPASS (1 << 10) -#define MCI_WIDE_BUS (1 << 11) +#define MCI_4BIT_BUS (1 << 11) +/* 8bit wide buses supported in ST Micro versions */ +#define MCI_ST_8BIT_BUS (1 << 12) /* HW flow control on the ST Micro version */ -#define MCI_FCEN (1 << 13) +#define MCI_ST_FCEN (1 << 13) #define MMCIARGUMENT 0x008 #define MMCICOMMAND 0x00c -- cgit v0.10.2 From 808d97ccbe8e8251b1435e86c762965fd7e8a75e Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 8 Apr 2010 07:39:38 +0100 Subject: ARM: 6033/1: ARM: MMCI: pass max frequency from platform This introduce the field f_max into the mmci_platform_data, making it possible to pass in a desired block clocking frequency from a board configuration. This is often more desirable than using a module parameter. We keep the module parameter as a fallback as well as the default frequency specified for this parameter if a parameter is not provided. This also adds some kerneldoc style documentation to the platform data struct in mmci.h. Signed-off-by: Linus Walleij Signed-off-by: Russell King diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 7e70c1a..ff115d9 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -631,7 +631,18 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) mmc->ops = &mmci_ops; mmc->f_min = (host->mclk + 511) / 512; - mmc->f_max = min(host->mclk, fmax); + /* + * If the platform data supplies a maximum operating + * frequency, this takes precedence. Else, we fall back + * to using the module parameter, which has a (low) + * default value in case it is not specified. Either + * value must not exceed the clock rate into the block, + * of course. + */ + if (plat->f_max) + mmc->f_max = min(host->mclk, plat->f_max); + else + mmc->f_max = min(host->mclk, fmax); dev_dbg(mmc_dev(mmc), "clocking block at %u Hz\n", mmc->f_max); #ifdef CONFIG_REGULATOR diff --git a/include/linux/amba/mmci.h b/include/linux/amba/mmci.h index 6b42417..7e466fe 100644 --- a/include/linux/amba/mmci.h +++ b/include/linux/amba/mmci.h @@ -6,8 +6,29 @@ #include +/** + * struct mmci_platform_data - platform configuration for the MMCI + * (also known as PL180) block. + * @f_max: the maximum operational frequency for this host in this + * platform configuration. When this is specified it takes precedence + * over the module parameter for the same frequency. + * @ocr_mask: available voltages on the 4 pins from the block, this + * is ignored if a regulator is used, see the MMC_VDD_* masks in + * mmc/host.h + * @translate_vdd: a callback function to translate a MMC_VDD_* + * mask into a value to be binary or:ed and written into the + * MMCIPWR register of the block + * @status: if no GPIO read function was given to the block in + * gpio_wp (below) this function will be called to determine + * whether a card is present in the MMC slot or not + * @gpio_wp: read this GPIO pin to see if the card is write protected + * @gpio_cd: read this GPIO pin to detect card insertion + * @capabilities: the capabilities of the block as implemented in + * this platform, signify anything MMC_CAP_* from mmc/host.h + */ struct mmci_platform_data { - unsigned int ocr_mask; /* available voltages */ + unsigned int f_max; + unsigned int ocr_mask; u32 (*translate_vdd)(struct device *, unsigned int); unsigned int (*status)(struct device *); int gpio_wp; -- cgit v0.10.2 From 72638ddd1422df38d1b1b269038cfc8d66152c10 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 8 Apr 2010 07:40:13 +0100 Subject: ARM: 6034/1: ARM: U300: set f_max to 24 MHz for MMCI This employs the frequency setting mechanism introduced to the MMCI to specify that this system can actually be clocked at 24 MHz. Signed-off-by: Linus Walleij Signed-off-by: Russell King diff --git a/arch/arm/mach-u300/mmc.c b/arch/arm/mach-u300/mmc.c index ef8032d..783f123 100644 --- a/arch/arm/mach-u300/mmc.c +++ b/arch/arm/mach-u300/mmc.c @@ -101,6 +101,7 @@ int __devinit mmc_init(struct amba_device *adev) * we have a regulator we can control instead. */ /* Nominally 2.85V on our platform */ + mmci_card->mmc0_plat_data.f_max = 24000000; mmci_card->mmc0_plat_data.status = mmc_status; mmci_card->mmc0_plat_data.gpio_wp = -1; mmci_card->mmc0_plat_data.gpio_cd = -1; -- cgit v0.10.2 From e2941054ed596dd67a6094b7aca165af1b1f9926 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Wed, 14 Apr 2010 17:54:04 +0100 Subject: ARM: 6056/1: AT91: at91sam9g10 chip identification changed A bit in the at91sam9g10 identification number changed between Engineering Sample and final product. This patch will identify both as being at91sam9g10. Signed-off-by: Nicolas Ferre Acked-by: Andrew Victor Signed-off-by: Russell King diff --git a/arch/arm/mach-at91/include/mach/cpu.h b/arch/arm/mach-at91/include/mach/cpu.h index 5a06501..833659d 100644 --- a/arch/arm/mach-at91/include/mach/cpu.h +++ b/arch/arm/mach-at91/include/mach/cpu.h @@ -21,7 +21,7 @@ #define ARCH_ID_AT91SAM9260 0x019803a0 #define ARCH_ID_AT91SAM9261 0x019703a0 #define ARCH_ID_AT91SAM9263 0x019607a0 -#define ARCH_ID_AT91SAM9G10 0x819903a0 +#define ARCH_ID_AT91SAM9G10 0x019903a0 #define ARCH_ID_AT91SAM9G20 0x019905a0 #define ARCH_ID_AT91SAM9RL64 0x019b03a0 #define ARCH_ID_AT91SAM9G45 0x819b05a0 @@ -108,7 +108,7 @@ static inline unsigned long at91cap9_rev_identify(void) #endif #ifdef CONFIG_ARCH_AT91SAM9G10 -#define cpu_is_at91sam9g10() (at91_cpu_identify() == ARCH_ID_AT91SAM9G10) +#define cpu_is_at91sam9g10() ((at91_cpu_identify() & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10) #else #define cpu_is_at91sam9g10() (0) #endif -- cgit v0.10.2 From 76e1d9047e4edefb8ada20aa90d5762306082bd6 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Mon, 5 Apr 2010 15:35:57 +0200 Subject: perf: Store active software events in a hashlist Each time a software event triggers, we need to walk through the entire list of events from the current cpu and task contexts to retrieve a running perf event that matches. We also need to check a matching perf event is actually counting. This walk is wasteful and makes the event fast path scaling down with a growing number of events running on the same contexts. To solve this, we store the running perf events in a hashlist to get an immediate access to them against their type:event_id when they trigger. v2: - Fix SWEVENT_HLIST_SIZE definition (and re-learn some basic maths along the way) - Only allocate hlist for online cpus, but keep track of the refcount on offline possible cpus too, so that we allocate it if needed when it becomes online. - Drop the kref use as it's not adapted to our tricks anymore. v3: - Fix bad refcount check (address instead of value). Thanks to Eric Dumazet who spotted this. - While exiting cpu, move the hlist release out of the IPI path to lock the hlist mutex sanely. Signed-off-by: Frederic Weisbecker Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Ingo Molnar diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 6e96cc8..bf896d0 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -589,6 +589,14 @@ enum perf_group_flag { PERF_GROUP_SOFTWARE = 0x1, }; +#define SWEVENT_HLIST_BITS 8 +#define SWEVENT_HLIST_SIZE (1 << SWEVENT_HLIST_BITS) + +struct swevent_hlist { + struct hlist_head heads[SWEVENT_HLIST_SIZE]; + struct rcu_head rcu_head; +}; + /** * struct perf_event - performance event kernel representation: */ @@ -597,6 +605,7 @@ struct perf_event { struct list_head group_entry; struct list_head event_entry; struct list_head sibling_list; + struct hlist_node hlist_entry; int nr_siblings; int group_flags; struct perf_event *group_leader; @@ -744,6 +753,9 @@ struct perf_cpu_context { int active_oncpu; int max_pertask; int exclusive; + struct swevent_hlist *swevent_hlist; + struct mutex hlist_mutex; + int hlist_refcount; /* * Recursion avoidance: diff --git a/kernel/perf_event.c b/kernel/perf_event.c index fcf42dcd..9efdfe5 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -3966,36 +3967,6 @@ static void perf_swevent_add(struct perf_event *event, u64 nr, perf_swevent_overflow(event, 0, nmi, data, regs); } -static int perf_swevent_is_counting(struct perf_event *event) -{ - /* - * The event is active, we're good! - */ - if (event->state == PERF_EVENT_STATE_ACTIVE) - return 1; - - /* - * The event is off/error, not counting. - */ - if (event->state != PERF_EVENT_STATE_INACTIVE) - return 0; - - /* - * The event is inactive, if the context is active - * we're part of a group that didn't make it on the 'pmu', - * not counting. - */ - if (event->ctx->is_active) - return 0; - - /* - * We're inactive and the context is too, this means the - * task is scheduled out, we're counting events that happen - * to us, like migration events. - */ - return 1; -} - static int perf_tp_event_match(struct perf_event *event, struct perf_sample_data *data); @@ -4019,12 +3990,6 @@ static int perf_swevent_match(struct perf_event *event, struct perf_sample_data *data, struct pt_regs *regs) { - if (event->cpu != -1 && event->cpu != smp_processor_id()) - return 0; - - if (!perf_swevent_is_counting(event)) - return 0; - if (event->attr.type != type) return 0; @@ -4041,18 +4006,53 @@ static int perf_swevent_match(struct perf_event *event, return 1; } -static void perf_swevent_ctx_event(struct perf_event_context *ctx, - enum perf_type_id type, - u32 event_id, u64 nr, int nmi, - struct perf_sample_data *data, - struct pt_regs *regs) +static inline u64 swevent_hash(u64 type, u32 event_id) +{ + u64 val = event_id | (type << 32); + + return hash_64(val, SWEVENT_HLIST_BITS); +} + +static struct hlist_head * +find_swevent_head(struct perf_cpu_context *ctx, u64 type, u32 event_id) +{ + u64 hash; + struct swevent_hlist *hlist; + + hash = swevent_hash(type, event_id); + + hlist = rcu_dereference(ctx->swevent_hlist); + if (!hlist) + return NULL; + + return &hlist->heads[hash]; +} + +static void do_perf_sw_event(enum perf_type_id type, u32 event_id, + u64 nr, int nmi, + struct perf_sample_data *data, + struct pt_regs *regs) { + struct perf_cpu_context *cpuctx; struct perf_event *event; + struct hlist_node *node; + struct hlist_head *head; - list_for_each_entry_rcu(event, &ctx->event_list, event_entry) { + cpuctx = &__get_cpu_var(perf_cpu_context); + + rcu_read_lock(); + + head = find_swevent_head(cpuctx, type, event_id); + + if (!head) + goto end; + + hlist_for_each_entry_rcu(event, node, head, hlist_entry) { if (perf_swevent_match(event, type, event_id, data, regs)) perf_swevent_add(event, nr, nmi, data, regs); } +end: + rcu_read_unlock(); } int perf_swevent_get_recursion_context(void) @@ -4090,27 +4090,6 @@ void perf_swevent_put_recursion_context(int rctx) } EXPORT_SYMBOL_GPL(perf_swevent_put_recursion_context); -static void do_perf_sw_event(enum perf_type_id type, u32 event_id, - u64 nr, int nmi, - struct perf_sample_data *data, - struct pt_regs *regs) -{ - struct perf_cpu_context *cpuctx; - struct perf_event_context *ctx; - - cpuctx = &__get_cpu_var(perf_cpu_context); - rcu_read_lock(); - perf_swevent_ctx_event(&cpuctx->ctx, type, event_id, - nr, nmi, data, regs); - /* - * doesn't really matter which of the child contexts the - * events ends up in. - */ - ctx = rcu_dereference(current->perf_event_ctxp); - if (ctx) - perf_swevent_ctx_event(ctx, type, event_id, nr, nmi, data, regs); - rcu_read_unlock(); -} void __perf_sw_event(u32 event_id, u64 nr, int nmi, struct pt_regs *regs, u64 addr) @@ -4136,16 +4115,28 @@ static void perf_swevent_read(struct perf_event *event) static int perf_swevent_enable(struct perf_event *event) { struct hw_perf_event *hwc = &event->hw; + struct perf_cpu_context *cpuctx; + struct hlist_head *head; + + cpuctx = &__get_cpu_var(perf_cpu_context); if (hwc->sample_period) { hwc->last_period = hwc->sample_period; perf_swevent_set_period(event); } + + head = find_swevent_head(cpuctx, event->attr.type, event->attr.config); + if (WARN_ON_ONCE(!head)) + return -EINVAL; + + hlist_add_head_rcu(&event->hlist_entry, head); + return 0; } static void perf_swevent_disable(struct perf_event *event) { + hlist_del_rcu(&event->hlist_entry); } static const struct pmu perf_ops_generic = { @@ -4359,13 +4350,115 @@ static int perf_tp_event_match(struct perf_event *event, return 0; } +static void swevent_hlist_release_rcu(struct rcu_head *rcu_head) +{ + struct swevent_hlist *hlist; + + hlist = container_of(rcu_head, struct swevent_hlist, rcu_head); + kfree(hlist); +} + +static void swevent_hlist_release(struct perf_cpu_context *cpuctx) +{ + struct swevent_hlist *hlist; + + if (!cpuctx->swevent_hlist) + return; + + hlist = cpuctx->swevent_hlist; + rcu_assign_pointer(cpuctx->swevent_hlist, NULL); + call_rcu(&hlist->rcu_head, swevent_hlist_release_rcu); +} + +static void swevent_hlist_put_cpu(struct perf_event *event, int cpu) +{ + struct perf_cpu_context *cpuctx = &per_cpu(perf_cpu_context, cpu); + + mutex_lock(&cpuctx->hlist_mutex); + + if (!--cpuctx->hlist_refcount) + swevent_hlist_release(cpuctx); + + mutex_unlock(&cpuctx->hlist_mutex); +} + +static void swevent_hlist_put(struct perf_event *event) +{ + int cpu; + + if (event->cpu != -1) { + swevent_hlist_put_cpu(event, event->cpu); + return; + } + + for_each_possible_cpu(cpu) + swevent_hlist_put_cpu(event, cpu); +} + +static int swevent_hlist_get_cpu(struct perf_event *event, int cpu) +{ + struct perf_cpu_context *cpuctx = &per_cpu(perf_cpu_context, cpu); + int err = 0; + + mutex_lock(&cpuctx->hlist_mutex); + + if (!cpuctx->swevent_hlist && cpu_online(cpu)) { + struct swevent_hlist *hlist; + + hlist = kzalloc(sizeof(*hlist), GFP_KERNEL); + if (!hlist) { + err = -ENOMEM; + goto exit; + } + rcu_assign_pointer(cpuctx->swevent_hlist, hlist); + } + cpuctx->hlist_refcount++; + exit: + mutex_unlock(&cpuctx->hlist_mutex); + + return err; +} + +static int swevent_hlist_get(struct perf_event *event) +{ + int err; + int cpu, failed_cpu; + + if (event->cpu != -1) + return swevent_hlist_get_cpu(event, event->cpu); + + get_online_cpus(); + for_each_possible_cpu(cpu) { + err = swevent_hlist_get_cpu(event, cpu); + if (err) { + failed_cpu = cpu; + goto fail; + } + } + put_online_cpus(); + + return 0; + fail: + for_each_possible_cpu(cpu) { + if (cpu == failed_cpu) + break; + swevent_hlist_put_cpu(event, cpu); + } + + put_online_cpus(); + return err; +} + static void tp_perf_event_destroy(struct perf_event *event) { perf_trace_disable(event->attr.config); + swevent_hlist_put(event); } static const struct pmu *tp_perf_event_init(struct perf_event *event) { + int err; + /* * Raw tracepoint data is a severe data leak, only allow root to * have these. @@ -4379,6 +4472,11 @@ static const struct pmu *tp_perf_event_init(struct perf_event *event) return NULL; event->destroy = tp_perf_event_destroy; + err = swevent_hlist_get(event); + if (err) { + perf_trace_disable(event->attr.config); + return ERR_PTR(err); + } return &perf_ops_generic; } @@ -4479,6 +4577,7 @@ static void sw_perf_event_destroy(struct perf_event *event) WARN_ON(event->parent); atomic_dec(&perf_swevent_enabled[event_id]); + swevent_hlist_put(event); } static const struct pmu *sw_perf_event_init(struct perf_event *event) @@ -4517,6 +4616,12 @@ static const struct pmu *sw_perf_event_init(struct perf_event *event) case PERF_COUNT_SW_ALIGNMENT_FAULTS: case PERF_COUNT_SW_EMULATION_FAULTS: if (!event->parent) { + int err; + + err = swevent_hlist_get(event); + if (err) + return ERR_PTR(err); + atomic_inc(&perf_swevent_enabled[event_id]); event->destroy = sw_perf_event_destroy; } @@ -5389,6 +5494,7 @@ static void __init perf_event_init_all_cpus(void) for_each_possible_cpu(cpu) { cpuctx = &per_cpu(perf_cpu_context, cpu); + mutex_init(&cpuctx->hlist_mutex); __perf_event_init_context(&cpuctx->ctx, NULL); } } @@ -5402,6 +5508,16 @@ static void __cpuinit perf_event_init_cpu(int cpu) spin_lock(&perf_resource_lock); cpuctx->max_pertask = perf_max_events - perf_reserved_percpu; spin_unlock(&perf_resource_lock); + + mutex_lock(&cpuctx->hlist_mutex); + if (cpuctx->hlist_refcount > 0) { + struct swevent_hlist *hlist; + + hlist = kzalloc(sizeof(*hlist), GFP_KERNEL); + WARN_ON_ONCE(!hlist); + rcu_assign_pointer(cpuctx->swevent_hlist, hlist); + } + mutex_unlock(&cpuctx->hlist_mutex); } #ifdef CONFIG_HOTPLUG_CPU @@ -5421,6 +5537,10 @@ static void perf_event_exit_cpu(int cpu) struct perf_cpu_context *cpuctx = &per_cpu(perf_cpu_context, cpu); struct perf_event_context *ctx = &cpuctx->ctx; + mutex_lock(&cpuctx->hlist_mutex); + swevent_hlist_release(cpuctx); + mutex_unlock(&cpuctx->hlist_mutex); + mutex_lock(&ctx->mutex); smp_call_function_single(cpu, __perf_event_exit_cpu, NULL, 1); mutex_unlock(&ctx->mutex); -- cgit v0.10.2 From df8290bf7ea6b3051e2f315579a6e829309ec1ed Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Fri, 9 Apr 2010 00:28:14 +0200 Subject: perf: Make clock software events consistent with general exclusion rules The cpu/task clock events implement their own version of exclusion on top of exclude_user and exclude_kernel. The result is that when the event triggered in the kernel but we have exclude_kernel set, we try to rewind using task_pt_regs. There are two side effects of this: - we call task_pt_regs even on kernel threads, which doesn't give us the desired result. - if the event occured in the kernel, we shouldn't rewind to the user context. We want to actually ignore the event. get_irq_regs() will always give us the right interrupted context, so use its result and submit it to perf_exclude_context() that knows when an event must be ignored. Signed-off-by: Frederic Weisbecker Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Ingo Molnar diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 9efdfe5..095101d 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -4164,15 +4164,8 @@ static enum hrtimer_restart perf_swevent_hrtimer(struct hrtimer *hrtimer) perf_sample_data_init(&data, 0); data.period = event->hw.last_period; regs = get_irq_regs(); - /* - * In case we exclude kernel IPs or are somehow not in interrupt - * context, provide the next best thing, the user IP. - */ - if ((event->attr.exclude_kernel || !regs) && - !event->attr.exclude_user) - regs = task_pt_regs(current); - if (regs) { + if (regs && !perf_exclude_event(event, regs)) { if (!(event->attr.exclude_idle && current->pid == 0)) if (perf_event_overflow(event, 0, &data, regs)) ret = HRTIMER_NORESTART; -- cgit v0.10.2 From b8f7fb13d2d7ff14818fd1d3edd8b834d38b0217 Mon Sep 17 00:00:00 2001 From: Cliff Wickman Date: Wed, 14 Apr 2010 11:35:46 -0500 Subject: x86, UV: Improve BAU performance and error recovery - increase performance of the interrupt handler - release timed-out software acknowledge resources - recover from continuous-busy status due to a hardware issue - add a 'throttle' to keep a uvhub from sending more than a specified number of broadcasts concurrently (work around the hardware issue) - provide a 'nobau' boot command line option - rename 'pnode' and 'node' to 'uvhub' (the 'node' terminology is ambiguous) - add some new statistics about the scope of broadcasts, retries, the hardware issue and the 'throttle' - split off new function uv_bau_retry_msg() from uv_bau_process_message() per community coding style feedback. - simplify the argument list to uv_bau_process_message(), per community coding style feedback. Signed-off-by: Cliff Wickman Cc: linux-mm@kvack.org Cc: Jack Steiner Cc: Russ Anderson Cc: Mike Travis Cc: "H. Peter Anvin" Cc: Thomas Gleixner LKML-Reference: Signed-off-by: Ingo Molnar diff --git a/arch/x86/include/asm/uv/uv_bau.h b/arch/x86/include/asm/uv/uv_bau.h index b414d2b..aa558ac 100644 --- a/arch/x86/include/asm/uv/uv_bau.h +++ b/arch/x86/include/asm/uv/uv_bau.h @@ -27,13 +27,14 @@ * set 2 is at BASE + 2*512, set 3 at BASE + 3*512, and so on. * * We will use 31 sets, one for sending BAU messages from each of the 32 - * cpu's on the node. + * cpu's on the uvhub. * * TLB shootdown will use the first of the 8 descriptors of each set. * Each of the descriptors is 64 bytes in size (8*64 = 512 bytes in a set). */ #define UV_ITEMS_PER_DESCRIPTOR 8 +#define MAX_BAU_CONCURRENT 3 #define UV_CPUS_PER_ACT_STATUS 32 #define UV_ACT_STATUS_MASK 0x3 #define UV_ACT_STATUS_SIZE 2 @@ -45,6 +46,9 @@ #define UV_PAYLOADQ_PNODE_SHIFT 49 #define UV_PTC_BASENAME "sgi_uv/ptc_statistics" #define uv_physnodeaddr(x) ((__pa((unsigned long)(x)) & uv_mmask)) +#define UV_ENABLE_INTD_SOFT_ACK_MODE_SHIFT 15 +#define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHIFT 16 +#define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD 0x000000000bUL /* * bits in UVH_LB_BAU_SB_ACTIVATION_STATUS_0/1 @@ -55,15 +59,29 @@ #define DESC_STATUS_SOURCE_TIMEOUT 3 /* - * source side thresholds at which message retries print a warning + * source side threshholds at which message retries print a warning */ #define SOURCE_TIMEOUT_LIMIT 20 #define DESTINATION_TIMEOUT_LIMIT 20 /* + * misc. delays, in microseconds + */ +#define THROTTLE_DELAY 10 +#define TIMEOUT_DELAY 10 +#define BIOS_TO 1000 +/* BIOS is assumed to set the destination timeout to 1003520 nanoseconds */ + +/* + * threshholds at which to use IPI to free resources + */ +#define PLUGSB4RESET 100 +#define TIMEOUTSB4RESET 100 + +/* * number of entries in the destination side payload queue */ -#define DEST_Q_SIZE 17 +#define DEST_Q_SIZE 20 /* * number of destination side software ack resources */ @@ -72,9 +90,10 @@ /* * completion statuses for sending a TLB flush message */ -#define FLUSH_RETRY 1 -#define FLUSH_GIVEUP 2 -#define FLUSH_COMPLETE 3 +#define FLUSH_RETRY_PLUGGED 1 +#define FLUSH_RETRY_TIMEOUT 2 +#define FLUSH_GIVEUP 3 +#define FLUSH_COMPLETE 4 /* * Distribution: 32 bytes (256 bits) (bytes 0-0x1f of descriptor) @@ -86,14 +105,14 @@ * 'base_dest_nodeid' field of the header corresponds to the * destination nodeID associated with that specified bit. */ -struct bau_target_nodemask { - unsigned long bits[BITS_TO_LONGS(256)]; +struct bau_target_uvhubmask { + unsigned long bits[BITS_TO_LONGS(UV_DISTRIBUTION_SIZE)]; }; /* - * mask of cpu's on a node + * mask of cpu's on a uvhub * (during initialization we need to check that unsigned long has - * enough bits for max. cpu's per node) + * enough bits for max. cpu's per uvhub) */ struct bau_local_cpumask { unsigned long bits; @@ -135,8 +154,8 @@ struct bau_msg_payload { struct bau_msg_header { unsigned int dest_subnodeid:6; /* must be 0x10, for the LB */ /* bits 5:0 */ - unsigned int base_dest_nodeid:15; /* nasid>>1 (pnode) of */ - /* bits 20:6 */ /* first bit in node_map */ + unsigned int base_dest_nodeid:15; /* nasid (pnode<<1) of */ + /* bits 20:6 */ /* first bit in uvhub map */ unsigned int command:8; /* message type */ /* bits 28:21 */ /* 0x38: SN3net EndPoint Message */ @@ -146,26 +165,38 @@ struct bau_msg_header { unsigned int rsvd_2:9; /* must be zero */ /* bits 40:32 */ /* Suppl_A is 56-41 */ - unsigned int payload_2a:8;/* becomes byte 16 of msg */ - /* bits 48:41 */ /* not currently using */ - unsigned int payload_2b:8;/* becomes byte 17 of msg */ - /* bits 56:49 */ /* not currently using */ + unsigned int sequence:16;/* message sequence number */ + /* bits 56:41 */ /* becomes bytes 16-17 of msg */ /* Address field (96:57) is never used as an address (these are address bits 42:3) */ + unsigned int rsvd_3:1; /* must be zero */ /* bit 57 */ /* address bits 27:4 are payload */ - /* these 24 bits become bytes 12-14 of msg */ + /* these next 24 (58-81) bits become bytes 12-14 of msg */ + + /* bits 65:58 land in byte 12 */ unsigned int replied_to:1;/* sent as 0 by the source to byte 12 */ /* bit 58 */ - - unsigned int payload_1a:5;/* not currently used */ - /* bits 63:59 */ - unsigned int payload_1b:8;/* not currently used */ - /* bits 71:64 */ - unsigned int payload_1c:8;/* not currently used */ - /* bits 79:72 */ - unsigned int payload_1d:2;/* not currently used */ + unsigned int msg_type:3; /* software type of the message*/ + /* bits 61:59 */ + unsigned int canceled:1; /* message canceled, resource to be freed*/ + /* bit 62 */ + unsigned int payload_1a:1;/* not currently used */ + /* bit 63 */ + unsigned int payload_1b:2;/* not currently used */ + /* bits 65:64 */ + + /* bits 73:66 land in byte 13 */ + unsigned int payload_1ca:6;/* not currently used */ + /* bits 71:66 */ + unsigned int payload_1c:2;/* not currently used */ + /* bits 73:72 */ + + /* bits 81:74 land in byte 14 */ + unsigned int payload_1d:6;/* not currently used */ + /* bits 79:74 */ + unsigned int payload_1e:2;/* not currently used */ /* bits 81:80 */ unsigned int rsvd_4:7; /* must be zero */ @@ -178,7 +209,7 @@ struct bau_msg_header { /* bits 95:90 */ unsigned int rsvd_6:5; /* must be zero */ /* bits 100:96 */ - unsigned int int_both:1;/* if 1, interrupt both sockets on the blade */ + unsigned int int_both:1;/* if 1, interrupt both sockets on the uvhub */ /* bit 101*/ unsigned int fairness:3;/* usually zero */ /* bits 104:102 */ @@ -191,13 +222,18 @@ struct bau_msg_header { /* bits 127:107 */ }; +/* see msg_type: */ +#define MSG_NOOP 0 +#define MSG_REGULAR 1 +#define MSG_RETRY 2 + /* * The activation descriptor: * The format of the message to send, plus all accompanying control * Should be 64 bytes */ struct bau_desc { - struct bau_target_nodemask distribution; + struct bau_target_uvhubmask distribution; /* * message template, consisting of header and payload: */ @@ -237,19 +273,25 @@ struct bau_payload_queue_entry { unsigned short acknowledge_count; /* filled in by destination */ /* 16 bits, bytes 10-11 */ - unsigned short replied_to:1; /* sent as 0 by the source */ - /* 1 bit */ - unsigned short unused1:7; /* not currently using */ - /* 7 bits: byte 12) */ + /* these next 3 bytes come from bits 58-81 of the message header */ + unsigned short replied_to:1; /* sent as 0 by the source */ + unsigned short msg_type:3; /* software message type */ + unsigned short canceled:1; /* sent as 0 by the source */ + unsigned short unused1:3; /* not currently using */ + /* byte 12 */ - unsigned char unused2[2]; /* not currently using */ - /* bytes 13-14 */ + unsigned char unused2a; /* not currently using */ + /* byte 13 */ + unsigned char unused2; /* not currently using */ + /* byte 14 */ unsigned char sw_ack_vector; /* filled in by the hardware */ /* byte 15 (bits 127:120) */ - unsigned char unused4[3]; /* not currently using bytes 17-19 */ - /* bytes 17-19 */ + unsigned short sequence; /* message sequence number */ + /* bytes 16-17 */ + unsigned char unused4[2]; /* not currently using bytes 18-19 */ + /* bytes 18-19 */ int number_of_cpus; /* filled in at destination */ /* 32 bits, bytes 20-23 (aligned) */ @@ -259,63 +301,93 @@ struct bau_payload_queue_entry { }; /* - * one for every slot in the destination payload queue - */ -struct bau_msg_status { - struct bau_local_cpumask seen_by; /* map of cpu's */ -}; - -/* - * one for every slot in the destination software ack resources - */ -struct bau_sw_ack_status { - struct bau_payload_queue_entry *msg; /* associated message */ - int watcher; /* cpu monitoring, or -1 */ -}; - -/* - * one on every node and per-cpu; to locate the software tables + * one per-cpu; to locate the software tables */ struct bau_control { struct bau_desc *descriptor_base; - struct bau_payload_queue_entry *bau_msg_head; struct bau_payload_queue_entry *va_queue_first; struct bau_payload_queue_entry *va_queue_last; - struct bau_msg_status *msg_statuses; - int *watching; /* pointer to array */ + struct bau_payload_queue_entry *bau_msg_head; + struct bau_control *uvhub_master; + struct bau_control *socket_master; + unsigned long timeout_interval; + atomic_t active_descriptor_count; + int max_concurrent; + int max_concurrent_constant; + int retry_message_scans; + int plugged_tries; + int timeout_tries; + int ipi_attempts; + int conseccompletes; + short cpu; + short uvhub_cpu; + short uvhub; + short cpus_in_socket; + short cpus_in_uvhub; + unsigned short message_number; + unsigned short uvhub_quiesce; + short socket_acknowledge_count[DEST_Q_SIZE]; + cycles_t send_message; + spinlock_t masks_lock; + spinlock_t uvhub_lock; + spinlock_t queue_lock; }; /* * This structure is allocated per_cpu for UV TLB shootdown statistics. */ struct ptc_stats { - unsigned long ptc_i; /* number of IPI-style flushes */ - unsigned long requestor; /* number of nodes this cpu sent to */ - unsigned long requestee; /* times cpu was remotely requested */ - unsigned long alltlb; /* times all tlb's on this cpu were flushed */ - unsigned long onetlb; /* times just one tlb on this cpu was flushed */ - unsigned long s_retry; /* retries on source side timeouts */ - unsigned long d_retry; /* retries on destination side timeouts */ - unsigned long sflush; /* cycles spent in uv_flush_tlb_others */ - unsigned long dflush; /* cycles spent on destination side */ - unsigned long retriesok; /* successes on retries */ - unsigned long nomsg; /* interrupts with no message */ - unsigned long multmsg; /* interrupts with multiple messages */ - unsigned long ntargeted;/* nodes targeted */ + /* sender statistics */ + unsigned long s_giveup; /* number of fall backs to IPI-style flushes */ + unsigned long s_requestor; /* number of shootdown requests */ + unsigned long s_stimeout; /* source side timeouts */ + unsigned long s_dtimeout; /* destination side timeouts */ + unsigned long s_time; /* time spent in sending side */ + unsigned long s_retriesok; /* successful retries */ + unsigned long s_ntargcpu; /* number of cpus targeted */ + unsigned long s_ntarguvhub; /* number of uvhubs targeted */ + unsigned long s_ntarguvhub16; /* number of times >= 16 target hubs */ + unsigned long s_ntarguvhub8; /* number of times >= 8 target hubs */ + unsigned long s_ntarguvhub4; /* number of times >= 4 target hubs */ + unsigned long s_ntarguvhub2; /* number of times >= 2 target hubs */ + unsigned long s_ntarguvhub1; /* number of times == 1 target hub */ + unsigned long s_resets_plug; /* ipi-style resets from plug state */ + unsigned long s_resets_timeout; /* ipi-style resets from timeouts */ + unsigned long s_busy; /* status stayed busy past s/w timer */ + unsigned long s_throttles; /* waits in throttle */ + unsigned long s_retry_messages; /* retry broadcasts */ + /* destination statistics */ + unsigned long d_alltlb; /* times all tlb's on this cpu were flushed */ + unsigned long d_onetlb; /* times just one tlb on this cpu was flushed */ + unsigned long d_multmsg; /* interrupts with multiple messages */ + unsigned long d_nomsg; /* interrupts with no message */ + unsigned long d_time; /* time spent on destination side */ + unsigned long d_requestee; /* number of messages processed */ + unsigned long d_retries; /* number of retry messages processed */ + unsigned long d_canceled; /* number of messages canceled by retries */ + unsigned long d_nocanceled; /* retries that found nothing to cancel */ + unsigned long d_resets; /* number of ipi-style requests processed */ + unsigned long d_rcanceled; /* number of messages canceled by resets */ }; -static inline int bau_node_isset(int node, struct bau_target_nodemask *dstp) +static inline int bau_uvhub_isset(int uvhub, struct bau_target_uvhubmask *dstp) { - return constant_test_bit(node, &dstp->bits[0]); + return constant_test_bit(uvhub, &dstp->bits[0]); } -static inline void bau_node_set(int node, struct bau_target_nodemask *dstp) +static inline void bau_uvhub_set(int uvhub, struct bau_target_uvhubmask *dstp) { - __set_bit(node, &dstp->bits[0]); + __set_bit(uvhub, &dstp->bits[0]); } -static inline void bau_nodes_clear(struct bau_target_nodemask *dstp, int nbits) +static inline void bau_uvhubs_clear(struct bau_target_uvhubmask *dstp, + int nbits) { bitmap_zero(&dstp->bits[0], nbits); } +static inline int bau_uvhub_weight(struct bau_target_uvhubmask *dstp) +{ + return bitmap_weight((unsigned long *)&dstp->bits[0], + UV_DISTRIBUTION_SIZE); +} static inline void bau_cpubits_clear(struct bau_local_cpumask *dstp, int nbits) { @@ -328,4 +400,35 @@ static inline void bau_cpubits_clear(struct bau_local_cpumask *dstp, int nbits) extern void uv_bau_message_intr1(void); extern void uv_bau_timeout_intr1(void); +struct atomic_short { + short counter; +}; + +/** + * atomic_read_short - read a short atomic variable + * @v: pointer of type atomic_short + * + * Atomically reads the value of @v. + */ +static inline int atomic_read_short(const struct atomic_short *v) +{ + return v->counter; +} + +/** + * atomic_add_short_return - add and return a short int + * @i: short value to add + * @v: pointer of type atomic_short + * + * Atomically adds @i to @v and returns @i + @v + */ +static inline int atomic_add_short_return(short i, struct atomic_short *v) +{ + short __i = i; + asm volatile(LOCK_PREFIX "xaddw %0, %1" + : "+r" (i), "+m" (v->counter) + : : "memory"); + return i + __i; +} + #endif /* _ASM_X86_UV_UV_BAU_H */ diff --git a/arch/x86/kernel/tlb_uv.c b/arch/x86/kernel/tlb_uv.c index ef68ba4..414f7c4f 100644 --- a/arch/x86/kernel/tlb_uv.c +++ b/arch/x86/kernel/tlb_uv.c @@ -1,7 +1,7 @@ /* * SGI UltraViolet TLB flush routines. * - * (c) 2008 Cliff Wickman , SGI. + * (c) 2008-2010 Cliff Wickman , SGI. * * This code is released under the GNU General Public License version 2 or * later. @@ -19,44 +19,67 @@ #include #include #include +#include + +struct msg_desc { + struct bau_payload_queue_entry *msg; + int msg_slot; + int sw_ack_slot; + struct bau_payload_queue_entry *va_queue_first; + struct bau_payload_queue_entry *va_queue_last; +}; #define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD 0x000000000bUL -static struct bau_control **uv_bau_table_bases __read_mostly; -static int uv_bau_retry_limit __read_mostly; +static int uv_bau_max_concurrent __read_mostly; -/* base pnode in this partition */ -static int uv_partition_base_pnode __read_mostly; +static int nobau; +static int __init setup_nobau(char *arg) +{ + nobau = 1; + return 0; +} +early_param("nobau", setup_nobau); -static unsigned long uv_mmask __read_mostly; +/* base pnode in this partition */ +static int uv_partition_base_pnode __read_mostly; +/* position of pnode (which is nasid>>1): */ +static int uv_nshift __read_mostly; +static unsigned long uv_mmask __read_mostly; static DEFINE_PER_CPU(struct ptc_stats, ptcstats); static DEFINE_PER_CPU(struct bau_control, bau_control); +static DEFINE_PER_CPU(cpumask_var_t, uv_flush_tlb_mask); + +struct reset_args { + int sender; +}; /* - * Determine the first node on a blade. + * Determine the first node on a uvhub. 'Nodes' are used for kernel + * memory allocation. */ -static int __init blade_to_first_node(int blade) +static int __init uvhub_to_first_node(int uvhub) { int node, b; for_each_online_node(node) { b = uv_node_to_blade_id(node); - if (blade == b) + if (uvhub == b) return node; } - return -1; /* shouldn't happen */ + return -1; } /* - * Determine the apicid of the first cpu on a blade. + * Determine the apicid of the first cpu on a uvhub. */ -static int __init blade_to_first_apicid(int blade) +static int __init uvhub_to_first_apicid(int uvhub) { int cpu; for_each_present_cpu(cpu) - if (blade == uv_cpu_to_blade_id(cpu)) + if (uvhub == uv_cpu_to_blade_id(cpu)) return per_cpu(x86_cpu_to_apicid, cpu); return -1; } @@ -69,195 +92,459 @@ static int __init blade_to_first_apicid(int blade) * clear of the Timeout bit (as well) will free the resource. No reply will * be sent (the hardware will only do one reply per message). */ -static void uv_reply_to_message(int resource, - struct bau_payload_queue_entry *msg, - struct bau_msg_status *msp) +static inline void uv_reply_to_message(struct msg_desc *mdp, + struct bau_control *bcp) { unsigned long dw; + struct bau_payload_queue_entry *msg; - dw = (1 << (resource + UV_SW_ACK_NPENDING)) | (1 << resource); + msg = mdp->msg; + if (!msg->canceled) { + dw = (msg->sw_ack_vector << UV_SW_ACK_NPENDING) | + msg->sw_ack_vector; + uv_write_local_mmr( + UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS, dw); + } msg->replied_to = 1; msg->sw_ack_vector = 0; - if (msp) - msp->seen_by.bits = 0; - uv_write_local_mmr(UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS, dw); } /* - * Do all the things a cpu should do for a TLB shootdown message. - * Other cpu's may come here at the same time for this message. + * Process the receipt of a RETRY message */ -static void uv_bau_process_message(struct bau_payload_queue_entry *msg, - int msg_slot, int sw_ack_slot) +static inline void uv_bau_process_retry_msg(struct msg_desc *mdp, + struct bau_control *bcp) { - unsigned long this_cpu_mask; - struct bau_msg_status *msp; - int cpu; + int i; + int cancel_count = 0; + int slot2; + unsigned long msg_res; + unsigned long mmr = 0; + struct bau_payload_queue_entry *msg; + struct bau_payload_queue_entry *msg2; + struct ptc_stats *stat; - msp = __get_cpu_var(bau_control).msg_statuses + msg_slot; - cpu = uv_blade_processor_id(); - msg->number_of_cpus = - uv_blade_nr_online_cpus(uv_node_to_blade_id(numa_node_id())); - this_cpu_mask = 1UL << cpu; - if (msp->seen_by.bits & this_cpu_mask) - return; - atomic_or_long(&msp->seen_by.bits, this_cpu_mask); + msg = mdp->msg; + stat = &per_cpu(ptcstats, bcp->cpu); + stat->d_retries++; + /* + * cancel any message from msg+1 to the retry itself + */ + for (msg2 = msg+1, i = 0; i < DEST_Q_SIZE; msg2++, i++) { + if (msg2 > mdp->va_queue_last) + msg2 = mdp->va_queue_first; + if (msg2 == msg) + break; + + /* same conditions for cancellation as uv_do_reset */ + if ((msg2->replied_to == 0) && (msg2->canceled == 0) && + (msg2->sw_ack_vector) && ((msg2->sw_ack_vector & + msg->sw_ack_vector) == 0) && + (msg2->sending_cpu == msg->sending_cpu) && + (msg2->msg_type != MSG_NOOP)) { + slot2 = msg2 - mdp->va_queue_first; + mmr = uv_read_local_mmr + (UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE); + msg_res = ((msg2->sw_ack_vector << 8) | + msg2->sw_ack_vector); + /* + * This is a message retry; clear the resources held + * by the previous message only if they timed out. + * If it has not timed out we have an unexpected + * situation to report. + */ + if (mmr & (msg_res << 8)) { + /* + * is the resource timed out? + * make everyone ignore the cancelled message. + */ + msg2->canceled = 1; + stat->d_canceled++; + cancel_count++; + uv_write_local_mmr( + UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS, + (msg_res << 8) | msg_res); + } else + printk(KERN_INFO "note bau retry: no effect\n"); + } + } + if (!cancel_count) + stat->d_nocanceled++; +} - if (msg->replied_to == 1) - return; +/* + * Do all the things a cpu should do for a TLB shootdown message. + * Other cpu's may come here at the same time for this message. + */ +static void uv_bau_process_message(struct msg_desc *mdp, + struct bau_control *bcp) +{ + int msg_ack_count; + short socket_ack_count = 0; + struct ptc_stats *stat; + struct bau_payload_queue_entry *msg; + struct bau_control *smaster = bcp->socket_master; + /* + * This must be a normal message, or retry of a normal message + */ + msg = mdp->msg; + stat = &per_cpu(ptcstats, bcp->cpu); if (msg->address == TLB_FLUSH_ALL) { local_flush_tlb(); - __get_cpu_var(ptcstats).alltlb++; + stat->d_alltlb++; } else { __flush_tlb_one(msg->address); - __get_cpu_var(ptcstats).onetlb++; + stat->d_onetlb++; } + stat->d_requestee++; + + /* + * One cpu on each uvhub has the additional job on a RETRY + * of releasing the resource held by the message that is + * being retried. That message is identified by sending + * cpu number. + */ + if (msg->msg_type == MSG_RETRY && bcp == bcp->uvhub_master) + uv_bau_process_retry_msg(mdp, bcp); - __get_cpu_var(ptcstats).requestee++; + /* + * This is a sw_ack message, so we have to reply to it. + * Count each responding cpu on the socket. This avoids + * pinging the count's cache line back and forth between + * the sockets. + */ + socket_ack_count = atomic_add_short_return(1, (struct atomic_short *) + &smaster->socket_acknowledge_count[mdp->msg_slot]); + if (socket_ack_count == bcp->cpus_in_socket) { + /* + * Both sockets dump their completed count total into + * the message's count. + */ + smaster->socket_acknowledge_count[mdp->msg_slot] = 0; + msg_ack_count = atomic_add_short_return(socket_ack_count, + (struct atomic_short *)&msg->acknowledge_count); + + if (msg_ack_count == bcp->cpus_in_uvhub) { + /* + * All cpus in uvhub saw it; reply + */ + uv_reply_to_message(mdp, bcp); + } + } - atomic_inc_short(&msg->acknowledge_count); - if (msg->number_of_cpus == msg->acknowledge_count) - uv_reply_to_message(sw_ack_slot, msg, msp); + return; } /* - * Examine the payload queue on one distribution node to see - * which messages have not been seen, and which cpu(s) have not seen them. + * Determine the first cpu on a uvhub. + */ +static int uvhub_to_first_cpu(int uvhub) +{ + int cpu; + for_each_present_cpu(cpu) + if (uvhub == uv_cpu_to_blade_id(cpu)) + return cpu; + return -1; +} + +/* + * Last resort when we get a large number of destination timeouts is + * to clear resources held by a given cpu. + * Do this with IPI so that all messages in the BAU message queue + * can be identified by their nonzero sw_ack_vector field. * - * Returns the number of cpu's that have not responded. + * This is entered for a single cpu on the uvhub. + * The sender want's this uvhub to free a specific message's + * sw_ack resources. */ -static int uv_examine_destination(struct bau_control *bau_tablesp, int sender) +static void +uv_do_reset(void *ptr) { - struct bau_payload_queue_entry *msg; - struct bau_msg_status *msp; - int count = 0; int i; - int j; + int slot; + int count = 0; + unsigned long mmr; + unsigned long msg_res; + struct bau_control *bcp; + struct reset_args *rap; + struct bau_payload_queue_entry *msg; + struct ptc_stats *stat; - for (msg = bau_tablesp->va_queue_first, i = 0; i < DEST_Q_SIZE; - msg++, i++) { - if ((msg->sending_cpu == sender) && (!msg->replied_to)) { - msp = bau_tablesp->msg_statuses + i; - printk(KERN_DEBUG - "blade %d: address:%#lx %d of %d, not cpu(s): ", - i, msg->address, msg->acknowledge_count, - msg->number_of_cpus); - for (j = 0; j < msg->number_of_cpus; j++) { - if (!((1L << j) & msp->seen_by.bits)) { - count++; - printk("%d ", j); - } + bcp = &per_cpu(bau_control, smp_processor_id()); + rap = (struct reset_args *)ptr; + stat = &per_cpu(ptcstats, bcp->cpu); + stat->d_resets++; + + /* + * We're looking for the given sender, and + * will free its sw_ack resource. + * If all cpu's finally responded after the timeout, its + * message 'replied_to' was set. + */ + for (msg = bcp->va_queue_first, i = 0; i < DEST_Q_SIZE; msg++, i++) { + /* uv_do_reset: same conditions for cancellation as + uv_bau_process_retry_msg() */ + if ((msg->replied_to == 0) && + (msg->canceled == 0) && + (msg->sending_cpu == rap->sender) && + (msg->sw_ack_vector) && + (msg->msg_type != MSG_NOOP)) { + /* + * make everyone else ignore this message + */ + msg->canceled = 1; + slot = msg - bcp->va_queue_first; + count++; + /* + * only reset the resource if it is still pending + */ + mmr = uv_read_local_mmr + (UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE); + msg_res = ((msg->sw_ack_vector << 8) | + msg->sw_ack_vector); + if (mmr & msg_res) { + stat->d_rcanceled++; + uv_write_local_mmr( + UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS, + msg_res); } - printk("\n"); } } - return count; + return; } /* - * Examine the payload queue on all the distribution nodes to see - * which messages have not been seen, and which cpu(s) have not seen them. - * - * Returns the number of cpu's that have not responded. + * Use IPI to get all target uvhubs to release resources held by + * a given sending cpu number. */ -static int uv_examine_destinations(struct bau_target_nodemask *distribution) +static void uv_reset_with_ipi(struct bau_target_uvhubmask *distribution, + int sender) { - int sender; - int i; - int count = 0; + int uvhub; + int cpu; + cpumask_t mask; + struct reset_args reset_args; - sender = smp_processor_id(); - for (i = 0; i < sizeof(struct bau_target_nodemask) * BITSPERBYTE; i++) { - if (!bau_node_isset(i, distribution)) + reset_args.sender = sender; + + cpus_clear(mask); + /* find a single cpu for each uvhub in this distribution mask */ + for (uvhub = 0; + uvhub < sizeof(struct bau_target_uvhubmask) * BITSPERBYTE; + uvhub++) { + if (!bau_uvhub_isset(uvhub, distribution)) continue; - count += uv_examine_destination(uv_bau_table_bases[i], sender); + /* find a cpu for this uvhub */ + cpu = uvhub_to_first_cpu(uvhub); + cpu_set(cpu, mask); } - return count; + /* IPI all cpus; Preemption is already disabled */ + smp_call_function_many(&mask, uv_do_reset, (void *)&reset_args, 1); + return; +} + +static inline unsigned long +cycles_2_us(unsigned long long cyc) +{ + unsigned long long ns; + unsigned long us; + ns = (cyc * per_cpu(cyc2ns, smp_processor_id())) + >> CYC2NS_SCALE_FACTOR; + us = ns / 1000; + return us; } /* - * wait for completion of a broadcast message - * - * return COMPLETE, RETRY or GIVEUP + * wait for all cpus on this hub to finish their sends and go quiet + * leaves uvhub_quiesce set so that no new broadcasts are started by + * bau_flush_send_and_wait() + */ +static inline void +quiesce_local_uvhub(struct bau_control *hmaster) +{ + atomic_add_short_return(1, (struct atomic_short *) + &hmaster->uvhub_quiesce); +} + +/* + * mark this quiet-requestor as done + */ +static inline void +end_uvhub_quiesce(struct bau_control *hmaster) +{ + atomic_add_short_return(-1, (struct atomic_short *) + &hmaster->uvhub_quiesce); +} + +/* + * Wait for completion of a broadcast software ack message + * return COMPLETE, RETRY(PLUGGED or TIMEOUT) or GIVEUP */ static int uv_wait_completion(struct bau_desc *bau_desc, - unsigned long mmr_offset, int right_shift) + unsigned long mmr_offset, int right_shift, int this_cpu, + struct bau_control *bcp, struct bau_control *smaster, long try) { - int exams = 0; - long destination_timeouts = 0; - long source_timeouts = 0; + int relaxes = 0; unsigned long descriptor_status; + unsigned long mmr; + unsigned long mask; + cycles_t ttime; + cycles_t timeout_time; + struct ptc_stats *stat = &per_cpu(ptcstats, this_cpu); + struct bau_control *hmaster; + hmaster = bcp->uvhub_master; + timeout_time = get_cycles() + bcp->timeout_interval; + + /* spin on the status MMR, waiting for it to go idle */ while ((descriptor_status = (((unsigned long) uv_read_local_mmr(mmr_offset) >> right_shift) & UV_ACT_STATUS_MASK)) != DESC_STATUS_IDLE) { - if (descriptor_status == DESC_STATUS_SOURCE_TIMEOUT) { - source_timeouts++; - if (source_timeouts > SOURCE_TIMEOUT_LIMIT) - source_timeouts = 0; - __get_cpu_var(ptcstats).s_retry++; - return FLUSH_RETRY; - } /* - * spin here looking for progress at the destinations + * Our software ack messages may be blocked because there are + * no swack resources available. As long as none of them + * has timed out hardware will NACK our message and its + * state will stay IDLE. */ - if (descriptor_status == DESC_STATUS_DESTINATION_TIMEOUT) { - destination_timeouts++; - if (destination_timeouts > DESTINATION_TIMEOUT_LIMIT) { - /* - * returns number of cpus not responding - */ - if (uv_examine_destinations - (&bau_desc->distribution) == 0) { - __get_cpu_var(ptcstats).d_retry++; - return FLUSH_RETRY; - } - exams++; - if (exams >= uv_bau_retry_limit) { - printk(KERN_DEBUG - "uv_flush_tlb_others"); - printk("giving up on cpu %d\n", - smp_processor_id()); + if (descriptor_status == DESC_STATUS_SOURCE_TIMEOUT) { + stat->s_stimeout++; + return FLUSH_GIVEUP; + } else if (descriptor_status == + DESC_STATUS_DESTINATION_TIMEOUT) { + stat->s_dtimeout++; + ttime = get_cycles(); + + /* + * Our retries may be blocked by all destination + * swack resources being consumed, and a timeout + * pending. In that case hardware returns the + * ERROR that looks like a destination timeout. + */ + if (cycles_2_us(ttime - bcp->send_message) < BIOS_TO) { + bcp->conseccompletes = 0; + return FLUSH_RETRY_PLUGGED; + } + + bcp->conseccompletes = 0; + return FLUSH_RETRY_TIMEOUT; + } else { + /* + * descriptor_status is still BUSY + */ + cpu_relax(); + relaxes++; + if (relaxes >= 10000) { + relaxes = 0; + if (get_cycles() > timeout_time) { + quiesce_local_uvhub(hmaster); + + /* single-thread the register change */ + spin_lock(&hmaster->masks_lock); + mmr = uv_read_local_mmr(mmr_offset); + mask = 0UL; + mask |= (3UL < right_shift); + mask = ~mask; + mmr &= mask; + uv_write_local_mmr(mmr_offset, mmr); + spin_unlock(&hmaster->masks_lock); + end_uvhub_quiesce(hmaster); + stat->s_busy++; return FLUSH_GIVEUP; } - /* - * delays can hang the simulator - udelay(1000); - */ - destination_timeouts = 0; } } - cpu_relax(); } + bcp->conseccompletes++; return FLUSH_COMPLETE; } +static inline cycles_t +sec_2_cycles(unsigned long sec) +{ + unsigned long ns; + cycles_t cyc; + + ns = sec * 1000000000; + cyc = (ns << CYC2NS_SCALE_FACTOR)/(per_cpu(cyc2ns, smp_processor_id())); + return cyc; +} + +/* + * conditionally add 1 to *v, unless *v is >= u + * return 0 if we cannot add 1 to *v because it is >= u + * return 1 if we can add 1 to *v because it is < u + * the add is atomic + * + * This is close to atomic_add_unless(), but this allows the 'u' value + * to be lowered below the current 'v'. atomic_add_unless can only stop + * on equal. + */ +static inline int atomic_inc_unless_ge(spinlock_t *lock, atomic_t *v, int u) +{ + spin_lock(lock); + if (atomic_read(v) >= u) { + spin_unlock(lock); + return 0; + } + atomic_inc(v); + spin_unlock(lock); + return 1; +} + /** * uv_flush_send_and_wait * - * Send a broadcast and wait for a broadcast message to complete. + * Send a broadcast and wait for it to complete. * - * The flush_mask contains the cpus the broadcast was sent to. + * The flush_mask contains the cpus the broadcast is to be sent to, plus + * cpus that are on the local uvhub. * - * Returns NULL if all remote flushing was done. The mask is zeroed. + * Returns NULL if all flushing represented in the mask was done. The mask + * is zeroed. * Returns @flush_mask if some remote flushing remains to be done. The - * mask will have some bits still set. + * mask will have some bits still set, representing any cpus on the local + * uvhub (not current cpu) and any on remote uvhubs if the broadcast failed. */ -const struct cpumask *uv_flush_send_and_wait(int cpu, int this_pnode, - struct bau_desc *bau_desc, - struct cpumask *flush_mask) +const struct cpumask *uv_flush_send_and_wait(struct bau_desc *bau_desc, + struct cpumask *flush_mask, + struct bau_control *bcp) { - int completion_status = 0; int right_shift; - int tries = 0; - int pnode; + int uvhub; int bit; + int completion_status = 0; + int seq_number = 0; + long try = 0; + int cpu = bcp->uvhub_cpu; + int this_cpu = bcp->cpu; + int this_uvhub = bcp->uvhub; unsigned long mmr_offset; unsigned long index; cycles_t time1; cycles_t time2; + struct ptc_stats *stat = &per_cpu(ptcstats, bcp->cpu); + struct bau_control *smaster = bcp->socket_master; + struct bau_control *hmaster = bcp->uvhub_master; + + /* + * Spin here while there are hmaster->max_concurrent or more active + * descriptors. This is the per-uvhub 'throttle'. + */ + if (!atomic_inc_unless_ge(&hmaster->uvhub_lock, + &hmaster->active_descriptor_count, + hmaster->max_concurrent)) { + stat->s_throttles++; + do { + cpu_relax(); + } while (!atomic_inc_unless_ge(&hmaster->uvhub_lock, + &hmaster->active_descriptor_count, + hmaster->max_concurrent)); + } + + while (hmaster->uvhub_quiesce) + cpu_relax(); if (cpu < UV_CPUS_PER_ACT_STATUS) { mmr_offset = UVH_LB_BAU_SB_ACTIVATION_STATUS_0; @@ -269,24 +556,108 @@ const struct cpumask *uv_flush_send_and_wait(int cpu, int this_pnode, } time1 = get_cycles(); do { - tries++; + /* + * Every message from any given cpu gets a unique message + * sequence number. But retries use that same number. + * Our message may have timed out at the destination because + * all sw-ack resources are in use and there is a timeout + * pending there. In that case, our last send never got + * placed into the queue and we need to persist until it + * does. + * + * Make any retry a type MSG_RETRY so that the destination will + * free any resource held by a previous message from this cpu. + */ + if (try == 0) { + /* use message type set by the caller the first time */ + seq_number = bcp->message_number++; + } else { + /* use RETRY type on all the rest; same sequence */ + bau_desc->header.msg_type = MSG_RETRY; + stat->s_retry_messages++; + } + bau_desc->header.sequence = seq_number; index = (1UL << UVH_LB_BAU_SB_ACTIVATION_CONTROL_PUSH_SHFT) | - cpu; + bcp->uvhub_cpu; + bcp->send_message = get_cycles(); + uv_write_local_mmr(UVH_LB_BAU_SB_ACTIVATION_CONTROL, index); + + try++; completion_status = uv_wait_completion(bau_desc, mmr_offset, - right_shift); - } while (completion_status == FLUSH_RETRY); + right_shift, this_cpu, bcp, smaster, try); + + if (completion_status == FLUSH_RETRY_PLUGGED) { + /* + * Our retries may be blocked by all destination swack + * resources being consumed, and a timeout pending. In + * that case hardware immediately returns the ERROR + * that looks like a destination timeout. + */ + udelay(TIMEOUT_DELAY); + bcp->plugged_tries++; + if (bcp->plugged_tries >= PLUGSB4RESET) { + bcp->plugged_tries = 0; + quiesce_local_uvhub(hmaster); + spin_lock(&hmaster->queue_lock); + uv_reset_with_ipi(&bau_desc->distribution, + this_cpu); + spin_unlock(&hmaster->queue_lock); + end_uvhub_quiesce(hmaster); + bcp->ipi_attempts++; + stat->s_resets_plug++; + } + } else if (completion_status == FLUSH_RETRY_TIMEOUT) { + hmaster->max_concurrent = 1; + bcp->timeout_tries++; + udelay(TIMEOUT_DELAY); + if (bcp->timeout_tries >= TIMEOUTSB4RESET) { + bcp->timeout_tries = 0; + quiesce_local_uvhub(hmaster); + spin_lock(&hmaster->queue_lock); + uv_reset_with_ipi(&bau_desc->distribution, + this_cpu); + spin_unlock(&hmaster->queue_lock); + end_uvhub_quiesce(hmaster); + bcp->ipi_attempts++; + stat->s_resets_timeout++; + } + } + if (bcp->ipi_attempts >= 3) { + bcp->ipi_attempts = 0; + completion_status = FLUSH_GIVEUP; + break; + } + cpu_relax(); + } while ((completion_status == FLUSH_RETRY_PLUGGED) || + (completion_status == FLUSH_RETRY_TIMEOUT)); time2 = get_cycles(); - __get_cpu_var(ptcstats).sflush += (time2 - time1); - if (tries > 1) - __get_cpu_var(ptcstats).retriesok++; - if (completion_status == FLUSH_GIVEUP) { + if ((completion_status == FLUSH_COMPLETE) && (bcp->conseccompletes > 5) + && (hmaster->max_concurrent < hmaster->max_concurrent_constant)) + hmaster->max_concurrent++; + + /* + * hold any cpu not timing out here; no other cpu currently held by + * the 'throttle' should enter the activation code + */ + while (hmaster->uvhub_quiesce) + cpu_relax(); + atomic_dec(&hmaster->active_descriptor_count); + + /* guard against cycles wrap */ + if (time2 > time1) + stat->s_time += (time2 - time1); + else + stat->s_requestor--; /* don't count this one */ + if (completion_status == FLUSH_COMPLETE && try > 1) + stat->s_retriesok++; + else if (completion_status == FLUSH_GIVEUP) { /* * Cause the caller to do an IPI-style TLB shootdown on - * the cpu's, all of which are still in the mask. + * the target cpu's, all of which are still in the mask. */ - __get_cpu_var(ptcstats).ptc_i++; + stat->s_giveup++; return flush_mask; } @@ -295,18 +666,17 @@ const struct cpumask *uv_flush_send_and_wait(int cpu, int this_pnode, * use the IPI method of shootdown on them. */ for_each_cpu(bit, flush_mask) { - pnode = uv_cpu_to_pnode(bit); - if (pnode == this_pnode) + uvhub = uv_cpu_to_blade_id(bit); + if (uvhub == this_uvhub) continue; cpumask_clear_cpu(bit, flush_mask); } if (!cpumask_empty(flush_mask)) return flush_mask; + return NULL; } -static DEFINE_PER_CPU(cpumask_var_t, uv_flush_tlb_mask); - /** * uv_flush_tlb_others - globally purge translation cache of a virtual * address or all TLB's @@ -323,8 +693,8 @@ static DEFINE_PER_CPU(cpumask_var_t, uv_flush_tlb_mask); * The caller has derived the cpumask from the mm_struct. This function * is called only if there are bits set in the mask. (e.g. flush_tlb_page()) * - * The cpumask is converted into a nodemask of the nodes containing - * the cpus. + * The cpumask is converted into a uvhubmask of the uvhubs containing + * those cpus. * * Note that this function should be called with preemption disabled. * @@ -336,52 +706,82 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, struct mm_struct *mm, unsigned long va, unsigned int cpu) { - struct cpumask *flush_mask = __get_cpu_var(uv_flush_tlb_mask); - int i; - int bit; - int pnode; - int uv_cpu; - int this_pnode; + int remotes; + int tcpu; + int uvhub; int locals = 0; struct bau_desc *bau_desc; + struct cpumask *flush_mask; + struct ptc_stats *stat; + struct bau_control *bcp; - cpumask_andnot(flush_mask, cpumask, cpumask_of(cpu)); + if (nobau) + return cpumask; - uv_cpu = uv_blade_processor_id(); - this_pnode = uv_hub_info->pnode; - bau_desc = __get_cpu_var(bau_control).descriptor_base; - bau_desc += UV_ITEMS_PER_DESCRIPTOR * uv_cpu; + bcp = &per_cpu(bau_control, cpu); + /* + * Each sending cpu has a per-cpu mask which it fills from the caller's + * cpu mask. Only remote cpus are converted to uvhubs and copied. + */ + flush_mask = (struct cpumask *)per_cpu(uv_flush_tlb_mask, cpu); + /* + * copy cpumask to flush_mask, removing current cpu + * (current cpu should already have been flushed by the caller and + * should never be returned if we return flush_mask) + */ + cpumask_andnot(flush_mask, cpumask, cpumask_of(cpu)); + if (cpu_isset(cpu, *cpumask)) + locals++; /* current cpu was targeted */ - bau_nodes_clear(&bau_desc->distribution, UV_DISTRIBUTION_SIZE); + bau_desc = bcp->descriptor_base; + bau_desc += UV_ITEMS_PER_DESCRIPTOR * bcp->uvhub_cpu; - i = 0; - for_each_cpu(bit, flush_mask) { - pnode = uv_cpu_to_pnode(bit); - BUG_ON(pnode > (UV_DISTRIBUTION_SIZE - 1)); - if (pnode == this_pnode) { + bau_uvhubs_clear(&bau_desc->distribution, UV_DISTRIBUTION_SIZE); + remotes = 0; + for_each_cpu(tcpu, flush_mask) { + uvhub = uv_cpu_to_blade_id(tcpu); + if (uvhub == bcp->uvhub) { locals++; continue; } - bau_node_set(pnode - uv_partition_base_pnode, - &bau_desc->distribution); - i++; + bau_uvhub_set(uvhub, &bau_desc->distribution); + remotes++; } - if (i == 0) { + if (remotes == 0) { /* - * no off_node flushing; return status for local node + * No off_hub flushing; return status for local hub. + * Return the caller's mask if all were local (the current + * cpu may be in that mask). */ if (locals) - return flush_mask; + return cpumask; else return NULL; } - __get_cpu_var(ptcstats).requestor++; - __get_cpu_var(ptcstats).ntargeted += i; + stat = &per_cpu(ptcstats, cpu); + stat->s_requestor++; + stat->s_ntargcpu += remotes; + remotes = bau_uvhub_weight(&bau_desc->distribution); + stat->s_ntarguvhub += remotes; + if (remotes >= 16) + stat->s_ntarguvhub16++; + else if (remotes >= 8) + stat->s_ntarguvhub8++; + else if (remotes >= 4) + stat->s_ntarguvhub4++; + else if (remotes >= 2) + stat->s_ntarguvhub2++; + else + stat->s_ntarguvhub1++; bau_desc->payload.address = va; bau_desc->payload.sending_cpu = cpu; - return uv_flush_send_and_wait(uv_cpu, this_pnode, bau_desc, flush_mask); + /* + * uv_flush_send_and_wait returns null if all cpu's were messaged, or + * the adjusted flush_mask if any cpu's were not messaged. + */ + return uv_flush_send_and_wait(bau_desc, flush_mask, bcp); } /* @@ -390,87 +790,70 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask, * * We received a broadcast assist message. * - * Interrupts may have been disabled; this interrupt could represent + * Interrupts are disabled; this interrupt could represent * the receipt of several messages. * - * All cores/threads on this node get this interrupt. - * The last one to see it does the s/w ack. + * All cores/threads on this hub get this interrupt. + * The last one to see it does the software ack. * (the resource will not be freed until noninterruptable cpus see this - * interrupt; hardware will timeout the s/w ack and reply ERROR) + * interrupt; hardware may timeout the s/w ack and reply ERROR) */ void uv_bau_message_interrupt(struct pt_regs *regs) { - struct bau_payload_queue_entry *va_queue_first; - struct bau_payload_queue_entry *va_queue_last; - struct bau_payload_queue_entry *msg; - struct pt_regs *old_regs = set_irq_regs(regs); - cycles_t time1; - cycles_t time2; - int msg_slot; - int sw_ack_slot; - int fw; int count = 0; - unsigned long local_pnode; - - ack_APIC_irq(); - exit_idle(); - irq_enter(); - - time1 = get_cycles(); - - local_pnode = uv_blade_to_pnode(uv_numa_blade_id()); - - va_queue_first = __get_cpu_var(bau_control).va_queue_first; - va_queue_last = __get_cpu_var(bau_control).va_queue_last; - - msg = __get_cpu_var(bau_control).bau_msg_head; + cycles_t time_start; + struct bau_payload_queue_entry *msg; + struct bau_control *bcp; + struct ptc_stats *stat; + struct msg_desc msgdesc; + + time_start = get_cycles(); + bcp = &per_cpu(bau_control, smp_processor_id()); + stat = &per_cpu(ptcstats, smp_processor_id()); + msgdesc.va_queue_first = bcp->va_queue_first; + msgdesc.va_queue_last = bcp->va_queue_last; + msg = bcp->bau_msg_head; while (msg->sw_ack_vector) { count++; - fw = msg->sw_ack_vector; - msg_slot = msg - va_queue_first; - sw_ack_slot = ffs(fw) - 1; - - uv_bau_process_message(msg, msg_slot, sw_ack_slot); - + msgdesc.msg_slot = msg - msgdesc.va_queue_first; + msgdesc.sw_ack_slot = ffs(msg->sw_ack_vector) - 1; + msgdesc.msg = msg; + uv_bau_process_message(&msgdesc, bcp); msg++; - if (msg > va_queue_last) - msg = va_queue_first; - __get_cpu_var(bau_control).bau_msg_head = msg; + if (msg > msgdesc.va_queue_last) + msg = msgdesc.va_queue_first; + bcp->bau_msg_head = msg; } + stat->d_time += (get_cycles() - time_start); if (!count) - __get_cpu_var(ptcstats).nomsg++; + stat->d_nomsg++; else if (count > 1) - __get_cpu_var(ptcstats).multmsg++; - - time2 = get_cycles(); - __get_cpu_var(ptcstats).dflush += (time2 - time1); - - irq_exit(); - set_irq_regs(old_regs); + stat->d_multmsg++; + ack_APIC_irq(); } /* * uv_enable_timeouts * - * Each target blade (i.e. blades that have cpu's) needs to have + * Each target uvhub (i.e. a uvhub that has no cpu's) needs to have * shootdown message timeouts enabled. The timeout does not cause * an interrupt, but causes an error message to be returned to * the sender. */ static void uv_enable_timeouts(void) { - int blade; - int nblades; + int uvhub; + int nuvhubs; int pnode; unsigned long mmr_image; - nblades = uv_num_possible_blades(); + nuvhubs = uv_num_possible_blades(); - for (blade = 0; blade < nblades; blade++) { - if (!uv_blade_nr_possible_cpus(blade)) + for (uvhub = 0; uvhub < nuvhubs; uvhub++) { + if (!uv_blade_nr_possible_cpus(uvhub)) continue; - pnode = uv_blade_to_pnode(blade); + pnode = uv_blade_to_pnode(uvhub); mmr_image = uv_read_global_mmr64(pnode, UVH_LB_BAU_MISC_CONTROL); /* @@ -523,9 +906,20 @@ static void uv_ptc_seq_stop(struct seq_file *file, void *data) { } +static inline unsigned long long +millisec_2_cycles(unsigned long millisec) +{ + unsigned long ns; + unsigned long long cyc; + + ns = millisec * 1000; + cyc = (ns << CYC2NS_SCALE_FACTOR)/(per_cpu(cyc2ns, smp_processor_id())); + return cyc; +} + /* - * Display the statistics thru /proc - * data points to the cpu number + * Display the statistics thru /proc. + * 'data' points to the cpu number */ static int uv_ptc_seq_show(struct seq_file *file, void *data) { @@ -536,78 +930,155 @@ static int uv_ptc_seq_show(struct seq_file *file, void *data) if (!cpu) { seq_printf(file, - "# cpu requestor requestee one all sretry dretry ptc_i "); + "# cpu sent stime numuvhubs numuvhubs16 numuvhubs8 "); seq_printf(file, - "sw_ack sflush dflush sok dnomsg dmult starget\n"); + "numuvhubs4 numuvhubs2 numuvhubs1 numcpus dto "); + seq_printf(file, + "retries rok resetp resett giveup sto bz throt "); + seq_printf(file, + "sw_ack recv rtime all "); + seq_printf(file, + "one mult none retry canc nocan reset rcan\n"); } if (cpu < num_possible_cpus() && cpu_online(cpu)) { stat = &per_cpu(ptcstats, cpu); - seq_printf(file, "cpu %d %ld %ld %ld %ld %ld %ld %ld ", - cpu, stat->requestor, - stat->requestee, stat->onetlb, stat->alltlb, - stat->s_retry, stat->d_retry, stat->ptc_i); - seq_printf(file, "%lx %ld %ld %ld %ld %ld %ld\n", + /* source side statistics */ + seq_printf(file, + "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld ", + cpu, stat->s_requestor, cycles_2_us(stat->s_time), + stat->s_ntarguvhub, stat->s_ntarguvhub16, + stat->s_ntarguvhub8, stat->s_ntarguvhub4, + stat->s_ntarguvhub2, stat->s_ntarguvhub1, + stat->s_ntargcpu, stat->s_dtimeout); + seq_printf(file, "%ld %ld %ld %ld %ld %ld %ld %ld ", + stat->s_retry_messages, stat->s_retriesok, + stat->s_resets_plug, stat->s_resets_timeout, + stat->s_giveup, stat->s_stimeout, + stat->s_busy, stat->s_throttles); + /* destination side statistics */ + seq_printf(file, + "%lx %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n", uv_read_global_mmr64(uv_cpu_to_pnode(cpu), UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE), - stat->sflush, stat->dflush, - stat->retriesok, stat->nomsg, - stat->multmsg, stat->ntargeted); + stat->d_requestee, cycles_2_us(stat->d_time), + stat->d_alltlb, stat->d_onetlb, stat->d_multmsg, + stat->d_nomsg, stat->d_retries, stat->d_canceled, + stat->d_nocanceled, stat->d_resets, + stat->d_rcanceled); } return 0; } /* + * -1: resetf the statistics * 0: display meaning of the statistics - * >0: retry limit + * >0: maximum concurrent active descriptors per uvhub (throttle) */ static ssize_t uv_ptc_proc_write(struct file *file, const char __user *user, size_t count, loff_t *data) { - long newmode; + int cpu; + long input_arg; char optstr[64]; + struct ptc_stats *stat; + struct bau_control *bcp; if (count == 0 || count > sizeof(optstr)) return -EINVAL; if (copy_from_user(optstr, user, count)) return -EFAULT; optstr[count - 1] = '\0'; - if (strict_strtoul(optstr, 10, &newmode) < 0) { + if (strict_strtol(optstr, 10, &input_arg) < 0) { printk(KERN_DEBUG "%s is invalid\n", optstr); return -EINVAL; } - if (newmode == 0) { + if (input_arg == 0) { printk(KERN_DEBUG "# cpu: cpu number\n"); + printk(KERN_DEBUG "Sender statistics:\n"); + printk(KERN_DEBUG + "sent: number of shootdown messages sent\n"); + printk(KERN_DEBUG + "stime: time spent sending messages\n"); + printk(KERN_DEBUG + "numuvhubs: number of hubs targeted with shootdown\n"); + printk(KERN_DEBUG + "numuvhubs16: number times 16 or more hubs targeted\n"); + printk(KERN_DEBUG + "numuvhubs8: number times 8 or more hubs targeted\n"); + printk(KERN_DEBUG + "numuvhubs4: number times 4 or more hubs targeted\n"); + printk(KERN_DEBUG + "numuvhubs2: number times 2 or more hubs targeted\n"); + printk(KERN_DEBUG + "numuvhubs1: number times 1 hub targeted\n"); + printk(KERN_DEBUG + "numcpus: number of cpus targeted with shootdown\n"); + printk(KERN_DEBUG + "dto: number of destination timeouts\n"); + printk(KERN_DEBUG + "retries: destination timeout retries sent\n"); + printk(KERN_DEBUG + "rok: : destination timeouts successfully retried\n"); + printk(KERN_DEBUG + "resetp: ipi-style resource resets for plugs\n"); + printk(KERN_DEBUG + "resett: ipi-style resource resets for timeouts\n"); + printk(KERN_DEBUG + "giveup: fall-backs to ipi-style shootdowns\n"); + printk(KERN_DEBUG + "sto: number of source timeouts\n"); + printk(KERN_DEBUG + "bz: number of stay-busy's\n"); + printk(KERN_DEBUG + "throt: number times spun in throttle\n"); + printk(KERN_DEBUG "Destination side statistics:\n"); printk(KERN_DEBUG - "requestor: times this cpu was the flush requestor\n"); + "sw_ack: image of UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE\n"); printk(KERN_DEBUG - "requestee: times this cpu was requested to flush its TLBs\n"); + "recv: shootdown messages received\n"); printk(KERN_DEBUG - "one: times requested to flush a single address\n"); + "rtime: time spent processing messages\n"); printk(KERN_DEBUG - "all: times requested to flush all TLB's\n"); + "all: shootdown all-tlb messages\n"); printk(KERN_DEBUG - "sretry: number of retries of source-side timeouts\n"); + "one: shootdown one-tlb messages\n"); printk(KERN_DEBUG - "dretry: number of retries of destination-side timeouts\n"); + "mult: interrupts that found multiple messages\n"); printk(KERN_DEBUG - "ptc_i: times UV fell through to IPI-style flushes\n"); + "none: interrupts that found no messages\n"); printk(KERN_DEBUG - "sw_ack: image of UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE\n"); + "retry: number of retry messages processed\n"); printk(KERN_DEBUG - "sflush_us: cycles spent in uv_flush_tlb_others()\n"); + "canc: number messages canceled by retries\n"); printk(KERN_DEBUG - "dflush_us: cycles spent in handling flush requests\n"); - printk(KERN_DEBUG "sok: successes on retry\n"); - printk(KERN_DEBUG "dnomsg: interrupts with no message\n"); + "nocan: number retries that found nothing to cancel\n"); printk(KERN_DEBUG - "dmult: interrupts with multiple messages\n"); - printk(KERN_DEBUG "starget: nodes targeted\n"); + "reset: number of ipi-style reset requests processed\n"); + printk(KERN_DEBUG + "rcan: number messages canceled by reset requests\n"); + } else if (input_arg == -1) { + for_each_present_cpu(cpu) { + stat = &per_cpu(ptcstats, cpu); + memset(stat, 0, sizeof(struct ptc_stats)); + } } else { - uv_bau_retry_limit = newmode; - printk(KERN_DEBUG "timeout retry limit:%d\n", - uv_bau_retry_limit); + uv_bau_max_concurrent = input_arg; + bcp = &per_cpu(bau_control, smp_processor_id()); + if (uv_bau_max_concurrent < 1 || + uv_bau_max_concurrent > bcp->cpus_in_uvhub) { + printk(KERN_DEBUG + "Error: BAU max concurrent %d; %d is invalid\n", + bcp->max_concurrent, uv_bau_max_concurrent); + return -EINVAL; + } + printk(KERN_DEBUG "Set BAU max concurrent:%d\n", + uv_bau_max_concurrent); + for_each_present_cpu(cpu) { + bcp = &per_cpu(bau_control, cpu); + bcp->max_concurrent = uv_bau_max_concurrent; + } } return count; @@ -651,79 +1122,30 @@ static int __init uv_ptc_init(void) } /* - * begin the initialization of the per-blade control structures - */ -static struct bau_control * __init uv_table_bases_init(int blade, int node) -{ - int i; - struct bau_msg_status *msp; - struct bau_control *bau_tabp; - - bau_tabp = - kmalloc_node(sizeof(struct bau_control), GFP_KERNEL, node); - BUG_ON(!bau_tabp); - - bau_tabp->msg_statuses = - kmalloc_node(sizeof(struct bau_msg_status) * - DEST_Q_SIZE, GFP_KERNEL, node); - BUG_ON(!bau_tabp->msg_statuses); - - for (i = 0, msp = bau_tabp->msg_statuses; i < DEST_Q_SIZE; i++, msp++) - bau_cpubits_clear(&msp->seen_by, (int) - uv_blade_nr_possible_cpus(blade)); - - uv_bau_table_bases[blade] = bau_tabp; - - return bau_tabp; -} - -/* - * finish the initialization of the per-blade control structures - */ -static void __init -uv_table_bases_finish(int blade, - struct bau_control *bau_tablesp, - struct bau_desc *adp) -{ - struct bau_control *bcp; - int cpu; - - for_each_present_cpu(cpu) { - if (blade != uv_cpu_to_blade_id(cpu)) - continue; - - bcp = (struct bau_control *)&per_cpu(bau_control, cpu); - bcp->bau_msg_head = bau_tablesp->va_queue_first; - bcp->va_queue_first = bau_tablesp->va_queue_first; - bcp->va_queue_last = bau_tablesp->va_queue_last; - bcp->msg_statuses = bau_tablesp->msg_statuses; - bcp->descriptor_base = adp; - } -} - -/* * initialize the sending side's sending buffers */ -static struct bau_desc * __init +static void uv_activation_descriptor_init(int node, int pnode) { int i; + int cpu; unsigned long pa; unsigned long m; unsigned long n; - struct bau_desc *adp; - struct bau_desc *ad2; + struct bau_desc *bau_desc; + struct bau_desc *bd2; + struct bau_control *bcp; /* * each bau_desc is 64 bytes; there are 8 (UV_ITEMS_PER_DESCRIPTOR) - * per cpu; and up to 32 (UV_ADP_SIZE) cpu's per blade + * per cpu; and up to 32 (UV_ADP_SIZE) cpu's per uvhub */ - adp = (struct bau_desc *)kmalloc_node(sizeof(struct bau_desc)* + bau_desc = (struct bau_desc *)kmalloc_node(sizeof(struct bau_desc)* UV_ADP_SIZE*UV_ITEMS_PER_DESCRIPTOR, GFP_KERNEL, node); - BUG_ON(!adp); + BUG_ON(!bau_desc); - pa = uv_gpa(adp); /* need the real nasid*/ - n = uv_gpa_to_pnode(pa); + pa = uv_gpa(bau_desc); /* need the real nasid*/ + n = pa >> uv_nshift; m = pa & uv_mmask; uv_write_global_mmr64(pnode, UVH_LB_BAU_SB_DESCRIPTOR_BASE, @@ -732,96 +1154,188 @@ uv_activation_descriptor_init(int node, int pnode) /* * initializing all 8 (UV_ITEMS_PER_DESCRIPTOR) descriptors for each * cpu even though we only use the first one; one descriptor can - * describe a broadcast to 256 nodes. + * describe a broadcast to 256 uv hubs. */ - for (i = 0, ad2 = adp; i < (UV_ADP_SIZE*UV_ITEMS_PER_DESCRIPTOR); - i++, ad2++) { - memset(ad2, 0, sizeof(struct bau_desc)); - ad2->header.sw_ack_flag = 1; + for (i = 0, bd2 = bau_desc; i < (UV_ADP_SIZE*UV_ITEMS_PER_DESCRIPTOR); + i++, bd2++) { + memset(bd2, 0, sizeof(struct bau_desc)); + bd2->header.sw_ack_flag = 1; /* - * base_dest_nodeid is the first node in the partition, so - * the bit map will indicate partition-relative node numbers. - * note that base_dest_nodeid is actually a nasid. + * base_dest_nodeid is the nasid (pnode<<1) of the first uvhub + * in the partition. The bit map will indicate uvhub numbers, + * which are 0-N in a partition. Pnodes are unique system-wide. */ - ad2->header.base_dest_nodeid = uv_partition_base_pnode << 1; - ad2->header.dest_subnodeid = 0x10; /* the LB */ - ad2->header.command = UV_NET_ENDPOINT_INTD; - ad2->header.int_both = 1; + bd2->header.base_dest_nodeid = uv_partition_base_pnode << 1; + bd2->header.dest_subnodeid = 0x10; /* the LB */ + bd2->header.command = UV_NET_ENDPOINT_INTD; + bd2->header.int_both = 1; /* * all others need to be set to zero: * fairness chaining multilevel count replied_to */ } - return adp; + for_each_present_cpu(cpu) { + if (pnode != uv_blade_to_pnode(uv_cpu_to_blade_id(cpu))) + continue; + bcp = &per_cpu(bau_control, cpu); + bcp->descriptor_base = bau_desc; + } } /* * initialize the destination side's receiving buffers + * entered for each uvhub in the partition + * - node is first node (kernel memory notion) on the uvhub + * - pnode is the uvhub's physical identifier */ -static struct bau_payload_queue_entry * __init -uv_payload_queue_init(int node, int pnode, struct bau_control *bau_tablesp) +static void +uv_payload_queue_init(int node, int pnode) { - struct bau_payload_queue_entry *pqp; - unsigned long pa; int pn; + int cpu; char *cp; + unsigned long pa; + struct bau_payload_queue_entry *pqp; + struct bau_payload_queue_entry *pqp_malloc; + struct bau_control *bcp; pqp = (struct bau_payload_queue_entry *) kmalloc_node( (DEST_Q_SIZE + 1) * sizeof(struct bau_payload_queue_entry), GFP_KERNEL, node); BUG_ON(!pqp); + pqp_malloc = pqp; cp = (char *)pqp + 31; pqp = (struct bau_payload_queue_entry *)(((unsigned long)cp >> 5) << 5); - bau_tablesp->va_queue_first = pqp; + + for_each_present_cpu(cpu) { + if (pnode != uv_cpu_to_pnode(cpu)) + continue; + /* for every cpu on this pnode: */ + bcp = &per_cpu(bau_control, cpu); + bcp->va_queue_first = pqp; + bcp->bau_msg_head = pqp; + bcp->va_queue_last = pqp + (DEST_Q_SIZE - 1); + } /* * need the pnode of where the memory was really allocated */ pa = uv_gpa(pqp); - pn = uv_gpa_to_pnode(pa); + pn = pa >> uv_nshift; uv_write_global_mmr64(pnode, UVH_LB_BAU_INTD_PAYLOAD_QUEUE_FIRST, ((unsigned long)pn << UV_PAYLOADQ_PNODE_SHIFT) | uv_physnodeaddr(pqp)); uv_write_global_mmr64(pnode, UVH_LB_BAU_INTD_PAYLOAD_QUEUE_TAIL, uv_physnodeaddr(pqp)); - bau_tablesp->va_queue_last = pqp + (DEST_Q_SIZE - 1); uv_write_global_mmr64(pnode, UVH_LB_BAU_INTD_PAYLOAD_QUEUE_LAST, (unsigned long) - uv_physnodeaddr(bau_tablesp->va_queue_last)); + uv_physnodeaddr(pqp + (DEST_Q_SIZE - 1))); + /* in effect, all msg_type's are set to MSG_NOOP */ memset(pqp, 0, sizeof(struct bau_payload_queue_entry) * DEST_Q_SIZE); - - return pqp; } /* - * Initialization of each UV blade's structures + * Initialization of each UV hub's structures */ -static int __init uv_init_blade(int blade) +static void __init uv_init_uvhub(int uvhub, int vector) { int node; int pnode; - unsigned long pa; unsigned long apicid; - struct bau_desc *adp; - struct bau_payload_queue_entry *pqp; - struct bau_control *bau_tablesp; - - node = blade_to_first_node(blade); - bau_tablesp = uv_table_bases_init(blade, node); - pnode = uv_blade_to_pnode(blade); - adp = uv_activation_descriptor_init(node, pnode); - pqp = uv_payload_queue_init(node, pnode, bau_tablesp); - uv_table_bases_finish(blade, bau_tablesp, adp); + + node = uvhub_to_first_node(uvhub); + pnode = uv_blade_to_pnode(uvhub); + uv_activation_descriptor_init(node, pnode); + uv_payload_queue_init(node, pnode); /* * the below initialization can't be in firmware because the * messaging IRQ will be determined by the OS */ - apicid = blade_to_first_apicid(blade); - pa = uv_read_global_mmr64(pnode, UVH_BAU_DATA_CONFIG); + apicid = uvhub_to_first_apicid(uvhub); uv_write_global_mmr64(pnode, UVH_BAU_DATA_CONFIG, - ((apicid << 32) | UV_BAU_MESSAGE)); - return 0; + ((apicid << 32) | vector)); +} + +/* + * initialize the bau_control structure for each cpu + */ +static void uv_init_per_cpu(int nuvhubs) +{ + int i, j, k; + int cpu; + int pnode; + int uvhub; + short socket = 0; + struct bau_control *bcp; + struct uvhub_desc *bdp; + struct socket_desc *sdp; + struct bau_control *hmaster = NULL; + struct bau_control *smaster = NULL; + struct socket_desc { + short num_cpus; + short cpu_number[16]; + }; + struct uvhub_desc { + short num_sockets; + short num_cpus; + short uvhub; + short pnode; + struct socket_desc socket[2]; + }; + struct uvhub_desc *uvhub_descs; + + uvhub_descs = (struct uvhub_desc *) + kmalloc(nuvhubs * sizeof(struct uvhub_desc), GFP_KERNEL); + memset(uvhub_descs, 0, nuvhubs * sizeof(struct uvhub_desc)); + for_each_present_cpu(cpu) { + bcp = &per_cpu(bau_control, cpu); + memset(bcp, 0, sizeof(struct bau_control)); + spin_lock_init(&bcp->masks_lock); + bcp->max_concurrent = uv_bau_max_concurrent; + pnode = uv_cpu_hub_info(cpu)->pnode; + uvhub = uv_cpu_hub_info(cpu)->numa_blade_id; + bdp = &uvhub_descs[uvhub]; + bdp->num_cpus++; + bdp->uvhub = uvhub; + bdp->pnode = pnode; + /* time interval to catch a hardware stay-busy bug */ + bcp->timeout_interval = millisec_2_cycles(3); + /* kludge: assume uv_hub.h is constant */ + socket = (cpu_physical_id(cpu)>>5)&1; + if (socket >= bdp->num_sockets) + bdp->num_sockets = socket+1; + sdp = &bdp->socket[socket]; + sdp->cpu_number[sdp->num_cpus] = cpu; + sdp->num_cpus++; + } + socket = 0; + for_each_possible_blade(uvhub) { + bdp = &uvhub_descs[uvhub]; + for (i = 0; i < bdp->num_sockets; i++) { + sdp = &bdp->socket[i]; + for (j = 0; j < sdp->num_cpus; j++) { + cpu = sdp->cpu_number[j]; + bcp = &per_cpu(bau_control, cpu); + bcp->cpu = cpu; + if (j == 0) { + smaster = bcp; + if (i == 0) + hmaster = bcp; + } + bcp->cpus_in_uvhub = bdp->num_cpus; + bcp->cpus_in_socket = sdp->num_cpus; + bcp->socket_master = smaster; + bcp->uvhub_master = hmaster; + for (k = 0; k < DEST_Q_SIZE; k++) + bcp->socket_acknowledge_count[k] = 0; + bcp->uvhub_cpu = + uv_cpu_hub_info(cpu)->blade_processor_id; + } + socket++; + } + } + kfree(uvhub_descs); } /* @@ -829,38 +1343,54 @@ static int __init uv_init_blade(int blade) */ static int __init uv_bau_init(void) { - int blade; - int nblades; + int uvhub; + int pnode; + int nuvhubs; int cur_cpu; + int vector; + unsigned long mmr; if (!is_uv_system()) return 0; + if (nobau) + return 0; + for_each_possible_cpu(cur_cpu) zalloc_cpumask_var_node(&per_cpu(uv_flush_tlb_mask, cur_cpu), GFP_KERNEL, cpu_to_node(cur_cpu)); - uv_bau_retry_limit = 1; + uv_bau_max_concurrent = MAX_BAU_CONCURRENT; + uv_nshift = uv_hub_info->m_val; uv_mmask = (1UL << uv_hub_info->m_val) - 1; - nblades = uv_num_possible_blades(); + nuvhubs = uv_num_possible_blades(); - uv_bau_table_bases = (struct bau_control **) - kmalloc(nblades * sizeof(struct bau_control *), GFP_KERNEL); - BUG_ON(!uv_bau_table_bases); + uv_init_per_cpu(nuvhubs); uv_partition_base_pnode = 0x7fffffff; - for (blade = 0; blade < nblades; blade++) - if (uv_blade_nr_possible_cpus(blade) && - (uv_blade_to_pnode(blade) < uv_partition_base_pnode)) - uv_partition_base_pnode = uv_blade_to_pnode(blade); - for (blade = 0; blade < nblades; blade++) - if (uv_blade_nr_possible_cpus(blade)) - uv_init_blade(blade); - - alloc_intr_gate(UV_BAU_MESSAGE, uv_bau_message_intr1); + for (uvhub = 0; uvhub < nuvhubs; uvhub++) + if (uv_blade_nr_possible_cpus(uvhub) && + (uv_blade_to_pnode(uvhub) < uv_partition_base_pnode)) + uv_partition_base_pnode = uv_blade_to_pnode(uvhub); + + vector = UV_BAU_MESSAGE; + for_each_possible_blade(uvhub) + if (uv_blade_nr_possible_cpus(uvhub)) + uv_init_uvhub(uvhub, vector); + uv_enable_timeouts(); + alloc_intr_gate(vector, uv_bau_message_intr1); + + for_each_possible_blade(uvhub) { + pnode = uv_blade_to_pnode(uvhub); + /* INIT the bau */ + uv_write_global_mmr64(pnode, UVH_LB_BAU_SB_ACTIVATION_CONTROL, + ((unsigned long)1 << 63)); + mmr = 1; /* should be 1 to broadcast to both sockets */ + uv_write_global_mmr64(pnode, UVH_BAU_DATA_BROADCAST, mmr); + } return 0; } -__initcall(uv_bau_init); -__initcall(uv_ptc_init); +core_initcall(uv_bau_init); +core_initcall(uv_ptc_init); -- cgit v0.10.2 From fcd1498405c2c88ac632e7c3c3fce3213d9196db Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 14 Apr 2010 19:11:29 +0200 Subject: perf tools: Fix accidentally preprocessed snprintf callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit struct sort_entry has a callback named snprintf that turns an entry into a string result. But there are glibc versions that implement snprintf through a macro. The following expression is then going to get the snprintf call preprocessed: ent->snprintf(...) to finally end up in a build error: util/hist.c: Dans la fonction «hist_entry__snprintf» : util/hist.c:539: erreur: «struct sort_entry» has no member named «__builtin___snprintf_chk» To fix this, prepend struct sort_entry callbacks with an "se_" prefix. Signed-off-by: Frederic Weisbecker Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Ingo Molnar Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 18cf8b3..9c2b874 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -68,7 +68,7 @@ hist_entry__cmp(struct hist_entry *left, struct hist_entry *right) int64_t cmp = 0; list_for_each_entry(se, &hist_entry__sort_list, list) { - cmp = se->cmp(left, right); + cmp = se->se_cmp(left, right); if (cmp) break; } @@ -85,7 +85,7 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right) list_for_each_entry(se, &hist_entry__sort_list, list) { int64_t (*f)(struct hist_entry *, struct hist_entry *); - f = se->collapse ?: se->cmp; + f = se->se_collapse ?: se->se_cmp; cmp = f(left, right); if (cmp) @@ -536,8 +536,8 @@ int hist_entry__snprintf(struct hist_entry *self, continue; ret += snprintf(s + ret, size - ret, "%s", sep ?: " "); - ret += se->snprintf(self, s + ret, size - ret, - se->width ? *se->width : 0); + ret += se->se_snprintf(self, s + ret, size - ret, + se->se_width ? *se->se_width : 0); } return ret; @@ -564,7 +564,7 @@ static size_t hist_entry__fprintf_callchain(struct hist_entry *self, FILE *fp, if (sort__first_dimension == SORT_COMM) { struct sort_entry *se = list_first_entry(&hist_entry__sort_list, typeof(*se), list); - left_margin = se->width ? *se->width : 0; + left_margin = se->se_width ? *se->se_width : 0; left_margin -= thread__comm_len(self->thread); } @@ -615,22 +615,22 @@ size_t perf_session__fprintf_hists(struct rb_root *hists, if (se->elide) continue; if (sep) { - fprintf(fp, "%c%s", *sep, se->header); + fprintf(fp, "%c%s", *sep, se->se_header); continue; } - width = strlen(se->header); - if (se->width) { + width = strlen(se->se_header); + if (se->se_width) { if (symbol_conf.col_width_list_str) { if (col_width) { - *se->width = atoi(col_width); + *se->se_width = atoi(col_width); col_width = strchr(col_width, ','); if (col_width) ++col_width; } } - width = *se->width = max(*se->width, width); + width = *se->se_width = max(*se->se_width, width); } - fprintf(fp, " %*s", width, se->header); + fprintf(fp, " %*s", width, se->se_header); } fprintf(fp, "\n"); @@ -652,10 +652,10 @@ size_t perf_session__fprintf_hists(struct rb_root *hists, continue; fprintf(fp, " "); - if (se->width) - width = *se->width; + if (se->se_width) + width = *se->se_width; else - width = strlen(se->header); + width = strlen(se->se_header); for (i = 0; i < width; i++) fprintf(fp, "."); } diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 9d24d4b..da30b30 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -30,38 +30,38 @@ static int hist_entry__parent_snprintf(struct hist_entry *self, char *bf, size_t size, unsigned int width); struct sort_entry sort_thread = { - .header = "Command: Pid", - .cmp = sort__thread_cmp, - .snprintf = hist_entry__thread_snprintf, - .width = &threads__col_width, + .se_header = "Command: Pid", + .se_cmp = sort__thread_cmp, + .se_snprintf = hist_entry__thread_snprintf, + .se_width = &threads__col_width, }; struct sort_entry sort_comm = { - .header = "Command", - .cmp = sort__comm_cmp, - .collapse = sort__comm_collapse, - .snprintf = hist_entry__comm_snprintf, - .width = &comms__col_width, + .se_header = "Command", + .se_cmp = sort__comm_cmp, + .se_collapse = sort__comm_collapse, + .se_snprintf = hist_entry__comm_snprintf, + .se_width = &comms__col_width, }; struct sort_entry sort_dso = { - .header = "Shared Object", - .cmp = sort__dso_cmp, - .snprintf = hist_entry__dso_snprintf, - .width = &dsos__col_width, + .se_header = "Shared Object", + .se_cmp = sort__dso_cmp, + .se_snprintf = hist_entry__dso_snprintf, + .se_width = &dsos__col_width, }; struct sort_entry sort_sym = { - .header = "Symbol", - .cmp = sort__sym_cmp, - .snprintf = hist_entry__sym_snprintf, + .se_header = "Symbol", + .se_cmp = sort__sym_cmp, + .se_snprintf = hist_entry__sym_snprintf, }; struct sort_entry sort_parent = { - .header = "Parent symbol", - .cmp = sort__parent_cmp, - .snprintf = hist_entry__parent_snprintf, - .width = &parent_symbol__col_width, + .se_header = "Parent symbol", + .se_cmp = sort__parent_cmp, + .se_snprintf = hist_entry__parent_snprintf, + .se_width = &parent_symbol__col_width, }; struct sort_dimension { @@ -255,7 +255,7 @@ int sort_dimension__add(const char *tok) if (strncasecmp(tok, sd->name, strlen(tok))) continue; - if (sd->entry->collapse) + if (sd->entry->se_collapse) sort__need_collapse = 1; if (sd->entry == &sort_parent) { diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index 6d7b4be..1d857aa 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h @@ -78,13 +78,13 @@ enum sort_type { struct sort_entry { struct list_head list; - const char *header; + const char *se_header; - int64_t (*cmp)(struct hist_entry *, struct hist_entry *); - int64_t (*collapse)(struct hist_entry *, struct hist_entry *); - int (*snprintf)(struct hist_entry *self, char *bf, size_t size, - unsigned int width); - unsigned int *width; + int64_t (*se_cmp)(struct hist_entry *, struct hist_entry *); + int64_t (*se_collapse)(struct hist_entry *, struct hist_entry *); + int (*se_snprintf)(struct hist_entry *self, char *bf, size_t size, + unsigned int width); + unsigned int *se_width; bool elide; }; -- cgit v0.10.2 From 48481938b02471d505296d7557ed296eb093d496 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Mon, 12 Apr 2010 13:16:53 -0400 Subject: perf probe: Support argument name Set given names to event arguments. The syntax is same as kprobe-tracer, you can add 'NAME=' right before each argument. e.g. ./perf probe vfs_read foo=file then, 'foo' is set to the argument name as below. ./perf probe -l probe:vfs_read (on vfs_read@linux-2.6-tip/fs/read_write.c with foo) Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Frederic Weisbecker LKML-Reference: <20100412171653.3790.74624.stgit@localhost6.localdomain6> Signed-off-by: Masami Hiramatsu Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt index bb671b3..e36ed4d 100644 --- a/tools/perf/Documentation/perf-probe.txt +++ b/tools/perf/Documentation/perf-probe.txt @@ -79,7 +79,15 @@ Probe points are defined by following syntax. 'EVENT' specifies the name of new event, if omitted, it will be set the name of the probed function. Currently, event group name is set as 'probe'. 'FUNC' specifies a probed function name, and it may have one of the following options; '+OFFS' is the offset from function entry address in bytes, ':RLN' is the relative-line number from function entry line, and '%return' means that it probes function return. And ';PTN' means lazy matching pattern (see LAZY MATCHING). Note that ';PTN' must be the end of the probe point definition. In addition, '@SRC' specifies a source file which has that function. It is also possible to specify a probe point by the source line number or lazy matching by using 'SRC:ALN' or 'SRC;PTN' syntax, where 'SRC' is the source file path, ':ALN' is the line number and ';PTN' is the lazy matching pattern. -'ARG' specifies the arguments of this probe point. You can use the name of local variable, or kprobe-tracer argument format (e.g. $retval, %ax, etc). +'ARG' specifies the arguments of this probe point, (see PROBE ARGUMENT). + +PROBE ARGUMENT +-------------- +Each probe argument follows below syntax. + + [NAME=]LOCALVAR|$retval|%REG|@SYMBOL + +'NAME' specifies the name of this argument (optional). You can use the name of local variable, local data structure member (e.g. var->field, var.field2), or kprobe-tracer argument format (e.g. $retval, %ax, etc). LINE SYNTAX ----------- diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index bfc47ff..daf4668 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c @@ -142,9 +142,9 @@ static const struct option options[] = { OPT_CALLBACK('a', "add", NULL, #ifdef DWARF_SUPPORT "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT" - " [ARG ...]", + " [[NAME=]ARG ...]", #else - "[EVENT=]FUNC[+OFF|%return] [ARG ...]", + "[EVENT=]FUNC[+OFF|%return] [[NAME=]ARG ...]", #endif "probe point definition, where\n" "\t\tGROUP:\tGroup name (optional)\n" diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 3fc0be7..ab6f53d 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -437,22 +437,28 @@ static void parse_perf_probe_point(char *arg, struct perf_probe_event *pev) /* Parse perf-probe event argument */ static void parse_perf_probe_arg(const char *str, struct perf_probe_arg *arg) { - const char *tmp; + char *tmp; struct perf_probe_arg_field **fieldp; pr_debug("parsing arg: %s into ", str); + tmp = strchr(str, '='); + if (tmp) { + arg->name = xstrndup(str, tmp - str); + str = tmp + 1; + } + tmp = strpbrk(str, "-."); if (!is_c_varname(str) || !tmp) { /* A variable, register, symbol or special value */ - arg->name = xstrdup(str); - pr_debug("%s\n", arg->name); + arg->var = xstrdup(str); + pr_debug("%s\n", arg->var); return; } /* Structure fields */ - arg->name = xstrndup(str, tmp - str); - pr_debug("%s, ", arg->name); + arg->var = xstrndup(str, tmp - str); + pr_debug("%s, ", arg->var); fieldp = &arg->field; do { @@ -497,7 +503,7 @@ void parse_perf_probe_command(const char *cmd, struct perf_probe_event *pev) pev->args = xzalloc(sizeof(struct perf_probe_arg) * pev->nargs); for (i = 0; i < pev->nargs; i++) { parse_perf_probe_arg(argv[i + 1], &pev->args[i]); - if (is_c_varname(pev->args[i].name) && pev->point.retprobe) + if (is_c_varname(pev->args[i].var) && pev->point.retprobe) semantic_error("You can't specify local variable for" " kretprobe"); } @@ -514,7 +520,7 @@ bool perf_probe_event_need_dwarf(struct perf_probe_event *pev) return true; for (i = 0; i < pev->nargs; i++) - if (is_c_varname(pev->args[i].name)) + if (is_c_varname(pev->args[i].var)) return true; return false; @@ -575,7 +581,10 @@ int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len) int ret; char *tmp = buf; - ret = e_snprintf(tmp, len, "%s", pa->name); + if (pa->name && pa->var) + ret = e_snprintf(tmp, len, "%s=%s", pa->name, pa->var); + else + ret = e_snprintf(tmp, len, "%s", pa->name ? pa->name : pa->var); if (ret <= 0) goto error; tmp += ret; @@ -803,6 +812,8 @@ void clear_perf_probe_event(struct perf_probe_event *pev) for (i = 0; i < pev->nargs; i++) { if (pev->args[i].name) free(pev->args[i].name); + if (pev->args[i].var) + free(pev->args[i].var); field = pev->args[i].field; while (field) { next = field->next; @@ -1117,8 +1128,11 @@ static int convert_to_kprobe_trace_events(struct perf_probe_event *pev, if (tev->nargs) { tev->args = xzalloc(sizeof(struct kprobe_trace_arg) * tev->nargs); - for (i = 0; i < tev->nargs; i++) - tev->args[i].value = xstrdup(pev->args[i].name); + for (i = 0; i < tev->nargs; i++) { + if (pev->args[i].name) + tev->args[i].name = xstrdup(pev->args[i].name); + tev->args[i].value = xstrdup(pev->args[i].var); + } } /* Currently just checking function name from symbol map */ diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h index 9d99fc2..10411f5 100644 --- a/tools/perf/util/probe-event.h +++ b/tools/perf/util/probe-event.h @@ -55,6 +55,7 @@ struct perf_probe_arg_field { /* Perf probe probing argument */ struct perf_probe_arg { char *name; /* Argument name */ + char *var; /* Variable name */ struct perf_probe_arg_field *field; /* Structure fields */ }; diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index a851377..105e95c 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -484,35 +484,40 @@ static void convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf) convert_location(expr, pf); if (pf->pvar->field) - convert_variable_fields(vr_die, pf->pvar->name, + convert_variable_fields(vr_die, pf->pvar->var, pf->pvar->field, &pf->tvar->ref); /* *expr will be cached in libdw. Don't free it. */ return ; error: /* TODO: Support const_value */ die("Failed to find the location of %s at this address.\n" - " Perhaps, it has been optimized out.", pf->pvar->name); + " Perhaps, it has been optimized out.", pf->pvar->var); } /* Find a variable in a subprogram die */ static void find_variable(Dwarf_Die *sp_die, struct probe_finder *pf) { Dwarf_Die vr_die; - char buf[128]; + char buf[32]; - /* TODO: Support struct members and arrays */ - if (!is_c_varname(pf->pvar->name)) { + /* TODO: Support arrays */ + if (pf->pvar->name) + pf->tvar->name = xstrdup(pf->pvar->name); + else { + synthesize_perf_probe_arg(pf->pvar, buf, 32); + pf->tvar->name = xstrdup(buf); + } + + if (!is_c_varname(pf->pvar->var)) { /* Copy raw parameters */ - pf->tvar->value = xstrdup(pf->pvar->name); + pf->tvar->value = xstrdup(pf->pvar->var); } else { - synthesize_perf_probe_arg(pf->pvar, buf, 128); - pf->tvar->name = xstrdup(buf); pr_debug("Searching '%s' variable in context.\n", - pf->pvar->name); + pf->pvar->var); /* Search child die for local variables and parameters. */ - if (!die_find_variable(sp_die, pf->pvar->name, &vr_die)) + if (!die_find_variable(sp_die, pf->pvar->var, &vr_die)) die("Failed to find '%s' in this function.", - pf->pvar->name); + pf->pvar->var); convert_variable(&vr_die, pf); } } -- cgit v0.10.2 From df0faf4be02996135bc3a06b4f34360449c78084 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Mon, 12 Apr 2010 13:17:00 -0400 Subject: perf probe: Use the last field name as the argument name Set the last field name to the argument name when the argument is refering a data-structure member. e.g. ./perf probe --add 'vfs_read file->f_mode' Add new event: probe:vfs_read (on vfs_read with f_mode=file->f_mode) This probe records file->f_mode, but the argument name becomes "f_mode". This enables perf-trace command to parse trace event format correctly. Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Frederic Weisbecker LKML-Reference: <20100412171700.3790.72961.stgit@localhost6.localdomain6> Signed-off-by: Masami Hiramatsu Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt index e36ed4d..441324f2 100644 --- a/tools/perf/Documentation/perf-probe.txt +++ b/tools/perf/Documentation/perf-probe.txt @@ -87,7 +87,7 @@ Each probe argument follows below syntax. [NAME=]LOCALVAR|$retval|%REG|@SYMBOL -'NAME' specifies the name of this argument (optional). You can use the name of local variable, local data structure member (e.g. var->field, var.field2), or kprobe-tracer argument format (e.g. $retval, %ax, etc). +'NAME' specifies the name of this argument (optional). You can use the name of local variable, local data structure member (e.g. var->field, var.field2), or kprobe-tracer argument format (e.g. $retval, %ax, etc). Note that the name of this argument will be set as the last member name if you specify a local data structure member (e.g. field2 for 'var->field1.field2'.) LINE SYNTAX ----------- diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index ab6f53d..19de8b7 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -481,6 +481,10 @@ static void parse_perf_probe_arg(const char *str, struct perf_probe_arg *arg) } while (tmp); (*fieldp)->name = xstrdup(str); pr_debug("%s(%d)\n", (*fieldp)->name, (*fieldp)->ref); + + /* If no name is specified, set the last field name */ + if (!arg->name) + arg->name = xstrdup((*fieldp)->name); } /* Parse perf-probe event command */ -- cgit v0.10.2 From 93ccae7a2227466a0d071fe52c51319f2f34c365 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Mon, 12 Apr 2010 13:17:08 -0400 Subject: tracing/kprobes: Support basic types on dynamic events Support basic types of integer (u8, u16, u32, u64, s8, s16, s32, s64) in kprobe tracer. With this patch, users can specify above basic types on each arguments after ':'. If omitted, the argument type is set as unsigned long (u32 or u64, arch-dependent). e.g. echo 'p account_system_time+0 hardirq_offset=%si:s32' > kprobe_events adds a probe recording hardirq_offset in signed-32bits value on the entry of account_system_time. Cc: Ingo Molnar Cc: Steven Rostedt Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Frederic Weisbecker LKML-Reference: <20100412171708.3790.18599.stgit@localhost6.localdomain6> Signed-off-by: Masami Hiramatsu Signed-off-by: Arnaldo Carvalho de Melo diff --git a/Documentation/trace/kprobetrace.txt b/Documentation/trace/kprobetrace.txt index a9100b2..ec94748 100644 --- a/Documentation/trace/kprobetrace.txt +++ b/Documentation/trace/kprobetrace.txt @@ -40,7 +40,9 @@ Synopsis of kprobe_events $stack : Fetch stack address. $retval : Fetch return value.(*) +|-offs(FETCHARG) : Fetch memory at FETCHARG +|- offs address.(**) - NAME=FETCHARG: Set NAME as the argument name of FETCHARG. + NAME=FETCHARG : Set NAME as the argument name of FETCHARG. + FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types + (u8/u16/u32/u64/s8/s16/s32/s64) are supported. (*) only for return probe. (**) this is useful for fetching a field of data structures. diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index bec2c97..3ebdb6b 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -102,29 +102,17 @@ struct syscall_trace_exit { long ret; }; -struct kprobe_trace_entry { +struct kprobe_trace_entry_head { struct trace_entry ent; unsigned long ip; - int nargs; - unsigned long args[]; }; -#define SIZEOF_KPROBE_TRACE_ENTRY(n) \ - (offsetof(struct kprobe_trace_entry, args) + \ - (sizeof(unsigned long) * (n))) - -struct kretprobe_trace_entry { +struct kretprobe_trace_entry_head { struct trace_entry ent; unsigned long func; unsigned long ret_ip; - int nargs; - unsigned long args[]; }; -#define SIZEOF_KRETPROBE_TRACE_ENTRY(n) \ - (offsetof(struct kretprobe_trace_entry, args) + \ - (sizeof(unsigned long) * (n))) - /* * trace_flag_type is an enumeration that holds different * states when a trace occurs. These are: diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 1251e36..a751432 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include "trace.h" #include "trace_output.h" @@ -40,7 +42,6 @@ /* Reserved field names */ #define FIELD_STRING_IP "__probe_ip" -#define FIELD_STRING_NARGS "__probe_nargs" #define FIELD_STRING_RETIP "__probe_ret_ip" #define FIELD_STRING_FUNC "__probe_func" @@ -52,56 +53,102 @@ const char *reserved_field_names[] = { "common_tgid", "common_lock_depth", FIELD_STRING_IP, - FIELD_STRING_NARGS, FIELD_STRING_RETIP, FIELD_STRING_FUNC, }; -struct fetch_func { - unsigned long (*func)(struct pt_regs *, void *); +/* Printing function type */ +typedef int (*print_type_func_t)(struct trace_seq *, const char *, void *); +#define PRINT_TYPE_FUNC_NAME(type) print_type_##type +#define PRINT_TYPE_FMT_NAME(type) print_type_format_##type + +/* Printing in basic type function template */ +#define DEFINE_BASIC_PRINT_TYPE_FUNC(type, fmt, cast) \ +static __kprobes int PRINT_TYPE_FUNC_NAME(type)(struct trace_seq *s, \ + const char *name, void *data)\ +{ \ + return trace_seq_printf(s, " %s=" fmt, name, (cast)*(type *)data);\ +} \ +static const char PRINT_TYPE_FMT_NAME(type)[] = fmt; + +DEFINE_BASIC_PRINT_TYPE_FUNC(u8, "%x", unsigned int) +DEFINE_BASIC_PRINT_TYPE_FUNC(u16, "%x", unsigned int) +DEFINE_BASIC_PRINT_TYPE_FUNC(u32, "%lx", unsigned long) +DEFINE_BASIC_PRINT_TYPE_FUNC(u64, "%llx", unsigned long long) +DEFINE_BASIC_PRINT_TYPE_FUNC(s8, "%d", int) +DEFINE_BASIC_PRINT_TYPE_FUNC(s16, "%d", int) +DEFINE_BASIC_PRINT_TYPE_FUNC(s32, "%ld", long) +DEFINE_BASIC_PRINT_TYPE_FUNC(s64, "%lld", long long) + +/* Data fetch function type */ +typedef void (*fetch_func_t)(struct pt_regs *, void *, void *); + +struct fetch_param { + fetch_func_t fn; void *data; }; -static __kprobes unsigned long call_fetch(struct fetch_func *f, - struct pt_regs *regs) +static __kprobes void call_fetch(struct fetch_param *fprm, + struct pt_regs *regs, void *dest) { - return f->func(regs, f->data); + return fprm->fn(regs, fprm->data, dest); } -/* fetch handlers */ -static __kprobes unsigned long fetch_register(struct pt_regs *regs, - void *offset) -{ - return regs_get_register(regs, (unsigned int)((unsigned long)offset)); +#define FETCH_FUNC_NAME(kind, type) fetch_##kind##_##type +/* + * Define macro for basic types - we don't need to define s* types, because + * we have to care only about bitwidth at recording time. + */ +#define DEFINE_BASIC_FETCH_FUNCS(kind) \ +DEFINE_FETCH_##kind(u8) \ +DEFINE_FETCH_##kind(u16) \ +DEFINE_FETCH_##kind(u32) \ +DEFINE_FETCH_##kind(u64) + +#define CHECK_BASIC_FETCH_FUNCS(kind, fn) \ + ((FETCH_FUNC_NAME(kind, u8) == fn) || \ + (FETCH_FUNC_NAME(kind, u16) == fn) || \ + (FETCH_FUNC_NAME(kind, u32) == fn) || \ + (FETCH_FUNC_NAME(kind, u64) == fn)) + +/* Data fetch function templates */ +#define DEFINE_FETCH_reg(type) \ +static __kprobes void FETCH_FUNC_NAME(reg, type)(struct pt_regs *regs, \ + void *offset, void *dest) \ +{ \ + *(type *)dest = (type)regs_get_register(regs, \ + (unsigned int)((unsigned long)offset)); \ } - -static __kprobes unsigned long fetch_stack(struct pt_regs *regs, - void *num) -{ - return regs_get_kernel_stack_nth(regs, - (unsigned int)((unsigned long)num)); +DEFINE_BASIC_FETCH_FUNCS(reg) + +#define DEFINE_FETCH_stack(type) \ +static __kprobes void FETCH_FUNC_NAME(stack, type)(struct pt_regs *regs,\ + void *offset, void *dest) \ +{ \ + *(type *)dest = (type)regs_get_kernel_stack_nth(regs, \ + (unsigned int)((unsigned long)offset)); \ } +DEFINE_BASIC_FETCH_FUNCS(stack) -static __kprobes unsigned long fetch_memory(struct pt_regs *regs, void *addr) -{ - unsigned long retval; - - if (probe_kernel_address(addr, retval)) - return 0; - return retval; +#define DEFINE_FETCH_retval(type) \ +static __kprobes void FETCH_FUNC_NAME(retval, type)(struct pt_regs *regs,\ + void *dummy, void *dest) \ +{ \ + *(type *)dest = (type)regs_return_value(regs); \ } - -static __kprobes unsigned long fetch_retvalue(struct pt_regs *regs, - void *dummy) -{ - return regs_return_value(regs); -} - -static __kprobes unsigned long fetch_stack_address(struct pt_regs *regs, - void *dummy) -{ - return kernel_stack_pointer(regs); +DEFINE_BASIC_FETCH_FUNCS(retval) + +#define DEFINE_FETCH_memory(type) \ +static __kprobes void FETCH_FUNC_NAME(memory, type)(struct pt_regs *regs,\ + void *addr, void *dest) \ +{ \ + type retval; \ + if (probe_kernel_address(addr, retval)) \ + *(type *)dest = 0; \ + else \ + *(type *)dest = retval; \ } +DEFINE_BASIC_FETCH_FUNCS(memory) /* Memory fetching by symbol */ struct symbol_cache { @@ -145,51 +192,126 @@ static struct symbol_cache *alloc_symbol_cache(const char *sym, long offset) return sc; } -static __kprobes unsigned long fetch_symbol(struct pt_regs *regs, void *data) -{ - struct symbol_cache *sc = data; - - if (sc->addr) - return fetch_memory(regs, (void *)sc->addr); - else - return 0; +#define DEFINE_FETCH_symbol(type) \ +static __kprobes void FETCH_FUNC_NAME(symbol, type)(struct pt_regs *regs,\ + void *data, void *dest) \ +{ \ + struct symbol_cache *sc = data; \ + if (sc->addr) \ + fetch_memory_##type(regs, (void *)sc->addr, dest); \ + else \ + *(type *)dest = 0; \ } +DEFINE_BASIC_FETCH_FUNCS(symbol) -/* Special indirect memory access interface */ -struct indirect_fetch_data { - struct fetch_func orig; +/* Dereference memory access function */ +struct deref_fetch_param { + struct fetch_param orig; long offset; }; -static __kprobes unsigned long fetch_indirect(struct pt_regs *regs, void *data) -{ - struct indirect_fetch_data *ind = data; - unsigned long addr; - - addr = call_fetch(&ind->orig, regs); - if (addr) { - addr += ind->offset; - return fetch_memory(regs, (void *)addr); - } else - return 0; +#define DEFINE_FETCH_deref(type) \ +static __kprobes void FETCH_FUNC_NAME(deref, type)(struct pt_regs *regs,\ + void *data, void *dest) \ +{ \ + struct deref_fetch_param *dprm = data; \ + unsigned long addr; \ + call_fetch(&dprm->orig, regs, &addr); \ + if (addr) { \ + addr += dprm->offset; \ + fetch_memory_##type(regs, (void *)addr, dest); \ + } else \ + *(type *)dest = 0; \ } +DEFINE_BASIC_FETCH_FUNCS(deref) -static __kprobes void free_indirect_fetch_data(struct indirect_fetch_data *data) +static __kprobes void free_deref_fetch_param(struct deref_fetch_param *data) { - if (data->orig.func == fetch_indirect) - free_indirect_fetch_data(data->orig.data); - else if (data->orig.func == fetch_symbol) + if (CHECK_BASIC_FETCH_FUNCS(deref, data->orig.fn)) + free_deref_fetch_param(data->orig.data); + else if (CHECK_BASIC_FETCH_FUNCS(symbol, data->orig.fn)) free_symbol_cache(data->orig.data); kfree(data); } +/* Default (unsigned long) fetch type */ +#define __DEFAULT_FETCH_TYPE(t) u##t +#define _DEFAULT_FETCH_TYPE(t) __DEFAULT_FETCH_TYPE(t) +#define DEFAULT_FETCH_TYPE _DEFAULT_FETCH_TYPE(BITS_PER_LONG) +#define DEFAULT_FETCH_TYPE_STR __stringify(DEFAULT_FETCH_TYPE) + +#define ASSIGN_FETCH_FUNC(kind, type) \ + .kind = FETCH_FUNC_NAME(kind, type) + +#define ASSIGN_FETCH_TYPE(ptype, ftype, sign) \ + {.name = #ptype, \ + .size = sizeof(ftype), \ + .is_signed = sign, \ + .print = PRINT_TYPE_FUNC_NAME(ptype), \ + .fmt = PRINT_TYPE_FMT_NAME(ptype), \ +ASSIGN_FETCH_FUNC(reg, ftype), \ +ASSIGN_FETCH_FUNC(stack, ftype), \ +ASSIGN_FETCH_FUNC(retval, ftype), \ +ASSIGN_FETCH_FUNC(memory, ftype), \ +ASSIGN_FETCH_FUNC(symbol, ftype), \ +ASSIGN_FETCH_FUNC(deref, ftype), \ + } + +/* Fetch type information table */ +static const struct fetch_type { + const char *name; /* Name of type */ + size_t size; /* Byte size of type */ + int is_signed; /* Signed flag */ + print_type_func_t print; /* Print functions */ + const char *fmt; /* Fromat string */ + /* Fetch functions */ + fetch_func_t reg; + fetch_func_t stack; + fetch_func_t retval; + fetch_func_t memory; + fetch_func_t symbol; + fetch_func_t deref; +} fetch_type_table[] = { + ASSIGN_FETCH_TYPE(u8, u8, 0), + ASSIGN_FETCH_TYPE(u16, u16, 0), + ASSIGN_FETCH_TYPE(u32, u32, 0), + ASSIGN_FETCH_TYPE(u64, u64, 0), + ASSIGN_FETCH_TYPE(s8, u8, 1), + ASSIGN_FETCH_TYPE(s16, u16, 1), + ASSIGN_FETCH_TYPE(s32, u32, 1), + ASSIGN_FETCH_TYPE(s64, u64, 1), +}; + +static const struct fetch_type *find_fetch_type(const char *type) +{ + int i; + + if (!type) + type = DEFAULT_FETCH_TYPE_STR; + + for (i = 0; i < ARRAY_SIZE(fetch_type_table); i++) + if (strcmp(type, fetch_type_table[i].name) == 0) + return &fetch_type_table[i]; + return NULL; +} + +/* Special function : only accept unsigned long */ +static __kprobes void fetch_stack_address(struct pt_regs *regs, + void *dummy, void *dest) +{ + *(unsigned long *)dest = kernel_stack_pointer(regs); +} + /** * Kprobe event core functions */ struct probe_arg { - struct fetch_func fetch; - const char *name; + struct fetch_param fetch; + unsigned int offset; /* Offset from argument entry */ + const char *name; /* Name of this argument */ + const char *comm; /* Command of this argument */ + const struct fetch_type *type; /* Type of this argument */ }; /* Flags for trace_probe */ @@ -204,6 +326,7 @@ struct trace_probe { const char *symbol; /* symbol name */ struct ftrace_event_call call; struct trace_event event; + ssize_t size; /* trace entry size */ unsigned int nr_args; struct probe_arg args[]; }; @@ -212,6 +335,7 @@ struct trace_probe { (offsetof(struct trace_probe, args) + \ (sizeof(struct probe_arg) * (n))) + static __kprobes int probe_is_return(struct trace_probe *tp) { return tp->rp.handler != NULL; @@ -222,49 +346,6 @@ static __kprobes const char *probe_symbol(struct trace_probe *tp) return tp->symbol ? tp->symbol : "unknown"; } -static int probe_arg_string(char *buf, size_t n, struct fetch_func *ff) -{ - int ret = -EINVAL; - - if (ff->func == fetch_register) { - const char *name; - name = regs_query_register_name((unsigned int)((long)ff->data)); - ret = snprintf(buf, n, "%%%s", name); - } else if (ff->func == fetch_stack) - ret = snprintf(buf, n, "$stack%lu", (unsigned long)ff->data); - else if (ff->func == fetch_memory) - ret = snprintf(buf, n, "@0x%p", ff->data); - else if (ff->func == fetch_symbol) { - struct symbol_cache *sc = ff->data; - if (sc->offset) - ret = snprintf(buf, n, "@%s%+ld", sc->symbol, - sc->offset); - else - ret = snprintf(buf, n, "@%s", sc->symbol); - } else if (ff->func == fetch_retvalue) - ret = snprintf(buf, n, "$retval"); - else if (ff->func == fetch_stack_address) - ret = snprintf(buf, n, "$stack"); - else if (ff->func == fetch_indirect) { - struct indirect_fetch_data *id = ff->data; - size_t l = 0; - ret = snprintf(buf, n, "%+ld(", id->offset); - if (ret >= n) - goto end; - l += ret; - ret = probe_arg_string(buf + l, n - l, &id->orig); - if (ret < 0) - goto end; - l += ret; - ret = snprintf(buf + l, n - l, ")"); - ret += l; - } -end: - if (ret >= n) - return -ENOSPC; - return ret; -} - static int register_probe_event(struct trace_probe *tp); static void unregister_probe_event(struct trace_probe *tp); @@ -347,11 +428,12 @@ error: static void free_probe_arg(struct probe_arg *arg) { - if (arg->fetch.func == fetch_symbol) + if (CHECK_BASIC_FETCH_FUNCS(deref, arg->fetch.fn)) + free_deref_fetch_param(arg->fetch.data); + else if (CHECK_BASIC_FETCH_FUNCS(symbol, arg->fetch.fn)) free_symbol_cache(arg->fetch.data); - else if (arg->fetch.func == fetch_indirect) - free_indirect_fetch_data(arg->fetch.data); kfree(arg->name); + kfree(arg->comm); } static void free_trace_probe(struct trace_probe *tp) @@ -457,28 +539,30 @@ static int split_symbol_offset(char *symbol, unsigned long *offset) #define PARAM_MAX_ARGS 16 #define PARAM_MAX_STACK (THREAD_SIZE / sizeof(unsigned long)) -static int parse_probe_vars(char *arg, struct fetch_func *ff, int is_return) +static int parse_probe_vars(char *arg, const struct fetch_type *t, + struct fetch_param *f, int is_return) { int ret = 0; unsigned long param; if (strcmp(arg, "retval") == 0) { - if (is_return) { - ff->func = fetch_retvalue; - ff->data = NULL; - } else + if (is_return) + f->fn = t->retval; + else ret = -EINVAL; } else if (strncmp(arg, "stack", 5) == 0) { if (arg[5] == '\0') { - ff->func = fetch_stack_address; - ff->data = NULL; + if (strcmp(t->name, DEFAULT_FETCH_TYPE_STR) == 0) + f->fn = fetch_stack_address; + else + ret = -EINVAL; } else if (isdigit(arg[5])) { ret = strict_strtoul(arg + 5, 10, ¶m); if (ret || param > PARAM_MAX_STACK) ret = -EINVAL; else { - ff->func = fetch_stack; - ff->data = (void *)param; + f->fn = t->stack; + f->data = (void *)param; } } else ret = -EINVAL; @@ -488,7 +572,8 @@ static int parse_probe_vars(char *arg, struct fetch_func *ff, int is_return) } /* Recursive argument parser */ -static int __parse_probe_arg(char *arg, struct fetch_func *ff, int is_return) +static int __parse_probe_arg(char *arg, const struct fetch_type *t, + struct fetch_param *f, int is_return) { int ret = 0; unsigned long param; @@ -497,13 +582,13 @@ static int __parse_probe_arg(char *arg, struct fetch_func *ff, int is_return) switch (arg[0]) { case '$': - ret = parse_probe_vars(arg + 1, ff, is_return); + ret = parse_probe_vars(arg + 1, t, f, is_return); break; case '%': /* named register */ ret = regs_query_register_offset(arg + 1); if (ret >= 0) { - ff->func = fetch_register; - ff->data = (void *)(unsigned long)ret; + f->fn = t->reg; + f->data = (void *)(unsigned long)ret; ret = 0; } break; @@ -512,26 +597,22 @@ static int __parse_probe_arg(char *arg, struct fetch_func *ff, int is_return) ret = strict_strtoul(arg + 1, 0, ¶m); if (ret) break; - ff->func = fetch_memory; - ff->data = (void *)param; + f->fn = t->memory; + f->data = (void *)param; } else { ret = split_symbol_offset(arg + 1, &offset); if (ret) break; - ff->data = alloc_symbol_cache(arg + 1, offset); - if (ff->data) - ff->func = fetch_symbol; - else - ret = -EINVAL; + f->data = alloc_symbol_cache(arg + 1, offset); + if (f->data) + f->fn = t->symbol; } break; - case '+': /* indirect memory */ + case '+': /* deref memory */ case '-': tmp = strchr(arg, '('); - if (!tmp) { - ret = -EINVAL; + if (!tmp) break; - } *tmp = '\0'; ret = strict_strtol(arg + 1, 0, &offset); if (ret) @@ -541,38 +622,58 @@ static int __parse_probe_arg(char *arg, struct fetch_func *ff, int is_return) arg = tmp + 1; tmp = strrchr(arg, ')'); if (tmp) { - struct indirect_fetch_data *id; + struct deref_fetch_param *dprm; + const struct fetch_type *t2 = find_fetch_type(NULL); *tmp = '\0'; - id = kzalloc(sizeof(struct indirect_fetch_data), - GFP_KERNEL); - if (!id) + dprm = kzalloc(sizeof(struct deref_fetch_param), + GFP_KERNEL); + if (!dprm) return -ENOMEM; - id->offset = offset; - ret = __parse_probe_arg(arg, &id->orig, is_return); + dprm->offset = offset; + ret = __parse_probe_arg(arg, t2, &dprm->orig, + is_return); if (ret) - kfree(id); + kfree(dprm); else { - ff->func = fetch_indirect; - ff->data = (void *)id; + f->fn = t->deref; + f->data = (void *)dprm; } - } else - ret = -EINVAL; + } break; - default: - /* TODO: support custom handler */ - ret = -EINVAL; } + if (!ret && !f->fn) + ret = -EINVAL; return ret; } /* String length checking wrapper */ -static int parse_probe_arg(char *arg, struct fetch_func *ff, int is_return) +static int parse_probe_arg(char *arg, struct trace_probe *tp, + struct probe_arg *parg, int is_return) { + const char *t; + if (strlen(arg) > MAX_ARGSTR_LEN) { pr_info("Argument is too long.: %s\n", arg); return -ENOSPC; } - return __parse_probe_arg(arg, ff, is_return); + parg->comm = kstrdup(arg, GFP_KERNEL); + if (!parg->comm) { + pr_info("Failed to allocate memory for command '%s'.\n", arg); + return -ENOMEM; + } + t = strchr(parg->comm, ':'); + if (t) { + arg[t - parg->comm] = '\0'; + t++; + } + parg->type = find_fetch_type(t); + if (!parg->type) { + pr_info("Unsupported type: %s\n", t); + return -EINVAL; + } + parg->offset = tp->size; + tp->size += parg->type->size; + return __parse_probe_arg(arg, parg->type, &parg->fetch, is_return); } /* Return 1 if name is reserved or already used by another argument */ @@ -602,15 +703,18 @@ static int create_trace_probe(int argc, char **argv) * @ADDR : fetch memory at ADDR (ADDR should be in kernel) * @SYM[+|-offs] : fetch memory at SYM +|- offs (SYM is a data symbol) * %REG : fetch register REG - * Indirect memory fetch: + * Dereferencing memory fetch: * +|-offs(ARG) : fetch memory at ARG +|- offs address. * Alias name of args: * NAME=FETCHARG : set NAME as alias of FETCHARG. + * Type of args: + * FETCHARG:TYPE : use TYPE instead of unsigned long. */ struct trace_probe *tp; int i, ret = 0; int is_return = 0, is_delete = 0; - char *symbol = NULL, *event = NULL, *arg = NULL, *group = NULL; + char *symbol = NULL, *event = NULL, *group = NULL; + char *arg, *tmp; unsigned long offset = 0; void *addr = NULL; char buf[MAX_EVENT_NAME_LEN]; @@ -723,13 +827,6 @@ static int create_trace_probe(int argc, char **argv) else arg = argv[i]; - if (conflict_field_name(argv[i], tp->args, i)) { - pr_info("Argument%d name '%s' conflicts with " - "another field.\n", i, argv[i]); - ret = -EINVAL; - goto error; - } - tp->args[i].name = kstrdup(argv[i], GFP_KERNEL); if (!tp->args[i].name) { pr_info("Failed to allocate argument%d name '%s'.\n", @@ -737,9 +834,19 @@ static int create_trace_probe(int argc, char **argv) ret = -ENOMEM; goto error; } + tmp = strchr(tp->args[i].name, ':'); + if (tmp) + *tmp = '_'; /* convert : to _ */ + + if (conflict_field_name(tp->args[i].name, tp->args, i)) { + pr_info("Argument%d name '%s' conflicts with " + "another field.\n", i, argv[i]); + ret = -EINVAL; + goto error; + } /* Parse fetch argument */ - ret = parse_probe_arg(arg, &tp->args[i].fetch, is_return); + ret = parse_probe_arg(arg, tp, &tp->args[i], is_return); if (ret) { pr_info("Parse error at argument%d. (%d)\n", i, ret); kfree(tp->args[i].name); @@ -794,8 +901,7 @@ static void probes_seq_stop(struct seq_file *m, void *v) static int probes_seq_show(struct seq_file *m, void *v) { struct trace_probe *tp = v; - int i, ret; - char buf[MAX_ARGSTR_LEN + 1]; + int i; seq_printf(m, "%c", probe_is_return(tp) ? 'r' : 'p'); seq_printf(m, ":%s/%s", tp->call.system, tp->call.name); @@ -807,15 +913,10 @@ static int probes_seq_show(struct seq_file *m, void *v) else seq_printf(m, " %s", probe_symbol(tp)); - for (i = 0; i < tp->nr_args; i++) { - ret = probe_arg_string(buf, MAX_ARGSTR_LEN, &tp->args[i].fetch); - if (ret < 0) { - pr_warning("Argument%d decoding error(%d).\n", i, ret); - return ret; - } - seq_printf(m, " %s=%s", tp->args[i].name, buf); - } + for (i = 0; i < tp->nr_args; i++) + seq_printf(m, " %s=%s", tp->args[i].name, tp->args[i].comm); seq_printf(m, "\n"); + return 0; } @@ -945,9 +1046,10 @@ static const struct file_operations kprobe_profile_ops = { static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) { struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp); - struct kprobe_trace_entry *entry; + struct kprobe_trace_entry_head *entry; struct ring_buffer_event *event; struct ring_buffer *buffer; + u8 *data; int size, i, pc; unsigned long irq_flags; struct ftrace_event_call *call = &tp->call; @@ -957,7 +1059,7 @@ static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) local_save_flags(irq_flags); pc = preempt_count(); - size = SIZEOF_KPROBE_TRACE_ENTRY(tp->nr_args); + size = sizeof(*entry) + tp->size; event = trace_current_buffer_lock_reserve(&buffer, call->id, size, irq_flags, pc); @@ -965,10 +1067,10 @@ static __kprobes void kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs) return; entry = ring_buffer_event_data(event); - entry->nargs = tp->nr_args; entry->ip = (unsigned long)kp->addr; + data = (u8 *)&entry[1]; for (i = 0; i < tp->nr_args; i++) - entry->args[i] = call_fetch(&tp->args[i].fetch, regs); + call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset); if (!filter_current_check_discard(buffer, call, entry, event)) trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc); @@ -979,9 +1081,10 @@ static __kprobes void kretprobe_trace_func(struct kretprobe_instance *ri, struct pt_regs *regs) { struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp); - struct kretprobe_trace_entry *entry; + struct kretprobe_trace_entry_head *entry; struct ring_buffer_event *event; struct ring_buffer *buffer; + u8 *data; int size, i, pc; unsigned long irq_flags; struct ftrace_event_call *call = &tp->call; @@ -989,7 +1092,7 @@ static __kprobes void kretprobe_trace_func(struct kretprobe_instance *ri, local_save_flags(irq_flags); pc = preempt_count(); - size = SIZEOF_KRETPROBE_TRACE_ENTRY(tp->nr_args); + size = sizeof(*entry) + tp->size; event = trace_current_buffer_lock_reserve(&buffer, call->id, size, irq_flags, pc); @@ -997,11 +1100,11 @@ static __kprobes void kretprobe_trace_func(struct kretprobe_instance *ri, return; entry = ring_buffer_event_data(event); - entry->nargs = tp->nr_args; entry->func = (unsigned long)tp->rp.kp.addr; entry->ret_ip = (unsigned long)ri->ret_addr; + data = (u8 *)&entry[1]; for (i = 0; i < tp->nr_args; i++) - entry->args[i] = call_fetch(&tp->args[i].fetch, regs); + call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset); if (!filter_current_check_discard(buffer, call, entry, event)) trace_nowake_buffer_unlock_commit(buffer, event, irq_flags, pc); @@ -1011,13 +1114,14 @@ static __kprobes void kretprobe_trace_func(struct kretprobe_instance *ri, enum print_line_t print_kprobe_event(struct trace_iterator *iter, int flags) { - struct kprobe_trace_entry *field; + struct kprobe_trace_entry_head *field; struct trace_seq *s = &iter->seq; struct trace_event *event; struct trace_probe *tp; + u8 *data; int i; - field = (struct kprobe_trace_entry *)iter->ent; + field = (struct kprobe_trace_entry_head *)iter->ent; event = ftrace_find_event(field->ent.type); tp = container_of(event, struct trace_probe, event); @@ -1030,9 +1134,10 @@ print_kprobe_event(struct trace_iterator *iter, int flags) if (!trace_seq_puts(s, ")")) goto partial; - for (i = 0; i < field->nargs; i++) - if (!trace_seq_printf(s, " %s=%lx", - tp->args[i].name, field->args[i])) + data = (u8 *)&field[1]; + for (i = 0; i < tp->nr_args; i++) + if (!tp->args[i].type->print(s, tp->args[i].name, + data + tp->args[i].offset)) goto partial; if (!trace_seq_puts(s, "\n")) @@ -1046,13 +1151,14 @@ partial: enum print_line_t print_kretprobe_event(struct trace_iterator *iter, int flags) { - struct kretprobe_trace_entry *field; + struct kretprobe_trace_entry_head *field; struct trace_seq *s = &iter->seq; struct trace_event *event; struct trace_probe *tp; + u8 *data; int i; - field = (struct kretprobe_trace_entry *)iter->ent; + field = (struct kretprobe_trace_entry_head *)iter->ent; event = ftrace_find_event(field->ent.type); tp = container_of(event, struct trace_probe, event); @@ -1071,9 +1177,10 @@ print_kretprobe_event(struct trace_iterator *iter, int flags) if (!trace_seq_puts(s, ")")) goto partial; - for (i = 0; i < field->nargs; i++) - if (!trace_seq_printf(s, " %s=%lx", - tp->args[i].name, field->args[i])) + data = (u8 *)&field[1]; + for (i = 0; i < tp->nr_args; i++) + if (!tp->args[i].type->print(s, tp->args[i].name, + data + tp->args[i].offset)) goto partial; if (!trace_seq_puts(s, "\n")) @@ -1129,29 +1236,43 @@ static int probe_event_raw_init(struct ftrace_event_call *event_call) static int kprobe_event_define_fields(struct ftrace_event_call *event_call) { int ret, i; - struct kprobe_trace_entry field; + struct kprobe_trace_entry_head field; struct trace_probe *tp = (struct trace_probe *)event_call->data; DEFINE_FIELD(unsigned long, ip, FIELD_STRING_IP, 0); - DEFINE_FIELD(int, nargs, FIELD_STRING_NARGS, 1); /* Set argument names as fields */ - for (i = 0; i < tp->nr_args; i++) - DEFINE_FIELD(unsigned long, args[i], tp->args[i].name, 0); + for (i = 0; i < tp->nr_args; i++) { + ret = trace_define_field(event_call, tp->args[i].type->name, + tp->args[i].name, + sizeof(field) + tp->args[i].offset, + tp->args[i].type->size, + tp->args[i].type->is_signed, + FILTER_OTHER); + if (ret) + return ret; + } return 0; } static int kretprobe_event_define_fields(struct ftrace_event_call *event_call) { int ret, i; - struct kretprobe_trace_entry field; + struct kretprobe_trace_entry_head field; struct trace_probe *tp = (struct trace_probe *)event_call->data; DEFINE_FIELD(unsigned long, func, FIELD_STRING_FUNC, 0); DEFINE_FIELD(unsigned long, ret_ip, FIELD_STRING_RETIP, 0); - DEFINE_FIELD(int, nargs, FIELD_STRING_NARGS, 1); /* Set argument names as fields */ - for (i = 0; i < tp->nr_args; i++) - DEFINE_FIELD(unsigned long, args[i], tp->args[i].name, 0); + for (i = 0; i < tp->nr_args; i++) { + ret = trace_define_field(event_call, tp->args[i].type->name, + tp->args[i].name, + sizeof(field) + tp->args[i].offset, + tp->args[i].type->size, + tp->args[i].type->is_signed, + FILTER_OTHER); + if (ret) + return ret; + } return 0; } @@ -1176,8 +1297,8 @@ static int __set_print_fmt(struct trace_probe *tp, char *buf, int len) pos += snprintf(buf + pos, LEN_OR_ZERO, "\"%s", fmt); for (i = 0; i < tp->nr_args; i++) { - pos += snprintf(buf + pos, LEN_OR_ZERO, " %s=%%lx", - tp->args[i].name); + pos += snprintf(buf + pos, LEN_OR_ZERO, " %s=%s", + tp->args[i].name, tp->args[i].type->fmt); } pos += snprintf(buf + pos, LEN_OR_ZERO, "\", %s", arg); @@ -1219,12 +1340,13 @@ static __kprobes void kprobe_perf_func(struct kprobe *kp, { struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp); struct ftrace_event_call *call = &tp->call; - struct kprobe_trace_entry *entry; + struct kprobe_trace_entry_head *entry; + u8 *data; int size, __size, i; unsigned long irq_flags; int rctx; - __size = SIZEOF_KPROBE_TRACE_ENTRY(tp->nr_args); + __size = sizeof(*entry) + tp->size; size = ALIGN(__size + sizeof(u32), sizeof(u64)); size -= sizeof(u32); if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, @@ -1235,10 +1357,10 @@ static __kprobes void kprobe_perf_func(struct kprobe *kp, if (!entry) return; - entry->nargs = tp->nr_args; entry->ip = (unsigned long)kp->addr; + data = (u8 *)&entry[1]; for (i = 0; i < tp->nr_args; i++) - entry->args[i] = call_fetch(&tp->args[i].fetch, regs); + call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset); perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, irq_flags, regs); } @@ -1249,12 +1371,13 @@ static __kprobes void kretprobe_perf_func(struct kretprobe_instance *ri, { struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp); struct ftrace_event_call *call = &tp->call; - struct kretprobe_trace_entry *entry; + struct kretprobe_trace_entry_head *entry; + u8 *data; int size, __size, i; unsigned long irq_flags; int rctx; - __size = SIZEOF_KRETPROBE_TRACE_ENTRY(tp->nr_args); + __size = sizeof(*entry) + tp->size; size = ALIGN(__size + sizeof(u32), sizeof(u64)); size -= sizeof(u32); if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, @@ -1265,11 +1388,11 @@ static __kprobes void kretprobe_perf_func(struct kretprobe_instance *ri, if (!entry) return; - entry->nargs = tp->nr_args; entry->func = (unsigned long)tp->rp.kp.addr; entry->ret_ip = (unsigned long)ri->ret_addr; + data = (u8 *)&entry[1]; for (i = 0; i < tp->nr_args; i++) - entry->args[i] = call_fetch(&tp->args[i].fetch, regs); + call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset); perf_trace_buf_submit(entry, size, rctx, entry->ret_ip, 1, irq_flags, regs); -- cgit v0.10.2 From 4984912eb23113a4007940cd09c8351c0623ea5f Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Mon, 12 Apr 2010 13:17:15 -0400 Subject: perf probe: Query basic types from debuginfo Query the basic type information (byte-size and signed-flag) from debuginfo and pass that to kprobe-tracer. This is especially useful for tracing the members of data structure, because each member has different byte-size on the memory. Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Frederic Weisbecker LKML-Reference: <20100412171715.3790.23730.stgit@localhost6.localdomain6> Signed-off-by: Masami Hiramatsu Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 19de8b7..05ca4a9 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -740,6 +740,13 @@ static int synthesize_kprobe_trace_arg(struct kprobe_trace_arg *arg, buf += ret; buflen -= ret; } + /* Print argument type */ + if (arg->type) { + ret = e_snprintf(buf, buflen, ":%s", arg->type); + if (ret <= 0) + return ret; + buf += ret; + } return buf - tmp; } @@ -848,6 +855,8 @@ void clear_kprobe_trace_event(struct kprobe_trace_event *tev) free(tev->args[i].name); if (tev->args[i].value) free(tev->args[i].value); + if (tev->args[i].type) + free(tev->args[i].type); ref = tev->args[i].ref; while (ref) { next = ref->next; diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h index 10411f5..a393a3f 100644 --- a/tools/perf/util/probe-event.h +++ b/tools/perf/util/probe-event.h @@ -23,6 +23,7 @@ struct kprobe_trace_arg_ref { struct kprobe_trace_arg { char *name; /* Argument name */ char *value; /* Base value */ + char *type; /* Type name */ struct kprobe_trace_arg_ref *ref; /* Referencing offset */ }; diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 105e95c..ebeb413 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -84,6 +84,9 @@ const char *x86_64_regs_table[X86_64_MAX_REGS] = { #define arch_regs_table x86_32_regs_table #endif +/* Kprobe tracer basic type is up to u64 */ +#define MAX_BASIC_TYPE_BITS 64 + /* Return architecture dependent register string (for kprobe-tracer) */ static const char *get_arch_regstr(unsigned int n) { @@ -230,6 +233,31 @@ static Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem) return die_mem; } +static bool die_is_signed_type(Dwarf_Die *tp_die) +{ + Dwarf_Attribute attr; + Dwarf_Word ret; + + if (dwarf_attr(tp_die, DW_AT_encoding, &attr) == NULL || + dwarf_formudata(&attr, &ret) != 0) + return false; + + return (ret == DW_ATE_signed_char || ret == DW_ATE_signed || + ret == DW_ATE_signed_fixed); +} + +static int die_get_byte_size(Dwarf_Die *tp_die) +{ + Dwarf_Attribute attr; + Dwarf_Word ret; + + if (dwarf_attr(tp_die, DW_AT_byte_size, &attr) == NULL || + dwarf_formudata(&attr, &ret) != 0) + return 0; + + return (int)ret; +} + /* Return values for die_find callbacks */ enum { DIE_FIND_CB_FOUND = 0, /* End of Search */ @@ -406,13 +434,42 @@ static void convert_location(Dwarf_Op *op, struct probe_finder *pf) } } +static void convert_variable_type(Dwarf_Die *vr_die, + struct kprobe_trace_arg *targ) +{ + Dwarf_Die type; + char buf[16]; + int ret; + + if (die_get_real_type(vr_die, &type) == NULL) + die("Failed to get a type information of %s.", + dwarf_diename(vr_die)); + + ret = die_get_byte_size(&type) * 8; + if (ret) { + /* Check the bitwidth */ + if (ret > MAX_BASIC_TYPE_BITS) { + pr_warning(" Warning: %s exceeds max-bitwidth." + " Cut down to %d bits.\n", + dwarf_diename(&type), MAX_BASIC_TYPE_BITS); + ret = MAX_BASIC_TYPE_BITS; + } + + ret = snprintf(buf, 16, "%c%d", + die_is_signed_type(&type) ? 's' : 'u', ret); + if (ret < 0 || ret >= 16) + die("Failed to convert variable type."); + targ->type = xstrdup(buf); + } +} + static void convert_variable_fields(Dwarf_Die *vr_die, const char *varname, struct perf_probe_arg_field *field, - struct kprobe_trace_arg_ref **ref_ptr) + struct kprobe_trace_arg_ref **ref_ptr, + Dwarf_Die *die_mem) { struct kprobe_trace_arg_ref *ref = *ref_ptr; Dwarf_Attribute attr; - Dwarf_Die member; Dwarf_Die type; Dwarf_Word offs; @@ -450,26 +507,27 @@ static void convert_variable_fields(Dwarf_Die *vr_die, const char *varname, die("Structure on a register is not supported yet."); } - if (die_find_member(&type, field->name, &member) == NULL) + if (die_find_member(&type, field->name, die_mem) == NULL) die("%s(tyep:%s) has no member %s.", varname, dwarf_diename(&type), field->name); /* Get the offset of the field */ - if (dwarf_attr(&member, DW_AT_data_member_location, &attr) == NULL || + if (dwarf_attr(die_mem, DW_AT_data_member_location, &attr) == NULL || dwarf_formudata(&attr, &offs) != 0) die("Failed to get the offset of %s.", field->name); ref->offset += (long)offs; /* Converting next field */ if (field->next) - convert_variable_fields(&member, field->name, field->next, - &ref); + convert_variable_fields(die_mem, field->name, field->next, + &ref, die_mem); } /* Show a variables in kprobe event format */ static void convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf) { Dwarf_Attribute attr; + Dwarf_Die die_mem; Dwarf_Op *expr; size_t nexpr; int ret; @@ -483,9 +541,13 @@ static void convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf) convert_location(expr, pf); - if (pf->pvar->field) + if (pf->pvar->field) { convert_variable_fields(vr_die, pf->pvar->var, - pf->pvar->field, &pf->tvar->ref); + pf->pvar->field, &pf->tvar->ref, + &die_mem); + vr_die = &die_mem; + } + convert_variable_type(vr_die, pf->tvar); /* *expr will be cached in libdw. Don't free it. */ return ; error: -- cgit v0.10.2 From 11a1ca3554b377d2a8a318a3cbf8ce10a7a2a8e4 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Mon, 12 Apr 2010 13:17:22 -0400 Subject: perf probe: Support basic type casting Add basic type casting for arguments to perf probe. This allows users to specify the actual type of arguments. Of course, if user sets invalid types, kprobe-tracer rejects that. Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Frederic Weisbecker LKML-Reference: <20100412171722.3790.50372.stgit@localhost6.localdomain6> Signed-off-by: Masami Hiramatsu Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt index 441324f2..63c25d3 100644 --- a/tools/perf/Documentation/perf-probe.txt +++ b/tools/perf/Documentation/perf-probe.txt @@ -85,9 +85,10 @@ PROBE ARGUMENT -------------- Each probe argument follows below syntax. - [NAME=]LOCALVAR|$retval|%REG|@SYMBOL + [NAME=]LOCALVAR|$retval|%REG|@SYMBOL[:TYPE] 'NAME' specifies the name of this argument (optional). You can use the name of local variable, local data structure member (e.g. var->field, var.field2), or kprobe-tracer argument format (e.g. $retval, %ax, etc). Note that the name of this argument will be set as the last member name if you specify a local data structure member (e.g. field2 for 'var->field1.field2'.) +'TYPE' casts the type of this argument (optional). If omitted, perf probe automatically set the type based on debuginfo. LINE SYNTAX ----------- diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 05ca4a9..bef2805 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -435,7 +435,7 @@ static void parse_perf_probe_point(char *arg, struct perf_probe_event *pev) } /* Parse perf-probe event argument */ -static void parse_perf_probe_arg(const char *str, struct perf_probe_arg *arg) +static void parse_perf_probe_arg(char *str, struct perf_probe_arg *arg) { char *tmp; struct perf_probe_arg_field **fieldp; @@ -445,9 +445,17 @@ static void parse_perf_probe_arg(const char *str, struct perf_probe_arg *arg) tmp = strchr(str, '='); if (tmp) { arg->name = xstrndup(str, tmp - str); + pr_debug("name:%s ", arg->name); str = tmp + 1; } + tmp = strchr(str, ':'); + if (tmp) { /* Type setting */ + *tmp = '\0'; + arg->type = xstrdup(tmp + 1); + pr_debug("type:%s ", arg->type); + } + tmp = strpbrk(str, "-."); if (!is_c_varname(str) || !tmp) { /* A variable, register, symbol or special value */ @@ -603,6 +611,15 @@ int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len) len -= ret; field = field->next; } + + if (pa->type) { + ret = e_snprintf(tmp, len, ":%s", pa->type); + if (ret <= 0) + goto error; + tmp += ret; + len -= ret; + } + return tmp - buf; error: die("Failed to synthesize perf probe argument: %s", strerror(-ret)); @@ -825,6 +842,8 @@ void clear_perf_probe_event(struct perf_probe_event *pev) free(pev->args[i].name); if (pev->args[i].var) free(pev->args[i].var); + if (pev->args[i].type) + free(pev->args[i].type); field = pev->args[i].field; while (field) { next = field->next; @@ -1145,6 +1164,8 @@ static int convert_to_kprobe_trace_events(struct perf_probe_event *pev, if (pev->args[i].name) tev->args[i].name = xstrdup(pev->args[i].name); tev->args[i].value = xstrdup(pev->args[i].var); + if (pev->args[i].type) + tev->args[i].type = xstrdup(pev->args[i].type); } } diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h index a393a3f..ff2f26b 100644 --- a/tools/perf/util/probe-event.h +++ b/tools/perf/util/probe-event.h @@ -57,6 +57,7 @@ struct perf_probe_arg_field { struct perf_probe_arg { char *name; /* Argument name */ char *var; /* Variable name */ + char *type; /* Type name */ struct perf_probe_arg_field *field; /* Structure fields */ }; diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index ebeb413..ab47673 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -547,7 +547,10 @@ static void convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf) &die_mem); vr_die = &die_mem; } - convert_variable_type(vr_die, pf->tvar); + if (pf->pvar->type) + pf->tvar->type = xstrdup(pf->pvar->type); + else + convert_variable_type(vr_die, pf->tvar); /* *expr will be cached in libdw. Don't free it. */ return ; error: @@ -560,13 +563,16 @@ error: static void find_variable(Dwarf_Die *sp_die, struct probe_finder *pf) { Dwarf_Die vr_die; - char buf[32]; + char buf[32], *ptr; /* TODO: Support arrays */ if (pf->pvar->name) pf->tvar->name = xstrdup(pf->pvar->name); else { synthesize_perf_probe_arg(pf->pvar, buf, 32); + ptr = strchr(buf, ':'); /* Change type separator to _ */ + if (ptr) + *ptr = '_'; pf->tvar->name = xstrdup(buf); } -- cgit v0.10.2 From a34a985499895a46a4dacff727d0fbc63cdc75e8 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Mon, 12 Apr 2010 13:17:29 -0400 Subject: perf probe: Support DW_OP_call_frame_cfa in debuginfo When building kernel without CONFIG_FRAME_POINTER, gcc uses CFA (canonical frame address) for frame base. With this patch, perf probe just gets CFI (call frame information) from debuginfo and search corresponding CFA from the CFI. IOW, this allows perf probe works correctly on the kernel without CONFIG_FRAME_POINTER. ./perf probe -fn sched_slice:12 lw.weight Fatal: DW_OP 156 is not supported. (^^^ DW_OP_call_frame_cfa) ./perf probe -fn sched_slice:12 lw.weight Add new event: probe:sched_slice (on sched_slice:12 with weight=lw.weight) Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Frederic Weisbecker LKML-Reference: <20100412171728.3790.98217.stgit@localhost6.localdomain6> Signed-off-by: Masami Hiramatsu Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index ab47673..1f45285 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -398,7 +398,6 @@ static void convert_location(Dwarf_Op *op, struct probe_finder *pf) const char *regs; struct kprobe_trace_arg *tvar = pf->tvar; - /* TODO: support CFA */ /* If this is based on frame buffer, set the offset */ if (op->atom == DW_OP_fbreg) { if (pf->fb_ops == NULL) @@ -629,11 +628,17 @@ static void convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf) /* Get the frame base attribute/ops */ dwarf_attr(sp_die, DW_AT_frame_base, &fb_attr); ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1); - if (ret <= 0 || nops == 0) + if (ret <= 0 || nops == 0) { pf->fb_ops = NULL; + } else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa && + pf->cfi != NULL) { + Dwarf_Frame *frame; + ret = dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame); + DIE_IF(ret != 0); + dwarf_frame_cfa(frame, &pf->fb_ops, &nops); + } /* Find each argument */ - /* TODO: use dwarf_cfi_addrframe */ tev->nargs = pf->pev->nargs; tev->args = xzalloc(sizeof(struct kprobe_trace_arg) * tev->nargs); for (i = 0; i < pf->pev->nargs; i++) { @@ -842,6 +847,9 @@ int find_kprobe_trace_events(int fd, struct perf_probe_event *pev, if (!dbg) return -ENOENT; + /* Get the call frame information from this dwarf */ + pf.cfi = dwarf_getcfi(dbg); + off = 0; line_list__init(&pf.lcache); /* Loop on CUs (Compilation Unit) */ diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h index 2a27132..310ce89 100644 --- a/tools/perf/util/probe-finder.h +++ b/tools/perf/util/probe-finder.h @@ -42,6 +42,7 @@ struct probe_finder { struct list_head lcache; /* Line cache for lazy match */ /* For variable searching */ + Dwarf_CFI *cfi; /* Call Frame Information */ Dwarf_Op *fb_ops; /* Frame base attribute */ struct perf_probe_arg *pvar; /* Current target variable */ struct kprobe_trace_arg *tvar; /* Current result variable */ -- cgit v0.10.2 From b55a87ade3839c33ab94768a0b5955734073f987 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Mon, 12 Apr 2010 13:17:35 -0400 Subject: perf probe: Remove die() from probe-finder code Remove die() and DIE_IF() code from util/probe-finder.c since these 'sudden death' in utility functions make reusing it from other code (especially tui/gui) difficult. Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Frederic Weisbecker LKML-Reference: <20100412171735.3790.88853.stgit@localhost6.localdomain6> Signed-off-by: Masami Hiramatsu Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index bef2805..7893b32 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -151,10 +151,10 @@ static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev, /* Error path */ if (need_dwarf) { - if (ntevs == -ENOENT) + if (ntevs == -EBADF) pr_warning("No dwarf info found in the vmlinux - " "please rebuild with CONFIG_DEBUG_INFO=y.\n"); - die("Could not analyze debuginfo."); + die("Failed to analyze debuginfo."); } pr_debug("An error occurred in debuginfo analysis." " Try to use symbols.\n"); diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 1f45285..54daa91 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -196,19 +196,7 @@ static bool die_compare_name(Dwarf_Die *dw_die, const char *tname) { const char *name; name = dwarf_diename(dw_die); - DIE_IF(name == NULL); - return strcmp(tname, name); -} - -/* Get entry pc(or low pc, 1st entry of ranges) of the die */ -static Dwarf_Addr die_get_entrypc(Dwarf_Die *dw_die) -{ - Dwarf_Addr epc; - int ret; - - ret = dwarf_entrypc(dw_die, &epc); - DIE_IF(ret == -1); - return epc; + return name ? strcmp(tname, name) : -1; } /* Get type die, but skip qualifiers and typedef */ @@ -390,7 +378,7 @@ static Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name, */ /* Show a location */ -static void convert_location(Dwarf_Op *op, struct probe_finder *pf) +static int convert_location(Dwarf_Op *op, struct probe_finder *pf) { unsigned int regn; Dwarf_Word offs = 0; @@ -400,8 +388,11 @@ static void convert_location(Dwarf_Op *op, struct probe_finder *pf) /* If this is based on frame buffer, set the offset */ if (op->atom == DW_OP_fbreg) { - if (pf->fb_ops == NULL) - die("The attribute of frame base is not supported.\n"); + if (pf->fb_ops == NULL) { + pr_warning("The attribute of frame base is not " + "supported.\n"); + return -ENOTSUP; + } ref = true; offs = op->number; op = &pf->fb_ops[0]; @@ -419,50 +410,63 @@ static void convert_location(Dwarf_Op *op, struct probe_finder *pf) ref = true; } else if (op->atom == DW_OP_regx) { regn = op->number; - } else - die("DW_OP %d is not supported.", op->atom); + } else { + pr_warning("DW_OP %x is not supported.\n", op->atom); + return -ENOTSUP; + } regs = get_arch_regstr(regn); - if (!regs) - die("%u exceeds max register number.", regn); + if (!regs) { + pr_warning("%u exceeds max register number.\n", regn); + return -ERANGE; + } tvar->value = xstrdup(regs); if (ref) { tvar->ref = xzalloc(sizeof(struct kprobe_trace_arg_ref)); tvar->ref->offset = (long)offs; } + return 0; } -static void convert_variable_type(Dwarf_Die *vr_die, - struct kprobe_trace_arg *targ) +static int convert_variable_type(Dwarf_Die *vr_die, + struct kprobe_trace_arg *targ) { Dwarf_Die type; char buf[16]; int ret; - if (die_get_real_type(vr_die, &type) == NULL) - die("Failed to get a type information of %s.", - dwarf_diename(vr_die)); + if (die_get_real_type(vr_die, &type) == NULL) { + pr_warning("Failed to get a type information of %s.\n", + dwarf_diename(vr_die)); + return -ENOENT; + } ret = die_get_byte_size(&type) * 8; if (ret) { /* Check the bitwidth */ if (ret > MAX_BASIC_TYPE_BITS) { - pr_warning(" Warning: %s exceeds max-bitwidth." - " Cut down to %d bits.\n", - dwarf_diename(&type), MAX_BASIC_TYPE_BITS); + pr_info("%s exceeds max-bitwidth." + " Cut down to %d bits.\n", + dwarf_diename(&type), MAX_BASIC_TYPE_BITS); ret = MAX_BASIC_TYPE_BITS; } ret = snprintf(buf, 16, "%c%d", die_is_signed_type(&type) ? 's' : 'u', ret); - if (ret < 0 || ret >= 16) - die("Failed to convert variable type."); + if (ret < 0 || ret >= 16) { + if (ret >= 16) + ret = -E2BIG; + pr_warning("Failed to convert variable type: %s\n", + strerror(-ret)); + return ret; + } targ->type = xstrdup(buf); } + return 0; } -static void convert_variable_fields(Dwarf_Die *vr_die, const char *varname, +static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, struct perf_probe_arg_field *field, struct kprobe_trace_arg_ref **ref_ptr, Dwarf_Die *die_mem) @@ -473,21 +477,28 @@ static void convert_variable_fields(Dwarf_Die *vr_die, const char *varname, Dwarf_Word offs; pr_debug("converting %s in %s\n", field->name, varname); - if (die_get_real_type(vr_die, &type) == NULL) - die("Failed to get a type information of %s.", varname); + if (die_get_real_type(vr_die, &type) == NULL) { + pr_warning("Failed to get the type of %s.\n", varname); + return -ENOENT; + } /* Check the pointer and dereference */ if (dwarf_tag(&type) == DW_TAG_pointer_type) { - if (!field->ref) - die("Semantic error: %s must be referred by '->'", - field->name); + if (!field->ref) { + pr_err("Semantic error: %s must be referred by '->'\n", + field->name); + return -EINVAL; + } /* Get the type pointed by this pointer */ - if (die_get_real_type(&type, &type) == NULL) - die("Failed to get a type information of %s.", varname); - + if (die_get_real_type(&type, &type) == NULL) { + pr_warning("Failed to get the type of %s.\n", varname); + return -ENOENT; + } /* Verify it is a data structure */ - if (dwarf_tag(&type) != DW_TAG_structure_type) - die("%s is not a data structure.", varname); + if (dwarf_tag(&type) != DW_TAG_structure_type) { + pr_warning("%s is not a data structure.\n", varname); + return -EINVAL; + } ref = xzalloc(sizeof(struct kprobe_trace_arg_ref)); if (*ref_ptr) @@ -496,34 +507,46 @@ static void convert_variable_fields(Dwarf_Die *vr_die, const char *varname, *ref_ptr = ref; } else { /* Verify it is a data structure */ - if (dwarf_tag(&type) != DW_TAG_structure_type) - die("%s is not a data structure.", varname); - - if (field->ref) - die("Semantic error: %s must be referred by '.'", - field->name); - if (!ref) - die("Structure on a register is not supported yet."); + if (dwarf_tag(&type) != DW_TAG_structure_type) { + pr_warning("%s is not a data structure.\n", varname); + return -EINVAL; + } + if (field->ref) { + pr_err("Semantic error: %s must be referred by '.'\n", + field->name); + return -EINVAL; + } + if (!ref) { + pr_warning("Structure on a register is not " + "supported yet.\n"); + return -ENOTSUP; + } } - if (die_find_member(&type, field->name, die_mem) == NULL) - die("%s(tyep:%s) has no member %s.", varname, - dwarf_diename(&type), field->name); + if (die_find_member(&type, field->name, die_mem) == NULL) { + pr_warning("%s(tyep:%s) has no member %s.\n", varname, + dwarf_diename(&type), field->name); + return -EINVAL; + } /* Get the offset of the field */ if (dwarf_attr(die_mem, DW_AT_data_member_location, &attr) == NULL || - dwarf_formudata(&attr, &offs) != 0) - die("Failed to get the offset of %s.", field->name); + dwarf_formudata(&attr, &offs) != 0) { + pr_warning("Failed to get the offset of %s.\n", field->name); + return -ENOENT; + } ref->offset += (long)offs; /* Converting next field */ if (field->next) - convert_variable_fields(die_mem, field->name, field->next, - &ref, die_mem); + return convert_variable_fields(die_mem, field->name, + field->next, &ref, die_mem); + else + return 0; } /* Show a variables in kprobe event format */ -static void convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf) +static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf) { Dwarf_Attribute attr; Dwarf_Die die_mem; @@ -538,28 +561,30 @@ static void convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf) if (ret <= 0 || nexpr == 0) goto error; - convert_location(expr, pf); - - if (pf->pvar->field) { - convert_variable_fields(vr_die, pf->pvar->var, - pf->pvar->field, &pf->tvar->ref, - &die_mem); + ret = convert_location(expr, pf); + if (ret == 0 && pf->pvar->field) { + ret = convert_variable_fields(vr_die, pf->pvar->var, + pf->pvar->field, &pf->tvar->ref, + &die_mem); vr_die = &die_mem; } - if (pf->pvar->type) - pf->tvar->type = xstrdup(pf->pvar->type); - else - convert_variable_type(vr_die, pf->tvar); + if (ret == 0) { + if (pf->pvar->type) + pf->tvar->type = xstrdup(pf->pvar->type); + else + ret = convert_variable_type(vr_die, pf->tvar); + } /* *expr will be cached in libdw. Don't free it. */ - return ; + return ret; error: /* TODO: Support const_value */ - die("Failed to find the location of %s at this address.\n" - " Perhaps, it has been optimized out.", pf->pvar->var); + pr_err("Failed to find the location of %s at this address.\n" + " Perhaps, it has been optimized out.\n", pf->pvar->var); + return -ENOENT; } /* Find a variable in a subprogram die */ -static void find_variable(Dwarf_Die *sp_die, struct probe_finder *pf) +static int find_variable(Dwarf_Die *sp_die, struct probe_finder *pf) { Dwarf_Die vr_die; char buf[32], *ptr; @@ -578,19 +603,22 @@ static void find_variable(Dwarf_Die *sp_die, struct probe_finder *pf) if (!is_c_varname(pf->pvar->var)) { /* Copy raw parameters */ pf->tvar->value = xstrdup(pf->pvar->var); - } else { - pr_debug("Searching '%s' variable in context.\n", - pf->pvar->var); - /* Search child die for local variables and parameters. */ - if (!die_find_variable(sp_die, pf->pvar->var, &vr_die)) - die("Failed to find '%s' in this function.", - pf->pvar->var); - convert_variable(&vr_die, pf); + return 0; } + + pr_debug("Searching '%s' variable in context.\n", + pf->pvar->var); + /* Search child die for local variables and parameters. */ + if (!die_find_variable(sp_die, pf->pvar->var, &vr_die)) { + pr_warning("Failed to find '%s' in this function.\n", + pf->pvar->var); + return -ENOENT; + } + return convert_variable(&vr_die, pf); } /* Show a probe point to output buffer */ -static void convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf) +static int convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf) { struct kprobe_trace_event *tev; Dwarf_Addr eaddr; @@ -600,22 +628,31 @@ static void convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf) Dwarf_Attribute fb_attr; size_t nops; - if (pf->ntevs == MAX_PROBES) - die("Too many( > %d) probe point found.\n", MAX_PROBES); + if (pf->ntevs == MAX_PROBES) { + pr_warning("Too many( > %d) probe point found.\n", MAX_PROBES); + return -ERANGE; + } tev = &pf->tevs[pf->ntevs++]; /* If no real subprogram, find a real one */ if (!sp_die || dwarf_tag(sp_die) != DW_TAG_subprogram) { sp_die = die_find_real_subprogram(&pf->cu_die, pf->addr, &die_mem); - if (!sp_die) - die("Probe point is not found in subprograms."); + if (!sp_die) { + pr_warning("Failed to find probe point in any " + "functions.\n"); + return -ENOENT; + } } /* Copy the name of probe point */ name = dwarf_diename(sp_die); if (name) { - dwarf_entrypc(sp_die, &eaddr); + if (dwarf_entrypc(sp_die, &eaddr) != 0) { + pr_warning("Failed to get entry pc of %s\n", + dwarf_diename(sp_die)); + return -ENOENT; + } tev->point.symbol = xstrdup(name); tev->point.offset = (unsigned long)(pf->addr - eaddr); } else @@ -633,9 +670,12 @@ static void convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf) } else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa && pf->cfi != NULL) { Dwarf_Frame *frame; - ret = dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame); - DIE_IF(ret != 0); - dwarf_frame_cfa(frame, &pf->fb_ops, &nops); + if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 || + dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) { + pr_warning("Failed to get CFA on 0x%jx\n", + (uintmax_t)pf->addr); + return -ENOENT; + } } /* Find each argument */ @@ -644,45 +684,53 @@ static void convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf) for (i = 0; i < pf->pev->nargs; i++) { pf->pvar = &pf->pev->args[i]; pf->tvar = &tev->args[i]; - find_variable(sp_die, pf); + ret = find_variable(sp_die, pf); + if (ret != 0) + return ret; } /* *pf->fb_ops will be cached in libdw. Don't free it. */ pf->fb_ops = NULL; + return 0; } /* Find probe point from its line number */ -static void find_probe_point_by_line(struct probe_finder *pf) +static int find_probe_point_by_line(struct probe_finder *pf) { Dwarf_Lines *lines; Dwarf_Line *line; size_t nlines, i; Dwarf_Addr addr; int lineno; - int ret; + int ret = 0; - ret = dwarf_getsrclines(&pf->cu_die, &lines, &nlines); - DIE_IF(ret != 0); + if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) { + pr_warning("No source lines found in this CU.\n"); + return -ENOENT; + } - for (i = 0; i < nlines; i++) { + for (i = 0; i < nlines && ret == 0; i++) { line = dwarf_onesrcline(lines, i); - dwarf_lineno(line, &lineno); - if (lineno != pf->lno) + if (dwarf_lineno(line, &lineno) != 0 || + lineno != pf->lno) continue; /* TODO: Get fileno from line, but how? */ if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0) continue; - ret = dwarf_lineaddr(line, &addr); - DIE_IF(ret != 0); + if (dwarf_lineaddr(line, &addr) != 0) { + pr_warning("Failed to get the address of the line.\n"); + return -ENOENT; + } pr_debug("Probe line found: line[%d]:%d addr:0x%jx\n", (int)i, lineno, (uintmax_t)addr); pf->addr = addr; - convert_probe_point(NULL, pf); + ret = convert_probe_point(NULL, pf); /* Continuing, because target line might be inlined. */ } + return ret; } /* Find lines which match lazy pattern */ @@ -690,15 +738,27 @@ static int find_lazy_match_lines(struct list_head *head, const char *fname, const char *pat) { char *fbuf, *p1, *p2; - int fd, line, nlines = 0; + int fd, ret, line, nlines = 0; struct stat st; fd = open(fname, O_RDONLY); - if (fd < 0) - die("failed to open %s", fname); - DIE_IF(fstat(fd, &st) < 0); + if (fd < 0) { + pr_warning("Failed to open %s: %s\n", fname, strerror(-fd)); + return fd; + } + + ret = fstat(fd, &st); + if (ret < 0) { + pr_warning("Failed to get the size of %s: %s\n", + fname, strerror(errno)); + return ret; + } fbuf = xmalloc(st.st_size + 2); - DIE_IF(read(fd, fbuf, st.st_size) < 0); + ret = read(fd, fbuf, st.st_size); + if (ret < 0) { + pr_warning("Failed to read %s: %s\n", fname, strerror(errno)); + return ret; + } close(fd); fbuf[st.st_size] = '\n'; /* Dummy line */ fbuf[st.st_size + 1] = '\0'; @@ -718,7 +778,7 @@ static int find_lazy_match_lines(struct list_head *head, } /* Find probe points from lazy pattern */ -static void find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf) +static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf) { Dwarf_Lines *lines; Dwarf_Line *line; @@ -726,31 +786,40 @@ static void find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf) Dwarf_Addr addr; Dwarf_Die die_mem; int lineno; - int ret; + int ret = 0; if (list_empty(&pf->lcache)) { /* Matching lazy line pattern */ ret = find_lazy_match_lines(&pf->lcache, pf->fname, pf->pev->point.lazy_line); - if (ret <= 0) - die("No matched lines found in %s.", pf->fname); + if (ret == 0) { + pr_debug("No matched lines found in %s.\n", pf->fname); + return 0; + } else if (ret < 0) + return ret; } - ret = dwarf_getsrclines(&pf->cu_die, &lines, &nlines); - DIE_IF(ret != 0); - for (i = 0; i < nlines; i++) { + if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) { + pr_warning("No source lines found in this CU.\n"); + return -ENOENT; + } + + for (i = 0; i < nlines && ret >= 0; i++) { line = dwarf_onesrcline(lines, i); - dwarf_lineno(line, &lineno); - if (!line_list__has_line(&pf->lcache, lineno)) + if (dwarf_lineno(line, &lineno) != 0 || + !line_list__has_line(&pf->lcache, lineno)) continue; /* TODO: Get fileno from line, but how? */ if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0) continue; - ret = dwarf_lineaddr(line, &addr); - DIE_IF(ret != 0); + if (dwarf_lineaddr(line, &addr) != 0) { + pr_debug("Failed to get the address of line %d.\n", + lineno); + continue; + } if (sp_die) { /* Address filtering 1: does sp_die include addr? */ if (!dwarf_haspc(sp_die, addr)) @@ -764,27 +833,42 @@ static void find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf) (int)i, lineno, (unsigned long long)addr); pf->addr = addr; - convert_probe_point(sp_die, pf); + ret = convert_probe_point(sp_die, pf); /* Continuing, because target line might be inlined. */ } /* TODO: deallocate lines, but how? */ + return ret; } +/* Callback parameter with return value */ +struct dwarf_callback_param { + void *data; + int retval; +}; + static int probe_point_inline_cb(Dwarf_Die *in_die, void *data) { - struct probe_finder *pf = (struct probe_finder *)data; + struct dwarf_callback_param *param = data; + struct probe_finder *pf = param->data; struct perf_probe_point *pp = &pf->pev->point; + Dwarf_Addr addr; if (pp->lazy_line) - find_probe_point_lazy(in_die, pf); + param->retval = find_probe_point_lazy(in_die, pf); else { /* Get probe address */ - pf->addr = die_get_entrypc(in_die); + if (dwarf_entrypc(in_die, &addr) != 0) { + pr_warning("Failed to get entry pc of %s.\n", + dwarf_diename(in_die)); + param->retval = -ENOENT; + return DWARF_CB_ABORT; + } + pf->addr = addr; pf->addr += pp->offset; pr_debug("found inline addr: 0x%jx\n", (uintmax_t)pf->addr); - convert_probe_point(in_die, pf); + param->retval = convert_probe_point(in_die, pf); } return DWARF_CB_OK; @@ -793,39 +877,53 @@ static int probe_point_inline_cb(Dwarf_Die *in_die, void *data) /* Search function from function name */ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data) { - struct probe_finder *pf = (struct probe_finder *)data; + struct dwarf_callback_param *param = data; + struct probe_finder *pf = param->data; struct perf_probe_point *pp = &pf->pev->point; /* Check tag and diename */ if (dwarf_tag(sp_die) != DW_TAG_subprogram || die_compare_name(sp_die, pp->function) != 0) - return 0; + return DWARF_CB_OK; pf->fname = dwarf_decl_file(sp_die); if (pp->line) { /* Function relative line */ dwarf_decl_line(sp_die, &pf->lno); pf->lno += pp->line; - find_probe_point_by_line(pf); + param->retval = find_probe_point_by_line(pf); } else if (!dwarf_func_inline(sp_die)) { /* Real function */ if (pp->lazy_line) - find_probe_point_lazy(sp_die, pf); + param->retval = find_probe_point_lazy(sp_die, pf); else { - pf->addr = die_get_entrypc(sp_die); + if (dwarf_entrypc(sp_die, &pf->addr) != 0) { + pr_warning("Failed to get entry pc of %s.\n", + dwarf_diename(sp_die)); + param->retval = -ENOENT; + return DWARF_CB_ABORT; + } pf->addr += pp->offset; /* TODO: Check the address in this function */ - convert_probe_point(sp_die, pf); + param->retval = convert_probe_point(sp_die, pf); } - } else + } else { + struct dwarf_callback_param _param = {.data = (void *)pf, + .retval = 0}; /* Inlined function: search instances */ - dwarf_func_inline_instances(sp_die, probe_point_inline_cb, pf); + dwarf_func_inline_instances(sp_die, probe_point_inline_cb, + &_param); + param->retval = _param.retval; + } - return 1; /* Exit; no same symbol in this CU. */ + return DWARF_CB_ABORT; /* Exit; no same symbol in this CU. */ } -static void find_probe_point_by_func(struct probe_finder *pf) +static int find_probe_point_by_func(struct probe_finder *pf) { - dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, pf, 0); + struct dwarf_callback_param _param = {.data = (void *)pf, + .retval = 0}; + dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, &_param, 0); + return _param.retval; } /* Find kprobe_trace_events specified by perf_probe_event from debuginfo */ @@ -838,14 +936,18 @@ int find_kprobe_trace_events(int fd, struct perf_probe_event *pev, size_t cuhl; Dwarf_Die *diep; Dwarf *dbg; + int ret = 0; pf.tevs = xzalloc(sizeof(struct kprobe_trace_event) * MAX_PROBES); *tevs = pf.tevs; pf.ntevs = 0; dbg = dwarf_begin(fd, DWARF_C_READ); - if (!dbg) - return -ENOENT; + if (!dbg) { + pr_warning("No dwarf info found in the vmlinux - " + "please rebuild with CONFIG_DEBUG_INFO=y.\n"); + return -EBADF; + } /* Get the call frame information from this dwarf */ pf.cfi = dwarf_getcfi(dbg); @@ -853,7 +955,8 @@ int find_kprobe_trace_events(int fd, struct perf_probe_event *pev, off = 0; line_list__init(&pf.lcache); /* Loop on CUs (Compilation Unit) */ - while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL)) { + while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) && + ret >= 0) { /* Get the DIE(Debugging Information Entry) of this CU */ diep = dwarf_offdie(dbg, off + cuhl, &pf.cu_die); if (!diep) @@ -867,12 +970,12 @@ int find_kprobe_trace_events(int fd, struct perf_probe_event *pev, if (!pp->file || pf.fname) { if (pp->function) - find_probe_point_by_func(&pf); + ret = find_probe_point_by_func(&pf); else if (pp->lazy_line) - find_probe_point_lazy(NULL, &pf); + ret = find_probe_point_lazy(NULL, &pf); else { pf.lno = pp->line; - find_probe_point_by_line(&pf); + ret = find_probe_point_by_line(&pf); } } off = noff; @@ -880,7 +983,7 @@ int find_kprobe_trace_events(int fd, struct perf_probe_event *pev, line_list__free(&pf.lcache); dwarf_end(dbg); - return pf.ntevs; + return (ret < 0) ? ret : pf.ntevs; } /* Reverse search */ @@ -893,10 +996,11 @@ int find_perf_probe_point(int fd, unsigned long addr, Dwarf_Addr laddr, eaddr; const char *tmp; int lineno, ret = 0; + bool found = false; dbg = dwarf_begin(fd, DWARF_C_READ); if (!dbg) - return -ENOENT; + return -EBADF; /* Find cu die */ if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr, &cudie)) { @@ -907,82 +1011,87 @@ int find_perf_probe_point(int fd, unsigned long addr, /* Find a corresponding line */ line = dwarf_getsrc_die(&cudie, (Dwarf_Addr)addr); if (line) { - dwarf_lineaddr(line, &laddr); - if ((Dwarf_Addr)addr == laddr) { - dwarf_lineno(line, &lineno); - ppt->line = lineno; - + if (dwarf_lineaddr(line, &laddr) == 0 && + (Dwarf_Addr)addr == laddr && + dwarf_lineno(line, &lineno) == 0) { tmp = dwarf_linesrc(line, NULL, NULL); - DIE_IF(!tmp); - ppt->file = xstrdup(tmp); - ret = 1; + if (tmp) { + ppt->line = lineno; + ppt->file = xstrdup(tmp); + found = true; + } } } /* Find a corresponding function */ if (die_find_real_subprogram(&cudie, (Dwarf_Addr)addr, &spdie)) { tmp = dwarf_diename(&spdie); - if (!tmp) + if (!tmp || dwarf_entrypc(&spdie, &eaddr) != 0) goto end; - dwarf_entrypc(&spdie, &eaddr); - if (!lineno) { - /* We don't have a line number, let's use offset */ - ppt->function = xstrdup(tmp); - ppt->offset = addr - (unsigned long)eaddr; - ret = 1; - goto end; - } - if (die_find_inlinefunc(&spdie, (Dwarf_Addr)addr, &indie)) { - /* addr in an inline function */ - tmp = dwarf_diename(&indie); - if (!tmp) - goto end; - dwarf_decl_line(&indie, &lineno); - } else { - if (eaddr == addr) /* No offset: function entry */ - lineno = ppt->line; - else - dwarf_decl_line(&spdie, &lineno); + if (ppt->line) { + if (die_find_inlinefunc(&spdie, (Dwarf_Addr)addr, + &indie)) { + /* addr in an inline function */ + tmp = dwarf_diename(&indie); + if (!tmp) + goto end; + ret = dwarf_decl_line(&indie, &lineno); + } else { + if (eaddr == addr) { /* Function entry */ + lineno = ppt->line; + ret = 0; + } else + ret = dwarf_decl_line(&spdie, &lineno); + } + if (ret == 0) { + /* Make a relative line number */ + ppt->line -= lineno; + goto found; + } } + /* We don't have a line number, let's use offset */ + ppt->offset = addr - (unsigned long)eaddr; +found: ppt->function = xstrdup(tmp); - ppt->line -= lineno; /* Make a relative line number */ + found = true; } end: dwarf_end(dbg); + if (ret >= 0) + ret = found ? 1 : 0; return ret; } /* Find line range from its line number */ -static void find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf) +static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf) { Dwarf_Lines *lines; Dwarf_Line *line; size_t nlines, i; Dwarf_Addr addr; int lineno; - int ret; const char *src; Dwarf_Die die_mem; line_list__init(&lf->lr->line_list); - ret = dwarf_getsrclines(&lf->cu_die, &lines, &nlines); - DIE_IF(ret != 0); + if (dwarf_getsrclines(&lf->cu_die, &lines, &nlines) != 0) { + pr_warning("No source lines found in this CU.\n"); + return -ENOENT; + } for (i = 0; i < nlines; i++) { line = dwarf_onesrcline(lines, i); - ret = dwarf_lineno(line, &lineno); - DIE_IF(ret != 0); - if (lf->lno_s > lineno || lf->lno_e < lineno) + if (dwarf_lineno(line, &lineno) != 0 || + (lf->lno_s > lineno || lf->lno_e < lineno)) continue; if (sp_die) { /* Address filtering 1: does sp_die include addr? */ - ret = dwarf_lineaddr(line, &addr); - DIE_IF(ret != 0); - if (!dwarf_haspc(sp_die, addr)) + if (dwarf_lineaddr(line, &addr) != 0 || + !dwarf_haspc(sp_die, addr)) continue; /* Address filtering 2: No child include addr? */ @@ -1007,18 +1116,22 @@ static void find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf) free(lf->lr->path); lf->lr->path = NULL; } + return lf->found; } static int line_range_inline_cb(Dwarf_Die *in_die, void *data) { - find_line_range_by_line(in_die, (struct line_finder *)data); + struct dwarf_callback_param *param = data; + + param->retval = find_line_range_by_line(in_die, param->data); return DWARF_CB_ABORT; /* No need to find other instances */ } /* Search function from function name */ static int line_range_search_cb(Dwarf_Die *sp_die, void *data) { - struct line_finder *lf = (struct line_finder *)data; + struct dwarf_callback_param *param = data; + struct line_finder *lf = param->data; struct line_range *lr = lf->lr; if (dwarf_tag(sp_die) == DW_TAG_subprogram && @@ -1033,38 +1146,47 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data) lf->lno_e = lr->offset + lr->end; lr->start = lf->lno_s; lr->end = lf->lno_e; - if (dwarf_func_inline(sp_die)) + if (dwarf_func_inline(sp_die)) { + struct dwarf_callback_param _param; + _param.data = (void *)lf; + _param.retval = 0; dwarf_func_inline_instances(sp_die, - line_range_inline_cb, lf); - else - find_line_range_by_line(sp_die, lf); - return 1; + line_range_inline_cb, + &_param); + param->retval = _param.retval; + } else + param->retval = find_line_range_by_line(sp_die, lf); + return DWARF_CB_ABORT; } - return 0; + return DWARF_CB_OK; } -static void find_line_range_by_func(struct line_finder *lf) +static int find_line_range_by_func(struct line_finder *lf) { - dwarf_getfuncs(&lf->cu_die, line_range_search_cb, lf, 0); + struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0}; + dwarf_getfuncs(&lf->cu_die, line_range_search_cb, ¶m, 0); + return param.retval; } int find_line_range(int fd, struct line_range *lr) { struct line_finder lf = {.lr = lr, .found = 0}; - int ret; + int ret = 0; Dwarf_Off off = 0, noff; size_t cuhl; Dwarf_Die *diep; Dwarf *dbg; dbg = dwarf_begin(fd, DWARF_C_READ); - if (!dbg) - return -ENOENT; + if (!dbg) { + pr_warning("No dwarf info found in the vmlinux - " + "please rebuild with CONFIG_DEBUG_INFO=y.\n"); + return -EBADF; + } /* Loop on CUs (Compilation Unit) */ - while (!lf.found) { - ret = dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL); - if (ret != 0) + while (!lf.found && ret >= 0) { + if (dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) != 0) break; /* Get the DIE(Debugging Information Entry) of this CU */ @@ -1080,20 +1202,21 @@ int find_line_range(int fd, struct line_range *lr) if (!lr->file || lf.fname) { if (lr->function) - find_line_range_by_func(&lf); + ret = find_line_range_by_func(&lf); else { lf.lno_s = lr->start; if (!lr->end) lf.lno_e = INT_MAX; else lf.lno_e = lr->end; - find_line_range_by_line(NULL, &lf); + ret = find_line_range_by_line(NULL, &lf); } } off = noff; } pr_debug("path: %lx\n", (unsigned long)lr->path); dwarf_end(dbg); - return lf.found; + + return (ret < 0) ? ret : lf.found; } -- cgit v0.10.2 From 146a143948ed9e8b248c0ec59937f3e9e1bbc7e5 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Mon, 12 Apr 2010 13:17:42 -0400 Subject: perf probe: Remove die() from probe-event code Remove die() and DIE_IF() code from util/probe-event.c since these 'sudden death' in utility functions make reusing it from other code (especially tui/gui) difficult. Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Frederic Weisbecker LKML-Reference: <20100412171742.3790.33650.stgit@localhost6.localdomain6> Signed-off-by: Masami Hiramatsu Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index daf4668..64bc11a 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c @@ -59,23 +59,25 @@ static struct { /* Parse an event definition. Note that any error must die. */ -static void parse_probe_event(const char *str) +static int parse_probe_event(const char *str) { struct perf_probe_event *pev = ¶ms.events[params.nevents]; + int ret; pr_debug("probe-definition(%d): %s\n", params.nevents, str); if (++params.nevents == MAX_PROBES) die("Too many probes (> %d) are specified.", MAX_PROBES); /* Parse a perf-probe command into event */ - parse_perf_probe_command(str, pev); - + ret = parse_perf_probe_command(str, pev); pr_debug("%d arguments\n", pev->nargs); + + return ret; } -static void parse_probe_event_argv(int argc, const char **argv) +static int parse_probe_event_argv(int argc, const char **argv) { - int i, len; + int i, len, ret; char *buf; /* Bind up rest arguments */ @@ -86,16 +88,18 @@ static void parse_probe_event_argv(int argc, const char **argv) len = 0; for (i = 0; i < argc; i++) len += sprintf(&buf[len], "%s ", argv[i]); - parse_probe_event(buf); + ret = parse_probe_event(buf); free(buf); + return ret; } static int opt_add_probe_event(const struct option *opt __used, const char *str, int unset __used) { if (str) - parse_probe_event(str); - return 0; + return parse_probe_event(str); + else + return 0; } static int opt_del_probe_event(const struct option *opt __used, @@ -113,11 +117,14 @@ static int opt_del_probe_event(const struct option *opt __used, static int opt_show_lines(const struct option *opt __used, const char *str, int unset __used) { + int ret = 0; + if (str) - parse_line_range_desc(str, ¶ms.line_range); + ret = parse_line_range_desc(str, ¶ms.line_range); INIT_LIST_HEAD(¶ms.line_range.line_list); params.show_lines = true; - return 0; + + return ret; } #endif @@ -178,6 +185,8 @@ static const struct option options[] = { int cmd_probe(int argc, const char **argv, const char *prefix __used) { + int ret; + argc = parse_options(argc, argv, options, probe_usage, PARSE_OPT_STOP_AT_NON_OPTION); if (argc > 0) { @@ -185,7 +194,11 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) pr_warning(" Error: '-' is not supported.\n"); usage_with_options(probe_usage, options); } - parse_probe_event_argv(argc, argv); + ret = parse_probe_event_argv(argc, argv); + if (ret < 0) { + pr_err(" Error: Parse Error. (%d)\n", ret); + return ret; + } } if ((!params.nevents && !params.dellist && !params.list_events && @@ -197,16 +210,18 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) if (params.list_events) { if (params.nevents != 0 || params.dellist) { - pr_warning(" Error: Don't use --list with" - " --add/--del.\n"); + pr_err(" Error: Don't use --list with --add/--del.\n"); usage_with_options(probe_usage, options); } if (params.show_lines) { - pr_warning(" Error: Don't use --list with --line.\n"); + pr_err(" Error: Don't use --list with --line.\n"); usage_with_options(probe_usage, options); } - show_perf_probe_events(); - return 0; + ret = show_perf_probe_events(); + if (ret < 0) + pr_err(" Error: Failed to show event list. (%d)\n", + ret); + return ret; } #ifdef DWARF_SUPPORT @@ -217,19 +232,30 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) usage_with_options(probe_usage, options); } - show_line_range(¶ms.line_range); - return 0; + ret = show_line_range(¶ms.line_range); + if (ret < 0) + pr_err(" Error: Failed to show lines. (%d)\n", ret); + return ret; } #endif if (params.dellist) { - del_perf_probe_events(params.dellist); + ret = del_perf_probe_events(params.dellist); strlist__delete(params.dellist); - if (params.nevents == 0) - return 0; + if (ret < 0) { + pr_err(" Error: Failed to delete events. (%d)\n", ret); + return ret; + } } - add_perf_probe_events(params.events, params.nevents, params.force_add); + if (params.nevents) { + ret = add_perf_probe_events(params.events, params.nevents, + params.force_add); + if (ret < 0) { + pr_err(" Error: Failed to add events. (%d)\n", ret); + return ret; + } + } return 0; } diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 7893b32..bd68f7b 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -53,7 +53,7 @@ bool probe_event_dry_run; /* Dry run flag */ -#define semantic_error(msg ...) die("Semantic error :" msg) +#define semantic_error(msg ...) pr_err("Semantic error :" msg) /* If there is no space to write, returns -E2BIG. */ static int e_snprintf(char *str, size_t size, const char *format, ...) @@ -76,19 +76,30 @@ static struct map_groups kmap_groups; static struct map *kmaps[MAP__NR_TYPES]; /* Initialize symbol maps and path of vmlinux */ -static void init_vmlinux(void) +static int init_vmlinux(void) { + int ret; + symbol_conf.sort_by_name = true; if (symbol_conf.vmlinux_name == NULL) symbol_conf.try_vmlinux_path = true; else pr_debug("Use vmlinux: %s\n", symbol_conf.vmlinux_name); - if (symbol__init() < 0) - die("Failed to init symbol map."); + ret = symbol__init(); + if (ret < 0) { + pr_debug("Failed to init symbol map.\n"); + goto out; + } map_groups__init(&kmap_groups); - if (map_groups__create_kernel_maps(&kmap_groups, kmaps) < 0) - die("Failed to create kernel maps."); + ret = map_groups__create_kernel_maps(&kmap_groups, kmaps); + if (ret < 0) + pr_debug("Failed to create kernel maps.\n"); + +out: + if (ret < 0) + pr_warning("Failed to init vmlinux path.\n"); + return ret; } #ifdef DWARF_SUPPORT @@ -102,24 +113,32 @@ static int open_vmlinux(void) return open(kmaps[MAP__FUNCTION]->dso->long_name, O_RDONLY); } -static void convert_to_perf_probe_point(struct kprobe_trace_point *tp, - struct perf_probe_point *pp) +/* Convert trace point to probe point with debuginfo */ +static int convert_to_perf_probe_point(struct kprobe_trace_point *tp, + struct perf_probe_point *pp) { struct symbol *sym; - int fd, ret = 0; + int fd, ret = -ENOENT; sym = map__find_symbol_by_name(kmaps[MAP__FUNCTION], tp->symbol, NULL); if (sym) { fd = open_vmlinux(); - ret = find_perf_probe_point(fd, sym->start + tp->offset, pp); - close(fd); + if (fd >= 0) { + ret = find_perf_probe_point(fd, + sym->start + tp->offset, pp); + close(fd); + } } if (ret <= 0) { + pr_debug("Failed to find corresponding probes from " + "debuginfo. Use kprobe event information.\n"); pp->function = xstrdup(tp->symbol); pp->offset = tp->offset; } pp->retprobe = tp->retprobe; + + return 0; } /* Try to find perf_probe_event with debuginfo */ @@ -131,9 +150,10 @@ static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev, fd = open_vmlinux(); if (fd < 0) { - if (need_dwarf) - die("Could not open debuginfo file."); - + if (need_dwarf) { + pr_warning("Failed to open debuginfo file.\n"); + return fd; + } pr_debug("Could not open vmlinux. Try to use symbols.\n"); return 0; } @@ -142,30 +162,32 @@ static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev, ntevs = find_kprobe_trace_events(fd, pev, tevs); close(fd); - if (ntevs > 0) /* Succeeded to find trace events */ + if (ntevs > 0) { /* Succeeded to find trace events */ + pr_debug("find %d kprobe_trace_events.\n", ntevs); return ntevs; + } - if (ntevs == 0) /* No error but failed to find probe point. */ - die("Probe point '%s' not found. - probe not added.", - synthesize_perf_probe_point(&pev->point)); - - /* Error path */ + if (ntevs == 0) { /* No error but failed to find probe point. */ + pr_warning("Probe point '%s' not found.\n", + synthesize_perf_probe_point(&pev->point)); + return -ENOENT; + } + /* Error path : ntevs < 0 */ if (need_dwarf) { if (ntevs == -EBADF) pr_warning("No dwarf info found in the vmlinux - " "please rebuild with CONFIG_DEBUG_INFO=y.\n"); - die("Failed to analyze debuginfo."); + return ntevs; } pr_debug("An error occurred in debuginfo analysis." " Try to use symbols.\n"); return 0; - } #define LINEBUF_SIZE 256 #define NR_ADDITIONAL_LINES 2 -static void show_one_line(FILE *fp, unsigned int l, bool skip, bool show_num) +static int show_one_line(FILE *fp, unsigned int l, bool skip, bool show_num) { char buf[LINEBUF_SIZE]; const char *color = PERF_COLOR_BLUE; @@ -190,19 +212,22 @@ static void show_one_line(FILE *fp, unsigned int l, bool skip, bool show_num) color_fprintf(stdout, color, "%s", buf); } } - return; + + return 0; error: if (feof(fp)) - die("Source file is shorter than expected."); + pr_warning("Source file is shorter than expected.\n"); else - die("File read error: %s", strerror(errno)); + pr_warning("File read error: %s\n", strerror(errno)); + + return -1; } /* * Show line-range always requires debuginfo to find source file and * line number. */ -void show_line_range(struct line_range *lr) +int show_line_range(struct line_range *lr) { unsigned int l = 1; struct line_node *ln; @@ -210,14 +235,25 @@ void show_line_range(struct line_range *lr) int fd, ret; /* Search a line range */ - init_vmlinux(); + ret = init_vmlinux(); + if (ret < 0) + return ret; + fd = open_vmlinux(); - if (fd < 0) - die("Could not open debuginfo file."); + if (fd < 0) { + pr_warning("Failed to open debuginfo file.\n"); + return fd; + } + ret = find_line_range(fd, lr); - if (ret <= 0) - die("Source line is not found.\n"); close(fd); + if (ret == 0) { + pr_warning("Specified source line is not found.\n"); + return -ENOENT; + } else if (ret < 0) { + pr_warning("Debuginfo analysis failed. (%d)\n", ret); + return ret; + } setup_pager(); @@ -228,52 +264,68 @@ void show_line_range(struct line_range *lr) fprintf(stdout, "<%s:%d>\n", lr->file, lr->start); fp = fopen(lr->path, "r"); - if (fp == NULL) - die("Failed to open %s: %s", lr->path, strerror(errno)); + if (fp == NULL) { + pr_warning("Failed to open %s: %s\n", lr->path, + strerror(errno)); + return -errno; + } /* Skip to starting line number */ - while (l < lr->start) - show_one_line(fp, l++, true, false); + while (l < lr->start && ret >= 0) + ret = show_one_line(fp, l++, true, false); + if (ret < 0) + goto end; list_for_each_entry(ln, &lr->line_list, list) { - while (ln->line > l) - show_one_line(fp, (l++) - lr->offset, false, false); - show_one_line(fp, (l++) - lr->offset, false, true); + while (ln->line > l && ret >= 0) + ret = show_one_line(fp, (l++) - lr->offset, + false, false); + if (ret >= 0) + ret = show_one_line(fp, (l++) - lr->offset, + false, true); + if (ret < 0) + goto end; } if (lr->end == INT_MAX) lr->end = l + NR_ADDITIONAL_LINES; - while (l < lr->end && !feof(fp)) - show_one_line(fp, (l++) - lr->offset, false, false); - + while (l < lr->end && !feof(fp) && ret >= 0) + ret = show_one_line(fp, (l++) - lr->offset, false, false); +end: fclose(fp); + return ret; } #else /* !DWARF_SUPPORT */ -static void convert_to_perf_probe_point(struct kprobe_trace_point *tp, +static int convert_to_perf_probe_point(struct kprobe_trace_point *tp, struct perf_probe_point *pp) { pp->function = xstrdup(tp->symbol); pp->offset = tp->offset; pp->retprobe = tp->retprobe; + + return 0; } static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev, struct kprobe_trace_event **tevs __unused) { - if (perf_probe_event_need_dwarf(pev)) - die("Debuginfo-analysis is not supported"); + if (perf_probe_event_need_dwarf(pev)) { + pr_warning("Debuginfo-analysis is not supported.\n"); + return -ENOSYS; + } return 0; } -void show_line_range(struct line_range *lr __unused) +int show_line_range(struct line_range *lr __unused) { - die("Debuginfo-analysis is not supported"); + pr_warning("Debuginfo-analysis is not supported.\n"); + return -ENOSYS; } #endif -void parse_line_range_desc(const char *arg, struct line_range *lr) +int parse_line_range_desc(const char *arg, struct line_range *lr) { const char *ptr; char *tmp; @@ -293,12 +345,16 @@ void parse_line_range_desc(const char *arg, struct line_range *lr) else lr->end = 0; pr_debug("Line range is %u to %u\n", lr->start, lr->end); - if (lr->end && lr->start > lr->end) + if (lr->end && lr->start > lr->end) { semantic_error("Start line must be smaller" - " than end line."); - if (*tmp != '\0') - semantic_error("Tailing with invalid character '%d'.", + " than end line.\n"); + return -EINVAL; + } + if (*tmp != '\0') { + semantic_error("Tailing with invalid character '%d'.\n", *tmp); + return -EINVAL; + } tmp = xstrndup(arg, (ptr - arg)); } else tmp = xstrdup(arg); @@ -307,6 +363,8 @@ void parse_line_range_desc(const char *arg, struct line_range *lr) lr->file = tmp; else lr->function = tmp; + + return 0; } /* Check the name is good for event/group */ @@ -322,7 +380,7 @@ static bool check_event_name(const char *name) } /* Parse probepoint definition. */ -static void parse_perf_probe_point(char *arg, struct perf_probe_event *pev) +static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) { struct perf_probe_point *pp = &pev->point; char *ptr, *tmp; @@ -339,12 +397,15 @@ static void parse_perf_probe_point(char *arg, struct perf_probe_event *pev) if (ptr && *ptr == '=') { /* Event name */ *ptr = '\0'; tmp = ptr + 1; - ptr = strchr(arg, ':'); - if (ptr) /* Group name is not supported yet. */ - semantic_error("Group name is not supported yet."); - if (!check_event_name(arg)) + if (strchr(arg, ':')) { + semantic_error("Group name is not supported yet.\n"); + return -ENOTSUP; + } + if (!check_event_name(arg)) { semantic_error("%s is bad for event name -it must " - "follow C symbol-naming rule.", arg); + "follow C symbol-naming rule.\n", arg); + return -EINVAL; + } pev->event = xstrdup(arg); pev->group = NULL; arg = tmp; @@ -378,64 +439,89 @@ static void parse_perf_probe_point(char *arg, struct perf_probe_event *pev) switch (c) { case ':': /* Line number */ pp->line = strtoul(arg, &tmp, 0); - if (*tmp != '\0') + if (*tmp != '\0') { semantic_error("There is non-digit char" - " in line number."); + " in line number.\n"); + return -EINVAL; + } break; case '+': /* Byte offset from a symbol */ pp->offset = strtoul(arg, &tmp, 0); - if (*tmp != '\0') + if (*tmp != '\0') { semantic_error("There is non-digit character" - " in offset."); + " in offset.\n"); + return -EINVAL; + } break; case '@': /* File name */ - if (pp->file) - semantic_error("SRC@SRC is not allowed."); + if (pp->file) { + semantic_error("SRC@SRC is not allowed.\n"); + return -EINVAL; + } pp->file = xstrdup(arg); break; case '%': /* Probe places */ if (strcmp(arg, "return") == 0) { pp->retprobe = 1; - } else /* Others not supported yet */ - semantic_error("%%%s is not supported.", arg); + } else { /* Others not supported yet */ + semantic_error("%%%s is not supported.\n", arg); + return -ENOTSUP; + } break; - default: - DIE_IF("Program has a bug."); + default: /* Buggy case */ + pr_err("This program has a bug at %s:%d.\n", + __FILE__, __LINE__); + return -ENOTSUP; break; } } /* Exclusion check */ - if (pp->lazy_line && pp->line) + if (pp->lazy_line && pp->line) { semantic_error("Lazy pattern can't be used with line number."); + return -EINVAL; + } - if (pp->lazy_line && pp->offset) + if (pp->lazy_line && pp->offset) { semantic_error("Lazy pattern can't be used with offset."); + return -EINVAL; + } - if (pp->line && pp->offset) + if (pp->line && pp->offset) { semantic_error("Offset can't be used with line number."); + return -EINVAL; + } - if (!pp->line && !pp->lazy_line && pp->file && !pp->function) + if (!pp->line && !pp->lazy_line && pp->file && !pp->function) { semantic_error("File always requires line number or " "lazy pattern."); + return -EINVAL; + } - if (pp->offset && !pp->function) + if (pp->offset && !pp->function) { semantic_error("Offset requires an entry function."); + return -EINVAL; + } - if (pp->retprobe && !pp->function) + if (pp->retprobe && !pp->function) { semantic_error("Return probe requires an entry function."); + return -EINVAL; + } - if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) + if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) { semantic_error("Offset/Line/Lazy pattern can't be used with " "return probe."); + return -EINVAL; + } pr_debug("symbol:%s file:%s line:%d offset:%lu return:%d lazy:%s\n", pp->function, pp->file, pp->line, pp->offset, pp->retprobe, pp->lazy_line); + return 0; } /* Parse perf-probe event argument */ -static void parse_perf_probe_arg(char *str, struct perf_probe_arg *arg) +static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg) { char *tmp; struct perf_probe_arg_field **fieldp; @@ -461,7 +547,7 @@ static void parse_perf_probe_arg(char *str, struct perf_probe_arg *arg) /* A variable, register, symbol or special value */ arg->var = xstrdup(str); pr_debug("%s\n", arg->var); - return; + return 0; } /* Structure fields */ @@ -477,8 +563,10 @@ static void parse_perf_probe_arg(char *str, struct perf_probe_arg *arg) } else if (tmp[1] == '>') { str = tmp + 2; (*fieldp)->ref = true; - } else - semantic_error("Argument parse error: %s", str); + } else { + semantic_error("Argument parse error: %s\n", str); + return -EINVAL; + } tmp = strpbrk(str, "-."); if (tmp) { @@ -493,34 +581,47 @@ static void parse_perf_probe_arg(char *str, struct perf_probe_arg *arg) /* If no name is specified, set the last field name */ if (!arg->name) arg->name = xstrdup((*fieldp)->name); + + return 0; } /* Parse perf-probe event command */ -void parse_perf_probe_command(const char *cmd, struct perf_probe_event *pev) +int parse_perf_probe_command(const char *cmd, struct perf_probe_event *pev) { char **argv; - int argc, i; + int argc, i, ret = 0; argv = argv_split(cmd, &argc); - if (!argv) - die("argv_split failed."); - if (argc > MAX_PROBE_ARGS + 1) - semantic_error("Too many arguments"); - + if (!argv) { + pr_debug("Failed to split arguments.\n"); + return -ENOMEM; + } + if (argc - 1 > MAX_PROBE_ARGS) { + semantic_error("Too many probe arguments (%d).\n", argc - 1); + ret = -ERANGE; + goto out; + } /* Parse probe point */ - parse_perf_probe_point(argv[0], pev); + ret = parse_perf_probe_point(argv[0], pev); + if (ret < 0) + goto out; /* Copy arguments and ensure return probe has no C argument */ pev->nargs = argc - 1; pev->args = xzalloc(sizeof(struct perf_probe_arg) * pev->nargs); - for (i = 0; i < pev->nargs; i++) { - parse_perf_probe_arg(argv[i + 1], &pev->args[i]); - if (is_c_varname(pev->args[i].var) && pev->point.retprobe) + for (i = 0; i < pev->nargs && ret >= 0; i++) { + ret = parse_perf_probe_arg(argv[i + 1], &pev->args[i]); + if (ret >= 0 && + is_c_varname(pev->args[i].var) && pev->point.retprobe) { semantic_error("You can't specify local variable for" - " kretprobe"); + " kretprobe.\n"); + ret = -EINVAL; + } } - +out: argv_free(argv); + + return ret; } /* Return true if this perf_probe_event requires debuginfo */ @@ -539,7 +640,7 @@ bool perf_probe_event_need_dwarf(struct perf_probe_event *pev) } /* Parse kprobe_events event into struct probe_point */ -void parse_kprobe_trace_command(const char *cmd, struct kprobe_trace_event *tev) +int parse_kprobe_trace_command(const char *cmd, struct kprobe_trace_event *tev) { struct kprobe_trace_point *tp = &tev->point; char pr; @@ -549,17 +650,25 @@ void parse_kprobe_trace_command(const char *cmd, struct kprobe_trace_event *tev) pr_debug("Parsing kprobe_events: %s\n", cmd); argv = argv_split(cmd, &argc); - if (!argv) - die("argv_split failed."); - if (argc < 2) - semantic_error("Too less arguments."); + if (!argv) { + pr_debug("Failed to split arguments.\n"); + return -ENOMEM; + } + if (argc < 2) { + semantic_error("Too few probe arguments.\n"); + ret = -ERANGE; + goto out; + } /* Scan event and group name. */ ret = sscanf(argv[0], "%c:%a[^/ \t]/%a[^ \t]", &pr, (float *)(void *)&tev->group, (float *)(void *)&tev->event); - if (ret != 3) - semantic_error("Failed to parse event name: %s", argv[0]); + if (ret != 3) { + semantic_error("Failed to parse event name: %s\n", argv[0]); + ret = -EINVAL; + goto out; + } pr_debug("Group:%s Event:%s probe:%c\n", tev->group, tev->event, pr); tp->retprobe = (pr == 'r'); @@ -582,8 +691,10 @@ void parse_kprobe_trace_command(const char *cmd, struct kprobe_trace_event *tev) /* TODO: parse regs and offset */ tev->args[i].value = xstrdup(p); } - + ret = 0; +out: argv_free(argv); + return ret; } /* Compose only probe arg */ @@ -622,7 +733,9 @@ int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len) return tmp - buf; error: - die("Failed to synthesize perf probe argument: %s", strerror(-ret)); + pr_debug("Failed to synthesize perf probe argument: %s", + strerror(-ret)); + return ret; } /* Compose only probe point (not argument) */ @@ -666,7 +779,10 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp) return buf; error: - die("Failed to synthesize perf probe point: %s", strerror(-ret)); + pr_debug("Failed to synthesize perf probe point: %s", + strerror(-ret)); + free(buf); + return NULL; } #if 0 @@ -796,29 +912,37 @@ error: return NULL; } -void convert_to_perf_probe_event(struct kprobe_trace_event *tev, - struct perf_probe_event *pev) +int convert_to_perf_probe_event(struct kprobe_trace_event *tev, + struct perf_probe_event *pev) { char buf[64]; - int i; + int i, ret; /* Convert event/group name */ pev->event = xstrdup(tev->event); pev->group = xstrdup(tev->group); /* Convert trace_point to probe_point */ - convert_to_perf_probe_point(&tev->point, &pev->point); + ret = convert_to_perf_probe_point(&tev->point, &pev->point); + if (ret < 0) + return ret; /* Convert trace_arg to probe_arg */ pev->nargs = tev->nargs; pev->args = xzalloc(sizeof(struct perf_probe_arg) * pev->nargs); - for (i = 0; i < tev->nargs; i++) + for (i = 0; i < tev->nargs && ret >= 0; i++) if (tev->args[i].name) pev->args[i].name = xstrdup(tev->args[i].name); else { - synthesize_kprobe_trace_arg(&tev->args[i], buf, 64); + ret = synthesize_kprobe_trace_arg(&tev->args[i], + buf, 64); pev->args[i].name = xstrdup(buf); } + + if (ret < 0) + clear_perf_probe_event(pev); + + return ret; } void clear_perf_probe_event(struct perf_probe_event *pev) @@ -894,21 +1018,20 @@ static int open_kprobe_events(bool readwrite) int ret; ret = e_snprintf(buf, PATH_MAX, "%s/../kprobe_events", debugfs_path); - if (ret < 0) - die("Failed to make kprobe_events path."); - - if (readwrite && !probe_event_dry_run) - ret = open(buf, O_RDWR, O_APPEND); - else - ret = open(buf, O_RDONLY, 0); + if (ret >= 0) { + if (readwrite && !probe_event_dry_run) + ret = open(buf, O_RDWR, O_APPEND); + else + ret = open(buf, O_RDONLY, 0); + } if (ret < 0) { if (errno == ENOENT) - die("kprobe_events file does not exist -" - " please rebuild with CONFIG_KPROBE_EVENT."); + pr_warning("kprobe_events file does not exist - please" + " rebuild kernel with CONFIG_KPROBE_EVENT.\n"); else - die("Could not open kprobe_events file: %s", - strerror(errno)); + pr_warning("Failed to open kprobe_events file: %s\n", + strerror(errno)); } return ret; } @@ -934,8 +1057,11 @@ static struct strlist *get_kprobe_trace_command_rawlist(int fd) if (p[idx] == '\n') p[idx] = '\0'; ret = strlist__add(sl, buf); - if (ret < 0) - die("strlist__add failed: %s", strerror(-ret)); + if (ret < 0) { + pr_debug("strlist__add failed: %s\n", strerror(-ret)); + strlist__delete(sl); + return NULL; + } } fclose(fp); @@ -943,7 +1069,7 @@ static struct strlist *get_kprobe_trace_command_rawlist(int fd) } /* Show an event */ -static void show_perf_probe_event(struct perf_probe_event *pev) +static int show_perf_probe_event(struct perf_probe_event *pev) { int i, ret; char buf[128]; @@ -951,52 +1077,71 @@ static void show_perf_probe_event(struct perf_probe_event *pev) /* Synthesize only event probe point */ place = synthesize_perf_probe_point(&pev->point); + if (!place) + return -EINVAL; ret = e_snprintf(buf, 128, "%s:%s", pev->group, pev->event); if (ret < 0) - die("Failed to copy event: %s", strerror(-ret)); + return ret; + printf(" %-20s (on %s", buf, place); if (pev->nargs > 0) { printf(" with"); for (i = 0; i < pev->nargs; i++) { - synthesize_perf_probe_arg(&pev->args[i], buf, 128); + ret = synthesize_perf_probe_arg(&pev->args[i], + buf, 128); + if (ret < 0) + break; printf(" %s", buf); } } printf(")\n"); free(place); + return ret; } /* List up current perf-probe events */ -void show_perf_probe_events(void) +int show_perf_probe_events(void) { - int fd; + int fd, ret; struct kprobe_trace_event tev; struct perf_probe_event pev; struct strlist *rawlist; struct str_node *ent; setup_pager(); - init_vmlinux(); + ret = init_vmlinux(); + if (ret < 0) + return ret; memset(&tev, 0, sizeof(tev)); memset(&pev, 0, sizeof(pev)); fd = open_kprobe_events(false); + if (fd < 0) + return fd; + rawlist = get_kprobe_trace_command_rawlist(fd); close(fd); + if (!rawlist) + return -ENOENT; strlist__for_each(ent, rawlist) { - parse_kprobe_trace_command(ent->s, &tev); - convert_to_perf_probe_event(&tev, &pev); - /* Show an event */ - show_perf_probe_event(&pev); + ret = parse_kprobe_trace_command(ent->s, &tev); + if (ret >= 0) { + ret = convert_to_perf_probe_event(&tev, &pev); + if (ret >= 0) + ret = show_perf_probe_event(&pev); + } clear_perf_probe_event(&pev); clear_kprobe_trace_event(&tev); + if (ret < 0) + break; } - strlist__delete(rawlist); + + return ret; } /* Get current perf-probe event names */ @@ -1006,88 +1151,118 @@ static struct strlist *get_kprobe_trace_event_names(int fd, bool include_group) struct strlist *sl, *rawlist; struct str_node *ent; struct kprobe_trace_event tev; + int ret = 0; memset(&tev, 0, sizeof(tev)); rawlist = get_kprobe_trace_command_rawlist(fd); sl = strlist__new(true, NULL); strlist__for_each(ent, rawlist) { - parse_kprobe_trace_command(ent->s, &tev); + ret = parse_kprobe_trace_command(ent->s, &tev); + if (ret < 0) + break; if (include_group) { - if (e_snprintf(buf, 128, "%s:%s", tev.group, - tev.event) < 0) - die("Failed to copy group:event name."); - strlist__add(sl, buf); + ret = e_snprintf(buf, 128, "%s:%s", tev.group, + tev.event); + if (ret >= 0) + ret = strlist__add(sl, buf); } else - strlist__add(sl, tev.event); + ret = strlist__add(sl, tev.event); clear_kprobe_trace_event(&tev); + if (ret < 0) + break; } - strlist__delete(rawlist); + if (ret < 0) { + strlist__delete(sl); + return NULL; + } return sl; } -static void write_kprobe_trace_event(int fd, struct kprobe_trace_event *tev) +static int write_kprobe_trace_event(int fd, struct kprobe_trace_event *tev) { int ret; char *buf = synthesize_kprobe_trace_command(tev); + if (!buf) { + pr_debug("Failed to synthesize kprobe trace event.\n"); + return -EINVAL; + } + pr_debug("Writing event: %s\n", buf); if (!probe_event_dry_run) { ret = write(fd, buf, strlen(buf)); if (ret <= 0) - die("Failed to write event: %s", strerror(errno)); + pr_warning("Failed to write event: %s\n", + strerror(errno)); } free(buf); + return ret; } -static void get_new_event_name(char *buf, size_t len, const char *base, - struct strlist *namelist, bool allow_suffix) +static int get_new_event_name(char *buf, size_t len, const char *base, + struct strlist *namelist, bool allow_suffix) { int i, ret; /* Try no suffix */ ret = e_snprintf(buf, len, "%s", base); - if (ret < 0) - die("snprintf() failed: %s", strerror(-ret)); + if (ret < 0) { + pr_debug("snprintf() failed: %s\n", strerror(-ret)); + return ret; + } if (!strlist__has_entry(namelist, buf)) - return; + return 0; if (!allow_suffix) { pr_warning("Error: event \"%s\" already exists. " "(Use -f to force duplicates.)\n", base); - die("Can't add new event."); + return -EEXIST; } /* Try to add suffix */ for (i = 1; i < MAX_EVENT_INDEX; i++) { ret = e_snprintf(buf, len, "%s_%d", base, i); - if (ret < 0) - die("snprintf() failed: %s", strerror(-ret)); + if (ret < 0) { + pr_debug("snprintf() failed: %s\n", strerror(-ret)); + return ret; + } if (!strlist__has_entry(namelist, buf)) break; } - if (i == MAX_EVENT_INDEX) - die("Too many events are on the same function."); + if (i == MAX_EVENT_INDEX) { + pr_warning("Too many events are on the same function.\n"); + ret = -ERANGE; + } + + return ret; } -static void __add_kprobe_trace_events(struct perf_probe_event *pev, - struct kprobe_trace_event *tevs, - int ntevs, bool allow_suffix) +static int __add_kprobe_trace_events(struct perf_probe_event *pev, + struct kprobe_trace_event *tevs, + int ntevs, bool allow_suffix) { - int i, fd; + int i, fd, ret; struct kprobe_trace_event *tev = NULL; char buf[64]; const char *event, *group; struct strlist *namelist; fd = open_kprobe_events(true); + if (fd < 0) + return fd; /* Get current event names */ namelist = get_kprobe_trace_event_names(fd, false); + if (!namelist) { + pr_debug("Failed to get current event list.\n"); + return -EIO; + } + ret = 0; printf("Add new event%s\n", (ntevs > 1) ? "s:" : ":"); - for (i = 0; i < ntevs; i++) { + for (i = 0; i < ntevs && ret >= 0; i++) { tev = &tevs[i]; if (pev->event) event = pev->event; @@ -1102,12 +1277,17 @@ static void __add_kprobe_trace_events(struct perf_probe_event *pev, group = PERFPROBE_GROUP; /* Get an unused new event name */ - get_new_event_name(buf, 64, event, namelist, allow_suffix); + ret = get_new_event_name(buf, 64, event, + namelist, allow_suffix); + if (ret < 0) + break; event = buf; tev->event = xstrdup(event); tev->group = xstrdup(group); - write_kprobe_trace_event(fd, tev); + ret = write_kprobe_trace_event(fd, tev); + if (ret < 0) + break; /* Add added event name to namelist */ strlist__add(namelist, event); @@ -1129,12 +1309,17 @@ static void __add_kprobe_trace_events(struct perf_probe_event *pev, */ allow_suffix = true; } - /* Show how to use the event. */ - printf("\nYou can now use it on all perf tools, such as:\n\n"); - printf("\tperf record -e %s:%s -a sleep 1\n\n", tev->group, tev->event); + + if (ret >= 0) { + /* Show how to use the event. */ + printf("\nYou can now use it on all perf tools, such as:\n\n"); + printf("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group, + tev->event); + } strlist__delete(namelist); close(fd); + return ret; } static int convert_to_kprobe_trace_events(struct perf_probe_event *pev, @@ -1146,7 +1331,7 @@ static int convert_to_kprobe_trace_events(struct perf_probe_event *pev, /* Convert perf_probe_event with debuginfo */ ntevs = try_to_find_kprobe_trace_events(pev, tevs); - if (ntevs > 0) + if (ntevs != 0) return ntevs; /* Allocate trace event buffer */ @@ -1172,10 +1357,11 @@ static int convert_to_kprobe_trace_events(struct perf_probe_event *pev, /* Currently just checking function name from symbol map */ sym = map__find_symbol_by_name(kmaps[MAP__FUNCTION], tev->point.symbol, NULL); - if (!sym) - die("Kernel symbol \'%s\' not found - probe not added.", - tev->point.symbol); - + if (!sym) { + pr_warning("Kernel symbol \'%s\' not found.\n", + tev->point.symbol); + return -ENOENT; + } return ntevs; } @@ -1185,93 +1371,128 @@ struct __event_package { int ntevs; }; -void add_perf_probe_events(struct perf_probe_event *pevs, int npevs, - bool force_add) +int add_perf_probe_events(struct perf_probe_event *pevs, int npevs, + bool force_add) { - int i; + int i, j, ret; struct __event_package *pkgs; pkgs = xzalloc(sizeof(struct __event_package) * npevs); /* Init vmlinux path */ - init_vmlinux(); + ret = init_vmlinux(); + if (ret < 0) + return ret; /* Loop 1: convert all events */ for (i = 0; i < npevs; i++) { pkgs[i].pev = &pevs[i]; /* Convert with or without debuginfo */ - pkgs[i].ntevs = convert_to_kprobe_trace_events(pkgs[i].pev, - &pkgs[i].tevs); + ret = convert_to_kprobe_trace_events(pkgs[i].pev, + &pkgs[i].tevs); + if (ret < 0) + goto end; + pkgs[i].ntevs = ret; } /* Loop 2: add all events */ + for (i = 0; i < npevs && ret >= 0; i++) + ret = __add_kprobe_trace_events(pkgs[i].pev, pkgs[i].tevs, + pkgs[i].ntevs, force_add); +end: + /* Loop 3: cleanup trace events */ for (i = 0; i < npevs; i++) - __add_kprobe_trace_events(pkgs[i].pev, pkgs[i].tevs, - pkgs[i].ntevs, force_add); - /* TODO: cleanup all trace events? */ + for (j = 0; j < pkgs[i].ntevs; j++) + clear_kprobe_trace_event(&pkgs[i].tevs[j]); + + return ret; } -static void __del_trace_kprobe_event(int fd, struct str_node *ent) +static int __del_trace_kprobe_event(int fd, struct str_node *ent) { char *p; char buf[128]; int ret; /* Convert from perf-probe event to trace-kprobe event */ - if (e_snprintf(buf, 128, "-:%s", ent->s) < 0) - die("Failed to copy event."); + ret = e_snprintf(buf, 128, "-:%s", ent->s); + if (ret < 0) + goto error; + p = strchr(buf + 2, ':'); - if (!p) - die("Internal error: %s should have ':' but not.", ent->s); + if (!p) { + pr_debug("Internal error: %s should have ':' but not.\n", + ent->s); + ret = -ENOTSUP; + goto error; + } *p = '/'; pr_debug("Writing event: %s\n", buf); ret = write(fd, buf, strlen(buf)); - if (ret <= 0) - die("Failed to write event: %s", strerror(errno)); + if (ret < 0) + goto error; + printf("Remove event: %s\n", ent->s); + return 0; +error: + pr_warning("Failed to delete event: %s\n", strerror(-ret)); + return ret; } -static void del_trace_kprobe_event(int fd, const char *group, - const char *event, struct strlist *namelist) +static int del_trace_kprobe_event(int fd, const char *group, + const char *event, struct strlist *namelist) { char buf[128]; struct str_node *ent, *n; - int found = 0; + int found = 0, ret = 0; - if (e_snprintf(buf, 128, "%s:%s", group, event) < 0) - die("Failed to copy event."); + ret = e_snprintf(buf, 128, "%s:%s", group, event); + if (ret < 0) { + pr_err("Failed to copy event."); + return ret; + } if (strpbrk(buf, "*?")) { /* Glob-exp */ strlist__for_each_safe(ent, n, namelist) if (strglobmatch(ent->s, buf)) { found++; - __del_trace_kprobe_event(fd, ent); + ret = __del_trace_kprobe_event(fd, ent); + if (ret < 0) + break; strlist__remove(namelist, ent); } } else { ent = strlist__find(namelist, buf); if (ent) { found++; - __del_trace_kprobe_event(fd, ent); - strlist__remove(namelist, ent); + ret = __del_trace_kprobe_event(fd, ent); + if (ret >= 0) + strlist__remove(namelist, ent); } } - if (found == 0) - pr_info("Info: event \"%s\" does not exist, could not remove it.\n", buf); + if (found == 0 && ret >= 0) + pr_info("Info: Event \"%s\" does not exist.\n", buf); + + return ret; } -void del_perf_probe_events(struct strlist *dellist) +int del_perf_probe_events(struct strlist *dellist) { - int fd; + int fd, ret = 0; const char *group, *event; char *p, *str; struct str_node *ent; struct strlist *namelist; fd = open_kprobe_events(true); + if (fd < 0) + return fd; + /* Get current event names */ namelist = get_kprobe_trace_event_names(fd, true); + if (namelist == NULL) + return -EINVAL; strlist__for_each(ent, dellist) { str = xstrdup(ent->s); @@ -1286,10 +1507,14 @@ void del_perf_probe_events(struct strlist *dellist) event = str; } pr_debug("Group: %s, Event: %s\n", group, event); - del_trace_kprobe_event(fd, group, event, namelist); + ret = del_trace_kprobe_event(fd, group, event, namelist); free(str); + if (ret < 0) + break; } strlist__delete(namelist); close(fd); + + return ret; } diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h index ff2f26b..ab54929 100644 --- a/tools/perf/util/probe-event.h +++ b/tools/perf/util/probe-event.h @@ -89,10 +89,10 @@ struct line_range { }; /* Command string to events */ -extern void parse_perf_probe_command(const char *cmd, - struct perf_probe_event *pev); -extern void parse_kprobe_trace_command(const char *cmd, - struct kprobe_trace_event *tev); +extern int parse_perf_probe_command(const char *cmd, + struct perf_probe_event *pev); +extern int parse_kprobe_trace_command(const char *cmd, + struct kprobe_trace_event *tev); /* Events to command string */ extern char *synthesize_perf_probe_command(struct perf_probe_event *pev); @@ -104,22 +104,22 @@ extern int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, extern bool perf_probe_event_need_dwarf(struct perf_probe_event *pev); /* Convert from kprobe_trace_event to perf_probe_event */ -extern void convert_to_perf_probe_event(struct kprobe_trace_event *tev, - struct perf_probe_event *pev); +extern int convert_to_perf_probe_event(struct kprobe_trace_event *tev, + struct perf_probe_event *pev); /* Release event contents */ extern void clear_perf_probe_event(struct perf_probe_event *pev); extern void clear_kprobe_trace_event(struct kprobe_trace_event *tev); /* Command string to line-range */ -extern void parse_line_range_desc(const char *cmd, struct line_range *lr); +extern int parse_line_range_desc(const char *cmd, struct line_range *lr); -extern void add_perf_probe_events(struct perf_probe_event *pevs, int ntevs, - bool force_add); -extern void del_perf_probe_events(struct strlist *dellist); -extern void show_perf_probe_events(void); -extern void show_line_range(struct line_range *lr); +extern int add_perf_probe_events(struct perf_probe_event *pevs, int ntevs, + bool force_add); +extern int del_perf_probe_events(struct strlist *dellist); +extern int show_perf_probe_events(void); +extern int show_line_range(struct line_range *lr); /* Maximum index number of event-name postfix */ -- cgit v0.10.2 From e334016f1d7250a6523b3a44ccecfe23af6e2f57 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Mon, 12 Apr 2010 13:17:49 -0400 Subject: perf probe: Remove xzalloc() from util/probe-{event, finder}.c Remove all xzalloc() calls from util/probe-{event,finder}.c since it may cause 'sudden death' in utility functions and it makes reusing it from other code difficult. Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Frederic Weisbecker LKML-Reference: <20100412171749.3790.33303.stgit@localhost6.localdomain6> Signed-off-by: Masami Hiramatsu Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index bd68f7b..aacbf73 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -556,7 +556,9 @@ static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg) fieldp = &arg->field; do { - *fieldp = xzalloc(sizeof(struct perf_probe_arg_field)); + *fieldp = zalloc(sizeof(struct perf_probe_arg_field)); + if (*fieldp == NULL) + return -ENOMEM; if (*tmp == '.') { str = tmp + 1; (*fieldp)->ref = false; @@ -608,7 +610,11 @@ int parse_perf_probe_command(const char *cmd, struct perf_probe_event *pev) /* Copy arguments and ensure return probe has no C argument */ pev->nargs = argc - 1; - pev->args = xzalloc(sizeof(struct perf_probe_arg) * pev->nargs); + pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs); + if (pev->args == NULL) { + ret = -ENOMEM; + goto out; + } for (i = 0; i < pev->nargs && ret >= 0; i++) { ret = parse_perf_probe_arg(argv[i + 1], &pev->args[i]); if (ret >= 0 && @@ -680,7 +686,11 @@ int parse_kprobe_trace_command(const char *cmd, struct kprobe_trace_event *tev) tp->offset = 0; tev->nargs = argc - 2; - tev->args = xzalloc(sizeof(struct kprobe_trace_arg) * tev->nargs); + tev->args = zalloc(sizeof(struct kprobe_trace_arg) * tev->nargs); + if (tev->args == NULL) { + ret = -ENOMEM; + goto out; + } for (i = 0; i < tev->nargs; i++) { p = strchr(argv[i + 2], '='); if (p) /* We don't need which register is assigned. */ @@ -745,7 +755,11 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp) char offs[32] = "", line[32] = "", file[32] = ""; int ret, len; - buf = xzalloc(MAX_CMDLEN); + buf = zalloc(MAX_CMDLEN); + if (buf == NULL) { + ret = -ENOMEM; + goto error; + } if (pp->offset) { ret = e_snprintf(offs, 32, "+%lu", pp->offset); if (ret <= 0) @@ -781,7 +795,8 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp) error: pr_debug("Failed to synthesize perf probe point: %s", strerror(-ret)); - free(buf); + if (buf) + free(buf); return NULL; } @@ -890,7 +905,10 @@ char *synthesize_kprobe_trace_command(struct kprobe_trace_event *tev) char *buf; int i, len, ret; - buf = xzalloc(MAX_CMDLEN); + buf = zalloc(MAX_CMDLEN); + if (buf == NULL) + return NULL; + len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s+%lu", tp->retprobe ? 'r' : 'p', tev->group, tev->event, @@ -929,7 +947,9 @@ int convert_to_perf_probe_event(struct kprobe_trace_event *tev, /* Convert trace_arg to probe_arg */ pev->nargs = tev->nargs; - pev->args = xzalloc(sizeof(struct perf_probe_arg) * pev->nargs); + pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs); + if (pev->args == NULL) + return -ENOMEM; for (i = 0; i < tev->nargs && ret >= 0; i++) if (tev->args[i].name) pev->args[i].name = xstrdup(tev->args[i].name); @@ -1326,25 +1346,31 @@ static int convert_to_kprobe_trace_events(struct perf_probe_event *pev, struct kprobe_trace_event **tevs) { struct symbol *sym; - int ntevs = 0, i; + int ret = 0, i; struct kprobe_trace_event *tev; /* Convert perf_probe_event with debuginfo */ - ntevs = try_to_find_kprobe_trace_events(pev, tevs); - if (ntevs != 0) - return ntevs; + ret = try_to_find_kprobe_trace_events(pev, tevs); + if (ret != 0) + return ret; /* Allocate trace event buffer */ - ntevs = 1; - tev = *tevs = xzalloc(sizeof(struct kprobe_trace_event)); + tev = *tevs = zalloc(sizeof(struct kprobe_trace_event)); + if (tev == NULL) + return -ENOMEM; /* Copy parameters */ tev->point.symbol = xstrdup(pev->point.function); tev->point.offset = pev->point.offset; tev->nargs = pev->nargs; if (tev->nargs) { - tev->args = xzalloc(sizeof(struct kprobe_trace_arg) - * tev->nargs); + tev->args = zalloc(sizeof(struct kprobe_trace_arg) + * tev->nargs); + if (tev->args == NULL) { + free(tev); + *tevs = NULL; + return -ENOMEM; + } for (i = 0; i < tev->nargs; i++) { if (pev->args[i].name) tev->args[i].name = xstrdup(pev->args[i].name); @@ -1360,9 +1386,14 @@ static int convert_to_kprobe_trace_events(struct perf_probe_event *pev, if (!sym) { pr_warning("Kernel symbol \'%s\' not found.\n", tev->point.symbol); + clear_kprobe_trace_event(tev); + free(tev); + *tevs = NULL; return -ENOENT; - } - return ntevs; + } else + ret = 1; + + return ret; } struct __event_package { @@ -1377,7 +1408,9 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs, int i, j, ret; struct __event_package *pkgs; - pkgs = xzalloc(sizeof(struct __event_package) * npevs); + pkgs = zalloc(sizeof(struct __event_package) * npevs); + if (pkgs == NULL) + return -ENOMEM; /* Init vmlinux path */ ret = init_vmlinux(); diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 54daa91..ce1ac82 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -111,7 +111,7 @@ static int strtailcmp(const char *s1, const char *s2) /* Line number list operations */ /* Add a line to line number list */ -static void line_list__add_line(struct list_head *head, unsigned int line) +static int line_list__add_line(struct list_head *head, unsigned int line) { struct line_node *ln; struct list_head *p; @@ -122,16 +122,19 @@ static void line_list__add_line(struct list_head *head, unsigned int line) p = &ln->list; goto found; } else if (ln->line == line) /* Already exist */ - return ; + return 1; } /* List is empty, or the smallest entry */ p = head; found: pr_debug("line list: add a line %u\n", line); - ln = xzalloc(sizeof(struct line_node)); + ln = zalloc(sizeof(struct line_node)); + if (ln == NULL) + return -ENOMEM; ln->line = line; INIT_LIST_HEAD(&ln->list); list_add(&ln->list, p); + return 0; } /* Check if the line in line number list */ @@ -423,7 +426,9 @@ static int convert_location(Dwarf_Op *op, struct probe_finder *pf) tvar->value = xstrdup(regs); if (ref) { - tvar->ref = xzalloc(sizeof(struct kprobe_trace_arg_ref)); + tvar->ref = zalloc(sizeof(struct kprobe_trace_arg_ref)); + if (tvar->ref == NULL) + return -ENOMEM; tvar->ref->offset = (long)offs; } return 0; @@ -500,7 +505,9 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, return -EINVAL; } - ref = xzalloc(sizeof(struct kprobe_trace_arg_ref)); + ref = zalloc(sizeof(struct kprobe_trace_arg_ref)); + if (ref == NULL) + return -ENOMEM; if (*ref_ptr) (*ref_ptr)->next = ref; else @@ -680,7 +687,9 @@ static int convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf) /* Find each argument */ tev->nargs = pf->pev->nargs; - tev->args = xzalloc(sizeof(struct kprobe_trace_arg) * tev->nargs); + tev->args = zalloc(sizeof(struct kprobe_trace_arg) * tev->nargs); + if (tev->args == NULL) + return -ENOMEM; for (i = 0; i < pf->pev->nargs; i++) { pf->pvar = &pf->pev->args[i]; pf->tvar = &tev->args[i]; @@ -938,7 +947,9 @@ int find_kprobe_trace_events(int fd, struct perf_probe_event *pev, Dwarf *dbg; int ret = 0; - pf.tevs = xzalloc(sizeof(struct kprobe_trace_event) * MAX_PROBES); + pf.tevs = zalloc(sizeof(struct kprobe_trace_event) * MAX_PROBES); + if (pf.tevs == NULL) + return -ENOMEM; *tevs = pf.tevs; pf.ntevs = 0; -- cgit v0.10.2 From 02b95dadc8a1d2c302513e5fa24c492380d26e93 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Mon, 12 Apr 2010 13:17:56 -0400 Subject: perf probe: Remove xstrdup()/xstrndup() from util/probe-{event, finder}.c Remove all xstr*dup() calls from util/probe-{event,finder}.c since it may cause 'sudden death' in utility functions and it makes reusing it from other code difficult. Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Frederic Weisbecker LKML-Reference: <20100412171756.3790.89607.stgit@localhost6.localdomain6> Signed-off-by: Masami Hiramatsu Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index aacbf73..ca108b2 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -133,7 +133,9 @@ static int convert_to_perf_probe_point(struct kprobe_trace_point *tp, if (ret <= 0) { pr_debug("Failed to find corresponding probes from " "debuginfo. Use kprobe event information.\n"); - pp->function = xstrdup(tp->symbol); + pp->function = strdup(tp->symbol); + if (pp->function == NULL) + return -ENOMEM; pp->offset = tp->offset; } pp->retprobe = tp->retprobe; @@ -300,7 +302,9 @@ end: static int convert_to_perf_probe_point(struct kprobe_trace_point *tp, struct perf_probe_point *pp) { - pp->function = xstrdup(tp->symbol); + pp->function = strdup(tp->symbol); + if (pp->function == NULL) + return -ENOMEM; pp->offset = tp->offset; pp->retprobe = tp->retprobe; @@ -355,9 +359,12 @@ int parse_line_range_desc(const char *arg, struct line_range *lr) *tmp); return -EINVAL; } - tmp = xstrndup(arg, (ptr - arg)); + tmp = strndup(arg, (ptr - arg)); } else - tmp = xstrdup(arg); + tmp = strdup(arg); + + if (tmp == NULL) + return -ENOMEM; if (strchr(tmp, '.')) lr->file = tmp; @@ -406,7 +413,9 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) "follow C symbol-naming rule.\n", arg); return -EINVAL; } - pev->event = xstrdup(arg); + pev->event = strdup(arg); + if (pev->event == NULL) + return -ENOMEM; pev->group = NULL; arg = tmp; } @@ -417,18 +426,24 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) *ptr++ = '\0'; } + tmp = strdup(arg); + if (tmp == NULL) + return -ENOMEM; + /* Check arg is function or file and copy it */ - if (strchr(arg, '.')) /* File */ - pp->file = xstrdup(arg); + if (strchr(tmp, '.')) /* File */ + pp->file = tmp; else /* Function */ - pp->function = xstrdup(arg); + pp->function = tmp; /* Parse other options */ while (ptr) { arg = ptr; c = nc; if (c == ';') { /* Lazy pattern must be the last part */ - pp->lazy_line = xstrdup(arg); + pp->lazy_line = strdup(arg); + if (pp->lazy_line == NULL) + return -ENOMEM; break; } ptr = strpbrk(arg, ";:+@%"); @@ -458,7 +473,9 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) semantic_error("SRC@SRC is not allowed.\n"); return -EINVAL; } - pp->file = xstrdup(arg); + pp->file = strdup(arg); + if (pp->file == NULL) + return -ENOMEM; break; case '%': /* Probe places */ if (strcmp(arg, "return") == 0) { @@ -530,7 +547,9 @@ static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg) tmp = strchr(str, '='); if (tmp) { - arg->name = xstrndup(str, tmp - str); + arg->name = strndup(str, tmp - str); + if (arg->name == NULL) + return -ENOMEM; pr_debug("name:%s ", arg->name); str = tmp + 1; } @@ -538,20 +557,26 @@ static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg) tmp = strchr(str, ':'); if (tmp) { /* Type setting */ *tmp = '\0'; - arg->type = xstrdup(tmp + 1); + arg->type = strdup(tmp + 1); + if (arg->type == NULL) + return -ENOMEM; pr_debug("type:%s ", arg->type); } tmp = strpbrk(str, "-."); if (!is_c_varname(str) || !tmp) { /* A variable, register, symbol or special value */ - arg->var = xstrdup(str); + arg->var = strdup(str); + if (arg->var == NULL) + return -ENOMEM; pr_debug("%s\n", arg->var); return 0; } /* Structure fields */ - arg->var = xstrndup(str, tmp - str); + arg->var = strndup(str, tmp - str); + if (arg->var == NULL) + return -ENOMEM; pr_debug("%s, ", arg->var); fieldp = &arg->field; @@ -572,18 +597,24 @@ static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg) tmp = strpbrk(str, "-."); if (tmp) { - (*fieldp)->name = xstrndup(str, tmp - str); + (*fieldp)->name = strndup(str, tmp - str); + if ((*fieldp)->name == NULL) + return -ENOMEM; pr_debug("%s(%d), ", (*fieldp)->name, (*fieldp)->ref); fieldp = &(*fieldp)->next; } } while (tmp); - (*fieldp)->name = xstrdup(str); + (*fieldp)->name = strdup(str); + if ((*fieldp)->name == NULL) + return -ENOMEM; pr_debug("%s(%d)\n", (*fieldp)->name, (*fieldp)->ref); /* If no name is specified, set the last field name */ - if (!arg->name) - arg->name = xstrdup((*fieldp)->name); - + if (!arg->name) { + arg->name = strdup((*fieldp)->name); + if (arg->name == NULL) + return -ENOMEM; + } return 0; } @@ -697,9 +728,13 @@ int parse_kprobe_trace_command(const char *cmd, struct kprobe_trace_event *tev) *p++ = '\0'; else p = argv[i + 2]; - tev->args[i].name = xstrdup(argv[i + 2]); + tev->args[i].name = strdup(argv[i + 2]); /* TODO: parse regs and offset */ - tev->args[i].value = xstrdup(p); + tev->args[i].value = strdup(p); + if (tev->args[i].name == NULL || tev->args[i].value == NULL) { + ret = -ENOMEM; + goto out; + } } ret = 0; out: @@ -933,12 +968,14 @@ error: int convert_to_perf_probe_event(struct kprobe_trace_event *tev, struct perf_probe_event *pev) { - char buf[64]; + char buf[64] = ""; int i, ret; /* Convert event/group name */ - pev->event = xstrdup(tev->event); - pev->group = xstrdup(tev->group); + pev->event = strdup(tev->event); + pev->group = strdup(tev->group); + if (pev->event == NULL || pev->group == NULL) + return -ENOMEM; /* Convert trace_point to probe_point */ ret = convert_to_perf_probe_point(&tev->point, &pev->point); @@ -950,14 +987,17 @@ int convert_to_perf_probe_event(struct kprobe_trace_event *tev, pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs); if (pev->args == NULL) return -ENOMEM; - for (i = 0; i < tev->nargs && ret >= 0; i++) + for (i = 0; i < tev->nargs && ret >= 0; i++) { if (tev->args[i].name) - pev->args[i].name = xstrdup(tev->args[i].name); + pev->args[i].name = strdup(tev->args[i].name); else { ret = synthesize_kprobe_trace_arg(&tev->args[i], buf, 64); - pev->args[i].name = xstrdup(buf); + pev->args[i].name = strdup(buf); } + if (pev->args[i].name == NULL && ret >= 0) + ret = -ENOMEM; + } if (ret < 0) clear_perf_probe_event(pev); @@ -1282,7 +1322,7 @@ static int __add_kprobe_trace_events(struct perf_probe_event *pev, ret = 0; printf("Add new event%s\n", (ntevs > 1) ? "s:" : ":"); - for (i = 0; i < ntevs && ret >= 0; i++) { + for (i = 0; i < ntevs; i++) { tev = &tevs[i]; if (pev->event) event = pev->event; @@ -1303,8 +1343,12 @@ static int __add_kprobe_trace_events(struct perf_probe_event *pev, break; event = buf; - tev->event = xstrdup(event); - tev->group = xstrdup(group); + tev->event = strdup(event); + tev->group = strdup(group); + if (tev->event == NULL || tev->group == NULL) { + ret = -ENOMEM; + break; + } ret = write_kprobe_trace_event(fd, tev); if (ret < 0) break; @@ -1360,23 +1404,40 @@ static int convert_to_kprobe_trace_events(struct perf_probe_event *pev, return -ENOMEM; /* Copy parameters */ - tev->point.symbol = xstrdup(pev->point.function); + tev->point.symbol = strdup(pev->point.function); + if (tev->point.symbol == NULL) { + ret = -ENOMEM; + goto error; + } tev->point.offset = pev->point.offset; tev->nargs = pev->nargs; if (tev->nargs) { tev->args = zalloc(sizeof(struct kprobe_trace_arg) * tev->nargs); if (tev->args == NULL) { - free(tev); - *tevs = NULL; - return -ENOMEM; + ret = -ENOMEM; + goto error; } for (i = 0; i < tev->nargs; i++) { - if (pev->args[i].name) - tev->args[i].name = xstrdup(pev->args[i].name); - tev->args[i].value = xstrdup(pev->args[i].var); - if (pev->args[i].type) - tev->args[i].type = xstrdup(pev->args[i].type); + if (pev->args[i].name) { + tev->args[i].name = strdup(pev->args[i].name); + if (tev->args[i].name == NULL) { + ret = -ENOMEM; + goto error; + } + } + tev->args[i].value = strdup(pev->args[i].var); + if (tev->args[i].value == NULL) { + ret = -ENOMEM; + goto error; + } + if (pev->args[i].type) { + tev->args[i].type = strdup(pev->args[i].type); + if (tev->args[i].type == NULL) { + ret = -ENOMEM; + goto error; + } + } } } @@ -1386,13 +1447,15 @@ static int convert_to_kprobe_trace_events(struct perf_probe_event *pev, if (!sym) { pr_warning("Kernel symbol \'%s\' not found.\n", tev->point.symbol); - clear_kprobe_trace_event(tev); - free(tev); - *tevs = NULL; - return -ENOENT; - } else - ret = 1; + ret = -ENOENT; + goto error; + } + return 1; +error: + clear_kprobe_trace_event(tev); + free(tev); + *tevs = NULL; return ret; } @@ -1528,7 +1591,11 @@ int del_perf_probe_events(struct strlist *dellist) return -EINVAL; strlist__for_each(ent, dellist) { - str = xstrdup(ent->s); + str = strdup(ent->s); + if (str == NULL) { + ret = -ENOMEM; + break; + } pr_debug("Parsing: %s\n", str); p = strchr(str, ':'); if (p) { diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index ce1ac82..e443e69 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -424,7 +424,10 @@ static int convert_location(Dwarf_Op *op, struct probe_finder *pf) return -ERANGE; } - tvar->value = xstrdup(regs); + tvar->value = strdup(regs); + if (tvar->value == NULL) + return -ENOMEM; + if (ref) { tvar->ref = zalloc(sizeof(struct kprobe_trace_arg_ref)); if (tvar->ref == NULL) @@ -466,7 +469,9 @@ static int convert_variable_type(Dwarf_Die *vr_die, strerror(-ret)); return ret; } - targ->type = xstrdup(buf); + targ->type = strdup(buf); + if (targ->type == NULL) + return -ENOMEM; } return 0; } @@ -576,9 +581,11 @@ static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf) vr_die = &die_mem; } if (ret == 0) { - if (pf->pvar->type) - pf->tvar->type = xstrdup(pf->pvar->type); - else + if (pf->pvar->type) { + pf->tvar->type = strdup(pf->pvar->type); + if (pf->tvar->type == NULL) + ret = -ENOMEM; + } else ret = convert_variable_type(vr_die, pf->tvar); } /* *expr will be cached in libdw. Don't free it. */ @@ -595,22 +602,30 @@ static int find_variable(Dwarf_Die *sp_die, struct probe_finder *pf) { Dwarf_Die vr_die; char buf[32], *ptr; + int ret; /* TODO: Support arrays */ if (pf->pvar->name) - pf->tvar->name = xstrdup(pf->pvar->name); + pf->tvar->name = strdup(pf->pvar->name); else { - synthesize_perf_probe_arg(pf->pvar, buf, 32); + ret = synthesize_perf_probe_arg(pf->pvar, buf, 32); + if (ret < 0) + return ret; ptr = strchr(buf, ':'); /* Change type separator to _ */ if (ptr) *ptr = '_'; - pf->tvar->name = xstrdup(buf); + pf->tvar->name = strdup(buf); } + if (pf->tvar->name == NULL) + return -ENOMEM; if (!is_c_varname(pf->pvar->var)) { /* Copy raw parameters */ - pf->tvar->value = xstrdup(pf->pvar->var); - return 0; + pf->tvar->value = strdup(pf->pvar->var); + if (pf->tvar->value == NULL) + return -ENOMEM; + else + return 0; } pr_debug("Searching '%s' variable in context.\n", @@ -660,7 +675,9 @@ static int convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf) dwarf_diename(sp_die)); return -ENOENT; } - tev->point.symbol = xstrdup(name); + tev->point.symbol = strdup(name); + if (tev->point.symbol == NULL) + return -ENOMEM; tev->point.offset = (unsigned long)(pf->addr - eaddr); } else /* This function has no name. */ @@ -1028,7 +1045,11 @@ int find_perf_probe_point(int fd, unsigned long addr, tmp = dwarf_linesrc(line, NULL, NULL); if (tmp) { ppt->line = lineno; - ppt->file = xstrdup(tmp); + ppt->file = strdup(tmp); + if (ppt->file == NULL) { + ret = -ENOMEM; + goto end; + } found = true; } } @@ -1064,7 +1085,11 @@ int find_perf_probe_point(int fd, unsigned long addr, /* We don't have a line number, let's use offset */ ppt->offset = addr - (unsigned long)eaddr; found: - ppt->function = xstrdup(tmp); + ppt->function = strdup(tmp); + if (ppt->function == NULL) { + ret = -ENOMEM; + goto end; + } found = true; } @@ -1116,8 +1141,11 @@ static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf) continue; /* Copy real path */ - if (!lf->lr->path) - lf->lr->path = xstrdup(src); + if (!lf->lr->path) { + lf->lr->path = strdup(src); + if (lf->lr->path == NULL) + return -ENOMEM; + } line_list__add_line(&lf->lr->line_list, (unsigned int)lineno); } /* Update status */ -- cgit v0.10.2 From 7ca5989dd065cbc48a958666c273794686ea7525 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Wed, 14 Apr 2010 18:39:28 -0400 Subject: perf probe: Fix to use correct debugfs path finder Instead of using debugfs_path, use debugfs_find_mountpoint() to find actual debugfs path. LKML-Reference: <20100414223928.14630.38326.stgit@localhost6.localdomain6> Signed-off-by: Masami Hiramatsu Reported-by: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Frederic Weisbecker Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index 64bc11a..c1e5403 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c @@ -40,7 +40,6 @@ #include "util/debug.h" #include "util/debugfs.h" #include "util/parse-options.h" -#include "util/parse-events.h" /* For debugfs_path */ #include "util/probe-finder.h" #include "util/probe-event.h" @@ -205,9 +204,6 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) !params.show_lines)) usage_with_options(probe_usage, options); - if (debugfs_valid_mountpoint(debugfs_path) < 0) - die("Failed to find debugfs path."); - if (params.list_events) { if (params.nevents != 0 || params.dellist) { pr_err(" Error: Don't use --list with --add/--del.\n"); diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index ca108b2..1c4a20a 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -42,8 +42,8 @@ #include "color.h" #include "symbol.h" #include "thread.h" +#include "debugfs.h" #include "trace-event.h" /* For __unused */ -#include "parse-events.h" /* For debugfs_path */ #include "probe-event.h" #include "probe-finder.h" @@ -1075,10 +1075,18 @@ void clear_kprobe_trace_event(struct kprobe_trace_event *tev) static int open_kprobe_events(bool readwrite) { char buf[PATH_MAX]; + const char *__debugfs; int ret; - ret = e_snprintf(buf, PATH_MAX, "%s/../kprobe_events", debugfs_path); + __debugfs = debugfs_find_mountpoint(); + if (__debugfs == NULL) { + pr_warning("Debugfs is not mounted.\n"); + return -ENOENT; + } + + ret = e_snprintf(buf, PATH_MAX, "%stracing/kprobe_events", __debugfs); if (ret >= 0) { + pr_debug("Opening %s write=%d\n", buf, readwrite); if (readwrite && !probe_event_dry_run) ret = open(buf, O_RDWR, O_APPEND); else -- cgit v0.10.2 From dd259c5db26ccda46409dbf6efc79d5a2b259e38 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Wed, 14 Apr 2010 18:39:35 -0400 Subject: perf probe: Fix mis-estimation for shortening filename Fix mis-estimation size for making a short filename. Since the buffer size is 32 bytes and there are '@' prefix and '\0' termination, maximum shorten filename length should be 30. This means, before searching '/', it should be 31 bytes. LKML-Reference: <20100414223935.14630.11954.stgit@localhost6.localdomain6> Signed-off-by: Masami Hiramatsu Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Frederic Weisbecker Cc: Ingo Molnar Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 1c4a20a..6d43839 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -806,12 +806,12 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp) goto error; } if (pp->file) { - len = strlen(pp->file) - 32; + len = strlen(pp->file) - 31; if (len < 0) len = 0; tmp = strchr(pp->file + len, '/'); if (!tmp) - tmp = pp->file + len - 1; + tmp = pp->file + len; ret = e_snprintf(file, 32, "@%s", tmp + 1); if (ret <= 0) goto error; -- cgit v0.10.2 From d3b63d7ae04879a817bac5c0bf09749f73629d32 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Wed, 14 Apr 2010 18:39:42 -0400 Subject: perf probe: Fix a bug that --line range can be overflow Since line_finder.lno_s/e are signed int but line_range.start/end are unsigned int, it is possible to be overflow when converting line_range->start/end to line_finder->lno_s/e. This changes line_range.start/end and line_list.line to signed int and adds overflow checks when setting line_finder.lno_s/e. LKML-Reference: <20100414223942.14630.72730.stgit@localhost6.localdomain6> Signed-off-by: Masami Hiramatsu Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Frederic Weisbecker Cc: Ingo Molnar Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 6d43839..954ca21 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -189,7 +189,7 @@ static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev, #define LINEBUF_SIZE 256 #define NR_ADDITIONAL_LINES 2 -static int show_one_line(FILE *fp, unsigned int l, bool skip, bool show_num) +static int show_one_line(FILE *fp, int l, bool skip, bool show_num) { char buf[LINEBUF_SIZE]; const char *color = PERF_COLOR_BLUE; @@ -198,7 +198,7 @@ static int show_one_line(FILE *fp, unsigned int l, bool skip, bool show_num) goto error; if (!skip) { if (show_num) - fprintf(stdout, "%7u %s", l, buf); + fprintf(stdout, "%7d %s", l, buf); else color_fprintf(stdout, color, " %s", buf); } @@ -231,7 +231,7 @@ error: */ int show_line_range(struct line_range *lr) { - unsigned int l = 1; + int l = 1; struct line_node *ln; FILE *fp; int fd, ret; @@ -340,16 +340,15 @@ int parse_line_range_desc(const char *arg, struct line_range *lr) */ ptr = strchr(arg, ':'); if (ptr) { - lr->start = (unsigned int)strtoul(ptr + 1, &tmp, 0); + lr->start = (int)strtoul(ptr + 1, &tmp, 0); if (*tmp == '+') - lr->end = lr->start + (unsigned int)strtoul(tmp + 1, - &tmp, 0); + lr->end = lr->start + (int)strtoul(tmp + 1, &tmp, 0); else if (*tmp == '-') - lr->end = (unsigned int)strtoul(tmp + 1, &tmp, 0); + lr->end = (int)strtoul(tmp + 1, &tmp, 0); else - lr->end = 0; - pr_debug("Line range is %u to %u\n", lr->start, lr->end); - if (lr->end && lr->start > lr->end) { + lr->end = INT_MAX; + pr_debug("Line range is %d to %d\n", lr->start, lr->end); + if (lr->start > lr->end) { semantic_error("Start line must be smaller" " than end line.\n"); return -EINVAL; @@ -360,8 +359,10 @@ int parse_line_range_desc(const char *arg, struct line_range *lr) return -EINVAL; } tmp = strndup(arg, (ptr - arg)); - } else + } else { tmp = strdup(arg); + lr->end = INT_MAX; + } if (tmp == NULL) return -ENOMEM; diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h index ab54929..e7ff0d0 100644 --- a/tools/perf/util/probe-event.h +++ b/tools/perf/util/probe-event.h @@ -74,15 +74,15 @@ struct perf_probe_event { /* Line number container */ struct line_node { struct list_head list; - unsigned int line; + int line; }; /* Line range */ struct line_range { char *file; /* File name */ char *function; /* Function name */ - unsigned int start; /* Start line number */ - unsigned int end; /* End line number */ + int start; /* Start line number */ + int end; /* End line number */ int offset; /* Start line offset */ char *path; /* Real path name */ struct list_head line_list; /* Visible lines */ diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index e443e69..b4c9365 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -111,7 +111,7 @@ static int strtailcmp(const char *s1, const char *s2) /* Line number list operations */ /* Add a line to line number list */ -static int line_list__add_line(struct list_head *head, unsigned int line) +static int line_list__add_line(struct list_head *head, int line) { struct line_node *ln; struct list_head *p; @@ -138,7 +138,7 @@ found: } /* Check if the line in line number list */ -static int line_list__has_line(struct list_head *head, unsigned int line) +static int line_list__has_line(struct list_head *head, int line) { struct line_node *ln; @@ -1146,7 +1146,7 @@ static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf) if (lf->lr->path == NULL) return -ENOMEM; } - line_list__add_line(&lf->lr->line_list, (unsigned int)lineno); + line_list__add_line(&lf->lr->line_list, lineno); } /* Update status */ if (!list_empty(&lf->lr->line_list)) @@ -1179,10 +1179,12 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data) dwarf_decl_line(sp_die, &lr->offset); pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset); lf->lno_s = lr->offset + lr->start; - if (!lr->end) + if (lf->lno_s < 0) /* Overflow */ + lf->lno_s = INT_MAX; + lf->lno_e = lr->offset + lr->end; + if (lf->lno_e < 0) /* Overflow */ lf->lno_e = INT_MAX; - else - lf->lno_e = lr->offset + lr->end; + pr_debug("New line range: %d to %d\n", lf->lno_s, lf->lno_e); lr->start = lf->lno_s; lr->end = lf->lno_e; if (dwarf_func_inline(sp_die)) { @@ -1244,10 +1246,7 @@ int find_line_range(int fd, struct line_range *lr) ret = find_line_range_by_func(&lf); else { lf.lno_s = lr->start; - if (!lr->end) - lf.lno_e = INT_MAX; - else - lf.lno_e = lr->end; + lf.lno_e = lr->end; ret = find_line_range_by_line(NULL, &lf); } } -- cgit v0.10.2 From dda4ab34fe1905d3d590572b776dd92aa0866558 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Wed, 14 Apr 2010 18:39:50 -0400 Subject: perf probe: Fix line range to show end line Line range should reject the range if the number of lines is 0 (e.g. "sched.c:1024+0"), and it should show the lines include the end of line number (e.g. "sched.c:1024-2048" should show 2048th line). LKML-Reference: <20100414223950.14630.42263.stgit@localhost6.localdomain6> Signed-off-by: Masami Hiramatsu Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Frederic Weisbecker Cc: Ingo Molnar Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 954ca21..5bf8ab0 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -290,7 +290,7 @@ int show_line_range(struct line_range *lr) if (lr->end == INT_MAX) lr->end = l + NR_ADDITIONAL_LINES; - while (l < lr->end && !feof(fp) && ret >= 0) + while (l <= lr->end && !feof(fp) && ret >= 0) ret = show_one_line(fp, (l++) - lr->offset, false, false); end: fclose(fp); @@ -341,9 +341,15 @@ int parse_line_range_desc(const char *arg, struct line_range *lr) ptr = strchr(arg, ':'); if (ptr) { lr->start = (int)strtoul(ptr + 1, &tmp, 0); - if (*tmp == '+') + if (*tmp == '+') { lr->end = lr->start + (int)strtoul(tmp + 1, &tmp, 0); - else if (*tmp == '-') + lr->end--; /* + * Adjust the number of lines here. + * If the number of lines == 1, the + * the end of line should be equal to + * the start of line. + */ + } else if (*tmp == '-') lr->end = (int)strtoul(tmp + 1, &tmp, 0); else lr->end = INT_MAX; -- cgit v0.10.2 From de1439d8a521d22c3219fc007a570fcf944ac789 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Wed, 14 Apr 2010 17:44:00 -0300 Subject: perf probe: Support DW_OP_plus_uconst in DW_AT_data_member_location MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DW_OP_plus_uconst can be used for DW_AT_data_member_location. This patch adds DW_OP_plus_uconst support when getting structure member offset. Commiter note: Fixed up the size_t format specifier in one case: cc1: warnings being treated as errors util/probe-finder.c: In function ‘die_get_data_member_location’: util/probe-finder.c:270: error: format ‘%d’ expects type ‘int’, but argument 4 has type ‘size_t’ make: *** [/home/acme/git/build/perf/util/probe-finder.o] Error 1 LKML-Reference: <20100414223958.14630.5230.stgit@localhost6.localdomain6> Signed-off-by: Masami Hiramatsu Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Frederic Weisbecker Cc: Ingo Molnar Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index b4c9365..03b4691 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -249,6 +249,33 @@ static int die_get_byte_size(Dwarf_Die *tp_die) return (int)ret; } +/* Get data_member_location offset */ +static int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs) +{ + Dwarf_Attribute attr; + Dwarf_Op *expr; + size_t nexpr; + int ret; + + if (dwarf_attr(mb_die, DW_AT_data_member_location, &attr) == NULL) + return -ENOENT; + + if (dwarf_formudata(&attr, offs) != 0) { + /* DW_AT_data_member_location should be DW_OP_plus_uconst */ + ret = dwarf_getlocation(&attr, &expr, &nexpr); + if (ret < 0 || nexpr == 0) + return -ENOENT; + + if (expr[0].atom != DW_OP_plus_uconst || nexpr != 1) { + pr_debug("Unable to get offset:Unexpected OP %x (%zd)\n", + expr[0].atom, nexpr); + return -ENOTSUP; + } + *offs = (Dwarf_Word)expr[0].number; + } + return 0; +} + /* Return values for die_find callbacks */ enum { DIE_FIND_CB_FOUND = 0, /* End of Search */ @@ -482,9 +509,9 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, Dwarf_Die *die_mem) { struct kprobe_trace_arg_ref *ref = *ref_ptr; - Dwarf_Attribute attr; Dwarf_Die type; Dwarf_Word offs; + int ret; pr_debug("converting %s in %s\n", field->name, varname); if (die_get_real_type(vr_die, &type) == NULL) { @@ -542,17 +569,17 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, } /* Get the offset of the field */ - if (dwarf_attr(die_mem, DW_AT_data_member_location, &attr) == NULL || - dwarf_formudata(&attr, &offs) != 0) { + ret = die_get_data_member_location(die_mem, &offs); + if (ret < 0) { pr_warning("Failed to get the offset of %s.\n", field->name); - return -ENOENT; + return ret; } ref->offset += (long)offs; /* Converting next field */ if (field->next) return convert_variable_fields(die_mem, field->name, - field->next, &ref, die_mem); + field->next, &ref, die_mem); else return 0; } -- cgit v0.10.2 From f6c903f5856ffa75ae19dcee4dbb5093e320d45c Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Wed, 14 Apr 2010 18:40:07 -0400 Subject: perf probe: Show function entry line as probe-able Function entry line should be shown as probe-able line, because each function has declared line attribute. LKML-Reference: <20100414224007.14630.96915.stgit@localhost6.localdomain6> Signed-off-by: Masami Hiramatsu Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Frederic Weisbecker Cc: Ingo Molnar Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 03b4691..3e79775 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -1127,6 +1127,45 @@ end: return ret; } +/* Add a line and store the src path */ +static int line_range_add_line(const char *src, unsigned int lineno, + struct line_range *lr) +{ + /* Copy real path */ + if (!lr->path) { + lr->path = strdup(src); + if (lr->path == NULL) + return -ENOMEM; + } + return line_list__add_line(&lr->line_list, lineno); +} + +/* Search function declaration lines */ +static int line_range_funcdecl_cb(Dwarf_Die *sp_die, void *data) +{ + struct dwarf_callback_param *param = data; + struct line_finder *lf = param->data; + const char *src; + int lineno; + + src = dwarf_decl_file(sp_die); + if (src && strtailcmp(src, lf->fname) != 0) + return DWARF_CB_OK; + + if (dwarf_decl_line(sp_die, &lineno) != 0 || + (lf->lno_s > lineno || lf->lno_e < lineno)) + return DWARF_CB_OK; + + param->retval = line_range_add_line(src, lineno, lf->lr); + return DWARF_CB_OK; +} + +static int find_line_range_func_decl_lines(struct line_finder *lf) +{ + struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0}; + dwarf_getfuncs(&lf->cu_die, line_range_funcdecl_cb, ¶m, 0); + return param.retval; +} /* Find line range from its line number */ static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf) @@ -1135,7 +1174,7 @@ static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf) Dwarf_Line *line; size_t nlines, i; Dwarf_Addr addr; - int lineno; + int lineno, ret = 0; const char *src; Dwarf_Die die_mem; @@ -1145,6 +1184,7 @@ static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf) return -ENOENT; } + /* Search probable lines on lines list */ for (i = 0; i < nlines; i++) { line = dwarf_onesrcline(lines, i); if (dwarf_lineno(line, &lineno) != 0 || @@ -1167,22 +1207,34 @@ static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf) if (strtailcmp(src, lf->fname) != 0) continue; - /* Copy real path */ - if (!lf->lr->path) { - lf->lr->path = strdup(src); - if (lf->lr->path == NULL) - return -ENOMEM; - } - line_list__add_line(&lf->lr->line_list, lineno); + ret = line_range_add_line(src, lineno, lf->lr); + if (ret < 0) + return ret; } + + /* + * Dwarf lines doesn't include function declarations. We have to + * check functions list or given function. + */ + if (sp_die) { + src = dwarf_decl_file(sp_die); + if (src && dwarf_decl_line(sp_die, &lineno) == 0 && + (lf->lno_s <= lineno && lf->lno_e >= lineno)) + ret = line_range_add_line(src, lineno, lf->lr); + } else + ret = find_line_range_func_decl_lines(lf); + /* Update status */ - if (!list_empty(&lf->lr->line_list)) - lf->found = 1; + if (ret >= 0) + if (!list_empty(&lf->lr->line_list)) + ret = lf->found = 1; + else + ret = 0; /* Lines are not found */ else { free(lf->lr->path); lf->lr->path = NULL; } - return lf->found; + return ret; } static int line_range_inline_cb(Dwarf_Die *in_die, void *data) -- cgit v0.10.2 From 95476b64ab11d528de2557366ec584977c215b9e Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 14 Apr 2010 23:42:18 +0200 Subject: perf: Fix hlist related build error hlist helpers need to be available for all software events, not only trace events. Pull them out outside the ifdef CONFIG_EVENT_TRACING section. Fixes: kernel/perf_event.c:4573: error: implicit declaration of function 'swevent_hlist_put' kernel/perf_event.c:4614: error: implicit declaration of function 'swevent_hlist_get' kernel/perf_event.c:5534: error: implicit declaration of function 'swevent_hlist_release Reported-by: Ingo Molnar Signed-off-by: Frederic Weisbecker Cc: Arnaldo Carvalho de Melo Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: <1271281338-23491-1-git-send-regression-fweisbec@gmail.com> Signed-off-by: Ingo Molnar diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 095101d..07b7a43 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -4313,36 +4313,6 @@ static const struct pmu perf_ops_task_clock = { .read = task_clock_perf_event_read, }; -#ifdef CONFIG_EVENT_TRACING - -void perf_tp_event(int event_id, u64 addr, u64 count, void *record, - int entry_size, struct pt_regs *regs) -{ - struct perf_sample_data data; - struct perf_raw_record raw = { - .size = entry_size, - .data = record, - }; - - perf_sample_data_init(&data, addr); - data.raw = &raw; - - /* Trace events already protected against recursion */ - do_perf_sw_event(PERF_TYPE_TRACEPOINT, event_id, count, 1, - &data, regs); -} -EXPORT_SYMBOL_GPL(perf_tp_event); - -static int perf_tp_event_match(struct perf_event *event, - struct perf_sample_data *data) -{ - void *record = data->raw->data; - - if (likely(!event->filter) || filter_match_preds(event->filter, record)) - return 1; - return 0; -} - static void swevent_hlist_release_rcu(struct rcu_head *rcu_head) { struct swevent_hlist *hlist; @@ -4442,6 +4412,36 @@ static int swevent_hlist_get(struct perf_event *event) return err; } +#ifdef CONFIG_EVENT_TRACING + +void perf_tp_event(int event_id, u64 addr, u64 count, void *record, + int entry_size, struct pt_regs *regs) +{ + struct perf_sample_data data; + struct perf_raw_record raw = { + .size = entry_size, + .data = record, + }; + + perf_sample_data_init(&data, addr); + data.raw = &raw; + + /* Trace events already protected against recursion */ + do_perf_sw_event(PERF_TYPE_TRACEPOINT, event_id, count, 1, + &data, regs); +} +EXPORT_SYMBOL_GPL(perf_tp_event); + +static int perf_tp_event_match(struct perf_event *event, + struct perf_sample_data *data) +{ + void *record = data->raw->data; + + if (likely(!event->filter) || filter_match_preds(event->filter, record)) + return 1; + return 0; +} + static void tp_perf_event_destroy(struct perf_event *event) { perf_trace_disable(event->attr.config); -- cgit v0.10.2 From a1e2f60e3efc812bf66a2be0d8530ee175003f6d Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 14 Apr 2010 23:58:03 +0200 Subject: perf: Fix dynamic field detection Checking if a tracing field is an array with a dynamic length requires to check the field type and seek the "__data_loc" string that prepends the actual type, as can be found in a trace event format file: field:__data_loc char[] name; offset:16; size:4; signed:1; But we actually use strcmp() to check if the field type fully matches "__data_loc", which may fail as we trip over the rest of the type. To fix this, use strncmp to only check if it starts with "__data_loc". Signed-off-by: Thomas Gleixner Signed-off-by: Frederic Weisbecker Cc: Arnaldo Carvalho de Melo Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Tom Zanussi Cc: Steven Rostedt LKML-Reference: <1271282283-23721-1-git-send-regression-fweisbec@gmail.com> Signed-off-by: Ingo Molnar diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index 17d6d66..d6ef414 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c @@ -761,7 +761,7 @@ static int field_is_string(struct format_field *field) static int field_is_dynamic(struct format_field *field) { - if (!strcmp(field->type, "__data_loc")) + if (!strncmp(field->type, "__data_loc", 10)) return 1; return 0; -- cgit v0.10.2 From 7865e817e9b4b378ac57ab7f16183100b95466ce Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 14 Apr 2010 19:42:07 +0200 Subject: perf: Make -f the default for perf record Force the overwriting mode by default if append mode is not explicit. Adding -f every time one uses perf on a daily basis quickly becomes a burden. Keep the -f among the options though to avoid breaking some random users scripts. Signed-off-by: Frederic Weisbecker Cc: Arnaldo Carvalho de Melo Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Ingo Molnar Cc: Thomas Gleixner diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt index fc46c0b..b29bd2d 100644 --- a/tools/perf/Documentation/perf-record.txt +++ b/tools/perf/Documentation/perf-record.txt @@ -58,7 +58,7 @@ OPTIONS -f:: --force:: - Overwrite existing data file. + Overwrite existing data file. (deprecated) -c:: --count=:: diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 9a95136..dcda899 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -26,6 +26,11 @@ #include #include +enum write_mode_t { + WRITE_FORCE, + WRITE_APPEND +}; + static int *fd[MAX_NR_CPUS][MAX_COUNTERS]; static long default_interval = 0; @@ -47,8 +52,7 @@ static pid_t *all_tids = NULL; static int thread_num = 0; static pid_t child_pid = -1; static bool inherit = true; -static bool force = false; -static bool append_file = false; +static enum write_mode_t write_mode = WRITE_FORCE; static bool call_graph = false; static bool inherit_stat = false; static bool no_samples = false; @@ -450,26 +454,19 @@ static int __cmd_record(int argc, const char **argv) } if (!stat(output_name, &st) && st.st_size) { - if (!force) { - if (!append_file) { - pr_err("Error, output file %s exists, use -A " - "to append or -f to overwrite.\n", - output_name); - exit(-1); - } - } else { + if (write_mode == WRITE_FORCE) { char oldname[PATH_MAX]; snprintf(oldname, sizeof(oldname), "%s.old", output_name); unlink(oldname); rename(output_name, oldname); } - } else { - append_file = false; + } else if (write_mode == WRITE_APPEND) { + write_mode = WRITE_FORCE; } flags = O_CREAT|O_RDWR; - if (append_file) + if (write_mode == WRITE_APPEND) file_new = 0; else flags |= O_TRUNC; @@ -480,7 +477,8 @@ static int __cmd_record(int argc, const char **argv) exit(-1); } - session = perf_session__new(output_name, O_WRONLY, force); + session = perf_session__new(output_name, O_WRONLY, + write_mode == WRITE_FORCE); if (session == NULL) { pr_err("Not enough memory for reading perf file header\n"); return -1; @@ -667,6 +665,8 @@ static const char * const record_usage[] = { NULL }; +static bool force, append_file; + static const struct option options[] = { OPT_CALLBACK('e', "event", NULL, "event", "event selector. use 'perf list' to list available events", @@ -688,7 +688,7 @@ static const struct option options[] = { OPT_INTEGER('C', "profile_cpu", &profile_cpu, "CPU to profile on"), OPT_BOOLEAN('f', "force", &force, - "overwrite existing data file"), + "overwrite existing data file (deprecated)"), OPT_LONG('c', "count", &default_interval, "event period to sample"), OPT_STRING('o', "output", &output_name, "file", @@ -725,6 +725,16 @@ int cmd_record(int argc, const char **argv, const char *prefix __used) !system_wide && profile_cpu == -1) usage_with_options(record_usage, options); + if (force && append_file) { + fprintf(stderr, "Can't overwrite and append at the same time." + " You need to choose between -f and -A"); + usage_with_options(record_usage, options); + } else if (append_file) { + write_mode = WRITE_APPEND; + } else { + write_mode = WRITE_FORCE; + } + symbol__init(); if (!nr_counters) { -- cgit v0.10.2 From bdef3b02ceeb97f5f67fcfa6dff13c4e70b34fb7 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 14 Apr 2010 20:05:17 +0200 Subject: perf: Always record tracepoints raw samples from perf record Trace events are mostly used for tracing rather than simple counting. Don't bother anymore with adding -R when using them, just record raw samples of trace events every time. Signed-off-by: Frederic Weisbecker Cc: Arnaldo Carvalho de Melo Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Ingo Molnar Cc: Thomas Gleixner diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt index b29bd2d..020d871 100644 --- a/tools/perf/Documentation/perf-record.txt +++ b/tools/perf/Documentation/perf-record.txt @@ -101,7 +101,7 @@ OPTIONS -R:: --raw-samples:: -Collect raw sample records from all opened counters (typically for tracepoint counters). +Collect raw sample records from all opened counters (default for tracepoint counters). SEE ALSO -------- diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 435781e..880070c 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -410,7 +410,6 @@ static enum event_result parse_single_tracepoint_event(char *sys_name, const char *evt_name, unsigned int evt_length, - char *flags, struct perf_event_attr *attr, const char **strp) { @@ -419,13 +418,9 @@ parse_single_tracepoint_event(char *sys_name, u64 id; int fd; - if (flags) { - if (!strncmp(flags, "record", strlen(flags))) { - attr->sample_type |= PERF_SAMPLE_RAW; - attr->sample_type |= PERF_SAMPLE_TIME; - attr->sample_type |= PERF_SAMPLE_CPU; - } - } + attr->sample_type |= PERF_SAMPLE_RAW; + attr->sample_type |= PERF_SAMPLE_TIME; + attr->sample_type |= PERF_SAMPLE_CPU; snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path, sys_name, evt_name); @@ -533,8 +528,7 @@ static enum event_result parse_tracepoint_event(const char **strp, flags); } else return parse_single_tracepoint_event(sys_name, evt_name, - evt_length, flags, - attr, strp); + evt_length, attr, strp); } static enum event_result -- cgit v0.10.2 From f92128193094c288bc315db1694fafeaeb7ee1d0 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 14 Apr 2010 22:09:02 +0200 Subject: perf: Make the trace events sample period default to 1 Trace events are mostly used for tracing and then require not to be lost when possible. As opposite to hardware events that really require to trigger after a given sample period, trace events mostly need to trigger everytime. It is a frustrating experience to trace with perf and realize we lost a lot of events because we forgot the "-c 1" option. Then default sample_period to 1 for trace events but let the user override it. Signed-off-by: Frederic Weisbecker Cc: Arnaldo Carvalho de Melo Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Ingo Molnar Cc: Thomas Gleixner diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index dcda899..ca2affc 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -33,11 +33,13 @@ enum write_mode_t { static int *fd[MAX_NR_CPUS][MAX_COUNTERS]; +static unsigned int user_interval = UINT_MAX; static long default_interval = 0; static int nr_cpus = 0; static unsigned int page_size; static unsigned int mmap_pages = 128; +static unsigned int user_freq = UINT_MAX; static int freq = 1000; static int output; static const char *output_name = "perf.data"; @@ -255,10 +257,19 @@ static void create_counter(int counter, int cpu) if (nr_counters > 1) attr->sample_type |= PERF_SAMPLE_ID; - if (freq) { - attr->sample_type |= PERF_SAMPLE_PERIOD; - attr->freq = 1; - attr->sample_freq = freq; + /* + * We default some events to a 1 default interval. But keep + * it a weak assumption overridable by the user. + */ + if (!attr->sample_period || (user_freq != UINT_MAX && + user_interval != UINT_MAX)) { + if (freq) { + attr->sample_type |= PERF_SAMPLE_PERIOD; + attr->freq = 1; + attr->sample_freq = freq; + } else { + attr->sample_period = default_interval; + } } if (no_samples) @@ -689,13 +700,13 @@ static const struct option options[] = { "CPU to profile on"), OPT_BOOLEAN('f', "force", &force, "overwrite existing data file (deprecated)"), - OPT_LONG('c', "count", &default_interval, + OPT_LONG('c', "count", &user_interval, "event period to sample"), OPT_STRING('o', "output", &output_name, "file", "output file name"), OPT_BOOLEAN('i', "inherit", &inherit, "child tasks inherit counters"), - OPT_INTEGER('F', "freq", &freq, + OPT_INTEGER('F', "freq", &user_freq, "profile at this frequency"), OPT_INTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"), @@ -716,7 +727,6 @@ static const struct option options[] = { int cmd_record(int argc, const char **argv, const char *prefix __used) { - int counter; int i,j; argc = parse_options(argc, argv, options, record_usage, @@ -774,6 +784,11 @@ int cmd_record(int argc, const char **argv, const char *prefix __used) if (!event_array) return -ENOMEM; + if (user_interval != UINT_MAX) + default_interval = user_interval; + if (user_freq != UINT_MAX) + freq = user_freq; + /* * User specified count overrides default frequency. */ @@ -786,12 +801,5 @@ int cmd_record(int argc, const char **argv, const char *prefix __used) exit(EXIT_FAILURE); } - for (counter = 0; counter < nr_counters; counter++) { - if (attrs[counter].sample_period) - continue; - - attrs[counter].sample_period = default_interval; - } - return __cmd_record(argc, argv); } diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 880070c..3b4ec67 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -422,6 +422,8 @@ parse_single_tracepoint_event(char *sys_name, attr->sample_type |= PERF_SAMPLE_TIME; attr->sample_type |= PERF_SAMPLE_CPU; + attr->sample_period = 1; + snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path, sys_name, evt_name); -- cgit v0.10.2 From fecf066c2d2fbc7e6a7e7e3a5af772a165bdd7b0 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 15 Apr 2010 11:59:28 +0900 Subject: sh: Disable IRQ balancing for timer and IPI IRQs. Make sure that the timer IRQs and IPIs aren't enabled for IRQ balancing. IPIs are disabled as a result of being percpu while the timers simply disable balancing outright. Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/smp-shx3.c b/arch/sh/kernel/cpu/sh4a/smp-shx3.c index 11bf4c1..c98b457 100644 --- a/arch/sh/kernel/cpu/sh4a/smp-shx3.c +++ b/arch/sh/kernel/cpu/sh4a/smp-shx3.c @@ -72,8 +72,8 @@ void __init plat_prepare_cpus(unsigned int max_cpus) BUILD_BUG_ON(SMP_MSG_NR >= 8); for (i = 0; i < SMP_MSG_NR; i++) - request_irq(104 + i, ipi_interrupt_handler, IRQF_DISABLED, - "IPI", (void *)(long)i); + request_irq(104 + i, ipi_interrupt_handler, + IRQF_DISABLED | IRQF_PERCPU, "IPI", (void *)(long)i); } void plat_start_cpu(unsigned int cpu, unsigned long entry_point) diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index c5f6617..45be4dc 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -605,7 +605,8 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) p->irqaction.name = dev_name(&p->pdev->dev); p->irqaction.handler = sh_cmt_interrupt; p->irqaction.dev_id = p; - p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL; + p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | \ + IRQF_IRQPOLL | IRQF_NOBALANCING; /* get hold of clock */ p->clk = clk_get(&p->pdev->dev, "cmt_fck"); diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c index b11882e..644ecbb 100644 --- a/drivers/clocksource/sh_mtu2.c +++ b/drivers/clocksource/sh_mtu2.c @@ -280,7 +280,8 @@ static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev) p->irqaction.handler = sh_mtu2_interrupt; p->irqaction.dev_id = p; p->irqaction.irq = irq; - p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL; + p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | \ + IRQF_IRQPOLL | IRQF_NOBALANCING; /* get hold of clock */ p->clk = clk_get(&p->pdev->dev, "mtu2_fck"); diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c index 6b62283..44c39a3 100644 --- a/drivers/clocksource/sh_tmu.c +++ b/drivers/clocksource/sh_tmu.c @@ -384,7 +384,8 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev) p->irqaction.handler = sh_tmu_interrupt; p->irqaction.dev_id = p; p->irqaction.irq = irq; - p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL; + p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | \ + IRQF_IRQPOLL | IRQF_NOBALANCING; /* get hold of clock */ p->clk = clk_get(&p->pdev->dev, "tmu_fck"); -- cgit v0.10.2 From dc825b17904a06bbd2f79d720b23156e4c01a22f Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 15 Apr 2010 13:13:52 +0900 Subject: sh: intc: IRQ auto-distribution support. This implements support for hardware-managed IRQ balancing as implemented by SH-X3 cores (presently only hooked up for SH7786, but can probably be carried over to other SH-X3 cores, too). CPUs need to specify their distribution register along with the mask definitions, as these follow the same format. Peripheral IRQs that don't opt out of balancing will be automatically distributed at the whim of the hardware block, while each CPU needs to verify whether it is handling the IRQ or not, especially before clearing the mask. Signed-off-by: Paul Mundt diff --git a/arch/sh/include/asm/irq.h b/arch/sh/include/asm/irq.h index df8e150..99c593b 100644 --- a/arch/sh/include/asm/irq.h +++ b/arch/sh/include/asm/irq.h @@ -12,6 +12,14 @@ #define NR_IRQS_LEGACY 8 /* Legacy external IRQ0-7 */ /* + * This is a special IRQ number for indicating that no IRQ has been + * triggered and to simply ignore the IRQ dispatch. This is a special + * case that can happen with IRQ auto-distribution when multiple CPUs + * are woken up and signalled in parallel. + */ +#define NO_IRQ_IGNORE ((unsigned int)-1) + +/* * Convert back and forth between INTEVT and IRQ values. */ #ifdef CONFIG_CPU_HAS_INTEVT @@ -53,6 +61,14 @@ extern void irq_ctx_exit(int cpu); # define irq_ctx_exit(cpu) do { } while (0) #endif +#ifdef CONFIG_INTC_BALANCING +extern unsigned int irq_lookup(unsigned int irq); +extern void irq_finish(unsigned int irq); +#else +#define irq_lookup(irq) (irq) +#define irq_finish(irq) do { } while (0) +#endif + #include #ifdef CONFIG_CPU_SH5 #include diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c index 235edf8..d733603 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c @@ -573,7 +573,6 @@ static struct platform_device *sh7786_devices[] __initdata = { &usb_ohci_device, }; - /* * Please call this function if your platform board * use external clock for USB @@ -581,6 +580,7 @@ static struct platform_device *sh7786_devices[] __initdata = { #define USBCTL0 0xffe70858 #define CLOCK_MODE_MASK 0xffffff7f #define EXT_CLOCK_MODE 0x00000080 + void __init sh7786_usb_use_exclock(void) { u32 val = __raw_readl(USBCTL0) & CLOCK_MODE_MASK; @@ -598,6 +598,7 @@ void __init sh7786_usb_use_exclock(void) #define PLL_ENB 0x00000002 #define PHY_RST 0x00000004 #define ACT_PLL_STATUS 0xc0000000 + static void __init sh7786_usb_setup(void) { int i = 1000000; @@ -753,9 +754,19 @@ static struct intc_vect vectors[] __initdata = { #define INTMSK2 0xfe410068 #define INTMSKCLR2 0xfe41006c +#define INTDISTCR0 0xfe4100b0 +#define INTDISTCR1 0xfe4100b4 +#define INTACK 0xfe4100b8 +#define INTACKCLR 0xfe4100bc +#define INT2DISTCR0 0xfe410900 +#define INT2DISTCR1 0xfe410904 +#define INT2DISTCR2 0xfe410908 +#define INT2DISTCR3 0xfe41090c + static struct intc_mask_reg mask_registers[] __initdata = { { CnINTMSK0, CnINTMSKCLR0, 32, - { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } }, + { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 }, + INTC_SMP_BALANCING(INTDISTCR0) }, { INTMSK2, INTMSKCLR2, 32, { IRL0_LLLL, IRL0_LLLH, IRL0_LLHL, IRL0_LLHH, IRL0_LHLL, IRL0_LHLH, IRL0_LHHL, IRL0_LHHH, @@ -767,7 +778,8 @@ static struct intc_mask_reg mask_registers[] __initdata = { IRL4_HHLL, IRL4_HHLH, IRL4_HHHL, 0, } }, { CnINT2MSKR0, CnINT2MSKCR0 , 32, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WDT } }, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, WDT }, + INTC_SMP_BALANCING(INT2DISTCR0) }, { CnINT2MSKR1, CnINT2MSKCR1, 32, { TMU0_0, TMU0_1, TMU0_2, TMU0_3, TMU1_0, TMU1_1, TMU1_2, 0, DMAC0_0, DMAC0_1, DMAC0_2, DMAC0_3, DMAC0_4, DMAC0_5, DMAC0_6, @@ -776,14 +788,14 @@ static struct intc_mask_reg mask_registers[] __initdata = { HPB_0, HPB_1, HPB_2, SCIF0_0, SCIF0_1, SCIF0_2, SCIF0_3, SCIF1, - TMU2, TMU3, 0, } }, + TMU2, TMU3, 0, }, INTC_SMP_BALANCING(INT2DISTCR1) }, { CnINT2MSKR2, CnINT2MSKCR2, 32, { 0, 0, SCIF2, SCIF3, SCIF4, SCIF5, Eth_0, Eth_1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, PCIeC0_0, PCIeC0_1, PCIeC0_2, PCIeC1_0, PCIeC1_1, PCIeC1_2, - USB, 0, 0 } }, + USB, 0, 0 }, INTC_SMP_BALANCING(INT2DISTCR2) }, { CnINT2MSKR3, CnINT2MSKCR3, 32, { 0, 0, 0, 0, 0, 0, I2C0, I2C1, @@ -792,7 +804,7 @@ static struct intc_mask_reg mask_registers[] __initdata = { HAC0, HAC1, FLCTL, 0, HSPI, GPIO0, GPIO1, Thermal, - 0, 0, 0, 0, 0, 0, 0, 0 } }, + 0, 0, 0, 0, 0, 0, 0, 0 }, INTC_SMP_BALANCING(INT2DISTCR3) }, }; static struct intc_prio_reg prio_registers[] __initdata = { @@ -910,6 +922,18 @@ static DECLARE_INTC_DESC(intc_desc_irl4567, "sh7786-irl4567", vectors_irl4567, #define INTC_INTMSKCLR2 INTMSKCLR2 #define INTC_USERIMASK 0xfe411000 +#ifdef CONFIG_INTC_BALANCING +unsigned int irq_lookup(unsigned int irq) +{ + return __raw_readl(INTACK) & 1 ? irq : NO_IRQ_IGNORE; +} + +void irq_finish(unsigned int irq) +{ + __raw_writel(irq2evt(irq), INTACKCLR); +} +#endif + void __init plat_irq_setup(void) { /* disable IRQ3-0 + IRQ7-4 */ diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index d2d41d0..f6a9319 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c @@ -113,19 +113,14 @@ union irq_ctx { static union irq_ctx *hardirq_ctx[NR_CPUS] __read_mostly; static union irq_ctx *softirq_ctx[NR_CPUS] __read_mostly; -#endif -asmlinkage __irq_entry int do_IRQ(unsigned int irq, struct pt_regs *regs) +static char softirq_stack[NR_CPUS * THREAD_SIZE] __page_aligned_bss; +static char hardirq_stack[NR_CPUS * THREAD_SIZE] __page_aligned_bss; + +static inline void handle_one_irq(unsigned int irq) { - struct pt_regs *old_regs = set_irq_regs(regs); -#ifdef CONFIG_IRQSTACKS union irq_ctx *curctx, *irqctx; -#endif - - irq_enter(); - irq = irq_demux(irq); -#ifdef CONFIG_IRQSTACKS curctx = (union irq_ctx *)current_thread_info(); irqctx = hardirq_ctx[smp_processor_id()]; @@ -164,20 +159,9 @@ asmlinkage __irq_entry int do_IRQ(unsigned int irq, struct pt_regs *regs) "r5", "r6", "r7", "r8", "t", "pr" ); } else -#endif generic_handle_irq(irq); - - irq_exit(); - - set_irq_regs(old_regs); - return 1; } -#ifdef CONFIG_IRQSTACKS -static char softirq_stack[NR_CPUS * THREAD_SIZE] __page_aligned_bss; - -static char hardirq_stack[NR_CPUS * THREAD_SIZE] __page_aligned_bss; - /* * allocate per-cpu stacks for hardirq and for softirq processing */ @@ -257,8 +241,33 @@ asmlinkage void do_softirq(void) local_irq_restore(flags); } +#else +static inline void handle_one_irq(unsigned int irq) +{ + generic_handle_irq(irq); +} #endif +asmlinkage __irq_entry int do_IRQ(unsigned int irq, struct pt_regs *regs) +{ + struct pt_regs *old_regs = set_irq_regs(regs); + + irq_enter(); + + irq = irq_demux(irq_lookup(irq)); + + if (irq != NO_IRQ_IGNORE) { + handle_one_irq(irq); + irq_finish(irq); + } + + irq_exit(); + + set_irq_regs(old_regs); + + return IRQ_HANDLED; +} + void __init init_IRQ(void) { plat_irq_setup(); diff --git a/drivers/sh/Kconfig b/drivers/sh/Kconfig index 22c3cda..a54de0b 100644 --- a/drivers/sh/Kconfig +++ b/drivers/sh/Kconfig @@ -11,3 +11,14 @@ config INTC_USERIMASK drivers that are using special priority levels. If in doubt, say N. + +config INTC_BALANCING + bool "Hardware IRQ balancing support" + depends on SMP && SUPERH && CPU_SUBTYPE_SH7786 + help + This enables support for IRQ auto-distribution mode on SH-X3 + SMP parts. All of the balancing and CPU wakeup decisions are + taken care of automatically by hardware for distributed + vectors. + + If in doubt, say N. diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c index 77d10ac..dcb4c83 100644 --- a/drivers/sh/intc.c +++ b/drivers/sh/intc.c @@ -98,6 +98,9 @@ static DEFINE_SPINLOCK(vector_lock); static unsigned int intc_prio_level[NR_IRQS]; /* for now */ static unsigned int default_prio_level = 2; /* 2 - 16 */ static unsigned long ack_handle[NR_IRQS]; +#ifdef CONFIG_INTC_BALANCING +static unsigned long dist_handle[NR_IRQS]; +#endif static inline struct intc_desc_int *get_intc_desc(unsigned int irq) { @@ -105,6 +108,47 @@ static inline struct intc_desc_int *get_intc_desc(unsigned int irq) return container_of(chip, struct intc_desc_int, chip); } +static unsigned long intc_phys_to_virt(struct intc_desc_int *d, + unsigned long address) +{ + struct intc_window *window; + int k; + + /* scan through physical windows and convert address */ + for (k = 0; k < d->nr_windows; k++) { + window = d->window + k; + + if (address < window->phys) + continue; + + if (address >= (window->phys + window->size)) + continue; + + address -= window->phys; + address += (unsigned long)window->virt; + + return address; + } + + /* no windows defined, register must be 1:1 mapped virt:phys */ + return address; +} + +static unsigned int intc_get_reg(struct intc_desc_int *d, unsigned long address) +{ + unsigned int k; + + address = intc_phys_to_virt(d, address); + + for (k = 0; k < d->nr_reg; k++) { + if (d->reg[k] == address) + return k; + } + + BUG(); + return 0; +} + static inline unsigned int set_field(unsigned int value, unsigned int field_value, unsigned int handle) @@ -238,6 +282,85 @@ static void (*intc_disable_fns[])(unsigned long addr, [MODE_PCLR_REG] = intc_mode_field, }; +#ifdef CONFIG_INTC_BALANCING +static inline void intc_balancing_enable(unsigned int irq) +{ + struct intc_desc_int *d = get_intc_desc(irq); + unsigned long handle = dist_handle[irq]; + unsigned long addr; + + if (irq_balancing_disabled(irq) || !handle) + return; + + addr = INTC_REG(d, _INTC_ADDR_D(handle), 0); + intc_reg_fns[_INTC_FN(handle)](addr, handle, 1); +} + +static inline void intc_balancing_disable(unsigned int irq) +{ + struct intc_desc_int *d = get_intc_desc(irq); + unsigned long handle = dist_handle[irq]; + unsigned long addr; + + if (irq_balancing_disabled(irq) || !handle) + return; + + addr = INTC_REG(d, _INTC_ADDR_D(handle), 0); + intc_reg_fns[_INTC_FN(handle)](addr, handle, 0); +} + +static unsigned int intc_dist_data(struct intc_desc *desc, + struct intc_desc_int *d, + intc_enum enum_id) +{ + struct intc_mask_reg *mr = desc->hw.mask_regs; + unsigned int i, j, fn, mode; + unsigned long reg_e, reg_d; + + for (i = 0; mr && enum_id && i < desc->hw.nr_mask_regs; i++) { + mr = desc->hw.mask_regs + i; + + /* + * Skip this entry if there's no auto-distribution + * register associated with it. + */ + if (!mr->dist_reg) + continue; + + for (j = 0; j < ARRAY_SIZE(mr->enum_ids); j++) { + if (mr->enum_ids[j] != enum_id) + continue; + + fn = REG_FN_MODIFY_BASE; + mode = MODE_ENABLE_REG; + reg_e = mr->dist_reg; + reg_d = mr->dist_reg; + + fn += (mr->reg_width >> 3) - 1; + return _INTC_MK(fn, mode, + intc_get_reg(d, reg_e), + intc_get_reg(d, reg_d), + 1, + (mr->reg_width - 1) - j); + } + } + + /* + * It's possible we've gotten here with no distribution options + * available for the IRQ in question, so we just skip over those. + */ + return 0; +} +#else +static inline void intc_balancing_enable(unsigned int irq) +{ +} + +static inline void intc_balancing_disable(unsigned int irq) +{ +} +#endif + static inline void _intc_enable(unsigned int irq, unsigned long handle) { struct intc_desc_int *d = get_intc_desc(irq); @@ -253,6 +376,8 @@ static inline void _intc_enable(unsigned int irq, unsigned long handle) intc_enable_fns[_INTC_MODE(handle)](addr, handle, intc_reg_fns\ [_INTC_FN(handle)], irq); } + + intc_balancing_enable(irq); } static void intc_enable(unsigned int irq) @@ -263,10 +388,12 @@ static void intc_enable(unsigned int irq) static void intc_disable(unsigned int irq) { struct intc_desc_int *d = get_intc_desc(irq); - unsigned long handle = (unsigned long) get_irq_chip_data(irq); + unsigned long handle = (unsigned long)get_irq_chip_data(irq); unsigned long addr; unsigned int cpu; + intc_balancing_disable(irq); + for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_D(handle)); cpu++) { #ifdef CONFIG_SMP if (!cpumask_test_cpu(cpu, irq_to_desc(irq)->affinity)) @@ -345,8 +472,7 @@ static void intc_mask_ack(unsigned int irq) intc_disable(irq); - /* read register and write zero only to the assocaited bit */ - + /* read register and write zero only to the associated bit */ if (handle) { addr = INTC_REG(d, _INTC_ADDR_D(handle), 0); switch (_INTC_FN(handle)) { @@ -375,7 +501,8 @@ static struct intc_handle_int *intc_find_irq(struct intc_handle_int *hp, { int i; - /* this doesn't scale well, but... + /* + * this doesn't scale well, but... * * this function should only be used for cerain uncommon * operations such as intc_set_priority() and intc_set_sense() @@ -386,7 +513,6 @@ static struct intc_handle_int *intc_find_irq(struct intc_handle_int *hp, * memory footprint down is to make sure the array is sorted * and then perform a bisect to lookup the irq. */ - for (i = 0; i < nr_hp; i++) { if ((hp + i)->irq != irq) continue; @@ -417,7 +543,6 @@ int intc_set_priority(unsigned int irq, unsigned int prio) * primary masking method is using intc_prio_level[irq] * priority level will be set during next enable() */ - if (_INTC_FN(ihp->handle) != REG_FN_ERR) _intc_enable(irq, ihp->handle); } @@ -456,48 +581,6 @@ static int intc_set_sense(unsigned int irq, unsigned int type) return 0; } -static unsigned long intc_phys_to_virt(struct intc_desc_int *d, - unsigned long address) -{ - struct intc_window *window; - int k; - - /* scan through physical windows and convert address */ - for (k = 0; k < d->nr_windows; k++) { - window = d->window + k; - - if (address < window->phys) - continue; - - if (address >= (window->phys + window->size)) - continue; - - address -= window->phys; - address += (unsigned long)window->virt; - - return address; - } - - /* no windows defined, register must be 1:1 mapped virt:phys */ - return address; -} - -static unsigned int __init intc_get_reg(struct intc_desc_int *d, - unsigned long address) -{ - unsigned int k; - - address = intc_phys_to_virt(d, address); - - for (k = 0; k < d->nr_reg; k++) { - if (d->reg[k] == address) - return k; - } - - BUG(); - return 0; -} - static intc_enum __init intc_grp_id(struct intc_desc *desc, intc_enum enum_id) { @@ -755,13 +838,14 @@ static void __init intc_register_irq(struct intc_desc *desc, */ set_bit(irq, intc_irq_map); - /* Prefer single interrupt source bitmap over other combinations: + /* + * Prefer single interrupt source bitmap over other combinations: + * * 1. bitmap, single interrupt source * 2. priority, single interrupt source * 3. bitmap, multiple interrupt sources (groups) * 4. priority, multiple interrupt sources (groups) */ - data[0] = intc_mask_data(desc, d, enum_id, 0); data[1] = intc_prio_data(desc, d, enum_id, 0); @@ -786,7 +870,8 @@ static void __init intc_register_irq(struct intc_desc *desc, handle_level_irq, "level"); set_irq_chip_data(irq, (void *)data[primary]); - /* set priority level + /* + * set priority level * - this needs to be at least 2 for 5-bit priorities on 7780 */ intc_prio_level[irq] = default_prio_level; @@ -806,7 +891,6 @@ static void __init intc_register_irq(struct intc_desc *desc, * only secondary priority should access registers, so * set _INTC_FN(h) = REG_FN_ERR for intc_set_priority() */ - hp->handle &= ~_INTC_MK(0x0f, 0, 0, 0, 0, 0); hp->handle |= _INTC_MK(REG_FN_ERR, 0, 0, 0, 0, 0); } @@ -827,6 +911,11 @@ static void __init intc_register_irq(struct intc_desc *desc, if (desc->hw.ack_regs) ack_handle[irq] = intc_ack_data(desc, d, enum_id); +#ifdef CONFIG_INTC_BALANCING + if (desc->hw.mask_regs) + dist_handle[irq] = intc_dist_data(desc, d, enum_id); +#endif + #ifdef CONFIG_ARM set_irq_flags(irq, IRQF_VALID); /* Enable IRQ on ARM systems */ #endif @@ -892,6 +981,10 @@ int __init register_intc_controller(struct intc_desc *desc) } d->nr_reg = hw->mask_regs ? hw->nr_mask_regs * 2 : 0; +#ifdef CONFIG_INTC_BALANCING + if (d->nr_reg) + d->nr_reg += hw->nr_mask_regs; +#endif d->nr_reg += hw->prio_regs ? hw->nr_prio_regs * 2 : 0; d->nr_reg += hw->sense_regs ? hw->nr_sense_regs : 0; d->nr_reg += hw->ack_regs ? hw->nr_ack_regs : 0; @@ -912,6 +1005,9 @@ int __init register_intc_controller(struct intc_desc *desc) smp = IS_SMP(hw->mask_regs[i]); k += save_reg(d, k, hw->mask_regs[i].set_reg, smp); k += save_reg(d, k, hw->mask_regs[i].clr_reg, smp); +#ifdef CONFIG_INTC_BALANCING + k += save_reg(d, k, hw->mask_regs[i].dist_reg, 0); +#endif } } diff --git a/include/linux/sh_intc.h b/include/linux/sh_intc.h index f0e8cca..0d6cd38 100644 --- a/include/linux/sh_intc.h +++ b/include/linux/sh_intc.h @@ -23,6 +23,9 @@ struct intc_group { struct intc_mask_reg { unsigned long set_reg, clr_reg, reg_width; intc_enum enum_ids[32]; +#ifdef CONFIG_INTC_BALANCING + unsigned long dist_reg; +#endif #ifdef CONFIG_SMP unsigned long smp; #endif @@ -41,8 +44,14 @@ struct intc_sense_reg { intc_enum enum_ids[16]; }; +#ifdef CONFIG_INTC_BALANCING +#define INTC_SMP_BALANCING(reg) .dist_reg = (reg) +#else +#define INTC_SMP_BALANCING(reg) +#endif + #ifdef CONFIG_SMP -#define INTC_SMP(stride, nr) .smp = (stride) | ((nr) << 8) +#define INTC_SMP(stride, nr) .smp = (stride) | ((nr) << 8) #else #define INTC_SMP(stride, nr) #endif -- cgit v0.10.2 From 09a40af5240de02d848247ab82440ad75b31ab11 Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Thu, 15 Apr 2010 07:29:59 +0200 Subject: sched: Fix UP update_avg() build warning update_avg() is only used for SMP builds, move it to the nearest SMP block. Reported-by: Stephen Rothwell Signed-off-by: Mike Galbraith Cc: Peter Zijlstra LKML-Reference: <1271309399.14779.17.camel@marge.simson.net> Signed-off-by: Ingo Molnar diff --git a/kernel/sched.c b/kernel/sched.c index ab562ae..de0da71 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1872,12 +1872,6 @@ static void set_load_weight(struct task_struct *p) p->se.load.inv_weight = prio_to_wmult[p->static_prio - MAX_RT_PRIO]; } -static void update_avg(u64 *avg, u64 sample) -{ - s64 diff = sample - *avg; - *avg += diff >> 3; -} - static void enqueue_task(struct rq *rq, struct task_struct *p, int flags) { update_rq_clock(rq); @@ -2332,6 +2326,12 @@ int select_task_rq(struct rq *rq, struct task_struct *p, int sd_flags, int wake_ return cpu; } + +static void update_avg(u64 *avg, u64 sample) +{ + s64 diff = sample - *avg; + *avg += diff >> 3; +} #endif /*** -- cgit v0.10.2 From a289cc7c70da784a2d370b91885cab4f966dcb0f Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 16 Apr 2010 17:51:42 -0700 Subject: x86, UV: uv_irq.c: Fix all sparse warnings Fix all sparse warnings in building uv_irq.c. arch/x86/kernel/uv_irq.c:46:17: warning: symbol 'uv_irq_chip' was not declared. Should it be static? arch/x86/kernel/uv_irq.c:143:50: error: no identifier for function argument arch/x86/kernel/uv_irq.c:162:13: error: typename in expression arch/x86/kernel/uv_irq.c:162:13: error: undefined identifier 'restrict' arch/x86/kernel/uv_irq.c:250:44: error: no identifier for function argument arch/x86/kernel/uv_irq.c:260:17: error: typename in expression arch/x86/kernel/uv_irq.c:260:17: error: undefined identifier 'restrict' arch/x86/kernel/uv_irq.c:233:50: warning: incorrect type in argument 3 (different signedness) arch/x86/kernel/uv_irq.c:233:50: expected int *pnode arch/x86/kernel/uv_irq.c:233:50: got unsigned int * arch/x86/include/asm/uv/uv_hub.h:318:44: warning: incorrect type in argument 2 (different address spaces) arch/x86/include/asm/uv/uv_hub.h:318:44: expected void volatile [noderef] *addr arch/x86/include/asm/uv/uv_hub.h:318:44: got unsigned long * Signed-off-by: Randy Dunlap Cc: Dimitri Sivanich Cc: Russ Anderson Cc: Robin Holt Cc: Mike Travis Cc: Cliff Wickman Cc: Jack Steiner LKML-Reference: <20100416175142.f4b59683.randy.dunlap@oracle.com> Signed-off-by: Ingo Molnar diff --git a/arch/x86/include/asm/uv/uv_hub.h b/arch/x86/include/asm/uv/uv_hub.h index 14cc74b..bf6b88e 100644 --- a/arch/x86/include/asm/uv/uv_hub.h +++ b/arch/x86/include/asm/uv/uv_hub.h @@ -307,7 +307,7 @@ static inline unsigned long uv_read_global_mmr32(int pnode, unsigned long offset * Access Global MMR space using the MMR space located at the top of physical * memory. */ -static inline unsigned long *uv_global_mmr64_address(int pnode, unsigned long offset) +static inline volatile void __iomem *uv_global_mmr64_address(int pnode, unsigned long offset) { return __va(UV_GLOBAL_MMR64_BASE | UV_GLOBAL_MMR64_PNODE_BITS(pnode) | offset); diff --git a/arch/x86/kernel/uv_irq.c b/arch/x86/kernel/uv_irq.c index ece73d8..1a9f55a 100644 --- a/arch/x86/kernel/uv_irq.c +++ b/arch/x86/kernel/uv_irq.c @@ -43,7 +43,7 @@ static void uv_ack_apic(unsigned int irq) ack_APIC_irq(); } -struct irq_chip uv_irq_chip = { +static struct irq_chip uv_irq_chip = { .name = "UV-CORE", .startup = uv_noop_ret, .shutdown = uv_noop, @@ -140,7 +140,7 @@ int uv_irq_2_mmr_info(int irq, unsigned long *offset, int *pnode) */ static int arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade, - unsigned long mmr_offset, int restrict) + unsigned long mmr_offset, int limit) { const struct cpumask *eligible_cpu = cpumask_of(cpu); struct irq_desc *desc = irq_to_desc(irq); @@ -159,7 +159,7 @@ arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade, if (err != 0) return err; - if (restrict == UV_AFFINITY_CPU) + if (limit == UV_AFFINITY_CPU) desc->status |= IRQ_NO_BALANCING; else desc->status |= IRQ_MOVE_PCNTXT; @@ -213,7 +213,7 @@ static int uv_set_irq_affinity(unsigned int irq, const struct cpumask *mask) unsigned long mmr_value; struct uv_IO_APIC_route_entry *entry; unsigned long mmr_offset; - unsigned mmr_pnode; + int mmr_pnode; if (set_desc_affinity(desc, mask, &dest)) return -1; @@ -247,7 +247,7 @@ static int uv_set_irq_affinity(unsigned int irq, const struct cpumask *mask) * interrupt is raised. */ int uv_setup_irq(char *irq_name, int cpu, int mmr_blade, - unsigned long mmr_offset, int restrict) + unsigned long mmr_offset, int limit) { int irq, ret; @@ -257,7 +257,7 @@ int uv_setup_irq(char *irq_name, int cpu, int mmr_blade, return -EBUSY; ret = arch_enable_uv_irq(irq_name, irq, cpu, mmr_blade, mmr_offset, - restrict); + limit); if (ret == irq) uv_set_irq_2_mmr_info(irq, mmr_offset, mmr_blade); else -- cgit v0.10.2 From d9c944463d8f3f7cafaaba8f3e44df62ce817484 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 19 Apr 2010 16:27:47 +0900 Subject: sh: mach-sdk7786: pm_power_off support. This wires up power-off support for the SDK7786 board. Signed-off-by: Paul Mundt diff --git a/arch/sh/boards/mach-sdk7786/setup.c b/arch/sh/boards/mach-sdk7786/setup.c index f094ea2..0c057a9 100644 --- a/arch/sh/boards/mach-sdk7786/setup.c +++ b/arch/sh/boards/mach-sdk7786/setup.c @@ -165,6 +165,19 @@ static void sdk7786_restart(char *cmd) fpga_write_reg(0xa5a5, SRSTR); } +static void sdk7786_power_off(void) +{ + fpga_write_reg(fpga_read_reg(PWRCR) | PWRCR_PDWNREQ, PWRCR); + + /* + * It can take up to 20us for the R8C to do its job, back off and + * wait a bit until we've been shut off. Even though newer FPGA + * versions don't set the ACK bit, the latency issue remains. + */ + while ((fpga_read_reg(PWRCR) & PWRCR_PDWNACK) == 0) + cpu_sleep(); +} + /* Initialize the board */ static void __init sdk7786_setup(char **cmdline_p) { @@ -175,6 +188,7 @@ static void __init sdk7786_setup(char **cmdline_p) pr_info("\tPCB revision:\t%d\n", fpga_read_reg(PCBRR) & 0xf); machine_ops.restart = sdk7786_restart; + pm_power_off = sdk7786_power_off; } /* diff --git a/arch/sh/include/mach-sdk7786/mach/fpga.h b/arch/sh/include/mach-sdk7786/mach/fpga.h index 2120d67..416b621 100644 --- a/arch/sh/include/mach-sdk7786/mach/fpga.h +++ b/arch/sh/include/mach-sdk7786/mach/fpga.h @@ -42,6 +42,15 @@ #define SCBR_I2CCEN BIT(1) /* CPU I2C master enable */ #define PWRCR 0x1a0 +#define PWRCR_SCISEL0 BIT(0) +#define PWRCR_SCISEL1 BIT(1) +#define PWRCR_SCIEN BIT(2) /* Serial port enable */ +#define PWRCR_PDWNACK BIT(5) /* Power down acknowledge */ +#define PWRCR_PDWNREQ BIT(7) /* Power down request */ +#define PWRCR_INT2 BIT(11) /* INT2 connection to power manager */ +#define PWRCR_BUPINIT BIT(13) /* DDR backup initialize */ +#define PWRCR_BKPRST BIT(15) /* Backup power reset */ + #define SPCBR 0x1b0 #define SPICR 0x1c0 #define SPIDR 0x1d0 -- cgit v0.10.2 From 3cf6fa1e334a3a4af702f92229690195018b747f Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 19 Apr 2010 17:27:17 +0900 Subject: sh: Enable SH-X3 hardware synonym avoidance handling. This enables support for the hardware synonym avoidance handling on SH-X3 CPUs for the case where dcache aliases are possible. icache handling is retained, but we flip on broadcasting of the block invalidations due to the lack of coherency otherwise on SMP. Signed-off-by: Paul Mundt diff --git a/arch/sh/mm/Makefile b/arch/sh/mm/Makefile index c73018a..53f7c68 100644 --- a/arch/sh/mm/Makefile +++ b/arch/sh/mm/Makefile @@ -10,6 +10,7 @@ cacheops-$(CONFIG_CPU_SH3) := cache-sh3.o cacheops-$(CONFIG_CPU_SH4) := cache-sh4.o flush-sh4.o cacheops-$(CONFIG_CPU_SH5) := cache-sh5.o flush-sh4.o cacheops-$(CONFIG_SH7705_CACHE_32KB) += cache-sh7705.o +cacheops-$(CONFIG_CPU_SHX3) += cache-shx3.o obj-y += $(cacheops-y) diff --git a/arch/sh/mm/cache-shx3.c b/arch/sh/mm/cache-shx3.c new file mode 100644 index 0000000..65936c4 --- /dev/null +++ b/arch/sh/mm/cache-shx3.c @@ -0,0 +1,35 @@ +/* + * arch/sh/mm/cache-shx3.c - SH-X3 optimized cache ops + * + * Copyright (C) 2010 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include + +#define CCR_CACHE_SNM 0x40000 /* Hardware-assisted synonym avoidance */ +#define CCR_CACHE_IBE 0x1000000 /* ICBI broadcast */ + +void __init shx3_cache_init(void) +{ + unsigned int ccr; + + ccr = __raw_readl(CCR); + + if (boot_cpu_data.dcache.n_aliases) + ccr |= CCR_CACHE_SNM; + +#ifdef CONFIG_SMP + /* + * Broadcast I-cache block invalidations by default. + */ + ccr |= CCR_CACHE_IBE; +#endif + + writel_uncached(ccr, CCR); +} diff --git a/arch/sh/mm/cache.c b/arch/sh/mm/cache.c index 0f4095d..ba401d1 100644 --- a/arch/sh/mm/cache.c +++ b/arch/sh/mm/cache.c @@ -334,6 +334,13 @@ void __init cpu_cache_init(void) extern void __weak sh4_cache_init(void); sh4_cache_init(); + + if ((boot_cpu_data.type == CPU_SH7786) || + (boot_cpu_data.type == CPU_SHX3)) { + extern void __weak shx3_cache_init(void); + + shx3_cache_init(); + } } if (boot_cpu_data.family == CPU_FAMILY_SH5) { -- cgit v0.10.2 From 39447b386c846bbf1c56f6403c5282837486200f Mon Sep 17 00:00:00 2001 From: "Zhang, Yanmin" Date: Mon, 19 Apr 2010 13:32:41 +0800 Subject: perf: Enhance perf to allow for guest statistic collection from host Below patch introduces perf_guest_info_callbacks and related register/unregister functions. Add more PERF_RECORD_MISC_XXX bits meaning guest kernel and guest user space. Signed-off-by: Zhang Yanmin Signed-off-by: Avi Kivity diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h index f6d43db..254883d 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h @@ -135,17 +135,10 @@ extern void perf_events_lapic_init(void); */ #define PERF_EFLAGS_EXACT (1UL << 3) -#define perf_misc_flags(regs) \ -({ int misc = 0; \ - if (user_mode(regs)) \ - misc |= PERF_RECORD_MISC_USER; \ - else \ - misc |= PERF_RECORD_MISC_KERNEL; \ - if (regs->flags & PERF_EFLAGS_EXACT) \ - misc |= PERF_RECORD_MISC_EXACT; \ - misc; }) - -#define perf_instruction_pointer(regs) ((regs)->ip) +struct pt_regs; +extern unsigned long perf_instruction_pointer(struct pt_regs *regs); +extern unsigned long perf_misc_flags(struct pt_regs *regs); +#define perf_misc_flags(regs) perf_misc_flags(regs) #else static inline void init_hw_perf_events(void) { } diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 626154a..2ea78ab 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -1720,6 +1720,11 @@ struct perf_callchain_entry *perf_callchain(struct pt_regs *regs) { struct perf_callchain_entry *entry; + if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { + /* TODO: We don't support guest os callchain now */ + return NULL; + } + if (in_nmi()) entry = &__get_cpu_var(pmc_nmi_entry); else @@ -1743,3 +1748,29 @@ void perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip, int ski regs->cs = __KERNEL_CS; local_save_flags(regs->flags); } + +unsigned long perf_instruction_pointer(struct pt_regs *regs) +{ + unsigned long ip; + if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) + ip = perf_guest_cbs->get_guest_ip(); + else + ip = instruction_pointer(regs); + return ip; +} + +unsigned long perf_misc_flags(struct pt_regs *regs) +{ + int misc = 0; + if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { + misc |= perf_guest_cbs->is_user_mode() ? + PERF_RECORD_MISC_GUEST_USER : + PERF_RECORD_MISC_GUEST_KERNEL; + } else + misc |= user_mode(regs) ? PERF_RECORD_MISC_USER : + PERF_RECORD_MISC_KERNEL; + if (regs->flags & PERF_EFLAGS_EXACT) + misc |= PERF_RECORD_MISC_EXACT; + + return misc; +} diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index bf896d0..24de5f1 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -288,11 +288,13 @@ struct perf_event_mmap_page { __u64 data_tail; /* user-space written tail */ }; -#define PERF_RECORD_MISC_CPUMODE_MASK (3 << 0) +#define PERF_RECORD_MISC_CPUMODE_MASK (7 << 0) #define PERF_RECORD_MISC_CPUMODE_UNKNOWN (0 << 0) #define PERF_RECORD_MISC_KERNEL (1 << 0) #define PERF_RECORD_MISC_USER (2 << 0) #define PERF_RECORD_MISC_HYPERVISOR (3 << 0) +#define PERF_RECORD_MISC_GUEST_KERNEL (4 << 0) +#define PERF_RECORD_MISC_GUEST_USER (5 << 0) #define PERF_RECORD_MISC_EXACT (1 << 14) /* @@ -446,6 +448,12 @@ enum perf_callchain_context { # include #endif +struct perf_guest_info_callbacks { + int (*is_in_guest) (void); + int (*is_user_mode) (void); + unsigned long (*get_guest_ip) (void); +}; + #ifdef CONFIG_HAVE_HW_BREAKPOINT #include #endif @@ -932,6 +940,12 @@ static inline void perf_event_mmap(struct vm_area_struct *vma) __perf_event_mmap(vma); } +extern struct perf_guest_info_callbacks *perf_guest_cbs; +extern int perf_register_guest_info_callbacks( + struct perf_guest_info_callbacks *); +extern int perf_unregister_guest_info_callbacks( + struct perf_guest_info_callbacks *); + extern void perf_event_comm(struct task_struct *tsk); extern void perf_event_fork(struct task_struct *tsk); @@ -1001,6 +1015,11 @@ perf_sw_event(u32 event_id, u64 nr, int nmi, static inline void perf_bp_event(struct perf_event *event, void *data) { } +static inline int perf_register_guest_info_callbacks +(struct perf_guest_info_callbacks *) {return 0; } +static inline int perf_unregister_guest_info_callbacks +(struct perf_guest_info_callbacks *) {return 0; } + static inline void perf_event_mmap(struct vm_area_struct *vma) { } static inline void perf_event_comm(struct task_struct *tsk) { } static inline void perf_event_fork(struct task_struct *tsk) { } diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 07b7a43..9dbe8cd 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -2798,6 +2798,27 @@ void perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip, int ski /* + * We assume there is only KVM supporting the callbacks. + * Later on, we might change it to a list if there is + * another virtualization implementation supporting the callbacks. + */ +struct perf_guest_info_callbacks *perf_guest_cbs; + +int perf_register_guest_info_callbacks(struct perf_guest_info_callbacks *cbs) +{ + perf_guest_cbs = cbs; + return 0; +} +EXPORT_SYMBOL_GPL(perf_register_guest_info_callbacks); + +int perf_unregister_guest_info_callbacks(struct perf_guest_info_callbacks *cbs) +{ + perf_guest_cbs = NULL; + return 0; +} +EXPORT_SYMBOL_GPL(perf_unregister_guest_info_callbacks); + +/* * Output */ static bool perf_output_space(struct perf_mmap_data *data, unsigned long tail, @@ -3749,7 +3770,7 @@ void __perf_event_mmap(struct vm_area_struct *vma) .event_id = { .header = { .type = PERF_RECORD_MMAP, - .misc = 0, + .misc = PERF_RECORD_MISC_USER, /* .size */ }, /* .pid */ -- cgit v0.10.2 From ff9d07a0e7ce756a183e7c2e483aec452ee6b574 Mon Sep 17 00:00:00 2001 From: "Zhang, Yanmin" Date: Mon, 19 Apr 2010 13:32:45 +0800 Subject: KVM: Implement perf callbacks for guest sampling Below patch implements the perf_guest_info_callbacks on kvm. Signed-off-by: Zhang Yanmin Signed-off-by: Avi Kivity diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 686492ed..82be6da 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -3654,8 +3654,11 @@ static void vmx_complete_interrupts(struct vcpu_vmx *vmx) /* We need to handle NMIs before interrupts are enabled */ if ((exit_intr_info & INTR_INFO_INTR_TYPE_MASK) == INTR_TYPE_NMI_INTR && - (exit_intr_info & INTR_INFO_VALID_MASK)) + (exit_intr_info & INTR_INFO_VALID_MASK)) { + kvm_before_handle_nmi(&vmx->vcpu); asm("int $2"); + kvm_after_handle_nmi(&vmx->vcpu); + } idtv_info_valid = idt_vectoring_info & VECTORING_INFO_VALID_MASK; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 24cd0ee..c3a33b2 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #undef TRACE_INCLUDE_FILE #define CREATE_TRACE_POINTS @@ -3765,6 +3766,47 @@ static void kvm_timer_init(void) } } +static DEFINE_PER_CPU(struct kvm_vcpu *, current_vcpu); + +static int kvm_is_in_guest(void) +{ + return percpu_read(current_vcpu) != NULL; +} + +static int kvm_is_user_mode(void) +{ + int user_mode = 3; + if (percpu_read(current_vcpu)) + user_mode = kvm_x86_ops->get_cpl(percpu_read(current_vcpu)); + return user_mode != 0; +} + +static unsigned long kvm_get_guest_ip(void) +{ + unsigned long ip = 0; + if (percpu_read(current_vcpu)) + ip = kvm_rip_read(percpu_read(current_vcpu)); + return ip; +} + +static struct perf_guest_info_callbacks kvm_guest_cbs = { + .is_in_guest = kvm_is_in_guest, + .is_user_mode = kvm_is_user_mode, + .get_guest_ip = kvm_get_guest_ip, +}; + +void kvm_before_handle_nmi(struct kvm_vcpu *vcpu) +{ + percpu_write(current_vcpu, vcpu); +} +EXPORT_SYMBOL_GPL(kvm_before_handle_nmi); + +void kvm_after_handle_nmi(struct kvm_vcpu *vcpu) +{ + percpu_write(current_vcpu, NULL); +} +EXPORT_SYMBOL_GPL(kvm_after_handle_nmi); + int kvm_arch_init(void *opaque) { int r; @@ -3801,6 +3843,8 @@ int kvm_arch_init(void *opaque) kvm_timer_init(); + perf_register_guest_info_callbacks(&kvm_guest_cbs); + return 0; out: @@ -3809,6 +3853,8 @@ out: void kvm_arch_exit(void) { + perf_unregister_guest_info_callbacks(&kvm_guest_cbs); + if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) cpufreq_unregister_notifier(&kvmclock_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index 2d101639..b7a4047 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h @@ -65,4 +65,7 @@ static inline int is_paging(struct kvm_vcpu *vcpu) return kvm_read_cr0_bits(vcpu, X86_CR0_PG); } +void kvm_before_handle_nmi(struct kvm_vcpu *vcpu); +void kvm_after_handle_nmi(struct kvm_vcpu *vcpu); + #endif -- cgit v0.10.2 From a1645ce12adb6c9cc9e19d7695466204e3f017fe Mon Sep 17 00:00:00 2001 From: "Zhang, Yanmin" Date: Mon, 19 Apr 2010 13:32:50 +0800 Subject: perf: 'perf kvm' tool for monitoring guest performance from host Here is the patch of userspace perf tool. Signed-off-by: Zhang Yanmin Signed-off-by: Avi Kivity diff --git a/tools/perf/Documentation/perf-kvm.txt b/tools/perf/Documentation/perf-kvm.txt new file mode 100644 index 0000000..93400a0 --- /dev/null +++ b/tools/perf/Documentation/perf-kvm.txt @@ -0,0 +1,67 @@ +perf-kvm(1) +============== + +NAME +---- +perf-kvm - Tool to trace/measure kvm guest os + +SYNOPSIS +-------- +[verse] +'perf kvm' [--host] [--guest] [--guestmount= + [--guestkallsyms= --guestmodules= | --guestvmlinux=]] + {top|record|report|diff|buildid-list} +'perf kvm' [--host] [--guest] [--guestkallsyms= --guestmodules= + | --guestvmlinux=] {top|record|report|diff|buildid-list} + +DESCRIPTION +----------- +There are a couple of variants of perf kvm: + + 'perf kvm [options] top ' to generates and displays + a performance counter profile of guest os in realtime + of an arbitrary workload. + + 'perf kvm record ' to record the performance couinter profile + of an arbitrary workload and save it into a perf data file. If both + --host and --guest are input, the perf data file name is perf.data.kvm. + If there is no --host but --guest, the file name is perf.data.guest. + If there is no --guest but --host, the file name is perf.data.host. + + 'perf kvm report' to display the performance counter profile information + recorded via perf kvm record. + + 'perf kvm diff' to displays the performance difference amongst two perf.data + files captured via perf record. + + 'perf kvm buildid-list' to display the buildids found in a perf data file, + so that other tools can be used to fetch packages with matching symbol tables + for use by perf report. + +OPTIONS +------- +--host=:: + Collect host side perforamnce profile. +--guest=:: + Collect guest side perforamnce profile. +--guestmount=:: + Guest os root file system mount directory. Users mounts guest os + root directories under by a specific filesystem access method, + typically, sshfs. For example, start 2 guest os. The one's pid is 8888 + and the other's is 9999. + #mkdir ~/guestmount; cd ~/guestmount + #sshfs -o allow_other,direct_io -p 5551 localhost:/ 8888/ + #sshfs -o allow_other,direct_io -p 5552 localhost:/ 9999/ + #perf kvm --host --guest --guestmount=~/guestmount top +--guestkallsyms=:: + Guest os /proc/kallsyms file copy. 'perf' kvm' reads it to get guest + kernel symbols. Users copy it out from guest os. +--guestmodules=:: + Guest os /proc/modules file copy. 'perf' kvm' reads it to get guest + kernel module information. Users copy it out from guest os. +--guestvmlinux=:: + Guest os kernel vmlinux. + +SEE ALSO +-------- +linkperf:perf-top[1] perf-record[1] perf-report[1] perf-diff[1] perf-buildid-list[1] diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 57b3569..3cb3449 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -472,6 +472,7 @@ BUILTIN_OBJS += $(OUTPUT)builtin-trace.o BUILTIN_OBJS += $(OUTPUT)builtin-probe.o BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o BUILTIN_OBJS += $(OUTPUT)builtin-lock.o +BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o PERFLIBS = $(LIB_FILE) diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 06eaebe..f924b43 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -571,7 +571,7 @@ static int __cmd_annotate(void) perf_session__fprintf(session, stdout); if (verbose > 2) - dsos__fprintf(stdout); + dsos__fprintf(&session->kerninfo_root, stdout); perf_session__collapse_resort(&session->hists); perf_session__output_resort(&session->hists, session->event_total[0]); diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c index af2ad8b..623afe3 100644 --- a/tools/perf/builtin-buildid-list.c +++ b/tools/perf/builtin-buildid-list.c @@ -46,7 +46,7 @@ static int __cmd_buildid_list(void) if (with_hits) perf_session__process_events(session, &build_id__mark_dso_hit_ops); - dsos__fprintf_buildid(stdout, with_hits); + dsos__fprintf_buildid(&session->kerninfo_root, stdout, with_hits); perf_session__delete(session); return err; diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 3a1d94d..207e860 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -33,7 +33,7 @@ static int perf_session__add_hist_entry(struct perf_session *self, return -ENOMEM; if (hit) - he->count += count; + __perf_session__add_count(he, al, count); return 0; } @@ -225,6 +225,10 @@ int cmd_diff(int argc, const char **argv, const char *prefix __used) input_new = argv[1]; } else input_new = argv[0]; + } else if (symbol_conf.default_guest_vmlinux_name || + symbol_conf.default_guest_kallsyms) { + input_old = "perf.data.host"; + input_new = "perf.data.guest"; } symbol_conf.exclude_other = false; diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index 513aa8a..db474bb 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c @@ -351,6 +351,7 @@ static void __print_result(struct rb_root *root, struct perf_session *session, int n_lines, int is_caller) { struct rb_node *next; + struct kernel_info *kerninfo; printf("%.102s\n", graph_dotted_line); printf(" %-34s |", is_caller ? "Callsite": "Alloc Ptr"); @@ -359,10 +360,16 @@ static void __print_result(struct rb_root *root, struct perf_session *session, next = rb_first(root); + kerninfo = kerninfo__findhost(&session->kerninfo_root); + if (!kerninfo) { + pr_err("__print_result: couldn't find kernel information\n"); + return; + } while (next && n_lines--) { struct alloc_stat *data = rb_entry(next, struct alloc_stat, node); struct symbol *sym = NULL; + struct map_groups *kmaps = &kerninfo->kmaps; struct map *map; char buf[BUFSIZ]; u64 addr; @@ -370,8 +377,8 @@ static void __print_result(struct rb_root *root, struct perf_session *session, if (is_caller) { addr = data->call_site; if (!raw_ip) - sym = map_groups__find_function(&session->kmaps, - addr, &map, NULL); + sym = map_groups__find_function(kmaps, addr, + &map, NULL); } else addr = data->ptr; diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c new file mode 100644 index 0000000..a4c7cae --- /dev/null +++ b/tools/perf/builtin-kvm.c @@ -0,0 +1,144 @@ +#include "builtin.h" +#include "perf.h" + +#include "util/util.h" +#include "util/cache.h" +#include "util/symbol.h" +#include "util/thread.h" +#include "util/header.h" +#include "util/session.h" + +#include "util/parse-options.h" +#include "util/trace-event.h" + +#include "util/debug.h" + +#include + +#include +#include +#include + +static char *file_name; +static char name_buffer[256]; + +int perf_host = 1; +int perf_guest; + +static const char * const kvm_usage[] = { + "perf kvm [] {top|record|report|diff|buildid-list}", + NULL +}; + +static const struct option kvm_options[] = { + OPT_STRING('i', "input", &file_name, "file", + "Input file name"), + OPT_STRING('o', "output", &file_name, "file", + "Output file name"), + OPT_BOOLEAN(0, "guest", &perf_guest, + "Collect guest os data"), + OPT_BOOLEAN(0, "host", &perf_host, + "Collect guest os data"), + OPT_STRING(0, "guestmount", &symbol_conf.guestmount, "directory", + "guest mount directory under which every guest os" + " instance has a subdir"), + OPT_STRING(0, "guestvmlinux", &symbol_conf.default_guest_vmlinux_name, + "file", "file saving guest os vmlinux"), + OPT_STRING(0, "guestkallsyms", &symbol_conf.default_guest_kallsyms, + "file", "file saving guest os /proc/kallsyms"), + OPT_STRING(0, "guestmodules", &symbol_conf.default_guest_modules, + "file", "file saving guest os /proc/modules"), + OPT_END() +}; + +static int __cmd_record(int argc, const char **argv) +{ + int rec_argc, i = 0, j; + const char **rec_argv; + + rec_argc = argc + 2; + rec_argv = calloc(rec_argc + 1, sizeof(char *)); + rec_argv[i++] = strdup("record"); + rec_argv[i++] = strdup("-o"); + rec_argv[i++] = strdup(file_name); + for (j = 1; j < argc; j++, i++) + rec_argv[i] = argv[j]; + + BUG_ON(i != rec_argc); + + return cmd_record(i, rec_argv, NULL); +} + +static int __cmd_report(int argc, const char **argv) +{ + int rec_argc, i = 0, j; + const char **rec_argv; + + rec_argc = argc + 2; + rec_argv = calloc(rec_argc + 1, sizeof(char *)); + rec_argv[i++] = strdup("report"); + rec_argv[i++] = strdup("-i"); + rec_argv[i++] = strdup(file_name); + for (j = 1; j < argc; j++, i++) + rec_argv[i] = argv[j]; + + BUG_ON(i != rec_argc); + + return cmd_report(i, rec_argv, NULL); +} + +static int __cmd_buildid_list(int argc, const char **argv) +{ + int rec_argc, i = 0, j; + const char **rec_argv; + + rec_argc = argc + 2; + rec_argv = calloc(rec_argc + 1, sizeof(char *)); + rec_argv[i++] = strdup("buildid-list"); + rec_argv[i++] = strdup("-i"); + rec_argv[i++] = strdup(file_name); + for (j = 1; j < argc; j++, i++) + rec_argv[i] = argv[j]; + + BUG_ON(i != rec_argc); + + return cmd_buildid_list(i, rec_argv, NULL); +} + +int cmd_kvm(int argc, const char **argv, const char *prefix __used) +{ + perf_host = perf_guest = 0; + + argc = parse_options(argc, argv, kvm_options, kvm_usage, + PARSE_OPT_STOP_AT_NON_OPTION); + if (!argc) + usage_with_options(kvm_usage, kvm_options); + + if (!perf_host) + perf_guest = 1; + + if (!file_name) { + if (perf_host && !perf_guest) + sprintf(name_buffer, "perf.data.host"); + else if (!perf_host && perf_guest) + sprintf(name_buffer, "perf.data.guest"); + else + sprintf(name_buffer, "perf.data.kvm"); + file_name = name_buffer; + } + + if (!strncmp(argv[0], "rec", 3)) + return __cmd_record(argc, argv); + else if (!strncmp(argv[0], "rep", 3)) + return __cmd_report(argc, argv); + else if (!strncmp(argv[0], "diff", 4)) + return cmd_diff(argc, argv, NULL); + else if (!strncmp(argv[0], "top", 3)) + return cmd_top(argc, argv, NULL); + else if (!strncmp(argv[0], "buildid-list", 12)) + return __cmd_buildid_list(argc, argv); + else + usage_with_options(kvm_usage, kvm_options); + + return 0; +} diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index a1b99ee..27f992a 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -456,6 +456,52 @@ static void atexit_header(void) } } +static void event__synthesize_guest_os(struct kernel_info *kerninfo, + void *data __attribute__((unused))) +{ + int err; + char *guest_kallsyms; + char path[PATH_MAX]; + + if (is_host_kernel(kerninfo)) + return; + + /* + *As for guest kernel when processing subcommand record&report, + *we arrange module mmap prior to guest kernel mmap and trigger + *a preload dso because default guest module symbols are loaded + *from guest kallsyms instead of /lib/modules/XXX/XXX. This + *method is used to avoid symbol missing when the first addr is + *in module instead of in guest kernel. + */ + err = event__synthesize_modules(process_synthesized_event, + session, + kerninfo); + if (err < 0) + pr_err("Couldn't record guest kernel [%d]'s reference" + " relocation symbol.\n", kerninfo->pid); + + if (is_default_guest(kerninfo)) + guest_kallsyms = (char *) symbol_conf.default_guest_kallsyms; + else { + sprintf(path, "%s/proc/kallsyms", kerninfo->root_dir); + guest_kallsyms = path; + } + + /* + * We use _stext for guest kernel because guest kernel's /proc/kallsyms + * have no _text sometimes. + */ + err = event__synthesize_kernel_mmap(process_synthesized_event, + session, kerninfo, "_text"); + if (err < 0) + err = event__synthesize_kernel_mmap(process_synthesized_event, + session, kerninfo, "_stext"); + if (err < 0) + pr_err("Couldn't record guest kernel [%d]'s reference" + " relocation symbol.\n", kerninfo->pid); +} + static int __cmd_record(int argc, const char **argv) { int i, counter; @@ -467,6 +513,7 @@ static int __cmd_record(int argc, const char **argv) int child_ready_pipe[2], go_pipe[2]; const bool forks = argc > 0; char buf; + struct kernel_info *kerninfo; page_size = sysconf(_SC_PAGE_SIZE); @@ -635,21 +682,31 @@ static int __cmd_record(int argc, const char **argv) advance_output(err); } + kerninfo = kerninfo__findhost(&session->kerninfo_root); + if (!kerninfo) { + pr_err("Couldn't find native kernel information.\n"); + return -1; + } + err = event__synthesize_kernel_mmap(process_synthesized_event, - session, "_text"); + session, kerninfo, "_text"); if (err < 0) err = event__synthesize_kernel_mmap(process_synthesized_event, - session, "_stext"); + session, kerninfo, "_stext"); if (err < 0) { pr_err("Couldn't record kernel reference relocation symbol.\n"); return err; } - err = event__synthesize_modules(process_synthesized_event, session); + err = event__synthesize_modules(process_synthesized_event, + session, kerninfo); if (err < 0) { pr_err("Couldn't record kernel reference relocation symbol.\n"); return err; } + if (perf_guest) + kerninfo__process_allkernels(&session->kerninfo_root, + event__synthesize_guest_os, session); if (!system_wide && profile_cpu == -1) event__synthesize_thread(target_tid, process_synthesized_event, diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 7da5fb3..816edae 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -108,7 +108,7 @@ static int perf_session__add_hist_entry(struct perf_session *self, return -ENOMEM; if (hit) - he->count += data->period; + __perf_session__add_count(he, al, data->period); if (symbol_conf.use_callchain) { if (!hit) @@ -313,7 +313,7 @@ static int __cmd_report(void) perf_session__fprintf(session, stdout); if (verbose > 2) - dsos__fprintf(stdout); + dsos__fprintf(&session->kerninfo_root, stdout); next = rb_first(&session->stats_by_id); while (next) { @@ -450,6 +450,8 @@ static const struct option options[] = { "sort by key(s): pid, comm, dso, symbol, parent"), OPT_BOOLEAN('P', "full-paths", &symbol_conf.full_paths, "Don't shorten the pathnames taking into account the cwd"), + OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization, + "Show sample percentage for different cpu modes"), OPT_STRING('p', "parent", &parent_pattern, "regex", "regex filter to identify parent, see: '--sort parent'"), OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other, diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 40f24dd..dfd7ea7 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -420,8 +420,9 @@ static double sym_weight(const struct sym_entry *sym) } static long samples; -static long userspace_samples; +static long kernel_samples, us_samples; static long exact_samples; +static long guest_us_samples, guest_kernel_samples; static const char CONSOLE_CLEAR[] = ""; static void __list_insert_active_sym(struct sym_entry *syme) @@ -461,7 +462,10 @@ static void print_sym_table(void) int printed = 0, j; int counter, snap = !display_weighted ? sym_counter : 0; float samples_per_sec = samples/delay_secs; - float ksamples_per_sec = (samples-userspace_samples)/delay_secs; + float ksamples_per_sec = kernel_samples/delay_secs; + float us_samples_per_sec = (us_samples)/delay_secs; + float guest_kernel_samples_per_sec = (guest_kernel_samples)/delay_secs; + float guest_us_samples_per_sec = (guest_us_samples)/delay_secs; float esamples_percent = (100.0*exact_samples)/samples; float sum_ksamples = 0.0; struct sym_entry *syme, *n; @@ -470,7 +474,8 @@ static void print_sym_table(void) int sym_width = 0, dso_width = 0, dso_short_width = 0; const int win_width = winsize.ws_col - 1; - samples = userspace_samples = exact_samples = 0; + samples = us_samples = kernel_samples = exact_samples = 0; + guest_kernel_samples = guest_us_samples = 0; /* Sort the active symbols */ pthread_mutex_lock(&active_symbols_lock); @@ -501,10 +506,30 @@ static void print_sym_table(void) puts(CONSOLE_CLEAR); printf("%-*.*s\n", win_width, win_width, graph_dotted_line); - printf( " PerfTop:%8.0f irqs/sec kernel:%4.1f%% exact: %4.1f%% [", - samples_per_sec, - 100.0 - (100.0*((samples_per_sec-ksamples_per_sec)/samples_per_sec)), - esamples_percent); + if (!perf_guest) { + printf(" PerfTop:%8.0f irqs/sec kernel:%4.1f%%" + " exact: %4.1f%% [", + samples_per_sec, + 100.0 - (100.0 * ((samples_per_sec - ksamples_per_sec) / + samples_per_sec)), + esamples_percent); + } else { + printf(" PerfTop:%8.0f irqs/sec kernel:%4.1f%% us:%4.1f%%" + " guest kernel:%4.1f%% guest us:%4.1f%%" + " exact: %4.1f%% [", + samples_per_sec, + 100.0 - (100.0 * ((samples_per_sec-ksamples_per_sec) / + samples_per_sec)), + 100.0 - (100.0 * ((samples_per_sec-us_samples_per_sec) / + samples_per_sec)), + 100.0 - (100.0 * ((samples_per_sec - + guest_kernel_samples_per_sec) / + samples_per_sec)), + 100.0 - (100.0 * ((samples_per_sec - + guest_us_samples_per_sec) / + samples_per_sec)), + esamples_percent); + } if (nr_counters == 1 || !display_weighted) { printf("%Ld", (u64)attrs[0].sample_period); @@ -597,7 +622,6 @@ static void print_sym_table(void) syme = rb_entry(nd, struct sym_entry, rb_node); sym = sym_entry__symbol(syme); - if (++printed > print_entries || (int)syme->snap_count < count_filter) continue; @@ -761,7 +785,7 @@ static int key_mapped(int c) return 0; } -static void handle_keypress(int c) +static void handle_keypress(struct perf_session *session, int c) { if (!key_mapped(c)) { struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; @@ -830,7 +854,7 @@ static void handle_keypress(int c) case 'Q': printf("exiting.\n"); if (dump_symtab) - dsos__fprintf(stderr); + dsos__fprintf(&session->kerninfo_root, stderr); exit(0); case 's': prompt_symbol(&sym_filter_entry, "Enter details symbol"); @@ -866,6 +890,7 @@ static void *display_thread(void *arg __used) struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; struct termios tc, save; int delay_msecs, c; + struct perf_session *session = (struct perf_session *) arg; tcgetattr(0, &save); tc = save; @@ -886,7 +911,7 @@ repeat: c = getc(stdin); tcsetattr(0, TCSAFLUSH, &save); - handle_keypress(c); + handle_keypress(session, c); goto repeat; return NULL; @@ -957,24 +982,46 @@ static void event__process_sample(const event_t *self, u64 ip = self->ip.ip; struct sym_entry *syme; struct addr_location al; + struct kernel_info *kerninfo; u8 origin = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; ++samples; switch (origin) { case PERF_RECORD_MISC_USER: - ++userspace_samples; + ++us_samples; if (hide_user_symbols) return; + kerninfo = kerninfo__findhost(&session->kerninfo_root); break; case PERF_RECORD_MISC_KERNEL: + ++kernel_samples; if (hide_kernel_symbols) return; + kerninfo = kerninfo__findhost(&session->kerninfo_root); break; + case PERF_RECORD_MISC_GUEST_KERNEL: + ++guest_kernel_samples; + kerninfo = kerninfo__find(&session->kerninfo_root, + self->ip.pid); + break; + case PERF_RECORD_MISC_GUEST_USER: + ++guest_us_samples; + /* + * TODO: we don't process guest user from host side + * except simple counting. + */ + return; default: return; } + if (!kerninfo && perf_guest) { + pr_err("Can't find guest [%d]'s kernel information\n", + self->ip.pid); + return; + } + if (self->header.misc & PERF_RECORD_MISC_EXACT) exact_samples++; @@ -994,7 +1041,7 @@ static void event__process_sample(const event_t *self, * --hide-kernel-symbols, even if the user specifies an * invalid --vmlinux ;-) */ - if (al.map == session->vmlinux_maps[MAP__FUNCTION] && + if (al.map == kerninfo->vmlinux_maps[MAP__FUNCTION] && RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) { pr_err("The %s file can't be used\n", symbol_conf.vmlinux_name); @@ -1261,7 +1308,7 @@ static int __cmd_top(void) perf_session__mmap_read(session); - if (pthread_create(&thread, NULL, display_thread, NULL)) { + if (pthread_create(&thread, NULL, display_thread, session)) { printf("Could not create display thread.\n"); exit(-1); } diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h index 10fe49e..ab28bca 100644 --- a/tools/perf/builtin.h +++ b/tools/perf/builtin.h @@ -32,5 +32,6 @@ extern int cmd_version(int argc, const char **argv, const char *prefix); extern int cmd_probe(int argc, const char **argv, const char *prefix); extern int cmd_kmem(int argc, const char **argv, const char *prefix); extern int cmd_lock(int argc, const char **argv, const char *prefix); +extern int cmd_kvm(int argc, const char **argv, const char *prefix); #endif diff --git a/tools/perf/command-list.txt b/tools/perf/command-list.txt index db6ee94..2a1162d 100644 --- a/tools/perf/command-list.txt +++ b/tools/perf/command-list.txt @@ -19,3 +19,4 @@ perf-trace mainporcelain common perf-probe mainporcelain common perf-kmem mainporcelain common perf-lock mainporcelain common +perf-kvm mainporcelain common diff --git a/tools/perf/perf.c b/tools/perf/perf.c index d4be55b..985cdb4 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c @@ -307,6 +307,7 @@ static void handle_internal_command(int argc, const char **argv) { "probe", cmd_probe, 0 }, { "kmem", cmd_kmem, 0 }, { "lock", cmd_lock, 0 }, + { "kvm", cmd_kvm, 0 }, }; unsigned int i; static const char ext[] = STRIP_EXTENSION; diff --git a/tools/perf/perf.h b/tools/perf/perf.h index ec21274..02821fe 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h @@ -131,4 +131,6 @@ struct ip_callchain { u64 ips[0]; }; +extern int perf_host, perf_guest; + #endif diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index 04904b3..0f60a390 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c @@ -24,7 +24,7 @@ static int build_id__mark_dso_hit(event_t *event, struct perf_session *session) } thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION, - event->ip.ip, &al); + event->ip.pid, event->ip.ip, &al); if (al.map != NULL) al.map->dso->hit = 1; diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 571fb25..e3fa8d3 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -112,7 +112,11 @@ static int event__synthesize_mmap_events(pid_t pid, pid_t tgid, event_t ev = { .header = { .type = PERF_RECORD_MMAP, - .misc = 0, /* Just like the kernel, see kernel/perf_event.c __perf_event_mmap */ + /* + * Just like the kernel, see __perf_event_mmap + * in kernel/perf_event.c + */ + .misc = PERF_RECORD_MISC_USER, }, }; int n; @@ -167,11 +171,23 @@ static int event__synthesize_mmap_events(pid_t pid, pid_t tgid, } int event__synthesize_modules(event__handler_t process, - struct perf_session *session) + struct perf_session *session, + struct kernel_info *kerninfo) { struct rb_node *nd; + struct map_groups *kmaps = &kerninfo->kmaps; + u16 misc; - for (nd = rb_first(&session->kmaps.maps[MAP__FUNCTION]); + /* + * kernel uses 0 for user space maps, see kernel/perf_event.c + * __perf_event_mmap + */ + if (is_host_kernel(kerninfo)) + misc = PERF_RECORD_MISC_KERNEL; + else + misc = PERF_RECORD_MISC_GUEST_KERNEL; + + for (nd = rb_first(&kmaps->maps[MAP__FUNCTION]); nd; nd = rb_next(nd)) { event_t ev; size_t size; @@ -182,12 +198,13 @@ int event__synthesize_modules(event__handler_t process, size = ALIGN(pos->dso->long_name_len + 1, sizeof(u64)); memset(&ev, 0, sizeof(ev)); - ev.mmap.header.misc = 1; /* kernel uses 0 for user space maps, see kernel/perf_event.c __perf_event_mmap */ + ev.mmap.header.misc = misc; ev.mmap.header.type = PERF_RECORD_MMAP; ev.mmap.header.size = (sizeof(ev.mmap) - (sizeof(ev.mmap.filename) - size)); ev.mmap.start = pos->start; ev.mmap.len = pos->end - pos->start; + ev.mmap.pid = kerninfo->pid; memcpy(ev.mmap.filename, pos->dso->long_name, pos->dso->long_name_len + 1); @@ -250,13 +267,18 @@ static int find_symbol_cb(void *arg, const char *name, char type, u64 start) int event__synthesize_kernel_mmap(event__handler_t process, struct perf_session *session, + struct kernel_info *kerninfo, const char *symbol_name) { size_t size; + const char *filename, *mmap_name; + char path[PATH_MAX]; + char name_buff[PATH_MAX]; + struct map *map; + event_t ev = { .header = { .type = PERF_RECORD_MMAP, - .misc = 1, /* kernel uses 0 for user space maps, see kernel/perf_event.c __perf_event_mmap */ }, }; /* @@ -266,16 +288,37 @@ int event__synthesize_kernel_mmap(event__handler_t process, */ struct process_symbol_args args = { .name = symbol_name, }; - if (kallsyms__parse("/proc/kallsyms", &args, find_symbol_cb) <= 0) + mmap_name = kern_mmap_name(kerninfo, name_buff); + if (is_host_kernel(kerninfo)) { + /* + * kernel uses PERF_RECORD_MISC_USER for user space maps, + * see kernel/perf_event.c __perf_event_mmap + */ + ev.header.misc = PERF_RECORD_MISC_KERNEL; + filename = "/proc/kallsyms"; + } else { + ev.header.misc = PERF_RECORD_MISC_GUEST_KERNEL; + if (is_default_guest(kerninfo)) + filename = (char *) symbol_conf.default_guest_kallsyms; + else { + sprintf(path, "%s/proc/kallsyms", kerninfo->root_dir); + filename = path; + } + } + + if (kallsyms__parse(filename, &args, find_symbol_cb) <= 0) return -ENOENT; + map = kerninfo->vmlinux_maps[MAP__FUNCTION]; size = snprintf(ev.mmap.filename, sizeof(ev.mmap.filename), - "[kernel.kallsyms.%s]", symbol_name) + 1; + "%s%s", mmap_name, symbol_name) + 1; size = ALIGN(size, sizeof(u64)); - ev.mmap.header.size = (sizeof(ev.mmap) - (sizeof(ev.mmap.filename) - size)); + ev.mmap.header.size = (sizeof(ev.mmap) - + (sizeof(ev.mmap.filename) - size)); ev.mmap.pgoff = args.start; - ev.mmap.start = session->vmlinux_maps[MAP__FUNCTION]->start; - ev.mmap.len = session->vmlinux_maps[MAP__FUNCTION]->end - ev.mmap.start ; + ev.mmap.start = map->start; + ev.mmap.len = map->end - ev.mmap.start; + ev.mmap.pid = kerninfo->pid; return process(&ev, session); } @@ -329,22 +372,50 @@ int event__process_lost(event_t *self, struct perf_session *session) return 0; } -int event__process_mmap(event_t *self, struct perf_session *session) +static void event_set_kernel_mmap_len(struct map **maps, event_t *self) +{ + maps[MAP__FUNCTION]->start = self->mmap.start; + maps[MAP__FUNCTION]->end = self->mmap.start + self->mmap.len; + /* + * Be a bit paranoid here, some perf.data file came with + * a zero sized synthesized MMAP event for the kernel. + */ + if (maps[MAP__FUNCTION]->end == 0) + maps[MAP__FUNCTION]->end = ~0UL; +} + +static int event__process_kernel_mmap(event_t *self, + struct perf_session *session) { - struct thread *thread; struct map *map; + char kmmap_prefix[PATH_MAX]; + struct kernel_info *kerninfo; + enum dso_kernel_type kernel_type; + bool is_kernel_mmap; + + kerninfo = kerninfo__findnew(&session->kerninfo_root, self->mmap.pid); + if (!kerninfo) { + pr_err("Can't find id %d's kerninfo\n", self->mmap.pid); + goto out_problem; + } - dump_printf(" %d/%d: [%#Lx(%#Lx) @ %#Lx]: %s\n", - self->mmap.pid, self->mmap.tid, self->mmap.start, - self->mmap.len, self->mmap.pgoff, self->mmap.filename); + kern_mmap_name(kerninfo, kmmap_prefix); + if (is_host_kernel(kerninfo)) + kernel_type = DSO_TYPE_KERNEL; + else + kernel_type = DSO_TYPE_GUEST_KERNEL; - if (self->mmap.pid == 0) { - static const char kmmap_prefix[] = "[kernel.kallsyms."; + is_kernel_mmap = memcmp(self->mmap.filename, + kmmap_prefix, + strlen(kmmap_prefix)) == 0; + if (self->mmap.filename[0] == '/' || + (!is_kernel_mmap && self->mmap.filename[0] == '[')) { - if (self->mmap.filename[0] == '/') { - char short_module_name[1024]; - char *name = strrchr(self->mmap.filename, '/'), *dot; + char short_module_name[1024]; + char *name, *dot; + if (self->mmap.filename[0] == '/') { + name = strrchr(self->mmap.filename, '/'); if (name == NULL) goto out_problem; @@ -352,59 +423,86 @@ int event__process_mmap(event_t *self, struct perf_session *session) dot = strrchr(name, '.'); if (dot == NULL) goto out_problem; - snprintf(short_module_name, sizeof(short_module_name), - "[%.*s]", (int)(dot - name), name); + "[%.*s]", (int)(dot - name), name); strxfrchar(short_module_name, '-', '_'); - - map = perf_session__new_module_map(session, - self->mmap.start, - self->mmap.filename); - if (map == NULL) - goto out_problem; - - name = strdup(short_module_name); - if (name == NULL) - goto out_problem; - - map->dso->short_name = name; - map->end = map->start + self->mmap.len; - } else if (memcmp(self->mmap.filename, kmmap_prefix, - sizeof(kmmap_prefix) - 1) == 0) { - const char *symbol_name = (self->mmap.filename + - sizeof(kmmap_prefix) - 1); + } else + strcpy(short_module_name, self->mmap.filename); + + map = map_groups__new_module(&kerninfo->kmaps, + self->mmap.start, + self->mmap.filename, + kerninfo); + if (map == NULL) + goto out_problem; + + name = strdup(short_module_name); + if (name == NULL) + goto out_problem; + + map->dso->short_name = name; + map->end = map->start + self->mmap.len; + } else if (is_kernel_mmap) { + const char *symbol_name = (self->mmap.filename + + strlen(kmmap_prefix)); + /* + * Should be there already, from the build-id table in + * the header. + */ + struct dso *kernel = __dsos__findnew(&kerninfo->dsos__kernel, + kmmap_prefix); + if (kernel == NULL) + goto out_problem; + + kernel->kernel = kernel_type; + if (__map_groups__create_kernel_maps(&kerninfo->kmaps, + kerninfo->vmlinux_maps, kernel) < 0) + goto out_problem; + + event_set_kernel_mmap_len(kerninfo->vmlinux_maps, self); + perf_session__set_kallsyms_ref_reloc_sym(kerninfo->vmlinux_maps, + symbol_name, + self->mmap.pgoff); + if (is_default_guest(kerninfo)) { /* - * Should be there already, from the build-id table in - * the header. + * preload dso of guest kernel and modules */ - struct dso *kernel = __dsos__findnew(&dsos__kernel, - "[kernel.kallsyms]"); - if (kernel == NULL) - goto out_problem; - - kernel->kernel = 1; - if (__perf_session__create_kernel_maps(session, kernel) < 0) - goto out_problem; + dso__load(kernel, + kerninfo->vmlinux_maps[MAP__FUNCTION], + NULL); + } + } + return 0; +out_problem: + return -1; +} - session->vmlinux_maps[MAP__FUNCTION]->start = self->mmap.start; - session->vmlinux_maps[MAP__FUNCTION]->end = self->mmap.start + self->mmap.len; - /* - * Be a bit paranoid here, some perf.data file came with - * a zero sized synthesized MMAP event for the kernel. - */ - if (session->vmlinux_maps[MAP__FUNCTION]->end == 0) - session->vmlinux_maps[MAP__FUNCTION]->end = ~0UL; +int event__process_mmap(event_t *self, struct perf_session *session) +{ + struct kernel_info *kerninfo; + struct thread *thread; + struct map *map; + u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; + int ret = 0; - perf_session__set_kallsyms_ref_reloc_sym(session, symbol_name, - self->mmap.pgoff); - } + dump_printf(" %d/%d: [%#Lx(%#Lx) @ %#Lx]: %s\n", + self->mmap.pid, self->mmap.tid, self->mmap.start, + self->mmap.len, self->mmap.pgoff, self->mmap.filename); + + if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL || + cpumode == PERF_RECORD_MISC_KERNEL) { + ret = event__process_kernel_mmap(self, session); + if (ret < 0) + goto out_problem; return 0; } thread = perf_session__findnew(session, self->mmap.pid); - map = map__new(self->mmap.start, self->mmap.len, self->mmap.pgoff, - self->mmap.pid, self->mmap.filename, MAP__FUNCTION, - session->cwd, session->cwdlen); + kerninfo = kerninfo__findhost(&session->kerninfo_root); + map = map__new(&kerninfo->dsos__user, self->mmap.start, + self->mmap.len, self->mmap.pgoff, + self->mmap.pid, self->mmap.filename, + MAP__FUNCTION, session->cwd, session->cwdlen); if (thread == NULL || map == NULL) goto out_problem; @@ -444,22 +542,52 @@ int event__process_task(event_t *self, struct perf_session *session) void thread__find_addr_map(struct thread *self, struct perf_session *session, u8 cpumode, - enum map_type type, u64 addr, + enum map_type type, pid_t pid, u64 addr, struct addr_location *al) { struct map_groups *mg = &self->mg; + struct kernel_info *kerninfo = NULL; al->thread = self; al->addr = addr; + al->cpumode = cpumode; + al->filtered = false; - if (cpumode == PERF_RECORD_MISC_KERNEL) { + if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) { al->level = 'k'; - mg = &session->kmaps; - } else if (cpumode == PERF_RECORD_MISC_USER) + kerninfo = kerninfo__findhost(&session->kerninfo_root); + mg = &kerninfo->kmaps; + } else if (cpumode == PERF_RECORD_MISC_USER && perf_host) { al->level = '.'; - else { - al->level = 'H'; + kerninfo = kerninfo__findhost(&session->kerninfo_root); + } else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) { + al->level = 'g'; + kerninfo = kerninfo__find(&session->kerninfo_root, pid); + if (!kerninfo) { + al->map = NULL; + return; + } + mg = &kerninfo->kmaps; + } else { + /* + * 'u' means guest os user space. + * TODO: We don't support guest user space. Might support late. + */ + if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest) + al->level = 'u'; + else + al->level = 'H'; al->map = NULL; + + if ((cpumode == PERF_RECORD_MISC_GUEST_USER || + cpumode == PERF_RECORD_MISC_GUEST_KERNEL) && + !perf_guest) + al->filtered = true; + if ((cpumode == PERF_RECORD_MISC_USER || + cpumode == PERF_RECORD_MISC_KERNEL) && + !perf_host) + al->filtered = true; + return; } try_again: @@ -474,8 +602,11 @@ try_again: * "[vdso]" dso, but for now lets use the old trick of looking * in the whole kernel symbol list. */ - if ((long long)al->addr < 0 && mg != &session->kmaps) { - mg = &session->kmaps; + if ((long long)al->addr < 0 && + cpumode == PERF_RECORD_MISC_KERNEL && + kerninfo && + mg != &kerninfo->kmaps) { + mg = &kerninfo->kmaps; goto try_again; } } else @@ -484,11 +615,11 @@ try_again: void thread__find_addr_location(struct thread *self, struct perf_session *session, u8 cpumode, - enum map_type type, u64 addr, + enum map_type type, pid_t pid, u64 addr, struct addr_location *al, symbol_filter_t filter) { - thread__find_addr_map(self, session, cpumode, type, addr, al); + thread__find_addr_map(self, session, cpumode, type, pid, addr, al); if (al->map != NULL) al->sym = map__find_symbol(al->map, al->addr, filter); else @@ -524,7 +655,7 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session, dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION, - self->ip.ip, al); + self->ip.pid, self->ip.ip, al); dump_printf(" ...... dso: %s\n", al->map ? al->map->dso->long_name : al->level == 'H' ? "[hypervisor]" : ""); @@ -554,7 +685,6 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session, !strlist__has_entry(symbol_conf.sym_list, al->sym->name)) goto out_filtered; - al->filtered = false; return 0; out_filtered: diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index e5740ea..4af2ed5 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -79,6 +79,7 @@ struct sample_data { struct build_id_event { struct perf_event_header header; + pid_t pid; u8 build_id[ALIGN(BUILD_ID_SIZE, sizeof(u64))]; char filename[]; }; @@ -154,10 +155,13 @@ int event__synthesize_thread(pid_t pid, event__handler_t process, void event__synthesize_threads(event__handler_t process, struct perf_session *session); int event__synthesize_kernel_mmap(event__handler_t process, - struct perf_session *session, - const char *symbol_name); + struct perf_session *session, + struct kernel_info *kerninfo, + const char *symbol_name); + int event__synthesize_modules(event__handler_t process, - struct perf_session *session); + struct perf_session *session, + struct kernel_info *kerninfo); int event__process_comm(event_t *self, struct perf_session *session); int event__process_lost(event_t *self, struct perf_session *session); diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 628173b..75d0167 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -190,7 +190,8 @@ static int write_padded(int fd, const void *bf, size_t count, continue; \ else -static int __dsos__write_buildid_table(struct list_head *head, u16 misc, int fd) +static int __dsos__write_buildid_table(struct list_head *head, pid_t pid, + u16 misc, int fd) { struct dso *pos; @@ -205,6 +206,7 @@ static int __dsos__write_buildid_table(struct list_head *head, u16 misc, int fd) len = ALIGN(len, NAME_ALIGN); memset(&b, 0, sizeof(b)); memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id)); + b.pid = pid; b.header.misc = misc; b.header.size = sizeof(b) + len; err = do_write(fd, &b, sizeof(b)); @@ -219,13 +221,33 @@ static int __dsos__write_buildid_table(struct list_head *head, u16 misc, int fd) return 0; } -static int dsos__write_buildid_table(int fd) +static int dsos__write_buildid_table(struct perf_header *header, int fd) { - int err = __dsos__write_buildid_table(&dsos__kernel, - PERF_RECORD_MISC_KERNEL, fd); - if (err == 0) - err = __dsos__write_buildid_table(&dsos__user, - PERF_RECORD_MISC_USER, fd); + struct perf_session *session = container_of(header, + struct perf_session, header); + struct rb_node *nd; + int err = 0; + u16 kmisc, umisc; + + for (nd = rb_first(&session->kerninfo_root); nd; nd = rb_next(nd)) { + struct kernel_info *pos = rb_entry(nd, struct kernel_info, + rb_node); + if (is_host_kernel(pos)) { + kmisc = PERF_RECORD_MISC_KERNEL; + umisc = PERF_RECORD_MISC_USER; + } else { + kmisc = PERF_RECORD_MISC_GUEST_KERNEL; + umisc = PERF_RECORD_MISC_GUEST_USER; + } + + err = __dsos__write_buildid_table(&pos->dsos__kernel, pos->pid, + kmisc, fd); + if (err == 0) + err = __dsos__write_buildid_table(&pos->dsos__user, + pos->pid, umisc, fd); + if (err) + break; + } return err; } @@ -342,9 +364,12 @@ static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir) return err; } -static int dsos__cache_build_ids(void) +static int dsos__cache_build_ids(struct perf_header *self) { - int err_kernel, err_user; + struct perf_session *session = container_of(self, + struct perf_session, header); + struct rb_node *nd; + int ret = 0; char debugdir[PATH_MAX]; snprintf(debugdir, sizeof(debugdir), "%s/%s", getenv("HOME"), @@ -353,9 +378,30 @@ static int dsos__cache_build_ids(void) if (mkdir(debugdir, 0755) != 0 && errno != EEXIST) return -1; - err_kernel = __dsos__cache_build_ids(&dsos__kernel, debugdir); - err_user = __dsos__cache_build_ids(&dsos__user, debugdir); - return err_kernel || err_user ? -1 : 0; + for (nd = rb_first(&session->kerninfo_root); nd; nd = rb_next(nd)) { + struct kernel_info *pos = rb_entry(nd, struct kernel_info, + rb_node); + ret |= __dsos__cache_build_ids(&pos->dsos__kernel, debugdir); + ret |= __dsos__cache_build_ids(&pos->dsos__user, debugdir); + } + return ret ? -1 : 0; +} + +static bool dsos__read_build_ids(struct perf_header *self, bool with_hits) +{ + bool ret = false; + struct perf_session *session = container_of(self, + struct perf_session, header); + struct rb_node *nd; + + for (nd = rb_first(&session->kerninfo_root); nd; nd = rb_next(nd)) { + struct kernel_info *pos = rb_entry(nd, struct kernel_info, + rb_node); + ret |= __dsos__read_build_ids(&pos->dsos__kernel, with_hits); + ret |= __dsos__read_build_ids(&pos->dsos__user, with_hits); + } + + return ret; } static int perf_header__adds_write(struct perf_header *self, int fd) @@ -366,7 +412,7 @@ static int perf_header__adds_write(struct perf_header *self, int fd) u64 sec_start; int idx = 0, err; - if (dsos__read_build_ids(true)) + if (dsos__read_build_ids(self, true)) perf_header__set_feat(self, HEADER_BUILD_ID); nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); @@ -401,14 +447,14 @@ static int perf_header__adds_write(struct perf_header *self, int fd) /* Write build-ids */ buildid_sec->offset = lseek(fd, 0, SEEK_CUR); - err = dsos__write_buildid_table(fd); + err = dsos__write_buildid_table(self, fd); if (err < 0) { pr_debug("failed to write buildid table\n"); goto out_free; } buildid_sec->size = lseek(fd, 0, SEEK_CUR) - buildid_sec->offset; - dsos__cache_build_ids(); + dsos__cache_build_ids(self); } lseek(fd, sec_start, SEEK_SET); @@ -633,6 +679,85 @@ int perf_file_header__read(struct perf_file_header *self, return 0; } +static int __event_process_build_id(struct build_id_event *bev, + char *filename, + struct perf_session *session) +{ + int err = -1; + struct list_head *head; + struct kernel_info *kerninfo; + u16 misc; + struct dso *dso; + enum dso_kernel_type dso_type; + + kerninfo = kerninfo__findnew(&session->kerninfo_root, bev->pid); + if (!kerninfo) + goto out; + + misc = bev->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; + + switch (misc) { + case PERF_RECORD_MISC_KERNEL: + dso_type = DSO_TYPE_KERNEL; + head = &kerninfo->dsos__kernel; + break; + case PERF_RECORD_MISC_GUEST_KERNEL: + dso_type = DSO_TYPE_GUEST_KERNEL; + head = &kerninfo->dsos__kernel; + break; + case PERF_RECORD_MISC_USER: + case PERF_RECORD_MISC_GUEST_USER: + dso_type = DSO_TYPE_USER; + head = &kerninfo->dsos__user; + break; + default: + goto out; + } + + dso = __dsos__findnew(head, filename); + if (dso != NULL) { + dso__set_build_id(dso, &bev->build_id); + if (filename[0] == '[') + dso->kernel = dso_type; + } + + err = 0; +out: + return err; +} + +static int perf_header__read_build_ids(struct perf_header *self, + int input, u64 offset, u64 size) +{ + struct perf_session *session = container_of(self, + struct perf_session, header); + struct build_id_event bev; + char filename[PATH_MAX]; + u64 limit = offset + size; + int err = -1; + + while (offset < limit) { + ssize_t len; + + if (read(input, &bev, sizeof(bev)) != sizeof(bev)) + goto out; + + if (self->needs_swap) + perf_event_header__bswap(&bev.header); + + len = bev.header.size - sizeof(bev); + if (read(input, filename, len) != len) + goto out; + + __event_process_build_id(&bev, filename, session); + + offset += bev.header.size; + } + err = 0; +out: + return err; +} + static int perf_file_section__process(struct perf_file_section *self, struct perf_header *ph, int feat, int fd) @@ -989,6 +1114,7 @@ int event__process_tracing_data(event_t *self, int event__synthesize_build_id(struct dso *pos, u16 misc, event__handler_t process, + struct kernel_info *kerninfo, struct perf_session *session) { event_t ev; @@ -1005,6 +1131,7 @@ int event__synthesize_build_id(struct dso *pos, u16 misc, memcpy(&ev.build_id.build_id, pos->build_id, sizeof(pos->build_id)); ev.build_id.header.type = PERF_RECORD_HEADER_BUILD_ID; ev.build_id.header.misc = misc; + ev.build_id.pid = kerninfo->pid; ev.build_id.header.size = sizeof(ev.build_id) + len; memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len); @@ -1015,6 +1142,7 @@ int event__synthesize_build_id(struct dso *pos, u16 misc, static int __event_synthesize_build_ids(struct list_head *head, u16 misc, event__handler_t process, + struct kernel_info *kerninfo, struct perf_session *session) { struct dso *pos; @@ -1024,7 +1152,8 @@ static int __event_synthesize_build_ids(struct list_head *head, u16 misc, if (!pos->hit) continue; - err = event__synthesize_build_id(pos, misc, process, session); + err = event__synthesize_build_id(pos, misc, process, + kerninfo, session); if (err < 0) return err; } @@ -1035,44 +1164,48 @@ static int __event_synthesize_build_ids(struct list_head *head, u16 misc, int event__synthesize_build_ids(event__handler_t process, struct perf_session *session) { - int err; + int err = 0; + u16 kmisc, umisc; + struct kernel_info *pos; + struct rb_node *nd; - if (!dsos__read_build_ids(true)) + if (!dsos__read_build_ids(&session->header, true)) return 0; - err = __event_synthesize_build_ids(&dsos__kernel, - PERF_RECORD_MISC_KERNEL, - process, session); - if (err == 0) - err = __event_synthesize_build_ids(&dsos__user, - PERF_RECORD_MISC_USER, - process, session); + for (nd = rb_first(&session->kerninfo_root); nd; nd = rb_next(nd)) { + pos = rb_entry(nd, struct kernel_info, rb_node); + if (is_host_kernel(pos)) { + kmisc = PERF_RECORD_MISC_KERNEL; + umisc = PERF_RECORD_MISC_USER; + } else { + kmisc = PERF_RECORD_MISC_GUEST_KERNEL; + umisc = PERF_RECORD_MISC_GUEST_USER; + } + + err = __event_synthesize_build_ids(&pos->dsos__kernel, + kmisc, process, pos, session); + if (err == 0) + err = __event_synthesize_build_ids(&pos->dsos__user, + umisc, process, pos, session); + if (err) + break; + } if (err < 0) { pr_debug("failed to synthesize build ids\n"); return err; } - dsos__cache_build_ids(); + dsos__cache_build_ids(&session->header); return 0; } int event__process_build_id(event_t *self, - struct perf_session *session __unused) + struct perf_session *session) { - struct list_head *head = &dsos__user; - struct dso *dso; - - if (self->build_id.header.misc & PERF_RECORD_MISC_KERNEL) - head = &dsos__kernel; - - dso = __dsos__findnew(head, self->build_id.filename); - if (dso != NULL) { - dso__set_build_id(dso, &self->build_id.build_id); - if (head == &dsos__kernel && self->build_id.filename[0] == '[') - dso->kernel = 1; - } - + __event_process_build_id(&self->build_id, + self->build_id.filename, + session); return 0; } diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index 4214e23..2759154 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h @@ -120,6 +120,7 @@ int event__process_tracing_data(event_t *self, int event__synthesize_build_id(struct dso *pos, u16 misc, event__handler_t process, + struct kernel_info *kerninfo, struct perf_session *session); int event__synthesize_build_ids(event__handler_t process, struct perf_session *session); diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 9c2b874..ad6b22d 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -8,6 +8,30 @@ struct callchain_param callchain_param = { .min_percent = 0.5 }; +void __perf_session__add_count(struct hist_entry *he, + struct addr_location *al, + u64 count) +{ + he->count += count; + + switch (al->cpumode) { + case PERF_RECORD_MISC_KERNEL: + he->count_sys += count; + break; + case PERF_RECORD_MISC_USER: + he->count_us += count; + break; + case PERF_RECORD_MISC_GUEST_KERNEL: + he->count_guest_sys += count; + break; + case PERF_RECORD_MISC_GUEST_USER: + he->count_guest_us += count; + break; + default: + break; + } +} + /* * histogram, sorted on item, collects counts */ @@ -464,7 +488,7 @@ int hist_entry__snprintf(struct hist_entry *self, u64 session_total) { struct sort_entry *se; - u64 count, total; + u64 count, total, count_sys, count_us, count_guest_sys, count_guest_us; const char *sep = symbol_conf.field_sep; int ret; @@ -474,9 +498,17 @@ int hist_entry__snprintf(struct hist_entry *self, if (pair_session) { count = self->pair ? self->pair->count : 0; total = pair_session->events_stats.total; + count_sys = self->pair ? self->pair->count_sys : 0; + count_us = self->pair ? self->pair->count_us : 0; + count_guest_sys = self->pair ? self->pair->count_guest_sys : 0; + count_guest_us = self->pair ? self->pair->count_guest_us : 0; } else { count = self->count; total = session_total; + count_sys = self->count_sys; + count_us = self->count_us; + count_guest_sys = self->count_guest_sys; + count_guest_us = self->count_guest_us; } if (total) { @@ -487,6 +519,26 @@ int hist_entry__snprintf(struct hist_entry *self, else ret = snprintf(s, size, sep ? "%.2f" : " %6.2f%%", (count * 100.0) / total); + if (symbol_conf.show_cpu_utilization) { + ret += percent_color_snprintf(s + ret, size - ret, + sep ? "%.2f" : " %6.2f%%", + (count_sys * 100.0) / total); + ret += percent_color_snprintf(s + ret, size - ret, + sep ? "%.2f" : " %6.2f%%", + (count_us * 100.0) / total); + if (perf_guest) { + ret += percent_color_snprintf(s + ret, + size - ret, + sep ? "%.2f" : " %6.2f%%", + (count_guest_sys * 100.0) / + total); + ret += percent_color_snprintf(s + ret, + size - ret, + sep ? "%.2f" : " %6.2f%%", + (count_guest_us * 100.0) / + total); + } + } } else ret = snprintf(s, size, sep ? "%lld" : "%12lld ", count); @@ -597,6 +649,24 @@ size_t perf_session__fprintf_hists(struct rb_root *hists, fputs(" Samples ", fp); } + if (symbol_conf.show_cpu_utilization) { + if (sep) { + ret += fprintf(fp, "%csys", *sep); + ret += fprintf(fp, "%cus", *sep); + if (perf_guest) { + ret += fprintf(fp, "%cguest sys", *sep); + ret += fprintf(fp, "%cguest us", *sep); + } + } else { + ret += fprintf(fp, " sys "); + ret += fprintf(fp, " us "); + if (perf_guest) { + ret += fprintf(fp, " guest sys "); + ret += fprintf(fp, " guest us "); + } + } + } + if (pair) { if (sep) ret += fprintf(fp, "%cDelta", *sep); diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index ad17f0a..9df1c34 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -12,6 +12,9 @@ struct addr_location; struct symbol; struct rb_root; +void __perf_session__add_count(struct hist_entry *he, + struct addr_location *al, + u64 count); struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists, struct addr_location *al, struct symbol *parent, diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 37913b2..7facd01 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "map.h" const char *map_type__name[MAP__NR_TYPES] = { @@ -37,9 +38,11 @@ void map__init(struct map *self, enum map_type type, self->map_ip = map__map_ip; self->unmap_ip = map__unmap_ip; RB_CLEAR_NODE(&self->rb_node); + self->groups = NULL; } -struct map *map__new(u64 start, u64 len, u64 pgoff, u32 pid, char *filename, +struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, + u64 pgoff, u32 pid, char *filename, enum map_type type, char *cwd, int cwdlen) { struct map *self = malloc(sizeof(*self)); @@ -66,7 +69,7 @@ struct map *map__new(u64 start, u64 len, u64 pgoff, u32 pid, char *filename, filename = newfilename; } - dso = dsos__findnew(filename); + dso = __dsos__findnew(dsos__list, filename); if (dso == NULL) goto out_delete; @@ -242,6 +245,7 @@ void map_groups__init(struct map_groups *self) self->maps[i] = RB_ROOT; INIT_LIST_HEAD(&self->removed_maps[i]); } + self->this_kerninfo = NULL; } void map_groups__flush(struct map_groups *self) @@ -508,3 +512,134 @@ struct map *maps__find(struct rb_root *maps, u64 ip) return NULL; } + +struct kernel_info *add_new_kernel_info(struct rb_root *kerninfo_root, + pid_t pid, const char *root_dir) +{ + struct rb_node **p = &kerninfo_root->rb_node; + struct rb_node *parent = NULL; + struct kernel_info *kerninfo, *pos; + + kerninfo = malloc(sizeof(struct kernel_info)); + if (!kerninfo) + return NULL; + + kerninfo->pid = pid; + map_groups__init(&kerninfo->kmaps); + kerninfo->root_dir = strdup(root_dir); + RB_CLEAR_NODE(&kerninfo->rb_node); + INIT_LIST_HEAD(&kerninfo->dsos__user); + INIT_LIST_HEAD(&kerninfo->dsos__kernel); + kerninfo->kmaps.this_kerninfo = kerninfo; + + while (*p != NULL) { + parent = *p; + pos = rb_entry(parent, struct kernel_info, rb_node); + if (pid < pos->pid) + p = &(*p)->rb_left; + else + p = &(*p)->rb_right; + } + + rb_link_node(&kerninfo->rb_node, parent, p); + rb_insert_color(&kerninfo->rb_node, kerninfo_root); + + return kerninfo; +} + +struct kernel_info *kerninfo__find(struct rb_root *kerninfo_root, pid_t pid) +{ + struct rb_node **p = &kerninfo_root->rb_node; + struct rb_node *parent = NULL; + struct kernel_info *kerninfo; + struct kernel_info *default_kerninfo = NULL; + + while (*p != NULL) { + parent = *p; + kerninfo = rb_entry(parent, struct kernel_info, rb_node); + if (pid < kerninfo->pid) + p = &(*p)->rb_left; + else if (pid > kerninfo->pid) + p = &(*p)->rb_right; + else + return kerninfo; + if (!kerninfo->pid) + default_kerninfo = kerninfo; + } + + return default_kerninfo; +} + +struct kernel_info *kerninfo__findhost(struct rb_root *kerninfo_root) +{ + struct rb_node **p = &kerninfo_root->rb_node; + struct rb_node *parent = NULL; + struct kernel_info *kerninfo; + pid_t pid = HOST_KERNEL_ID; + + while (*p != NULL) { + parent = *p; + kerninfo = rb_entry(parent, struct kernel_info, rb_node); + if (pid < kerninfo->pid) + p = &(*p)->rb_left; + else if (pid > kerninfo->pid) + p = &(*p)->rb_right; + else + return kerninfo; + } + + return NULL; +} + +struct kernel_info *kerninfo__findnew(struct rb_root *kerninfo_root, pid_t pid) +{ + char path[PATH_MAX]; + const char *root_dir; + int ret; + struct kernel_info *kerninfo = kerninfo__find(kerninfo_root, pid); + + if (!kerninfo || kerninfo->pid != pid) { + if (pid == HOST_KERNEL_ID || pid == DEFAULT_GUEST_KERNEL_ID) + root_dir = ""; + else { + if (!symbol_conf.guestmount) + goto out; + sprintf(path, "%s/%d", symbol_conf.guestmount, pid); + ret = access(path, R_OK); + if (ret) { + pr_err("Can't access file %s\n", path); + goto out; + } + root_dir = path; + } + kerninfo = add_new_kernel_info(kerninfo_root, pid, root_dir); + } + +out: + return kerninfo; +} + +void kerninfo__process_allkernels(struct rb_root *kerninfo_root, + process_kernel_info process, + void *data) +{ + struct rb_node *nd; + + for (nd = rb_first(kerninfo_root); nd; nd = rb_next(nd)) { + struct kernel_info *pos = rb_entry(nd, struct kernel_info, + rb_node); + process(pos, data); + } +} + +char *kern_mmap_name(struct kernel_info *kerninfo, char *buff) +{ + if (is_host_kernel(kerninfo)) + sprintf(buff, "[%s]", "kernel.kallsyms"); + else if (is_default_guest(kerninfo)) + sprintf(buff, "[%s]", "guest.kernel.kallsyms"); + else + sprintf(buff, "[%s.%d]", "guest.kernel.kallsyms", kerninfo->pid); + + return buff; +} diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index 2031278..30d38d6 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h @@ -19,6 +19,7 @@ extern const char *map_type__name[MAP__NR_TYPES]; struct dso; struct ref_reloc_sym; struct map_groups; +struct kernel_info; struct map { union { @@ -36,6 +37,7 @@ struct map { u64 (*unmap_ip)(struct map *, u64); struct dso *dso; + struct map_groups *groups; }; struct kmap { @@ -43,6 +45,26 @@ struct kmap { struct map_groups *kmaps; }; +struct map_groups { + struct rb_root maps[MAP__NR_TYPES]; + struct list_head removed_maps[MAP__NR_TYPES]; + struct kernel_info *this_kerninfo; +}; + +/* Native host kernel uses -1 as pid index in kernel_info */ +#define HOST_KERNEL_ID (-1) +#define DEFAULT_GUEST_KERNEL_ID (0) + +struct kernel_info { + struct rb_node rb_node; + pid_t pid; + char *root_dir; + struct list_head dsos__user; + struct list_head dsos__kernel; + struct map_groups kmaps; + struct map *vmlinux_maps[MAP__NR_TYPES]; +}; + static inline struct kmap *map__kmap(struct map *self) { return (struct kmap *)(self + 1); @@ -74,7 +96,8 @@ typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym); void map__init(struct map *self, enum map_type type, u64 start, u64 end, u64 pgoff, struct dso *dso); -struct map *map__new(u64 start, u64 len, u64 pgoff, u32 pid, char *filename, +struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, + u64 pgoff, u32 pid, char *filename, enum map_type type, char *cwd, int cwdlen); void map__delete(struct map *self); struct map *map__clone(struct map *self); @@ -91,11 +114,6 @@ void map__fixup_end(struct map *self); void map__reloc_vmlinux(struct map *self); -struct map_groups { - struct rb_root maps[MAP__NR_TYPES]; - struct list_head removed_maps[MAP__NR_TYPES]; -}; - size_t __map_groups__fprintf_maps(struct map_groups *self, enum map_type type, int verbose, FILE *fp); void maps__insert(struct rb_root *maps, struct map *map); @@ -106,9 +124,40 @@ int map_groups__clone(struct map_groups *self, size_t map_groups__fprintf(struct map_groups *self, int verbose, FILE *fp); size_t map_groups__fprintf_maps(struct map_groups *self, int verbose, FILE *fp); +struct kernel_info *add_new_kernel_info(struct rb_root *kerninfo_root, + pid_t pid, const char *root_dir); +struct kernel_info *kerninfo__find(struct rb_root *kerninfo_root, pid_t pid); +struct kernel_info *kerninfo__findnew(struct rb_root *kerninfo_root, pid_t pid); +struct kernel_info *kerninfo__findhost(struct rb_root *kerninfo_root); +char *kern_mmap_name(struct kernel_info *kerninfo, char *buff); + +/* + * Default guest kernel is defined by parameter --guestkallsyms + * and --guestmodules + */ +static inline int is_default_guest(struct kernel_info *kerninfo) +{ + if (!kerninfo) + return 0; + return kerninfo->pid == DEFAULT_GUEST_KERNEL_ID; +} + +static inline int is_host_kernel(struct kernel_info *kerninfo) +{ + if (!kerninfo) + return 0; + return kerninfo->pid == HOST_KERNEL_ID; +} + +typedef void (*process_kernel_info)(struct kernel_info *kerninfo, void *data); +void kerninfo__process_allkernels(struct rb_root *kerninfo_root, + process_kernel_info process, + void *data); + static inline void map_groups__insert(struct map_groups *self, struct map *map) { - maps__insert(&self->maps[map->type], map); + maps__insert(&self->maps[map->type], map); + map->groups = self; } static inline struct map *map_groups__find(struct map_groups *self, @@ -148,13 +197,11 @@ int map_groups__fixup_overlappings(struct map_groups *self, struct map *map, struct map *map_groups__find_by_name(struct map_groups *self, enum map_type type, const char *name); -int __map_groups__create_kernel_maps(struct map_groups *self, - struct map *vmlinux_maps[MAP__NR_TYPES], - struct dso *kernel); -int map_groups__create_kernel_maps(struct map_groups *self, - struct map *vmlinux_maps[MAP__NR_TYPES]); -struct map *map_groups__new_module(struct map_groups *self, u64 start, - const char *filename); +struct map *map_groups__new_module(struct map_groups *self, + u64 start, + const char *filename, + struct kernel_info *kerninfo); + void map_groups__flush(struct map_groups *self); #endif /* __PERF_MAP_H */ diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 5bf8ab0..3967f8f 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -78,6 +78,7 @@ static struct map *kmaps[MAP__NR_TYPES]; /* Initialize symbol maps and path of vmlinux */ static int init_vmlinux(void) { + struct dso *kernel; int ret; symbol_conf.sort_by_name = true; @@ -91,8 +92,12 @@ static int init_vmlinux(void) goto out; } + kernel = dso__new_kernel(symbol_conf.vmlinux_name); + if (kernel == NULL) + die("Failed to create kernel dso."); + map_groups__init(&kmap_groups); - ret = map_groups__create_kernel_maps(&kmap_groups, kmaps); + ret = __map_groups__create_kernel_maps(&kmap_groups, kmaps, kernel); if (ret < 0) pr_debug("Failed to create kernel maps.\n"); diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 0fdf3eb..7d88ae5 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -67,6 +67,17 @@ void perf_session__update_sample_type(struct perf_session *self) self->sample_type = perf_header__sample_type(&self->header); } +int perf_session__create_kernel_maps(struct perf_session *self) +{ + int ret; + struct rb_root *root = &self->kerninfo_root; + + ret = map_groups__create_kernel_maps(root, HOST_KERNEL_ID); + if (ret >= 0) + ret = map_groups__create_guest_kernel_maps(root); + return ret; +} + struct perf_session *perf_session__new(const char *filename, int mode, bool force) { size_t len = filename ? strlen(filename) + 1 : 0; @@ -86,7 +97,7 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc self->cwd = NULL; self->cwdlen = 0; self->unknown_events = 0; - map_groups__init(&self->kmaps); + self->kerninfo_root = RB_ROOT; if (mode == O_RDONLY) { if (perf_session__open(self, force) < 0) @@ -157,8 +168,9 @@ struct map_symbol *perf_session__resolve_callchain(struct perf_session *self, continue; } + al.filtered = false; thread__find_addr_location(thread, self, cpumode, - MAP__FUNCTION, ip, &al, NULL); + MAP__FUNCTION, thread->pid, ip, &al, NULL); if (al.sym != NULL) { if (sort__has_parent && !*parent && symbol__match_parent_regex(al.sym)) @@ -399,46 +411,6 @@ void perf_event_header__bswap(struct perf_event_header *self) self->size = bswap_16(self->size); } -int perf_header__read_build_ids(struct perf_header *self, - int input, u64 offset, u64 size) -{ - struct build_id_event bev; - char filename[PATH_MAX]; - u64 limit = offset + size; - int err = -1; - - while (offset < limit) { - struct dso *dso; - ssize_t len; - struct list_head *head = &dsos__user; - - if (read(input, &bev, sizeof(bev)) != sizeof(bev)) - goto out; - - if (self->needs_swap) - perf_event_header__bswap(&bev.header); - - len = bev.header.size - sizeof(bev); - if (read(input, filename, len) != len) - goto out; - - if (bev.header.misc & PERF_RECORD_MISC_KERNEL) - head = &dsos__kernel; - - dso = __dsos__findnew(head, filename); - if (dso != NULL) { - dso__set_build_id(dso, &bev.build_id); - if (head == &dsos__kernel && filename[0] == '[') - dso->kernel = 1; - } - - offset += bev.header.size; - } - err = 0; -out: - return err; -} - static struct thread *perf_session__register_idle_thread(struct perf_session *self) { struct thread *thread = perf_session__findnew(self, 0); @@ -690,26 +662,33 @@ bool perf_session__has_traces(struct perf_session *self, const char *msg) return true; } -int perf_session__set_kallsyms_ref_reloc_sym(struct perf_session *self, +int perf_session__set_kallsyms_ref_reloc_sym(struct map **maps, const char *symbol_name, u64 addr) { char *bracket; enum map_type i; + struct ref_reloc_sym *ref; + + ref = zalloc(sizeof(struct ref_reloc_sym)); + if (ref == NULL) + return -ENOMEM; - self->ref_reloc_sym.name = strdup(symbol_name); - if (self->ref_reloc_sym.name == NULL) + ref->name = strdup(symbol_name); + if (ref->name == NULL) { + free(ref); return -ENOMEM; + } - bracket = strchr(self->ref_reloc_sym.name, ']'); + bracket = strchr(ref->name, ']'); if (bracket) *bracket = '\0'; - self->ref_reloc_sym.addr = addr; + ref->addr = addr; for (i = 0; i < MAP__NR_TYPES; ++i) { - struct kmap *kmap = map__kmap(self->vmlinux_maps[i]); - kmap->ref_reloc_sym = &self->ref_reloc_sym; + struct kmap *kmap = map__kmap(maps[i]); + kmap->ref_reloc_sym = ref; } return 0; diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 0ac14d4..5e47c87 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -15,17 +15,15 @@ struct perf_session { struct perf_header header; unsigned long size; unsigned long mmap_window; - struct map_groups kmaps; struct rb_root threads; struct thread *last_match; - struct map *vmlinux_maps[MAP__NR_TYPES]; + struct rb_root kerninfo_root; struct events_stats events_stats; struct rb_root stats_by_id; unsigned long event_total[PERF_RECORD_MAX]; unsigned long unknown_events; struct rb_root hists; u64 sample_type; - struct ref_reloc_sym ref_reloc_sym; int fd; bool fd_pipe; int cwdlen; @@ -69,33 +67,13 @@ struct map_symbol *perf_session__resolve_callchain(struct perf_session *self, bool perf_session__has_traces(struct perf_session *self, const char *msg); -int perf_header__read_build_ids(struct perf_header *self, int input, - u64 offset, u64 file_size); - -int perf_session__set_kallsyms_ref_reloc_sym(struct perf_session *self, +int perf_session__set_kallsyms_ref_reloc_sym(struct map **maps, const char *symbol_name, u64 addr); void mem_bswap_64(void *src, int byte_size); -static inline int __perf_session__create_kernel_maps(struct perf_session *self, - struct dso *kernel) -{ - return __map_groups__create_kernel_maps(&self->kmaps, - self->vmlinux_maps, kernel); -} - -static inline int perf_session__create_kernel_maps(struct perf_session *self) -{ - return map_groups__create_kernel_maps(&self->kmaps, self->vmlinux_maps); -} - -static inline struct map * - perf_session__new_module_map(struct perf_session *self, - u64 start, const char *filename) -{ - return map_groups__new_module(&self->kmaps, start, filename); -} +int perf_session__create_kernel_maps(struct perf_session *self); int do_read(int fd, void *buf, size_t size); void perf_session__update_sample_type(struct perf_session *self); diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index 1d857aa..b7c54ee 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h @@ -44,6 +44,11 @@ extern enum sort_type sort__first_dimension; struct hist_entry { struct rb_node rb_node; u64 count; + u64 count_sys; + u64 count_us; + u64 count_guest_sys; + u64 count_guest_us; + /* * XXX WARNING! * thread _has_ to come after ms, see diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index f3d4151..e782e7d 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -28,6 +28,8 @@ static void dsos__add(struct list_head *head, struct dso *dso); static struct map *map__new2(u64 start, struct dso *dso, enum map_type type); static int dso__load_kernel_sym(struct dso *self, struct map *map, symbol_filter_t filter); +static int dso__load_guest_kernel_sym(struct dso *self, struct map *map, + symbol_filter_t filter); static int vmlinux_path__nr_entries; static char **vmlinux_path; @@ -186,6 +188,7 @@ struct dso *dso__new(const char *name) self->loaded = 0; self->sorted_by_name = 0; self->has_build_id = 0; + self->kernel = DSO_TYPE_USER; } return self; @@ -402,12 +405,9 @@ int kallsyms__parse(const char *filename, void *arg, char *symbol_name; line_len = getline(&line, &n, file); - if (line_len < 0) + if (line_len < 0 || !line) break; - if (!line) - goto out_failure; - line[--line_len] = '\0'; /* \n */ len = hex2u64(line, &start); @@ -459,6 +459,7 @@ static int map__process_kallsym_symbol(void *arg, const char *name, * map__split_kallsyms, when we have split the maps per module */ symbols__insert(root, sym); + return 0; } @@ -483,6 +484,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map, symbol_filter_t filter) { struct map_groups *kmaps = map__kmap(map)->kmaps; + struct kernel_info *kerninfo = kmaps->this_kerninfo; struct map *curr_map = map; struct symbol *pos; int count = 0; @@ -504,15 +506,33 @@ static int dso__split_kallsyms(struct dso *self, struct map *map, *module++ = '\0'; if (strcmp(curr_map->dso->short_name, module)) { - curr_map = map_groups__find_by_name(kmaps, map->type, module); + if (curr_map != map && + self->kernel == DSO_TYPE_GUEST_KERNEL && + is_default_guest(kerninfo)) { + /* + * We assume all symbols of a module are + * continuous in * kallsyms, so curr_map + * points to a module and all its + * symbols are in its kmap. Mark it as + * loaded. + */ + dso__set_loaded(curr_map->dso, + curr_map->type); + } + + curr_map = map_groups__find_by_name(kmaps, + map->type, module); if (curr_map == NULL) { - pr_debug("/proc/{kallsyms,modules} " + pr_err("%s/proc/{kallsyms,modules} " "inconsistency while looking " - "for \"%s\" module!\n", module); - return -1; + "for \"%s\" module!\n", + kerninfo->root_dir, module); + curr_map = map; + goto discard_symbol; } - if (curr_map->dso->loaded) + if (curr_map->dso->loaded && + !is_default_guest(kmaps->this_kerninfo)) goto discard_symbol; } /* @@ -525,13 +545,21 @@ static int dso__split_kallsyms(struct dso *self, struct map *map, char dso_name[PATH_MAX]; struct dso *dso; - snprintf(dso_name, sizeof(dso_name), "[kernel].%d", - kernel_range++); + if (self->kernel == DSO_TYPE_GUEST_KERNEL) + snprintf(dso_name, sizeof(dso_name), + "[guest.kernel].%d", + kernel_range++); + else + snprintf(dso_name, sizeof(dso_name), + "[kernel].%d", + kernel_range++); dso = dso__new(dso_name); if (dso == NULL) return -1; + dso->kernel = self->kernel; + curr_map = map__new2(pos->start, dso, map->type); if (curr_map == NULL) { dso__delete(dso); @@ -555,6 +583,12 @@ discard_symbol: rb_erase(&pos->rb_node, root); } } + if (curr_map != map && + self->kernel == DSO_TYPE_GUEST_KERNEL && + is_default_guest(kmaps->this_kerninfo)) { + dso__set_loaded(curr_map->dso, curr_map->type); + } + return count; } @@ -565,7 +599,10 @@ int dso__load_kallsyms(struct dso *self, const char *filename, return -1; symbols__fixup_end(&self->symbols[map->type]); - self->origin = DSO__ORIG_KERNEL; + if (self->kernel == DSO_TYPE_GUEST_KERNEL) + self->origin = DSO__ORIG_GUEST_KERNEL; + else + self->origin = DSO__ORIG_KERNEL; return dso__split_kallsyms(self, map, filter); } @@ -952,7 +989,7 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name, nr_syms = shdr.sh_size / shdr.sh_entsize; memset(&sym, 0, sizeof(sym)); - if (!self->kernel) { + if (self->kernel == DSO_TYPE_USER) { self->adjust_symbols = (ehdr.e_type == ET_EXEC || elf_section_by_name(elf, &ehdr, &shdr, ".gnu.prelink_undo", @@ -984,7 +1021,7 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name, section_name = elf_sec__name(&shdr, secstrs); - if (self->kernel || kmodule) { + if (self->kernel != DSO_TYPE_USER || kmodule) { char dso_name[PATH_MAX]; if (strcmp(section_name, @@ -1011,6 +1048,7 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name, curr_dso = dso__new(dso_name); if (curr_dso == NULL) goto out_elf_end; + curr_dso->kernel = self->kernel; curr_map = map__new2(start, curr_dso, map->type); if (curr_map == NULL) { @@ -1021,7 +1059,7 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name, curr_map->unmap_ip = identity__map_ip; curr_dso->origin = self->origin; map_groups__insert(kmap->kmaps, curr_map); - dsos__add(&dsos__kernel, curr_dso); + dsos__add(&self->node, curr_dso); dso__set_loaded(curr_dso, map->type); } else curr_dso = curr_map->dso; @@ -1083,7 +1121,7 @@ static bool dso__build_id_equal(const struct dso *self, u8 *build_id) return memcmp(self->build_id, build_id, sizeof(self->build_id)) == 0; } -static bool __dsos__read_build_ids(struct list_head *head, bool with_hits) +bool __dsos__read_build_ids(struct list_head *head, bool with_hits) { bool have_build_id = false; struct dso *pos; @@ -1101,13 +1139,6 @@ static bool __dsos__read_build_ids(struct list_head *head, bool with_hits) return have_build_id; } -bool dsos__read_build_ids(bool with_hits) -{ - bool kbuildids = __dsos__read_build_ids(&dsos__kernel, with_hits), - ubuildids = __dsos__read_build_ids(&dsos__user, with_hits); - return kbuildids || ubuildids; -} - /* * Align offset to 4 bytes as needed for note name and descriptor data. */ @@ -1242,6 +1273,8 @@ char dso__symtab_origin(const struct dso *self) [DSO__ORIG_BUILDID] = 'b', [DSO__ORIG_DSO] = 'd', [DSO__ORIG_KMODULE] = 'K', + [DSO__ORIG_GUEST_KERNEL] = 'g', + [DSO__ORIG_GUEST_KMODULE] = 'G', }; if (self == NULL || self->origin == DSO__ORIG_NOT_FOUND) @@ -1257,11 +1290,20 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) char build_id_hex[BUILD_ID_SIZE * 2 + 1]; int ret = -1; int fd; + struct kernel_info *kerninfo; + const char *root_dir; dso__set_loaded(self, map->type); - if (self->kernel) + if (self->kernel == DSO_TYPE_KERNEL) return dso__load_kernel_sym(self, map, filter); + else if (self->kernel == DSO_TYPE_GUEST_KERNEL) + return dso__load_guest_kernel_sym(self, map, filter); + + if (map->groups && map->groups->this_kerninfo) + kerninfo = map->groups->this_kerninfo; + else + kerninfo = NULL; name = malloc(size); if (!name) @@ -1315,6 +1357,13 @@ more: case DSO__ORIG_DSO: snprintf(name, size, "%s", self->long_name); break; + case DSO__ORIG_GUEST_KMODULE: + if (map->groups && map->groups->this_kerninfo) + root_dir = map->groups->this_kerninfo->root_dir; + else + root_dir = ""; + snprintf(name, size, "%s%s", root_dir, self->long_name); + break; default: goto out; @@ -1368,7 +1417,8 @@ struct map *map_groups__find_by_name(struct map_groups *self, return NULL; } -static int dso__kernel_module_get_build_id(struct dso *self) +static int dso__kernel_module_get_build_id(struct dso *self, + const char *root_dir) { char filename[PATH_MAX]; /* @@ -1378,8 +1428,8 @@ static int dso__kernel_module_get_build_id(struct dso *self) const char *name = self->short_name + 1; snprintf(filename, sizeof(filename), - "/sys/module/%.*s/notes/.note.gnu.build-id", - (int)strlen(name - 1), name); + "%s/sys/module/%.*s/notes/.note.gnu.build-id", + root_dir, (int)strlen(name) - 1, name); if (sysfs__read_build_id(filename, self->build_id, sizeof(self->build_id)) == 0) @@ -1388,7 +1438,8 @@ static int dso__kernel_module_get_build_id(struct dso *self) return 0; } -static int map_groups__set_modules_path_dir(struct map_groups *self, char *dir_name) +static int map_groups__set_modules_path_dir(struct map_groups *self, + const char *dir_name) { struct dirent *dent; DIR *dir = opendir(dir_name); @@ -1400,8 +1451,14 @@ static int map_groups__set_modules_path_dir(struct map_groups *self, char *dir_n while ((dent = readdir(dir)) != NULL) { char path[PATH_MAX]; + struct stat st; + + /*sshfs might return bad dent->d_type, so we have to stat*/ + sprintf(path, "%s/%s", dir_name, dent->d_name); + if (stat(path, &st)) + continue; - if (dent->d_type == DT_DIR) { + if (S_ISDIR(st.st_mode)) { if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) continue; @@ -1433,7 +1490,7 @@ static int map_groups__set_modules_path_dir(struct map_groups *self, char *dir_n if (long_name == NULL) goto failure; dso__set_long_name(map->dso, long_name); - dso__kernel_module_get_build_id(map->dso); + dso__kernel_module_get_build_id(map->dso, ""); } } @@ -1443,16 +1500,46 @@ failure: return -1; } -static int map_groups__set_modules_path(struct map_groups *self) +static char *get_kernel_version(const char *root_dir) { - struct utsname uts; + char version[PATH_MAX]; + FILE *file; + char *name, *tmp; + const char *prefix = "Linux version "; + + sprintf(version, "%s/proc/version", root_dir); + file = fopen(version, "r"); + if (!file) + return NULL; + + version[0] = '\0'; + tmp = fgets(version, sizeof(version), file); + fclose(file); + + name = strstr(version, prefix); + if (!name) + return NULL; + name += strlen(prefix); + tmp = strchr(name, ' '); + if (tmp) + *tmp = '\0'; + + return strdup(name); +} + +static int map_groups__set_modules_path(struct map_groups *self, + const char *root_dir) +{ + char *version; char modules_path[PATH_MAX]; - if (uname(&uts) < 0) + version = get_kernel_version(root_dir); + if (!version) return -1; - snprintf(modules_path, sizeof(modules_path), "/lib/modules/%s/kernel", - uts.release); + snprintf(modules_path, sizeof(modules_path), "%s/lib/modules/%s/kernel", + root_dir, version); + free(version); return map_groups__set_modules_path_dir(self, modules_path); } @@ -1477,11 +1564,13 @@ static struct map *map__new2(u64 start, struct dso *dso, enum map_type type) } struct map *map_groups__new_module(struct map_groups *self, u64 start, - const char *filename) + const char *filename, + struct kernel_info *kerninfo) { struct map *map; - struct dso *dso = __dsos__findnew(&dsos__kernel, filename); + struct dso *dso; + dso = __dsos__findnew(&kerninfo->dsos__kernel, filename); if (dso == NULL) return NULL; @@ -1489,21 +1578,37 @@ struct map *map_groups__new_module(struct map_groups *self, u64 start, if (map == NULL) return NULL; - dso->origin = DSO__ORIG_KMODULE; + if (is_host_kernel(kerninfo)) + dso->origin = DSO__ORIG_KMODULE; + else + dso->origin = DSO__ORIG_GUEST_KMODULE; map_groups__insert(self, map); return map; } -static int map_groups__create_modules(struct map_groups *self) +static int map_groups__create_modules(struct kernel_info *kerninfo) { char *line = NULL; size_t n; - FILE *file = fopen("/proc/modules", "r"); + FILE *file; struct map *map; + const char *root_dir; + const char *modules; + char path[PATH_MAX]; + + if (is_default_guest(kerninfo)) + modules = symbol_conf.default_guest_modules; + else { + sprintf(path, "%s/proc/modules", kerninfo->root_dir); + modules = path; + } + file = fopen(modules, "r"); if (file == NULL) return -1; + root_dir = kerninfo->root_dir; + while (!feof(file)) { char name[PATH_MAX]; u64 start; @@ -1532,16 +1637,17 @@ static int map_groups__create_modules(struct map_groups *self) *sep = '\0'; snprintf(name, sizeof(name), "[%s]", line); - map = map_groups__new_module(self, start, name); + map = map_groups__new_module(&kerninfo->kmaps, + start, name, kerninfo); if (map == NULL) goto out_delete_line; - dso__kernel_module_get_build_id(map->dso); + dso__kernel_module_get_build_id(map->dso, root_dir); } free(line); fclose(file); - return map_groups__set_modules_path(self); + return map_groups__set_modules_path(&kerninfo->kmaps, root_dir); out_delete_line: free(line); @@ -1708,8 +1814,57 @@ out_fixup: return err; } -LIST_HEAD(dsos__user); -LIST_HEAD(dsos__kernel); +static int dso__load_guest_kernel_sym(struct dso *self, struct map *map, + symbol_filter_t filter) +{ + int err; + const char *kallsyms_filename = NULL; + struct kernel_info *kerninfo; + char path[PATH_MAX]; + + if (!map->groups) { + pr_debug("Guest kernel map hasn't the point to groups\n"); + return -1; + } + kerninfo = map->groups->this_kerninfo; + + if (is_default_guest(kerninfo)) { + /* + * if the user specified a vmlinux filename, use it and only + * it, reporting errors to the user if it cannot be used. + * Or use file guest_kallsyms inputted by user on commandline + */ + if (symbol_conf.default_guest_vmlinux_name != NULL) { + err = dso__load_vmlinux(self, map, + symbol_conf.default_guest_vmlinux_name, filter); + goto out_try_fixup; + } + + kallsyms_filename = symbol_conf.default_guest_kallsyms; + if (!kallsyms_filename) + return -1; + } else { + sprintf(path, "%s/proc/kallsyms", kerninfo->root_dir); + kallsyms_filename = path; + } + + err = dso__load_kallsyms(self, kallsyms_filename, map, filter); + if (err > 0) + pr_debug("Using %s for symbols\n", kallsyms_filename); + +out_try_fixup: + if (err > 0) { + if (kallsyms_filename != NULL) { + kern_mmap_name(kerninfo, path); + dso__set_long_name(self, + strdup(path)); + } + map__fixup_start(map); + map__fixup_end(map); + } + + return err; +} static void dsos__add(struct list_head *head, struct dso *dso) { @@ -1752,10 +1907,16 @@ static void __dsos__fprintf(struct list_head *head, FILE *fp) } } -void dsos__fprintf(FILE *fp) +void dsos__fprintf(struct rb_root *kerninfo_root, FILE *fp) { - __dsos__fprintf(&dsos__kernel, fp); - __dsos__fprintf(&dsos__user, fp); + struct rb_node *nd; + + for (nd = rb_first(kerninfo_root); nd; nd = rb_next(nd)) { + struct kernel_info *pos = rb_entry(nd, struct kernel_info, + rb_node); + __dsos__fprintf(&pos->dsos__kernel, fp); + __dsos__fprintf(&pos->dsos__user, fp); + } } static size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, @@ -1773,10 +1934,21 @@ static size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, return ret; } -size_t dsos__fprintf_buildid(FILE *fp, bool with_hits) +size_t dsos__fprintf_buildid(struct rb_root *kerninfo_root, + FILE *fp, bool with_hits) { - return (__dsos__fprintf_buildid(&dsos__kernel, fp, with_hits) + - __dsos__fprintf_buildid(&dsos__user, fp, with_hits)); + struct rb_node *nd; + size_t ret = 0; + + for (nd = rb_first(kerninfo_root); nd; nd = rb_next(nd)) { + struct kernel_info *pos = rb_entry(nd, struct kernel_info, + rb_node); + ret += __dsos__fprintf_buildid(&pos->dsos__kernel, + fp, with_hits); + ret += __dsos__fprintf_buildid(&pos->dsos__user, + fp, with_hits); + } + return ret; } struct dso *dso__new_kernel(const char *name) @@ -1785,28 +1957,59 @@ struct dso *dso__new_kernel(const char *name) if (self != NULL) { dso__set_short_name(self, "[kernel]"); - self->kernel = 1; + self->kernel = DSO_TYPE_KERNEL; + } + + return self; +} + +static struct dso *dso__new_guest_kernel(struct kernel_info *kerninfo, + const char *name) +{ + char buff[PATH_MAX]; + struct dso *self; + + kern_mmap_name(kerninfo, buff); + self = dso__new(name ?: buff); + if (self != NULL) { + dso__set_short_name(self, "[guest.kernel]"); + self->kernel = DSO_TYPE_GUEST_KERNEL; } return self; } -void dso__read_running_kernel_build_id(struct dso *self) +void dso__read_running_kernel_build_id(struct dso *self, + struct kernel_info *kerninfo) { - if (sysfs__read_build_id("/sys/kernel/notes", self->build_id, + char path[PATH_MAX]; + + if (is_default_guest(kerninfo)) + return; + sprintf(path, "%s/sys/kernel/notes", kerninfo->root_dir); + if (sysfs__read_build_id(path, self->build_id, sizeof(self->build_id)) == 0) self->has_build_id = true; } -static struct dso *dsos__create_kernel(const char *vmlinux) +static struct dso *dsos__create_kernel(struct kernel_info *kerninfo) { - struct dso *kernel = dso__new_kernel(vmlinux); + const char *vmlinux_name = NULL; + struct dso *kernel; - if (kernel != NULL) { - dso__read_running_kernel_build_id(kernel); - dsos__add(&dsos__kernel, kernel); + if (is_host_kernel(kerninfo)) { + vmlinux_name = symbol_conf.vmlinux_name; + kernel = dso__new_kernel(vmlinux_name); + } else { + if (is_default_guest(kerninfo)) + vmlinux_name = symbol_conf.default_guest_vmlinux_name; + kernel = dso__new_guest_kernel(kerninfo, vmlinux_name); } + if (kernel != NULL) { + dso__read_running_kernel_build_id(kernel, kerninfo); + dsos__add(&kerninfo->dsos__kernel, kernel); + } return kernel; } @@ -1950,23 +2153,29 @@ out_free_comm_list: return -1; } -int map_groups__create_kernel_maps(struct map_groups *self, - struct map *vmlinux_maps[MAP__NR_TYPES]) +int map_groups__create_kernel_maps(struct rb_root *kerninfo_root, pid_t pid) { - struct dso *kernel = dsos__create_kernel(symbol_conf.vmlinux_name); + struct kernel_info *kerninfo; + struct dso *kernel; + kerninfo = kerninfo__findnew(kerninfo_root, pid); + if (kerninfo == NULL) + return -1; + kernel = dsos__create_kernel(kerninfo); if (kernel == NULL) return -1; - if (__map_groups__create_kernel_maps(self, vmlinux_maps, kernel) < 0) + if (__map_groups__create_kernel_maps(&kerninfo->kmaps, + kerninfo->vmlinux_maps, kernel) < 0) return -1; - if (symbol_conf.use_modules && map_groups__create_modules(self) < 0) + if (symbol_conf.use_modules && + map_groups__create_modules(kerninfo) < 0) pr_debug("Problems creating module maps, continuing anyway...\n"); /* * Now that we have all the maps created, just set the ->end of them: */ - map_groups__fixup_end(self); + map_groups__fixup_end(&kerninfo->kmaps); return 0; } @@ -2012,3 +2221,46 @@ char *strxfrchar(char *s, char from, char to) return s; } + +int map_groups__create_guest_kernel_maps(struct rb_root *kerninfo_root) +{ + int ret = 0; + struct dirent **namelist = NULL; + int i, items = 0; + char path[PATH_MAX]; + pid_t pid; + + if (symbol_conf.default_guest_vmlinux_name || + symbol_conf.default_guest_modules || + symbol_conf.default_guest_kallsyms) { + map_groups__create_kernel_maps(kerninfo_root, + DEFAULT_GUEST_KERNEL_ID); + } + + if (symbol_conf.guestmount) { + items = scandir(symbol_conf.guestmount, &namelist, NULL, NULL); + if (items <= 0) + return -ENOENT; + for (i = 0; i < items; i++) { + if (!isdigit(namelist[i]->d_name[0])) { + /* Filter out . and .. */ + continue; + } + pid = atoi(namelist[i]->d_name); + sprintf(path, "%s/%s/proc/kallsyms", + symbol_conf.guestmount, + namelist[i]->d_name); + ret = access(path, R_OK); + if (ret) { + pr_debug("Can't access file %s\n", path); + goto failure; + } + map_groups__create_kernel_maps(kerninfo_root, + pid); + } +failure: + free(namelist); + } + + return ret; +} diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 757fae3..478f5ab 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -69,10 +69,15 @@ struct symbol_conf { show_nr_samples, use_callchain, exclude_other, - full_paths; + full_paths, + show_cpu_utilization; const char *vmlinux_name, *field_sep; - char *dso_list_str, + const char *default_guest_vmlinux_name, + *default_guest_kallsyms, + *default_guest_modules; + const char *guestmount; + char *dso_list_str, *comm_list_str, *sym_list_str, *col_width_list_str; @@ -106,6 +111,13 @@ struct addr_location { u64 addr; char level; bool filtered; + unsigned int cpumode; +}; + +enum dso_kernel_type { + DSO_TYPE_USER = 0, + DSO_TYPE_KERNEL, + DSO_TYPE_GUEST_KERNEL }; struct dso { @@ -115,7 +127,7 @@ struct dso { u8 adjust_symbols:1; u8 slen_calculated:1; u8 has_build_id:1; - u8 kernel:1; + enum dso_kernel_type kernel; u8 hit:1; u8 annotate_warned:1; unsigned char origin; @@ -143,34 +155,30 @@ static inline void dso__set_loaded(struct dso *self, enum map_type type) void dso__sort_by_name(struct dso *self, enum map_type type); -extern struct list_head dsos__user, dsos__kernel; - struct dso *__dsos__findnew(struct list_head *head, const char *name); -static inline struct dso *dsos__findnew(const char *name) -{ - return __dsos__findnew(&dsos__user, name); -} - int dso__load(struct dso *self, struct map *map, symbol_filter_t filter); int dso__load_vmlinux_path(struct dso *self, struct map *map, symbol_filter_t filter); int dso__load_kallsyms(struct dso *self, const char *filename, struct map *map, symbol_filter_t filter); -void dsos__fprintf(FILE *fp); -size_t dsos__fprintf_buildid(FILE *fp, bool with_hits); +void dsos__fprintf(struct rb_root *kerninfo_root, FILE *fp); +size_t dsos__fprintf_buildid(struct rb_root *kerninfo_root, + FILE *fp, bool with_hits); size_t dso__fprintf_buildid(struct dso *self, FILE *fp); size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp); enum dso_origin { DSO__ORIG_KERNEL = 0, + DSO__ORIG_GUEST_KERNEL, DSO__ORIG_JAVA_JIT, DSO__ORIG_BUILD_ID_CACHE, DSO__ORIG_FEDORA, DSO__ORIG_UBUNTU, DSO__ORIG_BUILDID, DSO__ORIG_DSO, + DSO__ORIG_GUEST_KMODULE, DSO__ORIG_KMODULE, DSO__ORIG_NOT_FOUND, }; @@ -178,19 +186,26 @@ enum dso_origin { char dso__symtab_origin(const struct dso *self); void dso__set_long_name(struct dso *self, char *name); void dso__set_build_id(struct dso *self, void *build_id); -void dso__read_running_kernel_build_id(struct dso *self); +void dso__read_running_kernel_build_id(struct dso *self, + struct kernel_info *kerninfo); struct symbol *dso__find_symbol(struct dso *self, enum map_type type, u64 addr); struct symbol *dso__find_symbol_by_name(struct dso *self, enum map_type type, const char *name); int filename__read_build_id(const char *filename, void *bf, size_t size); int sysfs__read_build_id(const char *filename, void *bf, size_t size); -bool dsos__read_build_ids(bool with_hits); +bool __dsos__read_build_ids(struct list_head *head, bool with_hits); int build_id__sprintf(const u8 *self, int len, char *bf); int kallsyms__parse(const char *filename, void *arg, int (*process_symbol)(void *arg, const char *name, char type, u64 start)); +int __map_groups__create_kernel_maps(struct map_groups *self, + struct map *vmlinux_maps[MAP__NR_TYPES], + struct dso *kernel); +int map_groups__create_kernel_maps(struct rb_root *kerninfo_root, pid_t pid); +int map_groups__create_guest_kernel_maps(struct rb_root *kerninfo_root); + int symbol__init(void); bool symbol_type__is_a(char symbol_type, enum map_type map_type); diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index 9c488fc..1dfd9ff 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h @@ -33,12 +33,12 @@ static inline struct map *thread__find_map(struct thread *self, void thread__find_addr_map(struct thread *self, struct perf_session *session, u8 cpumode, - enum map_type type, u64 addr, + enum map_type type, pid_t pid, u64 addr, struct addr_location *al); void thread__find_addr_location(struct thread *self, struct perf_session *session, u8 cpumode, - enum map_type type, u64 addr, + enum map_type type, pid_t pid, u64 addr, struct addr_location *al, symbol_filter_t filter); #endif /* __PERF_THREAD_H */ -- cgit v0.10.2 From 1d5cc550ede76825ab401941fb1165f2056e2c46 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 20 Apr 2010 14:34:15 +0900 Subject: sh: dwarf unwinder needs linux/module.h. Previously the struct module definition was pulled in from other headers, but we want the reference to be explicit. Fixes up randconfig build issues. Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/dwarf.c b/arch/sh/kernel/dwarf.c index 94739ee..8c09f62 100644 --- a/arch/sh/kernel/dwarf.c +++ b/arch/sh/kernel/dwarf.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include -- cgit v0.10.2 From dcf46b9443ad48a227a61713adea001228925adf Mon Sep 17 00:00:00 2001 From: "Zhang, Yanmin" Date: Tue, 20 Apr 2010 10:13:58 +0800 Subject: perf & kvm: Clean up some of the guest profiling callback API details Fix some build bug and programming style issues: - use valid C - fix up various style details Signed-off-by: Zhang Yanmin Cc: Avi Kivity Cc: Peter Zijlstra Cc: Sheng Yang Cc: Marcelo Tosatti Cc: oerg Roedel Cc: Jes Sorensen Cc: Gleb Natapov Cc: Zachary Amsden Cc: zhiteng.huang@intel.com Cc: tim.c.chen@intel.com Cc: Arnaldo Carvalho de Melo LKML-Reference: <1271729638.2078.624.camel@ymzhang.sh.intel.com> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 2ea78ab..7de7061 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -1752,23 +1752,31 @@ void perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip, int ski unsigned long perf_instruction_pointer(struct pt_regs *regs) { unsigned long ip; + if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) ip = perf_guest_cbs->get_guest_ip(); else ip = instruction_pointer(regs); + return ip; } unsigned long perf_misc_flags(struct pt_regs *regs) { int misc = 0; + if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { - misc |= perf_guest_cbs->is_user_mode() ? - PERF_RECORD_MISC_GUEST_USER : - PERF_RECORD_MISC_GUEST_KERNEL; - } else - misc |= user_mode(regs) ? PERF_RECORD_MISC_USER : - PERF_RECORD_MISC_KERNEL; + if (perf_guest_cbs->is_user_mode()) + misc |= PERF_RECORD_MISC_GUEST_USER; + else + misc |= PERF_RECORD_MISC_GUEST_KERNEL; + } else { + if (user_mode(regs)) + misc |= PERF_RECORD_MISC_USER; + else + misc |= PERF_RECORD_MISC_KERNEL; + } + if (regs->flags & PERF_EFLAGS_EXACT) misc |= PERF_RECORD_MISC_EXACT; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index c3a33b2..21b9b6a 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -3776,16 +3776,20 @@ static int kvm_is_in_guest(void) static int kvm_is_user_mode(void) { int user_mode = 3; + if (percpu_read(current_vcpu)) user_mode = kvm_x86_ops->get_cpl(percpu_read(current_vcpu)); + return user_mode != 0; } static unsigned long kvm_get_guest_ip(void) { unsigned long ip = 0; + if (percpu_read(current_vcpu)) ip = kvm_rip_read(percpu_read(current_vcpu)); + return ip; } diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 24de5f1..ace31fb 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -941,10 +941,8 @@ static inline void perf_event_mmap(struct vm_area_struct *vma) } extern struct perf_guest_info_callbacks *perf_guest_cbs; -extern int perf_register_guest_info_callbacks( - struct perf_guest_info_callbacks *); -extern int perf_unregister_guest_info_callbacks( - struct perf_guest_info_callbacks *); +extern int perf_register_guest_info_callbacks(struct perf_guest_info_callbacks *callbacks); +extern int perf_unregister_guest_info_callbacks(struct perf_guest_info_callbacks *callbacks); extern void perf_event_comm(struct task_struct *tsk); extern void perf_event_fork(struct task_struct *tsk); @@ -1016,9 +1014,9 @@ static inline void perf_bp_event(struct perf_event *event, void *data) { } static inline int perf_register_guest_info_callbacks -(struct perf_guest_info_callbacks *) {return 0; } +(struct perf_guest_info_callbacks *callbacks) { return 0; } static inline int perf_unregister_guest_info_callbacks -(struct perf_guest_info_callbacks *) {return 0; } +(struct perf_guest_info_callbacks *callbacks) { return 0; } static inline void perf_event_mmap(struct vm_area_struct *vma) { } static inline void perf_event_comm(struct task_struct *tsk) { } -- cgit v0.10.2 From 88253e845996670f56635b054550fa45e1fec3d8 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 20 Apr 2010 15:37:23 +0900 Subject: sh: Zero out aliases counter when using SH-X3 hardware assistance. This zeroes out the number of cache aliases in the cache info descriptors when hardware alias avoidance is enabled. This cuts down on the amount of flushing taken care of by common code, and also permits coherency control to be disabled for the single CPU and 4k page size case. Signed-off-by: Paul Mundt diff --git a/arch/sh/mm/cache-shx3.c b/arch/sh/mm/cache-shx3.c index 65936c4..c0adbee 100644 --- a/arch/sh/mm/cache-shx3.c +++ b/arch/sh/mm/cache-shx3.c @@ -21,9 +21,18 @@ void __init shx3_cache_init(void) ccr = __raw_readl(CCR); - if (boot_cpu_data.dcache.n_aliases) + /* + * If we've got cache aliases, resolve them in hardware. + */ + if (boot_cpu_data.dcache.n_aliases || boot_cpu_data.icache.n_aliases) { ccr |= CCR_CACHE_SNM; + boot_cpu_data.icache.n_aliases = 0; + boot_cpu_data.dcache.n_aliases = 0; + + pr_info("Enabling hardware synonym avoidance\n"); + } + #ifdef CONFIG_SMP /* * Broadcast I-cache block invalidations by default. -- cgit v0.10.2 From 3bd16668872b5ad0afb22f15ef6c800a8faf7532 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 21 Apr 2010 11:38:04 +0900 Subject: sh: hw-breakpoints: Kill off stub unthrottle callback. This follows the x86 change and kills off the unthrottle stub. As the x86 change killed off the generic callback it isn't used anymore anyways. Signed-off-by: Paul Mundt diff --git a/arch/sh/include/asm/hw_breakpoint.h b/arch/sh/include/asm/hw_breakpoint.h index 965dd78..1c388c1 100644 --- a/arch/sh/include/asm/hw_breakpoint.h +++ b/arch/sh/include/asm/hw_breakpoint.h @@ -56,7 +56,6 @@ extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused, int arch_install_hw_breakpoint(struct perf_event *bp); void arch_uninstall_hw_breakpoint(struct perf_event *bp); void hw_breakpoint_pmu_read(struct perf_event *bp); -void hw_breakpoint_pmu_unthrottle(struct perf_event *bp); extern void arch_fill_perf_breakpoint(struct perf_event *bp); extern int register_sh_ubc(struct sh_ubc *); diff --git a/arch/sh/kernel/hw_breakpoint.c b/arch/sh/kernel/hw_breakpoint.c index 675eea7..5499857 100644 --- a/arch/sh/kernel/hw_breakpoint.c +++ b/arch/sh/kernel/hw_breakpoint.c @@ -425,11 +425,6 @@ void hw_breakpoint_pmu_read(struct perf_event *bp) /* TODO */ } -void hw_breakpoint_pmu_unthrottle(struct perf_event *bp) -{ - /* TODO */ -} - int register_sh_ubc(struct sh_ubc *ubc) { /* Bail if it's already assigned */ -- cgit v0.10.2 From a9079ca0cb15feda15e7a380092e02d5cd834148 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 21 Apr 2010 12:01:06 +0900 Subject: sh: Tidy CPU probing and fixup section annotations. This does a detect_cpu_and_cache_system() -> cpu_probe() rename, tidies up the unused return value, and stuffs it under __cpuinit in preparation for CPU hotplug. Signed-off-by: Paul Mundt diff --git a/arch/sh/include/asm/cache.h b/arch/sh/include/asm/cache.h index 02df18e..e461d67 100644 --- a/arch/sh/include/asm/cache.h +++ b/arch/sh/include/asm/cache.h @@ -38,14 +38,10 @@ struct cache_info { * 2. those in the physical page number. */ unsigned int alias_mask; - unsigned int n_aliases; /* Number of aliases */ unsigned long flags; }; - -int __init detect_cpu_and_cache_system(void); - #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ #endif /* __ASM_SH_CACHE_H */ diff --git a/arch/sh/include/asm/processor.h b/arch/sh/include/asm/processor.h index 9605e062..c2be225 100644 --- a/arch/sh/include/asm/processor.h +++ b/arch/sh/include/asm/processor.h @@ -102,6 +102,8 @@ struct task_struct; extern struct pt_regs fake_swapper_regs; +extern void cpu_probe(void); + /* arch/sh/kernel/process.c */ extern unsigned int xstate_size; extern void free_thread_xstate(struct task_struct *); diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c index c736422..ffaa00a 100644 --- a/arch/sh/kernel/cpu/init.c +++ b/arch/sh/kernel/cpu/init.c @@ -293,14 +293,14 @@ static inline void __init dsp_init(void) { } * subtype and initial configuration will all be done. * * Each processor family is still responsible for doing its own probing - * and cache configuration in detect_cpu_and_cache_system(). + * and cache configuration in cpu_probe(). */ asmlinkage void __init sh_cpu_init(void) { current_thread_info()->cpu = hard_smp_processor_id(); /* First, probe the CPU */ - detect_cpu_and_cache_system(); + cpu_probe(); if (current_cpu_data.type == CPU_SH_NONE) panic("Unknown CPU"); diff --git a/arch/sh/kernel/cpu/sh2/probe.c b/arch/sh/kernel/cpu/sh2/probe.c index 1db6d888..bab8e75 100644 --- a/arch/sh/kernel/cpu/sh2/probe.c +++ b/arch/sh/kernel/cpu/sh2/probe.c @@ -13,7 +13,7 @@ #include #include -int __init detect_cpu_and_cache_system(void) +void __cpuinit cpu_probe(void) { #if defined(CONFIG_CPU_SUBTYPE_SH7619) boot_cpu_data.type = CPU_SH7619; @@ -30,7 +30,4 @@ int __init detect_cpu_and_cache_system(void) boot_cpu_data.dcache.flags |= SH_CACHE_COMBINED; boot_cpu_data.icache = boot_cpu_data.dcache; boot_cpu_data.family = CPU_FAMILY_SH2; - - return 0; } - diff --git a/arch/sh/kernel/cpu/sh2a/probe.c b/arch/sh/kernel/cpu/sh2a/probe.c index 6825d65..48e97a2 100644 --- a/arch/sh/kernel/cpu/sh2a/probe.c +++ b/arch/sh/kernel/cpu/sh2a/probe.c @@ -13,7 +13,7 @@ #include #include -int __init detect_cpu_and_cache_system(void) +void __cpuinit cpu_probe(void) { boot_cpu_data.family = CPU_FAMILY_SH2A; @@ -51,6 +51,4 @@ int __init detect_cpu_and_cache_system(void) * on the cache info. */ boot_cpu_data.icache = boot_cpu_data.dcache; - - return 0; } diff --git a/arch/sh/kernel/cpu/sh3/probe.c b/arch/sh/kernel/cpu/sh3/probe.c index 295ec4c..bf23c32 100644 --- a/arch/sh/kernel/cpu/sh3/probe.c +++ b/arch/sh/kernel/cpu/sh3/probe.c @@ -16,7 +16,7 @@ #include #include -int detect_cpu_and_cache_system(void) +void __cpuinit cpu_probe(void) { unsigned long addr0, addr1, data0, data1, data2, data3; @@ -108,6 +108,4 @@ int detect_cpu_and_cache_system(void) boot_cpu_data.icache = boot_cpu_data.dcache; boot_cpu_data.family = CPU_FAMILY_SH3; - - return 0; } diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c index 822977a..d180f16 100644 --- a/arch/sh/kernel/cpu/sh4/probe.c +++ b/arch/sh/kernel/cpu/sh4/probe.c @@ -15,7 +15,7 @@ #include #include -int __init detect_cpu_and_cache_system(void) +void __cpuinit cpu_probe(void) { unsigned long pvr, prr, cvr; unsigned long size; @@ -251,6 +251,4 @@ int __init detect_cpu_and_cache_system(void) boot_cpu_data.scache.linesz); } } - - return 0; } diff --git a/arch/sh/kernel/cpu/sh5/probe.c b/arch/sh/kernel/cpu/sh5/probe.c index 521d05b..9e88240 100644 --- a/arch/sh/kernel/cpu/sh5/probe.c +++ b/arch/sh/kernel/cpu/sh5/probe.c @@ -17,7 +17,7 @@ #include #include -int __init detect_cpu_and_cache_system(void) +void __cpuinit cpu_probe(void) { unsigned long long cir; @@ -72,6 +72,4 @@ int __init detect_cpu_and_cache_system(void) /* Setup some I/D TLB defaults */ sh64_tlb_init(); - - return 0; } -- cgit v0.10.2 From 315e995c63a15cb4d4efdbfd70fe2db191917f7a Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Wed, 21 Apr 2010 03:18:28 +0000 Subject: [CIFS] use add_to_page_cache_lru add_to_page_cache_lru is exported, so it should be used. Benefits over using a private pagevec: neater code, 128 bytes fewer stack used, percpu lru ordering is preserved, and finally don't need to flush pagevec before returning so batching may be shared with other LRU insertions. Signed-off-by: Nick Piggin Reviewed-by: Dave Kleikamp Signed-off-by: Steve French diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 9b11a8f..1361d67 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -1931,8 +1931,7 @@ int cifs_file_mmap(struct file *file, struct vm_area_struct *vma) static void cifs_copy_cache_pages(struct address_space *mapping, - struct list_head *pages, int bytes_read, char *data, - struct pagevec *plru_pvec) + struct list_head *pages, int bytes_read, char *data) { struct page *page; char *target; @@ -1944,7 +1943,7 @@ static void cifs_copy_cache_pages(struct address_space *mapping, page = list_entry(pages->prev, struct page, lru); list_del(&page->lru); - if (add_to_page_cache(page, mapping, page->index, + if (add_to_page_cache_lru(page, mapping, page->index, GFP_KERNEL)) { page_cache_release(page); cFYI(1, ("Add page cache failed")); @@ -1970,8 +1969,6 @@ static void cifs_copy_cache_pages(struct address_space *mapping, flush_dcache_page(page); SetPageUptodate(page); unlock_page(page); - if (!pagevec_add(plru_pvec, page)) - __pagevec_lru_add_file(plru_pvec); data += PAGE_CACHE_SIZE; } return; @@ -1990,7 +1987,6 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, unsigned int read_size, i; char *smb_read_data = NULL; struct smb_com_read_rsp *pSMBr; - struct pagevec lru_pvec; struct cifsFileInfo *open_file; int buf_type = CIFS_NO_BUFFER; @@ -2004,7 +2000,6 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); pTcon = cifs_sb->tcon; - pagevec_init(&lru_pvec, 0); cFYI(DBG2, ("rpages: num pages %d", num_pages)); for (i = 0; i < num_pages; ) { unsigned contig_pages; @@ -2073,7 +2068,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, pSMBr = (struct smb_com_read_rsp *)smb_read_data; cifs_copy_cache_pages(mapping, page_list, bytes_read, smb_read_data + 4 /* RFC1001 hdr */ + - le16_to_cpu(pSMBr->DataOffset), &lru_pvec); + le16_to_cpu(pSMBr->DataOffset)); i += bytes_read >> PAGE_CACHE_SHIFT; cifs_stats_bytes_read(pTcon, bytes_read); @@ -2106,8 +2101,6 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, bytes_read = 0; } - pagevec_lru_add_file(&lru_pvec); - /* need to free smb_read_data buf before exit */ if (smb_read_data) { if (buf_type == CIFS_SMALL_BUFFER) -- cgit v0.10.2 From 4a6feab0ee5240c4bd5378d9f8a46b85718c68a7 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 21 Apr 2010 12:20:42 +0900 Subject: sh: __cpuinit annotate the CPU init path. All of the regular CPU init path needs to be __cpuinit annotated for CPU hotplug. Signed-off-by: Paul Mundt diff --git a/arch/sh/include/asm/processor.h b/arch/sh/include/asm/processor.h index c2be225..26b3f02 100644 --- a/arch/sh/include/asm/processor.h +++ b/arch/sh/include/asm/processor.h @@ -102,6 +102,7 @@ struct task_struct; extern struct pt_regs fake_swapper_regs; +extern void cpu_init(void); extern void cpu_probe(void); /* arch/sh/kernel/process.c */ diff --git a/arch/sh/include/asm/processor_32.h b/arch/sh/include/asm/processor_32.h index 572b4eb..61a445d 100644 --- a/arch/sh/include/asm/processor_32.h +++ b/arch/sh/include/asm/processor_32.h @@ -27,8 +27,6 @@ #define CCN_CVR 0xff000040 #define CCN_PRR 0xff000044 -asmlinkage void __init sh_cpu_init(void); - /* * User space process size: 2GB. * diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c index ffaa00a..9766106 100644 --- a/arch/sh/kernel/cpu/init.c +++ b/arch/sh/kernel/cpu/init.c @@ -43,9 +43,9 @@ * peripherals (nofpu, nodsp, and so forth). */ #define onchip_setup(x) \ -static int x##_disabled __initdata = !cpu_has_##x; \ +static int x##_disabled __cpuinitdata = !cpu_has_##x; \ \ -static int __init x##_setup(char *opts) \ +static int __cpuinit x##_setup(char *opts) \ { \ x##_disabled = 1; \ return 1; \ @@ -59,7 +59,7 @@ onchip_setup(dsp); #define CPUOPM 0xff2f0000 #define CPUOPM_RABD (1 << 5) -static void __init speculative_execution_init(void) +static void __cpuinit speculative_execution_init(void) { /* Clear RABD */ __raw_writel(__raw_readl(CPUOPM) & ~CPUOPM_RABD, CPUOPM); @@ -78,7 +78,7 @@ static void __init speculative_execution_init(void) #define EXPMASK_BRDSSLP (1 << 1) #define EXPMASK_MMCAW (1 << 4) -static void __init expmask_init(void) +static void __cpuinit expmask_init(void) { unsigned long expmask = __raw_readl(EXPMASK); @@ -217,7 +217,7 @@ static void detect_cache_shape(void) l2_cache_shape = -1; /* No S-cache */ } -static void __init fpu_init(void) +static void __cpuinit fpu_init(void) { /* Disable the FPU */ if (fpu_disabled && (current_cpu_data.flags & CPU_HAS_FPU)) { @@ -230,7 +230,7 @@ static void __init fpu_init(void) } #ifdef CONFIG_SH_DSP -static void __init release_dsp(void) +static void __cpuinit release_dsp(void) { unsigned long sr; @@ -244,7 +244,7 @@ static void __init release_dsp(void) ); } -static void __init dsp_init(void) +static void __cpuinit dsp_init(void) { unsigned long sr; @@ -276,11 +276,11 @@ static void __init dsp_init(void) release_dsp(); } #else -static inline void __init dsp_init(void) { } +static inline void __cpuinit dsp_init(void) { } #endif /* CONFIG_SH_DSP */ /** - * sh_cpu_init + * cpu_init * * This is our initial entry point for each CPU, and is invoked on the * boot CPU prior to calling start_kernel(). For SMP, a combination of @@ -295,7 +295,7 @@ static inline void __init dsp_init(void) { } * Each processor family is still responsible for doing its own probing * and cache configuration in cpu_probe(). */ -asmlinkage void __init sh_cpu_init(void) +asmlinkage void __cpuinit cpu_init(void) { current_thread_info()->cpu = hard_smp_processor_id(); diff --git a/arch/sh/kernel/head_32.S b/arch/sh/kernel/head_32.S index fe0b743..8c1fc9a 100644 --- a/arch/sh/kernel/head_32.S +++ b/arch/sh/kernel/head_32.S @@ -335,7 +335,7 @@ ENTRY(stack_start) 3: .long __bss_start 4: .long _end 5: .long start_kernel -6: .long sh_cpu_init +6: .long cpu_init 7: .long init_thread_union #ifdef CONFIG_PMB diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c index 81add9b..4d49c86 100644 --- a/arch/sh/kernel/process.c +++ b/arch/sh/kernel/process.c @@ -89,7 +89,7 @@ void arch_task_cache_init(void) # define HAVE_SOFTFP 0 #endif -void init_thread_xstate(void) +void __cpuinit init_thread_xstate(void) { if (boot_cpu_data.flags & CPU_HAS_FPU) xstate_size = sizeof(struct sh_fpu_hard_struct); -- cgit v0.10.2 From 3366e3585fbf0d40ce6f2382b544851cf4df1654 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 30 Mar 2010 12:38:01 +0900 Subject: sh: Move platform smp ops in to their own structure. This cribs the MIPS plat_smp_ops approach for wrapping up the platform ops. This will allow for mixing and matching different ops on the same platform in the future. Signed-off-by: Paul Mundt diff --git a/arch/sh/boards/board-urquell.c b/arch/sh/boards/board-urquell.c index a9bd6e3..d81c609 100644 --- a/arch/sh/boards/board-urquell.c +++ b/arch/sh/boards/board-urquell.c @@ -24,6 +24,7 @@ #include #include #include +#include /* * bit 1234 5678 @@ -203,6 +204,8 @@ static void __init urquell_setup(char **cmdline_p) printk(KERN_INFO "Renesas Technology Corp. Urquell support.\n"); pm_power_off = urquell_power_off; + + register_smp_ops(&shx3_smp_ops); } /* diff --git a/arch/sh/boards/mach-sdk7786/setup.c b/arch/sh/boards/mach-sdk7786/setup.c index 0c057a9..2ec1ea5 100644 --- a/arch/sh/boards/mach-sdk7786/setup.c +++ b/arch/sh/boards/mach-sdk7786/setup.c @@ -21,6 +21,7 @@ #include #include #include +#include static struct resource heartbeat_resource = { .start = 0x07fff8b0, @@ -189,6 +190,8 @@ static void __init sdk7786_setup(char **cmdline_p) machine_ops.restart = sdk7786_restart; pm_power_off = sdk7786_power_off; + + register_smp_ops(&shx3_smp_ops); } /* diff --git a/arch/sh/boards/mach-x3proto/setup.c b/arch/sh/boards/mach-x3proto/setup.c index e284592..102bf56 100644 --- a/arch/sh/boards/mach-x3proto/setup.c +++ b/arch/sh/boards/mach-x3proto/setup.c @@ -19,6 +19,7 @@ #include #include #include +#include static struct resource heartbeat_resources[] = { [0] = { @@ -152,7 +153,13 @@ static void __init x3proto_init_irq(void) __raw_writel(__raw_readl(0xfe410000) | (1 << 21), 0xfe410000); } +static void __init x3proto_setup(char **cmdline_p) +{ + register_smp_ops(&shx3_smp_ops); +} + static struct sh_machine_vector mv_x3proto __initmv = { .mv_name = "x3proto", + .mv_setup = x3proto_setup, .mv_init_irq = x3proto_init_irq, }; diff --git a/arch/sh/include/asm/smp-ops.h b/arch/sh/include/asm/smp-ops.h new file mode 100644 index 0000000..0581b2a --- /dev/null +++ b/arch/sh/include/asm/smp-ops.h @@ -0,0 +1,39 @@ +#ifndef __ASM_SH_SMP_OPS_H +#define __ASM_SH_SMP_OPS_H + +struct plat_smp_ops { + void (*smp_setup)(void); + unsigned int (*smp_processor_id)(void); + void (*prepare_cpus)(unsigned int max_cpus); + void (*start_cpu)(unsigned int cpu, unsigned long entry_point); + void (*send_ipi)(unsigned int cpu, unsigned int message); +}; + +extern struct plat_smp_ops shx3_smp_ops; + +#ifdef CONFIG_SMP + +static inline void plat_smp_setup(void) +{ + extern struct plat_smp_ops *mp_ops; /* private */ + + BUG_ON(!mp_ops); + mp_ops->smp_setup(); +} + +extern void register_smp_ops(struct plat_smp_ops *ops); + +#else + +static inline void plat_smp_setup(void) +{ + /* UP, nothing to do ... */ +} + +static inline void register_smp_ops(struct plat_smp_ops *ops) +{ +} + +#endif /* CONFIG_SMP */ + +#endif /* __ASM_SH_SMP_OPS_H */ diff --git a/arch/sh/include/asm/smp.h b/arch/sh/include/asm/smp.h index 53ef26c..7f13d46 100644 --- a/arch/sh/include/asm/smp.h +++ b/arch/sh/include/asm/smp.h @@ -3,6 +3,7 @@ #include #include +#include #ifdef CONFIG_SMP @@ -11,7 +12,6 @@ #include #define raw_smp_processor_id() (current_thread_info()->cpu) -#define hard_smp_processor_id() plat_smp_processor_id() /* Map from cpu id to sequential logical cpu number. */ extern int __cpu_number_map[NR_CPUS]; @@ -36,15 +36,19 @@ void smp_timer_broadcast(const struct cpumask *mask); void local_timer_interrupt(void); void local_timer_setup(unsigned int cpu); -void plat_smp_setup(void); -void plat_prepare_cpus(unsigned int max_cpus); -int plat_smp_processor_id(void); -void plat_start_cpu(unsigned int cpu, unsigned long entry_point); -void plat_send_ipi(unsigned int cpu, unsigned int message); - void arch_send_call_function_single_ipi(int cpu); extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); +static inline int hard_smp_processor_id(void) +{ + extern struct plat_smp_ops *mp_ops; /* private */ + + if (!mp_ops) + return 0; /* boot CPU */ + + return mp_ops->smp_processor_id(); +} + #else #define hard_smp_processor_id() (0) diff --git a/arch/sh/kernel/cpu/sh4a/smp-shx3.c b/arch/sh/kernel/cpu/sh4a/smp-shx3.c index c98b457..5c5d50c 100644 --- a/arch/sh/kernel/cpu/sh4a/smp-shx3.c +++ b/arch/sh/kernel/cpu/sh4a/smp-shx3.c @@ -1,7 +1,7 @@ /* * SH-X3 SMP * - * Copyright (C) 2007 - 2008 Paul Mundt + * Copyright (C) 2007 - 2010 Paul Mundt * Copyright (C) 2007 Magnus Damm * * This file is subject to the terms and conditions of the GNU General Public @@ -37,7 +37,7 @@ static irqreturn_t ipi_interrupt_handler(int irq, void *arg) return IRQ_HANDLED; } -void __init plat_smp_setup(void) +static void shx3_smp_setup(void) { unsigned int cpu = 0; int i, num; @@ -63,7 +63,7 @@ void __init plat_smp_setup(void) printk(KERN_INFO "Detected %i available secondary CPU(s)\n", num); } -void __init plat_prepare_cpus(unsigned int max_cpus) +static void shx3_prepare_cpus(unsigned int max_cpus) { int i; @@ -76,7 +76,7 @@ void __init plat_prepare_cpus(unsigned int max_cpus) IRQF_DISABLED | IRQF_PERCPU, "IPI", (void *)(long)i); } -void plat_start_cpu(unsigned int cpu, unsigned long entry_point) +static void shx3_start_cpu(unsigned int cpu, unsigned long entry_point) { if (__in_29bit_mode()) __raw_writel(entry_point, RESET_REG(cpu)); @@ -93,12 +93,12 @@ void plat_start_cpu(unsigned int cpu, unsigned long entry_point) __raw_writel(STBCR_RESET | STBCR_LTSLP, STBCR_REG(cpu)); } -int plat_smp_processor_id(void) +static unsigned int shx3_smp_processor_id(void) { return __raw_readl(0xff000048); /* CPIDR */ } -void plat_send_ipi(unsigned int cpu, unsigned int message) +static void shx3_send_ipi(unsigned int cpu, unsigned int message) { unsigned long addr = 0xfe410070 + (cpu * 4); @@ -106,3 +106,11 @@ void plat_send_ipi(unsigned int cpu, unsigned int message) __raw_writel(1 << (message << 2), addr); /* C0INTICI..CnINTICI */ } + +struct plat_smp_ops shx3_smp_ops = { + .smp_setup = shx3_smp_setup, + .prepare_cpus = shx3_prepare_cpus, + .start_cpu = shx3_start_cpu, + .smp_processor_id = shx3_smp_processor_id, + .send_ipi = shx3_send_ipi, +}; diff --git a/arch/sh/kernel/localtimer.c b/arch/sh/kernel/localtimer.c index 0b04e7d..865a2f1 100644 --- a/arch/sh/kernel/localtimer.c +++ b/arch/sh/kernel/localtimer.c @@ -44,7 +44,7 @@ static void dummy_timer_set_mode(enum clock_event_mode mode, { } -void __cpuinit local_timer_setup(unsigned int cpu) +void local_timer_setup(unsigned int cpu) { struct clock_event_device *clk = &per_cpu(local_clockevent, cpu); diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 8870d6b..2915538 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -459,9 +459,7 @@ void __init setup_arch(char **cmdline_p) if (likely(sh_mv.mv_setup)) sh_mv.mv_setup(cmdline_p); -#ifdef CONFIG_SMP plat_smp_setup(); -#endif } /* processor boot mode configuration */ diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c index 002cc61..2f348fd 100644 --- a/arch/sh/kernel/smp.c +++ b/arch/sh/kernel/smp.c @@ -3,7 +3,7 @@ * * SMP support for the SuperH processors. * - * Copyright (C) 2002 - 2008 Paul Mundt + * Copyright (C) 2002 - 2010 Paul Mundt * Copyright (C) 2006 - 2007 Akio Idehara * * This file is subject to the terms and conditions of the GNU General Public @@ -31,6 +31,16 @@ int __cpu_number_map[NR_CPUS]; /* Map physical to logical */ int __cpu_logical_map[NR_CPUS]; /* Map logical to physical */ +struct plat_smp_ops *mp_ops = NULL; + +void __cpuinit register_smp_ops(struct plat_smp_ops *ops) +{ + if (mp_ops) + printk(KERN_WARNING "Overriding previously set SMP ops\n"); + + mp_ops = ops; +} + static inline void __init smp_store_cpu_info(unsigned int cpu) { struct sh_cpuinfo *c = cpu_data + cpu; @@ -46,7 +56,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) init_new_context(current, &init_mm); current_thread_info()->cpu = cpu; - plat_prepare_cpus(max_cpus); + mp_ops->prepare_cpus(max_cpus); #ifndef CONFIG_HOTPLUG_CPU init_cpu_present(&cpu_possible_map); @@ -127,7 +137,7 @@ int __cpuinit __cpu_up(unsigned int cpu) (unsigned long)&stack_start + sizeof(stack_start)); wmb(); - plat_start_cpu(cpu, (unsigned long)_stext); + mp_ops->start_cpu(cpu, (unsigned long)_stext); timeout = jiffies + HZ; while (time_before(jiffies, timeout)) { @@ -159,7 +169,7 @@ void __init smp_cpus_done(unsigned int max_cpus) void smp_send_reschedule(int cpu) { - plat_send_ipi(cpu, SMP_MSG_RESCHEDULE); + mp_ops->send_ipi(cpu, SMP_MSG_RESCHEDULE); } void smp_send_stop(void) @@ -172,12 +182,12 @@ void arch_send_call_function_ipi_mask(const struct cpumask *mask) int cpu; for_each_cpu(cpu, mask) - plat_send_ipi(cpu, SMP_MSG_FUNCTION); + mp_ops->send_ipi(cpu, SMP_MSG_FUNCTION); } void arch_send_call_function_single_ipi(int cpu) { - plat_send_ipi(cpu, SMP_MSG_FUNCTION_SINGLE); + mp_ops->send_ipi(cpu, SMP_MSG_FUNCTION_SINGLE); } void smp_timer_broadcast(const struct cpumask *mask) @@ -185,7 +195,7 @@ void smp_timer_broadcast(const struct cpumask *mask) int cpu; for_each_cpu(cpu, mask) - plat_send_ipi(cpu, SMP_MSG_TIMER); + mp_ops->send_ipi(cpu, SMP_MSG_TIMER); } static void ipi_timer(void) -- cgit v0.10.2 From b6b38f704a8193daba520493ebdaf7e819962fc8 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 21 Apr 2010 03:50:45 +0000 Subject: [CIFS] Neaten cERROR and cFYI macros, reduce text space Neaten cERROR and cFYI macros, reduce text space ~2.5K Convert '__FILE__ ": " fmt' to '"%s: " fmt', __FILE__' to save text space Surround macros with do {} while Add parentheses to macros Make statement expression macro from macro with assign Remove now unnecessary parentheses from cFYI and cERROR uses defconfig with CIFS support old $ size fs/cifs/built-in.o text data bss dec hex filename 156012 1760 148 157920 268e0 fs/cifs/built-in.o defconfig with CIFS support old $ size fs/cifs/built-in.o text data bss dec hex filename 153508 1760 148 155416 25f18 fs/cifs/built-in.o allyesconfig old: $ size fs/cifs/built-in.o text data bss dec hex filename 309138 3864 74824 387826 5eaf2 fs/cifs/built-in.o allyesconfig new $ size fs/cifs/built-in.o text data bss dec hex filename 305655 3864 74824 384343 5dd57 fs/cifs/built-in.o Signed-off-by: Joe Perches Signed-off-by: Steve French diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c index a20bea5..6d555c0 100644 --- a/fs/cifs/asn1.c +++ b/fs/cifs/asn1.c @@ -510,11 +510,11 @@ decode_negTokenInit(unsigned char *security_blob, int length, /* GSSAPI header */ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { - cFYI(1, ("Error decoding negTokenInit header")); + cFYI(1, "Error decoding negTokenInit header"); return 0; } else if ((cls != ASN1_APL) || (con != ASN1_CON) || (tag != ASN1_EOC)) { - cFYI(1, ("cls = %d con = %d tag = %d", cls, con, tag)); + cFYI(1, "cls = %d con = %d tag = %d", cls, con, tag); return 0; } @@ -535,56 +535,52 @@ decode_negTokenInit(unsigned char *security_blob, int length, /* SPNEGO OID not present or garbled -- bail out */ if (!rc) { - cFYI(1, ("Error decoding negTokenInit header")); + cFYI(1, "Error decoding negTokenInit header"); return 0; } /* SPNEGO */ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { - cFYI(1, ("Error decoding negTokenInit")); + cFYI(1, "Error decoding negTokenInit"); return 0; } else if ((cls != ASN1_CTX) || (con != ASN1_CON) || (tag != ASN1_EOC)) { - cFYI(1, - ("cls = %d con = %d tag = %d end = %p (%d) exit 0", - cls, con, tag, end, *end)); + cFYI(1, "cls = %d con = %d tag = %d end = %p (%d) exit 0", + cls, con, tag, end, *end); return 0; } /* negTokenInit */ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { - cFYI(1, ("Error decoding negTokenInit")); + cFYI(1, "Error decoding negTokenInit"); return 0; } else if ((cls != ASN1_UNI) || (con != ASN1_CON) || (tag != ASN1_SEQ)) { - cFYI(1, - ("cls = %d con = %d tag = %d end = %p (%d) exit 1", - cls, con, tag, end, *end)); + cFYI(1, "cls = %d con = %d tag = %d end = %p (%d) exit 1", + cls, con, tag, end, *end); return 0; } /* sequence */ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { - cFYI(1, ("Error decoding 2nd part of negTokenInit")); + cFYI(1, "Error decoding 2nd part of negTokenInit"); return 0; } else if ((cls != ASN1_CTX) || (con != ASN1_CON) || (tag != ASN1_EOC)) { - cFYI(1, - ("cls = %d con = %d tag = %d end = %p (%d) exit 0", - cls, con, tag, end, *end)); + cFYI(1, "cls = %d con = %d tag = %d end = %p (%d) exit 0", + cls, con, tag, end, *end); return 0; } /* sequence of */ if (asn1_header_decode (&ctx, &sequence_end, &cls, &con, &tag) == 0) { - cFYI(1, ("Error decoding 2nd part of negTokenInit")); + cFYI(1, "Error decoding 2nd part of negTokenInit"); return 0; } else if ((cls != ASN1_UNI) || (con != ASN1_CON) || (tag != ASN1_SEQ)) { - cFYI(1, - ("cls = %d con = %d tag = %d end = %p (%d) exit 1", - cls, con, tag, end, *end)); + cFYI(1, "cls = %d con = %d tag = %d end = %p (%d) exit 1", + cls, con, tag, end, *end); return 0; } @@ -592,16 +588,15 @@ decode_negTokenInit(unsigned char *security_blob, int length, while (!asn1_eoc_decode(&ctx, sequence_end)) { rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag); if (!rc) { - cFYI(1, - ("Error decoding negTokenInit hdr exit2")); + cFYI(1, "Error decoding negTokenInit hdr exit2"); return 0; } if ((tag == ASN1_OJI) && (con == ASN1_PRI)) { if (asn1_oid_decode(&ctx, end, &oid, &oidlen)) { - cFYI(1, ("OID len = %d oid = 0x%lx 0x%lx " - "0x%lx 0x%lx", oidlen, *oid, - *(oid + 1), *(oid + 2), *(oid + 3))); + cFYI(1, "OID len = %d oid = 0x%lx 0x%lx " + "0x%lx 0x%lx", oidlen, *oid, + *(oid + 1), *(oid + 2), *(oid + 3)); if (compare_oid(oid, oidlen, MSKRB5_OID, MSKRB5_OID_LEN) && @@ -622,7 +617,7 @@ decode_negTokenInit(unsigned char *security_blob, int length, kfree(oid); } } else { - cFYI(1, ("Should be an oid what is going on?")); + cFYI(1, "Should be an oid what is going on?"); } } @@ -632,47 +627,47 @@ decode_negTokenInit(unsigned char *security_blob, int length, no mechListMic (e.g. NTLMSSP instead of KRB5) */ if (ctx.error == ASN1_ERR_DEC_EMPTY) goto decode_negtoken_exit; - cFYI(1, ("Error decoding last part negTokenInit exit3")); + cFYI(1, "Error decoding last part negTokenInit exit3"); return 0; } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { /* tag = 3 indicating mechListMIC */ - cFYI(1, ("Exit 4 cls = %d con = %d tag = %d end = %p (%d)", - cls, con, tag, end, *end)); + cFYI(1, "Exit 4 cls = %d con = %d tag = %d end = %p (%d)", + cls, con, tag, end, *end); return 0; } /* sequence */ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { - cFYI(1, ("Error decoding last part negTokenInit exit5")); + cFYI(1, "Error decoding last part negTokenInit exit5"); return 0; } else if ((cls != ASN1_UNI) || (con != ASN1_CON) || (tag != ASN1_SEQ)) { - cFYI(1, ("cls = %d con = %d tag = %d end = %p (%d)", - cls, con, tag, end, *end)); + cFYI(1, "cls = %d con = %d tag = %d end = %p (%d)", + cls, con, tag, end, *end); } /* sequence of */ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { - cFYI(1, ("Error decoding last part negTokenInit exit 7")); + cFYI(1, "Error decoding last part negTokenInit exit 7"); return 0; } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { - cFYI(1, ("Exit 8 cls = %d con = %d tag = %d end = %p (%d)", - cls, con, tag, end, *end)); + cFYI(1, "Exit 8 cls = %d con = %d tag = %d end = %p (%d)", + cls, con, tag, end, *end); return 0; } /* general string */ if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { - cFYI(1, ("Error decoding last part negTokenInit exit9")); + cFYI(1, "Error decoding last part negTokenInit exit9"); return 0; } else if ((cls != ASN1_UNI) || (con != ASN1_PRI) || (tag != ASN1_GENSTR)) { - cFYI(1, ("Exit10 cls = %d con = %d tag = %d end = %p (%d)", - cls, con, tag, end, *end)); + cFYI(1, "Exit10 cls = %d con = %d tag = %d end = %p (%d)", + cls, con, tag, end, *end); return 0; } - cFYI(1, ("Need to call asn1_octets_decode() function for %s", - ctx.pointer)); /* is this UTF-8 or ASCII? */ + cFYI(1, "Need to call asn1_octets_decode() function for %s", + ctx.pointer); /* is this UTF-8 or ASCII? */ decode_negtoken_exit: if (use_kerberos) *secType = Kerberos; diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index 42cec2a..5495180 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c @@ -60,10 +60,10 @@ cifs_dump_mem(char *label, void *data, int length) #ifdef CONFIG_CIFS_DEBUG2 void cifs_dump_detail(struct smb_hdr *smb) { - cERROR(1, ("Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d", + cERROR(1, "Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d", smb->Command, smb->Status.CifsError, - smb->Flags, smb->Flags2, smb->Mid, smb->Pid)); - cERROR(1, ("smb buf %p len %d", smb, smbCalcSize_LE(smb))); + smb->Flags, smb->Flags2, smb->Mid, smb->Pid); + cERROR(1, "smb buf %p len %d", smb, smbCalcSize_LE(smb)); } @@ -75,25 +75,25 @@ void cifs_dump_mids(struct TCP_Server_Info *server) if (server == NULL) return; - cERROR(1, ("Dump pending requests:")); + cERROR(1, "Dump pending requests:"); spin_lock(&GlobalMid_Lock); list_for_each(tmp, &server->pending_mid_q) { mid_entry = list_entry(tmp, struct mid_q_entry, qhead); - cERROR(1, ("State: %d Cmd: %d Pid: %d Tsk: %p Mid %d", + cERROR(1, "State: %d Cmd: %d Pid: %d Tsk: %p Mid %d", mid_entry->midState, (int)mid_entry->command, mid_entry->pid, mid_entry->tsk, - mid_entry->mid)); + mid_entry->mid); #ifdef CONFIG_CIFS_STATS2 - cERROR(1, ("IsLarge: %d buf: %p time rcv: %ld now: %ld", + cERROR(1, "IsLarge: %d buf: %p time rcv: %ld now: %ld", mid_entry->largeBuf, mid_entry->resp_buf, mid_entry->when_received, - jiffies)); + jiffies); #endif /* STATS2 */ - cERROR(1, ("IsMult: %d IsEnd: %d", mid_entry->multiRsp, - mid_entry->multiEnd)); + cERROR(1, "IsMult: %d IsEnd: %d", mid_entry->multiRsp, + mid_entry->multiEnd); if (mid_entry->resp_buf) { cifs_dump_detail(mid_entry->resp_buf); cifs_dump_mem("existing buf: ", @@ -750,7 +750,7 @@ static ssize_t cifs_security_flags_proc_write(struct file *file, extended_security = CIFSSEC_MAX; return count; } else if (!isdigit(c)) { - cERROR(1, ("invalid flag %c", c)); + cERROR(1, "invalid flag %c", c); return -EINVAL; } } @@ -758,16 +758,16 @@ static ssize_t cifs_security_flags_proc_write(struct file *file, flags = simple_strtoul(flags_string, NULL, 0); - cFYI(1, ("sec flags 0x%x", flags)); + cFYI(1, "sec flags 0x%x", flags); if (flags <= 0) { - cERROR(1, ("invalid security flags %s", flags_string)); + cERROR(1, "invalid security flags %s", flags_string); return -EINVAL; } if (flags & ~CIFSSEC_MASK) { - cERROR(1, ("attempt to set unsupported security flags 0x%x", - flags & ~CIFSSEC_MASK)); + cERROR(1, "attempt to set unsupported security flags 0x%x", + flags & ~CIFSSEC_MASK); return -EINVAL; } /* flags look ok - update the global security flags for cifs module */ @@ -775,9 +775,9 @@ static ssize_t cifs_security_flags_proc_write(struct file *file, if (extended_security & CIFSSEC_MUST_SIGN) { /* requiring signing implies signing is allowed */ extended_security |= CIFSSEC_MAY_SIGN; - cFYI(1, ("packet signing now required")); + cFYI(1, "packet signing now required"); } else if ((extended_security & CIFSSEC_MAY_SIGN) == 0) { - cFYI(1, ("packet signing disabled")); + cFYI(1, "packet signing disabled"); } /* BB should we turn on MAY flags for other MUST options? */ return count; diff --git a/fs/cifs/cifs_debug.h b/fs/cifs/cifs_debug.h index 5eb3b83..aa31689 100644 --- a/fs/cifs/cifs_debug.h +++ b/fs/cifs/cifs_debug.h @@ -43,34 +43,54 @@ void dump_smb(struct smb_hdr *, int); */ #ifdef CIFS_DEBUG - /* information message: e.g., configuration, major event */ extern int cifsFYI; -#define cifsfyi(format,arg...) if (cifsFYI & CIFS_INFO) printk(KERN_DEBUG " " __FILE__ ": " format "\n" "" , ## arg) +#define cifsfyi(fmt, arg...) \ +do { \ + if (cifsFYI & CIFS_INFO) \ + printk(KERN_DEBUG "%s: " fmt "\n", __FILE__, ##arg); \ +} while (0) -#define cFYI(button,prspec) if (button) cifsfyi prspec +#define cFYI(set, fmt, arg...) \ +do { \ + if (set) \ + cifsfyi(fmt, ##arg); \ +} while (0) -#define cifswarn(format, arg...) printk(KERN_WARNING ": " format "\n" , ## arg) +#define cifswarn(fmt, arg...) \ + printk(KERN_WARNING fmt "\n", ##arg) /* debug event message: */ extern int cifsERROR; -#define cEVENT(format,arg...) if (cifsERROR) printk(KERN_EVENT __FILE__ ": " format "\n" , ## arg) +#define cEVENT(fmt, arg...) \ +do { \ + if (cifsERROR) \ + printk(KERN_EVENT "%s: " fmt "\n", __FILE__, ##arg); \ +} while (0) /* error event message: e.g., i/o error */ -#define cifserror(format,arg...) if (cifsERROR) printk(KERN_ERR " CIFS VFS: " format "\n" "" , ## arg) +#define cifserror(fmt, arg...) \ +do { \ + if (cifsERROR) \ + printk(KERN_ERR "CIFS VFS: " fmt "\n", ##arg); \ +} while (0) -#define cERROR(button, prspec) if (button) cifserror prspec +#define cERROR(set, fmt, arg...) \ +do { \ + if (set) \ + cifserror(fmt, ##arg); \ +} while (0) /* * debug OFF * --------- */ #else /* _CIFS_DEBUG */ -#define cERROR(button, prspec) -#define cEVENT(format, arg...) -#define cFYI(button, prspec) -#define cifserror(format, arg...) +#define cERROR(set, fmt, arg...) +#define cEVENT(fmt, arg...) +#define cFYI(set, fmt, arg...) +#define cifserror(fmt, arg...) #endif /* _CIFS_DEBUG */ #endif /* _H_CIFS_DEBUG */ diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index 78e4d2a..ac19a6f 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c @@ -85,8 +85,8 @@ static char *cifs_get_share_name(const char *node_name) /* find server name end */ pSep = memchr(UNC+2, '\\', len-2); if (!pSep) { - cERROR(1, ("%s: no server name end in node name: %s", - __func__, node_name)); + cERROR(1, "%s: no server name end in node name: %s", + __func__, node_name); kfree(UNC); return ERR_PTR(-EINVAL); } @@ -142,8 +142,8 @@ char *cifs_compose_mount_options(const char *sb_mountdata, rc = dns_resolve_server_name_to_ip(*devname, &srvIP); if (rc != 0) { - cERROR(1, ("%s: Failed to resolve server part of %s to IP: %d", - __func__, *devname, rc)); + cERROR(1, "%s: Failed to resolve server part of %s to IP: %d", + __func__, *devname, rc); goto compose_mount_options_err; } /* md_len = strlen(...) + 12 for 'sep+prefixpath=' @@ -217,8 +217,8 @@ char *cifs_compose_mount_options(const char *sb_mountdata, strcat(mountdata, fullpath + ref->path_consumed); } - /*cFYI(1,("%s: parent mountdata: %s", __func__,sb_mountdata));*/ - /*cFYI(1, ("%s: submount mountdata: %s", __func__, mountdata ));*/ + /*cFYI(1, "%s: parent mountdata: %s", __func__,sb_mountdata);*/ + /*cFYI(1, "%s: submount mountdata: %s", __func__, mountdata );*/ compose_mount_options_out: kfree(srvIP); @@ -294,11 +294,11 @@ static int add_mount_helper(struct vfsmount *newmnt, struct nameidata *nd, static void dump_referral(const struct dfs_info3_param *ref) { - cFYI(1, ("DFS: ref path: %s", ref->path_name)); - cFYI(1, ("DFS: node path: %s", ref->node_name)); - cFYI(1, ("DFS: fl: %hd, srv_type: %hd", ref->flags, ref->server_type)); - cFYI(1, ("DFS: ref_flags: %hd, path_consumed: %hd", ref->ref_flag, - ref->path_consumed)); + cFYI(1, "DFS: ref path: %s", ref->path_name); + cFYI(1, "DFS: node path: %s", ref->node_name); + cFYI(1, "DFS: fl: %hd, srv_type: %hd", ref->flags, ref->server_type); + cFYI(1, "DFS: ref_flags: %hd, path_consumed: %hd", ref->ref_flag, + ref->path_consumed); } @@ -314,7 +314,7 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) int rc = 0; struct vfsmount *mnt = ERR_PTR(-ENOENT); - cFYI(1, ("in %s", __func__)); + cFYI(1, "in %s", __func__); BUG_ON(IS_ROOT(dentry)); xid = GetXid(); @@ -352,15 +352,15 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) /* connect to a node */ len = strlen(referrals[i].node_name); if (len < 2) { - cERROR(1, ("%s: Net Address path too short: %s", - __func__, referrals[i].node_name)); + cERROR(1, "%s: Net Address path too short: %s", + __func__, referrals[i].node_name); rc = -EINVAL; goto out_err; } mnt = cifs_dfs_do_refmount(nd->path.mnt, nd->path.dentry, referrals + i); - cFYI(1, ("%s: cifs_dfs_do_refmount:%s , mnt:%p", __func__, - referrals[i].node_name, mnt)); + cFYI(1, "%s: cifs_dfs_do_refmount:%s , mnt:%p", __func__, + referrals[i].node_name, mnt); /* complete mount procedure if we accured submount */ if (!IS_ERR(mnt)) @@ -378,7 +378,7 @@ out: FreeXid(xid); free_dfs_info_array(referrals, num_referrals); kfree(full_path); - cFYI(1, ("leaving %s" , __func__)); + cFYI(1, "leaving %s" , __func__); return ERR_PTR(rc); out_err: path_put(&nd->path); diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c index 310d12f..c53587b 100644 --- a/fs/cifs/cifs_spnego.c +++ b/fs/cifs/cifs_spnego.c @@ -149,7 +149,7 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo) dp = description + strlen(description); sprintf(dp, ";pid=0x%x", current->pid); - cFYI(1, ("key description = %s", description)); + cFYI(1, "key description = %s", description); spnego_key = request_key(&cifs_spnego_key_type, description, ""); #ifdef CONFIG_CIFS_DEBUG2 diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c index d07676b..430f510 100644 --- a/fs/cifs/cifs_unicode.c +++ b/fs/cifs/cifs_unicode.c @@ -200,9 +200,8 @@ cifs_strtoUCS(__le16 *to, const char *from, int len, /* works for 2.4.0 kernel or later */ charlen = codepage->char2uni(from, len, &wchar_to[i]); if (charlen < 1) { - cERROR(1, - ("strtoUCS: char2uni of %d returned %d", - (int)*from, charlen)); + cERROR(1, "strtoUCS: char2uni of %d returned %d", + (int)*from, charlen); /* A question mark */ to[i] = cpu_to_le16(0x003f); charlen = 1; diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 9b716d0..85d7cf7 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c @@ -87,11 +87,11 @@ int match_sid(struct cifs_sid *ctsid) continue; /* all sub_auth values do not match */ } - cFYI(1, ("matching sid: %s\n", wksidarr[i].sidname)); + cFYI(1, "matching sid: %s\n", wksidarr[i].sidname); return 0; /* sids compare/match */ } - cFYI(1, ("No matching sid")); + cFYI(1, "No matching sid"); return -1; } @@ -208,14 +208,14 @@ static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode, *pbits_to_set &= ~S_IXUGO; return; } else if (type != ACCESS_ALLOWED) { - cERROR(1, ("unknown access control type %d", type)); + cERROR(1, "unknown access control type %d", type); return; } /* else ACCESS_ALLOWED type */ if (flags & GENERIC_ALL) { *pmode |= (S_IRWXUGO & (*pbits_to_set)); - cFYI(DBG2, ("all perms")); + cFYI(DBG2, "all perms"); return; } if ((flags & GENERIC_WRITE) || @@ -228,7 +228,7 @@ static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode, ((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS)) *pmode |= (S_IXUGO & (*pbits_to_set)); - cFYI(DBG2, ("access flags 0x%x mode now 0x%x", flags, *pmode)); + cFYI(DBG2, "access flags 0x%x mode now 0x%x", flags, *pmode); return; } @@ -257,7 +257,7 @@ static void mode_to_access_flags(umode_t mode, umode_t bits_to_use, if (mode & S_IXUGO) *pace_flags |= SET_FILE_EXEC_RIGHTS; - cFYI(DBG2, ("mode: 0x%x, access flags now 0x%x", mode, *pace_flags)); + cFYI(DBG2, "mode: 0x%x, access flags now 0x%x", mode, *pace_flags); return; } @@ -297,24 +297,24 @@ static void dump_ace(struct cifs_ace *pace, char *end_of_acl) /* validate that we do not go past end of acl */ if (le16_to_cpu(pace->size) < 16) { - cERROR(1, ("ACE too small, %d", le16_to_cpu(pace->size))); + cERROR(1, "ACE too small %d", le16_to_cpu(pace->size)); return; } if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) { - cERROR(1, ("ACL too small to parse ACE")); + cERROR(1, "ACL too small to parse ACE"); return; } num_subauth = pace->sid.num_subauth; if (num_subauth) { int i; - cFYI(1, ("ACE revision %d num_auth %d type %d flags %d size %d", + cFYI(1, "ACE revision %d num_auth %d type %d flags %d size %d", pace->sid.revision, pace->sid.num_subauth, pace->type, - pace->flags, le16_to_cpu(pace->size))); + pace->flags, le16_to_cpu(pace->size)); for (i = 0; i < num_subauth; ++i) { - cFYI(1, ("ACE sub_auth[%d]: 0x%x", i, - le32_to_cpu(pace->sid.sub_auth[i]))); + cFYI(1, "ACE sub_auth[%d]: 0x%x", i, + le32_to_cpu(pace->sid.sub_auth[i])); } /* BB add length check to make sure that we do not have huge @@ -347,13 +347,13 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, /* validate that we do not go past end of acl */ if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) { - cERROR(1, ("ACL too small to parse DACL")); + cERROR(1, "ACL too small to parse DACL"); return; } - cFYI(DBG2, ("DACL revision %d size %d num aces %d", + cFYI(DBG2, "DACL revision %d size %d num aces %d", le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size), - le32_to_cpu(pdacl->num_aces))); + le32_to_cpu(pdacl->num_aces)); /* reset rwx permissions for user/group/other. Also, if num_aces is 0 i.e. DACL has no ACEs, @@ -437,25 +437,25 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl) /* validate that we do not go past end of ACL - sid must be at least 8 bytes long (assuming no sub-auths - e.g. the null SID */ if (end_of_acl < (char *)psid + 8) { - cERROR(1, ("ACL too small to parse SID %p", psid)); + cERROR(1, "ACL too small to parse SID %p", psid); return -EINVAL; } if (psid->num_subauth) { #ifdef CONFIG_CIFS_DEBUG2 int i; - cFYI(1, ("SID revision %d num_auth %d", - psid->revision, psid->num_subauth)); + cFYI(1, "SID revision %d num_auth %d", + psid->revision, psid->num_subauth); for (i = 0; i < psid->num_subauth; i++) { - cFYI(1, ("SID sub_auth[%d]: 0x%x ", i, - le32_to_cpu(psid->sub_auth[i]))); + cFYI(1, "SID sub_auth[%d]: 0x%x ", i, + le32_to_cpu(psid->sub_auth[i])); } /* BB add length check to make sure that we do not have huge num auths and therefore go off the end */ - cFYI(1, ("RID 0x%x", - le32_to_cpu(psid->sub_auth[psid->num_subauth-1]))); + cFYI(1, "RID 0x%x", + le32_to_cpu(psid->sub_auth[psid->num_subauth-1])); #endif } @@ -482,11 +482,11 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, le32_to_cpu(pntsd->gsidoffset)); dacloffset = le32_to_cpu(pntsd->dacloffset); dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset); - cFYI(DBG2, ("revision %d type 0x%x ooffset 0x%x goffset 0x%x " + cFYI(DBG2, "revision %d type 0x%x ooffset 0x%x goffset 0x%x " "sacloffset 0x%x dacloffset 0x%x", pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset), le32_to_cpu(pntsd->gsidoffset), - le32_to_cpu(pntsd->sacloffset), dacloffset)); + le32_to_cpu(pntsd->sacloffset), dacloffset); /* cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */ rc = parse_sid(owner_sid_ptr, end_of_acl); if (rc) @@ -500,7 +500,7 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len, parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, group_sid_ptr, fattr); else - cFYI(1, ("no ACL")); /* BB grant all or default perms? */ + cFYI(1, "no ACL"); /* BB grant all or default perms? */ /* cifscred->uid = owner_sid_ptr->rid; cifscred->gid = group_sid_ptr->rid; @@ -563,7 +563,7 @@ static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, FreeXid(xid); - cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen)); + cFYI(1, "GetCIFSACL rc = %d ACL len %d", rc, *pacllen); return pntsd; } @@ -581,12 +581,12 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, &fid, &oplock, NULL, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc) { - cERROR(1, ("Unable to open file to get ACL")); + cERROR(1, "Unable to open file to get ACL"); goto out; } rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, &pntsd, pacllen); - cFYI(1, ("GetCIFSACL rc = %d ACL len %d", rc, *pacllen)); + cFYI(1, "GetCIFSACL rc = %d ACL len %d", rc, *pacllen); CIFSSMBClose(xid, cifs_sb->tcon, fid); out: @@ -621,7 +621,7 @@ static int set_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, __u16 fid, rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen); FreeXid(xid); - cFYI(DBG2, ("SetCIFSACL rc = %d", rc)); + cFYI(DBG2, "SetCIFSACL rc = %d", rc); return rc; } @@ -638,12 +638,12 @@ static int set_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, const char *path, &fid, &oplock, NULL, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc) { - cERROR(1, ("Unable to open file to set ACL")); + cERROR(1, "Unable to open file to set ACL"); goto out; } rc = CIFSSMBSetCIFSACL(xid, cifs_sb->tcon, fid, pnntsd, acllen); - cFYI(DBG2, ("SetCIFSACL rc = %d", rc)); + cFYI(DBG2, "SetCIFSACL rc = %d", rc); CIFSSMBClose(xid, cifs_sb->tcon, fid); out: @@ -659,7 +659,7 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, struct cifsFileInfo *open_file; int rc; - cFYI(DBG2, ("set ACL for %s from mode 0x%x", path, inode->i_mode)); + cFYI(DBG2, "set ACL for %s from mode 0x%x", path, inode->i_mode); open_file = find_readable_file(CIFS_I(inode)); if (!open_file) @@ -679,7 +679,7 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, u32 acllen = 0; int rc = 0; - cFYI(DBG2, ("converting ACL to mode for %s", path)); + cFYI(DBG2, "converting ACL to mode for %s", path); if (pfid) pntsd = get_cifs_acl_by_fid(cifs_sb, *pfid, &acllen); @@ -690,7 +690,7 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, if (pntsd) rc = parse_sec_desc(pntsd, acllen, fattr); if (rc) - cFYI(1, ("parse sec desc failed rc = %d", rc)); + cFYI(1, "parse sec desc failed rc = %d", rc); kfree(pntsd); return; @@ -704,7 +704,7 @@ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode) struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */ struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */ - cFYI(DBG2, ("set ACL from mode for %s", path)); + cFYI(DBG2, "set ACL from mode for %s", path); /* Get the security descriptor */ pntsd = get_cifs_acl(CIFS_SB(inode->i_sb), inode, path, &secdesclen); @@ -721,19 +721,19 @@ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode) DEFSECDESCLEN : secdesclen; pnntsd = kmalloc(secdesclen, GFP_KERNEL); if (!pnntsd) { - cERROR(1, ("Unable to allocate security descriptor")); + cERROR(1, "Unable to allocate security descriptor"); kfree(pntsd); return -ENOMEM; } rc = build_sec_desc(pntsd, pnntsd, inode, nmode); - cFYI(DBG2, ("build_sec_desc rc: %d", rc)); + cFYI(DBG2, "build_sec_desc rc: %d", rc); if (!rc) { /* Set the security descriptor */ rc = set_cifs_acl(pnntsd, secdesclen, inode, path); - cFYI(DBG2, ("set_cifs_acl rc: %d", rc)); + cFYI(DBG2, "set_cifs_acl rc: %d", rc); } kfree(pnntsd); diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index fbe9864..61e4152 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c @@ -103,7 +103,7 @@ static int cifs_calc_signature2(const struct kvec *iov, int n_vec, if (iov[i].iov_len == 0) continue; if (iov[i].iov_base == NULL) { - cERROR(1, ("null iovec entry")); + cERROR(1, "null iovec entry"); return -EIO; } /* The first entry includes a length field (which does not get @@ -181,8 +181,8 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu, /* Do not need to verify session setups with signature "BSRSPYL " */ if (memcmp(cifs_pdu->Signature.SecuritySignature, "BSRSPYL ", 8) == 0) - cFYI(1, ("dummy signature received for smb command 0x%x", - cifs_pdu->Command)); + cFYI(1, "dummy signature received for smb command 0x%x", + cifs_pdu->Command); /* save off the origiginal signature so we can modify the smb and check its signature against what the server sent */ @@ -398,7 +398,7 @@ void setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf, /* calculate buf->ntlmv2_hash */ rc = calc_ntlmv2_hash(ses, nls_cp); if (rc) - cERROR(1, ("could not get v2 hash rc %d", rc)); + cERROR(1, "could not get v2 hash rc %d", rc); CalcNTLMv2_response(ses, resp_buf); /* now calculate the MAC key for NTLMv2 */ diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index ded66be..53e7941 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -128,8 +128,7 @@ cifs_read_super(struct super_block *sb, void *data, if (rc) { if (!silent) - cERROR(1, - ("cifs_mount failed w/return code = %d", rc)); + cERROR(1, "cifs_mount failed w/return code = %d", rc); goto out_mount_failed; } @@ -160,7 +159,7 @@ cifs_read_super(struct super_block *sb, void *data, #ifdef CONFIG_CIFS_EXPERIMENTAL if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { - cFYI(1, ("export ops supported")); + cFYI(1, "export ops supported"); sb->s_export_op = &cifs_export_ops; } #endif /* EXPERIMENTAL */ @@ -168,7 +167,7 @@ cifs_read_super(struct super_block *sb, void *data, return 0; out_no_root: - cERROR(1, ("cifs_read_super: get root inode failed")); + cERROR(1, "cifs_read_super: get root inode failed"); if (inode) iput(inode); @@ -194,10 +193,10 @@ cifs_put_super(struct super_block *sb) int rc = 0; struct cifs_sb_info *cifs_sb; - cFYI(1, ("In cifs_put_super")); + cFYI(1, "In cifs_put_super"); cifs_sb = CIFS_SB(sb); if (cifs_sb == NULL) { - cFYI(1, ("Empty cifs superblock info passed to unmount")); + cFYI(1, "Empty cifs superblock info passed to unmount"); return; } @@ -205,7 +204,7 @@ cifs_put_super(struct super_block *sb) rc = cifs_umount(sb, cifs_sb); if (rc) - cERROR(1, ("cifs_umount failed with return code %d", rc)); + cERROR(1, "cifs_umount failed with return code %d", rc); #ifdef CONFIG_CIFS_DFS_UPCALL if (cifs_sb->mountdata) { kfree(cifs_sb->mountdata); @@ -439,7 +438,7 @@ int cifs_xquota_set(struct super_block *sb, int quota_type, qid_t qid, xid = GetXid(); if (pTcon) { - cFYI(1, ("set type: 0x%x id: %d", quota_type, qid)); + cFYI(1, "set type: 0x%x id: %d", quota_type, qid); } else rc = -EIO; @@ -462,7 +461,7 @@ int cifs_xquota_get(struct super_block *sb, int quota_type, qid_t qid, xid = GetXid(); if (pTcon) { - cFYI(1, ("set type: 0x%x id: %d", quota_type, qid)); + cFYI(1, "set type: 0x%x id: %d", quota_type, qid); } else rc = -EIO; @@ -484,7 +483,7 @@ int cifs_xstate_set(struct super_block *sb, unsigned int flags, int operation) xid = GetXid(); if (pTcon) { - cFYI(1, ("flags: 0x%x operation: 0x%x", flags, operation)); + cFYI(1, "flags: 0x%x operation: 0x%x", flags, operation); } else rc = -EIO; @@ -506,7 +505,7 @@ int cifs_xstate_get(struct super_block *sb, struct fs_quota_stat *qstats) xid = GetXid(); if (pTcon) { - cFYI(1, ("pqstats %p", qstats)); + cFYI(1, "pqstats %p", qstats); } else rc = -EIO; @@ -548,7 +547,7 @@ static void cifs_umount_begin(struct super_block *sb) /* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */ /* cancel_notify_requests(tcon); */ if (tcon->ses && tcon->ses->server) { - cFYI(1, ("wake up tasks now - umount begin not complete")); + cFYI(1, "wake up tasks now - umount begin not complete"); wake_up_all(&tcon->ses->server->request_q); wake_up_all(&tcon->ses->server->response_q); msleep(1); /* yield */ @@ -599,7 +598,7 @@ cifs_get_sb(struct file_system_type *fs_type, int rc; struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL); - cFYI(1, ("Devname: %s flags: %d ", dev_name, flags)); + cFYI(1, "Devname: %s flags: %d ", dev_name, flags); if (IS_ERR(sb)) return PTR_ERR(sb); @@ -868,7 +867,7 @@ cifs_init_request_bufs(void) } else { CIFSMaxBufSize &= 0x1FE00; /* Round size to even 512 byte mult*/ } -/* cERROR(1,("CIFSMaxBufSize %d 0x%x",CIFSMaxBufSize,CIFSMaxBufSize)); */ +/* cERROR(1, "CIFSMaxBufSize %d 0x%x",CIFSMaxBufSize,CIFSMaxBufSize); */ cifs_req_cachep = kmem_cache_create("cifs_request", CIFSMaxBufSize + MAX_CIFS_HDR_SIZE, 0, @@ -880,7 +879,7 @@ cifs_init_request_bufs(void) cifs_min_rcv = 1; else if (cifs_min_rcv > 64) { cifs_min_rcv = 64; - cERROR(1, ("cifs_min_rcv set to maximum (64)")); + cERROR(1, "cifs_min_rcv set to maximum (64)"); } cifs_req_poolp = mempool_create_slab_pool(cifs_min_rcv, @@ -911,7 +910,7 @@ cifs_init_request_bufs(void) cifs_min_small = 2; else if (cifs_min_small > 256) { cifs_min_small = 256; - cFYI(1, ("cifs_min_small set to maximum (256)")); + cFYI(1, "cifs_min_small set to maximum (256)"); } cifs_sm_req_poolp = mempool_create_slab_pool(cifs_min_small, @@ -1009,10 +1008,10 @@ init_cifs(void) if (cifs_max_pending < 2) { cifs_max_pending = 2; - cFYI(1, ("cifs_max_pending set to min of 2")); + cFYI(1, "cifs_max_pending set to min of 2"); } else if (cifs_max_pending > 256) { cifs_max_pending = 256; - cFYI(1, ("cifs_max_pending set to max of 256")); + cFYI(1, "cifs_max_pending set to max of 256"); } rc = cifs_init_inodecache(); @@ -1070,7 +1069,7 @@ init_cifs(void) static void __exit exit_cifs(void) { - cFYI(DBG2, ("exit_cifs")); + cFYI(DBG2, "exit_cifs"); cifs_proc_clean(); #ifdef CONFIG_CIFS_DFS_UPCALL cifs_dfs_release_automount_timer(); diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 39e47f4..32262e1 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -39,8 +39,20 @@ extern int smb_send(struct TCP_Server_Info *, struct smb_hdr *, unsigned int /* length */); extern unsigned int _GetXid(void); extern void _FreeXid(unsigned int); -#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current_fsuid())); -#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__func__,curr_xid,(int)rc));} +#define GetXid() \ +({ \ + int __xid = (int)_GetXid(); \ + cFYI(1, "CIFS VFS: in %s as Xid: %d with uid: %d", \ + __func__, __xid, current_fsuid()); \ + __xid; \ +}) + +#define FreeXid(curr_xid) \ +do { \ + _FreeXid(curr_xid); \ + cFYI(1, "CIFS VFS: leaving %s (xid = %d) rc = %d", \ + __func__, curr_xid, (int)rc); \ +} while (0) extern char *build_path_from_dentry(struct dentry *); extern char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb); extern char *build_wildcard_path_from_dentry(struct dentry *direntry); diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 5d3f29f..be23e42 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -130,8 +130,8 @@ cifs_reconnect_tcon(struct cifsTconInfo *tcon, int smb_command) if (smb_command != SMB_COM_WRITE_ANDX && smb_command != SMB_COM_OPEN_ANDX && smb_command != SMB_COM_TREE_DISCONNECT) { - cFYI(1, ("can not send cmd %d while umounting", - smb_command)); + cFYI(1, "can not send cmd %d while umounting", + smb_command); return -ENODEV; } } @@ -157,7 +157,7 @@ cifs_reconnect_tcon(struct cifsTconInfo *tcon, int smb_command) * back on-line */ if (!tcon->retry || ses->status == CifsExiting) { - cFYI(1, ("gave up waiting on reconnect in smb_init")); + cFYI(1, "gave up waiting on reconnect in smb_init"); return -EHOSTDOWN; } } @@ -184,7 +184,7 @@ cifs_reconnect_tcon(struct cifsTconInfo *tcon, int smb_command) mark_open_files_invalid(tcon); rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage); mutex_unlock(&ses->session_mutex); - cFYI(1, ("reconnect tcon rc = %d", rc)); + cFYI(1, "reconnect tcon rc = %d", rc); if (rc) goto out; @@ -374,7 +374,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) else /* if override flags set only sign/seal OR them with global auth */ secFlags = extended_security | ses->overrideSecFlg; - cFYI(1, ("secFlags 0x%x", secFlags)); + cFYI(1, "secFlags 0x%x", secFlags); pSMB->hdr.Mid = GetNextMid(server); pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS); @@ -382,14 +382,14 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5) pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_KRB5) { - cFYI(1, ("Kerberos only mechanism, enable extended security")); + cFYI(1, "Kerberos only mechanism, enable extended security"); pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; } #ifdef CONFIG_CIFS_EXPERIMENTAL else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP) pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) { - cFYI(1, ("NTLMSSP only mechanism, enable extended security")); + cFYI(1, "NTLMSSP only mechanism, enable extended security"); pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; } #endif @@ -409,7 +409,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) goto neg_err_exit; dialect = le16_to_cpu(pSMBr->DialectIndex); - cFYI(1, ("Dialect: %d", dialect)); + cFYI(1, "Dialect: %d", dialect); /* Check wct = 1 error case */ if ((pSMBr->hdr.WordCount < 13) || (dialect == BAD_PROT)) { /* core returns wct = 1, but we do not ask for core - otherwise @@ -428,8 +428,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) (secFlags & CIFSSEC_MAY_PLNTXT)) server->secType = LANMAN; else { - cERROR(1, ("mount failed weak security disabled" - " in /proc/fs/cifs/SecurityFlags")); + cERROR(1, "mount failed weak security disabled" + " in /proc/fs/cifs/SecurityFlags"); rc = -EOPNOTSUPP; goto neg_err_exit; } @@ -462,9 +462,9 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) utc = CURRENT_TIME; ts = cnvrtDosUnixTm(rsp->SrvTime.Date, rsp->SrvTime.Time, 0); - cFYI(1, ("SrvTime %d sec since 1970 (utc: %d) diff: %d", + cFYI(1, "SrvTime %d sec since 1970 (utc: %d) diff: %d", (int)ts.tv_sec, (int)utc.tv_sec, - (int)(utc.tv_sec - ts.tv_sec))); + (int)(utc.tv_sec - ts.tv_sec)); val = (int)(utc.tv_sec - ts.tv_sec); seconds = abs(val); result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ; @@ -478,7 +478,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) server->timeAdj = (int)tmp; server->timeAdj *= 60; /* also in seconds */ } - cFYI(1, ("server->timeAdj: %d seconds", server->timeAdj)); + cFYI(1, "server->timeAdj: %d seconds", server->timeAdj); /* BB get server time for time conversions and add @@ -512,14 +512,14 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) /* else wct == 17 NTLM */ server->secMode = pSMBr->SecurityMode; if ((server->secMode & SECMODE_USER) == 0) - cFYI(1, ("share mode security")); + cFYI(1, "share mode security"); if ((server->secMode & SECMODE_PW_ENCRYPT) == 0) #ifdef CONFIG_CIFS_WEAK_PW_HASH if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0) #endif /* CIFS_WEAK_PW_HASH */ - cERROR(1, ("Server requests plain text password" - " but client support disabled")); + cERROR(1, "Server requests plain text password" + " but client support disabled"); if ((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2) server->secType = NTLMv2; @@ -539,7 +539,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) #endif */ else { rc = -EOPNOTSUPP; - cERROR(1, ("Invalid security type")); + cERROR(1, "Invalid security type"); goto neg_err_exit; } /* else ... any others ...? */ @@ -551,7 +551,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize), (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); server->max_rw = le32_to_cpu(pSMBr->MaxRawSize); - cFYI(DBG2, ("Max buf = %d", ses->server->maxBuf)); + cFYI(DBG2, "Max buf = %d", ses->server->maxBuf); GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey); server->capabilities = le32_to_cpu(pSMBr->Capabilities); server->timeAdj = (int)(__s16)le16_to_cpu(pSMBr->ServerTimeZone); @@ -582,7 +582,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) if (memcmp(server->server_GUID, pSMBr->u.extended_response. GUID, 16) != 0) { - cFYI(1, ("server UID changed")); + cFYI(1, "server UID changed"); memcpy(server->server_GUID, pSMBr->u.extended_response.GUID, 16); @@ -614,22 +614,21 @@ signing_check: if ((secFlags & CIFSSEC_MAY_SIGN) == 0) { /* MUST_SIGN already includes the MAY_SIGN FLAG so if this is zero it means that signing is disabled */ - cFYI(1, ("Signing disabled")); + cFYI(1, "Signing disabled"); if (server->secMode & SECMODE_SIGN_REQUIRED) { - cERROR(1, ("Server requires " + cERROR(1, "Server requires " "packet signing to be enabled in " - "/proc/fs/cifs/SecurityFlags.")); + "/proc/fs/cifs/SecurityFlags."); rc = -EOPNOTSUPP; } server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED); } else if ((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) { /* signing required */ - cFYI(1, ("Must sign - secFlags 0x%x", secFlags)); + cFYI(1, "Must sign - secFlags 0x%x", secFlags); if ((server->secMode & (SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) { - cERROR(1, - ("signing required but server lacks support")); + cERROR(1, "signing required but server lacks support"); rc = -EOPNOTSUPP; } else server->secMode |= SECMODE_SIGN_REQUIRED; @@ -643,7 +642,7 @@ signing_check: neg_err_exit: cifs_buf_release(pSMB); - cFYI(1, ("negprot rc %d", rc)); + cFYI(1, "negprot rc %d", rc); return rc; } @@ -653,7 +652,7 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon) struct smb_hdr *smb_buffer; int rc = 0; - cFYI(1, ("In tree disconnect")); + cFYI(1, "In tree disconnect"); /* BB: do we need to check this? These should never be NULL. */ if ((tcon->ses == NULL) || (tcon->ses->server == NULL)) @@ -675,7 +674,7 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon) rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0); if (rc) - cFYI(1, ("Tree disconnect failed %d", rc)); + cFYI(1, "Tree disconnect failed %d", rc); /* No need to return error on this operation if tid invalidated and closed on server already e.g. due to tcp session crashing */ @@ -691,7 +690,7 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) LOGOFF_ANDX_REQ *pSMB; int rc = 0; - cFYI(1, ("In SMBLogoff for session disconnect")); + cFYI(1, "In SMBLogoff for session disconnect"); /* * BB: do we need to check validity of ses and server? They should @@ -744,7 +743,7 @@ CIFSPOSIXDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName, int bytes_returned = 0; __u16 params, param_offset, offset, byte_count; - cFYI(1, ("In POSIX delete")); + cFYI(1, "In POSIX delete"); PsxDelete: rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -796,7 +795,7 @@ PsxDelete: rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) - cFYI(1, ("Posix delete returned %d", rc)); + cFYI(1, "Posix delete returned %d", rc); cifs_buf_release(pSMB); cifs_stats_inc(&tcon->num_deletes); @@ -843,7 +842,7 @@ DelFileRetry: (struct smb_hdr *) pSMBr, &bytes_returned, 0); cifs_stats_inc(&tcon->num_deletes); if (rc) - cFYI(1, ("Error in RMFile = %d", rc)); + cFYI(1, "Error in RMFile = %d", rc); cifs_buf_release(pSMB); if (rc == -EAGAIN) @@ -862,7 +861,7 @@ CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName, int bytes_returned; int name_len; - cFYI(1, ("In CIFSSMBRmDir")); + cFYI(1, "In CIFSSMBRmDir"); RmDirRetry: rc = smb_init(SMB_COM_DELETE_DIRECTORY, 0, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -887,7 +886,7 @@ RmDirRetry: (struct smb_hdr *) pSMBr, &bytes_returned, 0); cifs_stats_inc(&tcon->num_rmdirs); if (rc) - cFYI(1, ("Error in RMDir = %d", rc)); + cFYI(1, "Error in RMDir = %d", rc); cifs_buf_release(pSMB); if (rc == -EAGAIN) @@ -905,7 +904,7 @@ CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon, int bytes_returned; int name_len; - cFYI(1, ("In CIFSSMBMkDir")); + cFYI(1, "In CIFSSMBMkDir"); MkDirRetry: rc = smb_init(SMB_COM_CREATE_DIRECTORY, 0, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -930,7 +929,7 @@ MkDirRetry: (struct smb_hdr *) pSMBr, &bytes_returned, 0); cifs_stats_inc(&tcon->num_mkdirs); if (rc) - cFYI(1, ("Error in Mkdir = %d", rc)); + cFYI(1, "Error in Mkdir = %d", rc); cifs_buf_release(pSMB); if (rc == -EAGAIN) @@ -953,7 +952,7 @@ CIFSPOSIXCreate(const int xid, struct cifsTconInfo *tcon, __u32 posix_flags, OPEN_PSX_REQ *pdata; OPEN_PSX_RSP *psx_rsp; - cFYI(1, ("In POSIX Create")); + cFYI(1, "In POSIX Create"); PsxCreat: rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -1007,11 +1006,11 @@ PsxCreat: rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cFYI(1, ("Posix create returned %d", rc)); + cFYI(1, "Posix create returned %d", rc); goto psx_create_err; } - cFYI(1, ("copying inode info")); + cFYI(1, "copying inode info"); rc = validate_t2((struct smb_t2_rsp *)pSMBr); if (rc || (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP))) { @@ -1033,11 +1032,11 @@ PsxCreat: /* check to make sure response data is there */ if (psx_rsp->ReturnedLevel != cpu_to_le16(SMB_QUERY_FILE_UNIX_BASIC)) { pRetData->Type = cpu_to_le32(-1); /* unknown */ - cFYI(DBG2, ("unknown type")); + cFYI(DBG2, "unknown type"); } else { if (pSMBr->ByteCount < sizeof(OPEN_PSX_RSP) + sizeof(FILE_UNIX_BASIC_INFO)) { - cERROR(1, ("Open response data too small")); + cERROR(1, "Open response data too small"); pRetData->Type = cpu_to_le32(-1); goto psx_create_err; } @@ -1084,7 +1083,7 @@ static __u16 convert_disposition(int disposition) ofun = SMBOPEN_OCREATE | SMBOPEN_OTRUNC; break; default: - cFYI(1, ("unknown disposition %d", disposition)); + cFYI(1, "unknown disposition %d", disposition); ofun = SMBOPEN_OAPPEND; /* regular open */ } return ofun; @@ -1175,7 +1174,7 @@ OldOpenRetry: (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP); cifs_stats_inc(&tcon->num_opens); if (rc) { - cFYI(1, ("Error in Open = %d", rc)); + cFYI(1, "Error in Open = %d", rc); } else { /* BB verify if wct == 15 */ @@ -1288,7 +1287,7 @@ openRetry: (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_LONG_OP); cifs_stats_inc(&tcon->num_opens); if (rc) { - cFYI(1, ("Error in Open = %d", rc)); + cFYI(1, "Error in Open = %d", rc); } else { *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */ *netfid = pSMBr->Fid; /* cifs fid stays in le */ @@ -1326,7 +1325,7 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid, int resp_buf_type = 0; struct kvec iov[1]; - cFYI(1, ("Reading %d bytes on fid %d", count, netfid)); + cFYI(1, "Reading %d bytes on fid %d", count, netfid); if (tcon->ses->capabilities & CAP_LARGE_FILES) wct = 12; else { @@ -1371,7 +1370,7 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid, cifs_stats_inc(&tcon->num_reads); pSMBr = (READ_RSP *)iov[0].iov_base; if (rc) { - cERROR(1, ("Send error in read = %d", rc)); + cERROR(1, "Send error in read = %d", rc); } else { int data_length = le16_to_cpu(pSMBr->DataLengthHigh); data_length = data_length << 16; @@ -1381,15 +1380,15 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon, const int netfid, /*check that DataLength would not go beyond end of SMB */ if ((data_length > CIFSMaxBufSize) || (data_length > count)) { - cFYI(1, ("bad length %d for count %d", - data_length, count)); + cFYI(1, "bad length %d for count %d", + data_length, count); rc = -EIO; *nbytes = 0; } else { pReadData = (char *) (&pSMBr->hdr.Protocol) + le16_to_cpu(pSMBr->DataOffset); /* if (rc = copy_to_user(buf, pReadData, data_length)) { - cERROR(1,("Faulting on read rc = %d",rc)); + cERROR(1, "Faulting on read rc = %d",rc); rc = -EFAULT; }*/ /* can not use copy_to_user when using page cache*/ if (*buf) @@ -1433,7 +1432,7 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, *nbytes = 0; - /* cFYI(1, ("write at %lld %d bytes", offset, count));*/ + /* cFYI(1, "write at %lld %d bytes", offset, count);*/ if (tcon->ses == NULL) return -ECONNABORTED; @@ -1551,7 +1550,7 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, *nbytes = 0; - cFYI(1, ("write2 at %lld %d bytes", (long long)offset, count)); + cFYI(1, "write2 at %lld %d bytes", (long long)offset, count); if (tcon->ses->capabilities & CAP_LARGE_FILES) { wct = 14; @@ -1606,7 +1605,7 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, long_op); cifs_stats_inc(&tcon->num_writes); if (rc) { - cFYI(1, ("Send error Write2 = %d", rc)); + cFYI(1, "Send error Write2 = %d", rc); } else if (resp_buf_type == 0) { /* presumably this can not happen, but best to be safe */ rc = -EIO; @@ -1651,7 +1650,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, int timeout = 0; __u16 count; - cFYI(1, ("CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock)); + cFYI(1, "CIFSSMBLock timeout %d numLock %d", (int)waitFlag, numLock); rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB); if (rc) @@ -1699,7 +1698,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, } cifs_stats_inc(&tcon->num_locks); if (rc) - cFYI(1, ("Send error in Lock = %d", rc)); + cFYI(1, "Send error in Lock = %d", rc); /* Note: On -EAGAIN error only caller can retry on handle based calls since file handle passed in no longer valid */ @@ -1722,7 +1721,7 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, __u16 params, param_offset, offset, byte_count, count; struct kvec iov[1]; - cFYI(1, ("Posix Lock")); + cFYI(1, "Posix Lock"); if (pLockData == NULL) return -EINVAL; @@ -1792,7 +1791,7 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, } if (rc) { - cFYI(1, ("Send error in Posix Lock = %d", rc)); + cFYI(1, "Send error in Posix Lock = %d", rc); } else if (get_flag) { /* lock structure can be returned on get */ __u16 data_offset; @@ -1849,7 +1848,7 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id) { int rc = 0; CLOSE_REQ *pSMB = NULL; - cFYI(1, ("In CIFSSMBClose")); + cFYI(1, "In CIFSSMBClose"); /* do not retry on dead session on close */ rc = small_smb_init(SMB_COM_CLOSE, 3, tcon, (void **) &pSMB); @@ -1866,7 +1865,7 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id) if (rc) { if (rc != -EINTR) { /* EINTR is expected when user ctl-c to kill app */ - cERROR(1, ("Send error in Close = %d", rc)); + cERROR(1, "Send error in Close = %d", rc); } } @@ -1882,7 +1881,7 @@ CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, int smb_file_id) { int rc = 0; FLUSH_REQ *pSMB = NULL; - cFYI(1, ("In CIFSSMBFlush")); + cFYI(1, "In CIFSSMBFlush"); rc = small_smb_init(SMB_COM_FLUSH, 1, tcon, (void **) &pSMB); if (rc) @@ -1893,7 +1892,7 @@ CIFSSMBFlush(const int xid, struct cifsTconInfo *tcon, int smb_file_id) rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); cifs_stats_inc(&tcon->num_flushes); if (rc) - cERROR(1, ("Send error in Flush = %d", rc)); + cERROR(1, "Send error in Flush = %d", rc); return rc; } @@ -1910,7 +1909,7 @@ CIFSSMBRename(const int xid, struct cifsTconInfo *tcon, int name_len, name_len2; __u16 count; - cFYI(1, ("In CIFSSMBRename")); + cFYI(1, "In CIFSSMBRename"); renameRetry: rc = smb_init(SMB_COM_RENAME, 1, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -1956,7 +1955,7 @@ renameRetry: (struct smb_hdr *) pSMBr, &bytes_returned, 0); cifs_stats_inc(&tcon->num_renames); if (rc) - cFYI(1, ("Send error in rename = %d", rc)); + cFYI(1, "Send error in rename = %d", rc); cifs_buf_release(pSMB); @@ -1980,7 +1979,7 @@ int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon, int len_of_str; __u16 params, param_offset, offset, count, byte_count; - cFYI(1, ("Rename to File by handle")); + cFYI(1, "Rename to File by handle"); rc = smb_init(SMB_COM_TRANSACTION2, 15, pTcon, (void **) &pSMB, (void **) &pSMBr); if (rc) @@ -2035,7 +2034,7 @@ int CIFSSMBRenameOpenFile(const int xid, struct cifsTconInfo *pTcon, (struct smb_hdr *) pSMBr, &bytes_returned, 0); cifs_stats_inc(&pTcon->num_t2renames); if (rc) - cFYI(1, ("Send error in Rename (by file handle) = %d", rc)); + cFYI(1, "Send error in Rename (by file handle) = %d", rc); cifs_buf_release(pSMB); @@ -2057,7 +2056,7 @@ CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char *fromName, int name_len, name_len2; __u16 count; - cFYI(1, ("In CIFSSMBCopy")); + cFYI(1, "In CIFSSMBCopy"); copyRetry: rc = smb_init(SMB_COM_COPY, 1, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -2102,8 +2101,8 @@ copyRetry: rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cFYI(1, ("Send error in copy = %d with %d files copied", - rc, le16_to_cpu(pSMBr->CopyCount))); + cFYI(1, "Send error in copy = %d with %d files copied", + rc, le16_to_cpu(pSMBr->CopyCount)); } cifs_buf_release(pSMB); @@ -2127,7 +2126,7 @@ CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon, int bytes_returned = 0; __u16 params, param_offset, offset, byte_count; - cFYI(1, ("In Symlink Unix style")); + cFYI(1, "In Symlink Unix style"); createSymLinkRetry: rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -2192,7 +2191,7 @@ createSymLinkRetry: (struct smb_hdr *) pSMBr, &bytes_returned, 0); cifs_stats_inc(&tcon->num_symlinks); if (rc) - cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc)); + cFYI(1, "Send error in SetPathInfo create symlink = %d", rc); cifs_buf_release(pSMB); @@ -2216,7 +2215,7 @@ CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon, int bytes_returned = 0; __u16 params, param_offset, offset, byte_count; - cFYI(1, ("In Create Hard link Unix style")); + cFYI(1, "In Create Hard link Unix style"); createHardLinkRetry: rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -2278,7 +2277,7 @@ createHardLinkRetry: (struct smb_hdr *) pSMBr, &bytes_returned, 0); cifs_stats_inc(&tcon->num_hardlinks); if (rc) - cFYI(1, ("Send error in SetPathInfo (hard link) = %d", rc)); + cFYI(1, "Send error in SetPathInfo (hard link) = %d", rc); cifs_buf_release(pSMB); if (rc == -EAGAIN) @@ -2299,7 +2298,7 @@ CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon, int name_len, name_len2; __u16 count; - cFYI(1, ("In CIFSCreateHardLink")); + cFYI(1, "In CIFSCreateHardLink"); winCreateHardLinkRetry: rc = smb_init(SMB_COM_NT_RENAME, 4, tcon, (void **) &pSMB, @@ -2350,7 +2349,7 @@ winCreateHardLinkRetry: (struct smb_hdr *) pSMBr, &bytes_returned, 0); cifs_stats_inc(&tcon->num_hardlinks); if (rc) - cFYI(1, ("Send error in hard link (NT rename) = %d", rc)); + cFYI(1, "Send error in hard link (NT rename) = %d", rc); cifs_buf_release(pSMB); if (rc == -EAGAIN) @@ -2373,7 +2372,7 @@ CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon, __u16 params, byte_count; char *data_start; - cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName)); + cFYI(1, "In QPathSymLinkInfo (Unix) for path %s", searchName); querySymLinkRetry: rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, @@ -2420,7 +2419,7 @@ querySymLinkRetry: rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cFYI(1, ("Send error in QuerySymLinkInfo = %d", rc)); + cFYI(1, "Send error in QuerySymLinkInfo = %d", rc); } else { /* decode response */ @@ -2521,21 +2520,21 @@ validate_ntransact(char *buf, char **ppparm, char **ppdata, /* should we also check that parm and data areas do not overlap? */ if (*ppparm > end_of_smb) { - cFYI(1, ("parms start after end of smb")); + cFYI(1, "parms start after end of smb"); return -EINVAL; } else if (parm_count + *ppparm > end_of_smb) { - cFYI(1, ("parm end after end of smb")); + cFYI(1, "parm end after end of smb"); return -EINVAL; } else if (*ppdata > end_of_smb) { - cFYI(1, ("data starts after end of smb")); + cFYI(1, "data starts after end of smb"); return -EINVAL; } else if (data_count + *ppdata > end_of_smb) { - cFYI(1, ("data %p + count %d (%p) ends after end of smb %p start %p", + cFYI(1, "data %p + count %d (%p) ends after end of smb %p start %p", *ppdata, data_count, (data_count + *ppdata), - end_of_smb, pSMBr)); + end_of_smb, pSMBr); return -EINVAL; } else if (parm_count + data_count > pSMBr->ByteCount) { - cFYI(1, ("parm count and data count larger than SMB")); + cFYI(1, "parm count and data count larger than SMB"); return -EINVAL; } *pdatalen = data_count; @@ -2554,7 +2553,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, struct smb_com_transaction_ioctl_req *pSMB; struct smb_com_transaction_ioctl_rsp *pSMBr; - cFYI(1, ("In Windows reparse style QueryLink for path %s", searchName)); + cFYI(1, "In Windows reparse style QueryLink for path %s", searchName); rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB, (void **) &pSMBr); if (rc) @@ -2583,7 +2582,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cFYI(1, ("Send error in QueryReparseLinkInfo = %d", rc)); + cFYI(1, "Send error in QueryReparseLinkInfo = %d", rc); } else { /* decode response */ __u32 data_offset = le32_to_cpu(pSMBr->DataOffset); __u32 data_count = le32_to_cpu(pSMBr->DataCount); @@ -2607,7 +2606,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, if ((reparse_buf->LinkNamesBuf + reparse_buf->TargetNameOffset + reparse_buf->TargetNameLen) > end_of_smb) { - cFYI(1, ("reparse buf beyond SMB")); + cFYI(1, "reparse buf beyond SMB"); rc = -EIO; goto qreparse_out; } @@ -2628,12 +2627,12 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon, } } else { rc = -EIO; - cFYI(1, ("Invalid return data count on " - "get reparse info ioctl")); + cFYI(1, "Invalid return data count on " + "get reparse info ioctl"); } symlinkinfo[buflen] = 0; /* just in case so the caller does not go off the end of the buffer */ - cFYI(1, ("readlink result - %s", symlinkinfo)); + cFYI(1, "readlink result - %s", symlinkinfo); } qreparse_out: @@ -2656,7 +2655,7 @@ static void cifs_convert_ace(posix_acl_xattr_entry *ace, ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm); ace->e_tag = cpu_to_le16(cifs_ace->cifs_e_tag); ace->e_id = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid)); - /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */ + /* cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id); */ return; } @@ -2682,8 +2681,8 @@ static int cifs_copy_posix_acl(char *trgt, char *src, const int buflen, size += sizeof(struct cifs_posix_ace) * count; /* check if we would go beyond end of SMB */ if (size_of_data_area < size) { - cFYI(1, ("bad CIFS POSIX ACL size %d vs. %d", - size_of_data_area, size)); + cFYI(1, "bad CIFS POSIX ACL size %d vs. %d", + size_of_data_area, size); return -EINVAL; } } else if (acl_type & ACL_TYPE_DEFAULT) { @@ -2730,7 +2729,7 @@ static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace *cifs_ace, cifs_ace->cifs_uid = cpu_to_le64(-1); } else cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id)); - /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/ + /*cFYI(1, "perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id);*/ return rc; } @@ -2748,12 +2747,12 @@ static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL, return 0; count = posix_acl_xattr_count((size_t)buflen); - cFYI(1, ("setting acl with %d entries from buf of length %d and " + cFYI(1, "setting acl with %d entries from buf of length %d and " "version of %d", - count, buflen, le32_to_cpu(local_acl->a_version))); + count, buflen, le32_to_cpu(local_acl->a_version)); if (le32_to_cpu(local_acl->a_version) != 2) { - cFYI(1, ("unknown POSIX ACL version %d", - le32_to_cpu(local_acl->a_version))); + cFYI(1, "unknown POSIX ACL version %d", + le32_to_cpu(local_acl->a_version)); return 0; } cifs_acl->version = cpu_to_le16(1); @@ -2762,7 +2761,7 @@ static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL, else if (acl_type == ACL_TYPE_DEFAULT) cifs_acl->default_entry_count = cpu_to_le16(count); else { - cFYI(1, ("unknown ACL type %d", acl_type)); + cFYI(1, "unknown ACL type %d", acl_type); return 0; } for (i = 0; i < count; i++) { @@ -2795,7 +2794,7 @@ CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon, int name_len; __u16 params, byte_count; - cFYI(1, ("In GetPosixACL (Unix) for path %s", searchName)); + cFYI(1, "In GetPosixACL (Unix) for path %s", searchName); queryAclRetry: rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, @@ -2847,7 +2846,7 @@ queryAclRetry: (struct smb_hdr *) pSMBr, &bytes_returned, 0); cifs_stats_inc(&tcon->num_acl_get); if (rc) { - cFYI(1, ("Send error in Query POSIX ACL = %d", rc)); + cFYI(1, "Send error in Query POSIX ACL = %d", rc); } else { /* decode response */ @@ -2884,7 +2883,7 @@ CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon, int bytes_returned = 0; __u16 params, byte_count, data_count, param_offset, offset; - cFYI(1, ("In SetPosixACL (Unix) for path %s", fileName)); + cFYI(1, "In SetPosixACL (Unix) for path %s", fileName); setAclRetry: rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -2939,7 +2938,7 @@ setAclRetry: rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) - cFYI(1, ("Set POSIX ACL returned %d", rc)); + cFYI(1, "Set POSIX ACL returned %d", rc); setACLerrorExit: cifs_buf_release(pSMB); @@ -2959,7 +2958,7 @@ CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon, int bytes_returned; __u16 params, byte_count; - cFYI(1, ("In GetExtAttr")); + cFYI(1, "In GetExtAttr"); if (tcon == NULL) return -ENODEV; @@ -2998,7 +2997,7 @@ GetExtAttrRetry: rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cFYI(1, ("error %d in GetExtAttr", rc)); + cFYI(1, "error %d in GetExtAttr", rc); } else { /* decode response */ rc = validate_t2((struct smb_t2_rsp *)pSMBr); @@ -3013,7 +3012,7 @@ GetExtAttrRetry: struct file_chattr_info *pfinfo; /* BB Do we need a cast or hash here ? */ if (count != 16) { - cFYI(1, ("Illegal size ret in GetExtAttr")); + cFYI(1, "Illegal size ret in GetExtAttr"); rc = -EIO; goto GetExtAttrOut; } @@ -3043,7 +3042,7 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, QUERY_SEC_DESC_REQ *pSMB; struct kvec iov[1]; - cFYI(1, ("GetCifsACL")); + cFYI(1, "GetCifsACL"); *pbuflen = 0; *acl_inf = NULL; @@ -3068,7 +3067,7 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, CIFS_STD_OP); cifs_stats_inc(&tcon->num_acl_get); if (rc) { - cFYI(1, ("Send error in QuerySecDesc = %d", rc)); + cFYI(1, "Send error in QuerySecDesc = %d", rc); } else { /* decode response */ __le32 *parm; __u32 parm_len; @@ -3083,7 +3082,7 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, goto qsec_out; pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base; - cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf)); + cFYI(1, "smb %p parm %p data %p", pSMBr, parm, *acl_inf); if (le32_to_cpu(pSMBr->ParameterCount) != 4) { rc = -EIO; /* bad smb */ @@ -3095,8 +3094,8 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, acl_len = le32_to_cpu(*parm); if (acl_len != *pbuflen) { - cERROR(1, ("acl length %d does not match %d", - acl_len, *pbuflen)); + cERROR(1, "acl length %d does not match %d", + acl_len, *pbuflen); if (*pbuflen > acl_len) *pbuflen = acl_len; } @@ -3105,7 +3104,7 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid, header followed by the smallest SID */ if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) || (*pbuflen >= 64 * 1024)) { - cERROR(1, ("bad acl length %d", *pbuflen)); + cERROR(1, "bad acl length %d", *pbuflen); rc = -EINVAL; *pbuflen = 0; } else { @@ -3179,9 +3178,9 @@ setCifsAclRetry: rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); - cFYI(1, ("SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc)); + cFYI(1, "SetCIFSACL bytes_returned: %d, rc: %d", bytes_returned, rc); if (rc) - cFYI(1, ("Set CIFS ACL returned %d", rc)); + cFYI(1, "Set CIFS ACL returned %d", rc); cifs_buf_release(pSMB); if (rc == -EAGAIN) @@ -3205,7 +3204,7 @@ int SMBQueryInformation(const int xid, struct cifsTconInfo *tcon, int bytes_returned; int name_len; - cFYI(1, ("In SMBQPath path %s", searchName)); + cFYI(1, "In SMBQPath path %s", searchName); QInfRetry: rc = smb_init(SMB_COM_QUERY_INFORMATION, 0, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -3231,7 +3230,7 @@ QInfRetry: rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cFYI(1, ("Send error in QueryInfo = %d", rc)); + cFYI(1, "Send error in QueryInfo = %d", rc); } else if (pFinfo) { struct timespec ts; __u32 time = le32_to_cpu(pSMBr->last_write_time); @@ -3343,7 +3342,7 @@ CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, int name_len; __u16 params, byte_count; -/* cFYI(1, ("In QPathInfo path %s", searchName)); */ +/* cFYI(1, "In QPathInfo path %s", searchName); */ QPathInfoRetry: rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -3393,7 +3392,7 @@ QPathInfoRetry: rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cFYI(1, ("Send error in QPathInfo = %d", rc)); + cFYI(1, "Send error in QPathInfo = %d", rc); } else { /* decode response */ rc = validate_t2((struct smb_t2_rsp *)pSMBr); @@ -3512,7 +3511,7 @@ CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon, int name_len; __u16 params, byte_count; - cFYI(1, ("In QPathInfo (Unix) the path %s", searchName)); + cFYI(1, "In QPathInfo (Unix) the path %s", searchName); UnixQPathInfoRetry: rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -3559,14 +3558,14 @@ UnixQPathInfoRetry: rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cFYI(1, ("Send error in QPathInfo = %d", rc)); + cFYI(1, "Send error in QPathInfo = %d", rc); } else { /* decode response */ rc = validate_t2((struct smb_t2_rsp *)pSMBr); if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) { - cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n" + cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n" "Unix Extensions can be disabled on mount " - "by specifying the nosfu mount option.")); + "by specifying the nosfu mount option."); rc = -EIO; /* bad smb */ } else { __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); @@ -3600,7 +3599,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon, int name_len; __u16 params, byte_count; - cFYI(1, ("In FindFirst for %s", searchName)); + cFYI(1, "In FindFirst for %s", searchName); findFirstRetry: rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, @@ -3677,7 +3676,7 @@ findFirstRetry: if (rc) {/* BB add logic to retry regular search if Unix search rejected unexpectedly by server */ /* BB Add code to handle unsupported level rc */ - cFYI(1, ("Error in FindFirst = %d", rc)); + cFYI(1, "Error in FindFirst = %d", rc); cifs_buf_release(pSMB); @@ -3716,7 +3715,7 @@ findFirstRetry: lnoff = le16_to_cpu(parms->LastNameOffset); if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE < lnoff) { - cERROR(1, ("ignoring corrupt resume name")); + cERROR(1, "ignoring corrupt resume name"); psrch_inf->last_entry = NULL; return rc; } @@ -3744,7 +3743,7 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, int bytes_returned, name_len; __u16 params, byte_count; - cFYI(1, ("In FindNext")); + cFYI(1, "In FindNext"); if (psrch_inf->endOfSearch) return -ENOENT; @@ -3808,7 +3807,7 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, cifs_buf_release(pSMB); rc = 0; /* search probably was closed at end of search*/ } else - cFYI(1, ("FindNext returned = %d", rc)); + cFYI(1, "FindNext returned = %d", rc); } else { /* decode response */ rc = validate_t2((struct smb_t2_rsp *)pSMBr); @@ -3844,15 +3843,15 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, lnoff = le16_to_cpu(parms->LastNameOffset); if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE < lnoff) { - cERROR(1, ("ignoring corrupt resume name")); + cERROR(1, "ignoring corrupt resume name"); psrch_inf->last_entry = NULL; return rc; } else psrch_inf->last_entry = psrch_inf->srch_entries_start + lnoff; -/* cFYI(1,("fnxt2 entries in buf %d index_of_last %d", - psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */ +/* cFYI(1, "fnxt2 entries in buf %d index_of_last %d", + psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry); */ /* BB fixme add unlock here */ } @@ -3877,7 +3876,7 @@ CIFSFindClose(const int xid, struct cifsTconInfo *tcon, int rc = 0; FINDCLOSE_REQ *pSMB = NULL; - cFYI(1, ("In CIFSSMBFindClose")); + cFYI(1, "In CIFSSMBFindClose"); rc = small_smb_init(SMB_COM_FIND_CLOSE2, 1, tcon, (void **)&pSMB); /* no sense returning error if session restarted @@ -3891,7 +3890,7 @@ CIFSFindClose(const int xid, struct cifsTconInfo *tcon, pSMB->ByteCount = 0; rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); if (rc) - cERROR(1, ("Send error in FindClose = %d", rc)); + cERROR(1, "Send error in FindClose = %d", rc); cifs_stats_inc(&tcon->num_fclose); @@ -3914,7 +3913,7 @@ CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, int name_len, bytes_returned; __u16 params, byte_count; - cFYI(1, ("In GetSrvInodeNum for %s", searchName)); + cFYI(1, "In GetSrvInodeNum for %s", searchName); if (tcon == NULL) return -ENODEV; @@ -3964,7 +3963,7 @@ GetInodeNumberRetry: rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cFYI(1, ("error %d in QueryInternalInfo", rc)); + cFYI(1, "error %d in QueryInternalInfo", rc); } else { /* decode response */ rc = validate_t2((struct smb_t2_rsp *)pSMBr); @@ -3979,7 +3978,7 @@ GetInodeNumberRetry: struct file_internal_info *pfinfo; /* BB Do we need a cast or hash here ? */ if (count < 8) { - cFYI(1, ("Illegal size ret in QryIntrnlInf")); + cFYI(1, "Illegal size ret in QryIntrnlInf"); rc = -EIO; goto GetInodeNumOut; } @@ -4020,16 +4019,16 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, *num_of_nodes = le16_to_cpu(pSMBr->NumberOfReferrals); if (*num_of_nodes < 1) { - cERROR(1, ("num_referrals: must be at least > 0," - "but we get num_referrals = %d\n", *num_of_nodes)); + cERROR(1, "num_referrals: must be at least > 0," + "but we get num_referrals = %d\n", *num_of_nodes); rc = -EINVAL; goto parse_DFS_referrals_exit; } ref = (struct dfs_referral_level_3 *) &(pSMBr->referrals); if (ref->VersionNumber != cpu_to_le16(3)) { - cERROR(1, ("Referrals of V%d version are not supported," - "should be V3", le16_to_cpu(ref->VersionNumber))); + cERROR(1, "Referrals of V%d version are not supported," + "should be V3", le16_to_cpu(ref->VersionNumber)); rc = -EINVAL; goto parse_DFS_referrals_exit; } @@ -4038,14 +4037,14 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, data_end = (char *)(&(pSMBr->PathConsumed)) + le16_to_cpu(pSMBr->t2.DataCount); - cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n", + cFYI(1, "num_referrals: %d dfs flags: 0x%x ... \n", *num_of_nodes, - le32_to_cpu(pSMBr->DFSFlags))); + le32_to_cpu(pSMBr->DFSFlags)); *target_nodes = kzalloc(sizeof(struct dfs_info3_param) * *num_of_nodes, GFP_KERNEL); if (*target_nodes == NULL) { - cERROR(1, ("Failed to allocate buffer for target_nodes\n")); + cERROR(1, "Failed to allocate buffer for target_nodes\n"); rc = -ENOMEM; goto parse_DFS_referrals_exit; } @@ -4121,7 +4120,7 @@ CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, *num_of_nodes = 0; *target_nodes = NULL; - cFYI(1, ("In GetDFSRefer the path %s", searchName)); + cFYI(1, "In GetDFSRefer the path %s", searchName); if (ses == NULL) return -ENODEV; getDFSRetry: @@ -4188,7 +4187,7 @@ getDFSRetry: rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cFYI(1, ("Send error in GetDFSRefer = %d", rc)); + cFYI(1, "Send error in GetDFSRefer = %d", rc); goto GetDFSRefExit; } rc = validate_t2((struct smb_t2_rsp *)pSMBr); @@ -4199,9 +4198,9 @@ getDFSRetry: goto GetDFSRefExit; } - cFYI(1, ("Decoding GetDFSRefer response BCC: %d Offset %d", + cFYI(1, "Decoding GetDFSRefer response BCC: %d Offset %d", pSMBr->ByteCount, - le16_to_cpu(pSMBr->t2.DataOffset))); + le16_to_cpu(pSMBr->t2.DataOffset)); /* parse returned result into more usable form */ rc = parse_DFS_referrals(pSMBr, num_of_nodes, @@ -4229,7 +4228,7 @@ SMBOldQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData) int bytes_returned = 0; __u16 params, byte_count; - cFYI(1, ("OldQFSInfo")); + cFYI(1, "OldQFSInfo"); oldQFSInfoRetry: rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -4262,7 +4261,7 @@ oldQFSInfoRetry: rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cFYI(1, ("Send error in QFSInfo = %d", rc)); + cFYI(1, "Send error in QFSInfo = %d", rc); } else { /* decode response */ rc = validate_t2((struct smb_t2_rsp *)pSMBr); @@ -4270,8 +4269,8 @@ oldQFSInfoRetry: rc = -EIO; /* bad smb */ else { __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); - cFYI(1, ("qfsinf resp BCC: %d Offset %d", - pSMBr->ByteCount, data_offset)); + cFYI(1, "qfsinf resp BCC: %d Offset %d", + pSMBr->ByteCount, data_offset); response_data = (FILE_SYSTEM_ALLOC_INFO *) (((char *) &pSMBr->hdr.Protocol) + data_offset); @@ -4283,11 +4282,10 @@ oldQFSInfoRetry: le32_to_cpu(response_data->TotalAllocationUnits); FSData->f_bfree = FSData->f_bavail = le32_to_cpu(response_data->FreeAllocationUnits); - cFYI(1, - ("Blocks: %lld Free: %lld Block size %ld", - (unsigned long long)FSData->f_blocks, - (unsigned long long)FSData->f_bfree, - FSData->f_bsize)); + cFYI(1, "Blocks: %lld Free: %lld Block size %ld", + (unsigned long long)FSData->f_blocks, + (unsigned long long)FSData->f_bfree, + FSData->f_bsize); } } cifs_buf_release(pSMB); @@ -4309,7 +4307,7 @@ CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData) int bytes_returned = 0; __u16 params, byte_count; - cFYI(1, ("In QFSInfo")); + cFYI(1, "In QFSInfo"); QFSInfoRetry: rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -4342,7 +4340,7 @@ QFSInfoRetry: rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cFYI(1, ("Send error in QFSInfo = %d", rc)); + cFYI(1, "Send error in QFSInfo = %d", rc); } else { /* decode response */ rc = validate_t2((struct smb_t2_rsp *)pSMBr); @@ -4363,11 +4361,10 @@ QFSInfoRetry: le64_to_cpu(response_data->TotalAllocationUnits); FSData->f_bfree = FSData->f_bavail = le64_to_cpu(response_data->FreeAllocationUnits); - cFYI(1, - ("Blocks: %lld Free: %lld Block size %ld", - (unsigned long long)FSData->f_blocks, - (unsigned long long)FSData->f_bfree, - FSData->f_bsize)); + cFYI(1, "Blocks: %lld Free: %lld Block size %ld", + (unsigned long long)FSData->f_blocks, + (unsigned long long)FSData->f_bfree, + FSData->f_bsize); } } cifs_buf_release(pSMB); @@ -4389,7 +4386,7 @@ CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon) int bytes_returned = 0; __u16 params, byte_count; - cFYI(1, ("In QFSAttributeInfo")); + cFYI(1, "In QFSAttributeInfo"); QFSAttributeRetry: rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -4423,7 +4420,7 @@ QFSAttributeRetry: rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cERROR(1, ("Send error in QFSAttributeInfo = %d", rc)); + cERROR(1, "Send error in QFSAttributeInfo = %d", rc); } else { /* decode response */ rc = validate_t2((struct smb_t2_rsp *)pSMBr); @@ -4459,7 +4456,7 @@ CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon) int bytes_returned = 0; __u16 params, byte_count; - cFYI(1, ("In QFSDeviceInfo")); + cFYI(1, "In QFSDeviceInfo"); QFSDeviceRetry: rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -4494,7 +4491,7 @@ QFSDeviceRetry: rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cFYI(1, ("Send error in QFSDeviceInfo = %d", rc)); + cFYI(1, "Send error in QFSDeviceInfo = %d", rc); } else { /* decode response */ rc = validate_t2((struct smb_t2_rsp *)pSMBr); @@ -4529,7 +4526,7 @@ CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon) int bytes_returned = 0; __u16 params, byte_count; - cFYI(1, ("In QFSUnixInfo")); + cFYI(1, "In QFSUnixInfo"); QFSUnixRetry: rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -4563,7 +4560,7 @@ QFSUnixRetry: rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cERROR(1, ("Send error in QFSUnixInfo = %d", rc)); + cERROR(1, "Send error in QFSUnixInfo = %d", rc); } else { /* decode response */ rc = validate_t2((struct smb_t2_rsp *)pSMBr); @@ -4598,7 +4595,7 @@ CIFSSMBSetFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap) int bytes_returned = 0; __u16 params, param_offset, offset, byte_count; - cFYI(1, ("In SETFSUnixInfo")); + cFYI(1, "In SETFSUnixInfo"); SETFSUnixRetry: /* BB switch to small buf init to save memory */ rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, @@ -4646,7 +4643,7 @@ SETFSUnixRetry: rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cERROR(1, ("Send error in SETFSUnixInfo = %d", rc)); + cERROR(1, "Send error in SETFSUnixInfo = %d", rc); } else { /* decode response */ rc = validate_t2((struct smb_t2_rsp *)pSMBr); if (rc) @@ -4674,7 +4671,7 @@ CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon, int bytes_returned = 0; __u16 params, byte_count; - cFYI(1, ("In QFSPosixInfo")); + cFYI(1, "In QFSPosixInfo"); QFSPosixRetry: rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -4708,7 +4705,7 @@ QFSPosixRetry: rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cFYI(1, ("Send error in QFSUnixInfo = %d", rc)); + cFYI(1, "Send error in QFSUnixInfo = %d", rc); } else { /* decode response */ rc = validate_t2((struct smb_t2_rsp *)pSMBr); @@ -4768,7 +4765,7 @@ CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName, int bytes_returned = 0; __u16 params, byte_count, data_count, param_offset, offset; - cFYI(1, ("In SetEOF")); + cFYI(1, "In SetEOF"); SetEOFRetry: rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -4834,7 +4831,7 @@ SetEOFRetry: rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) - cFYI(1, ("SetPathInfo (file size) returned %d", rc)); + cFYI(1, "SetPathInfo (file size) returned %d", rc); cifs_buf_release(pSMB); @@ -4854,8 +4851,8 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, int rc = 0; __u16 params, param_offset, offset, byte_count, count; - cFYI(1, ("SetFileSize (via SetFileInfo) %lld", - (long long)size)); + cFYI(1, "SetFileSize (via SetFileInfo) %lld", + (long long)size); rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB); if (rc) @@ -4914,9 +4911,7 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, pSMB->ByteCount = cpu_to_le16(byte_count); rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); if (rc) { - cFYI(1, - ("Send error in SetFileInfo (SetFileSize) = %d", - rc)); + cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc); } /* Note: On -EAGAIN error only caller can retry on handle based calls @@ -4940,7 +4935,7 @@ CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon, int rc = 0; __u16 params, param_offset, offset, byte_count, count; - cFYI(1, ("Set Times (via SetFileInfo)")); + cFYI(1, "Set Times (via SetFileInfo)"); rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB); if (rc) @@ -4985,7 +4980,7 @@ CIFSSMBSetFileInfo(const int xid, struct cifsTconInfo *tcon, memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); if (rc) - cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc)); + cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc); /* Note: On -EAGAIN error only caller can retry on handle based calls since file handle passed in no longer valid */ @@ -5002,7 +4997,7 @@ CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon, int rc = 0; __u16 params, param_offset, offset, byte_count, count; - cFYI(1, ("Set File Disposition (via SetFileInfo)")); + cFYI(1, "Set File Disposition (via SetFileInfo)"); rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB); if (rc) @@ -5044,7 +5039,7 @@ CIFSSMBSetFileDisposition(const int xid, struct cifsTconInfo *tcon, *data_offset = delete_file ? 1 : 0; rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); if (rc) - cFYI(1, ("Send error in SetFileDisposition = %d", rc)); + cFYI(1, "Send error in SetFileDisposition = %d", rc); return rc; } @@ -5062,7 +5057,7 @@ CIFSSMBSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *data_offset; __u16 params, param_offset, offset, byte_count, count; - cFYI(1, ("In SetTimes")); + cFYI(1, "In SetTimes"); SetTimesRetry: rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, @@ -5118,7 +5113,7 @@ SetTimesRetry: rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) - cFYI(1, ("SetPathInfo (times) returned %d", rc)); + cFYI(1, "SetPathInfo (times) returned %d", rc); cifs_buf_release(pSMB); @@ -5143,7 +5138,7 @@ CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, char *fileName, int bytes_returned; int name_len; - cFYI(1, ("In SetAttrLegacy")); + cFYI(1, "In SetAttrLegacy"); SetAttrLgcyRetry: rc = smb_init(SMB_COM_SETATTR, 8, tcon, (void **) &pSMB, @@ -5169,7 +5164,7 @@ SetAttrLgcyRetry: rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) - cFYI(1, ("Error in LegacySetAttr = %d", rc)); + cFYI(1, "Error in LegacySetAttr = %d", rc); cifs_buf_release(pSMB); @@ -5231,7 +5226,7 @@ CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon, int rc = 0; u16 params, param_offset, offset, byte_count, count; - cFYI(1, ("Set Unix Info (via SetFileInfo)")); + cFYI(1, "Set Unix Info (via SetFileInfo)"); rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB); if (rc) @@ -5276,7 +5271,7 @@ CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon, rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); if (rc) - cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc)); + cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc); /* Note: On -EAGAIN error only caller can retry on handle based calls since file handle passed in no longer valid */ @@ -5297,7 +5292,7 @@ CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName, FILE_UNIX_BASIC_INFO *data_offset; __u16 params, param_offset, offset, count, byte_count; - cFYI(1, ("In SetUID/GID/Mode")); + cFYI(1, "In SetUID/GID/Mode"); setPermsRetry: rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -5353,7 +5348,7 @@ setPermsRetry: rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) - cFYI(1, ("SetPathInfo (perms) returned %d", rc)); + cFYI(1, "SetPathInfo (perms) returned %d", rc); cifs_buf_release(pSMB); if (rc == -EAGAIN) @@ -5372,7 +5367,7 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, struct dir_notify_req *dnotify_req; int bytes_returned; - cFYI(1, ("In CIFSSMBNotify for file handle %d", (int)netfid)); + cFYI(1, "In CIFSSMBNotify for file handle %d", (int)netfid); rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **) &pSMB, (void **) &pSMBr); if (rc) @@ -5406,7 +5401,7 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, (struct smb_hdr *)pSMBr, &bytes_returned, CIFS_ASYNC_OP); if (rc) { - cFYI(1, ("Error in Notify = %d", rc)); + cFYI(1, "Error in Notify = %d", rc); } else { /* Add file to outstanding requests */ /* BB change to kmem cache alloc */ @@ -5462,7 +5457,7 @@ CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, char *end_of_smb; __u16 params, byte_count, data_offset; - cFYI(1, ("In Query All EAs path %s", searchName)); + cFYI(1, "In Query All EAs path %s", searchName); QAllEAsRetry: rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -5509,7 +5504,7 @@ QAllEAsRetry: rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cFYI(1, ("Send error in QueryAllEAs = %d", rc)); + cFYI(1, "Send error in QueryAllEAs = %d", rc); goto QAllEAsOut; } @@ -5537,16 +5532,16 @@ QAllEAsRetry: (((char *) &pSMBr->hdr.Protocol) + data_offset); list_len = le32_to_cpu(ea_response_data->list_len); - cFYI(1, ("ea length %d", list_len)); + cFYI(1, "ea length %d", list_len); if (list_len <= 8) { - cFYI(1, ("empty EA list returned from server")); + cFYI(1, "empty EA list returned from server"); goto QAllEAsOut; } /* make sure list_len doesn't go past end of SMB */ end_of_smb = (char *)pByteArea(&pSMBr->hdr) + BCC(&pSMBr->hdr); if ((char *)ea_response_data + list_len > end_of_smb) { - cFYI(1, ("EA list appears to go beyond SMB")); + cFYI(1, "EA list appears to go beyond SMB"); rc = -EIO; goto QAllEAsOut; } @@ -5563,7 +5558,7 @@ QAllEAsRetry: temp_ptr += 4; /* make sure we can read name_len and value_len */ if (list_len < 0) { - cFYI(1, ("EA entry goes beyond length of list")); + cFYI(1, "EA entry goes beyond length of list"); rc = -EIO; goto QAllEAsOut; } @@ -5572,7 +5567,7 @@ QAllEAsRetry: value_len = le16_to_cpu(temp_fea->value_len); list_len -= name_len + 1 + value_len; if (list_len < 0) { - cFYI(1, ("EA entry goes beyond length of list")); + cFYI(1, "EA entry goes beyond length of list"); rc = -EIO; goto QAllEAsOut; } @@ -5639,7 +5634,7 @@ CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName, int bytes_returned = 0; __u16 params, param_offset, byte_count, offset, count; - cFYI(1, ("In SetEA")); + cFYI(1, "In SetEA"); SetEARetry: rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, (void **) &pSMBr); @@ -5721,7 +5716,7 @@ SetEARetry: rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) - cFYI(1, ("SetPathInfo (EA) returned %d", rc)); + cFYI(1, "SetPathInfo (EA) returned %d", rc); cifs_buf_release(pSMB); diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index d9566bf..58a2109 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -135,7 +135,7 @@ cifs_reconnect(struct TCP_Server_Info *server) spin_unlock(&GlobalMid_Lock); server->maxBuf = 0; - cFYI(1, ("Reconnecting tcp session")); + cFYI(1, "Reconnecting tcp session"); /* before reconnecting the tcp session, mark the smb session (uid) and the tid bad so they are not used until reconnected */ @@ -153,12 +153,12 @@ cifs_reconnect(struct TCP_Server_Info *server) /* do not want to be sending data on a socket we are freeing */ mutex_lock(&server->srv_mutex); if (server->ssocket) { - cFYI(1, ("State: 0x%x Flags: 0x%lx", server->ssocket->state, - server->ssocket->flags)); + cFYI(1, "State: 0x%x Flags: 0x%lx", server->ssocket->state, + server->ssocket->flags); kernel_sock_shutdown(server->ssocket, SHUT_WR); - cFYI(1, ("Post shutdown state: 0x%x Flags: 0x%lx", + cFYI(1, "Post shutdown state: 0x%x Flags: 0x%lx", server->ssocket->state, - server->ssocket->flags)); + server->ssocket->flags); sock_release(server->ssocket); server->ssocket = NULL; } @@ -187,7 +187,7 @@ cifs_reconnect(struct TCP_Server_Info *server) else rc = ipv4_connect(server); if (rc) { - cFYI(1, ("reconnect error %d", rc)); + cFYI(1, "reconnect error %d", rc); msleep(3000); } else { atomic_inc(&tcpSesReconnectCount); @@ -223,7 +223,7 @@ static int check2ndT2(struct smb_hdr *pSMB, unsigned int maxBufSize) /* check for plausible wct, bcc and t2 data and parm sizes */ /* check for parm and data offset going beyond end of smb */ if (pSMB->WordCount != 10) { /* coalesce_t2 depends on this */ - cFYI(1, ("invalid transact2 word count")); + cFYI(1, "invalid transact2 word count"); return -EINVAL; } @@ -237,15 +237,15 @@ static int check2ndT2(struct smb_hdr *pSMB, unsigned int maxBufSize) if (remaining == 0) return 0; else if (remaining < 0) { - cFYI(1, ("total data %d smaller than data in frame %d", - total_data_size, data_in_this_rsp)); + cFYI(1, "total data %d smaller than data in frame %d", + total_data_size, data_in_this_rsp); return -EINVAL; } else { - cFYI(1, ("missing %d bytes from transact2, check next response", - remaining)); + cFYI(1, "missing %d bytes from transact2, check next response", + remaining); if (total_data_size > maxBufSize) { - cERROR(1, ("TotalDataSize %d is over maximum buffer %d", - total_data_size, maxBufSize)); + cERROR(1, "TotalDataSize %d is over maximum buffer %d", + total_data_size, maxBufSize); return -EINVAL; } return remaining; @@ -267,7 +267,7 @@ static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB) total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount); if (total_data_size != le16_to_cpu(pSMB2->t2_rsp.TotalDataCount)) { - cFYI(1, ("total data size of primary and secondary t2 differ")); + cFYI(1, "total data size of primary and secondary t2 differ"); } total_in_buf = le16_to_cpu(pSMBt->t2_rsp.DataCount); @@ -282,7 +282,7 @@ static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB) total_in_buf2 = le16_to_cpu(pSMB2->t2_rsp.DataCount); if (remaining < total_in_buf2) { - cFYI(1, ("transact2 2nd response contains too much data")); + cFYI(1, "transact2 2nd response contains too much data"); } /* find end of first SMB data area */ @@ -311,7 +311,7 @@ static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB) pTargetSMB->smb_buf_length = byte_count; if (remaining == total_in_buf2) { - cFYI(1, ("found the last secondary response")); + cFYI(1, "found the last secondary response"); return 0; /* we are done */ } else /* more responses to go */ return 1; @@ -339,7 +339,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) int reconnect; current->flags |= PF_MEMALLOC; - cFYI(1, ("Demultiplex PID: %d", task_pid_nr(current))); + cFYI(1, "Demultiplex PID: %d", task_pid_nr(current)); length = atomic_inc_return(&tcpSesAllocCount); if (length > 1) @@ -353,7 +353,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) if (bigbuf == NULL) { bigbuf = cifs_buf_get(); if (!bigbuf) { - cERROR(1, ("No memory for large SMB response")); + cERROR(1, "No memory for large SMB response"); msleep(3000); /* retry will check if exiting */ continue; @@ -366,7 +366,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) if (smallbuf == NULL) { smallbuf = cifs_small_buf_get(); if (!smallbuf) { - cERROR(1, ("No memory for SMB response")); + cERROR(1, "No memory for SMB response"); msleep(1000); /* retry will check if exiting */ continue; @@ -391,9 +391,9 @@ incomplete_rcv: if (server->tcpStatus == CifsExiting) { break; } else if (server->tcpStatus == CifsNeedReconnect) { - cFYI(1, ("Reconnect after server stopped responding")); + cFYI(1, "Reconnect after server stopped responding"); cifs_reconnect(server); - cFYI(1, ("call to reconnect done")); + cFYI(1, "call to reconnect done"); csocket = server->ssocket; continue; } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) { @@ -411,7 +411,7 @@ incomplete_rcv: continue; } else if (length <= 0) { if (server->tcpStatus == CifsNew) { - cFYI(1, ("tcp session abend after SMBnegprot")); + cFYI(1, "tcp session abend after SMBnegprot"); /* some servers kill the TCP session rather than returning an SMB negprot error, in which case reconnecting here is not going to help, @@ -419,18 +419,18 @@ incomplete_rcv: break; } if (!try_to_freeze() && (length == -EINTR)) { - cFYI(1, ("cifsd thread killed")); + cFYI(1, "cifsd thread killed"); break; } - cFYI(1, ("Reconnect after unexpected peek error %d", - length)); + cFYI(1, "Reconnect after unexpected peek error %d", + length); cifs_reconnect(server); csocket = server->ssocket; wake_up(&server->response_q); continue; } else if (length < pdu_length) { - cFYI(1, ("requested %d bytes but only got %d bytes", - pdu_length, length)); + cFYI(1, "requested %d bytes but only got %d bytes", + pdu_length, length); pdu_length -= length; msleep(1); goto incomplete_rcv; @@ -450,18 +450,18 @@ incomplete_rcv: pdu_length = be32_to_cpu((__force __be32)smb_buffer->smb_buf_length); smb_buffer->smb_buf_length = pdu_length; - cFYI(1, ("rfc1002 length 0x%x", pdu_length+4)); + cFYI(1, "rfc1002 length 0x%x", pdu_length+4); if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) { continue; } else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) { - cFYI(1, ("Good RFC 1002 session rsp")); + cFYI(1, "Good RFC 1002 session rsp"); continue; } else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) { /* we get this from Windows 98 instead of an error on SMB negprot response */ - cFYI(1, ("Negative RFC1002 Session Response Error 0x%x)", - pdu_length)); + cFYI(1, "Negative RFC1002 Session Response Error 0x%x)", + pdu_length); if (server->tcpStatus == CifsNew) { /* if nack on negprot (rather than ret of smb negprot error) reconnecting @@ -484,7 +484,7 @@ incomplete_rcv: continue; } } else if (temp != (char) 0) { - cERROR(1, ("Unknown RFC 1002 frame")); + cERROR(1, "Unknown RFC 1002 frame"); cifs_dump_mem(" Received Data: ", (char *)smb_buffer, length); cifs_reconnect(server); @@ -495,8 +495,8 @@ incomplete_rcv: /* else we have an SMB response */ if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) || (pdu_length < sizeof(struct smb_hdr) - 1 - 4)) { - cERROR(1, ("Invalid size SMB length %d pdu_length %d", - length, pdu_length+4)); + cERROR(1, "Invalid size SMB length %d pdu_length %d", + length, pdu_length+4); cifs_reconnect(server); csocket = server->ssocket; wake_up(&server->response_q); @@ -539,8 +539,8 @@ incomplete_rcv: length = 0; continue; } else if (length <= 0) { - cERROR(1, ("Received no data, expecting %d", - pdu_length - total_read)); + cERROR(1, "Received no data, expecting %d", + pdu_length - total_read); cifs_reconnect(server); csocket = server->ssocket; reconnect = 1; @@ -588,7 +588,7 @@ incomplete_rcv: } } else { if (!isLargeBuf) { - cERROR(1,("1st trans2 resp needs bigbuf")); + cERROR(1, "1st trans2 resp needs bigbuf"); /* BB maybe we can fix this up, switch to already allocated large buffer? */ } else { @@ -630,8 +630,8 @@ multi_t2_fnd: wake_up_process(task_to_wake); } else if (!is_valid_oplock_break(smb_buffer, server) && !isMultiRsp) { - cERROR(1, ("No task to wake, unknown frame received! " - "NumMids %d", midCount.counter)); + cERROR(1, "No task to wake, unknown frame received! " + "NumMids %d", midCount.counter); cifs_dump_mem("Received Data is: ", (char *)smb_buffer, sizeof(struct smb_hdr)); #ifdef CONFIG_CIFS_DEBUG2 @@ -708,8 +708,8 @@ multi_t2_fnd: list_for_each(tmp, &server->pending_mid_q) { mid_entry = list_entry(tmp, struct mid_q_entry, qhead); if (mid_entry->midState == MID_REQUEST_SUBMITTED) { - cFYI(1, ("Clearing Mid 0x%x - waking up ", - mid_entry->mid)); + cFYI(1, "Clearing Mid 0x%x - waking up ", + mid_entry->mid); task_to_wake = mid_entry->tsk; if (task_to_wake) wake_up_process(task_to_wake); @@ -728,7 +728,7 @@ multi_t2_fnd: to wait at least 45 seconds before giving up on a request getting a response and going ahead and killing cifsd */ - cFYI(1, ("Wait for exit from demultiplex thread")); + cFYI(1, "Wait for exit from demultiplex thread"); msleep(46000); /* if threads still have not exited they are probably never coming home not much else we can do but free the memory */ @@ -849,7 +849,7 @@ cifs_parse_mount_options(char *options, const char *devname, separator[0] = options[4]; options += 5; } else { - cFYI(1, ("Null separator not allowed")); + cFYI(1, "Null separator not allowed"); } } @@ -974,7 +974,7 @@ cifs_parse_mount_options(char *options, const char *devname, } } else if (strnicmp(data, "sec", 3) == 0) { if (!value || !*value) { - cERROR(1, ("no security value specified")); + cERROR(1, "no security value specified"); continue; } else if (strnicmp(value, "krb5i", 5) == 0) { vol->secFlg |= CIFSSEC_MAY_KRB5 | @@ -982,7 +982,7 @@ cifs_parse_mount_options(char *options, const char *devname, } else if (strnicmp(value, "krb5p", 5) == 0) { /* vol->secFlg |= CIFSSEC_MUST_SEAL | CIFSSEC_MAY_KRB5; */ - cERROR(1, ("Krb5 cifs privacy not supported")); + cERROR(1, "Krb5 cifs privacy not supported"); return 1; } else if (strnicmp(value, "krb5", 4) == 0) { vol->secFlg |= CIFSSEC_MAY_KRB5; @@ -1014,7 +1014,7 @@ cifs_parse_mount_options(char *options, const char *devname, } else if (strnicmp(value, "none", 4) == 0) { vol->nullauth = 1; } else { - cERROR(1, ("bad security option: %s", value)); + cERROR(1, "bad security option: %s", value); return 1; } } else if ((strnicmp(data, "unc", 3) == 0) @@ -1053,7 +1053,7 @@ cifs_parse_mount_options(char *options, const char *devname, a domain name and need special handling? */ if (strnlen(value, 256) < 256) { vol->domainname = value; - cFYI(1, ("Domain name set")); + cFYI(1, "Domain name set"); } else { printk(KERN_WARNING "CIFS: domain name too " "long\n"); @@ -1076,7 +1076,7 @@ cifs_parse_mount_options(char *options, const char *devname, strcpy(vol->prepath+1, value); } else strcpy(vol->prepath, value); - cFYI(1, ("prefix path %s", vol->prepath)); + cFYI(1, "prefix path %s", vol->prepath); } else { printk(KERN_WARNING "CIFS: prefix too long\n"); return 1; @@ -1092,7 +1092,7 @@ cifs_parse_mount_options(char *options, const char *devname, vol->iocharset = value; /* if iocharset not set then load_nls_default is used by caller */ - cFYI(1, ("iocharset set to %s", value)); + cFYI(1, "iocharset set to %s", value); } else { printk(KERN_WARNING "CIFS: iocharset name " "too long.\n"); @@ -1144,14 +1144,14 @@ cifs_parse_mount_options(char *options, const char *devname, } } else if (strnicmp(data, "sockopt", 5) == 0) { if (!value || !*value) { - cERROR(1, ("no socket option specified")); + cERROR(1, "no socket option specified"); continue; } else if (strnicmp(value, "TCP_NODELAY", 11) == 0) { vol->sockopt_tcp_nodelay = 1; } } else if (strnicmp(data, "netbiosname", 4) == 0) { if (!value || !*value || (*value == ' ')) { - cFYI(1, ("invalid (empty) netbiosname")); + cFYI(1, "invalid (empty) netbiosname"); } else { memset(vol->source_rfc1001_name, 0x20, 15); for (i = 0; i < 15; i++) { @@ -1175,7 +1175,7 @@ cifs_parse_mount_options(char *options, const char *devname, } else if (strnicmp(data, "servern", 7) == 0) { /* servernetbiosname specified override *SMBSERVER */ if (!value || !*value || (*value == ' ')) { - cFYI(1, ("empty server netbiosname specified")); + cFYI(1, "empty server netbiosname specified"); } else { /* last byte, type, is 0x20 for servr type */ memset(vol->target_rfc1001_name, 0x20, 16); @@ -1434,7 +1434,7 @@ cifs_find_tcp_session(struct sockaddr_storage *addr, unsigned short int port) ++server->srv_count; write_unlock(&cifs_tcp_ses_lock); - cFYI(1, ("Existing tcp session with server found")); + cFYI(1, "Existing tcp session with server found"); return server; } write_unlock(&cifs_tcp_ses_lock); @@ -1475,7 +1475,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info) memset(&addr, 0, sizeof(struct sockaddr_storage)); - cFYI(1, ("UNC: %s ip: %s", volume_info->UNC, volume_info->UNCip)); + cFYI(1, "UNC: %s ip: %s", volume_info->UNC, volume_info->UNCip); if (volume_info->UNCip && volume_info->UNC) { rc = cifs_convert_address(volume_info->UNCip, &addr); @@ -1487,13 +1487,12 @@ cifs_get_tcp_session(struct smb_vol *volume_info) } else if (volume_info->UNCip) { /* BB using ip addr as tcp_ses name to connect to the DFS root below */ - cERROR(1, ("Connecting to DFS root not implemented yet")); + cERROR(1, "Connecting to DFS root not implemented yet"); rc = -EINVAL; goto out_err; } else /* which tcp_sess DFS root would we conect to */ { - cERROR(1, - ("CIFS mount error: No UNC path (e.g. -o " - "unc=//192.168.1.100/public) specified")); + cERROR(1, "CIFS mount error: No UNC path (e.g. -o " + "unc=//192.168.1.100/public) specified"); rc = -EINVAL; goto out_err; } @@ -1540,7 +1539,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info) ++tcp_ses->srv_count; if (addr.ss_family == AF_INET6) { - cFYI(1, ("attempting ipv6 connect")); + cFYI(1, "attempting ipv6 connect"); /* BB should we allow ipv6 on port 139? */ /* other OS never observed in Wild doing 139 with v6 */ sin_server6->sin6_port = htons(volume_info->port); @@ -1554,7 +1553,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info) rc = ipv4_connect(tcp_ses); } if (rc < 0) { - cERROR(1, ("Error connecting to socket. Aborting operation")); + cERROR(1, "Error connecting to socket. Aborting operation"); goto out_err; } @@ -1567,7 +1566,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info) tcp_ses, "cifsd"); if (IS_ERR(tcp_ses->tsk)) { rc = PTR_ERR(tcp_ses->tsk); - cERROR(1, ("error %d create cifsd thread", rc)); + cERROR(1, "error %d create cifsd thread", rc); module_put(THIS_MODULE); goto out_err; } @@ -1703,8 +1702,7 @@ get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path, strcpy(temp_unc + 2, pSesInfo->serverName); strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$"); rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage); - cFYI(1, - ("CIFS Tcon rc = %d ipc_tid = %d", rc, pSesInfo->ipc_tid)); + cFYI(1, "CIFS Tcon rc = %d ipc_tid = %d", rc, pSesInfo->ipc_tid); kfree(temp_unc); } if (rc == 0) @@ -1777,12 +1775,12 @@ ipv4_connect(struct TCP_Server_Info *server) rc = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &socket); if (rc < 0) { - cERROR(1, ("Error %d creating socket", rc)); + cERROR(1, "Error %d creating socket", rc); return rc; } /* BB other socket options to set KEEPALIVE, NODELAY? */ - cFYI(1, ("Socket created")); + cFYI(1, "Socket created"); server->ssocket = socket; socket->sk->sk_allocation = GFP_NOFS; cifs_reclassify_socket4(socket); @@ -1827,7 +1825,7 @@ ipv4_connect(struct TCP_Server_Info *server) if (!connected) { if (orig_port) server->addr.sockAddr.sin_port = orig_port; - cFYI(1, ("Error %d connecting to server via ipv4", rc)); + cFYI(1, "Error %d connecting to server via ipv4", rc); sock_release(socket); server->ssocket = NULL; return rc; @@ -1855,12 +1853,12 @@ ipv4_connect(struct TCP_Server_Info *server) rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY, (char *)&val, sizeof(val)); if (rc) - cFYI(1, ("set TCP_NODELAY socket option error %d", rc)); + cFYI(1, "set TCP_NODELAY socket option error %d", rc); } - cFYI(1, ("sndbuf %d rcvbuf %d rcvtimeo 0x%lx", + cFYI(1, "sndbuf %d rcvbuf %d rcvtimeo 0x%lx", socket->sk->sk_sndbuf, - socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo)); + socket->sk->sk_rcvbuf, socket->sk->sk_rcvtimeo); /* send RFC1001 sessinit */ if (server->addr.sockAddr.sin_port == htons(RFC1001_PORT)) { @@ -1938,13 +1936,13 @@ ipv6_connect(struct TCP_Server_Info *server) rc = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, &socket); if (rc < 0) { - cERROR(1, ("Error %d creating ipv6 socket", rc)); + cERROR(1, "Error %d creating ipv6 socket", rc); socket = NULL; return rc; } /* BB other socket options to set KEEPALIVE, NODELAY? */ - cFYI(1, ("ipv6 Socket created")); + cFYI(1, "ipv6 Socket created"); server->ssocket = socket; socket->sk->sk_allocation = GFP_NOFS; cifs_reclassify_socket6(socket); @@ -1988,7 +1986,7 @@ ipv6_connect(struct TCP_Server_Info *server) if (!connected) { if (orig_port) server->addr.sockAddr6.sin6_port = orig_port; - cFYI(1, ("Error %d connecting to server via ipv6", rc)); + cFYI(1, "Error %d connecting to server via ipv6", rc); sock_release(socket); server->ssocket = NULL; return rc; @@ -2007,7 +2005,7 @@ ipv6_connect(struct TCP_Server_Info *server) rc = kernel_setsockopt(socket, SOL_TCP, TCP_NODELAY, (char *)&val, sizeof(val)); if (rc) - cFYI(1, ("set TCP_NODELAY socket option error %d", rc)); + cFYI(1, "set TCP_NODELAY socket option error %d", rc); } server->ssocket = socket; @@ -2032,13 +2030,13 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon, if (vol_info && vol_info->no_linux_ext) { tcon->fsUnixInfo.Capability = 0; tcon->unix_ext = 0; /* Unix Extensions disabled */ - cFYI(1, ("Linux protocol extensions disabled")); + cFYI(1, "Linux protocol extensions disabled"); return; } else if (vol_info) tcon->unix_ext = 1; /* Unix Extensions supported */ if (tcon->unix_ext == 0) { - cFYI(1, ("Unix extensions disabled so not set on reconnect")); + cFYI(1, "Unix extensions disabled so not set on reconnect"); return; } @@ -2054,12 +2052,11 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon, cap &= ~CIFS_UNIX_POSIX_ACL_CAP; if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) { if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) - cERROR(1, ("POSIXPATH support change")); + cERROR(1, "POSIXPATH support change"); cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP; } else if ((cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0) { - cERROR(1, ("possible reconnect error")); - cERROR(1, - ("server disabled POSIX path support")); + cERROR(1, "possible reconnect error"); + cERROR(1, "server disabled POSIX path support"); } } @@ -2067,7 +2064,7 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon, if (vol_info && vol_info->no_psx_acl) cap &= ~CIFS_UNIX_POSIX_ACL_CAP; else if (CIFS_UNIX_POSIX_ACL_CAP & cap) { - cFYI(1, ("negotiated posix acl support")); + cFYI(1, "negotiated posix acl support"); if (sb) sb->s_flags |= MS_POSIXACL; } @@ -2075,7 +2072,7 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon, if (vol_info && vol_info->posix_paths == 0) cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP; else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) { - cFYI(1, ("negotiate posix pathnames")); + cFYI(1, "negotiate posix pathnames"); if (sb) CIFS_SB(sb)->mnt_cifs_flags |= CIFS_MOUNT_POSIX_PATHS; @@ -2090,39 +2087,38 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon, if (sb && (CIFS_SB(sb)->rsize > 127 * 1024)) { if ((cap & CIFS_UNIX_LARGE_READ_CAP) == 0) { CIFS_SB(sb)->rsize = 127 * 1024; - cFYI(DBG2, - ("larger reads not supported by srv")); + cFYI(DBG2, "larger reads not supported by srv"); } } - cFYI(1, ("Negotiate caps 0x%x", (int)cap)); + cFYI(1, "Negotiate caps 0x%x", (int)cap); #ifdef CONFIG_CIFS_DEBUG2 if (cap & CIFS_UNIX_FCNTL_CAP) - cFYI(1, ("FCNTL cap")); + cFYI(1, "FCNTL cap"); if (cap & CIFS_UNIX_EXTATTR_CAP) - cFYI(1, ("EXTATTR cap")); + cFYI(1, "EXTATTR cap"); if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) - cFYI(1, ("POSIX path cap")); + cFYI(1, "POSIX path cap"); if (cap & CIFS_UNIX_XATTR_CAP) - cFYI(1, ("XATTR cap")); + cFYI(1, "XATTR cap"); if (cap & CIFS_UNIX_POSIX_ACL_CAP) - cFYI(1, ("POSIX ACL cap")); + cFYI(1, "POSIX ACL cap"); if (cap & CIFS_UNIX_LARGE_READ_CAP) - cFYI(1, ("very large read cap")); + cFYI(1, "very large read cap"); if (cap & CIFS_UNIX_LARGE_WRITE_CAP) - cFYI(1, ("very large write cap")); + cFYI(1, "very large write cap"); #endif /* CIFS_DEBUG2 */ if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) { if (vol_info == NULL) { - cFYI(1, ("resetting capabilities failed")); + cFYI(1, "resetting capabilities failed"); } else - cERROR(1, ("Negotiating Unix capabilities " + cERROR(1, "Negotiating Unix capabilities " "with the server failed. Consider " "mounting with the Unix Extensions\n" "disabled, if problems are found, " "by specifying the nounix mount " - "option.")); + "option."); } } @@ -2152,8 +2148,8 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info, struct cifs_sb_info *cifs_sb) { if (pvolume_info->rsize > CIFSMaxBufSize) { - cERROR(1, ("rsize %d too large, using MaxBufSize", - pvolume_info->rsize)); + cERROR(1, "rsize %d too large, using MaxBufSize", + pvolume_info->rsize); cifs_sb->rsize = CIFSMaxBufSize; } else if ((pvolume_info->rsize) && (pvolume_info->rsize <= CIFSMaxBufSize)) @@ -2162,8 +2158,8 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info, cifs_sb->rsize = CIFSMaxBufSize; if (pvolume_info->wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) { - cERROR(1, ("wsize %d too large, using 4096 instead", - pvolume_info->wsize)); + cERROR(1, "wsize %d too large, using 4096 instead", + pvolume_info->wsize); cifs_sb->wsize = 4096; } else if (pvolume_info->wsize) cifs_sb->wsize = pvolume_info->wsize; @@ -2181,7 +2177,7 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info, if (cifs_sb->rsize < 2048) { cifs_sb->rsize = 2048; /* Windows ME may prefer this */ - cFYI(1, ("readsize set to minimum: 2048")); + cFYI(1, "readsize set to minimum: 2048"); } /* calculate prepath */ cifs_sb->prepath = pvolume_info->prepath; @@ -2199,8 +2195,8 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info, cifs_sb->mnt_gid = pvolume_info->linux_gid; cifs_sb->mnt_file_mode = pvolume_info->file_mode; cifs_sb->mnt_dir_mode = pvolume_info->dir_mode; - cFYI(1, ("file mode: 0x%x dir mode: 0x%x", - cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode)); + cFYI(1, "file mode: 0x%x dir mode: 0x%x", + cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode); if (pvolume_info->noperm) cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_PERM; @@ -2229,13 +2225,13 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info, if (pvolume_info->dynperm) cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM; if (pvolume_info->direct_io) { - cFYI(1, ("mounting share using direct i/o")); + cFYI(1, "mounting share using direct i/o"); cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; } if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm)) - cERROR(1, ("mount option dynperm ignored if cifsacl " - "mount option supported")); + cERROR(1, "mount option dynperm ignored if cifsacl " + "mount option supported"); } static int @@ -2344,11 +2340,11 @@ try_mount_again: } if (volume_info->nullauth) { - cFYI(1, ("null user")); + cFYI(1, "null user"); volume_info->username = ""; } else if (volume_info->username) { /* BB fixme parse for domain name here */ - cFYI(1, ("Username: %s", volume_info->username)); + cFYI(1, "Username: %s", volume_info->username); } else { cifserror("No username specified"); /* In userspace mount helper we can get user name from alternate @@ -2365,8 +2361,8 @@ try_mount_again: } else { cifs_sb->local_nls = load_nls(volume_info->iocharset); if (cifs_sb->local_nls == NULL) { - cERROR(1, ("CIFS mount error: iocharset %s not found", - volume_info->iocharset)); + cERROR(1, "CIFS mount error: iocharset %s not found", + volume_info->iocharset); rc = -ELIBACC; goto out; } @@ -2381,8 +2377,8 @@ try_mount_again: pSesInfo = cifs_find_smb_ses(srvTcp, volume_info->username); if (pSesInfo) { - cFYI(1, ("Existing smb sess found (status=%d)", - pSesInfo->status)); + cFYI(1, "Existing smb sess found (status=%d)", + pSesInfo->status); /* * The existing SMB session already has a reference to srvTcp, * so we can put back the extra one we got before @@ -2391,13 +2387,13 @@ try_mount_again: mutex_lock(&pSesInfo->session_mutex); if (pSesInfo->need_reconnect) { - cFYI(1, ("Session needs reconnect")); + cFYI(1, "Session needs reconnect"); rc = cifs_setup_session(xid, pSesInfo, cifs_sb->local_nls); } mutex_unlock(&pSesInfo->session_mutex); } else if (!rc) { - cFYI(1, ("Existing smb sess not found")); + cFYI(1, "Existing smb sess not found"); pSesInfo = sesInfoAlloc(); if (pSesInfo == NULL) { rc = -ENOMEM; @@ -2452,12 +2448,12 @@ try_mount_again: tcon = cifs_find_tcon(pSesInfo, volume_info->UNC); if (tcon) { - cFYI(1, ("Found match on UNC path")); + cFYI(1, "Found match on UNC path"); /* existing tcon already has a reference */ cifs_put_smb_ses(pSesInfo); if (tcon->seal != volume_info->seal) - cERROR(1, ("transport encryption setting " - "conflicts with existing tid")); + cERROR(1, "transport encryption setting " + "conflicts with existing tid"); } else { tcon = tconInfoAlloc(); if (tcon == NULL) { @@ -2477,7 +2473,7 @@ try_mount_again: if ((strchr(volume_info->UNC + 3, '\\') == NULL) && (strchr(volume_info->UNC + 3, '/') == NULL)) { - cERROR(1, ("Missing share name")); + cERROR(1, "Missing share name"); rc = -ENODEV; goto mount_fail_check; } else { @@ -2486,11 +2482,11 @@ try_mount_again: * we do on SessSetup and reconnect? */ rc = CIFSTCon(xid, pSesInfo, volume_info->UNC, tcon, cifs_sb->local_nls); - cFYI(1, ("CIFS Tcon rc = %d", rc)); + cFYI(1, "CIFS Tcon rc = %d", rc); if (volume_info->nodfs) { tcon->Flags &= ~SMB_SHARE_IS_IN_DFS; - cFYI(1, ("DFS disabled (%d)", - tcon->Flags)); + cFYI(1, "DFS disabled (%d)", + tcon->Flags); } } if (rc) @@ -2544,7 +2540,7 @@ try_mount_again: if ((tcon->unix_ext == 0) && (cifs_sb->rsize > (1024 * 127))) { cifs_sb->rsize = 1024 * 127; - cFYI(DBG2, ("no very large read support, rsize now 127K")); + cFYI(DBG2, "no very large read support, rsize now 127K"); } if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X)) cifs_sb->wsize = min(cifs_sb->wsize, @@ -2593,7 +2589,7 @@ remote_path_check: goto mount_fail_check; } - cFYI(1, ("Getting referral for: %s", full_path)); + cFYI(1, "Getting referral for: %s", full_path); rc = get_dfs_path(xid, pSesInfo , full_path + 1, cifs_sb->local_nls, &num_referrals, &referrals, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); @@ -2778,13 +2774,13 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, if (length == 3) { if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') && (bcc_ptr[2] == 'C')) { - cFYI(1, ("IPC connection")); + cFYI(1, "IPC connection"); tcon->ipc = 1; } } else if (length == 2) { if ((bcc_ptr[0] == 'A') && (bcc_ptr[1] == ':')) { /* the most common case */ - cFYI(1, ("disk share connection")); + cFYI(1, "disk share connection"); } } bcc_ptr += length + 1; @@ -2797,7 +2793,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, bytes_left, is_unicode, nls_codepage); - cFYI(1, ("nativeFileSystem=%s", tcon->nativeFileSystem)); + cFYI(1, "nativeFileSystem=%s", tcon->nativeFileSystem); if ((smb_buffer_response->WordCount == 3) || (smb_buffer_response->WordCount == 7)) @@ -2805,7 +2801,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport); else tcon->Flags = 0; - cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags)); + cFYI(1, "Tcon flags: 0x%x ", tcon->Flags); } else if ((rc == 0) && tcon == NULL) { /* all we need to save for IPC$ connection */ ses->ipc_tid = smb_buffer_response->Tid; @@ -2869,14 +2865,14 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, if (linuxExtEnabled == 0) pSesInfo->capabilities &= (~CAP_UNIX); - cFYI(1, ("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d", - server->secMode, server->capabilities, server->timeAdj)); + cFYI(1, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d", + server->secMode, server->capabilities, server->timeAdj); rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info); if (rc) { - cERROR(1, ("Send error in SessSetup = %d", rc)); + cERROR(1, "Send error in SessSetup = %d", rc); } else { - cFYI(1, ("CIFS Session Established successfully")); + cFYI(1, "CIFS Session Established successfully"); spin_lock(&GlobalMid_Lock); pSesInfo->status = CifsGood; pSesInfo->need_reconnect = false; diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index e9f7ecc..4aa2fe3 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -73,7 +73,7 @@ cifs_bp_rename_retry: namelen += (1 + temp->d_name.len); temp = temp->d_parent; if (temp == NULL) { - cERROR(1, ("corrupt dentry")); + cERROR(1, "corrupt dentry"); return NULL; } } @@ -90,19 +90,18 @@ cifs_bp_rename_retry: full_path[namelen] = dirsep; strncpy(full_path + namelen + 1, temp->d_name.name, temp->d_name.len); - cFYI(0, ("name: %s", full_path + namelen)); + cFYI(0, "name: %s", full_path + namelen); } temp = temp->d_parent; if (temp == NULL) { - cERROR(1, ("corrupt dentry")); + cERROR(1, "corrupt dentry"); kfree(full_path); return NULL; } } if (namelen != pplen + dfsplen) { - cERROR(1, - ("did not end path lookup where expected namelen is %d", - namelen)); + cERROR(1, "did not end path lookup where expected namelen is %d", + namelen); /* presumably this is only possible if racing with a rename of one of the parent directories (we can not lock the dentries above us to prevent this, but retrying should be harmless) */ @@ -173,7 +172,7 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) { pCifsInode->clientCanCacheAll = true; pCifsInode->clientCanCacheRead = true; - cFYI(1, ("Exclusive Oplock inode %p", newinode)); + cFYI(1, "Exclusive Oplock inode %p", newinode); } else if ((oplock & 0xF) == OPLOCK_READ) pCifsInode->clientCanCacheRead = true; } @@ -192,7 +191,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode, struct cifs_sb_info *cifs_sb = CIFS_SB(mnt->mnt_sb); struct cifs_fattr fattr; - cFYI(1, ("posix open %s", full_path)); + cFYI(1, "posix open %s", full_path); presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL); if (presp_data == NULL) @@ -358,7 +357,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, else if ((oflags & O_CREAT) == O_CREAT) disposition = FILE_OPEN_IF; else - cFYI(1, ("Create flag not set in create function")); + cFYI(1, "Create flag not set in create function"); } /* BB add processing to set equivalent of mode - e.g. via CreateX with @@ -394,7 +393,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); } if (rc) { - cFYI(1, ("cifs_create returned 0x%x", rc)); + cFYI(1, "cifs_create returned 0x%x", rc); goto cifs_create_out; } @@ -457,7 +456,7 @@ cifs_create_set_dentry: if (rc == 0) setup_cifs_dentry(tcon, direntry, newinode); else - cFYI(1, ("Create worked, get_inode_info failed rc = %d", rc)); + cFYI(1, "Create worked, get_inode_info failed rc = %d", rc); /* nfsd case - nfs srv does not set nd */ if ((nd == NULL) || (!(nd->flags & LOOKUP_OPEN))) { @@ -531,7 +530,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, u16 fileHandle; FILE_ALL_INFO *buf; - cFYI(1, ("sfu compat create special file")); + cFYI(1, "sfu compat create special file"); buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); if (buf == NULL) { @@ -616,8 +615,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, xid = GetXid(); - cFYI(1, ("parent inode = 0x%p name is: %s and dentry = 0x%p", - parent_dir_inode, direntry->d_name.name, direntry)); + cFYI(1, "parent inode = 0x%p name is: %s and dentry = 0x%p", + parent_dir_inode, direntry->d_name.name, direntry); /* check whether path exists */ @@ -632,7 +631,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, int i; for (i = 0; i < direntry->d_name.len; i++) if (direntry->d_name.name[i] == '\\') { - cFYI(1, ("Invalid file name")); + cFYI(1, "Invalid file name"); FreeXid(xid); return ERR_PTR(-EINVAL); } @@ -657,11 +656,11 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, } if (direntry->d_inode != NULL) { - cFYI(1, ("non-NULL inode in lookup")); + cFYI(1, "non-NULL inode in lookup"); } else { - cFYI(1, ("NULL inode in lookup")); + cFYI(1, "NULL inode in lookup"); } - cFYI(1, ("Full path: %s inode = 0x%p", full_path, direntry->d_inode)); + cFYI(1, "Full path: %s inode = 0x%p", full_path, direntry->d_inode); /* Posix open is only called (at lookup time) for file create now. * For opens (rather than creates), because we do not know if it @@ -723,7 +722,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, /* if it was once a directory (but how can we tell?) we could do shrink_dcache_parent(direntry); */ } else if (rc != -EACCES) { - cERROR(1, ("Unexpected lookup error %d", rc)); + cERROR(1, "Unexpected lookup error %d", rc); /* We special case check for Access Denied - since that is a common return code */ } @@ -742,8 +741,8 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) if (cifs_revalidate_dentry(direntry)) return 0; } else { - cFYI(1, ("neg dentry 0x%p name = %s", - direntry, direntry->d_name.name)); + cFYI(1, "neg dentry 0x%p name = %s", + direntry, direntry->d_name.name); if (time_after(jiffies, direntry->d_time + HZ) || !lookupCacheEnabled) { d_drop(direntry); @@ -758,7 +757,7 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) { int rc = 0; - cFYI(1, ("In cifs d_delete, name = %s", direntry->d_name.name)); + cFYI(1, "In cifs d_delete, name = %s", direntry->d_name.name); return rc; } */ diff --git a/fs/cifs/dns_resolve.c b/fs/cifs/dns_resolve.c index 6f8a0e3..4db2c5e 100644 --- a/fs/cifs/dns_resolve.c +++ b/fs/cifs/dns_resolve.c @@ -106,14 +106,14 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr) /* search for server name delimiter */ len = strlen(unc); if (len < 3) { - cFYI(1, ("%s: unc is too short: %s", __func__, unc)); + cFYI(1, "%s: unc is too short: %s", __func__, unc); return -EINVAL; } len -= 2; name = memchr(unc+2, '\\', len); if (!name) { - cFYI(1, ("%s: probably server name is whole unc: %s", - __func__, unc)); + cFYI(1, "%s: probably server name is whole unc: %s", + __func__, unc); } else { len = (name - unc) - 2/* leading // */; } @@ -127,8 +127,8 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr) name[len] = 0; if (is_ip(name)) { - cFYI(1, ("%s: it is IP, skipping dns upcall: %s", - __func__, name)); + cFYI(1, "%s: it is IP, skipping dns upcall: %s", + __func__, name); data = name; goto skip_upcall; } @@ -138,7 +138,7 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr) len = rkey->type_data.x[0]; data = rkey->payload.data; } else { - cERROR(1, ("%s: unable to resolve: %s", __func__, name)); + cERROR(1, "%s: unable to resolve: %s", __func__, name); goto out; } @@ -148,10 +148,10 @@ skip_upcall: if (*ip_addr) { memcpy(*ip_addr, data, len + 1); if (!IS_ERR(rkey)) - cFYI(1, ("%s: resolved: %s to %s", __func__, + cFYI(1, "%s: resolved: %s to %s", __func__, name, *ip_addr - )); + ); rc = 0; } else { rc = -ENOMEM; diff --git a/fs/cifs/export.c b/fs/cifs/export.c index 6177f7c..993f820 100644 --- a/fs/cifs/export.c +++ b/fs/cifs/export.c @@ -49,7 +49,7 @@ static struct dentry *cifs_get_parent(struct dentry *dentry) { /* BB need to add code here eventually to enable export via NFSD */ - cFYI(1, ("get parent for %p", dentry)); + cFYI(1, "get parent for %p", dentry); return ERR_PTR(-EACCES); } diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 1361d67..ed3689e 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -136,15 +136,15 @@ cifs_posix_open_inode_helper(struct inode *inode, struct file *file, if (timespec_equal(&file->f_path.dentry->d_inode->i_mtime, &temp) && (file->f_path.dentry->d_inode->i_size == (loff_t)le64_to_cpu(buf->EndOfFile))) { - cFYI(1, ("inode unchanged on server")); + cFYI(1, "inode unchanged on server"); } else { if (file->f_path.dentry->d_inode->i_mapping) { rc = filemap_write_and_wait(file->f_path.dentry->d_inode->i_mapping); if (rc != 0) CIFS_I(file->f_path.dentry->d_inode)->write_behind_rc = rc; } - cFYI(1, ("invalidating remote inode since open detected it " - "changed")); + cFYI(1, "invalidating remote inode since open detected it " + "changed"); invalidate_remote_inode(file->f_path.dentry->d_inode); } */ @@ -152,8 +152,8 @@ psx_client_can_cache: if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) { pCifsInode->clientCanCacheAll = true; pCifsInode->clientCanCacheRead = true; - cFYI(1, ("Exclusive Oplock granted on inode %p", - file->f_path.dentry->d_inode)); + cFYI(1, "Exclusive Oplock granted on inode %p", + file->f_path.dentry->d_inode); } else if ((oplock & 0xF) == OPLOCK_READ) pCifsInode->clientCanCacheRead = true; @@ -190,8 +190,8 @@ cifs_fill_filedata(struct file *file) if (file->private_data != NULL) { return pCifsFile; } else if ((file->f_flags & O_CREAT) && (file->f_flags & O_EXCL)) - cERROR(1, ("could not find file instance for " - "new file %p", file)); + cERROR(1, "could not find file instance for " + "new file %p", file); return NULL; } @@ -217,7 +217,7 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file, if (timespec_equal(&file->f_path.dentry->d_inode->i_mtime, &temp) && (file->f_path.dentry->d_inode->i_size == (loff_t)le64_to_cpu(buf->EndOfFile))) { - cFYI(1, ("inode unchanged on server")); + cFYI(1, "inode unchanged on server"); } else { if (file->f_path.dentry->d_inode->i_mapping) { /* BB no need to lock inode until after invalidate @@ -226,8 +226,8 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file, if (rc != 0) CIFS_I(file->f_path.dentry->d_inode)->write_behind_rc = rc; } - cFYI(1, ("invalidating remote inode since open detected it " - "changed")); + cFYI(1, "invalidating remote inode since open detected it " + "changed"); invalidate_remote_inode(file->f_path.dentry->d_inode); } @@ -242,8 +242,8 @@ client_can_cache: if ((*oplock & 0xF) == OPLOCK_EXCLUSIVE) { pCifsInode->clientCanCacheAll = true; pCifsInode->clientCanCacheRead = true; - cFYI(1, ("Exclusive Oplock granted on inode %p", - file->f_path.dentry->d_inode)); + cFYI(1, "Exclusive Oplock granted on inode %p", + file->f_path.dentry->d_inode); } else if ((*oplock & 0xF) == OPLOCK_READ) pCifsInode->clientCanCacheRead = true; @@ -285,8 +285,8 @@ int cifs_open(struct inode *inode, struct file *file) return rc; } - cFYI(1, ("inode = 0x%p file flags are 0x%x for %s", - inode, file->f_flags, full_path)); + cFYI(1, "inode = 0x%p file flags are 0x%x for %s", + inode, file->f_flags, full_path); if (oplockEnabled) oplock = REQ_OPLOCK; @@ -303,7 +303,7 @@ int cifs_open(struct inode *inode, struct file *file) cifs_sb->mnt_file_mode /* ignored */, oflags, &oplock, &netfid, xid); if (rc == 0) { - cFYI(1, ("posix open succeeded")); + cFYI(1, "posix open succeeded"); /* no need for special case handling of setting mode on read only files needed here */ @@ -313,12 +313,12 @@ int cifs_open(struct inode *inode, struct file *file) goto out; } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { if (tcon->ses->serverNOS) - cERROR(1, ("server %s of type %s returned" + cERROR(1, "server %s of type %s returned" " unexpected error on SMB posix open" ", disabling posix open support." " Check if server update available.", tcon->ses->serverName, - tcon->ses->serverNOS)); + tcon->ses->serverNOS); tcon->broken_posix_open = true; } else if ((rc != -EIO) && (rc != -EREMOTE) && (rc != -EOPNOTSUPP)) /* path not found or net err */ @@ -386,7 +386,7 @@ int cifs_open(struct inode *inode, struct file *file) & CIFS_MOUNT_MAP_SPECIAL_CHR); } if (rc) { - cFYI(1, ("cifs_open returned 0x%x", rc)); + cFYI(1, "cifs_open returned 0x%x", rc); goto out; } @@ -469,7 +469,7 @@ static int cifs_reopen_file(struct file *file, bool can_flush) } if (file->f_path.dentry == NULL) { - cERROR(1, ("no valid name if dentry freed")); + cERROR(1, "no valid name if dentry freed"); dump_stack(); rc = -EBADF; goto reopen_error_exit; @@ -477,7 +477,7 @@ static int cifs_reopen_file(struct file *file, bool can_flush) inode = file->f_path.dentry->d_inode; if (inode == NULL) { - cERROR(1, ("inode not valid")); + cERROR(1, "inode not valid"); dump_stack(); rc = -EBADF; goto reopen_error_exit; @@ -499,8 +499,8 @@ reopen_error_exit: return rc; } - cFYI(1, ("inode = 0x%p file flags 0x%x for %s", - inode, file->f_flags, full_path)); + cFYI(1, "inode = 0x%p file flags 0x%x for %s", + inode, file->f_flags, full_path); if (oplockEnabled) oplock = REQ_OPLOCK; @@ -516,7 +516,7 @@ reopen_error_exit: cifs_sb->mnt_file_mode /* ignored */, oflags, &oplock, &netfid, xid); if (rc == 0) { - cFYI(1, ("posix reopen succeeded")); + cFYI(1, "posix reopen succeeded"); goto reopen_success; } /* fallthrough to retry open the old way on errors, especially @@ -537,8 +537,8 @@ reopen_error_exit: CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc) { mutex_unlock(&pCifsFile->fh_mutex); - cFYI(1, ("cifs_open returned 0x%x", rc)); - cFYI(1, ("oplock: %d", oplock)); + cFYI(1, "cifs_open returned 0x%x", rc); + cFYI(1, "oplock: %d", oplock); } else { reopen_success: pCifsFile->netfid = netfid; @@ -570,8 +570,8 @@ reopen_success: if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) { pCifsInode->clientCanCacheAll = true; pCifsInode->clientCanCacheRead = true; - cFYI(1, ("Exclusive Oplock granted on inode %p", - file->f_path.dentry->d_inode)); + cFYI(1, "Exclusive Oplock granted on inode %p", + file->f_path.dentry->d_inode); } else if ((oplock & 0xF) == OPLOCK_READ) { pCifsInode->clientCanCacheRead = true; pCifsInode->clientCanCacheAll = false; @@ -619,8 +619,7 @@ int cifs_close(struct inode *inode, struct file *file) the struct would be in each open file, but this should give enough time to clear the socket */ - cFYI(DBG2, - ("close delay, write pending")); + cFYI(DBG2, "close delay, write pending"); msleep(timeout); timeout *= 4; } @@ -653,7 +652,7 @@ int cifs_close(struct inode *inode, struct file *file) read_lock(&GlobalSMBSeslock); if (list_empty(&(CIFS_I(inode)->openFileList))) { - cFYI(1, ("closing last open instance for inode %p", inode)); + cFYI(1, "closing last open instance for inode %p", inode); /* if the file is not open we do not know if we can cache info on this inode, much less write behind and read ahead */ CIFS_I(inode)->clientCanCacheRead = false; @@ -674,7 +673,7 @@ int cifs_closedir(struct inode *inode, struct file *file) (struct cifsFileInfo *)file->private_data; char *ptmp; - cFYI(1, ("Closedir inode = 0x%p", inode)); + cFYI(1, "Closedir inode = 0x%p", inode); xid = GetXid(); @@ -685,22 +684,22 @@ int cifs_closedir(struct inode *inode, struct file *file) pTcon = cifs_sb->tcon; - cFYI(1, ("Freeing private data in close dir")); + cFYI(1, "Freeing private data in close dir"); write_lock(&GlobalSMBSeslock); if (!pCFileStruct->srch_inf.endOfSearch && !pCFileStruct->invalidHandle) { pCFileStruct->invalidHandle = true; write_unlock(&GlobalSMBSeslock); rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid); - cFYI(1, ("Closing uncompleted readdir with rc %d", - rc)); + cFYI(1, "Closing uncompleted readdir with rc %d", + rc); /* not much we can do if it fails anyway, ignore rc */ rc = 0; } else write_unlock(&GlobalSMBSeslock); ptmp = pCFileStruct->srch_inf.ntwrk_buf_start; if (ptmp) { - cFYI(1, ("closedir free smb buf in srch struct")); + cFYI(1, "closedir free smb buf in srch struct"); pCFileStruct->srch_inf.ntwrk_buf_start = NULL; if (pCFileStruct->srch_inf.smallBuf) cifs_small_buf_release(ptmp); @@ -748,49 +747,49 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) rc = -EACCES; xid = GetXid(); - cFYI(1, ("Lock parm: 0x%x flockflags: " + cFYI(1, "Lock parm: 0x%x flockflags: " "0x%x flocktype: 0x%x start: %lld end: %lld", cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start, - pfLock->fl_end)); + pfLock->fl_end); if (pfLock->fl_flags & FL_POSIX) - cFYI(1, ("Posix")); + cFYI(1, "Posix"); if (pfLock->fl_flags & FL_FLOCK) - cFYI(1, ("Flock")); + cFYI(1, "Flock"); if (pfLock->fl_flags & FL_SLEEP) { - cFYI(1, ("Blocking lock")); + cFYI(1, "Blocking lock"); wait_flag = true; } if (pfLock->fl_flags & FL_ACCESS) - cFYI(1, ("Process suspended by mandatory locking - " - "not implemented yet")); + cFYI(1, "Process suspended by mandatory locking - " + "not implemented yet"); if (pfLock->fl_flags & FL_LEASE) - cFYI(1, ("Lease on file - not implemented yet")); + cFYI(1, "Lease on file - not implemented yet"); if (pfLock->fl_flags & (~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE))) - cFYI(1, ("Unknown lock flags 0x%x", pfLock->fl_flags)); + cFYI(1, "Unknown lock flags 0x%x", pfLock->fl_flags); if (pfLock->fl_type == F_WRLCK) { - cFYI(1, ("F_WRLCK ")); + cFYI(1, "F_WRLCK "); numLock = 1; } else if (pfLock->fl_type == F_UNLCK) { - cFYI(1, ("F_UNLCK")); + cFYI(1, "F_UNLCK"); numUnlock = 1; /* Check if unlock includes more than one lock range */ } else if (pfLock->fl_type == F_RDLCK) { - cFYI(1, ("F_RDLCK")); + cFYI(1, "F_RDLCK"); lockType |= LOCKING_ANDX_SHARED_LOCK; numLock = 1; } else if (pfLock->fl_type == F_EXLCK) { - cFYI(1, ("F_EXLCK")); + cFYI(1, "F_EXLCK"); numLock = 1; } else if (pfLock->fl_type == F_SHLCK) { - cFYI(1, ("F_SHLCK")); + cFYI(1, "F_SHLCK"); lockType |= LOCKING_ANDX_SHARED_LOCK; numLock = 1; } else - cFYI(1, ("Unknown type of lock")); + cFYI(1, "Unknown type of lock"); cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); tcon = cifs_sb->tcon; @@ -833,8 +832,8 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) 0 /* wait flag */ ); pfLock->fl_type = F_UNLCK; if (rc != 0) - cERROR(1, ("Error unlocking previously locked " - "range %d during test of lock", rc)); + cERROR(1, "Error unlocking previously locked " + "range %d during test of lock", rc); rc = 0; } else { @@ -988,9 +987,8 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, pTcon = cifs_sb->tcon; - /* cFYI(1, - (" write %d bytes to offset %lld of %s", write_size, - *poffset, file->f_path.dentry->d_name.name)); */ + /* cFYI(1, " write %d bytes to offset %lld of %s", write_size, + *poffset, file->f_path.dentry->d_name.name); */ if (file->private_data == NULL) return -EBADF; @@ -1091,8 +1089,8 @@ static ssize_t cifs_write(struct file *file, const char *write_data, pTcon = cifs_sb->tcon; - cFYI(1, ("write %zd bytes to offset %lld of %s", write_size, - *poffset, file->f_path.dentry->d_name.name)); + cFYI(1, "write %zd bytes to offset %lld of %s", write_size, + *poffset, file->f_path.dentry->d_name.name); if (file->private_data == NULL) return -EBADF; @@ -1233,7 +1231,7 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode) it being zero) during stress testcases so we need to check for it */ if (cifs_inode == NULL) { - cERROR(1, ("Null inode passed to cifs_writeable_file")); + cERROR(1, "Null inode passed to cifs_writeable_file"); dump_stack(); return NULL; } @@ -1277,7 +1275,7 @@ refind_writable: again. Note that it would be bad to hold up writepages here (rather than in caller) with continuous retries */ - cFYI(1, ("wp failed on reopen file")); + cFYI(1, "wp failed on reopen file"); read_lock(&GlobalSMBSeslock); /* can not use this handle, no write pending on this one after all */ @@ -1353,7 +1351,7 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) else if (bytes_written < 0) rc = bytes_written; } else { - cFYI(1, ("No writeable filehandles for inode")); + cFYI(1, "No writeable filehandles for inode"); rc = -EIO; } @@ -1525,7 +1523,7 @@ retry: */ open_file = find_writable_file(CIFS_I(mapping->host)); if (!open_file) { - cERROR(1, ("No writable handles for inode")); + cERROR(1, "No writable handles for inode"); rc = -EBADF; } else { long_op = cifs_write_timeout(cifsi, offset); @@ -1538,8 +1536,8 @@ retry: cifs_update_eof(cifsi, offset, bytes_written); if (rc || bytes_written < bytes_to_write) { - cERROR(1, ("Write2 ret %d, wrote %d", - rc, bytes_written)); + cERROR(1, "Write2 ret %d, wrote %d", + rc, bytes_written); /* BB what if continued retry is requested via mount flags? */ if (rc == -ENOSPC) @@ -1600,7 +1598,7 @@ static int cifs_writepage(struct page *page, struct writeback_control *wbc) /* BB add check for wbc flags */ page_cache_get(page); if (!PageUptodate(page)) - cFYI(1, ("ppw - page not up to date")); + cFYI(1, "ppw - page not up to date"); /* * Set the "writeback" flag, and clear "dirty" in the radix tree. @@ -1629,8 +1627,8 @@ static int cifs_write_end(struct file *file, struct address_space *mapping, int rc; struct inode *inode = mapping->host; - cFYI(1, ("write_end for page %p from pos %lld with %d bytes", - page, pos, copied)); + cFYI(1, "write_end for page %p from pos %lld with %d bytes", + page, pos, copied); if (PageChecked(page)) { if (copied == len) @@ -1686,8 +1684,8 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync) xid = GetXid(); - cFYI(1, ("Sync file - name: %s datasync: 0x%x", - dentry->d_name.name, datasync)); + cFYI(1, "Sync file - name: %s datasync: 0x%x", + dentry->d_name.name, datasync); rc = filemap_write_and_wait(inode->i_mapping); if (rc == 0) { @@ -1711,7 +1709,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync) unsigned int rpages = 0; int rc = 0; - cFYI(1, ("sync page %p",page)); + cFYI(1, "sync page %p",page); mapping = page->mapping; if (!mapping) return 0; @@ -1722,7 +1720,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync) /* fill in rpages then result = cifs_pagein_inode(inode, index, rpages); */ /* BB finish */ -/* cFYI(1, ("rpages is %d for sync page of Index %ld", rpages, index)); +/* cFYI(1, "rpages is %d for sync page of Index %ld", rpages, index); #if 0 if (rc < 0) @@ -1756,7 +1754,7 @@ int cifs_flush(struct file *file, fl_owner_t id) CIFS_I(inode)->write_behind_rc = 0; } - cFYI(1, ("Flush inode %p file %p rc %d", inode, file, rc)); + cFYI(1, "Flush inode %p file %p rc %d", inode, file, rc); return rc; } @@ -1788,7 +1786,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, open_file = (struct cifsFileInfo *)file->private_data; if ((file->f_flags & O_ACCMODE) == O_WRONLY) - cFYI(1, ("attempting read on write only file instance")); + cFYI(1, "attempting read on write only file instance"); for (total_read = 0, current_offset = read_data; read_size > total_read; @@ -1869,7 +1867,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, open_file = (struct cifsFileInfo *)file->private_data; if ((file->f_flags & O_ACCMODE) == O_WRONLY) - cFYI(1, ("attempting read on write only file instance")); + cFYI(1, "attempting read on write only file instance"); for (total_read = 0, current_offset = read_data; read_size > total_read; @@ -1920,7 +1918,7 @@ int cifs_file_mmap(struct file *file, struct vm_area_struct *vma) xid = GetXid(); rc = cifs_revalidate_file(file); if (rc) { - cFYI(1, ("Validation prior to mmap failed, error=%d", rc)); + cFYI(1, "Validation prior to mmap failed, error=%d", rc); FreeXid(xid); return rc; } @@ -1946,7 +1944,7 @@ static void cifs_copy_cache_pages(struct address_space *mapping, if (add_to_page_cache_lru(page, mapping, page->index, GFP_KERNEL)) { page_cache_release(page); - cFYI(1, ("Add page cache failed")); + cFYI(1, "Add page cache failed"); data += PAGE_CACHE_SIZE; bytes_read -= PAGE_CACHE_SIZE; continue; @@ -2033,8 +2031,8 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, /* Read size needs to be in multiples of one page */ read_size = min_t(const unsigned int, read_size, cifs_sb->rsize & PAGE_CACHE_MASK); - cFYI(DBG2, ("rpages: read size 0x%x contiguous pages %d", - read_size, contig_pages)); + cFYI(DBG2, "rpages: read size 0x%x contiguous pages %d", + read_size, contig_pages); rc = -EAGAIN; while (rc == -EAGAIN) { if ((open_file->invalidHandle) && @@ -2061,7 +2059,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, } } if ((rc < 0) || (smb_read_data == NULL)) { - cFYI(1, ("Read error in readpages: %d", rc)); + cFYI(1, "Read error in readpages: %d", rc); break; } else if (bytes_read > 0) { task_io_account_read(bytes_read); @@ -2084,9 +2082,9 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, /* break; */ } } else { - cFYI(1, ("No bytes read (%d) at offset %lld . " - "Cleaning remaining pages from readahead list", - bytes_read, offset)); + cFYI(1, "No bytes read (%d) at offset %lld . " + "Cleaning remaining pages from readahead list", + bytes_read, offset); /* BB turn off caching and do new lookup on file size at server? */ break; @@ -2129,7 +2127,7 @@ static int cifs_readpage_worker(struct file *file, struct page *page, if (rc < 0) goto io_error; else - cFYI(1, ("Bytes read %d", rc)); + cFYI(1, "Bytes read %d", rc); file->f_path.dentry->d_inode->i_atime = current_fs_time(file->f_path.dentry->d_inode->i_sb); @@ -2161,8 +2159,8 @@ static int cifs_readpage(struct file *file, struct page *page) return rc; } - cFYI(1, ("readpage %p at offset %d 0x%x\n", - page, (int)offset, (int)offset)); + cFYI(1, "readpage %p at offset %d 0x%x\n", + page, (int)offset, (int)offset); rc = cifs_readpage_worker(file, page, &offset); @@ -2232,7 +2230,7 @@ static int cifs_write_begin(struct file *file, struct address_space *mapping, struct page *page; int rc = 0; - cFYI(1, ("write_begin from %lld len %d", (long long)pos, len)); + cFYI(1, "write_begin from %lld len %d", (long long)pos, len); page = grab_cache_page_write_begin(mapping, index, flags); if (!page) { @@ -2319,7 +2317,7 @@ cifs_oplock_break(struct slow_work *work) rc = waitrc; if (rc) cinode->write_behind_rc = rc; - cFYI(1, ("Oplock flush inode %p rc %d", inode, rc)); + cFYI(1, "Oplock flush inode %p rc %d", inode, rc); } /* @@ -2331,7 +2329,7 @@ cifs_oplock_break(struct slow_work *work) if (!cfile->closePend && !cfile->oplock_break_cancelled) { rc = CIFSSMBLock(0, cifs_sb->tcon, cfile->netfid, 0, 0, 0, 0, LOCKING_ANDX_OPLOCK_RELEASE, false); - cFYI(1, ("Oplock release rc = %d", rc)); + cFYI(1, "Oplock release rc = %d", rc); } } diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 35ec117..7524a90 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -144,8 +144,8 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) else cifs_i->time = jiffies; - cFYI(1, ("inode 0x%p old_time=%ld new_time=%ld", inode, - oldtime, cifs_i->time)); + cFYI(1, "inode 0x%p old_time=%ld new_time=%ld", inode, + oldtime, cifs_i->time); cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING; @@ -227,7 +227,7 @@ cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info, /* safest to call it a file if we do not know */ fattr->cf_mode |= S_IFREG; fattr->cf_dtype = DT_REG; - cFYI(1, ("unknown type %d", le32_to_cpu(info->Type))); + cFYI(1, "unknown type %d", le32_to_cpu(info->Type)); break; } @@ -256,7 +256,7 @@ cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb) { struct cifs_sb_info *cifs_sb = CIFS_SB(sb); - cFYI(1, ("creating fake fattr for DFS referral")); + cFYI(1, "creating fake fattr for DFS referral"); memset(fattr, 0, sizeof(*fattr)); fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU; @@ -305,7 +305,7 @@ int cifs_get_inode_info_unix(struct inode **pinode, struct cifs_sb_info *cifs_sb = CIFS_SB(sb); tcon = cifs_sb->tcon; - cFYI(1, ("Getting info on %s", full_path)); + cFYI(1, "Getting info on %s", full_path); /* could have done a find first instead but this returns more info */ rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data, @@ -373,7 +373,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, &bytes_read, &pbuf, &buf_type); if ((rc == 0) && (bytes_read >= 8)) { if (memcmp("IntxBLK", pbuf, 8) == 0) { - cFYI(1, ("Block device")); + cFYI(1, "Block device"); fattr->cf_mode |= S_IFBLK; fattr->cf_dtype = DT_BLK; if (bytes_read == 24) { @@ -385,7 +385,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, fattr->cf_rdev = MKDEV(mjr, mnr); } } else if (memcmp("IntxCHR", pbuf, 8) == 0) { - cFYI(1, ("Char device")); + cFYI(1, "Char device"); fattr->cf_mode |= S_IFCHR; fattr->cf_dtype = DT_CHR; if (bytes_read == 24) { @@ -397,7 +397,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, fattr->cf_rdev = MKDEV(mjr, mnr); } } else if (memcmp("IntxLNK", pbuf, 7) == 0) { - cFYI(1, ("Symlink")); + cFYI(1, "Symlink"); fattr->cf_mode |= S_IFLNK; fattr->cf_dtype = DT_LNK; } else { @@ -439,10 +439,10 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path, else if (rc > 3) { mode = le32_to_cpu(*((__le32 *)ea_value)); fattr->cf_mode &= ~SFBITS_MASK; - cFYI(1, ("special bits 0%o org mode 0%o", mode, - fattr->cf_mode)); + cFYI(1, "special bits 0%o org mode 0%o", mode, + fattr->cf_mode); fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode; - cFYI(1, ("special mode bits 0%o", mode)); + cFYI(1, "special mode bits 0%o", mode); } return 0; @@ -548,11 +548,11 @@ int cifs_get_inode_info(struct inode **pinode, struct cifs_fattr fattr; pTcon = cifs_sb->tcon; - cFYI(1, ("Getting info on %s", full_path)); + cFYI(1, "Getting info on %s", full_path); if ((pfindData == NULL) && (*pinode != NULL)) { if (CIFS_I(*pinode)->clientCanCacheRead) { - cFYI(1, ("No need to revalidate cached inode sizes")); + cFYI(1, "No need to revalidate cached inode sizes"); return rc; } } @@ -618,7 +618,7 @@ int cifs_get_inode_info(struct inode **pinode, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc1 || !fattr.cf_uniqueid) { - cFYI(1, ("GetSrvInodeNum rc %d", rc1)); + cFYI(1, "GetSrvInodeNum rc %d", rc1); fattr.cf_uniqueid = iunique(sb, ROOT_I); cifs_autodisable_serverino(cifs_sb); } @@ -634,13 +634,13 @@ int cifs_get_inode_info(struct inode **pinode, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid); if (tmprc) - cFYI(1, ("cifs_sfu_type failed: %d", tmprc)); + cFYI(1, "cifs_sfu_type failed: %d", tmprc); } #ifdef CONFIG_CIFS_EXPERIMENTAL /* fill in 0777 bits from ACL */ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { - cFYI(1, ("Getting mode bits from ACL")); + cFYI(1, "Getting mode bits from ACL"); cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path, pfid); } #endif @@ -734,7 +734,7 @@ cifs_iget(struct super_block *sb, struct cifs_fattr *fattr) unsigned long hash; struct inode *inode; - cFYI(1, ("looking for uniqueid=%llu", fattr->cf_uniqueid)); + cFYI(1, "looking for uniqueid=%llu", fattr->cf_uniqueid); /* hash down to 32-bits on 32-bit arch */ hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid); @@ -780,7 +780,7 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) return ERR_PTR(-ENOMEM); if (rc && cifs_sb->tcon->ipc) { - cFYI(1, ("ipc connection - fake read inode")); + cFYI(1, "ipc connection - fake read inode"); inode->i_mode |= S_IFDIR; inode->i_nlink = 2; inode->i_op = &cifs_ipc_inode_ops; @@ -842,7 +842,7 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid, * server times. */ if (set_time && (attrs->ia_valid & ATTR_CTIME)) { - cFYI(1, ("CIFS - CTIME changed")); + cFYI(1, "CIFS - CTIME changed"); info_buf.ChangeTime = cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime)); } else @@ -877,8 +877,8 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid, goto out; } - cFYI(1, ("calling SetFileInfo since SetPathInfo for " - "times not supported by this server")); + cFYI(1, "calling SetFileInfo since SetPathInfo for " + "times not supported by this server"); rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, SYNCHRONIZE | FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR, &netfid, &oplock, @@ -1036,7 +1036,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) struct iattr *attrs = NULL; __u32 dosattr = 0, origattr = 0; - cFYI(1, ("cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry)); + cFYI(1, "cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry); xid = GetXid(); @@ -1055,7 +1055,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) rc = CIFSPOSIXDelFile(xid, tcon, full_path, SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - cFYI(1, ("posix del rc %d", rc)); + cFYI(1, "posix del rc %d", rc); if ((rc == 0) || (rc == -ENOENT)) goto psx_del_no_retry; } @@ -1129,7 +1129,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) struct inode *newinode = NULL; struct cifs_fattr fattr; - cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode)); + cFYI(1, "In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode); xid = GetXid(); @@ -1164,7 +1164,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) kfree(pInfo); goto mkdir_retry_old; } else if (rc) { - cFYI(1, ("posix mkdir returned 0x%x", rc)); + cFYI(1, "posix mkdir returned 0x%x", rc); d_drop(direntry); } else { if (pInfo->Type == cpu_to_le32(-1)) { @@ -1190,12 +1190,12 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) d_instantiate(direntry, newinode); #ifdef CONFIG_CIFS_DEBUG2 - cFYI(1, ("instantiated dentry %p %s to inode %p", - direntry, direntry->d_name.name, newinode)); + cFYI(1, "instantiated dentry %p %s to inode %p", + direntry, direntry->d_name.name, newinode); if (newinode->i_nlink != 2) - cFYI(1, ("unexpected number of links %d", - newinode->i_nlink)); + cFYI(1, "unexpected number of links %d", + newinode->i_nlink); #endif } kfree(pInfo); @@ -1206,7 +1206,7 @@ mkdir_retry_old: rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc) { - cFYI(1, ("cifs_mkdir returned 0x%x", rc)); + cFYI(1, "cifs_mkdir returned 0x%x", rc); d_drop(direntry); } else { mkdir_get_info: @@ -1309,7 +1309,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) char *full_path = NULL; struct cifsInodeInfo *cifsInode; - cFYI(1, ("cifs_rmdir, inode = 0x%p", inode)); + cFYI(1, "cifs_rmdir, inode = 0x%p", inode); xid = GetXid(); @@ -1673,12 +1673,12 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, nfid, npid, false); cifsFileInfo_put(open_file); - cFYI(1, ("SetFSize for attrs rc = %d", rc)); + cFYI(1, "SetFSize for attrs rc = %d", rc); if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { unsigned int bytes_written; rc = CIFSSMBWrite(xid, pTcon, nfid, 0, attrs->ia_size, &bytes_written, NULL, NULL, 1); - cFYI(1, ("Wrt seteof rc %d", rc)); + cFYI(1, "Wrt seteof rc %d", rc); } } else rc = -EINVAL; @@ -1692,7 +1692,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, false, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc)); + cFYI(1, "SetEOF by path (setattrs) rc = %d", rc); if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { __u16 netfid; int oplock = 0; @@ -1709,7 +1709,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, attrs->ia_size, &bytes_written, NULL, NULL, 1); - cFYI(1, ("wrt seteof rc %d", rc)); + cFYI(1, "wrt seteof rc %d", rc); CIFSSMBClose(xid, pTcon, netfid); } } @@ -1737,8 +1737,8 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) struct cifs_unix_set_info_args *args = NULL; struct cifsFileInfo *open_file; - cFYI(1, ("setattr_unix on file %s attrs->ia_valid=0x%x", - direntry->d_name.name, attrs->ia_valid)); + cFYI(1, "setattr_unix on file %s attrs->ia_valid=0x%x", + direntry->d_name.name, attrs->ia_valid); xid = GetXid(); @@ -1868,8 +1868,8 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) xid = GetXid(); - cFYI(1, ("setattr on file %s attrs->iavalid 0x%x", - direntry->d_name.name, attrs->ia_valid)); + cFYI(1, "setattr on file %s attrs->iavalid 0x%x", + direntry->d_name.name, attrs->ia_valid); if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) { /* check if we have permission to change attrs */ @@ -1926,7 +1926,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) attrs->ia_valid &= ~ATTR_MODE; if (attrs->ia_valid & ATTR_MODE) { - cFYI(1, ("Mode changed to 0%o", attrs->ia_mode)); + cFYI(1, "Mode changed to 0%o", attrs->ia_mode); mode = attrs->ia_mode; } @@ -2012,7 +2012,7 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs) #if 0 void cifs_delete_inode(struct inode *inode) { - cFYI(1, ("In cifs_delete_inode, inode = 0x%p", inode)); + cFYI(1, "In cifs_delete_inode, inode = 0x%p", inode); /* may have to add back in if and when safe distributed caching of directories added e.g. via FindNotify */ } diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c index f946506..505926f 100644 --- a/fs/cifs/ioctl.c +++ b/fs/cifs/ioctl.c @@ -47,7 +47,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) xid = GetXid(); - cFYI(1, ("ioctl file %p cmd %u arg %lu", filep, command, arg)); + cFYI(1, "ioctl file %p cmd %u arg %lu", filep, command, arg); cifs_sb = CIFS_SB(inode->i_sb); @@ -64,12 +64,12 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) switch (command) { case CIFS_IOC_CHECKUMOUNT: - cFYI(1, ("User unmount attempted")); + cFYI(1, "User unmount attempted"); if (cifs_sb->mnt_uid == current_uid()) rc = 0; else { rc = -EACCES; - cFYI(1, ("uids do not match")); + cFYI(1, "uids do not match"); } break; #ifdef CONFIG_CIFS_POSIX @@ -97,11 +97,11 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) /* rc= CIFSGetExtAttr(xid,tcon,pSMBFile->netfid, extAttrBits, &ExtAttrMask);*/ } - cFYI(1, ("set flags not implemented yet")); + cFYI(1, "set flags not implemented yet"); break; #endif /* CONFIG_CIFS_POSIX */ default: - cFYI(1, ("unsupported ioctl")); + cFYI(1, "unsupported ioctl"); break; } diff --git a/fs/cifs/link.c b/fs/cifs/link.c index c1a9d42..473ca80 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -139,7 +139,7 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd) if (!full_path) goto out; - cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode)); + cFYI(1, "Full path: %s inode = 0x%p", full_path, inode); rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path, cifs_sb->local_nls); @@ -178,8 +178,8 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) return rc; } - cFYI(1, ("Full path: %s", full_path)); - cFYI(1, ("symname is %s", symname)); + cFYI(1, "Full path: %s", full_path); + cFYI(1, "symname is %s", symname); /* BB what if DFS and this volume is on different share? BB */ if (pTcon->unix_ext) @@ -198,8 +198,8 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) inode->i_sb, xid, NULL); if (rc != 0) { - cFYI(1, ("Create symlink ok, getinodeinfo fail rc = %d", - rc)); + cFYI(1, "Create symlink ok, getinodeinfo fail rc = %d", + rc); } else { if (pTcon->nocase) direntry->d_op = &cifs_ci_dentry_ops; diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index d147499..1394aa3 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -51,7 +51,7 @@ _GetXid(void) if (GlobalTotalActiveXid > GlobalMaxActiveXid) GlobalMaxActiveXid = GlobalTotalActiveXid; if (GlobalTotalActiveXid > 65000) - cFYI(1, ("warning: more than 65000 requests active")); + cFYI(1, "warning: more than 65000 requests active"); xid = GlobalCurrentXid++; spin_unlock(&GlobalMid_Lock); return xid; @@ -88,7 +88,7 @@ void sesInfoFree(struct cifsSesInfo *buf_to_free) { if (buf_to_free == NULL) { - cFYI(1, ("Null buffer passed to sesInfoFree")); + cFYI(1, "Null buffer passed to sesInfoFree"); return; } @@ -126,7 +126,7 @@ void tconInfoFree(struct cifsTconInfo *buf_to_free) { if (buf_to_free == NULL) { - cFYI(1, ("Null buffer passed to tconInfoFree")); + cFYI(1, "Null buffer passed to tconInfoFree"); return; } atomic_dec(&tconInfoAllocCount); @@ -166,7 +166,7 @@ void cifs_buf_release(void *buf_to_free) { if (buf_to_free == NULL) { - /* cFYI(1, ("Null buffer passed to cifs_buf_release"));*/ + /* cFYI(1, "Null buffer passed to cifs_buf_release");*/ return; } mempool_free(buf_to_free, cifs_req_poolp); @@ -202,7 +202,7 @@ cifs_small_buf_release(void *buf_to_free) { if (buf_to_free == NULL) { - cFYI(1, ("Null buffer passed to cifs_small_buf_release")); + cFYI(1, "Null buffer passed to cifs_small_buf_release"); return; } mempool_free(buf_to_free, cifs_sm_req_poolp); @@ -345,19 +345,19 @@ header_assemble(struct smb_hdr *buffer, char smb_command /* command */ , /* with userid/password pairs found on the smb session */ /* for other target tcp/ip addresses BB */ if (current_fsuid() != treeCon->ses->linux_uid) { - cFYI(1, ("Multiuser mode and UID " - "did not match tcon uid")); + cFYI(1, "Multiuser mode and UID " + "did not match tcon uid"); read_lock(&cifs_tcp_ses_lock); list_for_each(temp_item, &treeCon->ses->server->smb_ses_list) { ses = list_entry(temp_item, struct cifsSesInfo, smb_ses_list); if (ses->linux_uid == current_fsuid()) { if (ses->server == treeCon->ses->server) { - cFYI(1, ("found matching uid substitute right smb_uid")); + cFYI(1, "found matching uid substitute right smb_uid"); buffer->Uid = ses->Suid; break; } else { /* BB eventually call cifs_setup_session here */ - cFYI(1, ("local UID found but no smb sess with this server exists")); + cFYI(1, "local UID found but no smb sess with this server exists"); } } } @@ -394,17 +394,16 @@ checkSMBhdr(struct smb_hdr *smb, __u16 mid) if (smb->Command == SMB_COM_LOCKING_ANDX) return 0; else - cERROR(1, ("Received Request not response")); + cERROR(1, "Received Request not response"); } } else { /* bad signature or mid */ if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff)) - cERROR(1, - ("Bad protocol string signature header %x", - *(unsigned int *) smb->Protocol)); + cERROR(1, "Bad protocol string signature header %x", + *(unsigned int *) smb->Protocol); if (mid != smb->Mid) - cERROR(1, ("Mids do not match")); + cERROR(1, "Mids do not match"); } - cERROR(1, ("bad smb detected. The Mid=%d", smb->Mid)); + cERROR(1, "bad smb detected. The Mid=%d", smb->Mid); return 1; } @@ -413,7 +412,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length) { __u32 len = smb->smb_buf_length; __u32 clc_len; /* calculated length */ - cFYI(0, ("checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len)); + cFYI(0, "checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len); if (length < 2 + sizeof(struct smb_hdr)) { if ((length >= sizeof(struct smb_hdr) - 1) @@ -437,15 +436,15 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length) tmp[sizeof(struct smb_hdr)+1] = 0; return 0; } - cERROR(1, ("rcvd invalid byte count (bcc)")); + cERROR(1, "rcvd invalid byte count (bcc)"); } else { - cERROR(1, ("Length less than smb header size")); + cERROR(1, "Length less than smb header size"); } return 1; } if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { - cERROR(1, ("smb length greater than MaxBufSize, mid=%d", - smb->Mid)); + cERROR(1, "smb length greater than MaxBufSize, mid=%d", + smb->Mid); return 1; } @@ -454,8 +453,8 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length) clc_len = smbCalcSize_LE(smb); if (4 + len != length) { - cERROR(1, ("Length read does not match RFC1001 length %d", - len)); + cERROR(1, "Length read does not match RFC1001 length %d", + len); return 1; } @@ -466,8 +465,8 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length) if (((4 + len) & 0xFFFF) == (clc_len & 0xFFFF)) return 0; /* bcc wrapped */ } - cFYI(1, ("Calculated size %d vs length %d mismatch for mid %d", - clc_len, 4 + len, smb->Mid)); + cFYI(1, "Calculated size %d vs length %d mismatch for mid %d", + clc_len, 4 + len, smb->Mid); /* Windows XP can return a few bytes too much, presumably an illegal pad, at the end of byte range lock responses so we allow for that three byte pad, as long as actual @@ -482,8 +481,8 @@ checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length) if ((4+len > clc_len) && (len <= clc_len + 512)) return 0; else { - cERROR(1, ("RFC1001 size %d bigger than SMB for Mid=%d", - len, smb->Mid)); + cERROR(1, "RFC1001 size %d bigger than SMB for Mid=%d", + len, smb->Mid); return 1; } } @@ -501,7 +500,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) struct cifsFileInfo *netfile; int rc; - cFYI(1, ("Checking for oplock break or dnotify response")); + cFYI(1, "Checking for oplock break or dnotify response"); if ((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) && (pSMB->hdr.Flags & SMBFLG_RESPONSE)) { struct smb_com_transaction_change_notify_rsp *pSMBr = @@ -513,15 +512,15 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) pnotify = (struct file_notify_information *) ((char *)&pSMBr->hdr.Protocol + data_offset); - cFYI(1, ("dnotify on %s Action: 0x%x", - pnotify->FileName, pnotify->Action)); + cFYI(1, "dnotify on %s Action: 0x%x", + pnotify->FileName, pnotify->Action); /* cifs_dump_mem("Rcvd notify Data: ",buf, sizeof(struct smb_hdr)+60); */ return true; } if (pSMBr->hdr.Status.CifsError) { - cFYI(1, ("notify err 0x%d", - pSMBr->hdr.Status.CifsError)); + cFYI(1, "notify err 0x%d", + pSMBr->hdr.Status.CifsError); return true; } return false; @@ -535,7 +534,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) large dirty files cached on the client */ if ((NT_STATUS_INVALID_HANDLE) == le32_to_cpu(pSMB->hdr.Status.CifsError)) { - cFYI(1, ("invalid handle on oplock break")); + cFYI(1, "invalid handle on oplock break"); return true; } else if (ERRbadfid == le16_to_cpu(pSMB->hdr.Status.DosError.Error)) { @@ -547,8 +546,8 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) if (pSMB->hdr.WordCount != 8) return false; - cFYI(1, ("oplock type 0x%d level 0x%d", - pSMB->LockType, pSMB->OplockLevel)); + cFYI(1, "oplock type 0x%d level 0x%d", + pSMB->LockType, pSMB->OplockLevel); if (!(pSMB->LockType & LOCKING_ANDX_OPLOCK_RELEASE)) return false; @@ -579,15 +578,15 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) return true; } - cFYI(1, ("file id match, oplock break")); + cFYI(1, "file id match, oplock break"); pCifsInode = CIFS_I(netfile->pInode); pCifsInode->clientCanCacheAll = false; if (pSMB->OplockLevel == 0) pCifsInode->clientCanCacheRead = false; rc = slow_work_enqueue(&netfile->oplock_break); if (rc) { - cERROR(1, ("failed to enqueue oplock " - "break: %d\n", rc)); + cERROR(1, "failed to enqueue oplock " + "break: %d\n", rc); } else { netfile->oplock_break_cancelled = false; } @@ -597,12 +596,12 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) } read_unlock(&GlobalSMBSeslock); read_unlock(&cifs_tcp_ses_lock); - cFYI(1, ("No matching file for oplock break")); + cFYI(1, "No matching file for oplock break"); return true; } } read_unlock(&cifs_tcp_ses_lock); - cFYI(1, ("Can not process oplock break for non-existent connection")); + cFYI(1, "Can not process oplock break for non-existent connection"); return true; } @@ -721,11 +720,11 @@ cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb) { if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM; - cERROR(1, ("Autodisabling the use of server inode numbers on " + cERROR(1, "Autodisabling the use of server inode numbers on " "%s. This server doesn't seem to support them " "properly. Hardlinks will not be recognized on this " "mount. Consider mounting with the \"noserverino\" " "option to silence this message.", - cifs_sb->tcon->treeName)); + cifs_sb->tcon->treeName); } } diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index bd6d689..d35d528 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c @@ -149,7 +149,7 @@ cifs_inet_pton(const int address_family, const char *cp, void *dst) else if (address_family == AF_INET6) ret = in6_pton(cp, -1 /* len */, dst , '\\', NULL); - cFYI(DBG2, ("address conversion returned %d for %s", ret, cp)); + cFYI(DBG2, "address conversion returned %d for %s", ret, cp); if (ret > 0) ret = 1; return ret; @@ -870,8 +870,8 @@ map_smb_to_linux_error(struct smb_hdr *smb, int logErr) } /* else ERRHRD class errors or junk - return EIO */ - cFYI(1, ("Mapping smb error code %d to POSIX err %d", - smberrcode, rc)); + cFYI(1, "Mapping smb error code %d to POSIX err %d", + smberrcode, rc); /* generic corrective action e.g. reconnect SMB session on * ERRbaduid could be added */ @@ -940,20 +940,20 @@ struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, int offset) SMB_TIME *st = (SMB_TIME *)&time; SMB_DATE *sd = (SMB_DATE *)&date; - cFYI(1, ("date %d time %d", date, time)); + cFYI(1, "date %d time %d", date, time); sec = 2 * st->TwoSeconds; min = st->Minutes; if ((sec > 59) || (min > 59)) - cERROR(1, ("illegal time min %d sec %d", min, sec)); + cERROR(1, "illegal time min %d sec %d", min, sec); sec += (min * 60); sec += 60 * 60 * st->Hours; if (st->Hours > 24) - cERROR(1, ("illegal hours %d", st->Hours)); + cERROR(1, "illegal hours %d", st->Hours); days = sd->Day; month = sd->Month; if ((days > 31) || (month > 12)) { - cERROR(1, ("illegal date, month %d day: %d", month, days)); + cERROR(1, "illegal date, month %d day: %d", month, days); if (month > 12) month = 12; } @@ -979,7 +979,7 @@ struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, int offset) ts.tv_sec = sec + offset; - /* cFYI(1,("sec after cnvrt dos to unix time %d",sec)); */ + /* cFYI(1, "sec after cnvrt dos to unix time %d",sec); */ ts.tv_nsec = 0; return ts; diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 18e0bc1..daf1753 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -47,15 +47,15 @@ static void dump_cifs_file_struct(struct file *file, char *label) if (file) { cf = file->private_data; if (cf == NULL) { - cFYI(1, ("empty cifs private file data")); + cFYI(1, "empty cifs private file data"); return; } if (cf->invalidHandle) - cFYI(1, ("invalid handle")); + cFYI(1, "invalid handle"); if (cf->srch_inf.endOfSearch) - cFYI(1, ("end of search")); + cFYI(1, "end of search"); if (cf->srch_inf.emptyDir) - cFYI(1, ("empty dir")); + cFYI(1, "empty dir"); } } #else @@ -76,7 +76,7 @@ cifs_readdir_lookup(struct dentry *parent, struct qstr *name, struct inode *inode; struct super_block *sb = parent->d_inode->i_sb; - cFYI(1, ("For %s", name->name)); + cFYI(1, "For %s", name->name); if (parent->d_op && parent->d_op->d_hash) parent->d_op->d_hash(parent, name); @@ -214,7 +214,7 @@ int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb, fid, cifs_sb->local_nls); if (CIFSSMBClose(xid, ptcon, fid)) { - cFYI(1, ("Error closing temporary reparsepoint open)")); + cFYI(1, "Error closing temporary reparsepoint open"); } } } @@ -252,7 +252,7 @@ static int initiate_cifs_search(const int xid, struct file *file) if (full_path == NULL) return -ENOMEM; - cFYI(1, ("Full path: %s start at: %lld", full_path, file->f_pos)); + cFYI(1, "Full path: %s start at: %lld", full_path, file->f_pos); ffirst_retry: /* test for Unix extensions */ @@ -297,7 +297,7 @@ static int cifs_unicode_bytelen(char *str) if (ustr[len] == 0) return len << 1; } - cFYI(1, ("Unicode string longer than PATH_MAX found")); + cFYI(1, "Unicode string longer than PATH_MAX found"); return len << 1; } @@ -314,19 +314,18 @@ static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level) pfData->FileNameLength; } else new_entry = old_entry + le32_to_cpu(pDirInfo->NextEntryOffset); - cFYI(1, ("new entry %p old entry %p", new_entry, old_entry)); + cFYI(1, "new entry %p old entry %p", new_entry, old_entry); /* validate that new_entry is not past end of SMB */ if (new_entry >= end_of_smb) { - cERROR(1, - ("search entry %p began after end of SMB %p old entry %p", - new_entry, end_of_smb, old_entry)); + cERROR(1, "search entry %p began after end of SMB %p old entry %p", + new_entry, end_of_smb, old_entry); return NULL; } else if (((level == SMB_FIND_FILE_INFO_STANDARD) && (new_entry + sizeof(FIND_FILE_STANDARD_INFO) > end_of_smb)) || ((level != SMB_FIND_FILE_INFO_STANDARD) && (new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb))) { - cERROR(1, ("search entry %p extends after end of SMB %p", - new_entry, end_of_smb)); + cERROR(1, "search entry %p extends after end of SMB %p", + new_entry, end_of_smb); return NULL; } else return new_entry; @@ -380,8 +379,8 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile) filename = &pFindData->FileName[0]; len = pFindData->FileNameLength; } else { - cFYI(1, ("Unknown findfirst level %d", - cfile->srch_inf.info_level)); + cFYI(1, "Unknown findfirst level %d", + cfile->srch_inf.info_level); } if (filename) { @@ -481,7 +480,7 @@ static int cifs_save_resume_key(const char *current_entry, len = (unsigned int)pFindData->FileNameLength; cifsFile->srch_inf.resume_key = pFindData->ResumeKey; } else { - cFYI(1, ("Unknown findfirst level %d", level)); + cFYI(1, "Unknown findfirst level %d", level); return -EINVAL; } cifsFile->srch_inf.resume_name_len = len; @@ -525,7 +524,7 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, is_dir_changed(file)) || (index_to_find < first_entry_in_buffer)) { /* close and restart search */ - cFYI(1, ("search backing up - close and restart search")); + cFYI(1, "search backing up - close and restart search"); write_lock(&GlobalSMBSeslock); if (!cifsFile->srch_inf.endOfSearch && !cifsFile->invalidHandle) { @@ -535,7 +534,7 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, } else write_unlock(&GlobalSMBSeslock); if (cifsFile->srch_inf.ntwrk_buf_start) { - cFYI(1, ("freeing SMB ff cache buf on search rewind")); + cFYI(1, "freeing SMB ff cache buf on search rewind"); if (cifsFile->srch_inf.smallBuf) cifs_small_buf_release(cifsFile->srch_inf. ntwrk_buf_start); @@ -546,8 +545,8 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, } rc = initiate_cifs_search(xid, file); if (rc) { - cFYI(1, ("error %d reinitiating a search on rewind", - rc)); + cFYI(1, "error %d reinitiating a search on rewind", + rc); return rc; } cifs_save_resume_key(cifsFile->srch_inf.last_entry, cifsFile); @@ -555,7 +554,7 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, while ((index_to_find >= cifsFile->srch_inf.index_of_last_entry) && (rc == 0) && !cifsFile->srch_inf.endOfSearch) { - cFYI(1, ("calling findnext2")); + cFYI(1, "calling findnext2"); rc = CIFSFindNext(xid, pTcon, cifsFile->netfid, &cifsFile->srch_inf); cifs_save_resume_key(cifsFile->srch_inf.last_entry, cifsFile); @@ -575,7 +574,7 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry - cifsFile->srch_inf.entries_in_buffer; pos_in_buf = index_to_find - first_entry_in_buffer; - cFYI(1, ("found entry - pos_in_buf %d", pos_in_buf)); + cFYI(1, "found entry - pos_in_buf %d", pos_in_buf); for (i = 0; (i < (pos_in_buf)) && (current_entry != NULL); i++) { /* go entry by entry figuring out which is first */ @@ -584,19 +583,19 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, } if ((current_entry == NULL) && (i < pos_in_buf)) { /* BB fixme - check if we should flag this error */ - cERROR(1, ("reached end of buf searching for pos in buf" + cERROR(1, "reached end of buf searching for pos in buf" " %d index to find %lld rc %d", - pos_in_buf, index_to_find, rc)); + pos_in_buf, index_to_find, rc); } rc = 0; *ppCurrentEntry = current_entry; } else { - cFYI(1, ("index not in buffer - could not findnext into it")); + cFYI(1, "index not in buffer - could not findnext into it"); return 0; } if (pos_in_buf >= cifsFile->srch_inf.entries_in_buffer) { - cFYI(1, ("can not return entries pos_in_buf beyond last")); + cFYI(1, "can not return entries pos_in_buf beyond last"); *num_to_ret = 0; } else *num_to_ret = cifsFile->srch_inf.entries_in_buffer - pos_in_buf; @@ -656,12 +655,12 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst, /* one byte length, no name conversion */ len = (unsigned int)pFindData->FileNameLength; } else { - cFYI(1, ("Unknown findfirst level %d", level)); + cFYI(1, "Unknown findfirst level %d", level); return -EINVAL; } if (len > max_len) { - cERROR(1, ("bad search response length %d past smb end", len)); + cERROR(1, "bad search response length %d past smb end", len); return -EINVAL; } @@ -754,7 +753,7 @@ static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir, * case already. Why should we be clobbering other errors from it? */ if (rc) { - cFYI(1, ("filldir rc = %d", rc)); + cFYI(1, "filldir rc = %d", rc); rc = -EOVERFLOW; } dput(tmp_dentry); @@ -786,7 +785,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) case 0: if (filldir(direntry, ".", 1, file->f_pos, file->f_path.dentry->d_inode->i_ino, DT_DIR) < 0) { - cERROR(1, ("Filldir for current dir failed")); + cERROR(1, "Filldir for current dir failed"); rc = -ENOMEM; break; } @@ -794,7 +793,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) case 1: if (filldir(direntry, "..", 2, file->f_pos, file->f_path.dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) { - cERROR(1, ("Filldir for parent dir failed")); + cERROR(1, "Filldir for parent dir failed"); rc = -ENOMEM; break; } @@ -807,7 +806,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) if (file->private_data == NULL) { rc = initiate_cifs_search(xid, file); - cFYI(1, ("initiate cifs search rc %d", rc)); + cFYI(1, "initiate cifs search rc %d", rc); if (rc) { FreeXid(xid); return rc; @@ -821,7 +820,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) cifsFile = file->private_data; if (cifsFile->srch_inf.endOfSearch) { if (cifsFile->srch_inf.emptyDir) { - cFYI(1, ("End of search, empty dir")); + cFYI(1, "End of search, empty dir"); rc = 0; break; } @@ -833,16 +832,16 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) rc = find_cifs_entry(xid, pTcon, file, ¤t_entry, &num_to_fill); if (rc) { - cFYI(1, ("fce error %d", rc)); + cFYI(1, "fce error %d", rc); goto rddir2_exit; } else if (current_entry != NULL) { - cFYI(1, ("entry %lld found", file->f_pos)); + cFYI(1, "entry %lld found", file->f_pos); } else { - cFYI(1, ("could not find entry")); + cFYI(1, "could not find entry"); goto rddir2_exit; } - cFYI(1, ("loop through %d times filling dir for net buf %p", - num_to_fill, cifsFile->srch_inf.ntwrk_buf_start)); + cFYI(1, "loop through %d times filling dir for net buf %p", + num_to_fill, cifsFile->srch_inf.ntwrk_buf_start); max_len = smbCalcSize((struct smb_hdr *) cifsFile->srch_inf.ntwrk_buf_start); end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len; @@ -851,8 +850,8 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) for (i = 0; (i < num_to_fill) && (rc == 0); i++) { if (current_entry == NULL) { /* evaluate whether this case is an error */ - cERROR(1, ("past SMB end, num to fill %d i %d", - num_to_fill, i)); + cERROR(1, "past SMB end, num to fill %d i %d", + num_to_fill, i); break; } /* if buggy server returns . and .. late do @@ -867,8 +866,8 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) file->f_pos++; if (file->f_pos == cifsFile->srch_inf.index_of_last_entry) { - cFYI(1, ("last entry in buf at pos %lld %s", - file->f_pos, tmp_buf)); + cFYI(1, "last entry in buf at pos %lld %s", + file->f_pos, tmp_buf); cifs_save_resume_key(current_entry, cifsFile); break; } else diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 7c3fd74..da9729d 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -284,7 +284,7 @@ decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifsSesInfo *ses, int len; char *data = *pbcc_area; - cFYI(1, ("bleft %d", bleft)); + cFYI(1, "bleft %d", bleft); /* * Windows servers do not always double null terminate their final @@ -301,7 +301,7 @@ decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifsSesInfo *ses, kfree(ses->serverOS); ses->serverOS = cifs_strndup_from_ucs(data, bleft, true, nls_cp); - cFYI(1, ("serverOS=%s", ses->serverOS)); + cFYI(1, "serverOS=%s", ses->serverOS); len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2; data += len; bleft -= len; @@ -310,7 +310,7 @@ decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifsSesInfo *ses, kfree(ses->serverNOS); ses->serverNOS = cifs_strndup_from_ucs(data, bleft, true, nls_cp); - cFYI(1, ("serverNOS=%s", ses->serverNOS)); + cFYI(1, "serverNOS=%s", ses->serverNOS); len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2; data += len; bleft -= len; @@ -319,7 +319,7 @@ decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifsSesInfo *ses, kfree(ses->serverDomain); ses->serverDomain = cifs_strndup_from_ucs(data, bleft, true, nls_cp); - cFYI(1, ("serverDomain=%s", ses->serverDomain)); + cFYI(1, "serverDomain=%s", ses->serverDomain); return; } @@ -332,7 +332,7 @@ static int decode_ascii_ssetup(char **pbcc_area, int bleft, int len; char *bcc_ptr = *pbcc_area; - cFYI(1, ("decode sessetup ascii. bleft %d", bleft)); + cFYI(1, "decode sessetup ascii. bleft %d", bleft); len = strnlen(bcc_ptr, bleft); if (len >= bleft) @@ -344,7 +344,7 @@ static int decode_ascii_ssetup(char **pbcc_area, int bleft, if (ses->serverOS) strncpy(ses->serverOS, bcc_ptr, len); if (strncmp(ses->serverOS, "OS/2", 4) == 0) { - cFYI(1, ("OS/2 server")); + cFYI(1, "OS/2 server"); ses->flags |= CIFS_SES_OS2; } @@ -373,7 +373,7 @@ static int decode_ascii_ssetup(char **pbcc_area, int bleft, /* BB For newer servers which do not support Unicode, but thus do return domain here we could add parsing for it later, but it is not very important */ - cFYI(1, ("ascii: bytes left %d", bleft)); + cFYI(1, "ascii: bytes left %d", bleft); return rc; } @@ -384,16 +384,16 @@ static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr; if (blob_len < sizeof(CHALLENGE_MESSAGE)) { - cERROR(1, ("challenge blob len %d too small", blob_len)); + cERROR(1, "challenge blob len %d too small", blob_len); return -EINVAL; } if (memcmp(pblob->Signature, "NTLMSSP", 8)) { - cERROR(1, ("blob signature incorrect %s", pblob->Signature)); + cERROR(1, "blob signature incorrect %s", pblob->Signature); return -EINVAL; } if (pblob->MessageType != NtLmChallenge) { - cERROR(1, ("Incorrect message type %d", pblob->MessageType)); + cERROR(1, "Incorrect message type %d", pblob->MessageType); return -EINVAL; } @@ -583,7 +583,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, type = ses->server->secType; - cFYI(1, ("sess setup type %d", type)); + cFYI(1, "sess setup type %d", type); ssetup_ntlmssp_authenticate: if (phase == NtLmChallenge) phase = NtLmAuthenticate; /* if ntlmssp, now final phase */ @@ -664,7 +664,7 @@ ssetup_ntlmssp_authenticate: changed to do higher than lanman dialect and we reconnected would we ever calc signing_key? */ - cFYI(1, ("Negotiating LANMAN setting up strings")); + cFYI(1, "Negotiating LANMAN setting up strings"); /* Unicode not allowed for LANMAN dialects */ ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); #endif @@ -758,17 +758,17 @@ ssetup_ntlmssp_authenticate: /* check version field to make sure that cifs.upcall is sending us a response in an expected form */ if (msg->version != CIFS_SPNEGO_UPCALL_VERSION) { - cERROR(1, ("incorrect version of cifs.upcall (expected" + cERROR(1, "incorrect version of cifs.upcall (expected" " %d but got %d)", - CIFS_SPNEGO_UPCALL_VERSION, msg->version)); + CIFS_SPNEGO_UPCALL_VERSION, msg->version); rc = -EKEYREJECTED; goto ssetup_exit; } /* bail out if key is too long */ if (msg->sesskey_len > sizeof(ses->server->mac_signing_key.data.krb5)) { - cERROR(1, ("Kerberos signing key too long (%u bytes)", - msg->sesskey_len)); + cERROR(1, "Kerberos signing key too long (%u bytes)", + msg->sesskey_len); rc = -EOVERFLOW; goto ssetup_exit; } @@ -796,7 +796,7 @@ ssetup_ntlmssp_authenticate: /* BB: is this right? */ ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); #else /* ! CONFIG_CIFS_UPCALL */ - cERROR(1, ("Kerberos negotiated but upcall support disabled!")); + cERROR(1, "Kerberos negotiated but upcall support disabled!"); rc = -ENOSYS; goto ssetup_exit; #endif /* CONFIG_CIFS_UPCALL */ @@ -804,12 +804,12 @@ ssetup_ntlmssp_authenticate: #ifdef CONFIG_CIFS_EXPERIMENTAL if (type == RawNTLMSSP) { if ((pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) == 0) { - cERROR(1, ("NTLMSSP requires Unicode support")); + cERROR(1, "NTLMSSP requires Unicode support"); rc = -ENOSYS; goto ssetup_exit; } - cFYI(1, ("ntlmssp session setup phase %d", phase)); + cFYI(1, "ntlmssp session setup phase %d", phase); pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; capabilities |= CAP_EXTENDED_SECURITY; pSMB->req.Capabilities |= cpu_to_le32(capabilities); @@ -827,7 +827,7 @@ ssetup_ntlmssp_authenticate: on the response (challenge) */ smb_buf->Uid = ses->Suid; } else { - cERROR(1, ("invalid phase %d", phase)); + cERROR(1, "invalid phase %d", phase); rc = -ENOSYS; goto ssetup_exit; } @@ -839,12 +839,12 @@ ssetup_ntlmssp_authenticate: } unicode_oslm_strings(&bcc_ptr, nls_cp); } else { - cERROR(1, ("secType %d not supported!", type)); + cERROR(1, "secType %d not supported!", type); rc = -ENOSYS; goto ssetup_exit; } #else - cERROR(1, ("secType %d not supported!", type)); + cERROR(1, "secType %d not supported!", type); rc = -ENOSYS; goto ssetup_exit; #endif @@ -862,7 +862,7 @@ ssetup_ntlmssp_authenticate: CIFS_STD_OP /* not long */ | CIFS_LOG_ERROR); /* SMB request buf freed in SendReceive2 */ - cFYI(1, ("ssetup rc from sendrecv2 is %d", rc)); + cFYI(1, "ssetup rc from sendrecv2 is %d", rc); pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base; smb_buf = (struct smb_hdr *)iov[0].iov_base; @@ -870,7 +870,7 @@ ssetup_ntlmssp_authenticate: if ((type == RawNTLMSSP) && (smb_buf->Status.CifsError == cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))) { if (phase != NtLmNegotiate) { - cERROR(1, ("Unexpected more processing error")); + cERROR(1, "Unexpected more processing error"); goto ssetup_exit; } /* NTLMSSP Negotiate sent now processing challenge (response) */ @@ -882,14 +882,14 @@ ssetup_ntlmssp_authenticate: if ((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) { rc = -EIO; - cERROR(1, ("bad word count %d", smb_buf->WordCount)); + cERROR(1, "bad word count %d", smb_buf->WordCount); goto ssetup_exit; } action = le16_to_cpu(pSMB->resp.Action); if (action & GUEST_LOGIN) - cFYI(1, ("Guest login")); /* BB mark SesInfo struct? */ + cFYI(1, "Guest login"); /* BB mark SesInfo struct? */ ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */ - cFYI(1, ("UID = %d ", ses->Suid)); + cFYI(1, "UID = %d ", ses->Suid); /* response can have either 3 or 4 word count - Samba sends 3 */ /* and lanman response is 3 */ bytes_remaining = BCC(smb_buf); @@ -899,7 +899,7 @@ ssetup_ntlmssp_authenticate: __u16 blob_len; blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength); if (blob_len > bytes_remaining) { - cERROR(1, ("bad security blob length %d", blob_len)); + cERROR(1, "bad security blob length %d", blob_len); rc = -EINVAL; goto ssetup_exit; } @@ -933,7 +933,7 @@ ssetup_exit: } kfree(str_area); if (resp_buf_type == CIFS_SMALL_BUFFER) { - cFYI(1, ("ssetup freeing small buf %p", iov[0].iov_base)); + cFYI(1, "ssetup freeing small buf %p", iov[0].iov_base); cifs_small_buf_release(iov[0].iov_base); } else if (resp_buf_type == CIFS_LARGE_BUFFER) cifs_buf_release(iov[0].iov_base); diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index ad081fe..28f563c 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -43,7 +43,7 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server) struct mid_q_entry *temp; if (server == NULL) { - cERROR(1, ("Null TCP session in AllocMidQEntry")); + cERROR(1, "Null TCP session in AllocMidQEntry"); return NULL; } @@ -55,7 +55,7 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server) temp->mid = smb_buffer->Mid; /* always LE */ temp->pid = current->pid; temp->command = smb_buffer->Command; - cFYI(1, ("For smb_command %d", temp->command)); + cFYI(1, "For smb_command %d", temp->command); /* do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */ /* when mid allocated can be before when sent */ temp->when_alloc = jiffies; @@ -140,7 +140,7 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec) total_len += iov[i].iov_len; smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length); - cFYI(1, ("Sending smb: total_len %d", total_len)); + cFYI(1, "Sending smb: total_len %d", total_len); dump_smb(smb_buffer, len); i = 0; @@ -168,9 +168,8 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec) reconnect which may clear the network problem. */ if ((i >= 14) || (!server->noblocksnd && (i > 2))) { - cERROR(1, - ("sends on sock %p stuck for 15 seconds", - ssocket)); + cERROR(1, "sends on sock %p stuck for 15 seconds", + ssocket); rc = -EAGAIN; break; } @@ -184,13 +183,13 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec) total_len = 0; break; } else if (rc > total_len) { - cERROR(1, ("sent %d requested %d", rc, total_len)); + cERROR(1, "sent %d requested %d", rc, total_len); break; } if (rc == 0) { /* should never happen, letting socket clear before retrying is our only obvious option here */ - cERROR(1, ("tcp sent no data")); + cERROR(1, "tcp sent no data"); msleep(500); continue; } @@ -213,8 +212,8 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec) } if ((total_len > 0) && (total_len != smb_buf_length + 4)) { - cFYI(1, ("partial send (%d remaining), terminating session", - total_len)); + cFYI(1, "partial send (%d remaining), terminating session", + total_len); /* If we have only sent part of an SMB then the next SMB could be taken as the remainder of this one. We need to kill the socket so the server throws away the partial @@ -223,7 +222,7 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec) } if (rc < 0) { - cERROR(1, ("Error %d sending data on socket to server", rc)); + cERROR(1, "Error %d sending data on socket to server", rc); } else rc = 0; @@ -296,7 +295,7 @@ static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf, } if (ses->server->tcpStatus == CifsNeedReconnect) { - cFYI(1, ("tcp session dead - return to caller to retry")); + cFYI(1, "tcp session dead - return to caller to retry"); return -EAGAIN; } @@ -348,7 +347,7 @@ static int wait_for_response(struct cifsSesInfo *ses, lrt += time_to_wait; if (time_after(jiffies, lrt)) { /* No replies for time_to_wait. */ - cERROR(1, ("server not responding")); + cERROR(1, "server not responding"); return -1; } } else { @@ -379,7 +378,7 @@ SendReceiveNoRsp(const unsigned int xid, struct cifsSesInfo *ses, iov[0].iov_len = in_buf->smb_buf_length + 4; flags |= CIFS_NO_RESP; rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags); - cFYI(DBG2, ("SendRcvNoRsp flags %d rc %d", flags, rc)); + cFYI(DBG2, "SendRcvNoRsp flags %d rc %d", flags, rc); return rc; } @@ -402,7 +401,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, if ((ses == NULL) || (ses->server == NULL)) { cifs_small_buf_release(in_buf); - cERROR(1, ("Null session")); + cERROR(1, "Null session"); return -EIO; } @@ -471,7 +470,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, else if (long_op == CIFS_BLOCKING_OP) timeout = 0x7FFFFFFF; /* large, but not so large as to wrap */ else { - cERROR(1, ("unknown timeout flag %d", long_op)); + cERROR(1, "unknown timeout flag %d", long_op); rc = -EIO; goto out; } @@ -490,8 +489,8 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, spin_lock(&GlobalMid_Lock); if (midQ->resp_buf == NULL) { - cERROR(1, ("No response to cmd %d mid %d", - midQ->command, midQ->mid)); + cERROR(1, "No response to cmd %d mid %d", + midQ->command, midQ->mid); if (midQ->midState == MID_REQUEST_SUBMITTED) { if (ses->server->tcpStatus == CifsExiting) rc = -EHOSTDOWN; @@ -504,7 +503,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, if (rc != -EHOSTDOWN) { if (midQ->midState == MID_RETRY_NEEDED) { rc = -EAGAIN; - cFYI(1, ("marking request for retry")); + cFYI(1, "marking request for retry"); } else { rc = -EIO; } @@ -521,8 +520,8 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, receive_len = midQ->resp_buf->smb_buf_length; if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { - cERROR(1, ("Frame too large received. Length: %d Xid: %d", - receive_len, xid)); + cERROR(1, "Frame too large received. Length: %d Xid: %d", + receive_len, xid); rc = -EIO; goto out; } @@ -548,7 +547,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, &ses->server->mac_signing_key, midQ->sequence_number+1); if (rc) { - cERROR(1, ("Unexpected SMB signature")); + cERROR(1, "Unexpected SMB signature"); /* BB FIXME add code to kill session */ } } @@ -569,7 +568,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, DeleteMidQEntry */ } else { rc = -EIO; - cFYI(1, ("Bad MID state?")); + cFYI(1, "Bad MID state?"); } out: @@ -591,11 +590,11 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, struct mid_q_entry *midQ; if (ses == NULL) { - cERROR(1, ("Null smb session")); + cERROR(1, "Null smb session"); return -EIO; } if (ses->server == NULL) { - cERROR(1, ("Null tcp session")); + cERROR(1, "Null tcp session"); return -EIO; } @@ -607,8 +606,8 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, use ses->maxReq */ if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { - cERROR(1, ("Illegal length, greater than maximum frame, %d", - in_buf->smb_buf_length)); + cERROR(1, "Illegal length, greater than maximum frame, %d", + in_buf->smb_buf_length); return -EIO; } @@ -665,7 +664,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, else if (long_op == CIFS_BLOCKING_OP) timeout = 0x7FFFFFFF; /* large but no so large as to wrap */ else { - cERROR(1, ("unknown timeout flag %d", long_op)); + cERROR(1, "unknown timeout flag %d", long_op); rc = -EIO; goto out; } @@ -681,8 +680,8 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, spin_lock(&GlobalMid_Lock); if (midQ->resp_buf == NULL) { - cERROR(1, ("No response for cmd %d mid %d", - midQ->command, midQ->mid)); + cERROR(1, "No response for cmd %d mid %d", + midQ->command, midQ->mid); if (midQ->midState == MID_REQUEST_SUBMITTED) { if (ses->server->tcpStatus == CifsExiting) rc = -EHOSTDOWN; @@ -695,7 +694,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, if (rc != -EHOSTDOWN) { if (midQ->midState == MID_RETRY_NEEDED) { rc = -EAGAIN; - cFYI(1, ("marking request for retry")); + cFYI(1, "marking request for retry"); } else { rc = -EIO; } @@ -712,8 +711,8 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, receive_len = midQ->resp_buf->smb_buf_length; if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { - cERROR(1, ("Frame too large received. Length: %d Xid: %d", - receive_len, xid)); + cERROR(1, "Frame too large received. Length: %d Xid: %d", + receive_len, xid); rc = -EIO; goto out; } @@ -736,7 +735,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, &ses->server->mac_signing_key, midQ->sequence_number+1); if (rc) { - cERROR(1, ("Unexpected SMB signature")); + cERROR(1, "Unexpected SMB signature"); /* BB FIXME add code to kill session */ } } @@ -753,7 +752,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf)); } else { rc = -EIO; - cERROR(1, ("Bad MID state?")); + cERROR(1, "Bad MID state?"); } out: @@ -824,13 +823,13 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, struct cifsSesInfo *ses; if (tcon == NULL || tcon->ses == NULL) { - cERROR(1, ("Null smb session")); + cERROR(1, "Null smb session"); return -EIO; } ses = tcon->ses; if (ses->server == NULL) { - cERROR(1, ("Null tcp session")); + cERROR(1, "Null tcp session"); return -EIO; } @@ -842,8 +841,8 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, use ses->maxReq */ if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { - cERROR(1, ("Illegal length, greater than maximum frame, %d", - in_buf->smb_buf_length)); + cERROR(1, "Illegal length, greater than maximum frame, %d", + in_buf->smb_buf_length); return -EIO; } @@ -933,8 +932,8 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, spin_unlock(&GlobalMid_Lock); receive_len = midQ->resp_buf->smb_buf_length; } else { - cERROR(1, ("No response for cmd %d mid %d", - midQ->command, midQ->mid)); + cERROR(1, "No response for cmd %d mid %d", + midQ->command, midQ->mid); if (midQ->midState == MID_REQUEST_SUBMITTED) { if (ses->server->tcpStatus == CifsExiting) rc = -EHOSTDOWN; @@ -947,7 +946,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, if (rc != -EHOSTDOWN) { if (midQ->midState == MID_RETRY_NEEDED) { rc = -EAGAIN; - cFYI(1, ("marking request for retry")); + cFYI(1, "marking request for retry"); } else { rc = -EIO; } @@ -958,8 +957,8 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, } if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { - cERROR(1, ("Frame too large received. Length: %d Xid: %d", - receive_len, xid)); + cERROR(1, "Frame too large received. Length: %d Xid: %d", + receive_len, xid); rc = -EIO; goto out; } @@ -968,7 +967,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, if ((out_buf == NULL) || (midQ->midState != MID_RESPONSE_RECEIVED)) { rc = -EIO; - cERROR(1, ("Bad MID state?")); + cERROR(1, "Bad MID state?"); goto out; } @@ -986,7 +985,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, &ses->server->mac_signing_key, midQ->sequence_number+1); if (rc) { - cERROR(1, ("Unexpected SMB signature")); + cERROR(1, "Unexpected SMB signature"); /* BB FIXME add code to kill session */ } } diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index f555ce0..a150920 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c @@ -70,12 +70,12 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name) return rc; } if (ea_name == NULL) { - cFYI(1, ("Null xattr names not supported")); + cFYI(1, "Null xattr names not supported"); } else if (strncmp(ea_name, CIFS_XATTR_USER_PREFIX, 5) && (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4))) { cFYI(1, - ("illegal xattr request %s (only user namespace supported)", - ea_name)); + "illegal xattr request %s (only user namespace supported)", + ea_name); /* BB what if no namespace prefix? */ /* Should we just pass them to server, except for system and perhaps security prefixes? */ @@ -131,19 +131,19 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, search server for EAs or streams to returns as xattrs */ if (value_size > MAX_EA_VALUE_SIZE) { - cFYI(1, ("size of EA value too large")); + cFYI(1, "size of EA value too large"); kfree(full_path); FreeXid(xid); return -EOPNOTSUPP; } if (ea_name == NULL) { - cFYI(1, ("Null xattr names not supported")); + cFYI(1, "Null xattr names not supported"); } else if (strncmp(ea_name, CIFS_XATTR_USER_PREFIX, 5) == 0) { if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) goto set_ea_exit; if (strncmp(ea_name, CIFS_XATTR_DOS_ATTRIB, 14) == 0) - cFYI(1, ("attempt to set cifs inode metadata")); + cFYI(1, "attempt to set cifs inode metadata"); ea_name += 5; /* skip past user. prefix */ rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value, @@ -169,9 +169,9 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, ACL_TYPE_ACCESS, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - cFYI(1, ("set POSIX ACL rc %d", rc)); + cFYI(1, "set POSIX ACL rc %d", rc); #else - cFYI(1, ("set POSIX ACL not supported")); + cFYI(1, "set POSIX ACL not supported"); #endif } else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT, strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { @@ -182,13 +182,13 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, ACL_TYPE_DEFAULT, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - cFYI(1, ("set POSIX default ACL rc %d", rc)); + cFYI(1, "set POSIX default ACL rc %d", rc); #else - cFYI(1, ("set default POSIX ACL not supported")); + cFYI(1, "set default POSIX ACL not supported"); #endif } else { - cFYI(1, ("illegal xattr request %s (only user namespace" - " supported)", ea_name)); + cFYI(1, "illegal xattr request %s (only user namespace" + " supported)", ea_name); /* BB what if no namespace prefix? */ /* Should we just pass them to server, except for system and perhaps security prefixes? */ @@ -235,13 +235,13 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, /* return dos attributes as pseudo xattr */ /* return alt name if available as pseudo attr */ if (ea_name == NULL) { - cFYI(1, ("Null xattr names not supported")); + cFYI(1, "Null xattr names not supported"); } else if (strncmp(ea_name, CIFS_XATTR_USER_PREFIX, 5) == 0) { if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) goto get_ea_exit; if (strncmp(ea_name, CIFS_XATTR_DOS_ATTRIB, 14) == 0) { - cFYI(1, ("attempt to query cifs inode metadata")); + cFYI(1, "attempt to query cifs inode metadata"); /* revalidate/getattr then populate from inode */ } /* BB add else when above is implemented */ ea_name += 5; /* skip past user. prefix */ @@ -287,7 +287,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, } #endif /* EXPERIMENTAL */ #else - cFYI(1, ("query POSIX ACL not supported yet")); + cFYI(1, "query POSIX ACL not supported yet"); #endif /* CONFIG_CIFS_POSIX */ } else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT, strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { @@ -299,18 +299,18 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); #else - cFYI(1, ("query POSIX default ACL not supported yet")); + cFYI(1, "query POSIX default ACL not supported yet"); #endif } else if (strncmp(ea_name, CIFS_XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) { - cFYI(1, ("Trusted xattr namespace not supported yet")); + cFYI(1, "Trusted xattr namespace not supported yet"); } else if (strncmp(ea_name, CIFS_XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) == 0) { - cFYI(1, ("Security xattr namespace not supported yet")); + cFYI(1, "Security xattr namespace not supported yet"); } else cFYI(1, - ("illegal xattr request %s (only user namespace supported)", - ea_name)); + "illegal xattr request %s (only user namespace supported)", + ea_name); /* We could add an additional check for streams ie if proc/fs/cifs/streamstoxattr is set then -- cgit v0.10.2 From f19159dc5ab9ec28c3b8230689101335d98e2d68 Mon Sep 17 00:00:00 2001 From: Steve French Date: Wed, 21 Apr 2010 04:12:10 +0000 Subject: [CIFS] Cleanup various minor breakage in previous cFYI cleanup Signed-off-by: Steve French diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 7aa57ec..dac7602 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -114,5 +114,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); extern const struct export_operations cifs_export_ops; #endif /* EXPERIMENTAL */ -#define CIFS_VERSION "1.62" +#define CIFS_VERSION "1.63" #endif /* _CIFSFS_H */ diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index be23e42..980c38c 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -1,7 +1,7 @@ /* * fs/cifs/cifssmb.c * - * Copyright (C) International Business Machines Corp., 2002,2009 + * Copyright (C) International Business Machines Corp., 2002,2010 * Author(s): Steve French (sfrench@us.ibm.com) * * Contains the routines for constructing the SMB PDUs themselves @@ -493,14 +493,14 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) goto neg_err_exit; } - cFYI(1, ("LANMAN negotiated")); + cFYI(1, "LANMAN negotiated"); /* we will not end up setting signing flags - as no signing was in LANMAN and server did not return the flags on */ goto signing_check; #else /* weak security disabled */ } else if (pSMBr->hdr.WordCount == 13) { - cERROR(1, ("mount failed, cifs module not built " - "with CIFS_WEAK_PW_HASH support")); + cERROR(1, "mount failed, cifs module not built " + "with CIFS_WEAK_PW_HASH support"); rc = -EOPNOTSUPP; #endif /* WEAK_PW_HASH */ goto neg_err_exit; @@ -1513,7 +1513,7 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, (struct smb_hdr *) pSMBr, &bytes_returned, long_op); cifs_stats_inc(&tcon->num_writes); if (rc) { - cFYI(1, ("Send error in write = %d", rc)); + cFYI(1, "Send error in write = %d", rc); } else { *nbytes = le16_to_cpu(pSMBr->CountHigh); *nbytes = (*nbytes) << 16; @@ -2529,7 +2529,7 @@ validate_ntransact(char *buf, char **ppparm, char **ppdata, cFYI(1, "data starts after end of smb"); return -EINVAL; } else if (data_count + *ppdata > end_of_smb) { - cFYI(1, "data %p + count %d (%p) ends after end of smb %p start %p", + cFYI(1, "data %p + count %d (%p) past smb end %p start %p", *ppdata, data_count, (data_count + *ppdata), end_of_smb, pSMBr); return -EINVAL; @@ -3304,7 +3304,7 @@ QFileInfoRetry: rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cFYI(1, ("Send error in QPathInfo = %d", rc)); + cFYI(1, "Send error in QPathInfo = %d", rc); } else { /* decode response */ rc = validate_t2((struct smb_t2_rsp *)pSMBr); @@ -3472,14 +3472,14 @@ UnixQFileInfoRetry: rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { - cFYI(1, ("Send error in QPathInfo = %d", rc)); + cFYI(1, "Send error in QPathInfo = %d", rc); } else { /* decode response */ rc = validate_t2((struct smb_t2_rsp *)pSMBr); if (rc || (pSMBr->ByteCount < sizeof(FILE_UNIX_BASIC_INFO))) { - cERROR(1, ("Malformed FILE_UNIX_BASIC_INFO response.\n" + cERROR(1, "Malformed FILE_UNIX_BASIC_INFO response.\n" "Unix Extensions can be disabled on mount " - "by specifying the nosfu mount option.")); + "by specifying the nosfu mount option."); rc = -EIO; /* bad smb */ } else { __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); @@ -4037,7 +4037,7 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, data_end = (char *)(&(pSMBr->PathConsumed)) + le16_to_cpu(pSMBr->t2.DataCount); - cFYI(1, "num_referrals: %d dfs flags: 0x%x ... \n", + cFYI(1, "num_referrals: %d dfs flags: 0x%x ...\n", *num_of_nodes, le32_to_cpu(pSMBr->DFSFlags)); diff --git a/fs/cifs/file.c b/fs/cifs/file.c index ed3689e..99897e3 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -3,7 +3,7 @@ * * vfs operations that deal with files * - * Copyright (C) International Business Machines Corp., 2002,2007 + * Copyright (C) International Business Machines Corp., 2002,2010 * Author(s): Steve French (sfrench@us.ibm.com) * Jeremy Allison (jra@samba.org) * @@ -855,9 +855,9 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) 0 /* wait flag */); pfLock->fl_type = F_RDLCK; if (rc != 0) - cERROR(1, ("Error unlocking " + cERROR(1, "Error unlocking " "previously locked range %d " - "during test of lock", rc)); + "during test of lock", rc); rc = 0; } else { pfLock->fl_type = F_WRLCK; @@ -1709,7 +1709,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync) unsigned int rpages = 0; int rc = 0; - cFYI(1, "sync page %p",page); + cFYI(1, "sync page %p", page); mapping = page->mapping; if (!mapping) return 0; @@ -1998,7 +1998,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); pTcon = cifs_sb->tcon; - cFYI(DBG2, ("rpages: num pages %d", num_pages)); + cFYI(DBG2, "rpages: num pages %d", num_pages); for (i = 0; i < num_pages; ) { unsigned contig_pages; struct page *tmp_page; @@ -2083,7 +2083,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, } } else { cFYI(1, "No bytes read (%d) at offset %lld . " - "Cleaning remaining pages from readahead list", + "Cleaning remaining pages from readahead list", bytes_read, offset); /* BB turn off caching and do new lookup on file size at server? */ diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 7524a90..b35cb03 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -1,7 +1,7 @@ /* * fs/cifs/inode.c * - * Copyright (C) International Business Machines Corp., 2002,2008 + * Copyright (C) International Business Machines Corp., 2002,2010 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify @@ -86,30 +86,30 @@ cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr) { struct cifsInodeInfo *cifs_i = CIFS_I(inode); - cFYI(1, ("%s: revalidating inode %llu", __func__, cifs_i->uniqueid)); + cFYI(1, "%s: revalidating inode %llu", __func__, cifs_i->uniqueid); if (inode->i_state & I_NEW) { - cFYI(1, ("%s: inode %llu is new", __func__, cifs_i->uniqueid)); + cFYI(1, "%s: inode %llu is new", __func__, cifs_i->uniqueid); return; } /* don't bother with revalidation if we have an oplock */ if (cifs_i->clientCanCacheRead) { - cFYI(1, ("%s: inode %llu is oplocked", __func__, - cifs_i->uniqueid)); + cFYI(1, "%s: inode %llu is oplocked", __func__, + cifs_i->uniqueid); return; } /* revalidate if mtime or size have changed */ if (timespec_equal(&inode->i_mtime, &fattr->cf_mtime) && cifs_i->server_eof == fattr->cf_eof) { - cFYI(1, ("%s: inode %llu is unchanged", __func__, - cifs_i->uniqueid)); + cFYI(1, "%s: inode %llu is unchanged", __func__, + cifs_i->uniqueid); return; } - cFYI(1, ("%s: invalidating inode %llu mapping", __func__, - cifs_i->uniqueid)); + cFYI(1, "%s: invalidating inode %llu mapping", __func__, + cifs_i->uniqueid); cifs_i->invalid_mapping = true; } @@ -1577,9 +1577,9 @@ int cifs_revalidate_dentry(struct dentry *dentry) goto check_inval; } - cFYI(1, ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld " + cFYI(1, "Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld " "jiffies %ld", full_path, inode, inode->i_count.counter, - dentry, dentry->d_time, jiffies)); + dentry, dentry->d_time, jiffies); if (CIFS_SB(sb)->tcon->unix_ext) rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid); -- cgit v0.10.2 From 6eca8cc35b50af1037bc919106dd6dd332c959c2 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 21 Apr 2010 02:01:05 +0200 Subject: perf: Fix perf probe build error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When we run into dry run mode, we want to make write_kprobe_trace_event to succeed on writing the event. Let's initialize it to 0. Fixes the following build error: util/probe-event.c:1266: attention : «ret» may be used uninitialized in this function util/probe-event.c:1266: note: «ret» was declared here Signed-off-by: Frederic Weisbecker Acked-by: Masami Hiramatsu Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo LKML-Reference: <1271808065-25290-1-git-send-regression-fweisbec@gmail.com> Signed-off-by: Ingo Molnar diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 3967f8f..4fb4803 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -1263,7 +1263,7 @@ static struct strlist *get_kprobe_trace_event_names(int fd, bool include_group) static int write_kprobe_trace_event(int fd, struct kprobe_trace_event *tev) { - int ret; + int ret = 0; char *buf = synthesize_kprobe_trace_command(tev); if (!buf) { -- cgit v0.10.2 From 2c964d1f7c87eb71f7902111cd7c8fbba225e4b6 Mon Sep 17 00:00:00 2001 From: Pavel Shilovsky Date: Wed, 21 Apr 2010 19:44:24 +0000 Subject: [CIFS] Fix losing locks during fork() When process does fork() private_data of files with lock list stays the same for file descriptors of the parent and of the child. While finishing the child closes files and deletes locks from the list even if unlocking fails. When the child process finishes the parent doesn't have lock in lock list and can't unlock previously before fork() locked region after the child process finished. This patch provides behaviour to save locks in lock list if unlocking fails. Signed-off-by: Pavel Shilovsky Reviewed-by: Jeff Layton Signed-off-by: Steve French diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 99897e3..2ba4c41 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -922,9 +922,10 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) 1, 0, li->type, false); if (stored_rc) rc = stored_rc; - - list_del(&li->llist); - kfree(li); + else { + list_del(&li->llist); + kfree(li); + } } } mutex_unlock(&fid->lock_mutex); -- cgit v0.10.2 From cecbca96da387428e220e307a9c945e37e2f4d9e Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Sun, 18 Apr 2010 19:08:41 +0200 Subject: tracing: Dump either the oops's cpu source or all cpus buffers The ftrace_dump_on_oops kernel parameter, sysctl and sysrq let one dump every cpu buffers when an oops or panic happens. It's nice when you have few cpus but it may take ages if have many, plus you miss the real origin of the problem in all the cpu traces. Sometimes, all you need is to dump the cpu buffer that triggered the opps, most of the time it is our main interest. This patch modifies ftrace_dump_on_oops to handle this choice. The ftrace_dump_on_oops kernel parameter, when it comes alone, has the same behaviour than before. But ftrace_dump_on_oops=orig_cpu will only dump the buffer of the cpu that oops'ed. Similarly, sysctl kernel.ftrace_dump_on_oops=1 and echo 1 > /proc/sys/kernel/ftrace_dump_on_oops keep their previous behaviour. But setting 2 jumps into cpu origin dump mode. v2: Fix double setup v3: Fix spelling issues reported by Randy Dunlap v4: Also update __ftrace_dump in the selftests Signed-off-by: Frederic Weisbecker Acked-by: David S. Miller Acked-by: Steven Rostedt Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Li Zefan Cc: Lai Jiangshan diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index e4cbca5..ab67b33 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -789,8 +789,12 @@ and is between 256 and 4096 characters. It is defined in the file as early as possible in order to facilitate early boot debugging. - ftrace_dump_on_oops + ftrace_dump_on_oops[=orig_cpu] [FTRACE] will dump the trace buffers on oops. + If no parameter is passed, ftrace will dump + buffers of all CPUs, but if you pass orig_cpu, it will + dump only the buffer of the CPU that triggered the + oops. ftrace_filter=[function-list] [FTRACE] Limit the functions traced by the function diff --git a/Documentation/trace/ftrace.txt b/Documentation/trace/ftrace.txt index 03485bf..5201181 100644 --- a/Documentation/trace/ftrace.txt +++ b/Documentation/trace/ftrace.txt @@ -1337,12 +1337,14 @@ ftrace_dump_on_oops must be set. To set ftrace_dump_on_oops, one can either use the sysctl function or set it via the proc system interface. - sysctl kernel.ftrace_dump_on_oops=1 + sysctl kernel.ftrace_dump_on_oops=n or - echo 1 > /proc/sys/kernel/ftrace_dump_on_oops + echo n > /proc/sys/kernel/ftrace_dump_on_oops +If n = 1, ftrace will dump buffers of all CPUs, if n = 2 ftrace will +only dump the buffer of the CPU that triggered the oops. Here's an example of such a dump after a null pointer dereference in a kernel module: diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 59de252..d4e8b21 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c @@ -289,7 +289,7 @@ static struct sysrq_key_op sysrq_showstate_blocked_op = { static void sysrq_ftrace_dump(int key, struct tty_struct *tty) { - ftrace_dump(); + ftrace_dump(DUMP_ALL); } static struct sysrq_key_op sysrq_ftrace_dump_op = { .handler = sysrq_ftrace_dump, diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index 01e6ade..ea5b1aa 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h @@ -492,7 +492,9 @@ static inline int test_tsk_trace_graph(struct task_struct *tsk) return tsk->trace & TSK_TRACE_FL_GRAPH; } -extern int ftrace_dump_on_oops; +enum ftrace_dump_mode; + +extern enum ftrace_dump_mode ftrace_dump_on_oops; #ifdef CONFIG_PREEMPT #define INIT_TRACE_RECURSION .trace_recursion = 0, diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 9365227..9fb1c12 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -490,6 +490,13 @@ static inline void tracing_off(void) { } static inline void tracing_off_permanent(void) { } static inline int tracing_is_on(void) { return 0; } #endif + +enum ftrace_dump_mode { + DUMP_NONE, + DUMP_ALL, + DUMP_ORIG, +}; + #ifdef CONFIG_TRACING extern void tracing_start(void); extern void tracing_stop(void); @@ -571,7 +578,7 @@ __ftrace_vbprintk(unsigned long ip, const char *fmt, va_list ap); extern int __ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap); -extern void ftrace_dump(void); +extern void ftrace_dump(enum ftrace_dump_mode oops_dump_mode); #else static inline void ftrace_special(unsigned long arg1, unsigned long arg2, unsigned long arg3) { } @@ -592,7 +599,7 @@ ftrace_vprintk(const char *fmt, va_list ap) { return 0; } -static inline void ftrace_dump(void) { } +static inline void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) { } #endif /* CONFIG_TRACING */ /* diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index bed83ca..7b516c7 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -117,9 +117,12 @@ static cpumask_var_t __read_mostly tracing_buffer_mask; * * It is default off, but you can enable it with either specifying * "ftrace_dump_on_oops" in the kernel command line, or setting - * /proc/sys/kernel/ftrace_dump_on_oops to true. + * /proc/sys/kernel/ftrace_dump_on_oops + * Set 1 if you want to dump buffers of all CPUs + * Set 2 if you want to dump the buffer of the CPU that triggered oops */ -int ftrace_dump_on_oops; + +enum ftrace_dump_mode ftrace_dump_on_oops; static int tracing_set_tracer(const char *buf); @@ -139,8 +142,17 @@ __setup("ftrace=", set_cmdline_ftrace); static int __init set_ftrace_dump_on_oops(char *str) { - ftrace_dump_on_oops = 1; - return 1; + if (*str++ != '=' || !*str) { + ftrace_dump_on_oops = DUMP_ALL; + return 1; + } + + if (!strcmp("orig_cpu", str)) { + ftrace_dump_on_oops = DUMP_ORIG; + return 1; + } + + return 0; } __setup("ftrace_dump_on_oops", set_ftrace_dump_on_oops); @@ -4338,7 +4350,7 @@ static int trace_panic_handler(struct notifier_block *this, unsigned long event, void *unused) { if (ftrace_dump_on_oops) - ftrace_dump(); + ftrace_dump(ftrace_dump_on_oops); return NOTIFY_OK; } @@ -4355,7 +4367,7 @@ static int trace_die_handler(struct notifier_block *self, switch (val) { case DIE_OOPS: if (ftrace_dump_on_oops) - ftrace_dump(); + ftrace_dump(ftrace_dump_on_oops); break; default: break; @@ -4396,7 +4408,8 @@ trace_printk_seq(struct trace_seq *s) trace_seq_init(s); } -static void __ftrace_dump(bool disable_tracing) +static void +__ftrace_dump(bool disable_tracing, enum ftrace_dump_mode oops_dump_mode) { static arch_spinlock_t ftrace_dump_lock = (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED; @@ -4429,12 +4442,25 @@ static void __ftrace_dump(bool disable_tracing) /* don't look at user memory in panic mode */ trace_flags &= ~TRACE_ITER_SYM_USEROBJ; - printk(KERN_TRACE "Dumping ftrace buffer:\n"); - /* Simulate the iterator */ iter.tr = &global_trace; iter.trace = current_trace; - iter.cpu_file = TRACE_PIPE_ALL_CPU; + + switch (oops_dump_mode) { + case DUMP_ALL: + iter.cpu_file = TRACE_PIPE_ALL_CPU; + break; + case DUMP_ORIG: + iter.cpu_file = raw_smp_processor_id(); + break; + case DUMP_NONE: + goto out_enable; + default: + printk(KERN_TRACE "Bad dumping mode, switching to all CPUs dump\n"); + iter.cpu_file = TRACE_PIPE_ALL_CPU; + } + + printk(KERN_TRACE "Dumping ftrace buffer:\n"); /* * We need to stop all tracing on all CPUS to read the @@ -4473,6 +4499,7 @@ static void __ftrace_dump(bool disable_tracing) else printk(KERN_TRACE "---------------------------------\n"); + out_enable: /* Re-enable tracing if requested */ if (!disable_tracing) { trace_flags |= old_userobj; @@ -4489,9 +4516,9 @@ static void __ftrace_dump(bool disable_tracing) } /* By default: disable tracing after the dump */ -void ftrace_dump(void) +void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) { - __ftrace_dump(true); + __ftrace_dump(true, oops_dump_mode); } __init static int tracer_alloc_buffers(void) diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c index 9398034..6a9d36d 100644 --- a/kernel/trace/trace_selftest.c +++ b/kernel/trace/trace_selftest.c @@ -256,7 +256,8 @@ trace_selftest_startup_function(struct tracer *trace, struct trace_array *tr) /* Maximum number of functions to trace before diagnosing a hang */ #define GRAPH_MAX_FUNC_TEST 100000000 -static void __ftrace_dump(bool disable_tracing); +static void +__ftrace_dump(bool disable_tracing, enum ftrace_dump_mode oops_dump_mode); static unsigned int graph_hang_thresh; /* Wrap the real function entry probe to avoid possible hanging */ @@ -267,7 +268,7 @@ static int trace_graph_entry_watchdog(struct ftrace_graph_ent *trace) ftrace_graph_stop(); printk(KERN_WARNING "BUG: Function graph tracer hang!\n"); if (ftrace_dump_on_oops) - __ftrace_dump(false); + __ftrace_dump(false, DUMP_ALL); return 0; } -- cgit v0.10.2 From c85b86a6dc7b5b4607c3a14fdbda78df06b5c79f Mon Sep 17 00:00:00 2001 From: Cory Fields Date: Wed, 21 Apr 2010 17:08:24 -0400 Subject: HID: wacom: remove annoying non-error printk This is the only line printed on my "quiet" boot and seems completely unnecessary. Signed-off-by: Cory Fields Signed-off-by: Bastien Nocera Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c index f7700cf..f947d83 100644 --- a/drivers/hid/hid-wacom.c +++ b/drivers/hid/hid-wacom.c @@ -277,7 +277,6 @@ static int __init wacom_init(void) ret = hid_register_driver(&wacom_driver); if (ret) printk(KERN_ERR "can't register wacom driver\n"); - printk(KERN_ERR "wacom driver registered\n"); return ret; } -- cgit v0.10.2 From cd932c593995abee1d1a8a0bfe608f7d103d87ad Mon Sep 17 00:00:00 2001 From: Ian Munsie Date: Tue, 20 Apr 2010 16:58:32 +1000 Subject: perf: Move arch specific code into separate arch directory The perf userspace tool included some architecture specific code to map registers from the DWARF register number into the names used by the regs and stack access API. This moves the architecture specific code out into a separate arch/x86 directory along with the infrastructure required to use it. Signed-off-by: Ian Munsie Acked-by: Masami Hiramatsu Signed-off-by: Paul Mackerras diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 3cb3449..e8bf2e1 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -173,6 +173,20 @@ uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not') uname_P := $(shell sh -c 'uname -p 2>/dev/null || echo not') uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not') +ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ + -e s/arm.*/arm/ -e s/sa110/arm/ \ + -e s/s390x/s390/ -e s/parisc64/parisc/ \ + -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ + -e s/sh[234].*/sh/ ) + +# Additional ARCH settings for x86 +ifeq ($(ARCH),i386) + ARCH := x86 +endif +ifeq ($(ARCH),x86_64) + ARCH := x86 +endif + # CFLAGS and LDFLAGS are for the users to override from the command line. # @@ -285,7 +299,7 @@ endif # Those must not be GNU-specific; they are shared with perl/ which may # be built by a different compiler. (Note that this is an artifact now # but it still might be nice to keep that distinction.) -BASIC_CFLAGS = -Iutil/include +BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include BASIC_LDFLAGS = # Guard against environment variables @@ -367,6 +381,7 @@ LIB_H += util/include/asm/byteorder.h LIB_H += util/include/asm/swab.h LIB_H += util/include/asm/system.h LIB_H += util/include/asm/uaccess.h +LIB_H += util/include/dwarf-regs.h LIB_H += perf.h LIB_H += util/cache.h LIB_H += util/callchain.h @@ -487,6 +502,15 @@ PERFLIBS = $(LIB_FILE) -include config.mak.autogen -include config.mak +ifndef NO_DWARF +ifneq ($(shell sh -c "(echo '\#include '; echo '\#include '; echo 'int main(void) { Dwarf *dbg; dbg = dwarf_begin(0, DWARF_C_READ); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -I/usr/include/elfutils -ldw -lelf -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y) + msg := $(warning No libdw.h found or old libdw.h found, disables dwarf support. Please install elfutils-devel/elfutils-dev); + NO_DWARF := 1 +endif # Dwarf support +endif # NO_DWARF + +-include arch/$(ARCH)/Makefile + ifeq ($(uname_S),Darwin) ifndef NO_FINK ifeq ($(shell test -d /sw/lib && echo y),y) @@ -519,15 +543,15 @@ else msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel and glibc-dev[el]); endif -ifneq ($(shell sh -c "(echo '\#include '; echo '\#include '; echo 'int main(void) { Dwarf *dbg; dbg = dwarf_begin(0, DWARF_C_READ); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -I/usr/include/elfutils -ldw -lelf -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y) - msg := $(warning No libdw.h found or old libdw.h found, disables dwarf support. Please install elfutils-devel/elfutils-dev); -else ifndef NO_DWARF +ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined) + msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled); +else BASIC_CFLAGS += -I/usr/include/elfutils -DDWARF_SUPPORT EXTLIBS += -lelf -ldw LIB_OBJS += $(OUTPUT)util/probe-finder.o -endif -endif +endif # PERF_HAVE_DWARF_REGS +endif # NO_DWARF ifneq ($(shell sh -c "(echo '\#include '; echo 'int main(void) { newtInit(); newtCls(); return newtFinished(); }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -lnewt -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y) msg := $(warning newt not found, disables TUI support. Please install newt-devel or libnewt-dev); diff --git a/tools/perf/arch/x86/Makefile b/tools/perf/arch/x86/Makefile new file mode 100644 index 0000000..15130b50 --- /dev/null +++ b/tools/perf/arch/x86/Makefile @@ -0,0 +1,4 @@ +ifndef NO_DWARF +PERF_HAVE_DWARF_REGS := 1 +LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o +endif diff --git a/tools/perf/arch/x86/util/dwarf-regs.c b/tools/perf/arch/x86/util/dwarf-regs.c new file mode 100644 index 0000000..a794d30 --- /dev/null +++ b/tools/perf/arch/x86/util/dwarf-regs.c @@ -0,0 +1,75 @@ +/* + * dwarf-regs.c : Mapping of DWARF debug register numbers into register names. + * Extracted from probe-finder.c + * + * Written by Masami Hiramatsu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include +#include + +/* + * Generic dwarf analysis helpers + */ + +#define X86_32_MAX_REGS 8 +const char *x86_32_regs_table[X86_32_MAX_REGS] = { + "%ax", + "%cx", + "%dx", + "%bx", + "$stack", /* Stack address instead of %sp */ + "%bp", + "%si", + "%di", +}; + +#define X86_64_MAX_REGS 16 +const char *x86_64_regs_table[X86_64_MAX_REGS] = { + "%ax", + "%dx", + "%cx", + "%bx", + "%si", + "%di", + "%bp", + "%sp", + "%r8", + "%r9", + "%r10", + "%r11", + "%r12", + "%r13", + "%r14", + "%r15", +}; + +/* TODO: switching by dwarf address size */ +#ifdef __x86_64__ +#define ARCH_MAX_REGS X86_64_MAX_REGS +#define arch_regs_table x86_64_regs_table +#else +#define ARCH_MAX_REGS X86_32_MAX_REGS +#define arch_regs_table x86_32_regs_table +#endif + +/* Return architecture dependent register string (for kprobe-tracer) */ +const char *get_arch_regstr(unsigned int n) +{ + return (n <= ARCH_MAX_REGS) ? arch_regs_table[n] : NULL; +} diff --git a/tools/perf/util/include/dwarf-regs.h b/tools/perf/util/include/dwarf-regs.h new file mode 100644 index 0000000..cf6727e --- /dev/null +++ b/tools/perf/util/include/dwarf-regs.h @@ -0,0 +1,8 @@ +#ifndef _PERF_DWARF_REGS_H_ +#define _PERF_DWARF_REGS_H_ + +#ifdef DWARF_SUPPORT +const char *get_arch_regstr(unsigned int n); +#endif + +#endif diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 3e79775..e7ee52f 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "string.h" #include "event.h" @@ -38,61 +39,9 @@ #include "util.h" #include "probe-finder.h" - -/* - * Generic dwarf analysis helpers - */ - -#define X86_32_MAX_REGS 8 -const char *x86_32_regs_table[X86_32_MAX_REGS] = { - "%ax", - "%cx", - "%dx", - "%bx", - "$stack", /* Stack address instead of %sp */ - "%bp", - "%si", - "%di", -}; - -#define X86_64_MAX_REGS 16 -const char *x86_64_regs_table[X86_64_MAX_REGS] = { - "%ax", - "%dx", - "%cx", - "%bx", - "%si", - "%di", - "%bp", - "%sp", - "%r8", - "%r9", - "%r10", - "%r11", - "%r12", - "%r13", - "%r14", - "%r15", -}; - -/* TODO: switching by dwarf address size */ -#ifdef __x86_64__ -#define ARCH_MAX_REGS X86_64_MAX_REGS -#define arch_regs_table x86_64_regs_table -#else -#define ARCH_MAX_REGS X86_32_MAX_REGS -#define arch_regs_table x86_32_regs_table -#endif - /* Kprobe tracer basic type is up to u64 */ #define MAX_BASIC_TYPE_BITS 64 -/* Return architecture dependent register string (for kprobe-tracer) */ -static const char *get_arch_regstr(unsigned int n) -{ - return (n <= ARCH_MAX_REGS) ? arch_regs_table[n] : NULL; -} - /* * Compare the tail of two strings. * Return 0 if whole of either string is same as another's tail part. @@ -447,7 +396,7 @@ static int convert_location(Dwarf_Op *op, struct probe_finder *pf) regs = get_arch_regstr(regn); if (!regs) { - pr_warning("%u exceeds max register number.\n", regn); + pr_warning("Mapping for DWARF register number %u missing on this architecture.", regn); return -ERANGE; } -- cgit v0.10.2 From fead7960f0b645348fa4757100f4d57654bf9ffa Mon Sep 17 00:00:00 2001 From: Ian Munsie Date: Tue, 20 Apr 2010 16:58:33 +1000 Subject: perf probe: Add PowerPC DWARF register number mappings This adds mappings from the register numbers from DWARF to the register names used in the PowerPC Regs and Stack Access API. This allows perf probe to be used to record variable contents on PowerPC. This requires the functionality represented by the config symbol HAVE_REGS_AND_STACK_ACCESS_API in order to function, although it will compile without it. That functionality is added for PowerPC in commit 359e4284 ("powerpc: Add kprobe-based event tracer"). Signed-off-by: Ian Munsie Acked-by: Masami Hiramatsu Signed-off-by: Paul Mackerras diff --git a/tools/perf/arch/powerpc/Makefile b/tools/perf/arch/powerpc/Makefile new file mode 100644 index 0000000..15130b50 --- /dev/null +++ b/tools/perf/arch/powerpc/Makefile @@ -0,0 +1,4 @@ +ifndef NO_DWARF +PERF_HAVE_DWARF_REGS := 1 +LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o +endif diff --git a/tools/perf/arch/powerpc/util/dwarf-regs.c b/tools/perf/arch/powerpc/util/dwarf-regs.c new file mode 100644 index 0000000..48ae0c5 --- /dev/null +++ b/tools/perf/arch/powerpc/util/dwarf-regs.c @@ -0,0 +1,88 @@ +/* + * Mapping of DWARF debug register numbers into register names. + * + * Copyright (C) 2010 Ian Munsie, IBM Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include + + +struct pt_regs_dwarfnum { + const char *name; + unsigned int dwarfnum; +}; + +#define STR(s) #s +#define REG_DWARFNUM_NAME(r, num) {.name = r, .dwarfnum = num} +#define GPR_DWARFNUM_NAME(num) \ + {.name = STR(%gpr##num), .dwarfnum = num} +#define REG_DWARFNUM_END {.name = NULL, .dwarfnum = 0} + +/* + * Reference: + * http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html + */ +static const struct pt_regs_dwarfnum regdwarfnum_table[] = { + GPR_DWARFNUM_NAME(0), + GPR_DWARFNUM_NAME(1), + GPR_DWARFNUM_NAME(2), + GPR_DWARFNUM_NAME(3), + GPR_DWARFNUM_NAME(4), + GPR_DWARFNUM_NAME(5), + GPR_DWARFNUM_NAME(6), + GPR_DWARFNUM_NAME(7), + GPR_DWARFNUM_NAME(8), + GPR_DWARFNUM_NAME(9), + GPR_DWARFNUM_NAME(10), + GPR_DWARFNUM_NAME(11), + GPR_DWARFNUM_NAME(12), + GPR_DWARFNUM_NAME(13), + GPR_DWARFNUM_NAME(14), + GPR_DWARFNUM_NAME(15), + GPR_DWARFNUM_NAME(16), + GPR_DWARFNUM_NAME(17), + GPR_DWARFNUM_NAME(18), + GPR_DWARFNUM_NAME(19), + GPR_DWARFNUM_NAME(20), + GPR_DWARFNUM_NAME(21), + GPR_DWARFNUM_NAME(22), + GPR_DWARFNUM_NAME(23), + GPR_DWARFNUM_NAME(24), + GPR_DWARFNUM_NAME(25), + GPR_DWARFNUM_NAME(26), + GPR_DWARFNUM_NAME(27), + GPR_DWARFNUM_NAME(28), + GPR_DWARFNUM_NAME(29), + GPR_DWARFNUM_NAME(30), + GPR_DWARFNUM_NAME(31), + REG_DWARFNUM_NAME("%msr", 66), + REG_DWARFNUM_NAME("%ctr", 109), + REG_DWARFNUM_NAME("%link", 108), + REG_DWARFNUM_NAME("%xer", 101), + REG_DWARFNUM_NAME("%dar", 119), + REG_DWARFNUM_NAME("%dsisr", 118), + REG_DWARFNUM_END, +}; + +/** + * get_arch_regstr() - lookup register name from it's DWARF register number + * @n: the DWARF register number + * + * get_arch_regstr() returns the name of the register in struct + * regdwarfnum_table from it's DWARF register number. If the register is not + * found in the table, this returns NULL; + */ +const char *get_arch_regstr(unsigned int n) +{ + const struct pt_regs_dwarfnum *roff; + for (roff = regdwarfnum_table; roff->name != NULL; roff++) + if (roff->dwarfnum == n) + return roff->name; + return NULL; +} -- cgit v0.10.2 From fa588e0c57048b3d4bfcd772d80dc0615f83fd35 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 22 Apr 2010 19:21:55 +0000 Subject: [CIFS] Allow null nd (as nfs server uses) on create While creating a file on a server which supports unix extensions such as Samba, if a file is being created which does not supply nameidata (i.e. nd is null), cifs client can oops when calling cifs_posix_open. Signed-off-by: Shirish Pargaonkar Signed-off-by: Steve French diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 32262e1..cc622a7 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -107,8 +107,10 @@ extern struct cifsFileInfo *cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, struct file *file, struct vfsmount *mnt, unsigned int oflags); extern int cifs_posix_open(char *full_path, struct inode **pinode, - struct vfsmount *mnt, int mode, int oflags, - __u32 *poplock, __u16 *pnetfid, int xid); + struct vfsmount *mnt, + struct super_block *sb, + int mode, int oflags, + __u32 *poplock, __u16 *pnetfid, int xid); extern void cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info, struct cifs_sb_info *cifs_sb); diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 4aa2fe3..d791d07 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -182,13 +182,14 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, } int cifs_posix_open(char *full_path, struct inode **pinode, - struct vfsmount *mnt, int mode, int oflags, - __u32 *poplock, __u16 *pnetfid, int xid) + struct vfsmount *mnt, struct super_block *sb, + int mode, int oflags, + __u32 *poplock, __u16 *pnetfid, int xid) { int rc; FILE_UNIX_BASIC_INFO *presp_data; __u32 posix_flags = 0; - struct cifs_sb_info *cifs_sb = CIFS_SB(mnt->mnt_sb); + struct cifs_sb_info *cifs_sb = CIFS_SB(sb); struct cifs_fattr fattr; cFYI(1, "posix open %s", full_path); @@ -241,7 +242,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode, /* get new inode and set it up */ if (*pinode == NULL) { - *pinode = cifs_iget(mnt->mnt_sb, &fattr); + *pinode = cifs_iget(sb, &fattr); if (!*pinode) { rc = -ENOMEM; goto posix_open_ret; @@ -250,7 +251,8 @@ int cifs_posix_open(char *full_path, struct inode **pinode, cifs_fattr_to_inode(*pinode, &fattr); } - cifs_new_fileinfo(*pinode, *pnetfid, NULL, mnt, oflags); + if (mnt) + cifs_new_fileinfo(*pinode, *pnetfid, NULL, mnt, oflags); posix_open_ret: kfree(presp_data); @@ -314,13 +316,14 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, if (nd && (nd->flags & LOOKUP_OPEN)) oflags = nd->intent.open.flags; else - oflags = FMODE_READ; + oflags = FMODE_READ | SMB_O_CREAT; if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) && (CIFS_UNIX_POSIX_PATH_OPS_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability))) { - rc = cifs_posix_open(full_path, &newinode, nd->path.mnt, - mode, oflags, &oplock, &fileHandle, xid); + rc = cifs_posix_open(full_path, &newinode, + nd ? nd->path.mnt : NULL, + inode->i_sb, mode, oflags, &oplock, &fileHandle, xid); /* EIO could indicate that (posix open) operation is not supported, despite what server claimed in capability negotation. EREMOTE indicates DFS junction, which is not @@ -677,6 +680,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open && (nd->intent.open.flags & O_CREAT)) { rc = cifs_posix_open(full_path, &newInode, nd->path.mnt, + parent_dir_inode->i_sb, nd->intent.open.create_mode, nd->intent.open.flags, &oplock, &fileHandle, xid); diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 2ba4c41..5f1f768 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -298,10 +298,12 @@ int cifs_open(struct inode *inode, struct file *file) (CIFS_UNIX_POSIX_PATH_OPS_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability))) { int oflags = (int) cifs_posix_convert_flags(file->f_flags); + oflags |= SMB_O_CREAT; /* can not refresh inode info since size could be stale */ rc = cifs_posix_open(full_path, &inode, file->f_path.mnt, - cifs_sb->mnt_file_mode /* ignored */, - oflags, &oplock, &netfid, xid); + inode->i_sb, + cifs_sb->mnt_file_mode /* ignored */, + oflags, &oplock, &netfid, xid); if (rc == 0) { cFYI(1, "posix open succeeded"); /* no need for special case handling of setting mode @@ -513,8 +515,9 @@ reopen_error_exit: int oflags = (int) cifs_posix_convert_flags(file->f_flags); /* can not refresh inode info since size could be stale */ rc = cifs_posix_open(full_path, NULL, file->f_path.mnt, - cifs_sb->mnt_file_mode /* ignored */, - oflags, &oplock, &netfid, xid); + inode->i_sb, + cifs_sb->mnt_file_mode /* ignored */, + oflags, &oplock, &netfid, xid); if (rc == 0) { cFYI(1, "posix reopen succeeded"); goto reopen_success; -- cgit v0.10.2 From 52882173cfed4fabcc1496755000bf022d681e52 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Mon, 19 Apr 2010 13:20:49 +0100 Subject: ARM: 6058/1: Add support for PCI domains This patch adds support for PCI domains on ARM platforms. Also, protect asm/mach/pci.h from multiple inclustions, otherwise build fails because of pci_domain_nr() and pci_proc_domain() redefinitions. Signed-off-by: Anton Vorontsov Signed-off-by: Russell King diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 5c8128c..88f9334 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1074,6 +1074,10 @@ config PCI your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or VESA. If you have PCI, say Y, otherwise N. +config PCI_DOMAINS + bool + depends on PCI + config PCI_SYSCALL def_bool PCI diff --git a/arch/arm/include/asm/mach/pci.h b/arch/arm/include/asm/mach/pci.h index a38bdc7..52f0da1 100644 --- a/arch/arm/include/asm/mach/pci.h +++ b/arch/arm/include/asm/mach/pci.h @@ -8,10 +8,16 @@ * published by the Free Software Foundation. */ +#ifndef __ASM_MACH_PCI_H +#define __ASM_MACH_PCI_H + struct pci_sys_data; struct pci_bus; struct hw_pci { +#ifdef CONFIG_PCI_DOMAINS + int domain; +#endif struct list_head buses; int nr_controllers; int (*setup)(int nr, struct pci_sys_data *); @@ -26,6 +32,9 @@ struct hw_pci { * Per-controller structure */ struct pci_sys_data { +#ifdef CONFIG_PCI_DOMAINS + int domain; +#endif struct list_head node; int busnr; /* primary bus number */ u64 mem_offset; /* bus->cpu memory mapping offset */ @@ -70,3 +79,5 @@ extern int pci_v3_setup(int nr, struct pci_sys_data *); extern struct pci_bus *pci_v3_scan_bus(int nr, struct pci_sys_data *); extern void pci_v3_preinit(void); extern void pci_v3_postinit(void); + +#endif /* __ASM_MACH_PCI_H */ diff --git a/arch/arm/include/asm/pci.h b/arch/arm/include/asm/pci.h index 4798011..92e2a83 100644 --- a/arch/arm/include/asm/pci.h +++ b/arch/arm/include/asm/pci.h @@ -4,8 +4,23 @@ #ifdef __KERNEL__ #include +#include /* for pci_sys_data */ #include /* for PCIBIOS_MIN_* */ +#ifdef CONFIG_PCI_DOMAINS +static inline int pci_domain_nr(struct pci_bus *bus) +{ + struct pci_sys_data *root = bus->sysdata; + + return root->domain; +} + +static inline int pci_proc_domain(struct pci_bus *bus) +{ + return pci_domain_nr(bus); +} +#endif /* CONFIG_PCI_DOMAINS */ + #ifdef CONFIG_PCI_HOST_ITE8152 /* ITE bridge requires setting latency timer to avoid early bus access termination by PIC bus mater devices diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index bd397e0..c6273a3 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -527,6 +527,9 @@ static void __init pcibios_init_hw(struct hw_pci *hw) if (!sys) panic("PCI: unable to allocate sys data!"); +#ifdef CONFIG_PCI_DOMAINS + sys->domain = hw->domain; +#endif sys->hw = hw; sys->busnr = busnr; sys->swizzle = hw->swizzle; -- cgit v0.10.2 From b1ab1b4d9ab9812c77843abec79030292ef0a544 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Thu, 22 Apr 2010 16:06:58 +0200 Subject: x86, cacheinfo: Unify AMD L3 cache index disable checking All F10h CPUs starting with model 8 resp. 9, stepping 1, support L3 cache index disable. Concentrate the family, model, stepping checking at one place and enable the feature implicitly on upcoming Fam10h models. Signed-off-by: Borislav Petkov LKML-Reference: <1271945222-5283-2-git-send-email-bp@amd64.org> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index b3eeb66..acfb083 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -328,18 +328,22 @@ static unsigned int __cpuinit amd_calc_l3_indices(void) static void __cpuinit amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf) { - if (index < 3) + if (boot_cpu_data.x86 != 0x10) return; - if (boot_cpu_data.x86 == 0x11) + if (index < 3) return; /* see errata #382 and #388 */ - if ((boot_cpu_data.x86 == 0x10) && - ((boot_cpu_data.x86_model < 0x8) || - (boot_cpu_data.x86_mask < 0x1))) + if (boot_cpu_data.x86_model < 0x8) return; + if ((boot_cpu_data.x86_model == 0x8 || + boot_cpu_data.x86_model == 0x9) + && + boot_cpu_data.x86_mask < 0x1) + return; + this_leaf->can_disable = true; this_leaf->l3_indices = amd_calc_l3_indices(); } @@ -443,8 +447,7 @@ __cpuinit cpuid4_cache_lookup_regs(int index, if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) { amd_cpuid4(index, &eax, &ebx, &ecx); - if (boot_cpu_data.x86 >= 0x10) - amd_check_l3_disable(index, this_leaf); + amd_check_l3_disable(index, this_leaf); } else { cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx); } -- cgit v0.10.2 From f2b20e41407fccfcfacf927ff91ec888832a37af Mon Sep 17 00:00:00 2001 From: Frank Arnold Date: Thu, 22 Apr 2010 16:06:59 +0200 Subject: x86, cacheinfo: Turn off L3 cache index disable feature in virtualized environments When running a quest kernel on xen we get: BUG: unable to handle kernel NULL pointer dereference at 0000000000000038 IP: [] cpuid4_cache_lookup_regs+0x2ca/0x3df PGD 0 Oops: 0000 [#1] SMP last sysfs file: CPU 0 Modules linked in: Pid: 0, comm: swapper Tainted: G W 2.6.34-rc3 #1 /HVM domU RIP: 0010:[] [] cpuid4_cache_lookup_regs+0x 2ca/0x3df RSP: 0018:ffff880002203e08 EFLAGS: 00010046 RAX: 0000000000000000 RBX: 0000000000000003 RCX: 0000000000000060 RDX: 0000000000000000 RSI: 0000000000000040 RDI: 0000000000000000 RBP: ffff880002203ed8 R08: 00000000000017c0 R09: ffff880002203e38 R10: ffff8800023d5d40 R11: ffffffff81a01e28 R12: ffff880187e6f5c0 R13: ffff880002203e34 R14: ffff880002203e58 R15: ffff880002203e68 FS: 0000000000000000(0000) GS:ffff880002200000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 0000000000000038 CR3: 0000000001a3c000 CR4: 00000000000006f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process swapper (pid: 0, threadinfo ffffffff81a00000, task ffffffff81a44020) Stack: ffffffff810d7ecb ffff880002203e20 ffffffff81059140 ffff880002203e30 <0> ffffffff810d7ec9 0000000002203e40 000000000050d140 ffff880002203e70 <0> 0000000002008140 0000000000000086 ffff880040020140 ffffffff81068b8b Call Trace: [] ? sync_supers_timer_fn+0x0/0x1c [] ? mod_timer+0x23/0x25 [] ? arm_supers_timer+0x34/0x36 [] ? hrtimer_get_next_event+0xa7/0xc3 [] ? get_next_timer_interrupt+0x19a/0x20d [] get_cpu_leaves+0x5c/0x232 [] ? sched_clock_local+0x1c/0x82 [] ? sched_clock_tick+0x75/0x7a [] generic_smp_call_function_single_interrupt+0xae/0xd0 [] smp_call_function_single_interrupt+0x18/0x27 [] call_function_single_interrupt+0x13/0x20 [] ? notifier_call_chain+0x14/0x63 [] ? native_safe_halt+0xc/0xd [] ? default_idle+0x36/0x53 [] cpu_idle+0xaa/0xe4 [] rest_init+0x7e/0x80 [] start_kernel+0x40e/0x419 [] x86_64_start_reservations+0xb3/0xb7 [] x86_64_start_kernel+0xf8/0x107 Code: 14 d5 40 ff ae 81 8b 14 02 31 c0 3b 15 47 1c 8b 00 7d 0e 48 8b 05 36 1c 8b 00 48 63 d2 48 8b 04 d0 c7 85 5c ff ff ff 00 00 00 00 <8b> 70 38 48 8d 8d 5c ff ff ff 48 8b 78 10 ba c4 01 00 00 e8 eb RIP [] cpuid4_cache_lookup_regs+0x2ca/0x3df RSP CR2: 0000000000000038 ---[ end trace a7919e7f17c0a726 ]--- The L3 cache index disable feature of AMD CPUs has to be disabled if the kernel is running as guest on top of a hypervisor because northbridge devices are not available to the guest. Currently, this fixes a boot crash on top of Xen. In the future this will become an issue on KVM as well. Check if northbridge devices are present and do not enable the feature if there are none. Signed-off-by: Frank Arnold LKML-Reference: <1271945222-5283-3-git-send-email-bp@amd64.org> Acked-by: Borislav Petkov Signed-off-by: H. Peter Anvin diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index acfb083..5ab14c8 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -344,6 +344,10 @@ amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf) boot_cpu_data.x86_mask < 0x1) return; + /* not in virtualized environments */ + if (num_k8_northbridges == 0) + return; + this_leaf->can_disable = true; this_leaf->l3_indices = amd_calc_l3_indices(); } -- cgit v0.10.2 From 9350f982e4fe539e83a2d4a13e9b53ad8253c4a8 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Thu, 22 Apr 2010 16:07:00 +0200 Subject: x86, cacheinfo: Reorganize AMD L3 cache structure Add a struct representing L3 cache attributes (subcache sizes and indices count) and move the respective members out of _cpuid4_info. Also, stash the struct pci_dev ptr into the struct simplifying the code even more. There should be no functionality change resulting from this patch except slightly slimming the _cpuid4_info per-cpu vars. Signed-off-by: Borislav Petkov LKML-Reference: <1271945222-5283-4-git-send-email-bp@amd64.org> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index 5ab14c8..ff663ca 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -148,13 +148,19 @@ union _cpuid4_leaf_ecx { u32 full; }; +struct amd_l3_cache { + struct pci_dev *dev; + bool can_disable; + unsigned indices; + u8 subcaches[4]; +}; + struct _cpuid4_info { union _cpuid4_leaf_eax eax; union _cpuid4_leaf_ebx ebx; union _cpuid4_leaf_ecx ecx; unsigned long size; - bool can_disable; - unsigned int l3_indices; + struct amd_l3_cache *l3; DECLARE_BITMAP(shared_cpu_map, NR_CPUS); }; @@ -164,8 +170,7 @@ struct _cpuid4_info_regs { union _cpuid4_leaf_ebx ebx; union _cpuid4_leaf_ecx ecx; unsigned long size; - bool can_disable; - unsigned int l3_indices; + struct amd_l3_cache *l3; }; unsigned short num_cache_leaves; @@ -302,7 +307,7 @@ struct _cache_attr { }; #ifdef CONFIG_CPU_SUP_AMD -static unsigned int __cpuinit amd_calc_l3_indices(void) +static void __cpuinit amd_calc_l3_indices(struct amd_l3_cache *l3) { /* * We're called over smp_call_function_single() and therefore @@ -317,12 +322,14 @@ static unsigned int __cpuinit amd_calc_l3_indices(void) pci_read_config_dword(dev, 0x1C4, &val); /* calculate subcache sizes */ - sc0 = !(val & BIT(0)); - sc1 = !(val & BIT(4)); - sc2 = !(val & BIT(8)) + !(val & BIT(9)); - sc3 = !(val & BIT(12)) + !(val & BIT(13)); + l3->subcaches[0] = sc0 = !(val & BIT(0)); + l3->subcaches[1] = sc1 = !(val & BIT(4)); + l3->subcaches[2] = sc2 = !(val & BIT(8)) + !(val & BIT(9)); + l3->subcaches[3] = sc3 = !(val & BIT(12)) + !(val & BIT(13)); + + l3->indices = (max(max(max(sc0, sc1), sc2), sc3) << 10) - 1; - return (max(max(max(sc0, sc1), sc2), sc3) << 10) - 1; + l3->dev = dev; } static void __cpuinit @@ -348,19 +355,23 @@ amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf) if (num_k8_northbridges == 0) return; - this_leaf->can_disable = true; - this_leaf->l3_indices = amd_calc_l3_indices(); + this_leaf->l3 = kzalloc(sizeof(struct amd_l3_cache), GFP_ATOMIC); + if (!this_leaf->l3) { + printk(KERN_WARNING "Error allocating L3 struct\n"); + return; + } + + this_leaf->l3->can_disable = true; + amd_calc_l3_indices(this_leaf->l3); } static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf, unsigned int index) { - int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map)); - int node = amd_get_nb_id(cpu); - struct pci_dev *dev = node_to_k8_nb_misc(node); + struct pci_dev *dev = this_leaf->l3->dev; unsigned int reg = 0; - if (!this_leaf->can_disable) + if (!this_leaf->l3 || !this_leaf->l3->can_disable) return -EINVAL; if (!dev) @@ -382,15 +393,14 @@ SHOW_CACHE_DISABLE(1) static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf, const char *buf, size_t count, unsigned int index) { + struct pci_dev *dev = this_leaf->l3->dev; int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map)); - int node = amd_get_nb_id(cpu); - struct pci_dev *dev = node_to_k8_nb_misc(node); unsigned long val = 0; #define SUBCACHE_MASK (3UL << 20) #define SUBCACHE_INDEX 0xfff - if (!this_leaf->can_disable) + if (!this_leaf->l3 || !this_leaf->l3->can_disable) return -EINVAL; if (!capable(CAP_SYS_ADMIN)) @@ -404,7 +414,7 @@ static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf, /* do not allow writes outside of allowed bits */ if ((val & ~(SUBCACHE_MASK | SUBCACHE_INDEX)) || - ((val & SUBCACHE_INDEX) > this_leaf->l3_indices)) + ((val & SUBCACHE_INDEX) > this_leaf->l3->indices)) return -EINVAL; val |= BIT(30); @@ -708,6 +718,7 @@ static void __cpuinit free_cache_attributes(unsigned int cpu) for (i = 0; i < num_cache_leaves; i++) cache_remove_shared_cpu_map(cpu, i); + kfree(per_cpu(ici_cpuid4_info, cpu)->l3); kfree(per_cpu(ici_cpuid4_info, cpu)); per_cpu(ici_cpuid4_info, cpu) = NULL; } @@ -992,7 +1003,7 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev) this_leaf = CPUID4_INFO_IDX(cpu, i); - if (this_leaf->can_disable) + if (this_leaf->l3 && this_leaf->l3->can_disable) ktype_cache.default_attrs = default_l3_attrs; else ktype_cache.default_attrs = default_attrs; -- cgit v0.10.2 From ba06edb63f5ef2913aad37070eaec3c9d8ac73b8 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Thu, 22 Apr 2010 16:07:01 +0200 Subject: x86, cacheinfo: Make L3 cache info per node Currently, we're allocating L3 cache info and calculating indices for each online cpu which is clearly superfluous. Instead, we need to do this per-node as is each L3 cache. No functional change, only per-cpu memory savings. -v2: Allocate L3 cache descriptors array dynamically. Signed-off-by: Borislav Petkov LKML-Reference: <1271945222-5283-5-git-send-email-bp@amd64.org> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index ff663ca..1346e9c 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -307,19 +307,18 @@ struct _cache_attr { }; #ifdef CONFIG_CPU_SUP_AMD + +/* + * L3 cache descriptors + */ +static struct amd_l3_cache **__cpuinitdata l3_caches; + static void __cpuinit amd_calc_l3_indices(struct amd_l3_cache *l3) { - /* - * We're called over smp_call_function_single() and therefore - * are on the correct cpu. - */ - int cpu = smp_processor_id(); - int node = cpu_to_node(cpu); - struct pci_dev *dev = node_to_k8_nb_misc(node); unsigned int sc0, sc1, sc2, sc3; u32 val = 0; - pci_read_config_dword(dev, 0x1C4, &val); + pci_read_config_dword(l3->dev, 0x1C4, &val); /* calculate subcache sizes */ l3->subcaches[0] = sc0 = !(val & BIT(0)); @@ -328,13 +327,31 @@ static void __cpuinit amd_calc_l3_indices(struct amd_l3_cache *l3) l3->subcaches[3] = sc3 = !(val & BIT(12)) + !(val & BIT(13)); l3->indices = (max(max(max(sc0, sc1), sc2), sc3) << 10) - 1; +} + +static struct amd_l3_cache * __cpuinit amd_init_l3_cache(int node) +{ + struct amd_l3_cache *l3; + struct pci_dev *dev = node_to_k8_nb_misc(node); + + l3 = kzalloc(sizeof(struct amd_l3_cache), GFP_ATOMIC); + if (!l3) { + printk(KERN_WARNING "Error allocating L3 struct\n"); + return NULL; + } l3->dev = dev; + + amd_calc_l3_indices(l3); + + return l3; } static void __cpuinit amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf) { + int node; + if (boot_cpu_data.x86 != 0x10) return; @@ -355,14 +372,28 @@ amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf) if (num_k8_northbridges == 0) return; - this_leaf->l3 = kzalloc(sizeof(struct amd_l3_cache), GFP_ATOMIC); - if (!this_leaf->l3) { - printk(KERN_WARNING "Error allocating L3 struct\n"); - return; + /* + * Strictly speaking, the amount in @size below is leaked since it is + * never freed but this is done only on shutdown so it doesn't matter. + */ + if (!l3_caches) { + int size = num_k8_northbridges * sizeof(struct amd_l3_cache *); + + l3_caches = kzalloc(size, GFP_ATOMIC); + if (!l3_caches) + return; } - this_leaf->l3->can_disable = true; - amd_calc_l3_indices(this_leaf->l3); + node = amd_get_nb_id(smp_processor_id()); + + if (!l3_caches[node]) { + l3_caches[node] = amd_init_l3_cache(node); + l3_caches[node]->can_disable = true; + } + + WARN_ON(!l3_caches[node]); + + this_leaf->l3 = l3_caches[node]; } static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf, -- cgit v0.10.2 From 59d3b388741cf1a5eb7ad27fd4e9ed72643164ae Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Thu, 22 Apr 2010 16:07:02 +0200 Subject: x86, cacheinfo: Disable index in all four subcaches When disabling an L3 cache index, make sure we disable that index in all four subcaches of the L3. Clarify nomenclature while at it, wrt to disable slots versus disable index and rename accordingly. Signed-off-by: Borislav Petkov LKML-Reference: <1271945222-5283-6-git-send-email-bp@amd64.org> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index 1346e9c..33eae20 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -397,7 +397,7 @@ amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf) } static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf, - unsigned int index) + unsigned int slot) { struct pci_dev *dev = this_leaf->l3->dev; unsigned int reg = 0; @@ -408,21 +408,53 @@ static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf, if (!dev) return -EINVAL; - pci_read_config_dword(dev, 0x1BC + index * 4, ®); + pci_read_config_dword(dev, 0x1BC + slot * 4, ®); return sprintf(buf, "0x%08x\n", reg); } -#define SHOW_CACHE_DISABLE(index) \ +#define SHOW_CACHE_DISABLE(slot) \ static ssize_t \ -show_cache_disable_##index(struct _cpuid4_info *this_leaf, char *buf) \ +show_cache_disable_##slot(struct _cpuid4_info *this_leaf, char *buf) \ { \ - return show_cache_disable(this_leaf, buf, index); \ + return show_cache_disable(this_leaf, buf, slot); \ } SHOW_CACHE_DISABLE(0) SHOW_CACHE_DISABLE(1) +static void amd_l3_disable_index(struct amd_l3_cache *l3, int cpu, + unsigned slot, unsigned long idx) +{ + int i; + + idx |= BIT(30); + + /* + * disable index in all 4 subcaches + */ + for (i = 0; i < 4; i++) { + u32 reg = idx | (i << 20); + + if (!l3->subcaches[i]) + continue; + + pci_write_config_dword(l3->dev, 0x1BC + slot * 4, reg); + + /* + * We need to WBINVD on a core on the node containing the L3 + * cache which indices we disable therefore a simple wbinvd() + * is not sufficient. + */ + wbinvd_on_cpu(cpu); + + reg |= BIT(31); + pci_write_config_dword(l3->dev, 0x1BC + slot * 4, reg); + } +} + + static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf, - const char *buf, size_t count, unsigned int index) + const char *buf, size_t count, + unsigned int slot) { struct pci_dev *dev = this_leaf->l3->dev; int cpu = cpumask_first(to_cpumask(this_leaf->shared_cpu_map)); @@ -448,23 +480,17 @@ static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf, ((val & SUBCACHE_INDEX) > this_leaf->l3->indices)) return -EINVAL; - val |= BIT(30); - pci_write_config_dword(dev, 0x1BC + index * 4, val); - /* - * We need to WBINVD on a core on the node containing the L3 cache which - * indices we disable therefore a simple wbinvd() is not sufficient. - */ - wbinvd_on_cpu(cpu); - pci_write_config_dword(dev, 0x1BC + index * 4, val | BIT(31)); + amd_l3_disable_index(this_leaf->l3, cpu, slot, val); + return count; } -#define STORE_CACHE_DISABLE(index) \ +#define STORE_CACHE_DISABLE(slot) \ static ssize_t \ -store_cache_disable_##index(struct _cpuid4_info *this_leaf, \ +store_cache_disable_##slot(struct _cpuid4_info *this_leaf, \ const char *buf, size_t count) \ { \ - return store_cache_disable(this_leaf, buf, count, index); \ + return store_cache_disable(this_leaf, buf, count, slot); \ } STORE_CACHE_DISABLE(0) STORE_CACHE_DISABLE(1) -- cgit v0.10.2 From 74f5187ac873042f502227701ed1727e7c5fbfa9 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 22 Apr 2010 21:50:19 +0200 Subject: sched: Cure load average vs NO_HZ woes Chase reported that due to us decrementing calc_load_task prematurely (before the next LOAD_FREQ sample), the load average could be scewed by as much as the number of CPUs in the machine. This patch, based on Chase's patch, cures the problem by keeping the delta of the CPU going into NO_HZ idle separately and folding that in on the next LOAD_FREQ update. This restores the balance and we get strict LOAD_FREQ period samples. Signed-off-by: Peter Zijlstra Acked-by: Chase Douglas LKML-Reference: <1271934490.1776.343.camel@laptop> Signed-off-by: Ingo Molnar diff --git a/kernel/sched.c b/kernel/sched.c index de0da71..0cc913a 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1815,7 +1815,7 @@ static void cfs_rq_set_shares(struct cfs_rq *cfs_rq, unsigned long shares) } #endif -static void calc_load_account_active(struct rq *this_rq); +static void calc_load_account_idle(struct rq *this_rq); static void update_sysctl(void); static int get_update_sysctl_factor(void); @@ -2950,6 +2950,61 @@ static unsigned long calc_load_update; unsigned long avenrun[3]; EXPORT_SYMBOL(avenrun); +static long calc_load_fold_active(struct rq *this_rq) +{ + long nr_active, delta = 0; + + nr_active = this_rq->nr_running; + nr_active += (long) this_rq->nr_uninterruptible; + + if (nr_active != this_rq->calc_load_active) { + delta = nr_active - this_rq->calc_load_active; + this_rq->calc_load_active = nr_active; + } + + return delta; +} + +#ifdef CONFIG_NO_HZ +/* + * For NO_HZ we delay the active fold to the next LOAD_FREQ update. + * + * When making the ILB scale, we should try to pull this in as well. + */ +static atomic_long_t calc_load_tasks_idle; + +static void calc_load_account_idle(struct rq *this_rq) +{ + long delta; + + delta = calc_load_fold_active(this_rq); + if (delta) + atomic_long_add(delta, &calc_load_tasks_idle); +} + +static long calc_load_fold_idle(void) +{ + long delta = 0; + + /* + * Its got a race, we don't care... + */ + if (atomic_long_read(&calc_load_tasks_idle)) + delta = atomic_long_xchg(&calc_load_tasks_idle, 0); + + return delta; +} +#else +static void calc_load_account_idle(struct rq *this_rq) +{ +} + +static inline long calc_load_fold_idle(void) +{ + return 0; +} +#endif + /** * get_avenrun - get the load average array * @loads: pointer to dest load array @@ -2996,20 +3051,22 @@ void calc_global_load(void) } /* - * Either called from update_cpu_load() or from a cpu going idle + * Called from update_cpu_load() to periodically update this CPU's + * active count. */ static void calc_load_account_active(struct rq *this_rq) { - long nr_active, delta; + long delta; - nr_active = this_rq->nr_running; - nr_active += (long) this_rq->nr_uninterruptible; + if (time_before(jiffies, this_rq->calc_load_update)) + return; - if (nr_active != this_rq->calc_load_active) { - delta = nr_active - this_rq->calc_load_active; - this_rq->calc_load_active = nr_active; + delta = calc_load_fold_active(this_rq); + delta += calc_load_fold_idle(); + if (delta) atomic_long_add(delta, &calc_load_tasks); - } + + this_rq->calc_load_update += LOAD_FREQ; } /* @@ -3041,10 +3098,7 @@ static void update_cpu_load(struct rq *this_rq) this_rq->cpu_load[i] = (old_load*(scale-1) + new_load) >> i; } - if (time_after_eq(jiffies, this_rq->calc_load_update)) { - this_rq->calc_load_update += LOAD_FREQ; - calc_load_account_active(this_rq); - } + calc_load_account_active(this_rq); } #ifdef CONFIG_SMP diff --git a/kernel/sched_idletask.c b/kernel/sched_idletask.c index bea2b8f..9fa0f40 100644 --- a/kernel/sched_idletask.c +++ b/kernel/sched_idletask.c @@ -23,8 +23,7 @@ static void check_preempt_curr_idle(struct rq *rq, struct task_struct *p, int fl static struct task_struct *pick_next_task_idle(struct rq *rq) { schedstat_inc(rq, sched_goidle); - /* adjust the active tasks as we might go into a long sleep */ - calc_load_account_active(rq); + calc_load_account_idle(rq); return rq->idle; } -- cgit v0.10.2 From 669c55e9f99b90e46eaa0f98a67ec53d46dc969a Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 16 Apr 2010 14:59:29 +0200 Subject: sched: Pre-compute cpumask_weight(sched_domain_span(sd)) Dave reported that his large SPARC machines spend lots of time in hweight64(), try and optimize some of those needless cpumask_weight() invocations (esp. with the large offstack cpumasks these are very expensive indeed). Reported-by: David Miller Signed-off-by: Peter Zijlstra LKML-Reference: Signed-off-by: Ingo Molnar diff --git a/include/linux/sched.h b/include/linux/sched.h index e3e900f..dfea405 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -960,6 +960,7 @@ struct sched_domain { char *name; #endif + unsigned int span_weight; /* * Span of all CPUs in this domain. * diff --git a/kernel/sched.c b/kernel/sched.c index 0cc913a..4956ed0 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -6271,6 +6271,9 @@ cpu_attach_domain(struct sched_domain *sd, struct root_domain *rd, int cpu) struct rq *rq = cpu_rq(cpu); struct sched_domain *tmp; + for (tmp = sd; tmp; tmp = tmp->parent) + tmp->span_weight = cpumask_weight(sched_domain_span(tmp)); + /* Remove the sched domains which do not contribute to scheduling. */ for (tmp = sd; tmp; ) { struct sched_domain *parent = tmp->parent; diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 88d3053..0a413c7 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -1508,9 +1508,7 @@ select_task_rq_fair(struct rq *rq, struct task_struct *p, int sd_flag, int wake_ * Pick the largest domain to update shares over */ tmp = sd; - if (affine_sd && (!tmp || - cpumask_weight(sched_domain_span(affine_sd)) > - cpumask_weight(sched_domain_span(sd)))) + if (affine_sd && (!tmp || affine_sd->span_weight > sd->span_weight)) tmp = affine_sd; if (tmp) { @@ -1554,10 +1552,10 @@ select_task_rq_fair(struct rq *rq, struct task_struct *p, int sd_flag, int wake_ /* Now try balancing at a lower domain level of new_cpu */ cpu = new_cpu; - weight = cpumask_weight(sched_domain_span(sd)); + weight = sd->span_weight; sd = NULL; for_each_domain(cpu, tmp) { - if (weight <= cpumask_weight(sched_domain_span(tmp))) + if (weight <= tmp->span_weight) break; if (tmp->flags & sd_flag) sd = tmp; @@ -2243,7 +2241,7 @@ unsigned long __weak arch_scale_freq_power(struct sched_domain *sd, int cpu) unsigned long default_scale_smt_power(struct sched_domain *sd, int cpu) { - unsigned long weight = cpumask_weight(sched_domain_span(sd)); + unsigned long weight = sd->span_weight; unsigned long smt_gain = sd->smt_gain; smt_gain /= weight; @@ -2276,7 +2274,7 @@ unsigned long scale_rt_power(int cpu) static void update_cpu_power(struct sched_domain *sd, int cpu) { - unsigned long weight = cpumask_weight(sched_domain_span(sd)); + unsigned long weight = sd->span_weight; unsigned long power = SCHED_LOAD_SCALE; struct sched_group *sdg = sd->groups; -- cgit v0.10.2 From 99bd5e2f245d8cd17d040c82d40becdb3efd9b69 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Wed, 31 Mar 2010 16:47:45 -0700 Subject: sched: Fix select_idle_sibling() logic in select_task_rq_fair() Issues in the current select_idle_sibling() logic in select_task_rq_fair() in the context of a task wake-up: a) Once we select the idle sibling, we use that domain (spanning the cpu that the task is currently woken-up and the idle sibling that we found) in our wake_affine() decisions. This domain is completely different from the domain(we are supposed to use) that spans the cpu that the task currently woken-up and the cpu where the task previously ran. b) We do select_idle_sibling() check only for the cpu that the task is currently woken-up on. If select_task_rq_fair() selects the previously run cpu for waking the task, doing a select_idle_sibling() check for that cpu also helps and we don't do this currently. c) In the scenarios where the cpu that the task is woken-up is busy but with its HT siblings are idle, we are selecting the task be woken-up on the idle HT sibling instead of a core that it previously ran and currently completely idle. i.e., we are not taking decisions based on wake_affine() but directly selecting an idle sibling that can cause an imbalance at the SMT/MC level which will be later corrected by the periodic load balancer. Fix this by first going through the load imbalance calculations using wake_affine() and once we make a decision of woken-up cpu vs previously-ran cpu, then choose a possible idle sibling for waking up the task on. Signed-off-by: Suresh Siddha Signed-off-by: Peter Zijlstra LKML-Reference: <1270079265.7835.8.camel@sbs-t61.sc.intel.com> Signed-off-by: Ingo Molnar diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 0a413c7..cbd8b8a 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -1375,29 +1375,48 @@ find_idlest_cpu(struct sched_group *group, struct task_struct *p, int this_cpu) /* * Try and locate an idle CPU in the sched_domain. */ -static int -select_idle_sibling(struct task_struct *p, struct sched_domain *sd, int target) +static int select_idle_sibling(struct task_struct *p, int target) { int cpu = smp_processor_id(); int prev_cpu = task_cpu(p); + struct sched_domain *sd; int i; /* - * If this domain spans both cpu and prev_cpu (see the SD_WAKE_AFFINE - * test in select_task_rq_fair) and the prev_cpu is idle then that's - * always a better target than the current cpu. + * If the task is going to be woken-up on this cpu and if it is + * already idle, then it is the right target. + */ + if (target == cpu && idle_cpu(cpu)) + return cpu; + + /* + * If the task is going to be woken-up on the cpu where it previously + * ran and if it is currently idle, then it the right target. */ - if (target == cpu && !cpu_rq(prev_cpu)->cfs.nr_running) + if (target == prev_cpu && idle_cpu(prev_cpu)) return prev_cpu; /* - * Otherwise, iterate the domain and find an elegible idle cpu. + * Otherwise, iterate the domains and find an elegible idle cpu. */ - for_each_cpu_and(i, sched_domain_span(sd), &p->cpus_allowed) { - if (!cpu_rq(i)->cfs.nr_running) { - target = i; + for_each_domain(target, sd) { + if (!(sd->flags & SD_SHARE_PKG_RESOURCES)) break; + + for_each_cpu_and(i, sched_domain_span(sd), &p->cpus_allowed) { + if (idle_cpu(i)) { + target = i; + break; + } } + + /* + * Lets stop looking for an idle sibling when we reached + * the domain that spans the current cpu and prev_cpu. + */ + if (cpumask_test_cpu(cpu, sched_domain_span(sd)) && + cpumask_test_cpu(prev_cpu, sched_domain_span(sd))) + break; } return target; @@ -1421,7 +1440,7 @@ select_task_rq_fair(struct rq *rq, struct task_struct *p, int sd_flag, int wake_ int cpu = smp_processor_id(); int prev_cpu = task_cpu(p); int new_cpu = cpu; - int want_affine = 0, cpu_idle = !current->pid; + int want_affine = 0; int want_sd = 1; int sync = wake_flags & WF_SYNC; @@ -1460,36 +1479,13 @@ select_task_rq_fair(struct rq *rq, struct task_struct *p, int sd_flag, int wake_ } /* - * While iterating the domains looking for a spanning - * WAKE_AFFINE domain, adjust the affine target to any idle cpu - * in cache sharing domains along the way. + * If both cpu and prev_cpu are part of this domain, + * cpu is a valid SD_WAKE_AFFINE target. */ - if (want_affine) { - int target = -1; - - /* - * If both cpu and prev_cpu are part of this domain, - * cpu is a valid SD_WAKE_AFFINE target. - */ - if (cpumask_test_cpu(prev_cpu, sched_domain_span(tmp))) - target = cpu; - - /* - * If there's an idle sibling in this domain, make that - * the wake_affine target instead of the current cpu. - */ - if (!cpu_idle && tmp->flags & SD_SHARE_PKG_RESOURCES) - target = select_idle_sibling(p, tmp, target); - - if (target >= 0) { - if (tmp->flags & SD_WAKE_AFFINE) { - affine_sd = tmp; - want_affine = 0; - if (target != cpu) - cpu_idle = 1; - } - cpu = target; - } + if (want_affine && (tmp->flags & SD_WAKE_AFFINE) && + cpumask_test_cpu(prev_cpu, sched_domain_span(tmp))) { + affine_sd = tmp; + want_affine = 0; } if (!want_sd && !want_affine) @@ -1520,8 +1516,10 @@ select_task_rq_fair(struct rq *rq, struct task_struct *p, int sd_flag, int wake_ #endif if (affine_sd) { - if (cpu_idle || cpu == prev_cpu || wake_affine(affine_sd, p, sync)) - return cpu; + if (cpu == prev_cpu || wake_affine(affine_sd, p, sync)) + return select_idle_sibling(p, cpu); + else + return select_idle_sibling(p, prev_cpu); } while (sd) { -- cgit v0.10.2 From cb6e943ccf19ab6d3189147e9d625a992e016084 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Thu, 1 Apr 2010 03:17:25 +0200 Subject: oprofile: remove double ring buffering oprofile used a double buffer scheme for its cpu event buffer to avoid races on reading with the old locked ring buffer. But that is obsolete now with the new ring buffer, so simply use a single buffer. This greatly simplifies the code and avoids a lot of sample drops on large runs, especially with call graph. Based on suggestions from Steven Rostedt For stable kernels from v2.6.32, but not earlier. Signed-off-by: Andi Kleen Cc: Steven Rostedt Cc: stable Signed-off-by: Robert Richter diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index 166b67e..de82183 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -30,23 +30,7 @@ #define OP_BUFFER_FLAGS 0 -/* - * Read and write access is using spin locking. Thus, writing to the - * buffer by NMI handler (x86) could occur also during critical - * sections when reading the buffer. To avoid this, there are 2 - * buffers for independent read and write access. Read access is in - * process context only, write access only in the NMI handler. If the - * read buffer runs empty, both buffers are swapped atomically. There - * is potentially a small window during swapping where the buffers are - * disabled and samples could be lost. - * - * Using 2 buffers is a little bit overhead, but the solution is clear - * and does not require changes in the ring buffer implementation. It - * can be changed to a single buffer solution when the ring buffer - * access is implemented as non-locking atomic code. - */ -static struct ring_buffer *op_ring_buffer_read; -static struct ring_buffer *op_ring_buffer_write; +static struct ring_buffer *op_ring_buffer; DEFINE_PER_CPU(struct oprofile_cpu_buffer, op_cpu_buffer); static void wq_sync_buffer(struct work_struct *work); @@ -68,12 +52,9 @@ void oprofile_cpu_buffer_inc_smpl_lost(void) void free_cpu_buffers(void) { - if (op_ring_buffer_read) - ring_buffer_free(op_ring_buffer_read); - op_ring_buffer_read = NULL; - if (op_ring_buffer_write) - ring_buffer_free(op_ring_buffer_write); - op_ring_buffer_write = NULL; + if (op_ring_buffer) + ring_buffer_free(op_ring_buffer); + op_ring_buffer = NULL; } #define RB_EVENT_HDR_SIZE 4 @@ -86,11 +67,8 @@ int alloc_cpu_buffers(void) unsigned long byte_size = buffer_size * (sizeof(struct op_sample) + RB_EVENT_HDR_SIZE); - op_ring_buffer_read = ring_buffer_alloc(byte_size, OP_BUFFER_FLAGS); - if (!op_ring_buffer_read) - goto fail; - op_ring_buffer_write = ring_buffer_alloc(byte_size, OP_BUFFER_FLAGS); - if (!op_ring_buffer_write) + op_ring_buffer = ring_buffer_alloc(byte_size, OP_BUFFER_FLAGS); + if (!op_ring_buffer) goto fail; for_each_possible_cpu(i) { @@ -162,16 +140,11 @@ struct op_sample *op_cpu_buffer_write_reserve(struct op_entry *entry, unsigned long size) { entry->event = ring_buffer_lock_reserve - (op_ring_buffer_write, sizeof(struct op_sample) + + (op_ring_buffer, sizeof(struct op_sample) + size * sizeof(entry->sample->data[0])); - if (entry->event) - entry->sample = ring_buffer_event_data(entry->event); - else - entry->sample = NULL; - - if (!entry->sample) + if (!entry->event) return NULL; - + entry->sample = ring_buffer_event_data(entry->event); entry->size = size; entry->data = entry->sample->data; @@ -180,25 +153,16 @@ struct op_sample int op_cpu_buffer_write_commit(struct op_entry *entry) { - return ring_buffer_unlock_commit(op_ring_buffer_write, entry->event); + return ring_buffer_unlock_commit(op_ring_buffer, entry->event); } struct op_sample *op_cpu_buffer_read_entry(struct op_entry *entry, int cpu) { struct ring_buffer_event *e; - e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL); - if (e) - goto event; - if (ring_buffer_swap_cpu(op_ring_buffer_read, - op_ring_buffer_write, - cpu)) + e = ring_buffer_consume(op_ring_buffer, cpu, NULL); + if (!e) return NULL; - e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL); - if (e) - goto event; - return NULL; -event: entry->event = e; entry->sample = ring_buffer_event_data(e); entry->size = (ring_buffer_event_length(e) - sizeof(struct op_sample)) @@ -209,8 +173,7 @@ event: unsigned long op_cpu_buffer_entries(int cpu) { - return ring_buffer_entries_cpu(op_ring_buffer_read, cpu) - + ring_buffer_entries_cpu(op_ring_buffer_write, cpu); + return ring_buffer_entries_cpu(op_ring_buffer, cpu); } static int -- cgit v0.10.2 From 1f9cc3cb6a27521edfe0a21abf97d2bb11c4d237 Mon Sep 17 00:00:00 2001 From: Robin Holt Date: Fri, 23 Apr 2010 10:36:22 -0500 Subject: x86, pat: Update the page flags for memtype atomically instead of using memtype_lock While testing an application using the xpmem (out of kernel) driver, we noticed a significant page fault rate reduction of x86_64 with respect to ia64. For one test running with 32 cpus, one thread per cpu, it took 01:08 for each of the threads to vm_insert_pfn 2GB worth of pages. For the same test running on 256 cpus, one thread per cpu, it took 14:48 to vm_insert_pfn 2 GB worth of pages. The slowdown was tracked to lookup_memtype which acquires the spinlock memtype_lock. This heavily contended lock was slowing down vm_insert_pfn(). With the cmpxchg on page->flags method, both the 32 cpu and 256 cpu cases take approx 00:01.3 seconds to complete. Signed-off-by: Robin Holt LKML-Reference: <20100423153627.751194346@gulag1.americas.sgi.com> Cc: Venkatesh Pallipadi Cc: Rafael Wysocki Reviewed-by: Suresh Siddha Signed-off-by: H. Peter Anvin diff --git a/arch/x86/include/asm/cacheflush.h b/arch/x86/include/asm/cacheflush.h index 634c40a..c70068d 100644 --- a/arch/x86/include/asm/cacheflush.h +++ b/arch/x86/include/asm/cacheflush.h @@ -44,9 +44,6 @@ static inline void copy_from_user_page(struct vm_area_struct *vma, memcpy(dst, src, len); } -#define PG_WC PG_arch_1 -PAGEFLAG(WC, WC) - #ifdef CONFIG_X86_PAT /* * X86 PAT uses page flags WC and Uncached together to keep track of @@ -55,16 +52,24 @@ PAGEFLAG(WC, WC) * _PAGE_CACHE_UC_MINUS and fourth state where page's memory type has not * been changed from its default (value of -1 used to denote this). * Note we do not support _PAGE_CACHE_UC here. - * - * Caller must hold memtype_lock for atomicity. */ + +#define _PGMT_DEFAULT 0 +#define _PGMT_WC (1UL << PG_arch_1) +#define _PGMT_UC_MINUS (1UL << PG_uncached) +#define _PGMT_WB (1UL << PG_uncached | 1UL << PG_arch_1) +#define _PGMT_MASK (1UL << PG_uncached | 1UL << PG_arch_1) +#define _PGMT_CLEAR_MASK (~_PGMT_MASK) + static inline unsigned long get_page_memtype(struct page *pg) { - if (!PageUncached(pg) && !PageWC(pg)) + unsigned long pg_flags = pg->flags & _PGMT_MASK; + + if (pg_flags == _PGMT_DEFAULT) return -1; - else if (!PageUncached(pg) && PageWC(pg)) + else if (pg_flags == _PGMT_WC) return _PAGE_CACHE_WC; - else if (PageUncached(pg) && !PageWC(pg)) + else if (pg_flags == _PGMT_UC_MINUS) return _PAGE_CACHE_UC_MINUS; else return _PAGE_CACHE_WB; @@ -72,25 +77,26 @@ static inline unsigned long get_page_memtype(struct page *pg) static inline void set_page_memtype(struct page *pg, unsigned long memtype) { + unsigned long memtype_flags = _PGMT_DEFAULT; + unsigned long old_flags; + unsigned long new_flags; + switch (memtype) { case _PAGE_CACHE_WC: - ClearPageUncached(pg); - SetPageWC(pg); + memtype_flags = _PGMT_WC; break; case _PAGE_CACHE_UC_MINUS: - SetPageUncached(pg); - ClearPageWC(pg); + memtype_flags = _PGMT_UC_MINUS; break; case _PAGE_CACHE_WB: - SetPageUncached(pg); - SetPageWC(pg); - break; - default: - case -1: - ClearPageUncached(pg); - ClearPageWC(pg); + memtype_flags = _PGMT_WB; break; } + + do { + old_flags = pg->flags; + new_flags = (old_flags & _PGMT_CLEAR_MASK) | memtype_flags; + } while (cmpxchg(&pg->flags, old_flags, new_flags) != old_flags); } #else static inline unsigned long get_page_memtype(struct page *pg) { return -1; } diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index 9510111..501fc60 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c @@ -190,8 +190,6 @@ static int pat_pagerange_is_ram(unsigned long start, unsigned long end) * Here we do two pass: * - Find the memtype of all the pages in the range, look for any conflicts * - In case of no conflicts, set the new memtype for pages in the range - * - * Caller must hold memtype_lock for atomicity. */ static int reserve_ram_pages_type(u64 start, u64 end, unsigned long req_type, unsigned long *new_type) @@ -297,9 +295,7 @@ int reserve_memtype(u64 start, u64 end, unsigned long req_type, is_range_ram = pat_pagerange_is_ram(start, end); if (is_range_ram == 1) { - spin_lock(&memtype_lock); err = reserve_ram_pages_type(start, end, req_type, new_type); - spin_unlock(&memtype_lock); return err; } else if (is_range_ram < 0) { @@ -351,9 +347,7 @@ int free_memtype(u64 start, u64 end) is_range_ram = pat_pagerange_is_ram(start, end); if (is_range_ram == 1) { - spin_lock(&memtype_lock); err = free_ram_pages_type(start, end); - spin_unlock(&memtype_lock); return err; } else if (is_range_ram < 0) { @@ -394,10 +388,8 @@ static unsigned long lookup_memtype(u64 paddr) if (pat_pagerange_is_ram(paddr, paddr + PAGE_SIZE)) { struct page *page; - spin_lock(&memtype_lock); page = pfn_to_page(paddr >> PAGE_SHIFT); rettype = get_page_memtype(page); - spin_unlock(&memtype_lock); /* * -1 from get_page_memtype() implies RAM page is in its * default state and not reserved, and hence of type WB -- cgit v0.10.2 From e4cef1f65061429c3e8b356233e87dc6653a9da5 Mon Sep 17 00:00:00 2001 From: Hitoshi Mitake Date: Wed, 21 Apr 2010 21:23:54 +0900 Subject: perf lock: Fix state machine to recognize lock sequence Previous state machine of perf lock was really broken. This patch improves it a little. This patch prepares the list of state machine that represents lock sequences for each threads. These state machines can be one of these sequences: 1) acquire -> acquired -> release 2) acquire -> contended -> acquired -> release 3) acquire (w/ try) -> release 4) acquire (w/ read) -> release The case of 4) is a little special. Double acquire of read lock is allowed, so the state machine counts read lock number, and permits double acquire and release. But, things are not so simple. Something in my model is still wrong. I counted the number of lock instances with bad sequence, and ratio is like this (case of tracing whoami): bad:233, total:2279 version 2: * threads are now identified with tid, not pid * prepared SEQ_STATE_READ_ACQUIRED for read lock. * bunch of struct lock_seq_stat is now linked list * debug information enhanced (this have to be removed someday) e.g. | === output for debug=== | | bad:233, total:2279 | bad rate:0.000000 | histogram of events caused bad sequence | acquire: 165 | acquired: 0 | contended: 0 | release: 68 Signed-off-by: Hitoshi Mitake Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo Cc: Jens Axboe Cc: Jason Baron Cc: Xiao Guangrong Cc: Ingo Molnar LKML-Reference: <1271852634-9351-1-git-send-email-mitake@dcl.info.waseda.ac.jp> [rename SEQ_STATE_UNINITED to SEQ_STATE_UNINITIALIZED] Signed-off-by: Frederic Weisbecker diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index 6c38e4f..716d8c5 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c @@ -23,6 +23,8 @@ #include #include +static struct perf_session *session; + /* based on kernel/lockdep.c */ #define LOCKHASH_BITS 12 #define LOCKHASH_SIZE (1UL << LOCKHASH_BITS) @@ -32,9 +34,6 @@ static struct list_head lockhash_table[LOCKHASH_SIZE]; #define __lockhashfn(key) hash_long((unsigned long)key, LOCKHASH_BITS) #define lockhashentry(key) (lockhash_table + __lockhashfn((key))) -#define LOCK_STATE_UNLOCKED 0 /* initial state */ -#define LOCK_STATE_LOCKED 1 - struct lock_stat { struct list_head hash_entry; struct rb_node rb; /* used for sorting */ @@ -47,20 +46,151 @@ struct lock_stat { void *addr; /* address of lockdep_map, used as ID */ char *name; /* for strcpy(), we cannot use const */ - int state; - u64 prev_event_time; /* timestamp of previous event */ - - unsigned int nr_acquired; unsigned int nr_acquire; + unsigned int nr_acquired; unsigned int nr_contended; unsigned int nr_release; + unsigned int nr_readlock; + unsigned int nr_trylock; /* these times are in nano sec. */ u64 wait_time_total; u64 wait_time_min; u64 wait_time_max; + + int discard; /* flag of blacklist */ +}; + +/* + * States of lock_seq_stat + * + * UNINITIALIZED is required for detecting first event of acquire. + * As the nature of lock events, there is no guarantee + * that the first event for the locks are acquire, + * it can be acquired, contended or release. + */ +#define SEQ_STATE_UNINITIALIZED 0 /* initial state */ +#define SEQ_STATE_RELEASED 1 +#define SEQ_STATE_ACQUIRING 2 +#define SEQ_STATE_ACQUIRED 3 +#define SEQ_STATE_READ_ACQUIRED 4 +#define SEQ_STATE_CONTENDED 5 + +/* + * MAX_LOCK_DEPTH + * Imported from include/linux/sched.h. + * Should this be synchronized? + */ +#define MAX_LOCK_DEPTH 48 + +/* + * struct lock_seq_stat: + * Place to put on state of one lock sequence + * 1) acquire -> acquired -> release + * 2) acquire -> contended -> acquired -> release + * 3) acquire (with read or try) -> release + * 4) Are there other patterns? + */ +struct lock_seq_stat { + struct list_head list; + int state; + u64 prev_event_time; + void *addr; + + int read_count; }; +struct thread_stat { + struct rb_node rb; + + u32 tid; + struct list_head seq_list; +}; + +static struct rb_root thread_stats; + +static struct thread_stat *thread_stat_find(u32 tid) +{ + struct rb_node *node; + struct thread_stat *st; + + node = thread_stats.rb_node; + while (node) { + st = container_of(node, struct thread_stat, rb); + if (st->tid == tid) + return st; + else if (tid < st->tid) + node = node->rb_left; + else + node = node->rb_right; + } + + return NULL; +} + +static void thread_stat_insert(struct thread_stat *new) +{ + struct rb_node **rb = &thread_stats.rb_node; + struct rb_node *parent = NULL; + struct thread_stat *p; + + while (*rb) { + p = container_of(*rb, struct thread_stat, rb); + parent = *rb; + + if (new->tid < p->tid) + rb = &(*rb)->rb_left; + else if (new->tid > p->tid) + rb = &(*rb)->rb_right; + else + BUG_ON("inserting invalid thread_stat\n"); + } + + rb_link_node(&new->rb, parent, rb); + rb_insert_color(&new->rb, &thread_stats); +} + +static struct thread_stat *thread_stat_findnew_after_first(u32 tid) +{ + struct thread_stat *st; + + st = thread_stat_find(tid); + if (st) + return st; + + st = zalloc(sizeof(struct thread_stat)); + if (!st) + die("memory allocation failed\n"); + + st->tid = tid; + INIT_LIST_HEAD(&st->seq_list); + + thread_stat_insert(st); + + return st; +} + +static struct thread_stat *thread_stat_findnew_first(u32 tid); +static struct thread_stat *(*thread_stat_findnew)(u32 tid) = + thread_stat_findnew_first; + +static struct thread_stat *thread_stat_findnew_first(u32 tid) +{ + struct thread_stat *st; + + st = zalloc(sizeof(struct thread_stat)); + if (!st) + die("memory allocation failed\n"); + st->tid = tid; + INIT_LIST_HEAD(&st->seq_list); + + rb_link_node(&st->rb, NULL, &thread_stats.rb_node); + rb_insert_color(&st->rb, &thread_stats); + + thread_stat_findnew = thread_stat_findnew_after_first; + return st; +} + /* build simple key function one is bigger than two */ #define SINGLE_KEY(member) \ static int lock_stat_key_ ## member(struct lock_stat *one, \ @@ -175,8 +305,6 @@ static struct lock_stat *lock_stat_findnew(void *addr, const char *name) goto alloc_failed; strcpy(new->name, name); - /* LOCK_STATE_UNLOCKED == 0 isn't guaranteed forever */ - new->state = LOCK_STATE_UNLOCKED; new->wait_time_min = ULLONG_MAX; list_add(&new->hash_entry, entry); @@ -198,6 +326,7 @@ struct raw_event_sample { struct trace_acquire_event { void *addr; const char *name; + int flag; }; struct trace_acquired_event { @@ -241,120 +370,246 @@ struct trace_lock_handler { struct thread *thread); }; +static struct lock_seq_stat *get_seq(struct thread_stat *ts, void *addr) +{ + struct lock_seq_stat *seq; + + list_for_each_entry(seq, &ts->seq_list, list) { + if (seq->addr == addr) + return seq; + } + + seq = zalloc(sizeof(struct lock_seq_stat)); + if (!seq) + die("Not enough memory\n"); + seq->state = SEQ_STATE_UNINITIALIZED; + seq->addr = addr; + + list_add(&seq->list, &ts->seq_list); + return seq; +} + +static int bad_hist[4]; + static void report_lock_acquire_event(struct trace_acquire_event *acquire_event, struct event *__event __used, int cpu __used, - u64 timestamp, + u64 timestamp __used, struct thread *thread __used) { - struct lock_stat *st; + struct lock_stat *ls; + struct thread_stat *ts; + struct lock_seq_stat *seq; + + ls = lock_stat_findnew(acquire_event->addr, acquire_event->name); + if (ls->discard) + return; - st = lock_stat_findnew(acquire_event->addr, acquire_event->name); + ts = thread_stat_findnew(thread->pid); + seq = get_seq(ts, acquire_event->addr); - switch (st->state) { - case LOCK_STATE_UNLOCKED: + switch (seq->state) { + case SEQ_STATE_UNINITIALIZED: + case SEQ_STATE_RELEASED: + if (!acquire_event->flag) { + seq->state = SEQ_STATE_ACQUIRING; + } else { + if (acquire_event->flag & 1) + ls->nr_trylock++; + if (acquire_event->flag & 2) + ls->nr_readlock++; + seq->state = SEQ_STATE_READ_ACQUIRED; + seq->read_count = 1; + ls->nr_acquired++; + } + break; + case SEQ_STATE_READ_ACQUIRED: + if (acquire_event->flag & 2) { + seq->read_count++; + ls->nr_acquired++; + goto end; + } else { + goto broken; + } break; - case LOCK_STATE_LOCKED: + case SEQ_STATE_ACQUIRED: + case SEQ_STATE_ACQUIRING: + case SEQ_STATE_CONTENDED: +broken: + /* broken lock sequence, discard it */ + ls->discard = 1; + bad_hist[0]++; + list_del(&seq->list); + free(seq); + goto end; break; default: - BUG_ON(1); + BUG_ON("Unknown state of lock sequence found!\n"); break; } - st->prev_event_time = timestamp; + ls->nr_acquire++; + seq->prev_event_time = timestamp; +end: + return; } static void report_lock_acquired_event(struct trace_acquired_event *acquired_event, struct event *__event __used, int cpu __used, - u64 timestamp, + u64 timestamp __used, struct thread *thread __used) { - struct lock_stat *st; + struct lock_stat *ls; + struct thread_stat *ts; + struct lock_seq_stat *seq; + u64 contended_term; - st = lock_stat_findnew(acquired_event->addr, acquired_event->name); + ls = lock_stat_findnew(acquired_event->addr, acquired_event->name); + if (ls->discard) + return; + + ts = thread_stat_findnew(thread->pid); + seq = get_seq(ts, acquired_event->addr); - switch (st->state) { - case LOCK_STATE_UNLOCKED: - st->state = LOCK_STATE_LOCKED; - st->nr_acquired++; + switch (seq->state) { + case SEQ_STATE_UNINITIALIZED: + /* orphan event, do nothing */ + return; + case SEQ_STATE_ACQUIRING: break; - case LOCK_STATE_LOCKED: + case SEQ_STATE_CONTENDED: + contended_term = timestamp - seq->prev_event_time; + ls->wait_time_total += contended_term; + + if (contended_term < ls->wait_time_min) + ls->wait_time_min = contended_term; + else if (ls->wait_time_max < contended_term) + ls->wait_time_max = contended_term; break; + case SEQ_STATE_RELEASED: + case SEQ_STATE_ACQUIRED: + case SEQ_STATE_READ_ACQUIRED: + /* broken lock sequence, discard it */ + ls->discard = 1; + bad_hist[1]++; + list_del(&seq->list); + free(seq); + goto end; + break; + default: - BUG_ON(1); + BUG_ON("Unknown state of lock sequence found!\n"); break; } - st->prev_event_time = timestamp; + seq->state = SEQ_STATE_ACQUIRED; + ls->nr_acquired++; + seq->prev_event_time = timestamp; +end: + return; } static void report_lock_contended_event(struct trace_contended_event *contended_event, struct event *__event __used, int cpu __used, - u64 timestamp, + u64 timestamp __used, struct thread *thread __used) { - struct lock_stat *st; + struct lock_stat *ls; + struct thread_stat *ts; + struct lock_seq_stat *seq; + + ls = lock_stat_findnew(contended_event->addr, contended_event->name); + if (ls->discard) + return; - st = lock_stat_findnew(contended_event->addr, contended_event->name); + ts = thread_stat_findnew(thread->pid); + seq = get_seq(ts, contended_event->addr); - switch (st->state) { - case LOCK_STATE_UNLOCKED: + switch (seq->state) { + case SEQ_STATE_UNINITIALIZED: + /* orphan event, do nothing */ + return; + case SEQ_STATE_ACQUIRING: break; - case LOCK_STATE_LOCKED: - st->nr_contended++; + case SEQ_STATE_RELEASED: + case SEQ_STATE_ACQUIRED: + case SEQ_STATE_READ_ACQUIRED: + case SEQ_STATE_CONTENDED: + /* broken lock sequence, discard it */ + ls->discard = 1; + bad_hist[2]++; + list_del(&seq->list); + free(seq); + goto end; break; default: - BUG_ON(1); + BUG_ON("Unknown state of lock sequence found!\n"); break; } - st->prev_event_time = timestamp; + seq->state = SEQ_STATE_CONTENDED; + ls->nr_contended++; + seq->prev_event_time = timestamp; +end: + return; } static void report_lock_release_event(struct trace_release_event *release_event, struct event *__event __used, int cpu __used, - u64 timestamp, + u64 timestamp __used, struct thread *thread __used) { - struct lock_stat *st; - u64 hold_time; + struct lock_stat *ls; + struct thread_stat *ts; + struct lock_seq_stat *seq; - st = lock_stat_findnew(release_event->addr, release_event->name); + ls = lock_stat_findnew(release_event->addr, release_event->name); + if (ls->discard) + return; - switch (st->state) { - case LOCK_STATE_UNLOCKED: - break; - case LOCK_STATE_LOCKED: - st->state = LOCK_STATE_UNLOCKED; - hold_time = timestamp - st->prev_event_time; + ts = thread_stat_findnew(thread->pid); + seq = get_seq(ts, release_event->addr); - if (timestamp < st->prev_event_time) { - /* terribly, this can happen... */ + switch (seq->state) { + case SEQ_STATE_UNINITIALIZED: + goto end; + break; + case SEQ_STATE_ACQUIRED: + break; + case SEQ_STATE_READ_ACQUIRED: + seq->read_count--; + BUG_ON(seq->read_count < 0); + if (!seq->read_count) { + ls->nr_release++; goto end; } - - if (st->wait_time_min > hold_time) - st->wait_time_min = hold_time; - if (st->wait_time_max < hold_time) - st->wait_time_max = hold_time; - st->wait_time_total += hold_time; - - st->nr_release++; + break; + case SEQ_STATE_ACQUIRING: + case SEQ_STATE_CONTENDED: + case SEQ_STATE_RELEASED: + /* broken lock sequence, discard it */ + ls->discard = 1; + bad_hist[3]++; + goto free_seq; break; default: - BUG_ON(1); + BUG_ON("Unknown state of lock sequence found!\n"); break; } + ls->nr_release++; +free_seq: + list_del(&seq->list); + free(seq); end: - st->prev_event_time = timestamp; + return; } /* lock oriented handlers */ @@ -381,6 +636,7 @@ process_lock_acquire_event(void *data, tmp = raw_field_value(event, "lockdep_addr", data); memcpy(&acquire_event.addr, &tmp, sizeof(void *)); acquire_event.name = (char *)raw_field_ptr(event, "name", data); + acquire_event.flag = (int)raw_field_value(event, "flag", data); if (trace_handler->acquire_event) trace_handler->acquire_event(&acquire_event, event, cpu, timestamp, thread); @@ -441,8 +697,8 @@ process_lock_release_event(void *data, } static void -process_raw_event(void *data, int cpu, - u64 timestamp, struct thread *thread) +process_raw_event(void *data, int cpu __used, + u64 timestamp __used, struct thread *thread __used) { struct event *event; int type; @@ -604,14 +860,15 @@ static void queue_raw_event(void *data, int raw_size, int cpu, } } -static int process_sample_event(event_t *event, struct perf_session *session) +static int process_sample_event(event_t *event, struct perf_session *s) { struct thread *thread; struct sample_data data; bzero(&data, sizeof(struct sample_data)); - event__parse_sample(event, session->sample_type, &data); - thread = perf_session__findnew(session, data.pid); + event__parse_sample(event, s->sample_type, &data); + /* CAUTION: using tid as thread.pid */ + thread = perf_session__findnew(s, data.tid); if (thread == NULL) { pr_debug("problem processing %d event, skipping it.\n", @@ -634,8 +891,8 @@ static void print_result(void) { struct lock_stat *st; char cut_name[20]; + int bad, total; - printf("%18s ", "ID"); printf("%20s ", "Name"); printf("%10s ", "acquired"); printf("%10s ", "contended"); @@ -646,11 +903,15 @@ static void print_result(void) printf("\n\n"); + bad = total = 0; while ((st = pop_from_result())) { + total++; + if (st->discard) { + bad++; + continue; + } bzero(cut_name, 20); - printf("%p ", st->addr); - if (strlen(st->name) < 16) { /* output raw name */ printf("%20s ", st->name); @@ -673,6 +934,21 @@ static void print_result(void) 0 : st->wait_time_min); printf("\n"); } + + { + /* Output for debug, this have to be removed */ + int i; + const char *name[4] = + { "acquire", "acquired", "contended", "release" }; + + printf("\n=== output for debug===\n\n"); + printf("bad:%d, total:%d\n", bad, total); + printf("bad rate:%f\n", (double)(bad / total)); + + printf("histogram of events caused bad sequence\n"); + for (i = 0; i < 4; i++) + printf(" %10s: %d\n", name[i], bad_hist[i]); + } } static void dump_map(void) @@ -692,8 +968,6 @@ static struct perf_event_ops eops = { .comm = event__process_comm, }; -static struct perf_session *session; - static int read_events(void) { session = perf_session__new(input_name, O_RDONLY, 0); -- cgit v0.10.2 From 5710fcad7c367adefe5634dc998f1f88780a8457 Mon Sep 17 00:00:00 2001 From: Stephane Eranian Date: Wed, 21 Apr 2010 18:06:01 +0200 Subject: perf: Fix initialization bug in parse_single_tracepoint_event() The parse_single_tracepoint_event() was setting some attributes before it validated the event was indeed a tracepoint event. This caused problems with other initialization routines like in the builtin-top.c module whereby sample_period is not set if not 0. Signed-off-by: Stephane Eranian Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Ingo Molnar LKML-Reference: <4bcf232b.698fd80a.6fbe.ffffb737@mx.google.com> Signed-off-by: Frederic Weisbecker diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 3b4ec67..600d327 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -418,12 +418,6 @@ parse_single_tracepoint_event(char *sys_name, u64 id; int fd; - attr->sample_type |= PERF_SAMPLE_RAW; - attr->sample_type |= PERF_SAMPLE_TIME; - attr->sample_type |= PERF_SAMPLE_CPU; - - attr->sample_period = 1; - snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path, sys_name, evt_name); @@ -442,6 +436,13 @@ parse_single_tracepoint_event(char *sys_name, attr->type = PERF_TYPE_TRACEPOINT; *strp = evt_name + evt_length; + attr->sample_type |= PERF_SAMPLE_RAW; + attr->sample_type |= PERF_SAMPLE_TIME; + attr->sample_type |= PERF_SAMPLE_CPU; + + attr->sample_period = 1; + + return EVT_HANDLED; } -- cgit v0.10.2 From c61e52ee705f938596d307625dce00cc4345aaf0 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Sat, 24 Apr 2010 00:04:12 +0200 Subject: perf: Generalize perf lock's sample event reordering to the session layer The sample events recorded by perf record are not time ordered because we have one buffer per cpu for each event (even demultiplexed per task/per cpu for task bound events). But when we read trace events we want them to be ordered by time because many state machines are involved. There are currently two ways perf tools deal with that: - use -M to multiplex every buffers (perf sched, perf kmem) But this creates a lot of contention in SMP machines on record time. - use a post-processing time reordering (perf timechart, perf lock) The reordering used by timechart is simple but doesn't scale well with huge flow of events, in terms of performance and memory use (unusable with perf lock for example). Perf lock has its own samples reordering that flushes its memory use in a regular basis and that uses a sorting based on the previous event queued (a new event to be queued is close to the previous one most of the time). This patch proposes to export perf lock's samples reordering facility to the session layer that reads the events. So if a tool wants to get ordered sample events, it needs to set its struct perf_event_ops::ordered_samples to true and that's it. This prepares tracing based perf tools to get rid of the need to use buffers multiplexing (-M) or to implement their own reordering. Also lower the flush period to 2 as it's sufficient already. Signed-off-by: Frederic Weisbecker Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Hitoshi Mitake Cc: Ingo Molnar Cc: Masami Hiramatsu Cc: Tom Zanussi diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index 716d8c5..ce27675 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c @@ -316,8 +316,6 @@ alloc_failed: static char const *input_name = "perf.data"; -static int profile_cpu = -1; - struct raw_event_sample { u32 size; char data[0]; @@ -697,8 +695,7 @@ process_lock_release_event(void *data, } static void -process_raw_event(void *data, int cpu __used, - u64 timestamp __used, struct thread *thread __used) +process_raw_event(void *data, int cpu, u64 timestamp, struct thread *thread) { struct event *event; int type; @@ -716,176 +713,6 @@ process_raw_event(void *data, int cpu __used, process_lock_release_event(data, event, cpu, timestamp, thread); } -struct raw_event_queue { - u64 timestamp; - int cpu; - void *data; - struct thread *thread; - struct list_head list; -}; - -static LIST_HEAD(raw_event_head); - -#define FLUSH_PERIOD (5 * NSEC_PER_SEC) - -static u64 flush_limit = ULLONG_MAX; -static u64 last_flush = 0; -struct raw_event_queue *last_inserted; - -static void flush_raw_event_queue(u64 limit) -{ - struct raw_event_queue *tmp, *iter; - - list_for_each_entry_safe(iter, tmp, &raw_event_head, list) { - if (iter->timestamp > limit) - return; - - if (iter == last_inserted) - last_inserted = NULL; - - process_raw_event(iter->data, iter->cpu, iter->timestamp, - iter->thread); - - last_flush = iter->timestamp; - list_del(&iter->list); - free(iter->data); - free(iter); - } -} - -static void __queue_raw_event_end(struct raw_event_queue *new) -{ - struct raw_event_queue *iter; - - list_for_each_entry_reverse(iter, &raw_event_head, list) { - if (iter->timestamp < new->timestamp) { - list_add(&new->list, &iter->list); - return; - } - } - - list_add(&new->list, &raw_event_head); -} - -static void __queue_raw_event_before(struct raw_event_queue *new, - struct raw_event_queue *iter) -{ - list_for_each_entry_continue_reverse(iter, &raw_event_head, list) { - if (iter->timestamp < new->timestamp) { - list_add(&new->list, &iter->list); - return; - } - } - - list_add(&new->list, &raw_event_head); -} - -static void __queue_raw_event_after(struct raw_event_queue *new, - struct raw_event_queue *iter) -{ - list_for_each_entry_continue(iter, &raw_event_head, list) { - if (iter->timestamp > new->timestamp) { - list_add_tail(&new->list, &iter->list); - return; - } - } - list_add_tail(&new->list, &raw_event_head); -} - -/* The queue is ordered by time */ -static void __queue_raw_event(struct raw_event_queue *new) -{ - if (!last_inserted) { - __queue_raw_event_end(new); - return; - } - - /* - * Most of the time the current event has a timestamp - * very close to the last event inserted, unless we just switched - * to another event buffer. Having a sorting based on a list and - * on the last inserted event that is close to the current one is - * probably more efficient than an rbtree based sorting. - */ - if (last_inserted->timestamp >= new->timestamp) - __queue_raw_event_before(new, last_inserted); - else - __queue_raw_event_after(new, last_inserted); -} - -static void queue_raw_event(void *data, int raw_size, int cpu, - u64 timestamp, struct thread *thread) -{ - struct raw_event_queue *new; - - if (flush_limit == ULLONG_MAX) - flush_limit = timestamp + FLUSH_PERIOD; - - if (timestamp < last_flush) { - printf("Warning: Timestamp below last timeslice flush\n"); - return; - } - - new = malloc(sizeof(*new)); - if (!new) - die("Not enough memory\n"); - - new->timestamp = timestamp; - new->cpu = cpu; - new->thread = thread; - - new->data = malloc(raw_size); - if (!new->data) - die("Not enough memory\n"); - - memcpy(new->data, data, raw_size); - - __queue_raw_event(new); - last_inserted = new; - - /* - * We want to have a slice of events covering 2 * FLUSH_PERIOD - * If FLUSH_PERIOD is big enough, it ensures every events that occured - * in the first half of the timeslice have all been buffered and there - * are none remaining (we need that because of the weakly ordered - * event recording we have). Then once we reach the 2 * FLUSH_PERIOD - * timeslice, we flush the first half to be gentle with the memory - * (the second half can still get new events in the middle, so wait - * another period to flush it) - */ - if (new->timestamp > flush_limit && - new->timestamp - flush_limit > FLUSH_PERIOD) { - flush_limit += FLUSH_PERIOD; - flush_raw_event_queue(flush_limit); - } -} - -static int process_sample_event(event_t *event, struct perf_session *s) -{ - struct thread *thread; - struct sample_data data; - - bzero(&data, sizeof(struct sample_data)); - event__parse_sample(event, s->sample_type, &data); - /* CAUTION: using tid as thread.pid */ - thread = perf_session__findnew(s, data.tid); - - if (thread == NULL) { - pr_debug("problem processing %d event, skipping it.\n", - event->header.type); - return -1; - } - - dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); - - if (profile_cpu != -1 && profile_cpu != (int) data.cpu) - return 0; - - queue_raw_event(data.raw_data, data.raw_size, data.cpu, data.time, thread); - - return 0; -} - /* TODO: various way to print, coloring, nano or milli sec */ static void print_result(void) { @@ -963,9 +790,30 @@ static void dump_map(void) } } +static int process_sample_event(event_t *self, struct perf_session *s) +{ + struct sample_data data; + struct thread *thread; + + bzero(&data, sizeof(data)); + event__parse_sample(self, s->sample_type, &data); + + thread = perf_session__findnew(s, data.tid); + if (thread == NULL) { + pr_debug("problem processing %d event, skipping it.\n", + self->header.type); + return -1; + } + + process_raw_event(data.raw_data, data.cpu, data.time, thread); + + return 0; +} + static struct perf_event_ops eops = { .sample = process_sample_event, .comm = event__process_comm, + .ordered_samples = true, }; static int read_events(void) @@ -994,7 +842,6 @@ static void __cmd_report(void) setup_pager(); select_key(); read_events(); - flush_raw_event_queue(ULLONG_MAX); sort_result(); print_result(); } diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 7d88ae5..b7aade2 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -98,6 +98,8 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc self->cwdlen = 0; self->unknown_events = 0; self->kerninfo_root = RB_ROOT; + self->ordered_samples.flush_limit = ULLONG_MAX; + INIT_LIST_HEAD(&self->ordered_samples.samples_head); if (mode == O_RDONLY) { if (perf_session__open(self, force) < 0) @@ -351,6 +353,178 @@ static event__swap_op event__swap_ops[] = { [PERF_RECORD_HEADER_MAX] = NULL, }; +struct sample_queue { + u64 timestamp; + struct sample_event *event; + struct list_head list; +}; + +#define FLUSH_PERIOD (2 * NSEC_PER_SEC) + +static void flush_sample_queue(struct perf_session *s, + struct perf_event_ops *ops) +{ + struct list_head *head = &s->ordered_samples.samples_head; + u64 limit = s->ordered_samples.flush_limit; + struct sample_queue *tmp, *iter; + + if (!ops->ordered_samples) + return; + + list_for_each_entry_safe(iter, tmp, head, list) { + if (iter->timestamp > limit) + return; + + if (iter == s->ordered_samples.last_inserted) + s->ordered_samples.last_inserted = NULL; + + ops->sample((event_t *)iter->event, s); + + s->ordered_samples.last_flush = iter->timestamp; + list_del(&iter->list); + free(iter->event); + free(iter); + } +} + +static void __queue_sample_end(struct sample_queue *new, struct list_head *head) +{ + struct sample_queue *iter; + + list_for_each_entry_reverse(iter, head, list) { + if (iter->timestamp < new->timestamp) { + list_add(&new->list, &iter->list); + return; + } + } + + list_add(&new->list, head); +} + +static void __queue_sample_before(struct sample_queue *new, + struct sample_queue *iter, + struct list_head *head) +{ + list_for_each_entry_continue_reverse(iter, head, list) { + if (iter->timestamp < new->timestamp) { + list_add(&new->list, &iter->list); + return; + } + } + + list_add(&new->list, head); +} + +static void __queue_sample_after(struct sample_queue *new, + struct sample_queue *iter, + struct list_head *head) +{ + list_for_each_entry_continue(iter, head, list) { + if (iter->timestamp > new->timestamp) { + list_add_tail(&new->list, &iter->list); + return; + } + } + list_add_tail(&new->list, head); +} + +/* The queue is ordered by time */ +static void __queue_sample_event(struct sample_queue *new, + struct perf_session *s) +{ + struct sample_queue *last_inserted = s->ordered_samples.last_inserted; + struct list_head *head = &s->ordered_samples.samples_head; + + + if (!last_inserted) { + __queue_sample_end(new, head); + return; + } + + /* + * Most of the time the current event has a timestamp + * very close to the last event inserted, unless we just switched + * to another event buffer. Having a sorting based on a list and + * on the last inserted event that is close to the current one is + * probably more efficient than an rbtree based sorting. + */ + if (last_inserted->timestamp >= new->timestamp) + __queue_sample_before(new, last_inserted, head); + else + __queue_sample_after(new, last_inserted, head); +} + +static int queue_sample_event(event_t *event, struct sample_data *data, + struct perf_session *s, + struct perf_event_ops *ops) +{ + u64 timestamp = data->time; + struct sample_queue *new; + u64 flush_limit; + + + if (s->ordered_samples.flush_limit == ULLONG_MAX) + s->ordered_samples.flush_limit = timestamp + FLUSH_PERIOD; + + if (timestamp < s->ordered_samples.last_flush) { + printf("Warning: Timestamp below last timeslice flush\n"); + return -EINVAL; + } + + new = malloc(sizeof(*new)); + if (!new) + return -ENOMEM; + + new->timestamp = timestamp; + + new->event = malloc(event->header.size); + if (!new->event) { + free(new); + return -ENOMEM; + } + + memcpy(new->event, event, event->header.size); + + __queue_sample_event(new, s); + s->ordered_samples.last_inserted = new; + + /* + * We want to have a slice of events covering 2 * FLUSH_PERIOD + * If FLUSH_PERIOD is big enough, it ensures every events that occured + * in the first half of the timeslice have all been buffered and there + * are none remaining (we need that because of the weakly ordered + * event recording we have). Then once we reach the 2 * FLUSH_PERIOD + * timeslice, we flush the first half to be gentle with the memory + * (the second half can still get new events in the middle, so wait + * another period to flush it) + */ + flush_limit = s->ordered_samples.flush_limit; + + if (new->timestamp > flush_limit && + new->timestamp - flush_limit > FLUSH_PERIOD) { + s->ordered_samples.flush_limit += FLUSH_PERIOD; + flush_sample_queue(s, ops); + } + + return 0; +} + +static int perf_session__process_sample(event_t *event, struct perf_session *s, + struct perf_event_ops *ops) +{ + struct sample_data data; + + if (!ops->ordered_samples) + return ops->sample(event, s); + + bzero(&data, sizeof(struct sample_data)); + event__parse_sample(event, s->sample_type, &data); + + queue_sample_event(event, &data, s, ops); + + return 0; +} + static int perf_session__process_event(struct perf_session *self, event_t *event, struct perf_event_ops *ops, @@ -371,7 +545,7 @@ static int perf_session__process_event(struct perf_session *self, switch (event->header.type) { case PERF_RECORD_SAMPLE: - return ops->sample(event, self); + return perf_session__process_sample(event, self, ops); case PERF_RECORD_MMAP: return ops->mmap(event, self); case PERF_RECORD_COMM: @@ -611,6 +785,9 @@ more: goto more; done: err = 0; + /* do the final flush for ordered samples */ + self->ordered_samples.flush_limit = ULLONG_MAX; + flush_sample_queue(self, ops); out_err: ui_progress__delete(progress); return err; diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 5e47c87..796e229 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -8,9 +8,17 @@ #include #include "../../../include/linux/perf_event.h" +struct sample_queue; struct ip_callchain; struct thread; +struct ordered_samples { + u64 last_flush; + u64 flush_limit; + struct list_head samples_head; + struct sample_queue *last_inserted; +}; + struct perf_session { struct perf_header header; unsigned long size; @@ -28,6 +36,7 @@ struct perf_session { bool fd_pipe; int cwdlen; char *cwd; + struct ordered_samples ordered_samples; char filename[0]; }; @@ -47,6 +56,7 @@ struct perf_event_ops { event_type, tracing_data, build_id; + bool ordered_samples; }; struct perf_session *perf_session__new(const char *filename, int mode, bool force); -- cgit v0.10.2 From a64eae703b390185abe1d15fa932b48f04fa7fbb Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Sat, 24 Apr 2010 00:29:40 +0200 Subject: perf: Use generic sample reordering in perf sched Use the new generic sample events reordering from perf sched, this drops the need of multiplexing the buffers on record time, improving the scalability of perf sched. Signed-off-by: Frederic Weisbecker Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Hitoshi Mitake Cc: Ingo Molnar Cc: Masami Hiramatsu Cc: Tom Zanussi diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 09ddc8e..94453f1 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -1651,9 +1651,10 @@ static int process_lost_event(event_t *event __used, } static struct perf_event_ops event_ops = { - .sample = process_sample_event, - .comm = event__process_comm, - .lost = process_lost_event, + .sample = process_sample_event, + .comm = event__process_comm, + .lost = process_lost_event, + .ordered_samples = true, }; static int read_events(void) @@ -1850,7 +1851,6 @@ static const char *record_args[] = { "record", "-a", "-R", - "-M", "-f", "-m", "1024", "-c", "1", -- cgit v0.10.2 From 587570d4cc3cac80da7d569bee9cea3ca104d60e Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Sat, 24 Apr 2010 00:34:53 +0200 Subject: perf: Use generic sample reordering in perf kmem Use the new generic sample events reordering from perf kmem, this drops the need of multiplexing the buffers on record time, improving the scalability of perf kmem. Signed-off-by: Frederic Weisbecker Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Hitoshi Mitake Cc: Ingo Molnar Cc: Masami Hiramatsu Cc: Tom Zanussi Cc: Pekka Enberg Cc: Li Zefan diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index db474bb..ab906cb 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c @@ -335,8 +335,9 @@ static int process_sample_event(event_t *event, struct perf_session *session) } static struct perf_event_ops event_ops = { - .sample = process_sample_event, - .comm = event__process_comm, + .sample = process_sample_event, + .comm = event__process_comm, + .ordered_samples = true, }; static double fragmentation(unsigned long n_req, unsigned long n_alloc) @@ -730,7 +731,6 @@ static const char *record_args[] = { "record", "-a", "-R", - "-M", "-f", "-c", "1", "-e", "kmem:kmalloc", -- cgit v0.10.2 From e0a808c65c23f88e48a5fff48775b90e7919c64f Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Sat, 24 Apr 2010 00:38:33 +0200 Subject: perf: Use generic sample reordering in perf trace Use the new generic sample events reordering from perf trace. Before that, the displayed traces were ordered as they were in the input as recorded by perf record (not time ordered). This makes eventually perf trace displaying the events as beeing time ordered. Signed-off-by: Frederic Weisbecker Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Hitoshi Mitake Cc: Ingo Molnar Cc: Masami Hiramatsu Cc: Tom Zanussi diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 2eefb33..1d034f6 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -108,6 +108,7 @@ static struct perf_event_ops event_ops = { .event_type = event__process_event_type, .tracing_data = event__process_tracing_data, .build_id = event__process_build_id, + .ordered_samples = true, }; extern volatile int session_done; -- cgit v0.10.2 From 9df9bbba9f7e2e4ffdc51bbbfa524b67691321d2 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Sat, 24 Apr 2010 01:18:48 +0200 Subject: perf: Use generic sample reordering in perf timechart Use the new generic sample events reordering from perf timechart, this drops the ad hoc sample reordering it was using before. Signed-off-by: Frederic Weisbecker Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Hitoshi Mitake Cc: Ingo Molnar Cc: Masami Hiramatsu Cc: Tom Zanussi Cc: Arjan van de Ven diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index 96f4a09..c35aa44 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c @@ -143,9 +143,6 @@ struct wake_event { static struct power_event *power_events; static struct wake_event *wake_events; -struct sample_wrapper *all_samples; - - struct process_filter; struct process_filter { char *name; @@ -566,88 +563,6 @@ static void end_sample_processing(void) } } -static u64 sample_time(event_t *event, const struct perf_session *session) -{ - int cursor; - - cursor = 0; - if (session->sample_type & PERF_SAMPLE_IP) - cursor++; - if (session->sample_type & PERF_SAMPLE_TID) - cursor++; - if (session->sample_type & PERF_SAMPLE_TIME) - return event->sample.array[cursor]; - return 0; -} - - -/* - * We first queue all events, sorted backwards by insertion. - * The order will get flipped later. - */ -static int queue_sample_event(event_t *event, struct perf_session *session) -{ - struct sample_wrapper *copy, *prev; - int size; - - size = event->sample.header.size + sizeof(struct sample_wrapper) + 8; - - copy = malloc(size); - if (!copy) - return 1; - - memset(copy, 0, size); - - copy->next = NULL; - copy->timestamp = sample_time(event, session); - - memcpy(©->data, event, event->sample.header.size); - - /* insert in the right place in the list */ - - if (!all_samples) { - /* first sample ever */ - all_samples = copy; - return 0; - } - - if (all_samples->timestamp < copy->timestamp) { - /* insert at the head of the list */ - copy->next = all_samples; - all_samples = copy; - return 0; - } - - prev = all_samples; - while (prev->next) { - if (prev->next->timestamp < copy->timestamp) { - copy->next = prev->next; - prev->next = copy; - return 0; - } - prev = prev->next; - } - /* insert at the end of the list */ - prev->next = copy; - - return 0; -} - -static void sort_queued_samples(void) -{ - struct sample_wrapper *cursor, *next; - - cursor = all_samples; - all_samples = NULL; - - while (cursor) { - next = cursor->next; - cursor->next = all_samples; - all_samples = cursor; - cursor = next; - } -} - /* * Sort the pid datastructure */ @@ -1011,26 +926,12 @@ static void write_svg_file(const char *filename) svg_close(); } -static void process_samples(struct perf_session *session) -{ - struct sample_wrapper *cursor; - event_t *event; - - sort_queued_samples(); - - cursor = all_samples; - while (cursor) { - event = (void *)&cursor->data; - cursor = cursor->next; - process_sample_event(event, session); - } -} - static struct perf_event_ops event_ops = { - .comm = process_comm_event, - .fork = process_fork_event, - .exit = process_exit_event, - .sample = queue_sample_event, + .comm = process_comm_event, + .fork = process_fork_event, + .exit = process_exit_event, + .sample = process_sample_event, + .ordered_samples = true, }; static int __cmd_timechart(void) @@ -1048,8 +949,6 @@ static int __cmd_timechart(void) if (ret) goto out_delete; - process_samples(session); - end_sample_processing(); sort_pids(); @@ -1072,7 +971,6 @@ static const char *record_args[] = { "record", "-a", "-R", - "-M", "-f", "-c", "1", "-e", "power:power_start", -- cgit v0.10.2 From e1889d75aff0c3786bc53aeb7d9eaca0691c19c5 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Sat, 24 Apr 2010 01:55:09 +0200 Subject: perf: Add a perf trace option to check samples ordering reliability To ensure sample events time reordering is reliable, add a -d option to perf trace to check that automatically. Signed-off-by: Frederic Weisbecker Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Hitoshi Mitake Cc: Ingo Molnar Cc: Masami Hiramatsu Cc: Tom Zanussi diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 1d034f6..77f556f 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -11,6 +11,8 @@ static char const *script_name; static char const *generate_script_lang; +static bool debug_ordering; +static u64 last_timestamp; static int default_start_script(const char *script __unused, int argc __unused, @@ -87,6 +89,14 @@ static int process_sample_event(event_t *event, struct perf_session *session) } if (session->sample_type & PERF_SAMPLE_RAW) { + if (debug_ordering) { + if (data.time < last_timestamp) { + pr_err("Samples misordered, previous: %llu " + "this: %llu\n", last_timestamp, + data.time); + } + last_timestamp = data.time; + } /* * FIXME: better resolve from pid from the struct trace_entry * field, although it should be the same than this perf @@ -532,6 +542,8 @@ static const struct option options[] = { "generate perf-trace.xx script in specified language"), OPT_STRING('i', "input", &input_name, "file", "input file name"), + OPT_BOOLEAN('d', "debug-ordering", &debug_ordering, + "check that samples time ordering is monotonic"), OPT_END() }; -- cgit v0.10.2 From cfadf9d4ac4be940595ab73d3def24c23c8b875f Mon Sep 17 00:00:00 2001 From: William Cohen Date: Fri, 23 Apr 2010 16:36:21 -0400 Subject: perf: Some perf-kvm documentation edits asciidoc does not allow the "===" to be longer than the line above it. Also fix a couple types and formatting errors. Signed-off-by: William Cohen Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Ingo Molnar LKML-Reference: <4BD204C5.9000504@redhat.com> Signed-off-by: Frederic Weisbecker diff --git a/tools/perf/Documentation/perf-kvm.txt b/tools/perf/Documentation/perf-kvm.txt index 93400a0..d004e19 100644 --- a/tools/perf/Documentation/perf-kvm.txt +++ b/tools/perf/Documentation/perf-kvm.txt @@ -1,5 +1,5 @@ perf-kvm(1) -============== +=========== NAME ---- @@ -41,9 +41,9 @@ There are a couple of variants of perf kvm: OPTIONS ------- --host=:: - Collect host side perforamnce profile. + Collect host side performance profile. --guest=:: - Collect guest side perforamnce profile. + Collect guest side performance profile. --guestmount=:: Guest os root file system mount directory. Users mounts guest os root directories under by a specific filesystem access method, @@ -64,4 +64,5 @@ OPTIONS SEE ALSO -------- -linkperf:perf-top[1] perf-record[1] perf-report[1] perf-diff[1] perf-buildid-list[1] +linkperf:perf-top[1], linkperf:perf-record[1], linkperf:perf-report[1], +linkperf:perf-diff[1], linkperf:perf-buildid-list[1] -- cgit v0.10.2 From 7c4584d39a8a144c60adaf4cf998c3233b6683d9 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Sat, 24 Apr 2010 11:12:12 +0100 Subject: sh: Assembly friendly __pa and __va definitions This patch defines ___pa and ___va which return the physical and virtual address of an address, respectively. These macros are suitable for calling from assembly because they don't include the C casts required by __pa and __va. Signed-off-by: Matt Fleming diff --git a/arch/sh/include/asm/page.h b/arch/sh/include/asm/page.h index d71feb3..0152c04 100644 --- a/arch/sh/include/asm/page.h +++ b/arch/sh/include/asm/page.h @@ -128,13 +128,18 @@ typedef struct page *pgtable_t; * added or subtracted as required. */ #ifdef CONFIG_PMB -#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET+__MEMORY_START) -#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET-__MEMORY_START)) +#define ___pa(x) ((x)-PAGE_OFFSET+__MEMORY_START) +#define ___va(x) ((x)+PAGE_OFFSET-__MEMORY_START) #else -#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET) -#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET)) +#define ___pa(x) ((x)-PAGE_OFFSET) +#define ___va(x) ((x)+PAGE_OFFSET) #endif +#ifndef __ASSEMBLY__ +#define __pa(x) ___pa((unsigned long)x) +#define __va(x) (void *)___va((unsigned long)x) +#endif /* !__ASSEMBLY__ */ + #ifdef CONFIG_UNCACHED_MAPPING #define UNCAC_ADDR(addr) ((addr) - PAGE_OFFSET + uncached_start) #define CAC_ADDR(addr) ((addr) - uncached_start + PAGE_OFFSET) -- cgit v0.10.2 From b161313ae8d9c64de589d1de72f975210ce37b48 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Sat, 24 Apr 2010 13:28:20 +0100 Subject: sh: Fix address to decompress at when CONFIG_32BIT=y When running in 32BIT mode the P1SEG region doesn't necessarily provide a window onto RAM (it depends how the bootloader setup the PMB). The correct location to place the decompressed kernel is the physical address of _text. Signed-off-by: Matt Fleming diff --git a/arch/sh/boot/compressed/head_32.S b/arch/sh/boot/compressed/head_32.S index 02a3093..200c1d4 100644 --- a/arch/sh/boot/compressed/head_32.S +++ b/arch/sh/boot/compressed/head_32.S @@ -97,7 +97,11 @@ init_stack_addr: decompress_kernel_addr: .long decompress_kernel kernel_start_addr: +#ifdef CONFIG_32BIT + .long ___pa(_text+PAGE_SIZE) +#else .long _text+PAGE_SIZE +#endif .align 9 fake_headers_as_bzImage: -- cgit v0.10.2 From 9c3d936352fefaadec57bafda1fe3807890cbf2c Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Sat, 24 Apr 2010 13:34:44 +0100 Subject: sh: Fix zImage load address when CONFIG_32BIT=y We can't necessarily use the P1SEG region to access RAM when running in 32BIT mode, so use CONFIG_MEMORY_START as the base address. Signed-off-by: Matt Fleming diff --git a/arch/sh/boot/compressed/Makefile b/arch/sh/boot/compressed/Makefile index 5d660b9..cfa5a08 100644 --- a/arch/sh/boot/compressed/Makefile +++ b/arch/sh/boot/compressed/Makefile @@ -14,10 +14,16 @@ OBJECTS = $(obj)/head_$(BITS).o $(obj)/misc.o $(obj)/cache.o # # IMAGE_OFFSET is the load offset of the compression loader # +ifeq ($(CONFIG_32BIT),y) +IMAGE_OFFSET := $(shell /bin/bash -c 'printf "0x%08x" \ + $$[$(CONFIG_MEMORY_START) + \ + $(CONFIG_BOOT_LINK_OFFSET)]') +else IMAGE_OFFSET := $(shell /bin/bash -c 'printf "0x%08x" \ $$[$(CONFIG_PAGE_OFFSET) + \ $(KERNEL_MEMORY) + \ $(CONFIG_BOOT_LINK_OFFSET)]') +endif LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) -- cgit v0.10.2 From c7b03fa0bdc04e00bfbdc4cc69da144b11108f37 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Sun, 25 Apr 2010 17:29:07 +0100 Subject: sh: Do not try merging two 128MB PMB mappings There is a logic error in pmb_merge() that means we will incorrectly try to merge two 128MB PMB mappings into one mapping. However, 256MB isn't a valid PMB map size and pmb_merge() will actually drop the second 128MB mapping. This patch allows my SDK7786 board to boot when configured with CONFIG_MEMORY_SIZE=0x10000000. Signed-off-by: Matt Fleming diff --git a/arch/sh/mm/pmb.c b/arch/sh/mm/pmb.c index 3cc2193..c0fdc21 100644 --- a/arch/sh/mm/pmb.c +++ b/arch/sh/mm/pmb.c @@ -681,7 +681,7 @@ static void __init pmb_merge(struct pmb_entry *head) /* * The merged page size must be valid. */ - if (!pmb_size_valid(newsize)) + if (!depth || !pmb_size_valid(newsize)) return; head->flags &= ~PMB_SZ_MASK; -- cgit v0.10.2 From 035ca59fe8399a67b56511bd5b28130f0c4874a0 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Sun, 25 Apr 2010 20:18:41 +0100 Subject: sh: Use correct mask when comparing PMB DATA array values Previously we were masking the PMB DATA array values with the value of __MEMORY_START | PMB_V, which misses some PFN bits off the mask. Signed-off-by: Matt Fleming diff --git a/arch/sh/kernel/head_32.S b/arch/sh/kernel/head_32.S index 8c1fc9a..6e35f01 100644 --- a/arch/sh/kernel/head_32.S +++ b/arch/sh/kernel/head_32.S @@ -131,6 +131,7 @@ ENTRY(_stext) * r8 = scratch register * r9 = scratch register * r10 = number of PMB entries we've setup + * r11 = scratch register */ mov.l .LMMUCR, r1 /* Flush the TLB */ @@ -167,8 +168,9 @@ ENTRY(_stext) .Lvalidate_existing_mappings: + mov.l .LPMB_DATA_MASK, r11 mov.l @r7, r8 - and r0, r8 + and r11, r8 cmp/eq r0, r8 /* Check for valid __MEMORY_START mappings */ bt .Lpmb_done @@ -341,6 +343,7 @@ ENTRY(stack_start) #ifdef CONFIG_PMB .LPMB_ADDR: .long PMB_ADDR .LPMB_DATA: .long PMB_DATA +.LPMB_DATA_MASK: .long PMB_PFN_MASK | PMB_V .LFIRST_ADDR_ENTRY: .long PAGE_OFFSET | PMB_V .LFIRST_DATA_ENTRY: .long __MEMORY_START | PMB_V .LMMUCR: .long MMUCR -- cgit v0.10.2 From 6b6b18e62cfba44ce7b6489c7100f12b199232d7 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Thu, 22 Apr 2010 16:06:26 +0000 Subject: sh: invoke oom-killer from page fault As explained in commit 1c0fe6e3bd, we want to call the architecture independent oom killer when getting an unexplained OOM from handle_mm_fault, rather than simply killing current. Cc: linux-sh@vger.kernel.org Cc: linux-arch@vger.kernel.org Signed-off-by: Nick Piggin Acked-by: David Rientjes Signed-off-by: Paul Mundt diff --git a/arch/sh/mm/fault_32.c b/arch/sh/mm/fault_32.c index 8bf79e3..93c3447 100644 --- a/arch/sh/mm/fault_32.c +++ b/arch/sh/mm/fault_32.c @@ -290,15 +290,10 @@ no_context: */ out_of_memory: up_read(&mm->mmap_sem); - if (is_global_init(current)) { - yield(); - down_read(&mm->mmap_sem); - goto survive; - } - printk("VM: killing process %s\n", tsk->comm); - if (user_mode(regs)) - do_group_exit(SIGKILL); - goto no_context; + if (!user_mode(regs)) + goto no_context; + pagefault_out_of_memory(); + return; do_sigbus: up_read(&mm->mmap_sem); diff --git a/arch/sh/mm/tlbflush_64.c b/arch/sh/mm/tlbflush_64.c index 706da1d..25bd64c 100644 --- a/arch/sh/mm/tlbflush_64.c +++ b/arch/sh/mm/tlbflush_64.c @@ -294,22 +294,11 @@ no_context: * us unable to handle the page fault gracefully. */ out_of_memory: - if (is_global_init(current)) { - panic("INIT out of memory\n"); - yield(); - goto survive; - } - printk("fault:Out of memory\n"); up_read(&mm->mmap_sem); - if (is_global_init(current)) { - yield(); - down_read(&mm->mmap_sem); - goto survive; - } - printk("VM: killing process %s\n", tsk->comm); - if (user_mode(regs)) - do_group_exit(SIGKILL); - goto no_context; + if (!user_mode(regs)) + goto no_context; + pagefault_out_of_memory(); + return; do_sigbus: printk("fault:Do sigbus\n"); -- cgit v0.10.2 From 5bac942db3d2c4738df04104240d65a5d1eaec6a Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 21 Apr 2010 15:36:49 +0000 Subject: SH: constify multiple DMA related objects and references to them Lists of DMA channels and slaves are not changed, make them constant. Besides, SH7724 channel and slave configuration of both DMA controllers is identical, remove the extra copy of the configuration data. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c index dc9b30d..24c6167 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c @@ -24,7 +24,7 @@ #include #include -static struct sh_dmae_slave_config sh7722_dmae_slaves[] = { +static const struct sh_dmae_slave_config sh7722_dmae_slaves[] = { { .slave_id = SHDMA_SLAVE_SCIF0_TX, .addr = 0xffe0000c, @@ -78,7 +78,7 @@ static struct sh_dmae_slave_config sh7722_dmae_slaves[] = { }, }; -static struct sh_dmae_channel sh7722_dmae_channels[] = { +static const struct sh_dmae_channel sh7722_dmae_channels[] = { { .offset = 0, .dmars = 0, @@ -106,7 +106,7 @@ static struct sh_dmae_channel sh7722_dmae_channels[] = { } }; -static unsigned int ts_shift[] = TS_SHIFT; +static const unsigned int ts_shift[] = TS_SHIFT; static struct sh_dmae_pdata dma_platform_data = { .slave = sh7722_dmae_slaves, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c index 8a0a4a9..89fe16d2 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c @@ -31,7 +31,7 @@ #include /* DMA */ -static struct sh_dmae_channel sh7724_dmae0_channels[] = { +static const struct sh_dmae_channel sh7724_dmae_channels[] = { { .offset = 0, .dmars = 0, @@ -59,51 +59,11 @@ static struct sh_dmae_channel sh7724_dmae0_channels[] = { } }; -static struct sh_dmae_channel sh7724_dmae1_channels[] = { - { - .offset = 0, - .dmars = 0, - .dmars_bit = 0, - }, { - .offset = 0x10, - .dmars = 0, - .dmars_bit = 8, - }, { - .offset = 0x20, - .dmars = 4, - .dmars_bit = 0, - }, { - .offset = 0x30, - .dmars = 4, - .dmars_bit = 8, - }, { - .offset = 0x50, - .dmars = 8, - .dmars_bit = 0, - }, { - .offset = 0x60, - .dmars = 8, - .dmars_bit = 8, - } -}; - -static unsigned int ts_shift[] = TS_SHIFT; - -static struct sh_dmae_pdata dma0_platform_data = { - .channel = sh7724_dmae0_channels, - .channel_num = ARRAY_SIZE(sh7724_dmae0_channels), - .ts_low_shift = CHCR_TS_LOW_SHIFT, - .ts_low_mask = CHCR_TS_LOW_MASK, - .ts_high_shift = CHCR_TS_HIGH_SHIFT, - .ts_high_mask = CHCR_TS_HIGH_MASK, - .ts_shift = ts_shift, - .ts_shift_num = ARRAY_SIZE(ts_shift), - .dmaor_init = DMAOR_INIT, -}; +static const unsigned int ts_shift[] = TS_SHIFT; -static struct sh_dmae_pdata dma1_platform_data = { - .channel = sh7724_dmae1_channels, - .channel_num = ARRAY_SIZE(sh7724_dmae1_channels), +static struct sh_dmae_pdata dma_platform_data = { + .channel = sh7724_dmae_channels, + .channel_num = ARRAY_SIZE(sh7724_dmae_channels), .ts_low_shift = CHCR_TS_LOW_SHIFT, .ts_low_mask = CHCR_TS_LOW_MASK, .ts_high_shift = CHCR_TS_HIGH_SHIFT, @@ -187,7 +147,7 @@ static struct platform_device dma0_device = { .resource = sh7724_dmae0_resources, .num_resources = ARRAY_SIZE(sh7724_dmae0_resources), .dev = { - .platform_data = &dma0_platform_data, + .platform_data = &dma_platform_data, }, .archdata = { .hwblk_id = HWBLK_DMAC0, @@ -200,7 +160,7 @@ static struct platform_device dma1_device = { .resource = sh7724_dmae1_resources, .num_resources = ARRAY_SIZE(sh7724_dmae1_resources), .dev = { - .platform_data = &dma1_platform_data, + .platform_data = &dma_platform_data, }, .archdata = { .hwblk_id = HWBLK_DMAC1, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c index 05fc38d..b12f537 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c @@ -233,7 +233,7 @@ static struct platform_device rtc_device = { }; /* DMA */ -static struct sh_dmae_channel sh7780_dmae0_channels[] = { +static const struct sh_dmae_channel sh7780_dmae0_channels[] = { { .offset = 0, .dmars = 0, @@ -261,7 +261,7 @@ static struct sh_dmae_channel sh7780_dmae0_channels[] = { } }; -static struct sh_dmae_channel sh7780_dmae1_channels[] = { +static const struct sh_dmae_channel sh7780_dmae1_channels[] = { { .offset = 0, }, { @@ -277,7 +277,7 @@ static struct sh_dmae_channel sh7780_dmae1_channels[] = { } }; -static unsigned int ts_shift[] = TS_SHIFT; +static const unsigned int ts_shift[] = TS_SHIFT; static struct sh_dmae_pdata dma0_platform_data = { .channel = sh7780_dmae0_channels, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c index 07bb2d4..f3e3ea0 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c @@ -275,7 +275,7 @@ static struct platform_device tmu5_device = { }; /* DMA */ -static struct sh_dmae_channel sh7785_dmae0_channels[] = { +static const struct sh_dmae_channel sh7785_dmae0_channels[] = { { .offset = 0, .dmars = 0, @@ -303,7 +303,7 @@ static struct sh_dmae_channel sh7785_dmae0_channels[] = { } }; -static struct sh_dmae_channel sh7785_dmae1_channels[] = { +static const struct sh_dmae_channel sh7785_dmae1_channels[] = { { .offset = 0, }, { @@ -319,7 +319,7 @@ static struct sh_dmae_channel sh7785_dmae1_channels[] = { } }; -static unsigned int ts_shift[] = TS_SHIFT; +static const unsigned int ts_shift[] = TS_SHIFT; static struct sh_dmae_pdata dma0_platform_data = { .channel = sh7785_dmae0_channels, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c index d733603..8165709 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c @@ -445,7 +445,7 @@ static struct platform_device tmu11_device = { .num_resources = ARRAY_SIZE(tmu11_resources), }; -static struct sh_dmae_channel dmac0_channels[] = { +static const struct sh_dmae_channel dmac0_channels[] = { { .offset = 0, .dmars = 0, @@ -473,7 +473,7 @@ static struct sh_dmae_channel dmac0_channels[] = { } }; -static unsigned int ts_shift[] = TS_SHIFT; +static const unsigned int ts_shift[] = TS_SHIFT; static struct sh_dmae_pdata dma0_platform_data = { .channel = dmac0_channels, diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index 7a18b58..aab352a 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c @@ -188,7 +188,7 @@ static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val) struct sh_dmae_device *shdev = container_of(sh_chan->common.device, struct sh_dmae_device, common); struct sh_dmae_pdata *pdata = shdev->pdata; - struct sh_dmae_channel *chan_pdata = &pdata->channel[sh_chan->id]; + const struct sh_dmae_channel *chan_pdata = &pdata->channel[sh_chan->id]; u16 __iomem *addr = shdev->dmars + chan_pdata->dmars / sizeof(u16); int shift = chan_pdata->dmars_bit; @@ -264,7 +264,7 @@ static struct sh_desc *sh_dmae_get_desc(struct sh_dmae_chan *sh_chan) return NULL; } -static struct sh_dmae_slave_config *sh_dmae_find_slave( +static const struct sh_dmae_slave_config *sh_dmae_find_slave( struct sh_dmae_chan *sh_chan, struct sh_dmae_slave *param) { struct dma_device *dma_dev = sh_chan->common.device; @@ -296,7 +296,7 @@ static int sh_dmae_alloc_chan_resources(struct dma_chan *chan) * never runs concurrently with itself or free_chan_resources. */ if (param) { - struct sh_dmae_slave_config *cfg; + const struct sh_dmae_slave_config *cfg; cfg = sh_dmae_find_slave(sh_chan, param); if (!cfg) @@ -557,12 +557,14 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_slave_sg( { struct sh_dmae_slave *param; struct sh_dmae_chan *sh_chan; + dma_addr_t slave_addr; if (!chan) return NULL; sh_chan = to_sh_chan(chan); param = chan->private; + slave_addr = param->config->addr; /* Someone calling slave DMA on a public channel? */ if (!param || !sg_len) { @@ -575,7 +577,7 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_slave_sg( * if (param != NULL), this is a successfully requested slave channel, * therefore param->config != NULL too. */ - return sh_dmae_prep_sg(sh_chan, sgl, sg_len, ¶m->config->addr, + return sh_dmae_prep_sg(sh_chan, sgl, sg_len, &slave_addr, direction, flags); } @@ -856,7 +858,7 @@ static int __devinit sh_dmae_chan_probe(struct sh_dmae_device *shdev, int id, int irq, unsigned long flags) { int err; - struct sh_dmae_channel *chan_pdata = &shdev->pdata->channel[id]; + const struct sh_dmae_channel *chan_pdata = &shdev->pdata->channel[id]; struct platform_device *pdev = to_platform_device(shdev->common.dev); struct sh_dmae_chan *new_sh_chan; diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h index cdaaff4..b08cd4e 100644 --- a/include/linux/sh_dma.h +++ b/include/linux/sh_dma.h @@ -17,7 +17,7 @@ struct sh_dmae_slave { unsigned int slave_id; /* Set by the platform */ struct device *dma_dev; /* Set by the platform */ - struct sh_dmae_slave_config *config; /* Set by the driver */ + const struct sh_dmae_slave_config *config; /* Set by the driver */ }; struct sh_dmae_regs { @@ -36,6 +36,7 @@ struct sh_desc { int chunks; int mark; }; + struct sh_dmae_slave_config { unsigned int slave_id; dma_addr_t addr; @@ -50,15 +51,15 @@ struct sh_dmae_channel { }; struct sh_dmae_pdata { - struct sh_dmae_slave_config *slave; + const struct sh_dmae_slave_config *slave; int slave_num; - struct sh_dmae_channel *channel; + const struct sh_dmae_channel *channel; int channel_num; unsigned int ts_low_shift; unsigned int ts_low_mask; unsigned int ts_high_shift; unsigned int ts_high_mask; - unsigned int *ts_shift; + const unsigned int *ts_shift; int ts_shift_num; u16 dmaor_init; }; -- cgit v0.10.2 From 364b97d9e2fec32b7c125f67e5a9e5f1cd0e6a37 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 26 Apr 2010 16:15:17 +0900 Subject: sh: Kill off dangling goto labels from oom-killer rework. Signed-off-by: Paul Mundt diff --git a/arch/sh/mm/fault_32.c b/arch/sh/mm/fault_32.c index 93c3447..d4c34d7 100644 --- a/arch/sh/mm/fault_32.c +++ b/arch/sh/mm/fault_32.c @@ -200,7 +200,6 @@ good_area: * make sure we exit gracefully rather than endlessly redo * the fault. */ -survive: fault = handle_mm_fault(mm, vma, address, writeaccess ? FAULT_FLAG_WRITE : 0); if (unlikely(fault & VM_FAULT_ERROR)) { if (fault & VM_FAULT_OOM) diff --git a/arch/sh/mm/tlbflush_64.c b/arch/sh/mm/tlbflush_64.c index 25bd64c..03db41c 100644 --- a/arch/sh/mm/tlbflush_64.c +++ b/arch/sh/mm/tlbflush_64.c @@ -189,7 +189,6 @@ good_area: * make sure we exit gracefully rather than endlessly redo * the fault. */ -survive: fault = handle_mm_fault(mm, vma, address, writeaccess ? FAULT_FLAG_WRITE : 0); if (unlikely(fault & VM_FAULT_ERROR)) { if (fault & VM_FAULT_OOM) -- cgit v0.10.2 From e60692b9347d17774cdad00ae2b9afd3dc5444af Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 26 Apr 2010 17:45:34 +0900 Subject: sh: mach-sdk7786: update defconfig for compressed kernel image. Now that compressed image loading is possible for sdk7786, drop the vmlinux.bin default image target and update the defconfig accordingly. Signed-off-by: Paul Mundt diff --git a/arch/sh/Makefile b/arch/sh/Makefile index 588579a..307b3a4 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile @@ -83,7 +83,6 @@ defaultimage-$(CONFIG_SH_AP325RXA) := uImage defaultimage-$(CONFIG_SH_7724_SOLUTION_ENGINE) := uImage defaultimage-$(CONFIG_SH_7206_SOLUTION_ENGINE) := vmlinux defaultimage-$(CONFIG_SH_7619_SOLUTION_ENGINE) := vmlinux -defaultimage-$(CONFIG_SH_SDK7786) := vmlinux.bin # Set some sensible Kbuild defaults KBUILD_IMAGE := $(defaultimage-y) diff --git a/arch/sh/configs/sdk7786_defconfig b/arch/sh/configs/sdk7786_defconfig index 9b331ea..740ada6 100644 --- a/arch/sh/configs/sdk7786_defconfig +++ b/arch/sh/configs/sdk7786_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc7 -# Tue Feb 9 15:27:06 2010 +# Linux kernel version: 2.6.34-rc5 +# Mon Apr 26 16:52:58 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -18,6 +18,8 @@ CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_LOCKBREAK=y # CONFIG_ARCH_SUSPEND_POSSIBLE is not set CONFIG_ARCH_HIBERNATION_POSSIBLE=y CONFIG_SYS_SUPPORTS_HUGETLBFS=y @@ -27,7 +29,6 @@ CONFIG_SYS_SUPPORTS_PCI=y CONFIG_SYS_SUPPORTS_TMU=y CONFIG_STACKTRACE_SUPPORT=y CONFIG_LOCKDEP_SUPPORT=y -CONFIG_HAVE_LATENCYTOP_SUPPORT=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set # CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_ARCH_NO_VIRT_TO_BUS=y @@ -35,6 +36,7 @@ CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_COHERENT=y # CONFIG_DMA_NONCOHERENT is not set +# CONFIG_NEED_DMA_MAP_STATE is not set CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -42,7 +44,6 @@ CONFIG_CONSTRUCTORS=y # General setup # CONFIG_EXPERIMENTAL=y -CONFIG_BROKEN_ON_SMP=y CONFIG_LOCK_KERNEL=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_LOCALVERSION="" @@ -51,25 +52,27 @@ CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y CONFIG_HAVE_KERNEL_LZO=y -CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_GZIP is not set # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set -# CONFIG_KERNEL_LZO is not set +CONFIG_KERNEL_LZO=y CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y CONFIG_POSIX_MQUEUE=y CONFIG_POSIX_MQUEUE_SYSCTL=y CONFIG_BSD_PROCESS_ACCT=y -# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_BSD_PROCESS_ACCT_V3=y # CONFIG_TASKSTATS is not set -# CONFIG_AUDIT is not set +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +CONFIG_AUDIT_TREE=y # # RCU Subsystem # -CONFIG_TREE_RCU=y -# CONFIG_TREE_PREEMPT_RCU is not set +# CONFIG_TREE_RCU is not set +CONFIG_TREE_PREEMPT_RCU=y # CONFIG_TINY_RCU is not set CONFIG_RCU_TRACE=y CONFIG_RCU_FANOUT=32 @@ -77,32 +80,36 @@ CONFIG_RCU_FANOUT=32 CONFIG_TREE_RCU_TRACE=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_GROUP_SCHED=y -CONFIG_FAIR_GROUP_SCHED=y -CONFIG_RT_GROUP_SCHED=y -CONFIG_USER_SCHED=y -# CONFIG_CGROUP_SCHED is not set +CONFIG_LOG_BUF_SHIFT=17 CONFIG_CGROUPS=y -# CONFIG_CGROUP_DEBUG is not set +CONFIG_CGROUP_DEBUG=y CONFIG_CGROUP_NS=y CONFIG_CGROUP_FREEZER=y CONFIG_CGROUP_DEVICE=y -# CONFIG_CPUSETS is not set +CONFIG_CPUSETS=y +# CONFIG_PROC_PID_CPUSET is not set CONFIG_CGROUP_CPUACCT=y CONFIG_RESOURCE_COUNTERS=y CONFIG_CGROUP_MEM_RES_CTLR=y -# CONFIG_CGROUP_MEM_RES_CTLR_SWAP is not set +CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y +CONFIG_CGROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_RT_GROUP_SCHED=y CONFIG_MM_OWNER=y # CONFIG_SYSFS_DEPRECATED_V2 is not set -# CONFIG_RELAY is not set +CONFIG_RELAY=y CONFIG_NAMESPACES=y CONFIG_UTS_NS=y CONFIG_IPC_NS=y CONFIG_USER_NS=y CONFIG_PID_NS=y CONFIG_NET_NS=y -# CONFIG_BLK_DEV_INITRD is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +CONFIG_RD_LZO=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_ANON_INODES=y @@ -131,7 +138,6 @@ CONFIG_PERF_USE_VMALLOC=y # Kernel Performance Events And Counters # CONFIG_PERF_EVENTS=y -CONFIG_EVENT_PROFILE=y # CONFIG_PERF_COUNTERS is not set # CONFIG_DEBUG_PERF_USE_VMALLOC is not set CONFIG_VM_EVENT_COUNTERS=y @@ -142,13 +148,15 @@ CONFIG_SLAB=y # CONFIG_SLOB is not set CONFIG_PROFILING=y CONFIG_TRACEPOINTS=y -# CONFIG_OPROFILE is not set +CONFIG_OPROFILE=m CONFIG_HAVE_OPROFILE=y -# CONFIG_KPROBES is not set +CONFIG_KPROBES=y +CONFIG_KRETPROBES=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y +CONFIG_USE_GENERIC_SMP_HELPERS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y CONFIG_HAVE_HW_BREAKPOINT=y @@ -157,7 +165,8 @@ CONFIG_HAVE_HW_BREAKPOINT=y # GCOV-based kernel profiling # # CONFIG_GCOV_KERNEL is not set -# CONFIG_SLOW_WORK is not set +CONFIG_SLOW_WORK=y +CONFIG_SLOW_WORK_DEBUG=y CONFIG_HAVE_GENERIC_DMA_COHERENT=y CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y @@ -168,9 +177,10 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_STOP_MACHINE=y CONFIG_BLOCK=y -# CONFIG_LBDAF is not set -# CONFIG_BLK_DEV_BSG is not set +CONFIG_LBDAF=y +CONFIG_BLK_DEV_BSG=y # CONFIG_BLK_DEV_INTEGRITY is not set CONFIG_BLK_CGROUP=y # CONFIG_DEBUG_BLK_CGROUP is not set @@ -215,7 +225,7 @@ CONFIG_DEFAULT_IOSCHED="cfq" # CONFIG_INLINE_WRITE_UNLOCK_BH is not set # CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set # CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set -# CONFIG_MUTEX_SPIN_ON_OWNER is not set +CONFIG_MUTEX_SPIN_ON_OWNER=y CONFIG_FREEZER=y # @@ -272,11 +282,10 @@ CONFIG_MEMORY_SIZE=0x20000000 # CONFIG_29BIT is not set CONFIG_32BIT=y CONFIG_PMB=y -# CONFIG_PMB_LEGACY is not set CONFIG_X2TLB=y CONFIG_VSYSCALL=y -# CONFIG_NUMA is not set -CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_NUMA=y +CONFIG_NODES_SHIFT=1 CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 @@ -286,21 +295,23 @@ CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y CONFIG_ARCH_MEMORY_PROBE=y CONFIG_IOREMAP_FIXED=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set # CONFIG_PAGE_SIZE_64KB is not set # CONFIG_HUGETLB_PAGE_SIZE_64K is not set # CONFIG_HUGETLB_PAGE_SIZE_256K is not set -CONFIG_HUGETLB_PAGE_SIZE_1MB=y +# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set # CONFIG_HUGETLB_PAGE_SIZE_4MB is not set -# CONFIG_HUGETLB_PAGE_SIZE_64MB is not set +CONFIG_HUGETLB_PAGE_SIZE_64MB=y # CONFIG_HUGETLB_PAGE_SIZE_512MB is not set CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_FLATMEM_MANUAL is not set # CONFIG_DISCONTIGMEM_MANUAL is not set CONFIG_SPARSEMEM_MANUAL=y CONFIG_SPARSEMEM=y +CONFIG_NEED_MULTIPLE_NODES=y CONFIG_HAVE_MEMORY_PRESENT=y CONFIG_SPARSEMEM_STATIC=y CONFIG_MEMORY_HOTPLUG=y @@ -313,6 +324,7 @@ CONFIG_ZONE_DMA_FLAG=0 CONFIG_NR_QUICK=1 CONFIG_KSM=y CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_SCHED_MC=y # # Cache configuration @@ -328,6 +340,7 @@ CONFIG_CPU_LITTLE_ENDIAN=y # CONFIG_CPU_BIG_ENDIAN is not set CONFIG_SH_FPU=y CONFIG_SH_STORE_QUEUES=y +CONFIG_SPECULATIVE_EXECUTION=y CONFIG_CPU_HAS_INTEVT=y CONFIG_CPU_HAS_SR_RB=y CONFIG_CPU_HAS_PTEAEX=y @@ -372,7 +385,10 @@ CONFIG_SH_CPU_FREQ=y # # DMA support # -# CONFIG_SH_DMA is not set +CONFIG_SH_DMA=y +# CONFIG_SH_DMA_API is not set +CONFIG_NR_ONCHIP_DMA_CHANNELS=6 +# CONFIG_NR_DMA_CHANNELS_BOOL is not set # # Companion Chips @@ -388,19 +404,21 @@ CONFIG_HEARTBEAT=y # Kernel features # # CONFIG_HZ_100 is not set -CONFIG_HZ_250=y +# CONFIG_HZ_250 is not set # CONFIG_HZ_300 is not set -# CONFIG_HZ_1000 is not set -CONFIG_HZ=250 +CONFIG_HZ_1000=y +CONFIG_HZ=1000 CONFIG_SCHED_HRTICK=y CONFIG_KEXEC=y # CONFIG_CRASH_DUMP is not set CONFIG_SECCOMP=y -# CONFIG_SMP is not set +CONFIG_SMP=y +CONFIG_NR_CPUS=2 # CONFIG_PREEMPT_NONE is not set # CONFIG_PREEMPT_VOLUNTARY is not set CONFIG_PREEMPT=y -CONFIG_GUSA=y +CONFIG_INTC_USERIMASK=y +CONFIG_INTC_BALANCING=y # # Boot options @@ -410,7 +428,7 @@ CONFIG_BOOT_LINK_OFFSET=0x00800000 CONFIG_ENTRY_OFFSET=0x00001000 CONFIG_CMDLINE_OVERWRITE=y # CONFIG_CMDLINE_EXTEND is not set -CONFIG_CMDLINE="console=ttySC1,115200 earlyprintk=sh-sci.1,115200 root=/dev/sda1 nmi_debug=state,debounce rootdelay=10" +CONFIG_CMDLINE="console=ttySC1,115200 earlyprintk=sh-sci.1,115200 root=/dev/sda1 nmi_debug=state,debounce rootdelay=5 pmb=iomap ignore_loglevel" # # Bus options @@ -424,8 +442,7 @@ CONFIG_PCIEAER_INJECT=y CONFIG_PCIEASPM=y CONFIG_PCIEASPM_DEBUG=y # CONFIG_ARCH_SUPPORTS_MSI is not set -# CONFIG_PCI_LEGACY is not set -CONFIG_PCI_DEBUG=y +# CONFIG_PCI_DEBUG is not set # CONFIG_PCI_STUB is not set # CONFIG_PCI_IOV is not set # CONFIG_PCCARD is not set @@ -435,7 +452,7 @@ CONFIG_PCI_DEBUG=y # Executable file formats # CONFIG_BINFMT_ELF=y -# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y # CONFIG_HAVE_AOUT is not set CONFIG_BINFMT_MISC=y @@ -444,9 +461,11 @@ CONFIG_BINFMT_MISC=y # CONFIG_PM=y CONFIG_PM_DEBUG=y +# CONFIG_PM_ADVANCED_DEBUG is not set CONFIG_PM_VERBOSE=y # CONFIG_HIBERNATION is not set CONFIG_PM_RUNTIME=y +CONFIG_PM_OPS=y CONFIG_CPU_IDLE=y CONFIG_CPU_IDLE_GOV_LADDER=y CONFIG_CPU_IDLE_GOV_MENU=y @@ -456,7 +475,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -520,19 +538,14 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NET_TCPPROBE is not set # CONFIG_NET_DROP_MONITOR is not set # CONFIG_HAMRADIO is not set # CONFIG_CAN is not set # CONFIG_IRDA is not set # CONFIG_BT is not set # CONFIG_AF_RXRPC is not set -CONFIG_WIRELESS=y -# CONFIG_CFG80211 is not set -# CONFIG_LIB80211 is not set - -# -# CFG80211 needs to be enabled for MAC80211 -# +# CONFIG_WIRELESS is not set # CONFIG_WIMAX is not set # CONFIG_RFKILL is not set # CONFIG_NET_9P is not set @@ -553,14 +566,118 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_DEBUG_DEVRES is not set # CONFIG_SYS_HYPERVISOR is not set # CONFIG_CONNECTOR is not set -# CONFIG_MTD is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +# CONFIG_MTD_CHAR is not set +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +CONFIG_FTL=y +CONFIG_NFTL=y +# CONFIG_NFTL_RW is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +CONFIG_MTD_OOPS=m + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +CONFIG_MTD_JEDECPROBE=y +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=m +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_STAA=m +CONFIG_MTD_CFI_UTIL=y +CONFIG_MTD_RAM=y +CONFIG_MTD_ROM=m +CONFIG_MTD_ABSENT=m + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_INTEL_VR_NOR is not set +CONFIG_MTD_PLATRAM=y + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_M25P80 is not set +# CONFIG_MTD_SST25L is not set +# CONFIG_MTD_SLRAM is not set +CONFIG_MTD_PHRAM=y +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_SMC is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_CAFE is not set +# CONFIG_MTD_NAND_NANDSIM is not set +CONFIG_MTD_NAND_PLATFORM=y +# CONFIG_MTD_ALAUDA is not set +CONFIG_MTD_NAND_SH_FLCTL=m +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set + +# +# UBI - Unsorted block images +# +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTD_UBI_BEB_RESERVE=1 +CONFIG_MTD_UBI_GLUEBI=m + +# +# UBI debugging options +# +# CONFIG_MTD_UBI_DEBUG is not set # CONFIG_PARPORT is not set CONFIG_BLK_DEV=y # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_UMEM is not set # CONFIG_BLK_DEV_COW_COMMON is not set -# CONFIG_BLK_DEV_LOOP is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_CRYPTOLOOP=y # # DRBD disabled because PROC_FS, INET or CONNECTOR not selected @@ -575,34 +692,63 @@ CONFIG_BLK_DEV_RAM_SIZE=4096 # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set # CONFIG_BLK_DEV_HD is not set -CONFIG_MISC_DEVICES=y -# CONFIG_AD525X_DPOT is not set -# CONFIG_PHANTOM is not set -# CONFIG_SGI_IOC4 is not set -# CONFIG_TIFM_CORE is not set -# CONFIG_ICS932S401 is not set -# CONFIG_ENCLOSURE_SERVICES is not set -# CONFIG_HP_ILO is not set -# CONFIG_ISL29003 is not set -# CONFIG_DS1682 is not set -# CONFIG_TI_DAC7512 is not set -# CONFIG_C2PORT is not set - -# -# EEPROM support -# -# CONFIG_EEPROM_AT24 is not set -# CONFIG_EEPROM_AT25 is not set -# CONFIG_EEPROM_LEGACY is not set -# CONFIG_EEPROM_MAX6875 is not set -# CONFIG_EEPROM_93CX6 is not set -# CONFIG_CB710_CORE is not set +# CONFIG_MISC_DEVICES is not set CONFIG_HAVE_IDE=y -# CONFIG_IDE is not set +CONFIG_IDE=y + +# +# Please see Documentation/ide/ide.txt for help/info on IDE drives +# +CONFIG_IDE_ATAPI=y +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_IDE_GD=y +CONFIG_IDE_GD_ATA=y +# CONFIG_IDE_GD_ATAPI is not set +CONFIG_BLK_DEV_IDECD=y +CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_PROC_FS=y + +# +# IDE chipset support/bugfixes +# +CONFIG_BLK_DEV_PLATFORM=y + +# +# PCI IDE chipsets support +# +# CONFIG_BLK_DEV_GENERIC is not set +# CONFIG_BLK_DEV_OPTI621 is not set +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_BLK_DEV_CMD64X is not set +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_JMICRON is not set +# CONFIG_BLK_DEV_SC1200 is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_IT8172 is not set +# CONFIG_BLK_DEV_IT8213 is not set +# CONFIG_BLK_DEV_IT821X is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_BLK_DEV_TC86C001 is not set +# CONFIG_BLK_DEV_IDEDMA is not set # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y @@ -616,11 +762,12 @@ CONFIG_SCSI_PROC_FS=y CONFIG_BLK_DEV_SD=y # CONFIG_CHR_DEV_ST is not set # CONFIG_CHR_DEV_OSST is not set -# CONFIG_BLK_DEV_SR is not set +CONFIG_BLK_DEV_SR=y +# CONFIG_BLK_DEV_SR_VENDOR is not set # CONFIG_CHR_DEV_SG is not set # CONFIG_CHR_DEV_SCH is not set -# CONFIG_SCSI_MULTI_LUN is not set -# CONFIG_SCSI_CONSTANTS is not set +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y # CONFIG_SCSI_LOGGING is not set # CONFIG_SCSI_SCAN_ASYNC is not set CONFIG_SCSI_WAIT_SCAN=m @@ -631,52 +778,10 @@ CONFIG_SCSI_WAIT_SCAN=m # CONFIG_SCSI_SPI_ATTRS is not set # CONFIG_SCSI_FC_ATTRS is not set # CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set # CONFIG_SCSI_SAS_LIBSAS is not set # CONFIG_SCSI_SRP_ATTRS is not set -CONFIG_SCSI_LOWLEVEL=y -# CONFIG_ISCSI_TCP is not set -# CONFIG_SCSI_BNX2_ISCSI is not set -# CONFIG_BE2ISCSI is not set -# CONFIG_BLK_DEV_3W_XXXX_RAID is not set -# CONFIG_SCSI_HPSA is not set -# CONFIG_SCSI_3W_9XXX is not set -# CONFIG_SCSI_3W_SAS is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AACRAID is not set -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_AIC79XX is not set -# CONFIG_SCSI_AIC94XX is not set -# CONFIG_SCSI_MVSAS is not set -# CONFIG_SCSI_ARCMSR is not set -# CONFIG_MEGARAID_NEWGEN is not set -# CONFIG_MEGARAID_LEGACY is not set -# CONFIG_MEGARAID_SAS is not set -# CONFIG_SCSI_MPT2SAS is not set -# CONFIG_SCSI_HPTIOP is not set -# CONFIG_LIBFC is not set -# CONFIG_LIBFCOE is not set -# CONFIG_FCOE is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -# CONFIG_SCSI_IPS is not set -# CONFIG_SCSI_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_STEX is not set -# CONFIG_SCSI_SYM53C8XX_2 is not set -# CONFIG_SCSI_IPR is not set -# CONFIG_SCSI_QLOGIC_1280 is not set -# CONFIG_SCSI_QLA_FC is not set -# CONFIG_SCSI_QLA_ISCSI is not set -# CONFIG_SCSI_LPFC is not set -# CONFIG_SCSI_DC395x is not set -# CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_NSP32 is not set -# CONFIG_SCSI_DEBUG is not set -# CONFIG_SCSI_PMCRAID is not set -# CONFIG_SCSI_PM8001 is not set -# CONFIG_SCSI_SRP is not set -# CONFIG_SCSI_BFA_FC is not set +# CONFIG_SCSI_LOWLEVEL is not set # CONFIG_SCSI_DH is not set # CONFIG_SCSI_OSD_INITIATOR is not set CONFIG_ATA=y @@ -719,6 +824,7 @@ CONFIG_ATA_SFF=y # CONFIG_PATA_IT821X is not set # CONFIG_PATA_IT8213 is not set # CONFIG_PATA_JMICRON is not set +# CONFIG_PATA_LEGACY is not set # CONFIG_PATA_TRIFLEX is not set # CONFIG_PATA_MARVELL is not set # CONFIG_PATA_MPIIX is not set @@ -743,7 +849,17 @@ CONFIG_ATA_SFF=y # CONFIG_PATA_WINBOND is not set CONFIG_PATA_PLATFORM=y # CONFIG_PATA_SCH is not set -# CONFIG_MD is not set +CONFIG_MD=y +# CONFIG_BLK_DEV_MD is not set +CONFIG_BLK_DEV_DM=y +CONFIG_DM_DEBUG=y +# CONFIG_DM_CRYPT is not set +# CONFIG_DM_SNAPSHOT is not set +# CONFIG_DM_MIRROR is not set +# CONFIG_DM_ZERO is not set +# CONFIG_DM_MULTIPATH is not set +# CONFIG_DM_DELAY is not set +CONFIG_DM_UEVENT=y # CONFIG_FUSION is not set # @@ -820,11 +936,7 @@ CONFIG_SMSC911X=y # CONFIG_NETDEV_1000 is not set # CONFIG_NETDEV_10000 is not set # CONFIG_TR is not set -CONFIG_WLAN=y -# CONFIG_ATMEL is not set -# CONFIG_PRISM54 is not set -# CONFIG_USB_ZD1201 is not set -# CONFIG_HOSTAP is not set +# CONFIG_WLAN is not set # # Enable WiMAX (Networking options) to see the WiMAX drivers @@ -838,6 +950,7 @@ CONFIG_WLAN=y # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set # CONFIG_USB_USBNET is not set +# CONFIG_USB_IPHETH is not set # CONFIG_WAN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set @@ -923,7 +1036,7 @@ CONFIG_VT=y CONFIG_CONSOLE_TRANSLATIONS=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y -# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_VT_HW_CONSOLE_BINDING=y CONFIG_DEVKMEM=y # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_NOZOMI is not set @@ -940,9 +1053,11 @@ CONFIG_DEVKMEM=y CONFIG_SERIAL_SH_SCI=y CONFIG_SERIAL_SH_SCI_NR_UARTS=6 CONFIG_SERIAL_SH_SCI_CONSOLE=y +CONFIG_SERIAL_SH_SCI_DMA=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set # CONFIG_LEGACY_PTYS is not set @@ -986,8 +1101,10 @@ CONFIG_I2C_HELPER_AUTO=y # # CONFIG_I2C_DESIGNWARE is not set # CONFIG_I2C_OCORES is not set +CONFIG_I2C_SDK7786=y # CONFIG_I2C_SH_MOBILE is not set # CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set # # External I2C/SMBus adapter drivers @@ -1001,15 +1118,9 @@ CONFIG_I2C_HELPER_AUTO=y # # CONFIG_I2C_PCA_PLATFORM is not set # CONFIG_I2C_STUB is not set - -# -# Miscellaneous I2C Chip support -# -# CONFIG_SENSORS_TSL2550 is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set CONFIG_SPI=y # CONFIG_SPI_DEBUG is not set CONFIG_SPI_MASTER=y @@ -1045,7 +1156,8 @@ CONFIG_WATCHDOG=y # # CONFIG_SOFT_WATCHDOG is not set # CONFIG_ALIM7101_WDT is not set -# CONFIG_SH_WDT is not set +CONFIG_SH_WDT=y +# CONFIG_SH_WDT_MMAP is not set # # PCI-based Watchdog Cards @@ -1068,6 +1180,7 @@ CONFIG_SSB_POSSIBLE=y # Multifunction device drivers # # CONFIG_MFD_CORE is not set +# CONFIG_MFD_88PM860X is not set # CONFIG_MFD_SM501 is not set # CONFIG_MFD_SH_MOBILE_SDHI is not set # CONFIG_HTC_PASIC3 is not set @@ -1075,15 +1188,17 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_TMIO is not set # CONFIG_PMIC_DA903X is not set # CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X is not set # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set # CONFIG_MFD_PCF50633 is not set # CONFIG_MFD_MC13783 is not set # CONFIG_AB3100_CORE is not set # CONFIG_EZX_PCAP is not set -# CONFIG_MFD_88PM8607 is not set # CONFIG_AB4500_CORE is not set +# CONFIG_LPC_SCH is not set # CONFIG_REGULATOR is not set # CONFIG_MEDIA_SUPPORT is not set @@ -1091,6 +1206,7 @@ CONFIG_SSB_POSSIBLE=y # Graphics support # CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 # CONFIG_DRM is not set # CONFIG_VGASTATE is not set CONFIG_VIDEO_OUTPUT_CONTROL=m @@ -1121,6 +1237,7 @@ CONFIG_USB_HID=y # # Special HID drivers # +# CONFIG_HID_3M_PCT is not set # CONFIG_HID_A4TECH is not set # CONFIG_HID_APPLE is not set # CONFIG_HID_BELKIN is not set @@ -1135,12 +1252,16 @@ CONFIG_USB_HID=y # CONFIG_HID_KENSINGTON is not set # CONFIG_HID_LOGITECH is not set # CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MOSART is not set # CONFIG_HID_MONTEREY is not set # CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set # CONFIG_HID_PANTHERLORD is not set # CONFIG_HID_PETALYNX is not set +# CONFIG_HID_QUANTA is not set # CONFIG_HID_SAMSUNG is not set # CONFIG_HID_SONY is not set +# CONFIG_HID_STANTUM is not set # CONFIG_HID_SUNPLUS is not set # CONFIG_HID_GREENASIA is not set # CONFIG_HID_SMARTJOYPLUS is not set @@ -1241,7 +1362,6 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set -# CONFIG_USB_BERRY_CHARGE is not set # CONFIG_USB_LED is not set # CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set @@ -1253,7 +1373,6 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set # CONFIG_USB_ISIGHTFW is not set -# CONFIG_USB_VST is not set CONFIG_USB_GADGET=y # CONFIG_USB_GADGET_DEBUG is not set # CONFIG_USB_GADGET_DEBUG_FILES is not set @@ -1291,6 +1410,7 @@ CONFIG_USB_GADGET_DUALSPEED=y # CONFIG_USB_MIDI_GADGET is not set # CONFIG_USB_G_PRINTER is not set # CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_G_NOKIA is not set # CONFIG_USB_G_MULTI is not set # @@ -1370,43 +1490,102 @@ CONFIG_RTC_DRV_MAX6900=y # CONFIG_RTC_DRV_SH=y # CONFIG_RTC_DRV_GENERIC is not set -# CONFIG_DMADEVICES is not set +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +CONFIG_SH_DMAE=y +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +# CONFIG_NET_DMA is not set +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_DMATEST is not set # CONFIG_AUXDISPLAY is not set CONFIG_UIO=m # CONFIG_UIO_CIF is not set -# CONFIG_UIO_PDRV is not set -# CONFIG_UIO_PDRV_GENIRQ is not set -# CONFIG_UIO_SMX is not set +CONFIG_UIO_PDRV=m +CONFIG_UIO_PDRV_GENIRQ=m # CONFIG_UIO_AEC is not set # CONFIG_UIO_SERCOS3 is not set -# CONFIG_UIO_PCI_GENERIC is not set +CONFIG_UIO_PCI_GENERIC=m +# CONFIG_UIO_NETX is not set # # TI VLYNQ # -# CONFIG_STAGING is not set +CONFIG_STAGING=y +# CONFIG_STAGING_EXCLUDE_BUILD is not set +# CONFIG_USB_IP_COMMON is not set +# CONFIG_ECHO is not set +# CONFIG_POCH is not set +# CONFIG_COMEDI is not set +# CONFIG_ASUS_OLED is not set +# CONFIG_TRANZPORT is not set + +# +# Qualcomm MSM Camera And Video +# + +# +# Camera Sensor Selection +# +# CONFIG_INPUT_GPIO is not set +# CONFIG_POHMELFS is not set +# CONFIG_IDE_PHISON is not set +# CONFIG_VME_BUS is not set + +# +# RAR Register Driver +# +# CONFIG_RAR_REGISTER is not set +# CONFIG_IIO is not set +CONFIG_RAMZSWAP=m +CONFIG_RAMZSWAP_STATS=y +# CONFIG_BATMAN_ADV is not set +# CONFIG_STRIP is not set +# CONFIG_DT3155 is not set +# CONFIG_CRYSTALHD is not set # # File systems # CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set +CONFIG_EXT2_FS_XATTR=y +# CONFIG_EXT2_FS_POSIX_ACL is not set +# CONFIG_EXT2_FS_SECURITY is not set # CONFIG_EXT2_FS_XIP is not set CONFIG_EXT3_FS=y # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set CONFIG_EXT3_FS_XATTR=y # CONFIG_EXT3_FS_POSIX_ACL is not set # CONFIG_EXT3_FS_SECURITY is not set -# CONFIG_EXT4_FS is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_XATTR=y +# CONFIG_EXT4_FS_POSIX_ACL is not set +# CONFIG_EXT4_FS_SECURITY is not set +# CONFIG_EXT4_DEBUG is not set CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set CONFIG_FS_MBCACHE=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set -# CONFIG_FS_POSIX_ACL is not set -# CONFIG_XFS_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=y +# CONFIG_XFS_QUOTA is not set +# CONFIG_XFS_POSIX_ACL is not set +# CONFIG_XFS_RT is not set +# CONFIG_XFS_DEBUG is not set +# CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set -# CONFIG_BTRFS_FS is not set +CONFIG_BTRFS_FS=y +# CONFIG_BTRFS_FS_POSIX_ACL is not set # CONFIG_NILFS2_FS is not set CONFIG_FILE_LOCKING=y CONFIG_FSNOTIFY=y @@ -1415,19 +1594,30 @@ CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set # CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set -# CONFIG_FUSE_FS is not set +CONFIG_AUTOFS4_FS=m +CONFIG_FUSE_FS=y +CONFIG_CUSE=m # # Caches # -# CONFIG_FSCACHE is not set +CONFIG_FSCACHE=m +# CONFIG_FSCACHE_STATS is not set +# CONFIG_FSCACHE_HISTOGRAM is not set +# CONFIG_FSCACHE_DEBUG is not set +# CONFIG_FSCACHE_OBJECT_LIST is not set +CONFIG_CACHEFILES=m +# CONFIG_CACHEFILES_DEBUG is not set +# CONFIG_CACHEFILES_HISTOGRAM is not set # # CD-ROM/DVD Filesystems # -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y # # DOS/FAT/NT Filesystems @@ -1448,7 +1638,7 @@ CONFIG_TMPFS=y # CONFIG_TMPFS_POSIX_ACL is not set CONFIG_HUGETLBFS=y CONFIG_HUGETLB_PAGE=y -# CONFIG_CONFIGFS_FS is not set +CONFIG_CONFIGFS_FS=y CONFIG_MISC_FILESYSTEMS=y # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set @@ -1457,30 +1647,60 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_SQUASHFS is not set +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +CONFIG_JFFS2_FS_XATTR=y +CONFIG_JFFS2_FS_POSIX_ACL=y +CONFIG_JFFS2_FS_SECURITY=y +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_UBIFS_FS=m +# CONFIG_UBIFS_FS_XATTR is not set +# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_ZLIB=y +# CONFIG_UBIFS_FS_DEBUG is not set +CONFIG_LOGFS=m +CONFIG_CRAMFS=m +CONFIG_SQUASHFS=m +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 # CONFIG_VXFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_OMFS_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set -# CONFIG_ROMFS_FS is not set +CONFIG_ROMFS_FS=m +CONFIG_ROMFS_BACKED_BY_BLOCK=y +# CONFIG_ROMFS_BACKED_BY_MTD is not set +# CONFIG_ROMFS_BACKED_BY_BOTH is not set +CONFIG_ROMFS_ON_BLOCK=y # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V3=y # CONFIG_NFS_V3_ACL is not set -# CONFIG_NFS_V4 is not set +CONFIG_NFS_V4=y +# CONFIG_NFS_V4_1 is not set CONFIG_ROOT_NFS=y # CONFIG_NFSD is not set CONFIG_LOCKD=y CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y -# CONFIG_RPCSEC_GSS_KRB5 is not set +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1493,7 +1713,7 @@ CONFIG_SUNRPC=y CONFIG_MSDOS_PARTITION=y CONFIG_NLS=y CONFIG_NLS_DEFAULT="iso8859-1" -# CONFIG_NLS_CODEPAGE_437 is not set +CONFIG_NLS_CODEPAGE_437=y # CONFIG_NLS_CODEPAGE_737 is not set # CONFIG_NLS_CODEPAGE_775 is not set # CONFIG_NLS_CODEPAGE_850 is not set @@ -1508,16 +1728,16 @@ CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_NLS_CODEPAGE_865 is not set # CONFIG_NLS_CODEPAGE_866 is not set # CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_936 is not set -# CONFIG_NLS_CODEPAGE_950 is not set -# CONFIG_NLS_CODEPAGE_932 is not set -# CONFIG_NLS_CODEPAGE_949 is not set +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=y +CONFIG_NLS_CODEPAGE_949=m # CONFIG_NLS_CODEPAGE_874 is not set # CONFIG_NLS_ISO8859_8 is not set # CONFIG_NLS_CODEPAGE_1250 is not set # CONFIG_NLS_CODEPAGE_1251 is not set -# CONFIG_NLS_ASCII is not set -# CONFIG_NLS_ISO8859_1 is not set +CONFIG_NLS_ASCII=m +CONFIG_NLS_ISO8859_1=y # CONFIG_NLS_ISO8859_2 is not set # CONFIG_NLS_ISO8859_3 is not set # CONFIG_NLS_ISO8859_4 is not set @@ -1527,10 +1747,10 @@ CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_NLS_ISO8859_9 is not set # CONFIG_NLS_ISO8859_13 is not set # CONFIG_NLS_ISO8859_14 is not set -# CONFIG_NLS_ISO8859_15 is not set +CONFIG_NLS_ISO8859_15=m # CONFIG_NLS_KOI8_R is not set # CONFIG_NLS_KOI8_U is not set -# CONFIG_NLS_UTF8 is not set +CONFIG_NLS_UTF8=m # CONFIG_DLM is not set # @@ -1538,7 +1758,7 @@ CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_TRACE_IRQFLAGS_SUPPORT=y CONFIG_PRINTK_TIME=y -CONFIG_ENABLE_WARN_DEPRECATED=y +# CONFIG_ENABLE_WARN_DEPRECATED is not set # CONFIG_ENABLE_MUST_CHECK is not set CONFIG_FRAME_WARN=1024 CONFIG_MAGIC_SYSRQ=y @@ -1547,7 +1767,7 @@ CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_FS=y # CONFIG_HEADERS_CHECK is not set CONFIG_DEBUG_KERNEL=y -CONFIG_DEBUG_SHIRQ=y +# CONFIG_DEBUG_SHIRQ is not set CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 @@ -1573,24 +1793,27 @@ CONFIG_STACKTRACE=y # CONFIG_DEBUG_KOBJECT is not set CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_INFO is not set -CONFIG_DEBUG_VM=y +# CONFIG_DEBUG_VM is not set # CONFIG_DEBUG_WRITECOUNT is not set -# CONFIG_DEBUG_MEMORY_INIT is not set +CONFIG_DEBUG_MEMORY_INIT=y # CONFIG_DEBUG_LIST is not set # CONFIG_DEBUG_SG is not set # CONFIG_DEBUG_NOTIFIERS is not set # CONFIG_DEBUG_CREDENTIALS is not set CONFIG_FRAME_POINTER=y # CONFIG_RCU_TORTURE_TEST is not set -# CONFIG_RCU_CPU_STALL_DETECTOR is not set +CONFIG_RCU_CPU_STALL_DETECTOR=y +# CONFIG_RCU_CPU_STALL_VERBOSE is not set +# CONFIG_KPROBES_SANITY_TEST is not set # CONFIG_BACKTRACE_SELF_TEST is not set # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_LKDTM is not set # CONFIG_FAULT_INJECTION is not set -# CONFIG_LATENCYTOP is not set -# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y # CONFIG_PAGE_POISONING is not set CONFIG_NOP_TRACER=y +CONFIG_HAVE_FTRACE_NMI_ENTER=y CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y @@ -1598,16 +1821,19 @@ CONFIG_HAVE_DYNAMIC_FTRACE=y CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y CONFIG_HAVE_SYSCALL_TRACEPOINTS=y CONFIG_RING_BUFFER=y +CONFIG_FTRACE_NMI_ENTER=y CONFIG_EVENT_TRACING=y CONFIG_CONTEXT_SWITCH_TRACER=y +CONFIG_RING_BUFFER_ALLOW_SWAP=y CONFIG_TRACING=y +CONFIG_GENERIC_TRACER=y CONFIG_TRACING_SUPPORT=y CONFIG_FTRACE=y -# CONFIG_FUNCTION_TRACER is not set +CONFIG_FUNCTION_TRACER=y +# CONFIG_FUNCTION_GRAPH_TRACER is not set # CONFIG_IRQSOFF_TRACER is not set # CONFIG_PREEMPT_TRACER is not set # CONFIG_SCHED_TRACER is not set -# CONFIG_ENABLE_DEFAULT_TRACERS is not set # CONFIG_FTRACE_SYSCALLS is not set # CONFIG_BOOT_TRACER is not set CONFIG_BRANCH_PROFILE_NONE=y @@ -1619,9 +1845,13 @@ CONFIG_KSYM_TRACER=y # CONFIG_KMEMTRACE is not set # CONFIG_WORKQUEUE_TRACER is not set # CONFIG_BLK_DEV_IO_TRACE is not set +CONFIG_DYNAMIC_FTRACE=y +# CONFIG_FUNCTION_PROFILER is not set +CONFIG_FTRACE_MCOUNT_RECORD=y +# CONFIG_FTRACE_STARTUP_TEST is not set # CONFIG_RING_BUFFER_BENCHMARK is not set # CONFIG_DYNAMIC_DEBUG is not set -# CONFIG_DMA_API_DEBUG is not set +CONFIG_DMA_API_DEBUG=y # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set @@ -1632,6 +1862,7 @@ CONFIG_DEBUG_STACK_USAGE=y CONFIG_DUMP_CODE=y CONFIG_DWARF_UNWINDER=y # CONFIG_SH_NO_BSS_INIT is not set +CONFIG_MCOUNT=y # # Security options @@ -1649,10 +1880,21 @@ CONFIG_CRYPTO=y # # Crypto core or helper # -# CONFIG_CRYPTO_MANAGER is not set -# CONFIG_CRYPTO_MANAGER2 is not set +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_PCOMP=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y # CONFIG_CRYPTO_GF128MUL is not set # CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_PCRYPT is not set +CONFIG_CRYPTO_WORKQUEUE=y # CONFIG_CRYPTO_CRYPTD is not set # CONFIG_CRYPTO_AUTHENC is not set # CONFIG_CRYPTO_TEST is not set @@ -1667,7 +1909,7 @@ CONFIG_CRYPTO=y # # Block modes # -# CONFIG_CRYPTO_CBC is not set +CONFIG_CRYPTO_CBC=y # CONFIG_CRYPTO_CTR is not set # CONFIG_CRYPTO_CTS is not set # CONFIG_CRYPTO_ECB is not set @@ -1685,10 +1927,10 @@ CONFIG_CRYPTO=y # # Digest # -# CONFIG_CRYPTO_CRC32C is not set +CONFIG_CRYPTO_CRC32C=y # CONFIG_CRYPTO_GHASH is not set # CONFIG_CRYPTO_MD4 is not set -# CONFIG_CRYPTO_MD5 is not set +CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_MICHAEL_MIC is not set # CONFIG_CRYPTO_RMD128 is not set # CONFIG_CRYPTO_RMD160 is not set @@ -1710,7 +1952,7 @@ CONFIG_CRYPTO=y # CONFIG_CRYPTO_CAMELLIA is not set # CONFIG_CRYPTO_CAST5 is not set # CONFIG_CRYPTO_CAST6 is not set -# CONFIG_CRYPTO_DES is not set +CONFIG_CRYPTO_DES=y # CONFIG_CRYPTO_FCRYPT is not set # CONFIG_CRYPTO_KHAZAD is not set # CONFIG_CRYPTO_SALSA20 is not set @@ -1722,9 +1964,9 @@ CONFIG_CRYPTO=y # # Compression # -# CONFIG_CRYPTO_DEFLATE is not set +CONFIG_CRYPTO_DEFLATE=m # CONFIG_CRYPTO_ZLIB is not set -# CONFIG_CRYPTO_LZO is not set +CONFIG_CRYPTO_LZO=m # # Random Number Generation @@ -1740,12 +1982,22 @@ CONFIG_BINARY_PRINTF=y CONFIG_BITREVERSE=y CONFIG_GENERIC_FIND_LAST_BIT=y # CONFIG_CRC_CCITT is not set -# CONFIG_CRC16 is not set +CONFIG_CRC16=y # CONFIG_CRC_T10DIF is not set -# CONFIG_CRC_ITU_T is not set +CONFIG_CRC_ITU_T=m CONFIG_CRC32=y # CONFIG_CRC7 is not set -# CONFIG_LIBCRC32C is not set +CONFIG_LIBCRC32C=y +CONFIG_AUDIT_GENERIC=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_LZO_COMPRESS=m +CONFIG_LZO_DECOMPRESS=y +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_DECOMPRESS_LZO=y +CONFIG_BTREE=y CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT=y CONFIG_HAS_DMA=y -- cgit v0.10.2 From 9e8c5be8b76b188ec5bc95b378cf67aaeba1f695 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 26 Apr 2010 18:20:29 +0900 Subject: sh: Flag present CPUs hotpluggable in topology registration. When registering CPUs in the topology initialization ensure that all of the present CPUs are flagged as hotpluggable. Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/topology.c b/arch/sh/kernel/topology.c index 9b0b633..948fdb6 100644 --- a/arch/sh/kernel/topology.c +++ b/arch/sh/kernel/topology.c @@ -52,7 +52,11 @@ static int __init topology_init(void) #endif for_each_present_cpu(i) { - ret = register_cpu(&per_cpu(cpu_devices, i), i); + struct cpu *c = &per_cpu(cpu_devices, i); + + c->hotpluggable = 1; + + ret = register_cpu(c, i); if (unlikely(ret)) printk(KERN_WARNING "%s: register_cpu %d failed (%d)\n", __func__, i, ret); -- cgit v0.10.2 From c9f4a3f53b5d61f86eae3512abdf948878ca3498 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 26 Apr 2010 18:35:44 +0900 Subject: sh: arch/sh/kernel/setup.c needs asm/smp.h. With the platform ops migration, the definitions still need to be included in the CONFIG_SMP=n case, so make the asm/smp.h include explicit. Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 2915538..14735d5 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -39,6 +39,7 @@ #include #include #include +#include #include /* -- cgit v0.10.2 From f0ccf2770f523bd4fc436886a38e499f9ec95c0e Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 26 Apr 2010 18:39:50 +0900 Subject: sh: convert online CPU map twiddling to cpumask. This converts from cpu_set() for the online map to set_cpu_online(). The two online map modifiers were the last remaining manual map manipulation bits, with this in place everything now goes through cpumask. Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/idle.c b/arch/sh/kernel/idle.c index 273f890..2040053 100644 --- a/arch/sh/kernel/idle.c +++ b/arch/sh/kernel/idle.c @@ -133,7 +133,7 @@ static void do_nothing(void *unused) void stop_this_cpu(void *unused) { local_irq_disable(); - cpu_clear(smp_processor_id(), cpu_online_map); + set_cpu_online(smp_processor_id(), false); for (;;) cpu_sleep(); diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c index 2f348fd..cc87830 100644 --- a/arch/sh/kernel/smp.c +++ b/arch/sh/kernel/smp.c @@ -102,7 +102,7 @@ asmlinkage void __cpuinit start_secondary(void) smp_store_cpu_info(cpu); - cpu_set(cpu, cpu_online_map); + set_cpu_online(cpu, true); cpu_idle(); } -- cgit v0.10.2 From 7acb59eb4b5eee113eb74eeafd1e6536171eeced Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 26 Apr 2010 18:44:04 +0900 Subject: sh: Make sure all SH-X3 cores are populated in the present CPU map. This iterates over the maximum number of CPUs we plan to support and makes sure they're all set in the present CPU map. Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/smp-shx3.c b/arch/sh/kernel/cpu/sh4a/smp-shx3.c index 5c5d50c..dd245e6 100644 --- a/arch/sh/kernel/cpu/sh4a/smp-shx3.c +++ b/arch/sh/kernel/cpu/sh4a/smp-shx3.c @@ -74,6 +74,9 @@ static void shx3_prepare_cpus(unsigned int max_cpus) for (i = 0; i < SMP_MSG_NR; i++) request_irq(104 + i, ipi_interrupt_handler, IRQF_DISABLED | IRQF_PERCPU, "IPI", (void *)(long)i); + + for (i = 0; i < max_cpus; i++) + set_cpu_present(i, true); } static void shx3_start_cpu(unsigned int cpu, unsigned long entry_point) -- cgit v0.10.2 From 9715b8c7d55912fb6f5dd9b1c084d8eefcd0d848 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 26 Apr 2010 18:49:58 +0900 Subject: sh: provide percpu CPU states for hotplug notifiers. This provides percpu CPU states in preparation for CPU hotplug and the associated notifier chains. Signed-off-by: Paul Mundt diff --git a/arch/sh/include/asm/smp.h b/arch/sh/include/asm/smp.h index 7f13d46..da5135b 100644 --- a/arch/sh/include/asm/smp.h +++ b/arch/sh/include/asm/smp.h @@ -10,6 +10,7 @@ #include #include #include +#include #define raw_smp_processor_id() (current_thread_info()->cpu) @@ -30,6 +31,8 @@ enum { SMP_MSG_NR, /* must be last */ }; +DECLARE_PER_CPU(int, cpu_state); + void smp_message_recv(unsigned int msg); void smp_timer_broadcast(const struct cpumask *mask); diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c index cc87830..4d27597 100644 --- a/arch/sh/kernel/smp.c +++ b/arch/sh/kernel/smp.c @@ -33,6 +33,9 @@ int __cpu_logical_map[NR_CPUS]; /* Map logical to physical */ struct plat_smp_ops *mp_ops = NULL; +/* State of each CPU */ +DEFINE_PER_CPU(int, cpu_state) = { 0 }; + void __cpuinit register_smp_ops(struct plat_smp_ops *ops) { if (mp_ops) @@ -72,11 +75,13 @@ void __devinit smp_prepare_boot_cpu(void) set_cpu_online(cpu, true); set_cpu_possible(cpu, true); + + per_cpu(cpu_state, cpu) = CPU_ONLINE; } asmlinkage void __cpuinit start_secondary(void) { - unsigned int cpu; + unsigned int cpu = smp_processor_id(); struct mm_struct *mm = &init_mm; enable_mmu(); @@ -90,12 +95,10 @@ asmlinkage void __cpuinit start_secondary(void) preempt_disable(); - notify_cpu_starting(smp_processor_id()); + notify_cpu_starting(cpu); local_irq_enable(); - cpu = smp_processor_id(); - /* Enable local timers */ local_timer_setup(cpu); calibrate_delay(); @@ -103,6 +106,7 @@ asmlinkage void __cpuinit start_secondary(void) smp_store_cpu_info(cpu); set_cpu_online(cpu, true); + per_cpu(cpu_state, cpu) = CPU_ONLINE; cpu_idle(); } @@ -127,6 +131,8 @@ int __cpuinit __cpu_up(unsigned int cpu) return PTR_ERR(tsk); } + per_cpu(cpu_state, cpu) = CPU_UP_PREPARE; + /* Fill in data in head.S for secondary cpus */ stack_start.sp = tsk->thread.sp; stack_start.thread_info = tsk->stack; -- cgit v0.10.2 From 1cfa1e8f2c824b131612c9a70b48433998237331 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 26 Apr 2010 18:55:01 +0900 Subject: sh: flag smp_store_cpu_info() __cpuinit. smp_store_cpu_info() is presently flagged as __init, but is called by start_secondary() which is __cpuinit, fix it up. Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c index 4d27597..3711a76 100644 --- a/arch/sh/kernel/smp.c +++ b/arch/sh/kernel/smp.c @@ -44,7 +44,7 @@ void __cpuinit register_smp_ops(struct plat_smp_ops *ops) mp_ops = ops; } -static inline void __init smp_store_cpu_info(unsigned int cpu) +static inline void __cpuinit smp_store_cpu_info(unsigned int cpu) { struct sh_cpuinfo *c = cpu_data + cpu; @@ -66,7 +66,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) #endif } -void __devinit smp_prepare_boot_cpu(void) +void __init smp_prepare_boot_cpu(void) { unsigned int cpu = smp_processor_id(); -- cgit v0.10.2 From 8db2bc4559639680a94d4492ae4b7ce71298a74f Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 26 Apr 2010 18:59:47 +0900 Subject: sh: cache secondary CPUs idle loop. This provides a cache of the secondary CPUs idle loop for the cases where hotplug simply enters a low power state instead of resetting or powering off the core. Signed-off-by: Paul Mundt diff --git a/arch/sh/include/asm/processor.h b/arch/sh/include/asm/processor.h index 26b3f02..0a58cb2 100644 --- a/arch/sh/include/asm/processor.h +++ b/arch/sh/include/asm/processor.h @@ -85,6 +85,10 @@ struct sh_cpuinfo { struct tlb_info itlb; struct tlb_info dtlb; +#ifdef CONFIG_SMP + struct task_struct *idle; +#endif + unsigned long flags; } __attribute__ ((aligned(L1_CACHE_BYTES))); diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c index 3711a76..21e7f8a 100644 --- a/arch/sh/kernel/smp.c +++ b/arch/sh/kernel/smp.c @@ -125,10 +125,15 @@ int __cpuinit __cpu_up(unsigned int cpu) struct task_struct *tsk; unsigned long timeout; - tsk = fork_idle(cpu); - if (IS_ERR(tsk)) { - printk(KERN_ERR "Failed forking idle task for cpu %d\n", cpu); - return PTR_ERR(tsk); + tsk = cpu_data[cpu].idle; + if (!tsk) { + tsk = fork_idle(cpu); + if (IS_ERR(tsk)) { + pr_err("Failed forking idle task for cpu %d\n", cpu); + return PTR_ERR(tsk); + } + + cpu_data[cpu].idle = tsk; } per_cpu(cpu_state, cpu) = CPU_UP_PREPARE; -- cgit v0.10.2 From 763142d1efb56effe614d71185781796c4b83c78 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 26 Apr 2010 19:08:55 +0900 Subject: sh: CPU hotplug support. This adds preliminary support for CPU hotplug for SH SMP systems. Signed-off-by: Paul Mundt diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index ba86bfb..d73bd4d 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -706,6 +706,13 @@ config NR_CPUS This is purely to save memory - each supported CPU adds approximately eight kilobytes to the kernel image. +config HOTPLUG_CPU + bool "Support for hot-pluggable CPUs (EXPERIMENTAL)" + depends on SMP && HOTPLUG && EXPERIMENTAL + help + Say Y here to experiment with turning CPUs off and on. CPUs + can be controlled through /sys/devices/system/cpu. + source "kernel/Kconfig.preempt" config GUSA diff --git a/arch/sh/include/asm/irq.h b/arch/sh/include/asm/irq.h index 99c593b..02c2f01 100644 --- a/arch/sh/include/asm/irq.h +++ b/arch/sh/include/asm/irq.h @@ -1,6 +1,7 @@ #ifndef __ASM_SH_IRQ_H #define __ASM_SH_IRQ_H +#include #include /* @@ -50,6 +51,8 @@ static inline int generic_irq_demux(int irq) #define irq_demux(irq) sh_mv.mv_irq_demux(irq) void init_IRQ(void); +void migrate_irqs(void); + asmlinkage int do_IRQ(unsigned int irq, struct pt_regs *regs); #ifdef CONFIG_IRQSTACKS diff --git a/arch/sh/include/asm/smp-ops.h b/arch/sh/include/asm/smp-ops.h index 0581b2a..c590f76 100644 --- a/arch/sh/include/asm/smp-ops.h +++ b/arch/sh/include/asm/smp-ops.h @@ -7,20 +7,27 @@ struct plat_smp_ops { void (*prepare_cpus)(unsigned int max_cpus); void (*start_cpu)(unsigned int cpu, unsigned long entry_point); void (*send_ipi)(unsigned int cpu, unsigned int message); + int (*cpu_disable)(unsigned int cpu); + void (*cpu_die)(unsigned int cpu); + void (*play_dead)(void); }; +extern struct plat_smp_ops *mp_ops; extern struct plat_smp_ops shx3_smp_ops; #ifdef CONFIG_SMP static inline void plat_smp_setup(void) { - extern struct plat_smp_ops *mp_ops; /* private */ - BUG_ON(!mp_ops); mp_ops->smp_setup(); } +static inline void play_dead(void) +{ + mp_ops->play_dead(); +} + extern void register_smp_ops(struct plat_smp_ops *ops); #else @@ -34,6 +41,11 @@ static inline void register_smp_ops(struct plat_smp_ops *ops) { } +static inline void play_dead(void) +{ + BUG(); +} + #endif /* CONFIG_SMP */ #endif /* __ASM_SH_SMP_OPS_H */ diff --git a/arch/sh/include/asm/smp.h b/arch/sh/include/asm/smp.h index da5135b..9070d94 100644 --- a/arch/sh/include/asm/smp.h +++ b/arch/sh/include/asm/smp.h @@ -38,9 +38,26 @@ void smp_timer_broadcast(const struct cpumask *mask); void local_timer_interrupt(void); void local_timer_setup(unsigned int cpu); +void local_timer_stop(unsigned int cpu); void arch_send_call_function_single_ipi(int cpu); -extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); +void arch_send_call_function_ipi_mask(const struct cpumask *mask); + +void native_play_dead(void); +void native_cpu_die(unsigned int cpu); +int native_cpu_disable(unsigned int cpu); + +#ifdef CONFIG_HOTPLUG_CPU +void play_dead_common(void); +extern int __cpu_disable(void); + +static inline void __cpu_die(unsigned int cpu) +{ + extern struct plat_smp_ops *mp_ops; /* private */ + + mp_ops->cpu_die(cpu); +} +#endif static inline int hard_smp_processor_id(void) { diff --git a/arch/sh/kernel/idle.c b/arch/sh/kernel/idle.c index 2040053..425d604 100644 --- a/arch/sh/kernel/idle.c +++ b/arch/sh/kernel/idle.c @@ -19,6 +19,7 @@ #include #include #include +#include void (*pm_idle)(void) = NULL; @@ -89,10 +90,13 @@ void cpu_idle(void) while (1) { tick_nohz_stop_sched_tick(1); - while (!need_resched() && cpu_online(cpu)) { + while (!need_resched()) { check_pgt_cache(); rmb(); + if (cpu_is_offline(cpu)) + play_dead(); + local_irq_disable(); /* Don't trace irqs off for idle */ stop_critical_timings(); diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index f6a9319..257de1f 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -292,3 +293,44 @@ int __init arch_probe_nr_irqs(void) return 0; } #endif + +#ifdef CONFIG_HOTPLUG_CPU +static void route_irq(struct irq_desc *desc, unsigned int irq, unsigned int cpu) +{ + printk(KERN_INFO "IRQ%u: moving from cpu%u to cpu%u\n", + irq, desc->node, cpu); + + raw_spin_lock_irq(&desc->lock); + desc->chip->set_affinity(irq, cpumask_of(cpu)); + raw_spin_unlock_irq(&desc->lock); +} + +/* + * The CPU has been marked offline. Migrate IRQs off this CPU. If + * the affinity settings do not allow other CPUs, force them onto any + * available CPU. + */ +void migrate_irqs(void) +{ + struct irq_desc *desc; + unsigned int irq, cpu = smp_processor_id(); + + for_each_irq_desc(irq, desc) { + if (desc->node == cpu) { + unsigned int newcpu = cpumask_any_and(desc->affinity, + cpu_online_mask); + if (newcpu >= nr_cpu_ids) { + if (printk_ratelimit()) + printk(KERN_INFO "IRQ%u no longer affine to CPU%u\n", + irq, cpu); + + cpumask_setall(desc->affinity); + newcpu = cpumask_any_and(desc->affinity, + cpu_online_mask); + } + + route_irq(desc, irq, newcpu); + } + } +} +#endif diff --git a/arch/sh/kernel/localtimer.c b/arch/sh/kernel/localtimer.c index 865a2f1..8bfc6df 100644 --- a/arch/sh/kernel/localtimer.c +++ b/arch/sh/kernel/localtimer.c @@ -60,3 +60,7 @@ void local_timer_setup(unsigned int cpu) clockevents_register_device(clk); } + +void local_timer_stop(unsigned int cpu) +{ +} diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c index 21e7f8a..86cd6f9 100644 --- a/arch/sh/kernel/smp.c +++ b/arch/sh/kernel/smp.c @@ -79,6 +79,105 @@ void __init smp_prepare_boot_cpu(void) per_cpu(cpu_state, cpu) = CPU_ONLINE; } +#ifdef CONFIG_HOTPLUG_CPU +void native_cpu_die(unsigned int cpu) +{ + unsigned int i; + + for (i = 0; i < 10; i++) { + smp_rmb(); + if (per_cpu(cpu_state, cpu) == CPU_DEAD) { + if (system_state == SYSTEM_RUNNING) + pr_info("CPU %u is now offline\n", cpu); + + return; + } + + msleep(100); + } + + pr_err("CPU %u didn't die...\n", cpu); +} + +int native_cpu_disable(unsigned int cpu) +{ + return cpu == 0 ? -EPERM : 0; +} + +void play_dead_common(void) +{ + idle_task_exit(); + irq_ctx_exit(raw_smp_processor_id()); + mb(); + + __get_cpu_var(cpu_state) = CPU_DEAD; + local_irq_disable(); +} + +void native_play_dead(void) +{ + play_dead_common(); +} + +int __cpu_disable(void) +{ + unsigned int cpu = smp_processor_id(); + struct task_struct *p; + int ret; + + ret = mp_ops->cpu_disable(cpu); + if (ret) + return ret; + + /* + * Take this CPU offline. Once we clear this, we can't return, + * and we must not schedule until we're ready to give up the cpu. + */ + set_cpu_online(cpu, false); + + /* + * OK - migrate IRQs away from this CPU + */ + migrate_irqs(); + + /* + * Stop the local timer for this CPU. + */ + local_timer_stop(cpu); + + /* + * Flush user cache and TLB mappings, and then remove this CPU + * from the vm mask set of all processes. + */ + flush_cache_all(); + local_flush_tlb_all(); + + read_lock(&tasklist_lock); + for_each_process(p) + if (p->mm) + cpumask_clear_cpu(cpu, mm_cpumask(p->mm)); + read_unlock(&tasklist_lock); + + return 0; +} +#else /* ... !CONFIG_HOTPLUG_CPU */ +int native_cpu_disable(void) +{ + return -ENOSYS; +} + +void native_cpu_die(unsigned int cpu) +{ + /* We said "no" in __cpu_disable */ + BUG(); +} + +void native_play_dead(void) +{ + BUG(); +} +#endif + asmlinkage void __cpuinit start_secondary(void) { unsigned int cpu = smp_processor_id(); @@ -88,8 +187,8 @@ asmlinkage void __cpuinit start_secondary(void) atomic_inc(&mm->mm_count); atomic_inc(&mm->mm_users); current->active_mm = mm; - BUG_ON(current->mm); enter_lazy_tlb(mm, current); + local_flush_tlb_all(); per_cpu_trap_init(); @@ -156,6 +255,7 @@ int __cpuinit __cpu_up(unsigned int cpu) break; udelay(10); + barrier(); } if (cpu_online(cpu)) @@ -270,7 +370,6 @@ static void flush_tlb_mm_ipi(void *mm) * behalf of debugees, kswapd stealing pages from another process etc). * Kanoj 07/00. */ - void flush_tlb_mm(struct mm_struct *mm) { preempt_disable(); -- cgit v0.10.2 From e7dc951eecb708d4aef18db4dbf489ba282d16ff Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 26 Apr 2010 19:09:57 +0900 Subject: sh: CPU hotplug support for SH-X3 SMP. This wires up CPU hotplug for SH-X3 SMP CPUs. Presently only secondary cores can be hotplugged given that the boot CPU has to contend with the broadcast timer. When real local timers are implemented this restriction can be lifted. Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/smp-shx3.c b/arch/sh/kernel/cpu/sh4a/smp-shx3.c index dd245e6..de865ca 100644 --- a/arch/sh/kernel/cpu/sh4a/smp-shx3.c +++ b/arch/sh/kernel/cpu/sh4a/smp-shx3.c @@ -9,16 +9,22 @@ * for more details. */ #include +#include #include #include #include #include +#include +#include +#include +#include #define STBCR_REG(phys_id) (0xfe400004 | (phys_id << 12)) #define RESET_REG(phys_id) (0xfe400008 | (phys_id << 12)) #define STBCR_MSTP 0x00000001 #define STBCR_RESET 0x00000002 +#define STBCR_SLEEP 0x00000004 #define STBCR_LTSLP 0x80000000 static irqreturn_t ipi_interrupt_handler(int irq, void *arg) @@ -110,10 +116,51 @@ static void shx3_send_ipi(unsigned int cpu, unsigned int message) __raw_writel(1 << (message << 2), addr); /* C0INTICI..CnINTICI */ } +static void shx3_update_boot_vector(unsigned int cpu) +{ + __raw_writel(STBCR_MSTP, STBCR_REG(cpu)); + while (!(__raw_readl(STBCR_REG(cpu)) & STBCR_MSTP)) + cpu_relax(); + __raw_writel(STBCR_RESET, STBCR_REG(cpu)); +} + +static int __cpuinit +shx3_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) +{ + unsigned int cpu = (unsigned int)hcpu; + + switch (action) { + case CPU_UP_PREPARE: + shx3_update_boot_vector(cpu); + break; + case CPU_ONLINE: + pr_info("CPU %u is now online\n", cpu); + break; + case CPU_DEAD: + break; + } + + return NOTIFY_OK; +} + +static struct notifier_block __cpuinitdata shx3_cpu_notifier = { + .notifier_call = shx3_cpu_callback, +}; + +static int __cpuinit register_shx3_cpu_notifier(void) +{ + register_hotcpu_notifier(&shx3_cpu_notifier); + return 0; +} +late_initcall(register_shx3_cpu_notifier); + struct plat_smp_ops shx3_smp_ops = { .smp_setup = shx3_smp_setup, .prepare_cpus = shx3_prepare_cpus, .start_cpu = shx3_start_cpu, .smp_processor_id = shx3_smp_processor_id, .send_ipi = shx3_send_ipi, + .cpu_die = native_cpu_die, + .cpu_disable = native_cpu_disable, + .play_dead = native_play_dead, }; -- cgit v0.10.2 From 0ab061cd523a7f2dbf1b59aab0542cb0ab2e4633 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Wed, 21 Apr 2010 15:56:16 -0400 Subject: perf tools: Initialize dso->node member in dso__new If dso->node member is not initialized, it causes a segmentation fault when adding to other lists. It should be initilized in dso__new(). Signed-off-by: Masami Hiramatsu Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Mike Galbraith Cc: Frederic Weisbecker Cc: Ingo Molnar LKML-Reference: : <20100421195616.24664.89980.stgit@localhost6.localdomain6> Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index e782e7d..e77c33a 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -189,6 +189,7 @@ struct dso *dso__new(const char *name) self->sorted_by_name = 0; self->has_build_id = 0; self->kernel = DSO_TYPE_USER; + INIT_LIST_HEAD(&self->node); } return self; -- cgit v0.10.2 From 15eca306ec95e164d05457f9f27c722f69af6d18 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Wed, 21 Apr 2010 15:56:24 -0400 Subject: perf probe: Fix to use symtab only if no debuginfo Fix perf probe to use symtab only if there is no debuginfo, because debuginfo has more information than symtab. If we can't find a function in debuginfo, we never find it in symtab. Signed-off-by: Masami Hiramatsu Reported-by: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Frederic Weisbecker Cc: Ingo Molnar LKML-Reference: <20100421195624.24664.46214.stgit@localhost6.localdomain6> Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 4fb4803..5d3baec 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -180,15 +180,16 @@ static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev, return -ENOENT; } /* Error path : ntevs < 0 */ - if (need_dwarf) { - if (ntevs == -EBADF) - pr_warning("No dwarf info found in the vmlinux - " - "please rebuild with CONFIG_DEBUG_INFO=y.\n"); - return ntevs; + pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs); + if (ntevs == -EBADF) { + pr_warning("Warning: No dwarf info found in the vmlinux - " + "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n"); + if (!need_dwarf) { + pr_debug("Trying to use symbols.\nn"); + return 0; + } } - pr_debug("An error occurred in debuginfo analysis." - " Try to use symbols.\n"); - return 0; + return ntevs; } #define LINEBUF_SIZE 256 -- cgit v0.10.2 From 5d1ee0413c8e2e0aa48510b1edfb3c4d2d43455b Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Wed, 21 Apr 2010 15:56:32 -0400 Subject: perf probe: Fix to exit callback soon after finding too many probe points Fix to exit callback soon after finding too many probe points. Don't try to continue searching because it already failed. Signed-off-by: Masami Hiramatsu Reported-by: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Frederic Weisbecker Cc: Ingo Molnar LKML-Reference: <20100421195632.24664.42598.stgit@localhost6.localdomain6> Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index e7ee52f..0d795bc 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -871,6 +871,8 @@ static int probe_point_inline_cb(Dwarf_Die *in_die, void *data) (uintmax_t)pf->addr); param->retval = convert_probe_point(in_die, pf); + if (param->retval < 0) + return DWARF_CB_ABORT; } return DWARF_CB_OK; @@ -1106,6 +1108,8 @@ static int line_range_funcdecl_cb(Dwarf_Die *sp_die, void *data) return DWARF_CB_OK; param->retval = line_range_add_line(src, lineno, lf->lr); + if (param->retval < 0) + return DWARF_CB_ABORT; return DWARF_CB_OK; } -- cgit v0.10.2 From ef4a356574426877d569f8b6579325537eb7909b Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Wed, 21 Apr 2010 15:56:40 -0400 Subject: perf probe: Add --max-probes option Add --max-probes option to change the maximum limit of findable probe points per event, since inlined function can be expanded into thousands of probe points. Default value is 128. Signed-off-by: Masami Hiramatsu Suggested-by: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Frederic Weisbecker Cc: Ingo Molnar LKML-Reference: <20100421195640.24664.62984.stgit@localhost6.localdomain6> Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt index 63c25d3..94a258c 100644 --- a/tools/perf/Documentation/perf-probe.txt +++ b/tools/perf/Documentation/perf-probe.txt @@ -62,6 +62,9 @@ OPTIONS Dry run. With this option, --add and --del doesn't execute actual adding and removal operations. +--max-probes:: + Set the maximum number of probe points for an event. Default is 128. + PROBE SYNTAX ------------ Probe points are defined by following syntax. diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index c1e5403..61c6d70 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c @@ -54,6 +54,7 @@ static struct { struct perf_probe_event events[MAX_PROBES]; struct strlist *dellist; struct line_range line_range; + int max_probe_points; } params; @@ -179,6 +180,8 @@ static const struct option options[] = { "file", "vmlinux pathname"), #endif OPT__DRY_RUN(&probe_event_dry_run), + OPT_INTEGER('\0', "max-probes", ¶ms.max_probe_points, + "Set how many probe points can be found for a probe."), OPT_END() }; @@ -200,6 +203,9 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) } } + if (params.max_probe_points == 0) + params.max_probe_points = MAX_PROBES; + if ((!params.nevents && !params.dellist && !params.list_events && !params.show_lines)) usage_with_options(probe_usage, options); @@ -246,7 +252,8 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) if (params.nevents) { ret = add_perf_probe_events(params.events, params.nevents, - params.force_add); + params.force_add, + params.max_probe_points); if (ret < 0) { pr_err(" Error: Failed to add events. (%d)\n", ret); return ret; diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 5d3baec..9ded38c 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -150,7 +150,8 @@ static int convert_to_perf_probe_point(struct kprobe_trace_point *tp, /* Try to find perf_probe_event with debuginfo */ static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev, - struct kprobe_trace_event **tevs) + struct kprobe_trace_event **tevs, + int max_tevs) { bool need_dwarf = perf_probe_event_need_dwarf(pev); int fd, ntevs; @@ -166,7 +167,7 @@ static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev, } /* Searching trace events corresponding to probe event */ - ntevs = find_kprobe_trace_events(fd, pev, tevs); + ntevs = find_kprobe_trace_events(fd, pev, tevs, max_tevs); close(fd); if (ntevs > 0) { /* Succeeded to find trace events */ @@ -318,7 +319,8 @@ static int convert_to_perf_probe_point(struct kprobe_trace_point *tp, } static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev, - struct kprobe_trace_event **tevs __unused) + struct kprobe_trace_event **tevs __unused, + int max_tevs __unused) { if (perf_probe_event_need_dwarf(pev)) { pr_warning("Debuginfo-analysis is not supported.\n"); @@ -1408,14 +1410,15 @@ static int __add_kprobe_trace_events(struct perf_probe_event *pev, } static int convert_to_kprobe_trace_events(struct perf_probe_event *pev, - struct kprobe_trace_event **tevs) + struct kprobe_trace_event **tevs, + int max_tevs) { struct symbol *sym; int ret = 0, i; struct kprobe_trace_event *tev; /* Convert perf_probe_event with debuginfo */ - ret = try_to_find_kprobe_trace_events(pev, tevs); + ret = try_to_find_kprobe_trace_events(pev, tevs, max_tevs); if (ret != 0) return ret; @@ -1487,7 +1490,7 @@ struct __event_package { }; int add_perf_probe_events(struct perf_probe_event *pevs, int npevs, - bool force_add) + bool force_add, int max_tevs) { int i, j, ret; struct __event_package *pkgs; @@ -1506,7 +1509,7 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs, pkgs[i].pev = &pevs[i]; /* Convert with or without debuginfo */ ret = convert_to_kprobe_trace_events(pkgs[i].pev, - &pkgs[i].tevs); + &pkgs[i].tevs, max_tevs); if (ret < 0) goto end; pkgs[i].ntevs = ret; diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h index e7ff0d0..e9db1a2 100644 --- a/tools/perf/util/probe-event.h +++ b/tools/perf/util/probe-event.h @@ -115,8 +115,8 @@ extern void clear_kprobe_trace_event(struct kprobe_trace_event *tev); extern int parse_line_range_desc(const char *cmd, struct line_range *lr); -extern int add_perf_probe_events(struct perf_probe_event *pevs, int ntevs, - bool force_add); +extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs, + bool force_add, int max_probe_points); extern int del_perf_probe_events(struct strlist *dellist); extern int show_perf_probe_events(void); extern int show_line_range(struct line_range *lr); diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 0d795bc..562b144 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -626,8 +626,9 @@ static int convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf) Dwarf_Attribute fb_attr; size_t nops; - if (pf->ntevs == MAX_PROBES) { - pr_warning("Too many( > %d) probe point found.\n", MAX_PROBES); + if (pf->ntevs == pf->max_tevs) { + pr_warning("Too many( > %d) probe point found.\n", + pf->max_tevs); return -ERANGE; } tev = &pf->tevs[pf->ntevs++]; @@ -932,9 +933,9 @@ static int find_probe_point_by_func(struct probe_finder *pf) /* Find kprobe_trace_events specified by perf_probe_event from debuginfo */ int find_kprobe_trace_events(int fd, struct perf_probe_event *pev, - struct kprobe_trace_event **tevs) + struct kprobe_trace_event **tevs, int max_tevs) { - struct probe_finder pf = {.pev = pev}; + struct probe_finder pf = {.pev = pev, .max_tevs = max_tevs}; struct perf_probe_point *pp = &pev->point; Dwarf_Off off, noff; size_t cuhl; @@ -942,7 +943,7 @@ int find_kprobe_trace_events(int fd, struct perf_probe_event *pev, Dwarf *dbg; int ret = 0; - pf.tevs = zalloc(sizeof(struct kprobe_trace_event) * MAX_PROBES); + pf.tevs = zalloc(sizeof(struct kprobe_trace_event) * max_tevs); if (pf.tevs == NULL) return -ENOMEM; *tevs = pf.tevs; diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h index 310ce89..66f1980 100644 --- a/tools/perf/util/probe-finder.h +++ b/tools/perf/util/probe-finder.h @@ -18,7 +18,8 @@ static inline int is_c_varname(const char *name) #ifdef DWARF_SUPPORT /* Find kprobe_trace_events specified by perf_probe_event from debuginfo */ extern int find_kprobe_trace_events(int fd, struct perf_probe_event *pev, - struct kprobe_trace_event **tevs); + struct kprobe_trace_event **tevs, + int max_tevs); /* Find a perf_probe_point from debuginfo */ extern int find_perf_probe_point(int fd, unsigned long addr, @@ -32,7 +33,8 @@ extern int find_line_range(int fd, struct line_range *lr); struct probe_finder { struct perf_probe_event *pev; /* Target probe event */ struct kprobe_trace_event *tevs; /* Result trace events */ - int ntevs; /* number of trace events */ + int ntevs; /* Number of trace events */ + int max_tevs; /* Max number of trace events */ /* For function searching */ int lno; /* Line number */ -- cgit v0.10.2 From f93830fbb06b67848c762f2177c06cc3cbb97deb Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Mon, 26 Apr 2010 15:39:54 -0300 Subject: perf tools: Fix libdw-dev package name in error message The headers required for DWARF support are provided by the libdw-dev package in Debian-based distros. This patch corrects the elfutils-dev package name to libdw-dev in the Makefile error message when libdw.h is not found. Signed-off-by: Stefan Hajnoczi Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Masami Hiramatsu Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Tom Zanussi LKML-Reference: <1272292023-9869-1-git-send-email-stefanha@linux.vnet.ibm.com> Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Makefile b/tools/perf/Makefile index e8bf2e1..3ac6b67 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -504,7 +504,7 @@ PERFLIBS = $(LIB_FILE) ifndef NO_DWARF ifneq ($(shell sh -c "(echo '\#include '; echo '\#include '; echo 'int main(void) { Dwarf *dbg; dbg = dwarf_begin(0, DWARF_C_READ); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -I/usr/include/elfutils -ldw -lelf -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y) - msg := $(warning No libdw.h found or old libdw.h found, disables dwarf support. Please install elfutils-devel/elfutils-dev); + msg := $(warning No libdw.h found or old libdw.h found, disables dwarf support. Please install elfutils-devel/libdw-dev); NO_DWARF := 1 endif # Dwarf support endif # NO_DWARF -- cgit v0.10.2 From a5fc4ce01867842f6a9cc317035df3081302bffc Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Sat, 24 Apr 2010 07:57:42 -0400 Subject: cifs: track local_nls in volume info Add a local_nls field to the smb_vol struct and keep a pointer to the local_nls in it. Signed-off-by: Jeff Layton Signed-off-by: Steve French diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 58a2109..eb85dd8 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -102,6 +102,7 @@ struct smb_vol { bool sockopt_tcp_nodelay:1; unsigned short int port; char *prepath; + struct nls_table *local_nls; }; static int ipv4_connect(struct TCP_Server_Info *server); @@ -2353,20 +2354,20 @@ try_mount_again: goto out; } - /* this is needed for ASCII cp to Unicode converts */ if (volume_info->iocharset == NULL) { - cifs_sb->local_nls = load_nls_default(); - /* load_nls_default can not return null */ + /* load_nls_default cannot return null */ + volume_info->local_nls = load_nls_default(); } else { - cifs_sb->local_nls = load_nls(volume_info->iocharset); - if (cifs_sb->local_nls == NULL) { + volume_info->local_nls = load_nls(volume_info->iocharset); + if (volume_info->local_nls == NULL) { cERROR(1, "CIFS mount error: iocharset %s not found", volume_info->iocharset); rc = -ELIBACC; goto out; } } + cifs_sb->local_nls = volume_info->local_nls; /* get a reference to a tcp session */ srvTcp = cifs_get_tcp_session(volume_info); -- cgit v0.10.2 From 36988c76f007738cad5fe1c873a5fb0cda7eb2f6 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Sat, 24 Apr 2010 07:57:43 -0400 Subject: cifs: move SMB session creation code into separate function ...it's mostly part of cifs_mount. Break it out into a separate function. Signed-off-by: Jeff Layton Signed-off-by: Steve French diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index eb85dd8..74c222e 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1616,6 +1616,7 @@ cifs_put_smb_ses(struct cifsSesInfo *ses) int xid; struct TCP_Server_Info *server = ses->server; + cFYI(1, "%s: ses_count=%d\n", __func__, ses->ses_count); write_lock(&cifs_tcp_ses_lock); if (--ses->ses_count > 0) { write_unlock(&cifs_tcp_ses_lock); @@ -1634,6 +1635,92 @@ cifs_put_smb_ses(struct cifsSesInfo *ses) cifs_put_tcp_session(server); } +static struct cifsSesInfo * +cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info) +{ + int rc = -ENOMEM, xid; + struct cifsSesInfo *ses; + + xid = GetXid(); + + ses = cifs_find_smb_ses(server, volume_info->username); + if (ses) { + cFYI(1, "Existing smb sess found (status=%d)", ses->status); + + /* existing SMB ses has a server reference already */ + cifs_put_tcp_session(server); + + mutex_lock(&ses->session_mutex); + if (ses->need_reconnect) { + cFYI(1, "Session needs reconnect"); + rc = cifs_setup_session(xid, ses, + volume_info->local_nls); + if (rc) { + mutex_unlock(&ses->session_mutex); + /* problem -- put our reference */ + cifs_put_smb_ses(ses); + FreeXid(xid); + return ERR_PTR(rc); + } + } + mutex_unlock(&ses->session_mutex); + FreeXid(xid); + return ses; + } + + cFYI(1, "Existing smb sess not found"); + ses = sesInfoAlloc(); + if (ses == NULL) + goto get_ses_fail; + + /* new SMB session uses our server ref */ + ses->server = server; + if (server->addr.sockAddr6.sin6_family == AF_INET6) + sprintf(ses->serverName, "%pI6", + &server->addr.sockAddr6.sin6_addr); + else + sprintf(ses->serverName, "%pI4", + &server->addr.sockAddr.sin_addr.s_addr); + + if (volume_info->username) + strncpy(ses->userName, volume_info->username, + MAX_USERNAME_SIZE); + + /* volume_info->password freed at unmount */ + if (volume_info->password) { + ses->password = kstrdup(volume_info->password, GFP_KERNEL); + if (!ses->password) + goto get_ses_fail; + } + if (volume_info->domainname) { + int len = strlen(volume_info->domainname); + ses->domainName = kmalloc(len + 1, GFP_KERNEL); + if (ses->domainName) + strcpy(ses->domainName, volume_info->domainname); + } + ses->linux_uid = volume_info->linux_uid; + ses->overrideSecFlg = volume_info->secFlg; + + mutex_lock(&ses->session_mutex); + rc = cifs_setup_session(xid, ses, volume_info->local_nls); + mutex_unlock(&ses->session_mutex); + if (rc) + goto get_ses_fail; + + /* success, put it on the list */ + write_lock(&cifs_tcp_ses_lock); + list_add(&ses->smb_ses_list, &server->smb_ses_list); + write_unlock(&cifs_tcp_ses_lock); + + FreeXid(xid); + return ses; + +get_ses_fail: + sesInfoFree(ses); + FreeXid(xid); + return ERR_PTR(rc); +} + static struct cifsTconInfo * cifs_find_tcon(struct cifsSesInfo *ses, const char *unc) { @@ -2376,71 +2463,12 @@ try_mount_again: goto out; } - pSesInfo = cifs_find_smb_ses(srvTcp, volume_info->username); - if (pSesInfo) { - cFYI(1, "Existing smb sess found (status=%d)", - pSesInfo->status); - /* - * The existing SMB session already has a reference to srvTcp, - * so we can put back the extra one we got before - */ - cifs_put_tcp_session(srvTcp); - - mutex_lock(&pSesInfo->session_mutex); - if (pSesInfo->need_reconnect) { - cFYI(1, "Session needs reconnect"); - rc = cifs_setup_session(xid, pSesInfo, - cifs_sb->local_nls); - } - mutex_unlock(&pSesInfo->session_mutex); - } else if (!rc) { - cFYI(1, "Existing smb sess not found"); - pSesInfo = sesInfoAlloc(); - if (pSesInfo == NULL) { - rc = -ENOMEM; - goto mount_fail_check; - } - - /* new SMB session uses our srvTcp ref */ - pSesInfo->server = srvTcp; - if (srvTcp->addr.sockAddr6.sin6_family == AF_INET6) - sprintf(pSesInfo->serverName, "%pI6", - &srvTcp->addr.sockAddr6.sin6_addr); - else - sprintf(pSesInfo->serverName, "%pI4", - &srvTcp->addr.sockAddr.sin_addr.s_addr); - - write_lock(&cifs_tcp_ses_lock); - list_add(&pSesInfo->smb_ses_list, &srvTcp->smb_ses_list); - write_unlock(&cifs_tcp_ses_lock); - - /* volume_info->password freed at unmount */ - if (volume_info->password) { - pSesInfo->password = kstrdup(volume_info->password, - GFP_KERNEL); - if (!pSesInfo->password) { - rc = -ENOMEM; - goto mount_fail_check; - } - } - if (volume_info->username) - strncpy(pSesInfo->userName, volume_info->username, - MAX_USERNAME_SIZE); - if (volume_info->domainname) { - int len = strlen(volume_info->domainname); - pSesInfo->domainName = kmalloc(len + 1, GFP_KERNEL); - if (pSesInfo->domainName) - strcpy(pSesInfo->domainName, - volume_info->domainname); - } - pSesInfo->linux_uid = volume_info->linux_uid; - pSesInfo->overrideSecFlg = volume_info->secFlg; - mutex_lock(&pSesInfo->session_mutex); - - /* BB FIXME need to pass vol->secFlgs BB */ - rc = cifs_setup_session(xid, pSesInfo, - cifs_sb->local_nls); - mutex_unlock(&pSesInfo->session_mutex); + /* get a reference to a SMB session */ + pSesInfo = cifs_get_smb_ses(srvTcp, volume_info); + if (IS_ERR(pSesInfo)) { + rc = PTR_ERR(pSesInfo); + pSesInfo = NULL; + goto mount_fail_check; } /* search for existing tcon to this server share */ -- cgit v0.10.2 From d00c28de55a69d13cf2c6a99efc3e81a5d95af74 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Sat, 24 Apr 2010 07:57:44 -0400 Subject: cifs: move tcon find/create into separate function ...and out of cifs_mount. Signed-off-by: Jeff Layton Signed-off-by: Steve French diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 74c222e..c104f54 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1749,6 +1749,7 @@ cifs_put_tcon(struct cifsTconInfo *tcon) int xid; struct cifsSesInfo *ses = tcon->ses; + cFYI(1, "%s: tc_count=%d\n", __func__, tcon->tc_count); write_lock(&cifs_tcp_ses_lock); if (--tcon->tc_count > 0) { write_unlock(&cifs_tcp_ses_lock); @@ -1766,6 +1767,80 @@ cifs_put_tcon(struct cifsTconInfo *tcon) cifs_put_smb_ses(ses); } +static struct cifsTconInfo * +cifs_get_tcon(struct cifsSesInfo *ses, struct smb_vol *volume_info) +{ + int rc, xid; + struct cifsTconInfo *tcon; + + tcon = cifs_find_tcon(ses, volume_info->UNC); + if (tcon) { + cFYI(1, "Found match on UNC path"); + /* existing tcon already has a reference */ + cifs_put_smb_ses(ses); + if (tcon->seal != volume_info->seal) + cERROR(1, "transport encryption setting " + "conflicts with existing tid"); + return tcon; + } + + tcon = tconInfoAlloc(); + if (tcon == NULL) { + rc = -ENOMEM; + goto out_fail; + } + + tcon->ses = ses; + if (volume_info->password) { + tcon->password = kstrdup(volume_info->password, GFP_KERNEL); + if (!tcon->password) { + rc = -ENOMEM; + goto out_fail; + } + } + + if (strchr(volume_info->UNC + 3, '\\') == NULL + && strchr(volume_info->UNC + 3, '/') == NULL) { + cERROR(1, "Missing share name"); + rc = -ENODEV; + goto out_fail; + } + + /* BB Do we need to wrap session_mutex around + * this TCon call and Unix SetFS as + * we do on SessSetup and reconnect? */ + xid = GetXid(); + rc = CIFSTCon(xid, ses, volume_info->UNC, tcon, volume_info->local_nls); + FreeXid(xid); + cFYI(1, "CIFS Tcon rc = %d", rc); + if (rc) + goto out_fail; + + if (volume_info->nodfs) { + tcon->Flags &= ~SMB_SHARE_IS_IN_DFS; + cFYI(1, "DFS disabled (%d)", tcon->Flags); + } + tcon->seal = volume_info->seal; + /* we can have only one retry value for a connection + to a share so for resources mounted more than once + to the same server share the last value passed in + for the retry flag is used */ + tcon->retry = volume_info->retry; + tcon->nocase = volume_info->nocase; + tcon->local_lease = volume_info->local_lease; + + write_lock(&cifs_tcp_ses_lock); + list_add(&tcon->tcon_list, &ses->tcon_list); + write_unlock(&cifs_tcp_ses_lock); + + return tcon; + +out_fail: + tconInfoFree(tcon); + return ERR_PTR(rc); +} + + int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path, const struct nls_table *nls_codepage, unsigned int *pnum_referrals, @@ -2471,81 +2546,22 @@ try_mount_again: goto mount_fail_check; } - /* search for existing tcon to this server share */ - if (!rc) { - setup_cifs_sb(volume_info, cifs_sb); - - tcon = cifs_find_tcon(pSesInfo, volume_info->UNC); - if (tcon) { - cFYI(1, "Found match on UNC path"); - /* existing tcon already has a reference */ - cifs_put_smb_ses(pSesInfo); - if (tcon->seal != volume_info->seal) - cERROR(1, "transport encryption setting " - "conflicts with existing tid"); - } else { - tcon = tconInfoAlloc(); - if (tcon == NULL) { - rc = -ENOMEM; - goto mount_fail_check; - } - - tcon->ses = pSesInfo; - if (volume_info->password) { - tcon->password = kstrdup(volume_info->password, - GFP_KERNEL); - if (!tcon->password) { - rc = -ENOMEM; - goto mount_fail_check; - } - } - - if ((strchr(volume_info->UNC + 3, '\\') == NULL) - && (strchr(volume_info->UNC + 3, '/') == NULL)) { - cERROR(1, "Missing share name"); - rc = -ENODEV; - goto mount_fail_check; - } else { - /* BB Do we need to wrap sesSem around - * this TCon call and Unix SetFS as - * we do on SessSetup and reconnect? */ - rc = CIFSTCon(xid, pSesInfo, volume_info->UNC, - tcon, cifs_sb->local_nls); - cFYI(1, "CIFS Tcon rc = %d", rc); - if (volume_info->nodfs) { - tcon->Flags &= ~SMB_SHARE_IS_IN_DFS; - cFYI(1, "DFS disabled (%d)", - tcon->Flags); - } - } - if (rc) - goto remote_path_check; - tcon->seal = volume_info->seal; - write_lock(&cifs_tcp_ses_lock); - list_add(&tcon->tcon_list, &pSesInfo->tcon_list); - write_unlock(&cifs_tcp_ses_lock); - } - - /* we can have only one retry value for a connection - to a share so for resources mounted more than once - to the same server share the last value passed in - for the retry flag is used */ - tcon->retry = volume_info->retry; - tcon->nocase = volume_info->nocase; - tcon->local_lease = volume_info->local_lease; - } - if (pSesInfo) { - if (pSesInfo->capabilities & CAP_LARGE_FILES) - sb->s_maxbytes = MAX_LFS_FILESIZE; - else - sb->s_maxbytes = MAX_NON_LFS; - } + setup_cifs_sb(volume_info, cifs_sb); + if (pSesInfo->capabilities & CAP_LARGE_FILES) + sb->s_maxbytes = MAX_LFS_FILESIZE; + else + sb->s_maxbytes = MAX_NON_LFS; /* BB FIXME fix time_gran to be larger for LANMAN sessions */ sb->s_time_gran = 100; - if (rc) + /* search for existing tcon to this server share */ + tcon = cifs_get_tcon(pSesInfo, volume_info); + if (IS_ERR(tcon)) { + rc = PTR_ERR(tcon); + tcon = NULL; goto remote_path_check; + } cifs_sb->tcon = tcon; -- cgit v0.10.2 From 04912d6a20185473db025061b9b2c81fbdffc48b Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Sat, 24 Apr 2010 07:57:45 -0400 Subject: cifs: rename "extended_security" to "global_secflags" ...since that more accurately describes what that variable holds. Signed-off-by: Jeff Layton Signed-off-by: Steve French diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index 5495180..4fce6e6 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c @@ -716,7 +716,7 @@ static const struct file_operations cifs_multiuser_mount_proc_fops = { static int cifs_security_flags_proc_show(struct seq_file *m, void *v) { - seq_printf(m, "0x%x\n", extended_security); + seq_printf(m, "0x%x\n", global_secflags); return 0; } @@ -744,10 +744,10 @@ static ssize_t cifs_security_flags_proc_write(struct file *file, /* single char or single char followed by null */ c = flags_string[0]; if (c == '0' || c == 'n' || c == 'N') { - extended_security = CIFSSEC_DEF; /* default */ + global_secflags = CIFSSEC_DEF; /* default */ return count; } else if (c == '1' || c == 'y' || c == 'Y') { - extended_security = CIFSSEC_MAX; + global_secflags = CIFSSEC_MAX; return count; } else if (!isdigit(c)) { cERROR(1, "invalid flag %c", c); @@ -771,12 +771,12 @@ static ssize_t cifs_security_flags_proc_write(struct file *file, return -EINVAL; } /* flags look ok - update the global security flags for cifs module */ - extended_security = flags; - if (extended_security & CIFSSEC_MUST_SIGN) { + global_secflags = flags; + if (global_secflags & CIFSSEC_MUST_SIGN) { /* requiring signing implies signing is allowed */ - extended_security |= CIFSSEC_MAY_SIGN; + global_secflags |= CIFSSEC_MAY_SIGN; cFYI(1, "packet signing now required"); - } else if ((extended_security & CIFSSEC_MAY_SIGN) == 0) { + } else if ((global_secflags & CIFSSEC_MAY_SIGN) == 0) { cFYI(1, "packet signing disabled"); } /* BB should we turn on MAY flags for other MUST options? */ diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index 61e4152..847628d 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c @@ -291,7 +291,7 @@ void calc_lanman_hash(const char *password, const char *cryptkey, bool encrypt, if (password) strncpy(password_with_pad, password, CIFS_ENCPWD_SIZE); - if (!encrypt && extended_security & CIFSSEC_MAY_PLNTXT) { + if (!encrypt && global_secflags & CIFSSEC_MAY_PLNTXT) { memset(lnm_session_key, 0, CIFS_SESS_KEY_SIZE); memcpy(lnm_session_key, password_with_pad, CIFS_ENCPWD_SIZE); diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 53e7941..440e98c 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -61,7 +61,7 @@ unsigned int experimEnabled = 0; unsigned int linuxExtEnabled = 1; unsigned int lookupCacheEnabled = 1; unsigned int multiuser_mount = 0; -unsigned int extended_security = CIFSSEC_DEF; +unsigned int global_secflags = CIFSSEC_DEF; /* unsigned int ntlmv2_support = 0; */ unsigned int sign_CIFS_PDUs = 1; static const struct super_operations cifs_super_ops; diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index ecf0ffb..4a2715b 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -717,7 +717,7 @@ GLOBAL_EXTERN unsigned int multiuser_mount; /* if enabled allows new sessions GLOBAL_EXTERN unsigned int oplockEnabled; GLOBAL_EXTERN unsigned int experimEnabled; GLOBAL_EXTERN unsigned int lookupCacheEnabled; -GLOBAL_EXTERN unsigned int extended_security; /* if on, session setup sent +GLOBAL_EXTERN unsigned int global_secflags; /* if on, session setup sent with more secure ntlmssp2 challenge/resp */ GLOBAL_EXTERN unsigned int sign_CIFS_PDUs; /* enable smb packet signing */ GLOBAL_EXTERN unsigned int linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/ diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 980c38c..4ecb361 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -372,7 +372,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) if (ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL))) secFlags = ses->overrideSecFlg; /* BB FIXME fix sign flags? */ else /* if override flags set only sign/seal OR them with global auth */ - secFlags = extended_security | ses->overrideSecFlg; + secFlags = global_secflags | ses->overrideSecFlg; cFYI(1, "secFlags 0x%x", secFlags); diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index c104f54..c2793bd 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -2748,7 +2748,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, by Samba (not sure whether other servers allow NTLMv2 password here) */ #ifdef CONFIG_CIFS_WEAK_PW_HASH - if ((extended_security & CIFSSEC_MAY_LANMAN) && + if ((global_secflags & CIFSSEC_MAY_LANMAN) && (ses->server->secType == LANMAN)) calc_lanman_hash(tcon->password, ses->server->cryptKey, ses->server->secMode & -- cgit v0.10.2 From ad6cca6d5d0f713e1987e20ed982cfa9eb16b27e Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 26 Apr 2010 12:10:06 +0200 Subject: cifs: change && to || This is a typo, if pvolume_info were NULL it would oops. This function is used in clean up and error handling. The current code never passes a NULL pvolume_info, but it could pass a NULL *pvolume_info if the kmalloc() failed. Signed-off-by: Dan Carpenter Acked-by: Jeff Layton Signed-off-by: Steve French diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index c2793bd..7a47c7c 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -2421,7 +2421,7 @@ cleanup_volume_info(struct smb_vol **pvolume_info) { struct smb_vol *volume_info; - if (!pvolume_info && !*pvolume_info) + if (!pvolume_info || !*pvolume_info) return; volume_info = *pvolume_info; -- cgit v0.10.2 From 9106b69382912ddc403a307b69bf894a6f3004e4 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 2 Apr 2010 19:01:20 +0200 Subject: tracing: Add ftrace events for graph tracer Add ftrace events for graph tracer, so the graph output could be shared with other tracers. Signed-off-by: Jiri Olsa LKML-Reference: <1270227683-14631-2-git-send-email-jolsa@redhat.com> Signed-off-by: Steven Rostedt diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c index 669b9c3..db9e06b 100644 --- a/kernel/trace/trace_functions_graph.c +++ b/kernel/trace/trace_functions_graph.c @@ -40,7 +40,7 @@ struct fgraph_data { #define TRACE_GRAPH_PRINT_OVERHEAD 0x4 #define TRACE_GRAPH_PRINT_PROC 0x8 #define TRACE_GRAPH_PRINT_DURATION 0x10 -#define TRACE_GRAPH_PRINT_ABS_TIME 0X20 +#define TRACE_GRAPH_PRINT_ABS_TIME 0x20 static struct tracer_opt trace_opts[] = { /* Display overruns? (for self-debug purpose) */ @@ -1096,6 +1096,12 @@ print_graph_function(struct trace_iterator *iter) return TRACE_TYPE_HANDLED; } +static enum print_line_t +print_graph_function_event(struct trace_iterator *iter, int flags) +{ + return print_graph_function(iter); +} + static void print_lat_header(struct seq_file *s) { static const char spaces[] = " " /* 16 spaces */ @@ -1199,6 +1205,16 @@ static void graph_trace_close(struct trace_iterator *iter) } } +static struct trace_event graph_trace_entry_event = { + .type = TRACE_GRAPH_ENT, + .trace = print_graph_function_event, +}; + +static struct trace_event graph_trace_ret_event = { + .type = TRACE_GRAPH_RET, + .trace = print_graph_function_event, +}; + static struct tracer graph_trace __read_mostly = { .name = "function_graph", .open = graph_trace_open, @@ -1220,6 +1236,16 @@ static __init int init_graph_trace(void) { max_bytes_for_cpu = snprintf(NULL, 0, "%d", nr_cpu_ids - 1); + if (!register_ftrace_event(&graph_trace_entry_event)) { + pr_warning("Warning: could not register graph trace events\n"); + return 1; + } + + if (!register_ftrace_event(&graph_trace_ret_event)) { + pr_warning("Warning: could not register graph trace events\n"); + return 1; + } + return register_tracer(&graph_trace); } -- cgit v0.10.2 From d7a8d9e907cc294ec7a4a7046d1886375fbcc82e Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 2 Apr 2010 19:01:21 +0200 Subject: tracing: Have graph flags passed in to ouput functions Let the function graph tracer have custom flags passed to its output functions. Signed-off-by: Jiri Olsa LKML-Reference: <1270227683-14631-3-git-send-email-jolsa@redhat.com> Signed-off-by: Steven Rostedt diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 2825ef2..970004c 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -491,7 +491,9 @@ extern int trace_clock_id; /* Standard output formatting function used for function return traces */ #ifdef CONFIG_FUNCTION_GRAPH_TRACER -extern enum print_line_t print_graph_function(struct trace_iterator *iter); +extern enum print_line_t +print_graph_function_flags(struct trace_iterator *iter, u32 flags); +extern void print_graph_headers_flags(struct seq_file *s, u32 flags); extern enum print_line_t trace_print_graph_duration(unsigned long long duration, struct trace_seq *s); @@ -524,7 +526,7 @@ static inline int ftrace_graph_addr(unsigned long addr) #endif /* CONFIG_DYNAMIC_FTRACE */ #else /* CONFIG_FUNCTION_GRAPH_TRACER */ static inline enum print_line_t -print_graph_function(struct trace_iterator *iter) +print_graph_function_flags(struct trace_iterator *iter, u32 flags) { return TRACE_TYPE_UNHANDLED; } diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c index db9e06b..de5f651 100644 --- a/kernel/trace/trace_functions_graph.c +++ b/kernel/trace/trace_functions_graph.c @@ -527,17 +527,18 @@ get_return_for_leaf(struct trace_iterator *iter, /* Signal a overhead of time execution to the output */ static int -print_graph_overhead(unsigned long long duration, struct trace_seq *s) +print_graph_overhead(unsigned long long duration, struct trace_seq *s, + u32 flags) { /* If duration disappear, we don't need anything */ - if (!(tracer_flags.val & TRACE_GRAPH_PRINT_DURATION)) + if (!(flags & TRACE_GRAPH_PRINT_DURATION)) return 1; /* Non nested entry or return */ if (duration == -1) return trace_seq_printf(s, " "); - if (tracer_flags.val & TRACE_GRAPH_PRINT_OVERHEAD) { + if (flags & TRACE_GRAPH_PRINT_OVERHEAD) { /* Duration exceeded 100 msecs */ if (duration > 100000ULL) return trace_seq_printf(s, "! "); @@ -563,7 +564,7 @@ static int print_graph_abs_time(u64 t, struct trace_seq *s) static enum print_line_t print_graph_irq(struct trace_iterator *iter, unsigned long addr, - enum trace_type type, int cpu, pid_t pid) + enum trace_type type, int cpu, pid_t pid, u32 flags) { int ret; struct trace_seq *s = &iter->seq; @@ -573,21 +574,21 @@ print_graph_irq(struct trace_iterator *iter, unsigned long addr, return TRACE_TYPE_UNHANDLED; /* Absolute time */ - if (tracer_flags.val & TRACE_GRAPH_PRINT_ABS_TIME) { + if (flags & TRACE_GRAPH_PRINT_ABS_TIME) { ret = print_graph_abs_time(iter->ts, s); if (!ret) return TRACE_TYPE_PARTIAL_LINE; } /* Cpu */ - if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU) { + if (flags & TRACE_GRAPH_PRINT_CPU) { ret = print_graph_cpu(s, cpu); if (ret == TRACE_TYPE_PARTIAL_LINE) return TRACE_TYPE_PARTIAL_LINE; } /* Proc */ - if (tracer_flags.val & TRACE_GRAPH_PRINT_PROC) { + if (flags & TRACE_GRAPH_PRINT_PROC) { ret = print_graph_proc(s, pid); if (ret == TRACE_TYPE_PARTIAL_LINE) return TRACE_TYPE_PARTIAL_LINE; @@ -597,7 +598,7 @@ print_graph_irq(struct trace_iterator *iter, unsigned long addr, } /* No overhead */ - ret = print_graph_overhead(-1, s); + ret = print_graph_overhead(-1, s, flags); if (!ret) return TRACE_TYPE_PARTIAL_LINE; @@ -610,7 +611,7 @@ print_graph_irq(struct trace_iterator *iter, unsigned long addr, return TRACE_TYPE_PARTIAL_LINE; /* Don't close the duration column if haven't one */ - if (tracer_flags.val & TRACE_GRAPH_PRINT_DURATION) + if (flags & TRACE_GRAPH_PRINT_DURATION) trace_seq_printf(s, " |"); ret = trace_seq_printf(s, "\n"); @@ -680,7 +681,8 @@ print_graph_duration(unsigned long long duration, struct trace_seq *s) static enum print_line_t print_graph_entry_leaf(struct trace_iterator *iter, struct ftrace_graph_ent_entry *entry, - struct ftrace_graph_ret_entry *ret_entry, struct trace_seq *s) + struct ftrace_graph_ret_entry *ret_entry, + struct trace_seq *s, u32 flags) { struct fgraph_data *data = iter->private; struct ftrace_graph_ret *graph_ret; @@ -712,12 +714,12 @@ print_graph_entry_leaf(struct trace_iterator *iter, } /* Overhead */ - ret = print_graph_overhead(duration, s); + ret = print_graph_overhead(duration, s, flags); if (!ret) return TRACE_TYPE_PARTIAL_LINE; /* Duration */ - if (tracer_flags.val & TRACE_GRAPH_PRINT_DURATION) { + if (flags & TRACE_GRAPH_PRINT_DURATION) { ret = print_graph_duration(duration, s); if (ret == TRACE_TYPE_PARTIAL_LINE) return TRACE_TYPE_PARTIAL_LINE; @@ -740,7 +742,7 @@ print_graph_entry_leaf(struct trace_iterator *iter, static enum print_line_t print_graph_entry_nested(struct trace_iterator *iter, struct ftrace_graph_ent_entry *entry, - struct trace_seq *s, int cpu) + struct trace_seq *s, int cpu, u32 flags) { struct ftrace_graph_ent *call = &entry->graph_ent; struct fgraph_data *data = iter->private; @@ -760,12 +762,12 @@ print_graph_entry_nested(struct trace_iterator *iter, } /* No overhead */ - ret = print_graph_overhead(-1, s); + ret = print_graph_overhead(-1, s, flags); if (!ret) return TRACE_TYPE_PARTIAL_LINE; /* No time */ - if (tracer_flags.val & TRACE_GRAPH_PRINT_DURATION) { + if (flags & TRACE_GRAPH_PRINT_DURATION) { ret = trace_seq_printf(s, " | "); if (!ret) return TRACE_TYPE_PARTIAL_LINE; @@ -791,7 +793,7 @@ print_graph_entry_nested(struct trace_iterator *iter, static enum print_line_t print_graph_prologue(struct trace_iterator *iter, struct trace_seq *s, - int type, unsigned long addr) + int type, unsigned long addr, u32 flags) { struct fgraph_data *data = iter->private; struct trace_entry *ent = iter->ent; @@ -804,27 +806,27 @@ print_graph_prologue(struct trace_iterator *iter, struct trace_seq *s, if (type) { /* Interrupt */ - ret = print_graph_irq(iter, addr, type, cpu, ent->pid); + ret = print_graph_irq(iter, addr, type, cpu, ent->pid, flags); if (ret == TRACE_TYPE_PARTIAL_LINE) return TRACE_TYPE_PARTIAL_LINE; } /* Absolute time */ - if (tracer_flags.val & TRACE_GRAPH_PRINT_ABS_TIME) { + if (flags & TRACE_GRAPH_PRINT_ABS_TIME) { ret = print_graph_abs_time(iter->ts, s); if (!ret) return TRACE_TYPE_PARTIAL_LINE; } /* Cpu */ - if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU) { + if (flags & TRACE_GRAPH_PRINT_CPU) { ret = print_graph_cpu(s, cpu); if (ret == TRACE_TYPE_PARTIAL_LINE) return TRACE_TYPE_PARTIAL_LINE; } /* Proc */ - if (tracer_flags.val & TRACE_GRAPH_PRINT_PROC) { + if (flags & TRACE_GRAPH_PRINT_PROC) { ret = print_graph_proc(s, ent->pid); if (ret == TRACE_TYPE_PARTIAL_LINE) return TRACE_TYPE_PARTIAL_LINE; @@ -846,7 +848,7 @@ print_graph_prologue(struct trace_iterator *iter, struct trace_seq *s, static enum print_line_t print_graph_entry(struct ftrace_graph_ent_entry *field, struct trace_seq *s, - struct trace_iterator *iter) + struct trace_iterator *iter, u32 flags) { struct fgraph_data *data = iter->private; struct ftrace_graph_ent *call = &field->graph_ent; @@ -854,14 +856,14 @@ print_graph_entry(struct ftrace_graph_ent_entry *field, struct trace_seq *s, static enum print_line_t ret; int cpu = iter->cpu; - if (print_graph_prologue(iter, s, TRACE_GRAPH_ENT, call->func)) + if (print_graph_prologue(iter, s, TRACE_GRAPH_ENT, call->func, flags)) return TRACE_TYPE_PARTIAL_LINE; leaf_ret = get_return_for_leaf(iter, field); if (leaf_ret) - ret = print_graph_entry_leaf(iter, field, leaf_ret, s); + ret = print_graph_entry_leaf(iter, field, leaf_ret, s, flags); else - ret = print_graph_entry_nested(iter, field, s, cpu); + ret = print_graph_entry_nested(iter, field, s, cpu, flags); if (data) { /* @@ -880,7 +882,8 @@ print_graph_entry(struct ftrace_graph_ent_entry *field, struct trace_seq *s, static enum print_line_t print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s, - struct trace_entry *ent, struct trace_iterator *iter) + struct trace_entry *ent, struct trace_iterator *iter, + u32 flags) { unsigned long long duration = trace->rettime - trace->calltime; struct fgraph_data *data = iter->private; @@ -910,16 +913,16 @@ print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s, } } - if (print_graph_prologue(iter, s, 0, 0)) + if (print_graph_prologue(iter, s, 0, 0, flags)) return TRACE_TYPE_PARTIAL_LINE; /* Overhead */ - ret = print_graph_overhead(duration, s); + ret = print_graph_overhead(duration, s, flags); if (!ret) return TRACE_TYPE_PARTIAL_LINE; /* Duration */ - if (tracer_flags.val & TRACE_GRAPH_PRINT_DURATION) { + if (flags & TRACE_GRAPH_PRINT_DURATION) { ret = print_graph_duration(duration, s); if (ret == TRACE_TYPE_PARTIAL_LINE) return TRACE_TYPE_PARTIAL_LINE; @@ -949,14 +952,15 @@ print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s, } /* Overrun */ - if (tracer_flags.val & TRACE_GRAPH_PRINT_OVERRUN) { + if (flags & TRACE_GRAPH_PRINT_OVERRUN) { ret = trace_seq_printf(s, " (Overruns: %lu)\n", trace->overrun); if (!ret) return TRACE_TYPE_PARTIAL_LINE; } - ret = print_graph_irq(iter, trace->func, TRACE_GRAPH_RET, cpu, pid); + ret = print_graph_irq(iter, trace->func, TRACE_GRAPH_RET, + cpu, pid, flags); if (ret == TRACE_TYPE_PARTIAL_LINE) return TRACE_TYPE_PARTIAL_LINE; @@ -964,8 +968,8 @@ print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s, } static enum print_line_t -print_graph_comment(struct trace_seq *s, struct trace_entry *ent, - struct trace_iterator *iter) +print_graph_comment(struct trace_seq *s, struct trace_entry *ent, + struct trace_iterator *iter, u32 flags) { unsigned long sym_flags = (trace_flags & TRACE_ITER_SYM_MASK); struct fgraph_data *data = iter->private; @@ -977,16 +981,16 @@ print_graph_comment(struct trace_seq *s, struct trace_entry *ent, if (data) depth = per_cpu_ptr(data->cpu_data, iter->cpu)->depth; - if (print_graph_prologue(iter, s, 0, 0)) + if (print_graph_prologue(iter, s, 0, 0, flags)) return TRACE_TYPE_PARTIAL_LINE; /* No overhead */ - ret = print_graph_overhead(-1, s); + ret = print_graph_overhead(-1, s, flags); if (!ret) return TRACE_TYPE_PARTIAL_LINE; /* No time */ - if (tracer_flags.val & TRACE_GRAPH_PRINT_DURATION) { + if (flags & TRACE_GRAPH_PRINT_DURATION) { ret = trace_seq_printf(s, " | "); if (!ret) return TRACE_TYPE_PARTIAL_LINE; @@ -1041,7 +1045,7 @@ print_graph_comment(struct trace_seq *s, struct trace_entry *ent, enum print_line_t -print_graph_function(struct trace_iterator *iter) +print_graph_function_flags(struct trace_iterator *iter, u32 flags) { struct ftrace_graph_ent_entry *field; struct fgraph_data *data = iter->private; @@ -1062,7 +1066,7 @@ print_graph_function(struct trace_iterator *iter) if (data && data->failed) { field = &data->ent; iter->cpu = data->cpu; - ret = print_graph_entry(field, s, iter); + ret = print_graph_entry(field, s, iter, flags); if (ret == TRACE_TYPE_HANDLED && iter->cpu != cpu) { per_cpu_ptr(data->cpu_data, iter->cpu)->ignore = 1; ret = TRACE_TYPE_NO_CONSUME; @@ -1082,38 +1086,44 @@ print_graph_function(struct trace_iterator *iter) struct ftrace_graph_ent_entry saved; trace_assign_type(field, entry); saved = *field; - return print_graph_entry(&saved, s, iter); + return print_graph_entry(&saved, s, iter, flags); } case TRACE_GRAPH_RET: { struct ftrace_graph_ret_entry *field; trace_assign_type(field, entry); - return print_graph_return(&field->ret, s, entry, iter); + return print_graph_return(&field->ret, s, entry, iter, flags); } default: - return print_graph_comment(s, entry, iter); + return print_graph_comment(s, entry, iter, flags); } return TRACE_TYPE_HANDLED; } static enum print_line_t +print_graph_function(struct trace_iterator *iter) +{ + return print_graph_function_flags(iter, tracer_flags.val); +} + +static enum print_line_t print_graph_function_event(struct trace_iterator *iter, int flags) { return print_graph_function(iter); } -static void print_lat_header(struct seq_file *s) +static void print_lat_header(struct seq_file *s, u32 flags) { static const char spaces[] = " " /* 16 spaces */ " " /* 4 spaces */ " "; /* 17 spaces */ int size = 0; - if (tracer_flags.val & TRACE_GRAPH_PRINT_ABS_TIME) + if (flags & TRACE_GRAPH_PRINT_ABS_TIME) size += 16; - if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU) + if (flags & TRACE_GRAPH_PRINT_CPU) size += 4; - if (tracer_flags.val & TRACE_GRAPH_PRINT_PROC) + if (flags & TRACE_GRAPH_PRINT_PROC) size += 17; seq_printf(s, "#%.*s _-----=> irqs-off \n", size, spaces); @@ -1124,42 +1134,47 @@ static void print_lat_header(struct seq_file *s) seq_printf(s, "#%.*s|||| / \n", size, spaces); } -static void print_graph_headers(struct seq_file *s) +void print_graph_headers_flags(struct seq_file *s, u32 flags) { int lat = trace_flags & TRACE_ITER_LATENCY_FMT; if (lat) - print_lat_header(s); + print_lat_header(s, flags); /* 1st line */ seq_printf(s, "#"); - if (tracer_flags.val & TRACE_GRAPH_PRINT_ABS_TIME) + if (flags & TRACE_GRAPH_PRINT_ABS_TIME) seq_printf(s, " TIME "); - if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU) + if (flags & TRACE_GRAPH_PRINT_CPU) seq_printf(s, " CPU"); - if (tracer_flags.val & TRACE_GRAPH_PRINT_PROC) + if (flags & TRACE_GRAPH_PRINT_PROC) seq_printf(s, " TASK/PID "); if (lat) seq_printf(s, "|||||"); - if (tracer_flags.val & TRACE_GRAPH_PRINT_DURATION) + if (flags & TRACE_GRAPH_PRINT_DURATION) seq_printf(s, " DURATION "); seq_printf(s, " FUNCTION CALLS\n"); /* 2nd line */ seq_printf(s, "#"); - if (tracer_flags.val & TRACE_GRAPH_PRINT_ABS_TIME) + if (flags & TRACE_GRAPH_PRINT_ABS_TIME) seq_printf(s, " | "); - if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU) + if (flags & TRACE_GRAPH_PRINT_CPU) seq_printf(s, " | "); - if (tracer_flags.val & TRACE_GRAPH_PRINT_PROC) + if (flags & TRACE_GRAPH_PRINT_PROC) seq_printf(s, " | | "); if (lat) seq_printf(s, "|||||"); - if (tracer_flags.val & TRACE_GRAPH_PRINT_DURATION) + if (flags & TRACE_GRAPH_PRINT_DURATION) seq_printf(s, " | | "); seq_printf(s, " | | | |\n"); } +static void print_graph_headers(struct seq_file *s) +{ + print_graph_headers_flags(s, tracer_flags.val); +} + static void graph_trace_open(struct trace_iterator *iter) { /* pid and depth on the last trace processed */ -- cgit v0.10.2 From b8bc1389b74c2b66255651a6fcfae56c78b6e63f Mon Sep 17 00:00:00 2001 From: Alessio Igor Bogani Date: Sun, 25 Apr 2010 13:18:48 +0200 Subject: ptrace: Cleanup useless header BKL isn't present anymore into this file thus we can safely remove smp_lock.h inclusion. Signed-off-by: Alessio Igor Bogani Cc: Roland McGrath Cc: Oleg Nesterov Cc: Andrew Morton Cc: James Morris Cc: Ingo Molnar Signed-off-by: Frederic Weisbecker diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 5357502..2f0f50b 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include -- cgit v0.10.2 From 9bf67e516f16d31f86aa6f063576a959bbf19990 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Sat, 24 Apr 2010 07:57:46 -0400 Subject: cifs: save the dialect chosen by server Signed-off-by: Jeff Layton Signed-off-by: Steve French diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 4a2715b..c412568 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -185,6 +185,7 @@ struct TCP_Server_Info { struct mac_key mac_signing_key; char ntlmv2_hash[16]; unsigned long lstrp; /* when we got last response from this server */ + u16 dialect; /* dialect index that server chose */ }; /* diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 4ecb361..1372253 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -355,7 +355,6 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) struct TCP_Server_Info *server; u16 count; unsigned int secFlags; - u16 dialect; if (ses->server) server = ses->server; @@ -408,10 +407,10 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) if (rc != 0) goto neg_err_exit; - dialect = le16_to_cpu(pSMBr->DialectIndex); - cFYI(1, "Dialect: %d", dialect); + server->dialect = le16_to_cpu(pSMBr->DialectIndex); + cFYI(1, "Dialect: %d", server->dialect); /* Check wct = 1 error case */ - if ((pSMBr->hdr.WordCount < 13) || (dialect == BAD_PROT)) { + if ((pSMBr->hdr.WordCount < 13) || (server->dialect == BAD_PROT)) { /* core returns wct = 1, but we do not ask for core - otherwise small wct just comes when dialect index is -1 indicating we could not negotiate a common dialect */ @@ -419,8 +418,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) goto neg_err_exit; #ifdef CONFIG_CIFS_WEAK_PW_HASH } else if ((pSMBr->hdr.WordCount == 13) - && ((dialect == LANMAN_PROT) - || (dialect == LANMAN2_PROT))) { + && ((server->dialect == LANMAN_PROT) + || (server->dialect == LANMAN2_PROT))) { __s16 tmp; struct lanman_neg_rsp *rsp = (struct lanman_neg_rsp *)pSMBr; -- cgit v0.10.2 From d54ff73259a852d4b3886dc586587fdef5e9c8de Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 27 Apr 2010 04:38:15 +0000 Subject: [CIFS] Fix lease break for writes On lease break we were breaking to readonly leases always even if write requested. Also removed experimental ifdef around setlease code Signed-off-by: Steve French diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 440e98c..80a9356 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -645,7 +645,6 @@ static loff_t cifs_llseek(struct file *file, loff_t offset, int origin) return generic_file_llseek_unlocked(file, offset, origin); } -#ifdef CONFIG_CIFS_EXPERIMENTAL static int cifs_setlease(struct file *file, long arg, struct file_lock **lease) { /* note that this is called by vfs setlease with the BKL held @@ -674,7 +673,6 @@ static int cifs_setlease(struct file *file, long arg, struct file_lock **lease) else return -EAGAIN; } -#endif struct file_system_type cifs_fs_type = { .owner = THIS_MODULE, @@ -751,10 +749,7 @@ const struct file_operations cifs_file_ops = { #ifdef CONFIG_CIFS_POSIX .unlocked_ioctl = cifs_ioctl, #endif /* CONFIG_CIFS_POSIX */ - -#ifdef CONFIG_CIFS_EXPERIMENTAL .setlease = cifs_setlease, -#endif /* CONFIG_CIFS_EXPERIMENTAL */ }; const struct file_operations cifs_file_direct_ops = { @@ -773,9 +768,7 @@ const struct file_operations cifs_file_direct_ops = { .unlocked_ioctl = cifs_ioctl, #endif /* CONFIG_CIFS_POSIX */ .llseek = cifs_llseek, -#ifdef CONFIG_CIFS_EXPERIMENTAL .setlease = cifs_setlease, -#endif /* CONFIG_CIFS_EXPERIMENTAL */ }; const struct file_operations cifs_file_nobrl_ops = { .read = do_sync_read, @@ -792,10 +785,7 @@ const struct file_operations cifs_file_nobrl_ops = { #ifdef CONFIG_CIFS_POSIX .unlocked_ioctl = cifs_ioctl, #endif /* CONFIG_CIFS_POSIX */ - -#ifdef CONFIG_CIFS_EXPERIMENTAL .setlease = cifs_setlease, -#endif /* CONFIG_CIFS_EXPERIMENTAL */ }; const struct file_operations cifs_file_direct_nobrl_ops = { @@ -813,9 +803,7 @@ const struct file_operations cifs_file_direct_nobrl_ops = { .unlocked_ioctl = cifs_ioctl, #endif /* CONFIG_CIFS_POSIX */ .llseek = cifs_llseek, -#ifdef CONFIG_CIFS_EXPERIMENTAL .setlease = cifs_setlease, -#endif /* CONFIG_CIFS_EXPERIMENTAL */ }; const struct file_operations cifs_dir_ops = { diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index dac7602..0242ff9 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -114,5 +114,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); extern const struct export_operations cifs_export_ops; #endif /* EXPERIMENTAL */ -#define CIFS_VERSION "1.63" +#define CIFS_VERSION "1.64" #endif /* _CIFSFS_H */ diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 5f1f768..d53d630 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -2306,12 +2306,10 @@ cifs_oplock_break(struct slow_work *work) int rc, waitrc = 0; if (inode && S_ISREG(inode->i_mode)) { -#ifdef CONFIG_CIFS_EXPERIMENTAL - if (cinode->clientCanCacheAll == 0) + if (cinode->clientCanCacheRead) break_lease(inode, O_RDONLY); - else if (cinode->clientCanCacheRead == 0) + else break_lease(inode, O_WRONLY); -#endif rc = filemap_fdatawrite(inode->i_mapping); if (cinode->clientCanCacheRead == 0) { waitrc = filemap_fdatawait(inode->i_mapping); -- cgit v0.10.2 From b7386a09ce7e8add333f5d67f2fe1b1eac1f4746 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 27 Apr 2010 16:41:12 +0900 Subject: sh: make latencytop available on SMP, too. The UP dependency was inherited from ARM, which seems to have run in to it due to the stacktrace code not being available for SMP in certain cases, as we don't have this particular limitation there is no specific need to block on the SMP dependency. Signed-off-by: Paul Mundt diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index d73bd4d..c497307 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -157,7 +157,6 @@ config LOCKDEP_SUPPORT config HAVE_LATENCYTOP_SUPPORT def_bool y - depends on !SMP config ARCH_HAS_ILOG2_U32 def_bool n -- cgit v0.10.2 From 5a38f2c7c4dd53d5be097930902c108e362584a3 Mon Sep 17 00:00:00 2001 From: Alan Ott Date: Mon, 26 Apr 2010 18:34:46 -0400 Subject: HID: hidraw: fix numbered reports Make hidraw not stick an extra byte on the beginning of an IN transfer when a HID device contains multiple reports. Signed-off-by: Alan Ott Acked-by: Jiri Slaby Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index d25152b..143e788 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1043,13 +1043,8 @@ void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size, if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event) hid->hiddev_report_event(hid, report); - if (hid->claimed & HID_CLAIMED_HIDRAW) { - /* numbered reports need to be passed with the report num */ - if (report_enum->numbered) - hidraw_report_event(hid, data - 1, size + 1); - else - hidraw_report_event(hid, data, size); - } + if (hid->claimed & HID_CLAIMED_HIDRAW) + hidraw_report_event(hid, data, size); for (a = 0; a < report->maxfield; a++) hid_input_field(hid, report->field[a], cdata, interrupt); -- cgit v0.10.2 From a3be6327163c223c1715c8307a616941fbf8bf73 Mon Sep 17 00:00:00 2001 From: Hans Ulli Kroll Date: Tue, 27 Apr 2010 12:45:10 +0200 Subject: ARM: Gemini: fix compiler error in copypage-fa.c Fix compiler error in copypage-fs.c missing struct vm_area_struct *vma in function fa_copy_user_highpage Signed-off-by: Hans Ulli Kroll diff --git a/arch/arm/mm/copypage-fa.c b/arch/arm/mm/copypage-fa.c index b2a6008..d2852e1 100644 --- a/arch/arm/mm/copypage-fa.c +++ b/arch/arm/mm/copypage-fa.c @@ -40,7 +40,7 @@ fa_copy_user_page(void *kto, const void *kfrom) } void fa_copy_user_highpage(struct page *to, struct page *from, - unsigned long vaddr) + unsigned long vaddr, struct vm_area_struct *vma) { void *kto, *kfrom; -- cgit v0.10.2 From 62b915f1060996a8e1f69be50e3b8e9e43b710cb Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 2 Apr 2010 19:01:22 +0200 Subject: tracing: Add graph output support for irqsoff tracer Add function graph output to irqsoff tracer. The graph output is enabled by setting new 'display-graph' trace option. Signed-off-by: Jiri Olsa LKML-Reference: <1270227683-14631-4-git-send-email-jolsa@redhat.com> Signed-off-by: Steven Rostedt diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index ea5b1aa..8415a52 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h @@ -352,6 +352,10 @@ struct ftrace_graph_ret { int depth; }; +/* Type of the callback handlers for tracing function graph*/ +typedef void (*trace_func_graph_ret_t)(struct ftrace_graph_ret *); /* return */ +typedef int (*trace_func_graph_ent_t)(struct ftrace_graph_ent *); /* entry */ + #ifdef CONFIG_FUNCTION_GRAPH_TRACER /* for init task */ @@ -400,10 +404,6 @@ extern char __irqentry_text_end[]; #define FTRACE_RETFUNC_DEPTH 50 #define FTRACE_RETSTACK_ALLOC_SIZE 32 -/* Type of the callback handlers for tracing function graph*/ -typedef void (*trace_func_graph_ret_t)(struct ftrace_graph_ret *); /* return */ -typedef int (*trace_func_graph_ent_t)(struct ftrace_graph_ent *); /* entry */ - extern int register_ftrace_graph(trace_func_graph_ret_t retfunc, trace_func_graph_ent_t entryfunc); @@ -441,6 +441,13 @@ static inline void unpause_graph_tracing(void) static inline void ftrace_graph_init_task(struct task_struct *t) { } static inline void ftrace_graph_exit_task(struct task_struct *t) { } +static inline int register_ftrace_graph(trace_func_graph_ret_t retfunc, + trace_func_graph_ent_t entryfunc) +{ + return -1; +} +static inline void unregister_ftrace_graph(void) { } + static inline int task_curr_ret_stack(struct task_struct *tsk) { return -1; diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 7b516c7..8b9ba41 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -1808,7 +1808,7 @@ static void print_func_help_header(struct seq_file *m) } -static void +void print_trace_header(struct seq_file *m, struct trace_iterator *iter) { unsigned long sym_flags = (trace_flags & TRACE_ITER_SYM_MASK); @@ -2017,7 +2017,7 @@ static enum print_line_t print_bin_fmt(struct trace_iterator *iter) return event ? event->binary(iter, 0) : TRACE_TYPE_HANDLED; } -static int trace_empty(struct trace_iterator *iter) +int trace_empty(struct trace_iterator *iter) { int cpu; @@ -2084,6 +2084,23 @@ static enum print_line_t print_trace_line(struct trace_iterator *iter) return print_trace_fmt(iter); } +void trace_default_header(struct seq_file *m) +{ + struct trace_iterator *iter = m->private; + + if (iter->iter_flags & TRACE_FILE_LAT_FMT) { + /* print nothing if the buffers are empty */ + if (trace_empty(iter)) + return; + print_trace_header(m, iter); + if (!(trace_flags & TRACE_ITER_VERBOSE)) + print_lat_help_header(m); + } else { + if (!(trace_flags & TRACE_ITER_VERBOSE)) + print_func_help_header(m); + } +} + static int s_show(struct seq_file *m, void *v) { struct trace_iterator *iter = v; @@ -2096,17 +2113,9 @@ static int s_show(struct seq_file *m, void *v) } if (iter->trace && iter->trace->print_header) iter->trace->print_header(m); - else if (iter->iter_flags & TRACE_FILE_LAT_FMT) { - /* print nothing if the buffers are empty */ - if (trace_empty(iter)) - return 0; - print_trace_header(m, iter); - if (!(trace_flags & TRACE_ITER_VERBOSE)) - print_lat_help_header(m); - } else { - if (!(trace_flags & TRACE_ITER_VERBOSE)) - print_func_help_header(m); - } + else + trace_default_header(m); + } else if (iter->leftover) { /* * If we filled the seq_file buffer earlier, we diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 970004c..911e986 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -378,6 +378,9 @@ void trace_function(struct trace_array *tr, unsigned long ip, unsigned long parent_ip, unsigned long flags, int pc); +void trace_default_header(struct seq_file *m); +void print_trace_header(struct seq_file *m, struct trace_iterator *iter); +int trace_empty(struct trace_iterator *iter); void trace_graph_return(struct ftrace_graph_ret *trace); int trace_graph_entry(struct ftrace_graph_ent *trace); @@ -491,11 +494,29 @@ extern int trace_clock_id; /* Standard output formatting function used for function return traces */ #ifdef CONFIG_FUNCTION_GRAPH_TRACER + +/* Flag options */ +#define TRACE_GRAPH_PRINT_OVERRUN 0x1 +#define TRACE_GRAPH_PRINT_CPU 0x2 +#define TRACE_GRAPH_PRINT_OVERHEAD 0x4 +#define TRACE_GRAPH_PRINT_PROC 0x8 +#define TRACE_GRAPH_PRINT_DURATION 0x10 +#define TRACE_GRAPH_PRINT_ABS_TIME 0x20 + extern enum print_line_t print_graph_function_flags(struct trace_iterator *iter, u32 flags); extern void print_graph_headers_flags(struct seq_file *s, u32 flags); extern enum print_line_t trace_print_graph_duration(unsigned long long duration, struct trace_seq *s); +extern void graph_trace_open(struct trace_iterator *iter); +extern void graph_trace_close(struct trace_iterator *iter); +extern int __trace_graph_entry(struct trace_array *tr, + struct ftrace_graph_ent *trace, + unsigned long flags, int pc); +extern void __trace_graph_return(struct trace_array *tr, + struct ftrace_graph_ret *trace, + unsigned long flags, int pc); + #ifdef CONFIG_DYNAMIC_FTRACE /* TODO: make this variable */ diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c index de5f651..dd11c83 100644 --- a/kernel/trace/trace_functions_graph.c +++ b/kernel/trace/trace_functions_graph.c @@ -179,7 +179,7 @@ unsigned long ftrace_return_to_handler(unsigned long frame_pointer) return ret; } -static int __trace_graph_entry(struct trace_array *tr, +int __trace_graph_entry(struct trace_array *tr, struct ftrace_graph_ent *trace, unsigned long flags, int pc) @@ -246,7 +246,7 @@ int trace_graph_thresh_entry(struct ftrace_graph_ent *trace) return trace_graph_entry(trace); } -static void __trace_graph_return(struct trace_array *tr, +void __trace_graph_return(struct trace_array *tr, struct ftrace_graph_ret *trace, unsigned long flags, int pc) @@ -1093,6 +1093,11 @@ print_graph_function_flags(struct trace_iterator *iter, u32 flags) trace_assign_type(field, entry); return print_graph_return(&field->ret, s, entry, iter, flags); } + case TRACE_STACK: + case TRACE_FN: + /* dont trace stack and functions as comments */ + return TRACE_TYPE_UNHANDLED; + default: return print_graph_comment(s, entry, iter, flags); } @@ -1170,12 +1175,12 @@ void print_graph_headers_flags(struct seq_file *s, u32 flags) seq_printf(s, " | | | |\n"); } -static void print_graph_headers(struct seq_file *s) +void print_graph_headers(struct seq_file *s) { print_graph_headers_flags(s, tracer_flags.val); } -static void graph_trace_open(struct trace_iterator *iter) +void graph_trace_open(struct trace_iterator *iter) { /* pid and depth on the last trace processed */ struct fgraph_data *data; @@ -1210,7 +1215,7 @@ static void graph_trace_open(struct trace_iterator *iter) pr_warning("function graph tracer: not enough memory\n"); } -static void graph_trace_close(struct trace_iterator *iter) +void graph_trace_close(struct trace_iterator *iter) { struct fgraph_data *data = iter->private; diff --git a/kernel/trace/trace_irqsoff.c b/kernel/trace/trace_irqsoff.c index 2974bc7..6fd486e 100644 --- a/kernel/trace/trace_irqsoff.c +++ b/kernel/trace/trace_irqsoff.c @@ -34,6 +34,9 @@ static int trace_type __read_mostly; static int save_lat_flag; +static void stop_irqsoff_tracer(struct trace_array *tr, int graph); +static int start_irqsoff_tracer(struct trace_array *tr, int graph); + #ifdef CONFIG_PREEMPT_TRACER static inline int preempt_trace(void) @@ -55,6 +58,23 @@ irq_trace(void) # define irq_trace() (0) #endif +#define TRACE_DISPLAY_GRAPH 1 + +static struct tracer_opt trace_opts[] = { +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + /* display latency trace as call graph */ + { TRACER_OPT(display-graph, TRACE_DISPLAY_GRAPH) }, +#endif + { } /* Empty entry */ +}; + +static struct tracer_flags tracer_flags = { + .val = 0, + .opts = trace_opts, +}; + +#define is_graph() (tracer_flags.val & TRACE_DISPLAY_GRAPH) + /* * Sequence count - we record it when starting a measurement and * skip the latency if the sequence has changed - some other section @@ -108,6 +128,202 @@ static struct ftrace_ops trace_ops __read_mostly = }; #endif /* CONFIG_FUNCTION_TRACER */ +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +static int irqsoff_set_flag(u32 old_flags, u32 bit, int set) +{ + int cpu; + + if (!(bit & TRACE_DISPLAY_GRAPH)) + return -EINVAL; + + if (!(is_graph() ^ set)) + return 0; + + stop_irqsoff_tracer(irqsoff_trace, !set); + + for_each_possible_cpu(cpu) + per_cpu(tracing_cpu, cpu) = 0; + + tracing_max_latency = 0; + tracing_reset_online_cpus(irqsoff_trace); + + return start_irqsoff_tracer(irqsoff_trace, set); +} + +static int irqsoff_graph_entry(struct ftrace_graph_ent *trace) +{ + struct trace_array *tr = irqsoff_trace; + struct trace_array_cpu *data; + unsigned long flags; + long disabled; + int ret; + int cpu; + int pc; + + cpu = raw_smp_processor_id(); + if (likely(!per_cpu(tracing_cpu, cpu))) + return 0; + + local_save_flags(flags); + /* slight chance to get a false positive on tracing_cpu */ + if (!irqs_disabled_flags(flags)) + return 0; + + data = tr->data[cpu]; + disabled = atomic_inc_return(&data->disabled); + + if (likely(disabled == 1)) { + pc = preempt_count(); + ret = __trace_graph_entry(tr, trace, flags, pc); + } else + ret = 0; + + atomic_dec(&data->disabled); + return ret; +} + +static void irqsoff_graph_return(struct ftrace_graph_ret *trace) +{ + struct trace_array *tr = irqsoff_trace; + struct trace_array_cpu *data; + unsigned long flags; + long disabled; + int cpu; + int pc; + + cpu = raw_smp_processor_id(); + if (likely(!per_cpu(tracing_cpu, cpu))) + return; + + local_save_flags(flags); + /* slight chance to get a false positive on tracing_cpu */ + if (!irqs_disabled_flags(flags)) + return; + + data = tr->data[cpu]; + disabled = atomic_inc_return(&data->disabled); + + if (likely(disabled == 1)) { + pc = preempt_count(); + __trace_graph_return(tr, trace, flags, pc); + } + + atomic_dec(&data->disabled); +} + +static void irqsoff_trace_open(struct trace_iterator *iter) +{ + if (is_graph()) + graph_trace_open(iter); + +} + +static void irqsoff_trace_close(struct trace_iterator *iter) +{ + if (iter->private) + graph_trace_close(iter); +} + +#define GRAPH_TRACER_FLAGS (TRACE_GRAPH_PRINT_CPU | \ + TRACE_GRAPH_PRINT_PROC) + +static enum print_line_t irqsoff_print_line(struct trace_iterator *iter) +{ + u32 flags = GRAPH_TRACER_FLAGS; + + if (trace_flags & TRACE_ITER_LATENCY_FMT) + flags |= TRACE_GRAPH_PRINT_DURATION; + else + flags |= TRACE_GRAPH_PRINT_ABS_TIME; + + /* + * In graph mode call the graph tracer output function, + * otherwise go with the TRACE_FN event handler + */ + if (is_graph()) + return print_graph_function_flags(iter, flags); + + return TRACE_TYPE_UNHANDLED; +} + +static void irqsoff_print_header(struct seq_file *s) +{ + if (is_graph()) { + struct trace_iterator *iter = s->private; + u32 flags = GRAPH_TRACER_FLAGS; + + if (trace_flags & TRACE_ITER_LATENCY_FMT) { + /* print nothing if the buffers are empty */ + if (trace_empty(iter)) + return; + + print_trace_header(s, iter); + flags |= TRACE_GRAPH_PRINT_DURATION; + } else + flags |= TRACE_GRAPH_PRINT_ABS_TIME; + + print_graph_headers_flags(s, flags); + } else + trace_default_header(s); +} + +static void +trace_graph_function(struct trace_array *tr, + unsigned long ip, unsigned long flags, int pc) +{ + u64 time = trace_clock_local(); + struct ftrace_graph_ent ent = { + .func = ip, + .depth = 0, + }; + struct ftrace_graph_ret ret = { + .func = ip, + .depth = 0, + .calltime = time, + .rettime = time, + }; + + __trace_graph_entry(tr, &ent, flags, pc); + __trace_graph_return(tr, &ret, flags, pc); +} + +static void +__trace_function(struct trace_array *tr, + unsigned long ip, unsigned long parent_ip, + unsigned long flags, int pc) +{ + if (!is_graph()) + trace_function(tr, ip, parent_ip, flags, pc); + else { + trace_graph_function(tr, parent_ip, flags, pc); + trace_graph_function(tr, ip, flags, pc); + } +} + +#else +#define __trace_function trace_function + +static int irqsoff_set_flag(u32 old_flags, u32 bit, int set) +{ + return -EINVAL; +} + +static int irqsoff_graph_entry(struct ftrace_graph_ent *trace) +{ + return -1; +} + +static enum print_line_t irqsoff_print_line(struct trace_iterator *iter) +{ + return TRACE_TYPE_UNHANDLED; +} + +static void irqsoff_graph_return(struct ftrace_graph_ret *trace) { } +static void irqsoff_print_header(struct seq_file *s) { } +static void irqsoff_trace_open(struct trace_iterator *iter) { } +static void irqsoff_trace_close(struct trace_iterator *iter) { } +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ + /* * Should this new latency be reported/recorded? */ @@ -150,7 +366,7 @@ check_critical_timing(struct trace_array *tr, if (!report_latency(delta)) goto out_unlock; - trace_function(tr, CALLER_ADDR0, parent_ip, flags, pc); + __trace_function(tr, CALLER_ADDR0, parent_ip, flags, pc); /* Skip 5 functions to get to the irq/preempt enable function */ __trace_stack(tr, flags, 5, pc); @@ -172,7 +388,7 @@ out_unlock: out: data->critical_sequence = max_sequence; data->preempt_timestamp = ftrace_now(cpu); - trace_function(tr, CALLER_ADDR0, parent_ip, flags, pc); + __trace_function(tr, CALLER_ADDR0, parent_ip, flags, pc); } static inline void @@ -204,7 +420,7 @@ start_critical_timing(unsigned long ip, unsigned long parent_ip) local_save_flags(flags); - trace_function(tr, ip, parent_ip, flags, preempt_count()); + __trace_function(tr, ip, parent_ip, flags, preempt_count()); per_cpu(tracing_cpu, cpu) = 1; @@ -238,7 +454,7 @@ stop_critical_timing(unsigned long ip, unsigned long parent_ip) atomic_inc(&data->disabled); local_save_flags(flags); - trace_function(tr, ip, parent_ip, flags, preempt_count()); + __trace_function(tr, ip, parent_ip, flags, preempt_count()); check_critical_timing(tr, data, parent_ip ? : ip, cpu); data->critical_start = 0; atomic_dec(&data->disabled); @@ -347,19 +563,32 @@ void trace_preempt_off(unsigned long a0, unsigned long a1) } #endif /* CONFIG_PREEMPT_TRACER */ -static void start_irqsoff_tracer(struct trace_array *tr) +static int start_irqsoff_tracer(struct trace_array *tr, int graph) { - register_ftrace_function(&trace_ops); - if (tracing_is_enabled()) + int ret = 0; + + if (!graph) + ret = register_ftrace_function(&trace_ops); + else + ret = register_ftrace_graph(&irqsoff_graph_return, + &irqsoff_graph_entry); + + if (!ret && tracing_is_enabled()) tracer_enabled = 1; else tracer_enabled = 0; + + return ret; } -static void stop_irqsoff_tracer(struct trace_array *tr) +static void stop_irqsoff_tracer(struct trace_array *tr, int graph) { tracer_enabled = 0; - unregister_ftrace_function(&trace_ops); + + if (!graph) + unregister_ftrace_function(&trace_ops); + else + unregister_ftrace_graph(); } static void __irqsoff_tracer_init(struct trace_array *tr) @@ -372,12 +601,14 @@ static void __irqsoff_tracer_init(struct trace_array *tr) /* make sure that the tracer is visible */ smp_wmb(); tracing_reset_online_cpus(tr); - start_irqsoff_tracer(tr); + + if (start_irqsoff_tracer(tr, is_graph())) + printk(KERN_ERR "failed to start irqsoff tracer\n"); } static void irqsoff_tracer_reset(struct trace_array *tr) { - stop_irqsoff_tracer(tr); + stop_irqsoff_tracer(tr, is_graph()); if (!save_lat_flag) trace_flags &= ~TRACE_ITER_LATENCY_FMT; @@ -409,9 +640,15 @@ static struct tracer irqsoff_tracer __read_mostly = .start = irqsoff_tracer_start, .stop = irqsoff_tracer_stop, .print_max = 1, + .print_header = irqsoff_print_header, + .print_line = irqsoff_print_line, + .flags = &tracer_flags, + .set_flag = irqsoff_set_flag, #ifdef CONFIG_FTRACE_SELFTEST .selftest = trace_selftest_startup_irqsoff, #endif + .open = irqsoff_trace_open, + .close = irqsoff_trace_close, }; # define register_irqsoff(trace) register_tracer(&trace) #else @@ -435,9 +672,15 @@ static struct tracer preemptoff_tracer __read_mostly = .start = irqsoff_tracer_start, .stop = irqsoff_tracer_stop, .print_max = 1, + .print_header = irqsoff_print_header, + .print_line = irqsoff_print_line, + .flags = &tracer_flags, + .set_flag = irqsoff_set_flag, #ifdef CONFIG_FTRACE_SELFTEST .selftest = trace_selftest_startup_preemptoff, #endif + .open = irqsoff_trace_open, + .close = irqsoff_trace_close, }; # define register_preemptoff(trace) register_tracer(&trace) #else @@ -463,9 +706,15 @@ static struct tracer preemptirqsoff_tracer __read_mostly = .start = irqsoff_tracer_start, .stop = irqsoff_tracer_stop, .print_max = 1, + .print_header = irqsoff_print_header, + .print_line = irqsoff_print_line, + .flags = &tracer_flags, + .set_flag = irqsoff_set_flag, #ifdef CONFIG_FTRACE_SELFTEST .selftest = trace_selftest_startup_preemptirqsoff, #endif + .open = irqsoff_trace_open, + .close = irqsoff_trace_close, }; # define register_preemptirqsoff(trace) register_tracer(&trace) -- cgit v0.10.2 From 72c9ddfd4c5bf54ef03cfdf57026416cb678eeba Mon Sep 17 00:00:00 2001 From: David Miller Date: Tue, 20 Apr 2010 15:47:11 -0700 Subject: ring-buffer: Make non-consuming read less expensive with lots of cpus. When performing a non-consuming read, a synchronize_sched() is performed once for every cpu which is actively tracing. This is very expensive, and can make it take several seconds to open up the 'trace' file with lots of cpus. Only one synchronize_sched() call is actually necessary. What is desired is for all cpus to see the disabling state change. So we transform the existing sequence: for_each_cpu() { ring_buffer_read_start(); } where each ring_buffer_start() call performs a synchronize_sched(), into the following: for_each_cpu() { ring_buffer_read_prepare(); } ring_buffer_read_prepare_sync(); for_each_cpu() { ring_buffer_read_start(); } wherein only the single ring_buffer_read_prepare_sync() call needs to do the synchronize_sched(). The first phase, via ring_buffer_read_prepare(), allocates the 'iter' memory and increments ->record_disabled. In the second phase, ring_buffer_read_prepare_sync() makes sure this ->record_disabled state is visible fully to all cpus. And in the final third phase, the ring_buffer_read_start() calls reset the 'iter' objects allocated in the first phase since we now know that none of the cpus are adding trace entries any more. This makes openning the 'trace' file nearly instantaneous on a sparc64 Niagara2 box with 128 cpus tracing. Signed-off-by: David S. Miller LKML-Reference: <20100420.154711.11246950.davem@davemloft.net> Signed-off-by: Steven Rostedt diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h index c829776..25b4f68 100644 --- a/include/linux/ring_buffer.h +++ b/include/linux/ring_buffer.h @@ -127,7 +127,9 @@ ring_buffer_consume(struct ring_buffer *buffer, int cpu, u64 *ts, unsigned long *lost_events); struct ring_buffer_iter * -ring_buffer_read_start(struct ring_buffer *buffer, int cpu); +ring_buffer_read_prepare(struct ring_buffer *buffer, int cpu); +void ring_buffer_read_prepare_sync(void); +void ring_buffer_read_start(struct ring_buffer_iter *iter); void ring_buffer_read_finish(struct ring_buffer_iter *iter); struct ring_buffer_event * diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 5885cdf..2a09044 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -3332,23 +3332,30 @@ ring_buffer_consume(struct ring_buffer *buffer, int cpu, u64 *ts, EXPORT_SYMBOL_GPL(ring_buffer_consume); /** - * ring_buffer_read_start - start a non consuming read of the buffer + * ring_buffer_read_prepare - Prepare for a non consuming read of the buffer * @buffer: The ring buffer to read from * @cpu: The cpu buffer to iterate over * - * This starts up an iteration through the buffer. It also disables - * the recording to the buffer until the reading is finished. - * This prevents the reading from being corrupted. This is not - * a consuming read, so a producer is not expected. + * This performs the initial preparations necessary to iterate + * through the buffer. Memory is allocated, buffer recording + * is disabled, and the iterator pointer is returned to the caller. * - * Must be paired with ring_buffer_finish. + * Disabling buffer recordng prevents the reading from being + * corrupted. This is not a consuming read, so a producer is not + * expected. + * + * After a sequence of ring_buffer_read_prepare calls, the user is + * expected to make at least one call to ring_buffer_prepare_sync. + * Afterwards, ring_buffer_read_start is invoked to get things going + * for real. + * + * This overall must be paired with ring_buffer_finish. */ struct ring_buffer_iter * -ring_buffer_read_start(struct ring_buffer *buffer, int cpu) +ring_buffer_read_prepare(struct ring_buffer *buffer, int cpu) { struct ring_buffer_per_cpu *cpu_buffer; struct ring_buffer_iter *iter; - unsigned long flags; if (!cpumask_test_cpu(cpu, buffer->cpumask)) return NULL; @@ -3362,15 +3369,52 @@ ring_buffer_read_start(struct ring_buffer *buffer, int cpu) iter->cpu_buffer = cpu_buffer; atomic_inc(&cpu_buffer->record_disabled); + + return iter; +} +EXPORT_SYMBOL_GPL(ring_buffer_read_prepare); + +/** + * ring_buffer_read_prepare_sync - Synchronize a set of prepare calls + * + * All previously invoked ring_buffer_read_prepare calls to prepare + * iterators will be synchronized. Afterwards, read_buffer_read_start + * calls on those iterators are allowed. + */ +void +ring_buffer_read_prepare_sync(void) +{ synchronize_sched(); +} +EXPORT_SYMBOL_GPL(ring_buffer_read_prepare_sync); + +/** + * ring_buffer_read_start - start a non consuming read of the buffer + * @iter: The iterator returned by ring_buffer_read_prepare + * + * This finalizes the startup of an iteration through the buffer. + * The iterator comes from a call to ring_buffer_read_prepare and + * an intervening ring_buffer_read_prepare_sync must have been + * performed. + * + * Must be paired with ring_buffer_finish. + */ +void +ring_buffer_read_start(struct ring_buffer_iter *iter) +{ + struct ring_buffer_per_cpu *cpu_buffer; + unsigned long flags; + + if (!iter) + return; + + cpu_buffer = iter->cpu_buffer; spin_lock_irqsave(&cpu_buffer->reader_lock, flags); arch_spin_lock(&cpu_buffer->lock); rb_iter_reset(iter); arch_spin_unlock(&cpu_buffer->lock); spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); - - return iter; } EXPORT_SYMBOL_GPL(ring_buffer_read_start); diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 8b9ba41..756d728 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -2201,15 +2201,20 @@ __tracing_open(struct inode *inode, struct file *file) if (iter->cpu_file == TRACE_PIPE_ALL_CPU) { for_each_tracing_cpu(cpu) { - iter->buffer_iter[cpu] = - ring_buffer_read_start(iter->tr->buffer, cpu); + ring_buffer_read_prepare(iter->tr->buffer, cpu); + } + ring_buffer_read_prepare_sync(); + for_each_tracing_cpu(cpu) { + ring_buffer_read_start(iter->buffer_iter[cpu]); tracing_iter_reset(iter, cpu); } } else { cpu = iter->cpu_file; iter->buffer_iter[cpu] = - ring_buffer_read_start(iter->tr->buffer, cpu); + ring_buffer_read_prepare(iter->tr->buffer, cpu); + ring_buffer_read_prepare_sync(); + ring_buffer_read_start(iter->buffer_iter[cpu]); tracing_iter_reset(iter, cpu); } -- cgit v0.10.2 From a838b2e634405fb89ddbf4fa9412acb33911911f Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 27 Apr 2010 13:26:58 -0400 Subject: ring-buffer: Make benchmark handle missed events With the addition of the "missed events" flags that is stored in the commit field of the ring buffer page, the ring_buffer_benchmark was not updated to handle this. If events are missed, then the missed events flag is set in the ring buffer page, the benchmark will count that flag as part of the size of the page and will hit the BUG() when it tries to read beyond the page. The solution is simply to have the ring buffer benchmark mask off the extra bits. Reported-by: Ingo Molnar Signed-off-by: Steven Rostedt diff --git a/kernel/trace/ring_buffer_benchmark.c b/kernel/trace/ring_buffer_benchmark.c index dc56556..302f8a6 100644 --- a/kernel/trace/ring_buffer_benchmark.c +++ b/kernel/trace/ring_buffer_benchmark.c @@ -113,7 +113,8 @@ static enum event_status read_page(int cpu) ret = ring_buffer_read_page(buffer, &bpage, PAGE_SIZE, cpu, 1); if (ret >= 0) { rpage = bpage; - commit = local_read(&rpage->commit); + /* The commit may have missed event flags set, clear them */ + commit = local_read(&rpage->commit) & 0xfffff; for (i = 0; i < commit && !kill_test; i += inc) { if (i >= (PAGE_SIZE - offsetof(struct rb_page, data))) { -- cgit v0.10.2 From 07271aa42d13378e67ebd79ea9ca1c4a5e2ad46f Mon Sep 17 00:00:00 2001 From: Chase Douglas Date: Fri, 23 Apr 2010 14:02:39 -0400 Subject: tracing: Add documentation for trace commands mod, traceon/traceoff The mod command went in as commit 64e7c440618998fd69eee6ab490b042d12248021 The traceon/traceoff commands went in as commit 23b4ff3aa479c9e3bb23cb6b2d0a97878399784a Signed-off-by: Chase Douglas LKML-Reference: <1272045759-32018-1-git-send-email-chase.douglas@canonical.com> Signed-off-by: Steven Rostedt diff --git a/Documentation/trace/ftrace.txt b/Documentation/trace/ftrace.txt index 5201181..557c1ed 100644 --- a/Documentation/trace/ftrace.txt +++ b/Documentation/trace/ftrace.txt @@ -155,6 +155,9 @@ of ftrace. Here is a list of some of the key files: to be traced. Echoing names of functions into this file will limit the trace to only those functions. + This interface also allows for commands to be used. See the + "Filter commands" section for more details. + set_ftrace_notrace: This has an effect opposite to that of @@ -1824,6 +1827,47 @@ this special filter via: echo > set_graph_function +Filter commands +--------------- + +A few commands are supported by the set_ftrace_filter interface. +Trace commands have the following format: + +:: + +The following commands are supported: + +- mod + This command enables function filtering per module. The + parameter defines the module. For example, if only the write* + functions in the ext3 module are desired, run: + + echo 'write*:mod:ext3' > set_ftrace_filter + + This command interacts with the filter in the same way as + filtering based on function names. Thus, adding more functions + in a different module is accomplished by appending (>>) to the + filter file. Remove specific module functions by prepending + '!': + + echo '!writeback*:mod:ext3' >> set_ftrace_filter + +- traceon/traceoff + These commands turn tracing on and off when the specified + functions are hit. The parameter determines how many times the + tracing system is turned on and off. If unspecified, there is + no limit. For example, to disable tracing when a schedule bug + is hit the first 5 times, run: + + echo '__schedule_bug:traceoff:5' > set_ftrace_filter + + These commands are cumulative whether or not they are appended + to set_ftrace_filter. To remove a command, prepend it by '!' + and drop the parameter: + + echo '!__schedule_bug:traceoff' > set_ftrace_filter + + trace_pipe ---------- -- cgit v0.10.2 From e330b3bcd83199dd63a819d8d12e40f9edae6c77 Mon Sep 17 00:00:00 2001 From: Chase Douglas Date: Mon, 26 Apr 2010 14:02:05 -0400 Subject: tracing: Show sample std dev in function profiling When combined with function graph tracing the ftrace function profiler also prints the average run time of functions. While this gives us some good information, it doesn't tell us anything about the variance of the run times of the function. This change prints out the s^2 sample standard deviation alongside the average. This change adds one entry to the profile record structure. This increases the memory footprint of the function profiler by 1/3 on a 32-bit system, and by 1/5 on a 64-bit system when function graphing is enabled, though the memory is only allocated when the profiler is turned on. During the profiling, one extra line of code adds the squared calltime to the new record entry, so this should not adversly affect performance. Note that the square of the sample standard deviation is printed because there is no sqrt implementation for unsigned long long in the kernel. Signed-off-by: Chase Douglas LKML-Reference: <1272304925-2436-1-git-send-email-chase.douglas@canonical.com> [ fixed comment about ns^2 -> us^2 conversion ] Signed-off-by: Steven Rostedt diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 2404b59..3bcb340 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -264,6 +264,7 @@ struct ftrace_profile { unsigned long counter; #ifdef CONFIG_FUNCTION_GRAPH_TRACER unsigned long long time; + unsigned long long time_squared; #endif }; @@ -366,9 +367,9 @@ static int function_stat_headers(struct seq_file *m) { #ifdef CONFIG_FUNCTION_GRAPH_TRACER seq_printf(m, " Function " - "Hit Time Avg\n" + "Hit Time Avg s^2\n" " -------- " - "--- ---- ---\n"); + "--- ---- --- ---\n"); #else seq_printf(m, " Function Hit\n" " -------- ---\n"); @@ -384,6 +385,7 @@ static int function_stat_show(struct seq_file *m, void *v) static DEFINE_MUTEX(mutex); static struct trace_seq s; unsigned long long avg; + unsigned long long stddev; #endif kallsyms_lookup(rec->ip, NULL, NULL, NULL, str); @@ -394,11 +396,25 @@ static int function_stat_show(struct seq_file *m, void *v) avg = rec->time; do_div(avg, rec->counter); + /* Sample standard deviation (s^2) */ + if (rec->counter <= 1) + stddev = 0; + else { + stddev = rec->time_squared - rec->counter * avg * avg; + /* + * Divide only 1000 for ns^2 -> us^2 conversion. + * trace_print_graph_duration will divide 1000 again. + */ + do_div(stddev, (rec->counter - 1) * 1000); + } + mutex_lock(&mutex); trace_seq_init(&s); trace_print_graph_duration(rec->time, &s); trace_seq_puts(&s, " "); trace_print_graph_duration(avg, &s); + trace_seq_puts(&s, " "); + trace_print_graph_duration(stddev, &s); trace_print_seq(m, &s); mutex_unlock(&mutex); #endif @@ -668,8 +684,10 @@ static void profile_graph_return(struct ftrace_graph_ret *trace) } rec = ftrace_find_profiled_func(stat, trace->func); - if (rec) + if (rec) { rec->time += calltime; + rec->time_squared += calltime * calltime; + } out: local_irq_restore(flags); -- cgit v0.10.2 From 23346f21b277e3aae5e9989e711a11cbe8133a45 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 27 Apr 2010 21:17:50 -0300 Subject: perf tools: Rename "kernel_info" to "machine" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit struct kernel_info and kerninfo__ are too vague, what they really describe are machines, virtual ones or hosts. There are more changes to introduce helpers to shorten function calls and to make more clear what is really being done, but I left that for subsequent patches. Cc: Avi Kivity Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Zhang, Yanmin LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index f924b43..986b2ef 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -571,7 +571,7 @@ static int __cmd_annotate(void) perf_session__fprintf(session, stdout); if (verbose > 2) - dsos__fprintf(&session->kerninfo_root, stdout); + dsos__fprintf(&session->machines, stdout); perf_session__collapse_resort(&session->hists); perf_session__output_resort(&session->hists, session->event_total[0]); diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c index 623afe3..b4a265a 100644 --- a/tools/perf/builtin-buildid-list.c +++ b/tools/perf/builtin-buildid-list.c @@ -46,7 +46,7 @@ static int __cmd_buildid_list(void) if (with_hits) perf_session__process_events(session, &build_id__mark_dso_hit_ops); - dsos__fprintf_buildid(&session->kerninfo_root, stdout, with_hits); + dsos__fprintf_buildid(&session->machines, stdout, with_hits); perf_session__delete(session); return err; diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index ab906cb..2067475 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c @@ -352,7 +352,7 @@ static void __print_result(struct rb_root *root, struct perf_session *session, int n_lines, int is_caller) { struct rb_node *next; - struct kernel_info *kerninfo; + struct machine *machine; printf("%.102s\n", graph_dotted_line); printf(" %-34s |", is_caller ? "Callsite": "Alloc Ptr"); @@ -361,8 +361,8 @@ static void __print_result(struct rb_root *root, struct perf_session *session, next = rb_first(root); - kerninfo = kerninfo__findhost(&session->kerninfo_root); - if (!kerninfo) { + machine = perf_session__find_host_machine(session); + if (!machine) { pr_err("__print_result: couldn't find kernel information\n"); return; } @@ -370,7 +370,7 @@ static void __print_result(struct rb_root *root, struct perf_session *session, struct alloc_stat *data = rb_entry(next, struct alloc_stat, node); struct symbol *sym = NULL; - struct map_groups *kmaps = &kerninfo->kmaps; + struct map_groups *kmaps = &machine->kmaps; struct map *map; char buf[BUFSIZ]; u64 addr; diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 27f992a..83b308a 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -456,14 +456,14 @@ static void atexit_header(void) } } -static void event__synthesize_guest_os(struct kernel_info *kerninfo, - void *data __attribute__((unused))) +static void event__synthesize_guest_os(struct machine *machine, void *data) { int err; char *guest_kallsyms; char path[PATH_MAX]; + struct perf_session *psession = data; - if (is_host_kernel(kerninfo)) + if (machine__is_host(machine)) return; /* @@ -475,16 +475,15 @@ static void event__synthesize_guest_os(struct kernel_info *kerninfo, *in module instead of in guest kernel. */ err = event__synthesize_modules(process_synthesized_event, - session, - kerninfo); + psession, machine); if (err < 0) pr_err("Couldn't record guest kernel [%d]'s reference" - " relocation symbol.\n", kerninfo->pid); + " relocation symbol.\n", machine->pid); - if (is_default_guest(kerninfo)) + if (machine__is_default_guest(machine)) guest_kallsyms = (char *) symbol_conf.default_guest_kallsyms; else { - sprintf(path, "%s/proc/kallsyms", kerninfo->root_dir); + sprintf(path, "%s/proc/kallsyms", machine->root_dir); guest_kallsyms = path; } @@ -493,13 +492,13 @@ static void event__synthesize_guest_os(struct kernel_info *kerninfo, * have no _text sometimes. */ err = event__synthesize_kernel_mmap(process_synthesized_event, - session, kerninfo, "_text"); + psession, machine, "_text"); if (err < 0) err = event__synthesize_kernel_mmap(process_synthesized_event, - session, kerninfo, "_stext"); + psession, machine, "_stext"); if (err < 0) pr_err("Couldn't record guest kernel [%d]'s reference" - " relocation symbol.\n", kerninfo->pid); + " relocation symbol.\n", machine->pid); } static int __cmd_record(int argc, const char **argv) @@ -513,7 +512,7 @@ static int __cmd_record(int argc, const char **argv) int child_ready_pipe[2], go_pipe[2]; const bool forks = argc > 0; char buf; - struct kernel_info *kerninfo; + struct machine *machine; page_size = sysconf(_SC_PAGE_SIZE); @@ -682,31 +681,30 @@ static int __cmd_record(int argc, const char **argv) advance_output(err); } - kerninfo = kerninfo__findhost(&session->kerninfo_root); - if (!kerninfo) { + machine = perf_session__find_host_machine(session); + if (!machine) { pr_err("Couldn't find native kernel information.\n"); return -1; } err = event__synthesize_kernel_mmap(process_synthesized_event, - session, kerninfo, "_text"); + session, machine, "_text"); if (err < 0) err = event__synthesize_kernel_mmap(process_synthesized_event, - session, kerninfo, "_stext"); + session, machine, "_stext"); if (err < 0) { pr_err("Couldn't record kernel reference relocation symbol.\n"); return err; } err = event__synthesize_modules(process_synthesized_event, - session, kerninfo); + session, machine); if (err < 0) { pr_err("Couldn't record kernel reference relocation symbol.\n"); return err; } if (perf_guest) - kerninfo__process_allkernels(&session->kerninfo_root, - event__synthesize_guest_os, session); + perf_session__process_machines(session, event__synthesize_guest_os); if (!system_wide && profile_cpu == -1) event__synthesize_thread(target_tid, process_synthesized_event, diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 816edae..49cc367 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -313,7 +313,7 @@ static int __cmd_report(void) perf_session__fprintf(session, stdout); if (verbose > 2) - dsos__fprintf(&session->kerninfo_root, stdout); + dsos__fprintf(&session->machines, stdout); next = rb_first(&session->stats_by_id); while (next) { diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index dfd7ea7..c390f34 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -854,7 +854,7 @@ static void handle_keypress(struct perf_session *session, int c) case 'Q': printf("exiting.\n"); if (dump_symtab) - dsos__fprintf(&session->kerninfo_root, stderr); + dsos__fprintf(&session->machines, stderr); exit(0); case 's': prompt_symbol(&sym_filter_entry, "Enter details symbol"); @@ -982,7 +982,7 @@ static void event__process_sample(const event_t *self, u64 ip = self->ip.ip; struct sym_entry *syme; struct addr_location al; - struct kernel_info *kerninfo; + struct machine *machine; u8 origin = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; ++samples; @@ -992,18 +992,17 @@ static void event__process_sample(const event_t *self, ++us_samples; if (hide_user_symbols) return; - kerninfo = kerninfo__findhost(&session->kerninfo_root); + machine = perf_session__find_host_machine(session); break; case PERF_RECORD_MISC_KERNEL: ++kernel_samples; if (hide_kernel_symbols) return; - kerninfo = kerninfo__findhost(&session->kerninfo_root); + machine = perf_session__find_host_machine(session); break; case PERF_RECORD_MISC_GUEST_KERNEL: ++guest_kernel_samples; - kerninfo = kerninfo__find(&session->kerninfo_root, - self->ip.pid); + machine = perf_session__find_machine(session, self->ip.pid); break; case PERF_RECORD_MISC_GUEST_USER: ++guest_us_samples; @@ -1016,7 +1015,7 @@ static void event__process_sample(const event_t *self, return; } - if (!kerninfo && perf_guest) { + if (!machine && perf_guest) { pr_err("Can't find guest [%d]'s kernel information\n", self->ip.pid); return; @@ -1041,7 +1040,7 @@ static void event__process_sample(const event_t *self, * --hide-kernel-symbols, even if the user specifies an * invalid --vmlinux ;-) */ - if (al.map == kerninfo->vmlinux_maps[MAP__FUNCTION] && + if (al.map == machine->vmlinux_maps[MAP__FUNCTION] && RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) { pr_err("The %s file can't be used\n", symbol_conf.vmlinux_name); diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index e3fa8d3..2f33ca9 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -172,17 +172,17 @@ static int event__synthesize_mmap_events(pid_t pid, pid_t tgid, int event__synthesize_modules(event__handler_t process, struct perf_session *session, - struct kernel_info *kerninfo) + struct machine *machine) { struct rb_node *nd; - struct map_groups *kmaps = &kerninfo->kmaps; + struct map_groups *kmaps = &machine->kmaps; u16 misc; /* * kernel uses 0 for user space maps, see kernel/perf_event.c * __perf_event_mmap */ - if (is_host_kernel(kerninfo)) + if (machine__is_host(machine)) misc = PERF_RECORD_MISC_KERNEL; else misc = PERF_RECORD_MISC_GUEST_KERNEL; @@ -204,7 +204,7 @@ int event__synthesize_modules(event__handler_t process, (sizeof(ev.mmap.filename) - size)); ev.mmap.start = pos->start; ev.mmap.len = pos->end - pos->start; - ev.mmap.pid = kerninfo->pid; + ev.mmap.pid = machine->pid; memcpy(ev.mmap.filename, pos->dso->long_name, pos->dso->long_name_len + 1); @@ -267,7 +267,7 @@ static int find_symbol_cb(void *arg, const char *name, char type, u64 start) int event__synthesize_kernel_mmap(event__handler_t process, struct perf_session *session, - struct kernel_info *kerninfo, + struct machine *machine, const char *symbol_name) { size_t size; @@ -288,8 +288,8 @@ int event__synthesize_kernel_mmap(event__handler_t process, */ struct process_symbol_args args = { .name = symbol_name, }; - mmap_name = kern_mmap_name(kerninfo, name_buff); - if (is_host_kernel(kerninfo)) { + mmap_name = machine__mmap_name(machine, name_buff); + if (machine__is_host(machine)) { /* * kernel uses PERF_RECORD_MISC_USER for user space maps, * see kernel/perf_event.c __perf_event_mmap @@ -298,10 +298,10 @@ int event__synthesize_kernel_mmap(event__handler_t process, filename = "/proc/kallsyms"; } else { ev.header.misc = PERF_RECORD_MISC_GUEST_KERNEL; - if (is_default_guest(kerninfo)) + if (machine__is_default_guest(machine)) filename = (char *) symbol_conf.default_guest_kallsyms; else { - sprintf(path, "%s/proc/kallsyms", kerninfo->root_dir); + sprintf(path, "%s/proc/kallsyms", machine->root_dir); filename = path; } } @@ -309,7 +309,7 @@ int event__synthesize_kernel_mmap(event__handler_t process, if (kallsyms__parse(filename, &args, find_symbol_cb) <= 0) return -ENOENT; - map = kerninfo->vmlinux_maps[MAP__FUNCTION]; + map = machine->vmlinux_maps[MAP__FUNCTION]; size = snprintf(ev.mmap.filename, sizeof(ev.mmap.filename), "%s%s", mmap_name, symbol_name) + 1; size = ALIGN(size, sizeof(u64)); @@ -318,7 +318,7 @@ int event__synthesize_kernel_mmap(event__handler_t process, ev.mmap.pgoff = args.start; ev.mmap.start = map->start; ev.mmap.len = map->end - ev.mmap.start; - ev.mmap.pid = kerninfo->pid; + ev.mmap.pid = machine->pid; return process(&ev, session); } @@ -389,18 +389,18 @@ static int event__process_kernel_mmap(event_t *self, { struct map *map; char kmmap_prefix[PATH_MAX]; - struct kernel_info *kerninfo; + struct machine *machine; enum dso_kernel_type kernel_type; bool is_kernel_mmap; - kerninfo = kerninfo__findnew(&session->kerninfo_root, self->mmap.pid); - if (!kerninfo) { - pr_err("Can't find id %d's kerninfo\n", self->mmap.pid); + machine = perf_session__findnew_machine(session, self->mmap.pid); + if (!machine) { + pr_err("Can't find id %d's machine\n", self->mmap.pid); goto out_problem; } - kern_mmap_name(kerninfo, kmmap_prefix); - if (is_host_kernel(kerninfo)) + machine__mmap_name(machine, kmmap_prefix); + if (machine__is_host(machine)) kernel_type = DSO_TYPE_KERNEL; else kernel_type = DSO_TYPE_GUEST_KERNEL; @@ -429,10 +429,9 @@ static int event__process_kernel_mmap(event_t *self, } else strcpy(short_module_name, self->mmap.filename); - map = map_groups__new_module(&kerninfo->kmaps, - self->mmap.start, - self->mmap.filename, - kerninfo); + map = map_groups__new_module(&machine->kmaps, + self->mmap.start, + self->mmap.filename, machine); if (map == NULL) goto out_problem; @@ -449,27 +448,27 @@ static int event__process_kernel_mmap(event_t *self, * Should be there already, from the build-id table in * the header. */ - struct dso *kernel = __dsos__findnew(&kerninfo->dsos__kernel, - kmmap_prefix); + struct dso *kernel = __dsos__findnew(&machine->kernel_dsos, + kmmap_prefix); if (kernel == NULL) goto out_problem; kernel->kernel = kernel_type; - if (__map_groups__create_kernel_maps(&kerninfo->kmaps, - kerninfo->vmlinux_maps, kernel) < 0) + if (__map_groups__create_kernel_maps(&machine->kmaps, + machine->vmlinux_maps, + kernel) < 0) goto out_problem; - event_set_kernel_mmap_len(kerninfo->vmlinux_maps, self); - perf_session__set_kallsyms_ref_reloc_sym(kerninfo->vmlinux_maps, - symbol_name, - self->mmap.pgoff); - if (is_default_guest(kerninfo)) { + event_set_kernel_mmap_len(machine->vmlinux_maps, self); + perf_session__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, + symbol_name, + self->mmap.pgoff); + if (machine__is_default_guest(machine)) { /* * preload dso of guest kernel and modules */ - dso__load(kernel, - kerninfo->vmlinux_maps[MAP__FUNCTION], - NULL); + dso__load(kernel, machine->vmlinux_maps[MAP__FUNCTION], + NULL); } } return 0; @@ -479,7 +478,7 @@ out_problem: int event__process_mmap(event_t *self, struct perf_session *session) { - struct kernel_info *kerninfo; + struct machine *machine; struct thread *thread; struct map *map; u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; @@ -498,8 +497,8 @@ int event__process_mmap(event_t *self, struct perf_session *session) } thread = perf_session__findnew(session, self->mmap.pid); - kerninfo = kerninfo__findhost(&session->kerninfo_root); - map = map__new(&kerninfo->dsos__user, self->mmap.start, + machine = perf_session__find_host_machine(session); + map = map__new(&machine->user_dsos, self->mmap.start, self->mmap.len, self->mmap.pgoff, self->mmap.pid, self->mmap.filename, MAP__FUNCTION, session->cwd, session->cwdlen); @@ -546,7 +545,7 @@ void thread__find_addr_map(struct thread *self, struct addr_location *al) { struct map_groups *mg = &self->mg; - struct kernel_info *kerninfo = NULL; + struct machine *machine = NULL; al->thread = self; al->addr = addr; @@ -555,19 +554,19 @@ void thread__find_addr_map(struct thread *self, if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) { al->level = 'k'; - kerninfo = kerninfo__findhost(&session->kerninfo_root); - mg = &kerninfo->kmaps; + machine = perf_session__find_host_machine(session); + mg = &machine->kmaps; } else if (cpumode == PERF_RECORD_MISC_USER && perf_host) { al->level = '.'; - kerninfo = kerninfo__findhost(&session->kerninfo_root); + machine = perf_session__find_host_machine(session); } else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) { al->level = 'g'; - kerninfo = kerninfo__find(&session->kerninfo_root, pid); - if (!kerninfo) { + machine = perf_session__find_machine(session, pid); + if (!machine) { al->map = NULL; return; } - mg = &kerninfo->kmaps; + mg = &machine->kmaps; } else { /* * 'u' means guest os user space. @@ -603,10 +602,9 @@ try_again: * in the whole kernel symbol list. */ if ((long long)al->addr < 0 && - cpumode == PERF_RECORD_MISC_KERNEL && - kerninfo && - mg != &kerninfo->kmaps) { - mg = &kerninfo->kmaps; + cpumode == PERF_RECORD_MISC_KERNEL && + machine && mg != &machine->kmaps) { + mg = &machine->kmaps; goto try_again; } } else diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 4af2ed5..b364da5 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -156,12 +156,12 @@ void event__synthesize_threads(event__handler_t process, struct perf_session *session); int event__synthesize_kernel_mmap(event__handler_t process, struct perf_session *session, - struct kernel_info *kerninfo, + struct machine *machine, const char *symbol_name); int event__synthesize_modules(event__handler_t process, struct perf_session *session, - struct kernel_info *kerninfo); + struct machine *machine); int event__process_comm(event_t *self, struct perf_session *session); int event__process_lost(event_t *self, struct perf_session *session); diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 75d0167..6227dc4 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -229,10 +229,9 @@ static int dsos__write_buildid_table(struct perf_header *header, int fd) int err = 0; u16 kmisc, umisc; - for (nd = rb_first(&session->kerninfo_root); nd; nd = rb_next(nd)) { - struct kernel_info *pos = rb_entry(nd, struct kernel_info, - rb_node); - if (is_host_kernel(pos)) { + for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) { + struct machine *pos = rb_entry(nd, struct machine, rb_node); + if (machine__is_host(pos)) { kmisc = PERF_RECORD_MISC_KERNEL; umisc = PERF_RECORD_MISC_USER; } else { @@ -240,11 +239,11 @@ static int dsos__write_buildid_table(struct perf_header *header, int fd) umisc = PERF_RECORD_MISC_GUEST_USER; } - err = __dsos__write_buildid_table(&pos->dsos__kernel, pos->pid, - kmisc, fd); + err = __dsos__write_buildid_table(&pos->kernel_dsos, pos->pid, + kmisc, fd); if (err == 0) - err = __dsos__write_buildid_table(&pos->dsos__user, - pos->pid, umisc, fd); + err = __dsos__write_buildid_table(&pos->user_dsos, + pos->pid, umisc, fd); if (err) break; } @@ -378,11 +377,10 @@ static int dsos__cache_build_ids(struct perf_header *self) if (mkdir(debugdir, 0755) != 0 && errno != EEXIST) return -1; - for (nd = rb_first(&session->kerninfo_root); nd; nd = rb_next(nd)) { - struct kernel_info *pos = rb_entry(nd, struct kernel_info, - rb_node); - ret |= __dsos__cache_build_ids(&pos->dsos__kernel, debugdir); - ret |= __dsos__cache_build_ids(&pos->dsos__user, debugdir); + for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) { + struct machine *pos = rb_entry(nd, struct machine, rb_node); + ret |= __dsos__cache_build_ids(&pos->kernel_dsos, debugdir); + ret |= __dsos__cache_build_ids(&pos->user_dsos, debugdir); } return ret ? -1 : 0; } @@ -394,11 +392,10 @@ static bool dsos__read_build_ids(struct perf_header *self, bool with_hits) struct perf_session, header); struct rb_node *nd; - for (nd = rb_first(&session->kerninfo_root); nd; nd = rb_next(nd)) { - struct kernel_info *pos = rb_entry(nd, struct kernel_info, - rb_node); - ret |= __dsos__read_build_ids(&pos->dsos__kernel, with_hits); - ret |= __dsos__read_build_ids(&pos->dsos__user, with_hits); + for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) { + struct machine *pos = rb_entry(nd, struct machine, rb_node); + ret |= __dsos__read_build_ids(&pos->kernel_dsos, with_hits); + ret |= __dsos__read_build_ids(&pos->user_dsos, with_hits); } return ret; @@ -685,13 +682,13 @@ static int __event_process_build_id(struct build_id_event *bev, { int err = -1; struct list_head *head; - struct kernel_info *kerninfo; + struct machine *machine; u16 misc; struct dso *dso; enum dso_kernel_type dso_type; - kerninfo = kerninfo__findnew(&session->kerninfo_root, bev->pid); - if (!kerninfo) + machine = perf_session__findnew_machine(session, bev->pid); + if (!machine) goto out; misc = bev->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; @@ -699,16 +696,16 @@ static int __event_process_build_id(struct build_id_event *bev, switch (misc) { case PERF_RECORD_MISC_KERNEL: dso_type = DSO_TYPE_KERNEL; - head = &kerninfo->dsos__kernel; + head = &machine->kernel_dsos; break; case PERF_RECORD_MISC_GUEST_KERNEL: dso_type = DSO_TYPE_GUEST_KERNEL; - head = &kerninfo->dsos__kernel; + head = &machine->kernel_dsos; break; case PERF_RECORD_MISC_USER: case PERF_RECORD_MISC_GUEST_USER: dso_type = DSO_TYPE_USER; - head = &kerninfo->dsos__user; + head = &machine->user_dsos; break; default: goto out; @@ -1113,8 +1110,7 @@ int event__process_tracing_data(event_t *self, } int event__synthesize_build_id(struct dso *pos, u16 misc, - event__handler_t process, - struct kernel_info *kerninfo, + event__handler_t process, struct machine *machine, struct perf_session *session) { event_t ev; @@ -1131,7 +1127,7 @@ int event__synthesize_build_id(struct dso *pos, u16 misc, memcpy(&ev.build_id.build_id, pos->build_id, sizeof(pos->build_id)); ev.build_id.header.type = PERF_RECORD_HEADER_BUILD_ID; ev.build_id.header.misc = misc; - ev.build_id.pid = kerninfo->pid; + ev.build_id.pid = machine->pid; ev.build_id.header.size = sizeof(ev.build_id) + len; memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len); @@ -1142,7 +1138,7 @@ int event__synthesize_build_id(struct dso *pos, u16 misc, static int __event_synthesize_build_ids(struct list_head *head, u16 misc, event__handler_t process, - struct kernel_info *kerninfo, + struct machine *machine, struct perf_session *session) { struct dso *pos; @@ -1153,7 +1149,7 @@ static int __event_synthesize_build_ids(struct list_head *head, u16 misc, continue; err = event__synthesize_build_id(pos, misc, process, - kerninfo, session); + machine, session); if (err < 0) return err; } @@ -1166,15 +1162,15 @@ int event__synthesize_build_ids(event__handler_t process, { int err = 0; u16 kmisc, umisc; - struct kernel_info *pos; + struct machine *pos; struct rb_node *nd; if (!dsos__read_build_ids(&session->header, true)) return 0; - for (nd = rb_first(&session->kerninfo_root); nd; nd = rb_next(nd)) { - pos = rb_entry(nd, struct kernel_info, rb_node); - if (is_host_kernel(pos)) { + for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) { + pos = rb_entry(nd, struct machine, rb_node); + if (machine__is_host(pos)) { kmisc = PERF_RECORD_MISC_KERNEL; umisc = PERF_RECORD_MISC_USER; } else { @@ -1182,11 +1178,11 @@ int event__synthesize_build_ids(event__handler_t process, umisc = PERF_RECORD_MISC_GUEST_USER; } - err = __event_synthesize_build_ids(&pos->dsos__kernel, - kmisc, process, pos, session); + err = __event_synthesize_build_ids(&pos->kernel_dsos, kmisc, + process, pos, session); if (err == 0) - err = __event_synthesize_build_ids(&pos->dsos__user, - umisc, process, pos, session); + err = __event_synthesize_build_ids(&pos->user_dsos, umisc, + process, pos, session); if (err) break; } diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index 2759154..f39443d 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h @@ -120,7 +120,7 @@ int event__process_tracing_data(event_t *self, int event__synthesize_build_id(struct dso *pos, u16 misc, event__handler_t process, - struct kernel_info *kerninfo, + struct machine *machine, struct perf_session *session); int event__synthesize_build_ids(event__handler_t process, struct perf_session *session); diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 7facd01..da3d4e8 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -245,7 +245,7 @@ void map_groups__init(struct map_groups *self) self->maps[i] = RB_ROOT; INIT_LIST_HEAD(&self->removed_maps[i]); } - self->this_kerninfo = NULL; + self->machine = NULL; } void map_groups__flush(struct map_groups *self) @@ -513,133 +513,130 @@ struct map *maps__find(struct rb_root *maps, u64 ip) return NULL; } -struct kernel_info *add_new_kernel_info(struct rb_root *kerninfo_root, - pid_t pid, const char *root_dir) +struct machine *machines__add(struct rb_root *self, pid_t pid, + const char *root_dir) { - struct rb_node **p = &kerninfo_root->rb_node; + struct rb_node **p = &self->rb_node; struct rb_node *parent = NULL; - struct kernel_info *kerninfo, *pos; + struct machine *pos, *machine = malloc(sizeof(*machine)); - kerninfo = malloc(sizeof(struct kernel_info)); - if (!kerninfo) + if (!machine) return NULL; - kerninfo->pid = pid; - map_groups__init(&kerninfo->kmaps); - kerninfo->root_dir = strdup(root_dir); - RB_CLEAR_NODE(&kerninfo->rb_node); - INIT_LIST_HEAD(&kerninfo->dsos__user); - INIT_LIST_HEAD(&kerninfo->dsos__kernel); - kerninfo->kmaps.this_kerninfo = kerninfo; + machine->pid = pid; + map_groups__init(&machine->kmaps); + machine->root_dir = strdup(root_dir); + RB_CLEAR_NODE(&machine->rb_node); + INIT_LIST_HEAD(&machine->user_dsos); + INIT_LIST_HEAD(&machine->kernel_dsos); + machine->kmaps.machine = machine; while (*p != NULL) { parent = *p; - pos = rb_entry(parent, struct kernel_info, rb_node); + pos = rb_entry(parent, struct machine, rb_node); if (pid < pos->pid) p = &(*p)->rb_left; else p = &(*p)->rb_right; } - rb_link_node(&kerninfo->rb_node, parent, p); - rb_insert_color(&kerninfo->rb_node, kerninfo_root); + rb_link_node(&machine->rb_node, parent, p); + rb_insert_color(&machine->rb_node, self); - return kerninfo; + return machine; } -struct kernel_info *kerninfo__find(struct rb_root *kerninfo_root, pid_t pid) +struct machine *machines__find(struct rb_root *self, pid_t pid) { - struct rb_node **p = &kerninfo_root->rb_node; + struct rb_node **p = &self->rb_node; struct rb_node *parent = NULL; - struct kernel_info *kerninfo; - struct kernel_info *default_kerninfo = NULL; + struct machine *machine; + struct machine *default_machine = NULL; while (*p != NULL) { parent = *p; - kerninfo = rb_entry(parent, struct kernel_info, rb_node); - if (pid < kerninfo->pid) + machine = rb_entry(parent, struct machine, rb_node); + if (pid < machine->pid) p = &(*p)->rb_left; - else if (pid > kerninfo->pid) + else if (pid > machine->pid) p = &(*p)->rb_right; else - return kerninfo; - if (!kerninfo->pid) - default_kerninfo = kerninfo; + return machine; + if (!machine->pid) + default_machine = machine; } - return default_kerninfo; + return default_machine; } -struct kernel_info *kerninfo__findhost(struct rb_root *kerninfo_root) +/* + * FIXME: Why repeatedly search for this? + */ +struct machine *machines__find_host(struct rb_root *self) { - struct rb_node **p = &kerninfo_root->rb_node; + struct rb_node **p = &self->rb_node; struct rb_node *parent = NULL; - struct kernel_info *kerninfo; + struct machine *machine; pid_t pid = HOST_KERNEL_ID; while (*p != NULL) { parent = *p; - kerninfo = rb_entry(parent, struct kernel_info, rb_node); - if (pid < kerninfo->pid) + machine = rb_entry(parent, struct machine, rb_node); + if (pid < machine->pid) p = &(*p)->rb_left; - else if (pid > kerninfo->pid) + else if (pid > machine->pid) p = &(*p)->rb_right; else - return kerninfo; + return machine; } return NULL; } -struct kernel_info *kerninfo__findnew(struct rb_root *kerninfo_root, pid_t pid) +struct machine *machines__findnew(struct rb_root *self, pid_t pid) { char path[PATH_MAX]; const char *root_dir; - int ret; - struct kernel_info *kerninfo = kerninfo__find(kerninfo_root, pid); + struct machine *machine = machines__find(self, pid); - if (!kerninfo || kerninfo->pid != pid) { + if (!machine || machine->pid != pid) { if (pid == HOST_KERNEL_ID || pid == DEFAULT_GUEST_KERNEL_ID) root_dir = ""; else { if (!symbol_conf.guestmount) goto out; sprintf(path, "%s/%d", symbol_conf.guestmount, pid); - ret = access(path, R_OK); - if (ret) { + if (access(path, R_OK)) { pr_err("Can't access file %s\n", path); goto out; } root_dir = path; } - kerninfo = add_new_kernel_info(kerninfo_root, pid, root_dir); + machine = machines__add(self, pid, root_dir); } out: - return kerninfo; + return machine; } -void kerninfo__process_allkernels(struct rb_root *kerninfo_root, - process_kernel_info process, - void *data) +void machines__process(struct rb_root *self, machine__process_t process, void *data) { struct rb_node *nd; - for (nd = rb_first(kerninfo_root); nd; nd = rb_next(nd)) { - struct kernel_info *pos = rb_entry(nd, struct kernel_info, - rb_node); + for (nd = rb_first(self); nd; nd = rb_next(nd)) { + struct machine *pos = rb_entry(nd, struct machine, rb_node); process(pos, data); } } -char *kern_mmap_name(struct kernel_info *kerninfo, char *buff) +char *machine__mmap_name(struct machine *self, char *buff) { - if (is_host_kernel(kerninfo)) + if (machine__is_host(self)) sprintf(buff, "[%s]", "kernel.kallsyms"); - else if (is_default_guest(kerninfo)) + else if (machine__is_default_guest(self)) sprintf(buff, "[%s]", "guest.kernel.kallsyms"); else - sprintf(buff, "[%s.%d]", "guest.kernel.kallsyms", kerninfo->pid); + sprintf(buff, "[%s.%d]", "guest.kernel.kallsyms", self->pid); return buff; } diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index 30d38d6..4c1c2da 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h @@ -5,6 +5,7 @@ #include #include #include +#include #include "types.h" enum map_type { @@ -19,7 +20,7 @@ extern const char *map_type__name[MAP__NR_TYPES]; struct dso; struct ref_reloc_sym; struct map_groups; -struct kernel_info; +struct machine; struct map { union { @@ -46,23 +47,23 @@ struct kmap { }; struct map_groups { - struct rb_root maps[MAP__NR_TYPES]; - struct list_head removed_maps[MAP__NR_TYPES]; - struct kernel_info *this_kerninfo; + struct rb_root maps[MAP__NR_TYPES]; + struct list_head removed_maps[MAP__NR_TYPES]; + struct machine *machine; }; -/* Native host kernel uses -1 as pid index in kernel_info */ +/* Native host kernel uses -1 as pid index in machine */ #define HOST_KERNEL_ID (-1) #define DEFAULT_GUEST_KERNEL_ID (0) -struct kernel_info { - struct rb_node rb_node; - pid_t pid; - char *root_dir; - struct list_head dsos__user; - struct list_head dsos__kernel; +struct machine { + struct rb_node rb_node; + pid_t pid; + char *root_dir; + struct list_head user_dsos; + struct list_head kernel_dsos; struct map_groups kmaps; - struct map *vmlinux_maps[MAP__NR_TYPES]; + struct map *vmlinux_maps[MAP__NR_TYPES]; }; static inline struct kmap *map__kmap(struct map *self) @@ -124,36 +125,30 @@ int map_groups__clone(struct map_groups *self, size_t map_groups__fprintf(struct map_groups *self, int verbose, FILE *fp); size_t map_groups__fprintf_maps(struct map_groups *self, int verbose, FILE *fp); -struct kernel_info *add_new_kernel_info(struct rb_root *kerninfo_root, - pid_t pid, const char *root_dir); -struct kernel_info *kerninfo__find(struct rb_root *kerninfo_root, pid_t pid); -struct kernel_info *kerninfo__findnew(struct rb_root *kerninfo_root, pid_t pid); -struct kernel_info *kerninfo__findhost(struct rb_root *kerninfo_root); -char *kern_mmap_name(struct kernel_info *kerninfo, char *buff); +typedef void (*machine__process_t)(struct machine *self, void *data); + +void machines__process(struct rb_root *self, machine__process_t process, void *data); +struct machine *machines__add(struct rb_root *self, pid_t pid, + const char *root_dir); +struct machine *machines__find_host(struct rb_root *self); +struct machine *machines__find(struct rb_root *self, pid_t pid); +struct machine *machines__findnew(struct rb_root *self, pid_t pid); +char *machine__mmap_name(struct machine *self, char *buff); /* * Default guest kernel is defined by parameter --guestkallsyms * and --guestmodules */ -static inline int is_default_guest(struct kernel_info *kerninfo) +static inline bool machine__is_default_guest(struct machine *self) { - if (!kerninfo) - return 0; - return kerninfo->pid == DEFAULT_GUEST_KERNEL_ID; + return self ? self->pid == DEFAULT_GUEST_KERNEL_ID : false; } -static inline int is_host_kernel(struct kernel_info *kerninfo) +static inline bool machine__is_host(struct machine *self) { - if (!kerninfo) - return 0; - return kerninfo->pid == HOST_KERNEL_ID; + return self ? self->pid == HOST_KERNEL_ID : false; } -typedef void (*process_kernel_info)(struct kernel_info *kerninfo, void *data); -void kerninfo__process_allkernels(struct rb_root *kerninfo_root, - process_kernel_info process, - void *data); - static inline void map_groups__insert(struct map_groups *self, struct map *map) { maps__insert(&self->maps[map->type], map); @@ -197,10 +192,8 @@ int map_groups__fixup_overlappings(struct map_groups *self, struct map *map, struct map *map_groups__find_by_name(struct map_groups *self, enum map_type type, const char *name); -struct map *map_groups__new_module(struct map_groups *self, - u64 start, - const char *filename, - struct kernel_info *kerninfo); +struct map *map_groups__new_module(struct map_groups *self, u64 start, + const char *filename, struct machine *machine); void map_groups__flush(struct map_groups *self); diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index b7aade2..b745c1c 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -70,7 +70,7 @@ void perf_session__update_sample_type(struct perf_session *self) int perf_session__create_kernel_maps(struct perf_session *self) { int ret; - struct rb_root *root = &self->kerninfo_root; + struct rb_root *root = &self->machines; ret = map_groups__create_kernel_maps(root, HOST_KERNEL_ID); if (ret >= 0) @@ -97,7 +97,7 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc self->cwd = NULL; self->cwdlen = 0; self->unknown_events = 0; - self->kerninfo_root = RB_ROOT; + self->machines = RB_ROOT; self->ordered_samples.flush_limit = ULLONG_MAX; INIT_LIST_HEAD(&self->ordered_samples.samples_head); diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 796e229..7125272 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -25,7 +25,7 @@ struct perf_session { unsigned long mmap_window; struct rb_root threads; struct thread *last_match; - struct rb_root kerninfo_root; + struct rb_root machines; struct events_stats events_stats; struct rb_root stats_by_id; unsigned long event_total[PERF_RECORD_MAX]; @@ -102,4 +102,29 @@ int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, u64 session_total, const char *helpline, const char *input_name); #endif + +static inline +struct machine *perf_session__find_host_machine(struct perf_session *self) +{ + return machines__find_host(&self->machines); +} + +static inline +struct machine *perf_session__find_machine(struct perf_session *self, pid_t pid) +{ + return machines__find(&self->machines, pid); +} + +static inline +struct machine *perf_session__findnew_machine(struct perf_session *self, pid_t pid) +{ + return machines__findnew(&self->machines, pid); +} + +static inline +void perf_session__process_machines(struct perf_session *self, + machine__process_t process) +{ + return machines__process(&self->machines, process, self); +} #endif /* __PERF_SESSION_H */ diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index e77c33a..dc04636 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -485,7 +485,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map, symbol_filter_t filter) { struct map_groups *kmaps = map__kmap(map)->kmaps; - struct kernel_info *kerninfo = kmaps->this_kerninfo; + struct machine *machine = kmaps->machine; struct map *curr_map = map; struct symbol *pos; int count = 0; @@ -508,8 +508,8 @@ static int dso__split_kallsyms(struct dso *self, struct map *map, if (strcmp(curr_map->dso->short_name, module)) { if (curr_map != map && - self->kernel == DSO_TYPE_GUEST_KERNEL && - is_default_guest(kerninfo)) { + self->kernel == DSO_TYPE_GUEST_KERNEL && + machine__is_default_guest(machine)) { /* * We assume all symbols of a module are * continuous in * kallsyms, so curr_map @@ -527,13 +527,13 @@ static int dso__split_kallsyms(struct dso *self, struct map *map, pr_err("%s/proc/{kallsyms,modules} " "inconsistency while looking " "for \"%s\" module!\n", - kerninfo->root_dir, module); + machine->root_dir, module); curr_map = map; goto discard_symbol; } if (curr_map->dso->loaded && - !is_default_guest(kmaps->this_kerninfo)) + !machine__is_default_guest(machine)) goto discard_symbol; } /* @@ -586,7 +586,7 @@ discard_symbol: rb_erase(&pos->rb_node, root); if (curr_map != map && self->kernel == DSO_TYPE_GUEST_KERNEL && - is_default_guest(kmaps->this_kerninfo)) { + machine__is_default_guest(kmaps->machine)) { dso__set_loaded(curr_map->dso, curr_map->type); } @@ -1291,7 +1291,7 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) char build_id_hex[BUILD_ID_SIZE * 2 + 1]; int ret = -1; int fd; - struct kernel_info *kerninfo; + struct machine *machine; const char *root_dir; dso__set_loaded(self, map->type); @@ -1301,10 +1301,10 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) else if (self->kernel == DSO_TYPE_GUEST_KERNEL) return dso__load_guest_kernel_sym(self, map, filter); - if (map->groups && map->groups->this_kerninfo) - kerninfo = map->groups->this_kerninfo; + if (map->groups && map->groups->machine) + machine = map->groups->machine; else - kerninfo = NULL; + machine = NULL; name = malloc(size); if (!name) @@ -1359,8 +1359,8 @@ more: snprintf(name, size, "%s", self->long_name); break; case DSO__ORIG_GUEST_KMODULE: - if (map->groups && map->groups->this_kerninfo) - root_dir = map->groups->this_kerninfo->root_dir; + if (map->groups && map->groups->machine) + root_dir = map->groups->machine->root_dir; else root_dir = ""; snprintf(name, size, "%s%s", root_dir, self->long_name); @@ -1566,12 +1566,12 @@ static struct map *map__new2(u64 start, struct dso *dso, enum map_type type) struct map *map_groups__new_module(struct map_groups *self, u64 start, const char *filename, - struct kernel_info *kerninfo) + struct machine *machine) { struct map *map; struct dso *dso; - dso = __dsos__findnew(&kerninfo->dsos__kernel, filename); + dso = __dsos__findnew(&machine->kernel_dsos, filename); if (dso == NULL) return NULL; @@ -1579,7 +1579,7 @@ struct map *map_groups__new_module(struct map_groups *self, u64 start, if (map == NULL) return NULL; - if (is_host_kernel(kerninfo)) + if (machine__is_host(machine)) dso->origin = DSO__ORIG_KMODULE; else dso->origin = DSO__ORIG_GUEST_KMODULE; @@ -1587,7 +1587,7 @@ struct map *map_groups__new_module(struct map_groups *self, u64 start, return map; } -static int map_groups__create_modules(struct kernel_info *kerninfo) +static int map_groups__create_modules(struct machine *machine) { char *line = NULL; size_t n; @@ -1597,10 +1597,10 @@ static int map_groups__create_modules(struct kernel_info *kerninfo) const char *modules; char path[PATH_MAX]; - if (is_default_guest(kerninfo)) + if (machine__is_default_guest(machine)) modules = symbol_conf.default_guest_modules; else { - sprintf(path, "%s/proc/modules", kerninfo->root_dir); + sprintf(path, "%s/proc/modules", machine->root_dir); modules = path; } @@ -1608,7 +1608,7 @@ static int map_groups__create_modules(struct kernel_info *kerninfo) if (file == NULL) return -1; - root_dir = kerninfo->root_dir; + root_dir = machine->root_dir; while (!feof(file)) { char name[PATH_MAX]; @@ -1638,8 +1638,8 @@ static int map_groups__create_modules(struct kernel_info *kerninfo) *sep = '\0'; snprintf(name, sizeof(name), "[%s]", line); - map = map_groups__new_module(&kerninfo->kmaps, - start, name, kerninfo); + map = map_groups__new_module(&machine->kmaps, start, + name, machine); if (map == NULL) goto out_delete_line; dso__kernel_module_get_build_id(map->dso, root_dir); @@ -1648,7 +1648,7 @@ static int map_groups__create_modules(struct kernel_info *kerninfo) free(line); fclose(file); - return map_groups__set_modules_path(&kerninfo->kmaps, root_dir); + return map_groups__set_modules_path(&machine->kmaps, root_dir); out_delete_line: free(line); @@ -1820,16 +1820,16 @@ static int dso__load_guest_kernel_sym(struct dso *self, struct map *map, { int err; const char *kallsyms_filename = NULL; - struct kernel_info *kerninfo; + struct machine *machine; char path[PATH_MAX]; if (!map->groups) { pr_debug("Guest kernel map hasn't the point to groups\n"); return -1; } - kerninfo = map->groups->this_kerninfo; + machine = map->groups->machine; - if (is_default_guest(kerninfo)) { + if (machine__is_default_guest(machine)) { /* * if the user specified a vmlinux filename, use it and only * it, reporting errors to the user if it cannot be used. @@ -1845,7 +1845,7 @@ static int dso__load_guest_kernel_sym(struct dso *self, struct map *map, if (!kallsyms_filename) return -1; } else { - sprintf(path, "%s/proc/kallsyms", kerninfo->root_dir); + sprintf(path, "%s/proc/kallsyms", machine->root_dir); kallsyms_filename = path; } @@ -1856,9 +1856,8 @@ static int dso__load_guest_kernel_sym(struct dso *self, struct map *map, out_try_fixup: if (err > 0) { if (kallsyms_filename != NULL) { - kern_mmap_name(kerninfo, path); - dso__set_long_name(self, - strdup(path)); + machine__mmap_name(machine, path); + dso__set_long_name(self, strdup(path)); } map__fixup_start(map); map__fixup_end(map); @@ -1908,15 +1907,14 @@ static void __dsos__fprintf(struct list_head *head, FILE *fp) } } -void dsos__fprintf(struct rb_root *kerninfo_root, FILE *fp) +void dsos__fprintf(struct rb_root *machines, FILE *fp) { struct rb_node *nd; - for (nd = rb_first(kerninfo_root); nd; nd = rb_next(nd)) { - struct kernel_info *pos = rb_entry(nd, struct kernel_info, - rb_node); - __dsos__fprintf(&pos->dsos__kernel, fp); - __dsos__fprintf(&pos->dsos__user, fp); + for (nd = rb_first(machines); nd; nd = rb_next(nd)) { + struct machine *pos = rb_entry(nd, struct machine, rb_node); + __dsos__fprintf(&pos->kernel_dsos, fp); + __dsos__fprintf(&pos->user_dsos, fp); } } @@ -1935,19 +1933,15 @@ static size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, return ret; } -size_t dsos__fprintf_buildid(struct rb_root *kerninfo_root, - FILE *fp, bool with_hits) +size_t dsos__fprintf_buildid(struct rb_root *machines, FILE *fp, bool with_hits) { struct rb_node *nd; size_t ret = 0; - for (nd = rb_first(kerninfo_root); nd; nd = rb_next(nd)) { - struct kernel_info *pos = rb_entry(nd, struct kernel_info, - rb_node); - ret += __dsos__fprintf_buildid(&pos->dsos__kernel, - fp, with_hits); - ret += __dsos__fprintf_buildid(&pos->dsos__user, - fp, with_hits); + for (nd = rb_first(machines); nd; nd = rb_next(nd)) { + struct machine *pos = rb_entry(nd, struct machine, rb_node); + ret += __dsos__fprintf_buildid(&pos->kernel_dsos, fp, with_hits); + ret += __dsos__fprintf_buildid(&pos->user_dsos, fp, with_hits); } return ret; } @@ -1964,14 +1958,12 @@ struct dso *dso__new_kernel(const char *name) return self; } -static struct dso *dso__new_guest_kernel(struct kernel_info *kerninfo, +static struct dso *dso__new_guest_kernel(struct machine *machine, const char *name) { char buff[PATH_MAX]; - struct dso *self; + struct dso *self = dso__new(name ?: machine__mmap_name(machine, buff)); - kern_mmap_name(kerninfo, buff); - self = dso__new(name ?: buff); if (self != NULL) { dso__set_short_name(self, "[guest.kernel]"); self->kernel = DSO_TYPE_GUEST_KERNEL; @@ -1980,36 +1972,35 @@ static struct dso *dso__new_guest_kernel(struct kernel_info *kerninfo, return self; } -void dso__read_running_kernel_build_id(struct dso *self, - struct kernel_info *kerninfo) +void dso__read_running_kernel_build_id(struct dso *self, struct machine *machine) { char path[PATH_MAX]; - if (is_default_guest(kerninfo)) + if (machine__is_default_guest(machine)) return; - sprintf(path, "%s/sys/kernel/notes", kerninfo->root_dir); + sprintf(path, "%s/sys/kernel/notes", machine->root_dir); if (sysfs__read_build_id(path, self->build_id, sizeof(self->build_id)) == 0) self->has_build_id = true; } -static struct dso *dsos__create_kernel(struct kernel_info *kerninfo) +static struct dso *dsos__create_kernel(struct machine *machine) { const char *vmlinux_name = NULL; struct dso *kernel; - if (is_host_kernel(kerninfo)) { + if (machine__is_host(machine)) { vmlinux_name = symbol_conf.vmlinux_name; kernel = dso__new_kernel(vmlinux_name); } else { - if (is_default_guest(kerninfo)) + if (machine__is_default_guest(machine)) vmlinux_name = symbol_conf.default_guest_vmlinux_name; - kernel = dso__new_guest_kernel(kerninfo, vmlinux_name); + kernel = dso__new_guest_kernel(machine, vmlinux_name); } if (kernel != NULL) { - dso__read_running_kernel_build_id(kernel, kerninfo); - dsos__add(&kerninfo->dsos__kernel, kernel); + dso__read_running_kernel_build_id(kernel, machine); + dsos__add(&machine->kernel_dsos, kernel); } return kernel; } @@ -2154,29 +2145,28 @@ out_free_comm_list: return -1; } -int map_groups__create_kernel_maps(struct rb_root *kerninfo_root, pid_t pid) +int map_groups__create_kernel_maps(struct rb_root *machines, pid_t pid) { - struct kernel_info *kerninfo; struct dso *kernel; + struct machine *machine = machines__findnew(machines, pid); - kerninfo = kerninfo__findnew(kerninfo_root, pid); - if (kerninfo == NULL) + if (machine == NULL) return -1; - kernel = dsos__create_kernel(kerninfo); + kernel = dsos__create_kernel(machine); if (kernel == NULL) return -1; - if (__map_groups__create_kernel_maps(&kerninfo->kmaps, - kerninfo->vmlinux_maps, kernel) < 0) + if (__map_groups__create_kernel_maps(&machine->kmaps, + machine->vmlinux_maps, kernel) < 0) return -1; if (symbol_conf.use_modules && - map_groups__create_modules(kerninfo) < 0) + map_groups__create_modules(machine) < 0) pr_debug("Problems creating module maps, continuing anyway...\n"); /* * Now that we have all the maps created, just set the ->end of them: */ - map_groups__fixup_end(&kerninfo->kmaps); + map_groups__fixup_end(&machine->kmaps); return 0; } @@ -2223,7 +2213,7 @@ char *strxfrchar(char *s, char from, char to) return s; } -int map_groups__create_guest_kernel_maps(struct rb_root *kerninfo_root) +int map_groups__create_guest_kernel_maps(struct rb_root *machines) { int ret = 0; struct dirent **namelist = NULL; @@ -2234,8 +2224,7 @@ int map_groups__create_guest_kernel_maps(struct rb_root *kerninfo_root) if (symbol_conf.default_guest_vmlinux_name || symbol_conf.default_guest_modules || symbol_conf.default_guest_kallsyms) { - map_groups__create_kernel_maps(kerninfo_root, - DEFAULT_GUEST_KERNEL_ID); + map_groups__create_kernel_maps(machines, DEFAULT_GUEST_KERNEL_ID); } if (symbol_conf.guestmount) { @@ -2256,8 +2245,7 @@ int map_groups__create_guest_kernel_maps(struct rb_root *kerninfo_root) pr_debug("Can't access file %s\n", path); goto failure; } - map_groups__create_kernel_maps(kerninfo_root, - pid); + map_groups__create_kernel_maps(machines, pid); } failure: free(namelist); diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 478f5ab..ed885b0 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -186,8 +186,7 @@ enum dso_origin { char dso__symtab_origin(const struct dso *self); void dso__set_long_name(struct dso *self, char *name); void dso__set_build_id(struct dso *self, void *build_id); -void dso__read_running_kernel_build_id(struct dso *self, - struct kernel_info *kerninfo); +void dso__read_running_kernel_build_id(struct dso *self, struct machine *machine); struct symbol *dso__find_symbol(struct dso *self, enum map_type type, u64 addr); struct symbol *dso__find_symbol_by_name(struct dso *self, enum map_type type, const char *name); -- cgit v0.10.2 From 48ea8f5470aa6f35244d1b218316705ea88c0259 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 27 Apr 2010 21:19:05 -0300 Subject: perf machine: Pass buffer size to machine__mmap_name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't blindly assume that the size of the buffer is enough, use snprintf. Cc: Avi Kivity Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Zhang, Yanmin LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 2f33ca9..7400e51 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -288,7 +288,7 @@ int event__synthesize_kernel_mmap(event__handler_t process, */ struct process_symbol_args args = { .name = symbol_name, }; - mmap_name = machine__mmap_name(machine, name_buff); + mmap_name = machine__mmap_name(machine, name_buff, sizeof(name_buff)); if (machine__is_host(machine)) { /* * kernel uses PERF_RECORD_MISC_USER for user space maps, @@ -399,7 +399,7 @@ static int event__process_kernel_mmap(event_t *self, goto out_problem; } - machine__mmap_name(machine, kmmap_prefix); + machine__mmap_name(machine, kmmap_prefix, sizeof(kmmap_prefix)); if (machine__is_host(machine)) kernel_type = DSO_TYPE_KERNEL; else diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index da3d4e8..ee25ee9 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -629,14 +629,14 @@ void machines__process(struct rb_root *self, machine__process_t process, void *d } } -char *machine__mmap_name(struct machine *self, char *buff) +char *machine__mmap_name(struct machine *self, char *bf, size_t size) { if (machine__is_host(self)) - sprintf(buff, "[%s]", "kernel.kallsyms"); + snprintf(bf, size, "[%s]", "kernel.kallsyms"); else if (machine__is_default_guest(self)) - sprintf(buff, "[%s]", "guest.kernel.kallsyms"); + snprintf(bf, size, "[%s]", "guest.kernel.kallsyms"); else - sprintf(buff, "[%s.%d]", "guest.kernel.kallsyms", self->pid); + snprintf(bf, size, "[%s.%d]", "guest.kernel.kallsyms", self->pid); - return buff; + return bf; } diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index 4c1c2da..6fabad1 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h @@ -133,7 +133,7 @@ struct machine *machines__add(struct rb_root *self, pid_t pid, struct machine *machines__find_host(struct rb_root *self); struct machine *machines__find(struct rb_root *self, pid_t pid); struct machine *machines__findnew(struct rb_root *self, pid_t pid); -char *machine__mmap_name(struct machine *self, char *buff); +char *machine__mmap_name(struct machine *self, char *bf, size_t size); /* * Default guest kernel is defined by parameter --guestkallsyms diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index dc04636..c9c0bdd 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1856,7 +1856,7 @@ static int dso__load_guest_kernel_sym(struct dso *self, struct map *map, out_try_fixup: if (err > 0) { if (kallsyms_filename != NULL) { - machine__mmap_name(machine, path); + machine__mmap_name(machine, path, sizeof(path)); dso__set_long_name(self, strdup(path)); } map__fixup_start(map); @@ -1961,8 +1961,8 @@ struct dso *dso__new_kernel(const char *name) static struct dso *dso__new_guest_kernel(struct machine *machine, const char *name) { - char buff[PATH_MAX]; - struct dso *self = dso__new(name ?: machine__mmap_name(machine, buff)); + char bf[PATH_MAX]; + struct dso *self = dso__new(name ?: machine__mmap_name(machine, bf, sizeof(bf))); if (self != NULL) { dso__set_short_name(self, "[guest.kernel]"); -- cgit v0.10.2 From d28c62232e50eab202bcd3f19b5c7a25b8b900b6 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 27 Apr 2010 21:20:43 -0300 Subject: perf machine: Adopt some map_groups functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Those functions operated on members now grouped in 'struct machine', so move those methods to this new class. The changes made to 'perf probe' shows that using this abstraction inserting probes on guests almost got supported for free. Cc: Avi Kivity Cc: Frédéric Weisbecker Cc: Masami Hiramatsu Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Zhang, Yanmin LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index 2067475..1563561 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c @@ -370,7 +370,6 @@ static void __print_result(struct rb_root *root, struct perf_session *session, struct alloc_stat *data = rb_entry(next, struct alloc_stat, node); struct symbol *sym = NULL; - struct map_groups *kmaps = &machine->kmaps; struct map *map; char buf[BUFSIZ]; u64 addr; @@ -378,8 +377,7 @@ static void __print_result(struct rb_root *root, struct perf_session *session, if (is_caller) { addr = data->call_site; if (!raw_ip) - sym = map_groups__find_function(kmaps, addr, - &map, NULL); + sym = machine__find_function(machine, addr, &map, NULL); } else addr = data->ptr; diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 7400e51..1757b0f 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -429,9 +429,8 @@ static int event__process_kernel_mmap(event_t *self, } else strcpy(short_module_name, self->mmap.filename); - map = map_groups__new_module(&machine->kmaps, - self->mmap.start, - self->mmap.filename, machine); + map = machine__new_module(machine, self->mmap.start, + self->mmap.filename); if (map == NULL) goto out_problem; @@ -454,9 +453,7 @@ static int event__process_kernel_mmap(event_t *self, goto out_problem; kernel->kernel = kernel_type; - if (__map_groups__create_kernel_maps(&machine->kmaps, - machine->vmlinux_maps, - kernel) < 0) + if (__machine__create_kernel_maps(machine, kernel) < 0) goto out_problem; event_set_kernel_mmap_len(machine->vmlinux_maps, self); diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index ee25ee9..44a4df6 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -513,6 +513,19 @@ struct map *maps__find(struct rb_root *maps, u64 ip) return NULL; } +int machine__init(struct machine *self, const char *root_dir, pid_t pid) +{ + map_groups__init(&self->kmaps); + RB_CLEAR_NODE(&self->rb_node); + INIT_LIST_HEAD(&self->user_dsos); + INIT_LIST_HEAD(&self->kernel_dsos); + + self->kmaps.machine = self; + self->pid = pid; + self->root_dir = strdup(root_dir); + return self->root_dir == NULL ? -ENOMEM : 0; +} + struct machine *machines__add(struct rb_root *self, pid_t pid, const char *root_dir) { @@ -523,13 +536,10 @@ struct machine *machines__add(struct rb_root *self, pid_t pid, if (!machine) return NULL; - machine->pid = pid; - map_groups__init(&machine->kmaps); - machine->root_dir = strdup(root_dir); - RB_CLEAR_NODE(&machine->rb_node); - INIT_LIST_HEAD(&machine->user_dsos); - INIT_LIST_HEAD(&machine->kernel_dsos); - machine->kmaps.machine = machine; + if (machine__init(machine, root_dir, pid) != 0) { + free(machine); + return NULL; + } while (*p != NULL) { parent = *p; diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index 6fabad1..881dba4 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h @@ -134,6 +134,7 @@ struct machine *machines__find_host(struct rb_root *self); struct machine *machines__find(struct rb_root *self, pid_t pid); struct machine *machines__findnew(struct rb_root *self, pid_t pid); char *machine__mmap_name(struct machine *self, char *bf, size_t size); +int machine__init(struct machine *self, const char *root_dir, pid_t pid); /* * Default guest kernel is defined by parameter --guestkallsyms @@ -172,11 +173,11 @@ struct symbol *map_groups__find_symbol_by_name(struct map_groups *self, struct map **mapp, symbol_filter_t filter); -static inline -struct symbol *map_groups__find_function(struct map_groups *self, u64 addr, - struct map **mapp, symbol_filter_t filter) +static inline struct symbol *machine__find_function(struct machine *self, + u64 addr, struct map **mapp, + symbol_filter_t filter) { - return map_groups__find_symbol(self, MAP__FUNCTION, addr, mapp, filter); + return map_groups__find_symbol(&self->kmaps, MAP__FUNCTION, addr, mapp, filter); } static inline @@ -192,8 +193,7 @@ int map_groups__fixup_overlappings(struct map_groups *self, struct map *map, struct map *map_groups__find_by_name(struct map_groups *self, enum map_type type, const char *name); -struct map *map_groups__new_module(struct map_groups *self, u64 start, - const char *filename, struct machine *machine); +struct map *machine__new_module(struct machine *self, u64 start, const char *filename); void map_groups__flush(struct map_groups *self); diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 9ded38c..914c670 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -72,8 +72,7 @@ static int e_snprintf(char *str, size_t size, const char *format, ...) } static char *synthesize_perf_probe_point(struct perf_probe_point *pp); -static struct map_groups kmap_groups; -static struct map *kmaps[MAP__NR_TYPES]; +static struct machine machine; /* Initialize symbol maps and path of vmlinux */ static int init_vmlinux(void) @@ -92,12 +91,15 @@ static int init_vmlinux(void) goto out; } + ret = machine__init(&machine, "/", 0); + if (ret < 0) + goto out; + kernel = dso__new_kernel(symbol_conf.vmlinux_name); if (kernel == NULL) die("Failed to create kernel dso."); - map_groups__init(&kmap_groups); - ret = __map_groups__create_kernel_maps(&kmap_groups, kmaps, kernel); + ret = __machine__create_kernel_maps(&machine, kernel); if (ret < 0) pr_debug("Failed to create kernel maps.\n"); @@ -110,12 +112,12 @@ out: #ifdef DWARF_SUPPORT static int open_vmlinux(void) { - if (map__load(kmaps[MAP__FUNCTION], NULL) < 0) { + if (map__load(machine.vmlinux_maps[MAP__FUNCTION], NULL) < 0) { pr_debug("Failed to load kernel map.\n"); return -EINVAL; } - pr_debug("Try to open %s\n", kmaps[MAP__FUNCTION]->dso->long_name); - return open(kmaps[MAP__FUNCTION]->dso->long_name, O_RDONLY); + pr_debug("Try to open %s\n", machine.vmlinux_maps[MAP__FUNCTION]->dso->long_name); + return open(machine.vmlinux_maps[MAP__FUNCTION]->dso->long_name, O_RDONLY); } /* Convert trace point to probe point with debuginfo */ @@ -125,7 +127,7 @@ static int convert_to_perf_probe_point(struct kprobe_trace_point *tp, struct symbol *sym; int fd, ret = -ENOENT; - sym = map__find_symbol_by_name(kmaps[MAP__FUNCTION], + sym = map__find_symbol_by_name(machine.vmlinux_maps[MAP__FUNCTION], tp->symbol, NULL); if (sym) { fd = open_vmlinux(); @@ -1466,7 +1468,7 @@ static int convert_to_kprobe_trace_events(struct perf_probe_event *pev, } /* Currently just checking function name from symbol map */ - sym = map__find_symbol_by_name(kmaps[MAP__FUNCTION], + sym = map__find_symbol_by_name(machine.vmlinux_maps[MAP__FUNCTION], tev->point.symbol, NULL); if (!sym) { pr_warning("Kernel symbol \'%s\' not found.\n", diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index b745c1c..a8dd73e 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -69,12 +69,11 @@ void perf_session__update_sample_type(struct perf_session *self) int perf_session__create_kernel_maps(struct perf_session *self) { - int ret; - struct rb_root *root = &self->machines; + struct rb_root *machines = &self->machines; + int ret = machines__create_kernel_maps(machines, HOST_KERNEL_ID); - ret = map_groups__create_kernel_maps(root, HOST_KERNEL_ID); if (ret >= 0) - ret = map_groups__create_guest_kernel_maps(root); + ret = machines__create_guest_kernel_maps(machines); return ret; } diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index c9c0bdd..12359c3 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1528,21 +1528,20 @@ static char *get_kernel_version(const char *root_dir) return strdup(name); } -static int map_groups__set_modules_path(struct map_groups *self, - const char *root_dir) +static int machine__set_modules_path(struct machine *self) { char *version; char modules_path[PATH_MAX]; - version = get_kernel_version(root_dir); + version = get_kernel_version(self->root_dir); if (!version) return -1; snprintf(modules_path, sizeof(modules_path), "%s/lib/modules/%s/kernel", - root_dir, version); + self->root_dir, version); free(version); - return map_groups__set_modules_path_dir(self, modules_path); + return map_groups__set_modules_path_dir(&self->kmaps, modules_path); } /* @@ -1564,14 +1563,12 @@ static struct map *map__new2(u64 start, struct dso *dso, enum map_type type) return self; } -struct map *map_groups__new_module(struct map_groups *self, u64 start, - const char *filename, - struct machine *machine) +struct map *machine__new_module(struct machine *self, u64 start, + const char *filename) { struct map *map; - struct dso *dso; + struct dso *dso = __dsos__findnew(&self->kernel_dsos, filename); - dso = __dsos__findnew(&machine->kernel_dsos, filename); if (dso == NULL) return NULL; @@ -1579,28 +1576,27 @@ struct map *map_groups__new_module(struct map_groups *self, u64 start, if (map == NULL) return NULL; - if (machine__is_host(machine)) + if (machine__is_host(self)) dso->origin = DSO__ORIG_KMODULE; else dso->origin = DSO__ORIG_GUEST_KMODULE; - map_groups__insert(self, map); + map_groups__insert(&self->kmaps, map); return map; } -static int map_groups__create_modules(struct machine *machine) +static int machine__create_modules(struct machine *self) { char *line = NULL; size_t n; FILE *file; struct map *map; - const char *root_dir; const char *modules; char path[PATH_MAX]; - if (machine__is_default_guest(machine)) + if (machine__is_default_guest(self)) modules = symbol_conf.default_guest_modules; else { - sprintf(path, "%s/proc/modules", machine->root_dir); + sprintf(path, "%s/proc/modules", self->root_dir); modules = path; } @@ -1608,8 +1604,6 @@ static int map_groups__create_modules(struct machine *machine) if (file == NULL) return -1; - root_dir = machine->root_dir; - while (!feof(file)) { char name[PATH_MAX]; u64 start; @@ -1638,17 +1632,16 @@ static int map_groups__create_modules(struct machine *machine) *sep = '\0'; snprintf(name, sizeof(name), "[%s]", line); - map = map_groups__new_module(&machine->kmaps, start, - name, machine); + map = machine__new_module(self, start, name); if (map == NULL) goto out_delete_line; - dso__kernel_module_get_build_id(map->dso, root_dir); + dso__kernel_module_get_build_id(map->dso, self->root_dir); } free(line); fclose(file); - return map_groups__set_modules_path(&machine->kmaps, root_dir); + return machine__set_modules_path(self); out_delete_line: free(line); @@ -2005,25 +1998,23 @@ static struct dso *dsos__create_kernel(struct machine *machine) return kernel; } -int __map_groups__create_kernel_maps(struct map_groups *self, - struct map *vmlinux_maps[MAP__NR_TYPES], - struct dso *kernel) +int __machine__create_kernel_maps(struct machine *self, struct dso *kernel) { enum map_type type; for (type = 0; type < MAP__NR_TYPES; ++type) { struct kmap *kmap; - vmlinux_maps[type] = map__new2(0, kernel, type); - if (vmlinux_maps[type] == NULL) + self->vmlinux_maps[type] = map__new2(0, kernel, type); + if (self->vmlinux_maps[type] == NULL) return -1; - vmlinux_maps[type]->map_ip = - vmlinux_maps[type]->unmap_ip = identity__map_ip; + self->vmlinux_maps[type]->map_ip = + self->vmlinux_maps[type]->unmap_ip = identity__map_ip; - kmap = map__kmap(vmlinux_maps[type]); - kmap->kmaps = self; - map_groups__insert(self, vmlinux_maps[type]); + kmap = map__kmap(self->vmlinux_maps[type]); + kmap->kmaps = &self->kmaps; + map_groups__insert(&self->kmaps, self->vmlinux_maps[type]); } return 0; @@ -2145,10 +2136,10 @@ out_free_comm_list: return -1; } -int map_groups__create_kernel_maps(struct rb_root *machines, pid_t pid) +int machines__create_kernel_maps(struct rb_root *self, pid_t pid) { struct dso *kernel; - struct machine *machine = machines__findnew(machines, pid); + struct machine *machine = machines__findnew(self, pid); if (machine == NULL) return -1; @@ -2156,12 +2147,10 @@ int map_groups__create_kernel_maps(struct rb_root *machines, pid_t pid) if (kernel == NULL) return -1; - if (__map_groups__create_kernel_maps(&machine->kmaps, - machine->vmlinux_maps, kernel) < 0) + if (__machine__create_kernel_maps(machine, kernel) < 0) return -1; - if (symbol_conf.use_modules && - map_groups__create_modules(machine) < 0) + if (symbol_conf.use_modules && machine__create_modules(machine) < 0) pr_debug("Problems creating module maps, continuing anyway...\n"); /* * Now that we have all the maps created, just set the ->end of them: @@ -2213,7 +2202,7 @@ char *strxfrchar(char *s, char from, char to) return s; } -int map_groups__create_guest_kernel_maps(struct rb_root *machines) +int machines__create_guest_kernel_maps(struct rb_root *self) { int ret = 0; struct dirent **namelist = NULL; @@ -2224,7 +2213,7 @@ int map_groups__create_guest_kernel_maps(struct rb_root *machines) if (symbol_conf.default_guest_vmlinux_name || symbol_conf.default_guest_modules || symbol_conf.default_guest_kallsyms) { - map_groups__create_kernel_maps(machines, DEFAULT_GUEST_KERNEL_ID); + machines__create_kernel_maps(self, DEFAULT_GUEST_KERNEL_ID); } if (symbol_conf.guestmount) { @@ -2245,7 +2234,7 @@ int map_groups__create_guest_kernel_maps(struct rb_root *machines) pr_debug("Can't access file %s\n", path); goto failure; } - map_groups__create_kernel_maps(machines, pid); + machines__create_kernel_maps(self, pid); } failure: free(namelist); diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index ed885b0..37b717b 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -199,11 +199,9 @@ int kallsyms__parse(const char *filename, void *arg, int (*process_symbol)(void *arg, const char *name, char type, u64 start)); -int __map_groups__create_kernel_maps(struct map_groups *self, - struct map *vmlinux_maps[MAP__NR_TYPES], - struct dso *kernel); -int map_groups__create_kernel_maps(struct rb_root *kerninfo_root, pid_t pid); -int map_groups__create_guest_kernel_maps(struct rb_root *kerninfo_root); +int __machine__create_kernel_maps(struct machine *self, struct dso *kernel); +int machines__create_kernel_maps(struct rb_root *self, pid_t pid); +int machines__create_guest_kernel_maps(struct rb_root *self); int symbol__init(void); bool symbol_type__is_a(char symbol_type, enum map_type map_type); -- cgit v0.10.2 From cbf6968098f89d3216d074f06544b5032b344da4 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 27 Apr 2010 21:22:44 -0300 Subject: perf machines: Make the machines class adopt the dsos__fprintf methods MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now those methods don't operate on a global list of dsos, but on lists of machines, so make this clear by renaming the functions. Cc: Avi Kivity Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Zhang, Yanmin LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 986b2ef..b57dbcf 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -571,7 +571,7 @@ static int __cmd_annotate(void) perf_session__fprintf(session, stdout); if (verbose > 2) - dsos__fprintf(&session->machines, stdout); + perf_session__fprintf_dsos(session, stdout); perf_session__collapse_resort(&session->hists); perf_session__output_resort(&session->hists, session->event_total[0]); diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c index b4a265a..7dc3b2e 100644 --- a/tools/perf/builtin-buildid-list.c +++ b/tools/perf/builtin-buildid-list.c @@ -46,7 +46,7 @@ static int __cmd_buildid_list(void) if (with_hits) perf_session__process_events(session, &build_id__mark_dso_hit_ops); - dsos__fprintf_buildid(&session->machines, stdout, with_hits); + perf_session__fprintf_dsos_buildid(session, stdout, with_hits); perf_session__delete(session); return err; diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 49cc367..f1b46eb 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -313,7 +313,7 @@ static int __cmd_report(void) perf_session__fprintf(session, stdout); if (verbose > 2) - dsos__fprintf(&session->machines, stdout); + perf_session__fprintf_dsos(session, stdout); next = rb_first(&session->stats_by_id); while (next) { diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index c390f34..d95281f 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -854,7 +854,7 @@ static void handle_keypress(struct perf_session *session, int c) case 'Q': printf("exiting.\n"); if (dump_symtab) - dsos__fprintf(&session->machines, stderr); + perf_session__fprintf_dsos(session, stderr); exit(0); case 's': prompt_symbol(&sym_filter_entry, "Enter details symbol"); diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 7125272..61ca92e 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -127,4 +127,17 @@ void perf_session__process_machines(struct perf_session *self, { return machines__process(&self->machines, process, self); } + +static inline +size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp) +{ + return machines__fprintf_dsos(&self->machines, fp); +} + +static inline +size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, FILE *fp, + bool with_hits) +{ + return machines__fprintf_dsos_buildid(&self->machines, fp, with_hits); +} #endif /* __PERF_SESSION_H */ diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 12359c3..caa890f 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1889,26 +1889,32 @@ struct dso *__dsos__findnew(struct list_head *head, const char *name) return dso; } -static void __dsos__fprintf(struct list_head *head, FILE *fp) +static size_t __dsos__fprintf(struct list_head *head, FILE *fp) { struct dso *pos; + size_t ret = 0; list_for_each_entry(pos, head, node) { int i; for (i = 0; i < MAP__NR_TYPES; ++i) - dso__fprintf(pos, i, fp); + ret += dso__fprintf(pos, i, fp); } + + return ret; } -void dsos__fprintf(struct rb_root *machines, FILE *fp) +size_t machines__fprintf_dsos(struct rb_root *self, FILE *fp) { struct rb_node *nd; + size_t ret = 0; - for (nd = rb_first(machines); nd; nd = rb_next(nd)) { + for (nd = rb_first(self); nd; nd = rb_next(nd)) { struct machine *pos = rb_entry(nd, struct machine, rb_node); - __dsos__fprintf(&pos->kernel_dsos, fp); - __dsos__fprintf(&pos->user_dsos, fp); + ret += __dsos__fprintf(&pos->kernel_dsos, fp); + ret += __dsos__fprintf(&pos->user_dsos, fp); } + + return ret; } static size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, @@ -1926,12 +1932,12 @@ static size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, return ret; } -size_t dsos__fprintf_buildid(struct rb_root *machines, FILE *fp, bool with_hits) +size_t machines__fprintf_dsos_buildid(struct rb_root *self, FILE *fp, bool with_hits) { struct rb_node *nd; size_t ret = 0; - for (nd = rb_first(machines); nd; nd = rb_next(nd)) { + for (nd = rb_first(self); nd; nd = rb_next(nd)) { struct machine *pos = rb_entry(nd, struct machine, rb_node); ret += __dsos__fprintf_buildid(&pos->kernel_dsos, fp, with_hits); ret += __dsos__fprintf_buildid(&pos->user_dsos, fp, with_hits); diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 37b717b..2cec6a1 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -162,9 +162,8 @@ int dso__load_vmlinux_path(struct dso *self, struct map *map, symbol_filter_t filter); int dso__load_kallsyms(struct dso *self, const char *filename, struct map *map, symbol_filter_t filter); -void dsos__fprintf(struct rb_root *kerninfo_root, FILE *fp); -size_t dsos__fprintf_buildid(struct rb_root *kerninfo_root, - FILE *fp, bool with_hits); +size_t machines__fprintf_dsos(struct rb_root *self, FILE *fp); +size_t machines__fprintf_dsos_buildid(struct rb_root *self, FILE *fp, bool with_hits); size_t dso__fprintf_buildid(struct dso *self, FILE *fp); size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp); -- cgit v0.10.2 From ebe6aa5ac456a13213ed563863e70dd441618a97 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Sat, 24 Apr 2010 07:57:47 -0400 Subject: cifs: eliminate "first_time" parm to CIFS_SessSetup We can use the is_first_ses_reconnect() function to determine this. Signed-off-by: Jeff Layton Signed-off-by: Steve French diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index cc622a7..8e92142 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -95,7 +95,6 @@ extern int small_smb_init_no_tc(const int smb_cmd, const int wct, struct cifsSesInfo *ses, void **request_buf); extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, - const int stage, const struct nls_table *nls_cp); extern __u16 GetNextMid(struct TCP_Server_Info *server); extern struct timespec cifs_NTtimeToUnix(__le64 utc_nanoseconds_since_1601); diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 7a47c7c..9123c23 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -2878,7 +2878,6 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, struct nls_table *nls_info) { int rc = 0; - int first_time = 0; struct TCP_Server_Info *server = pSesInfo->server; /* what if server changes its buffer size after dropping the session? */ @@ -2899,7 +2898,6 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, spin_unlock(&GlobalMid_Lock); } - first_time = 1; } if (rc) @@ -2913,7 +2911,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, cFYI(1, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d", server->secMode, server->capabilities, server->timeAdj); - rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info); + rc = CIFS_SessSetup(xid, pSesInfo, nls_info); if (rc) { cERROR(1, "Send error in SessSetup = %d", rc); } else { diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index da9729d..84b92df 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -35,9 +35,11 @@ extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24); -/* Checks if this is the first smb session to be reconnected after - the socket has been reestablished (so we know whether to use vc 0). - Called while holding the cifs_tcp_ses_lock, so do not block */ +/* + * Checks if this is the first smb session to be reconnected after + * the socket has been reestablished (so we know whether to use vc 0). + * Called while holding the cifs_tcp_ses_lock, so do not block + */ static bool is_first_ses_reconnect(struct cifsSesInfo *ses) { struct list_head *tmp; @@ -447,7 +449,7 @@ static void build_ntlmssp_negotiate_blob(unsigned char *pbuffer, This function returns the length of the data in the blob */ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, struct cifsSesInfo *ses, - const struct nls_table *nls_cp, int first) + const struct nls_table *nls_cp, bool first) { AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer; __u32 flags; @@ -546,7 +548,7 @@ static void setup_ntlmssp_neg_req(SESSION_SETUP_ANDX *pSMB, static int setup_ntlmssp_auth_req(SESSION_SETUP_ANDX *pSMB, struct cifsSesInfo *ses, - const struct nls_table *nls, int first_time) + const struct nls_table *nls, bool first_time) { int bloblen; @@ -559,8 +561,8 @@ static int setup_ntlmssp_auth_req(SESSION_SETUP_ANDX *pSMB, #endif int -CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, - const struct nls_table *nls_cp) +CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, + const struct nls_table *nls_cp) { int rc = 0; int wct; @@ -577,10 +579,15 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, int bytes_remaining; struct key *spnego_key = NULL; __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */ + bool first_time; if (ses == NULL) return -EINVAL; + read_lock(&cifs_tcp_ses_lock); + first_time = is_first_ses_reconnect(ses); + read_unlock(&cifs_tcp_ses_lock); + type = ses->server->secType; cFYI(1, "sess setup type %d", type); -- cgit v0.10.2 From 37e44bc50d91df1fe7edcf6f02fe168c6d802e64 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 27 Apr 2010 21:04:24 -0400 Subject: tracing: Fix sleep time function profiling When sleep_time is off the function profiler ignores the time that a task is scheduled out. When the task is scheduled out a timestamp is taken. When the task is scheduled back in, the timestamp is compared to the current time and the saved calltimes are adjusted accordingly. But when stopping the function profiler, the sched switch hook that does this adjustment was stopped before shutting down the tracer. This allowed some tasks to not get their timestamps set when they scheduled out. When the function profiler started again, this would skew the times of the scheduler functions. This patch moves the stopping of the sched switch to after the function profiler is stopped. It also ignores zero set calltimes, which may happen on start up. Signed-off-by: Steven Rostedt diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 3bcb340..8c9c293 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -666,6 +666,10 @@ static void profile_graph_return(struct ftrace_graph_ret *trace) if (!stat->hash || !ftrace_profile_enabled) goto out; + /* If the calltime was zero'd ignore it */ + if (!trace->calltime) + goto out; + calltime = trace->rettime - trace->calltime; if (!(trace_flags & TRACE_ITER_GRAPH_TIME)) { @@ -3357,11 +3361,11 @@ void unregister_ftrace_graph(void) goto out; ftrace_graph_active--; - unregister_trace_sched_switch(ftrace_graph_probe_sched_switch); ftrace_graph_return = (trace_func_graph_ret_t)ftrace_stub; ftrace_graph_entry = ftrace_graph_entry_stub; ftrace_shutdown(FTRACE_STOP_FUNC_RET); unregister_pm_notifier(&ftrace_suspend_notifier); + unregister_trace_sched_switch(ftrace_graph_probe_sched_switch); out: mutex_unlock(&ftrace_lock); -- cgit v0.10.2 From 18acde52b83bd1c8e1d007db519f46d344aa13ed Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 27 Apr 2010 22:26:51 -0300 Subject: perf tools: Create $(OUTPUT)arch/$(ARCH)/util/ directory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So that "make -C tools/perf O=/tmp/some/path" works again. Problem introduced in: cd932c5 "perf: Move arch specific code into separate arch director" Cc: Ian Munsie Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 3ac6b67..b86f2ad 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -187,6 +187,8 @@ ifeq ($(ARCH),x86_64) ARCH := x86 endif +$(shell sh -c 'mkdir -p $(OUTPUT)arch/$(ARCH)/util/' 2> /dev/null) + # CFLAGS and LDFLAGS are for the users to override from the command line. # -- cgit v0.10.2 From 402af0d7c692ddcfa2333e93d3f275ebd0487926 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Wed, 21 Apr 2010 15:21:51 +0100 Subject: x86, asm: Introduce and use percpu_inc() ... generating slightly smaller code. Signed-off-by: Jan Beulich LKML-Reference: <4BCF261F020000780003B33C@vpn.id2.novell.com> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/include/asm/hardirq.h b/arch/x86/include/asm/hardirq.h index 0f85764..aeab29a 100644 --- a/arch/x86/include/asm/hardirq.h +++ b/arch/x86/include/asm/hardirq.h @@ -35,7 +35,7 @@ DECLARE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat); #define __ARCH_IRQ_STAT -#define inc_irq_stat(member) percpu_add(irq_stat.member, 1) +#define inc_irq_stat(member) percpu_inc(irq_stat.member) #define local_softirq_pending() percpu_read(irq_stat.__softirq_pending) diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h index 66a272d..0ec6d12 100644 --- a/arch/x86/include/asm/percpu.h +++ b/arch/x86/include/asm/percpu.h @@ -190,6 +190,29 @@ do { \ pfo_ret__; \ }) +#define percpu_unary_op(op, var) \ +({ \ + switch (sizeof(var)) { \ + case 1: \ + asm(op "b "__percpu_arg(0) \ + : "+m" (var)); \ + break; \ + case 2: \ + asm(op "w "__percpu_arg(0) \ + : "+m" (var)); \ + break; \ + case 4: \ + asm(op "l "__percpu_arg(0) \ + : "+m" (var)); \ + break; \ + case 8: \ + asm(op "q "__percpu_arg(0) \ + : "+m" (var)); \ + break; \ + default: __bad_percpu_size(); \ + } \ +}) + /* * percpu_read() makes gcc load the percpu variable every time it is * accessed while percpu_read_stable() allows the value to be cached. @@ -207,6 +230,7 @@ do { \ #define percpu_and(var, val) percpu_to_op("and", var, val) #define percpu_or(var, val) percpu_to_op("or", var, val) #define percpu_xor(var, val) percpu_to_op("xor", var, val) +#define percpu_inc(var) percpu_unary_op("inc", var) #define __this_cpu_read_1(pcp) percpu_from_op("mov", (pcp), "m"(pcp)) #define __this_cpu_read_2(pcp) percpu_from_op("mov", (pcp), "m"(pcp)) diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 8a6f0af..7a355dd 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -539,7 +539,7 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b) struct mce m; int i; - __get_cpu_var(mce_poll_count)++; + percpu_inc(mce_poll_count); mce_setup(&m); @@ -934,7 +934,7 @@ void do_machine_check(struct pt_regs *regs, long error_code) atomic_inc(&mce_entry); - __get_cpu_var(mce_exception_count)++; + percpu_inc(mce_exception_count); if (notify_die(DIE_NMI, "machine check", regs, error_code, 18, SIGKILL) == NOTIFY_STOP) -- cgit v0.10.2 From 2e61878698781d6a9a8bfbaa4ea9c5ddb5a178c3 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Wed, 21 Apr 2010 16:13:20 +0100 Subject: x86-64: Combine SRAT regions when possible ... i.e. when the hole between two regions isn't occupied by memory on another node. This reduces the memory->node table size, thus reducing cache footprint of lookups, which got increased significantly some time ago, and things go back to how they were before that change on the systems I looked at. Signed-off-by: Jan Beulich LKML-Reference: <4BCF3230020000780003B3CA@vpn.id2.novell.com> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/mm/srat_64.c b/arch/x86/mm/srat_64.c index 28c6876..3ebe651 100644 --- a/arch/x86/mm/srat_64.c +++ b/arch/x86/mm/srat_64.c @@ -363,6 +363,54 @@ int __init acpi_scan_nodes(unsigned long start, unsigned long end) for (i = 0; i < MAX_NUMNODES; i++) cutoff_node(i, start, end); + /* + * Join together blocks on the same node, holes between + * which don't overlap with memory on other nodes. + */ + for (i = 0; i < num_node_memblks; ++i) { + int j, k; + + for (j = i + 1; j < num_node_memblks; ++j) { + unsigned long start, end; + + if (memblk_nodeid[i] != memblk_nodeid[j]) + continue; + start = min(node_memblk_range[i].end, + node_memblk_range[j].end); + end = max(node_memblk_range[i].start, + node_memblk_range[j].start); + for (k = 0; k < num_node_memblks; ++k) { + if (memblk_nodeid[i] == memblk_nodeid[k]) + continue; + if (start < node_memblk_range[k].end && + end > node_memblk_range[k].start) + break; + } + if (k < num_node_memblks) + continue; + start = min(node_memblk_range[i].start, + node_memblk_range[j].start); + end = max(node_memblk_range[i].end, + node_memblk_range[j].end); + printk(KERN_INFO "SRAT: Node %d " + "[%Lx,%Lx) + [%Lx,%Lx) -> [%lx,%lx)\n", + memblk_nodeid[i], + node_memblk_range[i].start, + node_memblk_range[i].end, + node_memblk_range[j].start, + node_memblk_range[j].end, + start, end); + node_memblk_range[i].start = start; + node_memblk_range[i].end = end; + k = --num_node_memblks - j; + memmove(memblk_nodeid + j, memblk_nodeid + j+1, + k * sizeof(*memblk_nodeid)); + memmove(node_memblk_range + j, node_memblk_range + j+1, + k * sizeof(*node_memblk_range)); + --j; + } + } + memnode_shift = compute_hash_shift(node_memblk_range, num_node_memblks, memblk_nodeid); if (memnode_shift < 0) { -- cgit v0.10.2 From 5967ed87ade85a421ef814296c3c7f182b08c225 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Wed, 21 Apr 2010 16:08:14 +0100 Subject: x86-64: Reduce SMP locks table size Reduce the SMP locks table size by using relative pointers instead of absolute ones, thus cutting the table size by half. Signed-off-by: Jan Beulich LKML-Reference: <4BCF30FE020000780003B3B6@vpn.id2.novell.com> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/include/asm/alternative-asm.h b/arch/x86/include/asm/alternative-asm.h index b97f786..a63a68b 100644 --- a/arch/x86/include/asm/alternative-asm.h +++ b/arch/x86/include/asm/alternative-asm.h @@ -6,8 +6,8 @@ .macro LOCK_PREFIX 1: lock .section .smp_locks,"a" - _ASM_ALIGN - _ASM_PTR 1b + .balign 4 + .long 1b - . .previous .endm #else diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h index b09ec55..714bf24 100644 --- a/arch/x86/include/asm/alternative.h +++ b/arch/x86/include/asm/alternative.h @@ -30,8 +30,8 @@ #ifdef CONFIG_SMP #define LOCK_PREFIX \ ".section .smp_locks,\"a\"\n" \ - _ASM_ALIGN "\n" \ - _ASM_PTR "661f\n" /* address */ \ + ".balign 4\n" \ + ".long 661f - .\n" /* offset */ \ ".previous\n" \ "661:\n\tlock; " diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index 1a160d5..9367384 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -194,7 +194,7 @@ static void __init_or_module add_nops(void *insns, unsigned int len) } extern struct alt_instr __alt_instructions[], __alt_instructions_end[]; -extern u8 *__smp_locks[], *__smp_locks_end[]; +extern s32 __smp_locks[], __smp_locks_end[]; static void *text_poke_early(void *addr, const void *opcode, size_t len); /* Replace instructions with better alternatives for this CPU type. @@ -235,37 +235,39 @@ void __init_or_module apply_alternatives(struct alt_instr *start, #ifdef CONFIG_SMP -static void alternatives_smp_lock(u8 **start, u8 **end, u8 *text, u8 *text_end) +static void alternatives_smp_lock(const s32 *start, const s32 *end, + u8 *text, u8 *text_end) { - u8 **ptr; + const s32 *poff; mutex_lock(&text_mutex); - for (ptr = start; ptr < end; ptr++) { - if (*ptr < text) - continue; - if (*ptr > text_end) + for (poff = start; poff < end; poff++) { + u8 *ptr = (u8 *)poff + *poff; + + if (!*poff || ptr < text || ptr >= text_end) continue; /* turn DS segment override prefix into lock prefix */ - text_poke(*ptr, ((unsigned char []){0xf0}), 1); + text_poke(ptr, ((unsigned char []){0xf0}), 1); }; mutex_unlock(&text_mutex); } -static void alternatives_smp_unlock(u8 **start, u8 **end, u8 *text, u8 *text_end) +static void alternatives_smp_unlock(const s32 *start, const s32 *end, + u8 *text, u8 *text_end) { - u8 **ptr; + const s32 *poff; if (noreplace_smp) return; mutex_lock(&text_mutex); - for (ptr = start; ptr < end; ptr++) { - if (*ptr < text) - continue; - if (*ptr > text_end) + for (poff = start; poff < end; poff++) { + u8 *ptr = (u8 *)poff + *poff; + + if (!*poff || ptr < text || ptr >= text_end) continue; /* turn lock prefix into DS segment override prefix */ - text_poke(*ptr, ((unsigned char []){0x3E}), 1); + text_poke(ptr, ((unsigned char []){0x3E}), 1); }; mutex_unlock(&text_mutex); } @@ -276,8 +278,8 @@ struct smp_alt_module { char *name; /* ptrs to lock prefixes */ - u8 **locks; - u8 **locks_end; + const s32 *locks; + const s32 *locks_end; /* .text segment, needed to avoid patching init code ;) */ u8 *text; @@ -398,16 +400,19 @@ void alternatives_smp_switch(int smp) int alternatives_text_reserved(void *start, void *end) { struct smp_alt_module *mod; - u8 **ptr; + const s32 *poff; u8 *text_start = start; u8 *text_end = end; list_for_each_entry(mod, &smp_alt_modules, next) { if (mod->text > text_end || mod->text_end < text_start) continue; - for (ptr = mod->locks; ptr < mod->locks_end; ptr++) - if (text_start <= *ptr && text_end >= *ptr) + for (poff = mod->locks; poff < mod->locks_end; poff++) { + const u8 *ptr = (const u8 *)poff + *poff; + + if (text_start <= ptr && text_end > ptr) return 1; + } } return 0; -- cgit v0.10.2 From 47f9fe26299ae022ac1e3fa12e7e73def62b7898 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Wed, 21 Apr 2010 16:19:57 +0100 Subject: x86-64: Don't export init_level4_pgt It's not used by any module, and i386 (as well as some other arches) also doesn't export its equivalent (swapper_pg_dir). Signed-off-by: Jan Beulich LKML-Reference: <4BCF33BD020000780003B3E4@vpn.id2.novell.com> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c index 693920b..1b950d1 100644 --- a/arch/x86/kernel/x8664_ksyms_64.c +++ b/arch/x86/kernel/x8664_ksyms_64.c @@ -54,7 +54,6 @@ EXPORT_SYMBOL(memcpy); EXPORT_SYMBOL(__memcpy); EXPORT_SYMBOL(empty_zero_page); -EXPORT_SYMBOL(init_level4_pgt); #ifndef CONFIG_PARAVIRT EXPORT_SYMBOL(native_load_gs_index); #endif -- cgit v0.10.2 From 6fc108a08dcddf8f9113cc7102ddaacf7ed37a6b Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Wed, 21 Apr 2010 15:23:44 +0100 Subject: x86: Clean up arch/x86/Kconfig* No functional change intended. Signed-off-by: Jan Beulich LKML-Reference: <4BCF2690020000780003B340@vpn.id2.novell.com> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 9458685..85e2252 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -197,20 +197,17 @@ config HAVE_INTEL_TXT # Use the generic interrupt handling code in kernel/irq/: config GENERIC_HARDIRQS - bool - default y + def_bool y config GENERIC_HARDIRQS_NO__DO_IRQ def_bool y config GENERIC_IRQ_PROBE - bool - default y + def_bool y config GENERIC_PENDING_IRQ - bool + def_bool y depends on GENERIC_HARDIRQS && SMP - default y config USE_GENERIC_SMP_HELPERS def_bool y @@ -225,14 +222,12 @@ config X86_64_SMP depends on X86_64 && SMP config X86_HT - bool + def_bool y depends on SMP - default y config X86_TRAMPOLINE - bool + def_bool y depends on SMP || (64BIT && ACPI_SLEEP) - default y config X86_32_LAZY_GS def_bool y @@ -447,7 +442,7 @@ config X86_NUMAQ firmware with - send email to . config X86_SUPPORTS_MEMORY_FAILURE - bool + def_bool y # MCE code calls memory_failure(): depends on X86_MCE # On 32-bit this adds too big of NODES_SHIFT and we run out of page flags: @@ -455,7 +450,6 @@ config X86_SUPPORTS_MEMORY_FAILURE # On 32-bit SPARSEMEM adds too big of SECTIONS_WIDTH: depends on X86_64 || !SPARSEMEM select ARCH_SUPPORTS_MEMORY_FAILURE - default y config X86_VISWS bool "SGI 320/540 (Visual Workstation)" @@ -570,7 +564,6 @@ config PARAVIRT_SPINLOCKS config PARAVIRT_CLOCK bool - default n endif @@ -749,7 +742,6 @@ config MAXSMP bool "Configure Maximum number of SMP Processors and NUMA Nodes" depends on X86_64 && SMP && DEBUG_KERNEL && EXPERIMENTAL select CPUMASK_OFFSTACK - default n ---help--- Configure maximum number of CPUS and NUMA Nodes for this architecture. If unsure, say N. @@ -829,7 +821,6 @@ config X86_VISWS_APIC config X86_REROUTE_FOR_BROKEN_BOOT_IRQS bool "Reroute for broken boot IRQs" - default n depends on X86_IO_APIC ---help--- This option enables a workaround that fixes a source of @@ -876,9 +867,8 @@ config X86_MCE_AMD the DRAM Error Threshold. config X86_ANCIENT_MCE - def_bool n + bool "Support for old Pentium 5 / WinChip machine checks" depends on X86_32 && X86_MCE - prompt "Support for old Pentium 5 / WinChip machine checks" ---help--- Include support for machine check handling on old Pentium 5 or WinChip systems. These typically need to be enabled explicitely on the command @@ -886,8 +876,7 @@ config X86_ANCIENT_MCE config X86_MCE_THRESHOLD depends on X86_MCE_AMD || X86_MCE_INTEL - bool - default y + def_bool y config X86_MCE_INJECT depends on X86_MCE @@ -1026,8 +1015,8 @@ config X86_CPUID choice prompt "High Memory Support" - default HIGHMEM4G if !X86_NUMAQ default HIGHMEM64G if X86_NUMAQ + default HIGHMEM4G depends on X86_32 config NOHIGHMEM @@ -1285,7 +1274,7 @@ source "mm/Kconfig" config HIGHPTE bool "Allocate 3rd-level pagetables from highmem" - depends on X86_32 && (HIGHMEM4G || HIGHMEM64G) + depends on HIGHMEM ---help--- The VM uses one page table entry for each page of physical memory. For systems with a lot of RAM, this can be wasteful of precious @@ -1369,8 +1358,7 @@ config MATH_EMULATION kernel, it won't hurt. config MTRR - bool - default y + def_bool y prompt "MTRR (Memory Type Range Register) support" if EMBEDDED ---help--- On Intel P6 family processors (Pentium Pro, Pentium II and later) @@ -1436,8 +1424,7 @@ config MTRR_SANITIZER_SPARE_REG_NR_DEFAULT mtrr_spare_reg_nr=N on the kernel command line. config X86_PAT - bool - default y + def_bool y prompt "x86 PAT support" if EMBEDDED depends on MTRR ---help--- @@ -1605,8 +1592,7 @@ config X86_NEED_RELOCS depends on X86_32 && RELOCATABLE config PHYSICAL_ALIGN - hex - prompt "Alignment value to which kernel should be aligned" if X86_32 + hex "Alignment value to which kernel should be aligned" if X86_32 default "0x1000000" range 0x2000 0x1000000 ---help--- @@ -1653,7 +1639,6 @@ config COMPAT_VDSO config CMDLINE_BOOL bool "Built-in kernel command line" - default n ---help--- Allow for specifying boot arguments to the kernel at build time. On some systems (e.g. embedded ones), it is @@ -1687,7 +1672,6 @@ config CMDLINE config CMDLINE_OVERRIDE bool "Built-in command line overrides boot loader arguments" - default n depends on CMDLINE_BOOL ---help--- Set this option to 'Y' to have the kernel ignore the boot loader @@ -1723,8 +1707,7 @@ source "drivers/acpi/Kconfig" source "drivers/sfi/Kconfig" config X86_APM_BOOT - bool - default y + def_bool y depends on APM || APM_MODULE menuconfig APM @@ -1953,8 +1936,7 @@ config DMAR_DEFAULT_ON experimental. config DMAR_BROKEN_GFX_WA - def_bool n - prompt "Workaround broken graphics drivers (going away soon)" + bool "Workaround broken graphics drivers (going away soon)" depends on DMAR && BROKEN ---help--- Current Graphics drivers tend to use physical address @@ -2052,7 +2034,6 @@ config SCx200HR_TIMER config OLPC bool "One Laptop Per Child support" select GPIOLIB - default n ---help--- Add support for detecting the unique features of the OLPC XO hardware. diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index bc01e3e..e7edd66 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -45,7 +45,6 @@ config EARLY_PRINTK config EARLY_PRINTK_DBGP bool "Early printk via EHCI debug port" - default n depends on EARLY_PRINTK && PCI ---help--- Write kernel log output directly into the EHCI debug port. @@ -76,7 +75,6 @@ config DEBUG_PER_CPU_MAPS bool "Debug access to per_cpu maps" depends on DEBUG_KERNEL depends on SMP - default n ---help--- Say Y to verify that the per_cpu map being accessed has been setup. Adds a fair amount of code to kernel memory diff --git a/arch/x86/include/asm/boot.h b/arch/x86/include/asm/boot.h index 7a10659..3b62ab5 100644 --- a/arch/x86/include/asm/boot.h +++ b/arch/x86/include/asm/boot.h @@ -24,7 +24,7 @@ #define MIN_KERNEL_ALIGN (_AC(1, UL) << MIN_KERNEL_ALIGN_LG2) #if (CONFIG_PHYSICAL_ALIGN & (CONFIG_PHYSICAL_ALIGN-1)) || \ - (CONFIG_PHYSICAL_ALIGN < (_AC(1, UL) << MIN_KERNEL_ALIGN_LG2)) + (CONFIG_PHYSICAL_ALIGN < MIN_KERNEL_ALIGN) #error "Invalid value for CONFIG_PHYSICAL_ALIGN" #endif -- cgit v0.10.2 From 3272c8a57b77a7277a740e211fe12171e4b37e99 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 21 Apr 2010 12:33:54 +0200 Subject: logfs: testing the wrong variable There is a typo here. We should test "last" instead of "first". Signed-off-by: Dan Carpenter Signed-off-by: Joern Engel diff --git a/fs/logfs/super.c b/fs/logfs/super.c index 5866ee6..7fc4625 100644 --- a/fs/logfs/super.c +++ b/fs/logfs/super.c @@ -382,7 +382,7 @@ static struct page *find_super_block(struct super_block *sb) if (!first || IS_ERR(first)) return NULL; last = super->s_devops->find_last_sb(sb, &super->s_sb_ofs[1]); - if (!last || IS_ERR(first)) { + if (!last || IS_ERR(last)) { page_cache_release(first); return NULL; } -- cgit v0.10.2 From 2e531fa0d0868f5114c2b3a782ab02eb9d6f914d Mon Sep 17 00:00:00 2001 From: Joern Engel Date: Thu, 29 Apr 2010 14:56:37 +0200 Subject: LogFS: Fix typo in b6349ac8 Signed-off-by: Joern Engel diff --git a/fs/logfs/readwrite.c b/fs/logfs/readwrite.c index 3159db6..8c663a5 100644 --- a/fs/logfs/readwrite.c +++ b/fs/logfs/readwrite.c @@ -1861,7 +1861,7 @@ int logfs_truncate(struct inode *inode, u64 target) size = target; logfs_get_wblocks(sb, NULL, 1); - err = __logfs_truncate(inode, target); + err = __logfs_truncate(inode, size); if (!err) err = __logfs_write_inode(inode, 0); logfs_put_wblocks(sb, NULL, 1); -- cgit v0.10.2 From 5f737b39be9110bd64874f508bd89ba27746b17e Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 28 Apr 2010 05:46:11 +0000 Subject: sh: add CONFIG_VIRTUALIZATION for virtio support Add CONFIG_VIRTUALIZATION to the SH architecture and include the virtio code there. Used to enable the virtio drivers under QEMU. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index c497307..c2325bd 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -871,4 +871,20 @@ source "security/Kconfig" source "crypto/Kconfig" +menuconfig VIRTUALIZATION + bool "Virtualization" + default n + ---help--- + Say Y here to get to see options for using your Linux host to run other + operating systems inside virtual machines (guests). + This option alone does not add any kernel code. + + If you say N, all options in this submenu will be skipped and disabled. + +if VIRTUALIZATION + +source drivers/virtio/Kconfig + +endif # VIRTUALIZATION + source "lib/Kconfig" -- cgit v0.10.2 From 1483feac74fdfd84a7ed7586c66482842e3b6e86 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Wed, 28 Apr 2010 11:11:30 +0000 Subject: sh: native_cpu_disable() build error when CONFIG_HOTPLUG_CPU=n arch/sh/kernel/smp.c:164: error: conflicting types for 'native_cpu_disable' /home/matt/src/kernels/sh-2.6/arch/sh/include/asm/smp.h:48: error: previous declaration of 'native_cpu_disable' was here Signed-off-by: Matt Fleming Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c index 86cd6f9..509b36b 100644 --- a/arch/sh/kernel/smp.c +++ b/arch/sh/kernel/smp.c @@ -161,7 +161,7 @@ int __cpu_disable(void) return 0; } #else /* ... !CONFIG_HOTPLUG_CPU */ -int native_cpu_disable(void) +int native_cpu_disable(unsigned int cpu) { return -ENOSYS; } -- cgit v0.10.2 From 28d7f4ec98a8edb029ef24c1ee4af6a1ccbc9633 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Thu, 29 Apr 2010 17:11:45 +0100 Subject: ARM: 6063/1: pmu: add enum describing PMU types This patch adds an enum describing the potential PMU device types in preparation for PMU device registration via platform devices. Signed-off-by: Will Deacon Signed-off-by: Russell King diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h index 2829b9f..44bec1f 100644 --- a/arch/arm/include/asm/pmu.h +++ b/arch/arm/include/asm/pmu.h @@ -12,6 +12,11 @@ #ifndef __ARM_PMU_H__ #define __ARM_PMU_H__ +enum arm_pmu_type { + ARM_PMU_DEVICE_CPU = 0, + ARM_NUM_PMU_DEVICES, +}; + #ifdef CONFIG_CPU_HAS_PMU struct pmu_irqs { -- cgit v0.10.2 From 8716011315a5b2fa932fa1e7570c34975ed2cb14 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 9 Apr 2010 13:55:54 +0100 Subject: ARM: 6047/1: ARM: BCMRING: register PMU IRQ during board initialisation This patch updates the initialisation routine for the BCMRING platform so that it registers its PMU IRQ with the PMU framework in the Kernel. Acked-by: Leo Chen Signed-off-by: Will Deacon Signed-off-by: Russell King diff --git a/arch/arm/mach-bcmring/arch.c b/arch/arm/mach-bcmring/arch.c index 53dd2a9..2f13919 100644 --- a/arch/arm/mach-bcmring/arch.c +++ b/arch/arm/mach-bcmring/arch.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -85,8 +86,23 @@ static struct platform_device nand_device = { .num_resources = ARRAY_SIZE(nand_resource), }; +static struct resource pmu_resource = { + .start = IRQ_PMUIRQ, + .end = IRQ_PMUIRQ, + .flags = IORESOURCE_IRQ, +}; + +static struct platform_device pmu_device = { + .name = "arm-pmu", + .id = ARM_PMU_DEVICE_CPU, + .resource = &pmu_resource, + .num_resources = 1, +}; + + static struct platform_device *devices[] __initdata = { &nand_device, + &pmu_device, }; /**************************************************************************** -- cgit v0.10.2 From cc761beda2426cf663a649b905b6643673ff7b30 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 16 Feb 2010 22:06:14 +0100 Subject: ARM: 5943/1: iop: n2100: enable serial interrupt Thecus N2100 has a jumper (J3/J4) to select whether the XINT1 interrupt line is connected to the second UHCI controller (position J3) or to the serial port UART (position J4). Currently, the kernel is hardcoded to assume the J3 position, and the serial port is always being used in polling mode. The patch adds the IRQ autodetection flag for the serial port interrupt, and also marks it as shared (as the driver for the second UHCI controller will request the interrupt in any case). Now, when the jumper is set to the J4 position, the serial port will have an interrupt line, resulting in less CPU overhead and faster throughput. Tested-by: Mikael Pettersson Signed-off-by: Aaro Koskinen Acked-by: Lennert Buytenhek Signed-off-by: Russell King diff --git a/arch/arm/mach-iop32x/n2100.c b/arch/arm/mach-iop32x/n2100.c index 2a5c6376..266b1f5 100644 --- a/arch/arm/mach-iop32x/n2100.c +++ b/arch/arm/mach-iop32x/n2100.c @@ -177,7 +177,7 @@ static struct plat_serial8250_port n2100_serial_port[] = { .mapbase = N2100_UART, .membase = (char *)N2100_UART, .irq = 0, - .flags = UPF_SKIP_TEST, + .flags = UPF_SKIP_TEST | UPF_AUTO_IRQ | UPF_SHARE_IRQ, .iotype = UPIO_MEM, .regshift = 0, .uartclk = 1843200, -- cgit v0.10.2 From de4338f40e48da3b604219909a1d4aa7aa60870f Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 9 Apr 2010 13:57:02 +0100 Subject: ARM: 6048/1: ARM: iop3xx: register PMU IRQs during board initialisation This patch adds an initcall for the iop3xx platforms so that they register their PMU IRQS with the PMU framework in the Kernel. Cc: Lennert Buytenhek Signed-off-by: Will Deacon Signed-off-by: Russell King diff --git a/arch/arm/plat-iop/Makefile b/arch/arm/plat-iop/Makefile index 36bff03..69b09c1 100644 --- a/arch/arm/plat-iop/Makefile +++ b/arch/arm/plat-iop/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_ARCH_IOP32X) += time.o obj-$(CONFIG_ARCH_IOP32X) += io.o obj-$(CONFIG_ARCH_IOP32X) += cp6.o obj-$(CONFIG_ARCH_IOP32X) += adma.o +obj-$(CONFIG_ARCH_IOP32X) += pmu.o # IOP33X obj-$(CONFIG_ARCH_IOP33X) += gpio.o @@ -23,6 +24,7 @@ obj-$(CONFIG_ARCH_IOP33X) += time.o obj-$(CONFIG_ARCH_IOP33X) += io.o obj-$(CONFIG_ARCH_IOP33X) += cp6.o obj-$(CONFIG_ARCH_IOP33X) += adma.o +obj-$(CONFIG_ARCH_IOP33X) += pmu.o # IOP13XX obj-$(CONFIG_ARCH_IOP13XX) += cp6.o diff --git a/arch/arm/plat-iop/pmu.c b/arch/arm/plat-iop/pmu.c new file mode 100644 index 0000000..a2024b8 --- /dev/null +++ b/arch/arm/plat-iop/pmu.c @@ -0,0 +1,40 @@ +/* + * PMU IRQ registration for the iop3xx xscale PMU families. + * Copyright (C) 2010 Will Deacon, ARM Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include + +static struct resource pmu_resource = { +#ifdef CONFIG_ARCH_IOP32X + .start = IRQ_IOP32X_CORE_PMU, + .end = IRQ_IOP32X_CORE_PMU, +#endif +#ifdef CONFIG_ARCH_IOP33X + .start = IRQ_IOP33X_CORE_PMU, + .end = IRQ_IOP33X_CORE_PMU, +#endif + .flags = IORESOURCE_IRQ, +}; + +static struct platform_device pmu_device = { + .name = "arm-pmu", + .id = ARM_PMU_DEVICE_CPU, + .resource = &pmu_resource, + .num_resources = 1, +}; + +static int __init iop3xx_pmu_init(void) +{ + platform_device_register(&pmu_device); + return 0; +} + +arch_initcall(iop3xx_pmu_init); -- cgit v0.10.2 From a285edcf18b8838814d645c7e411a337a825236e Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 14 Jan 2010 19:59:37 +0000 Subject: ARM: Fix Versatile&Integrator includes to behave in the same way as Realview Realview doesn't include mach/platform.h in mach/hardware.h, so make versatile behave in the same way. Also, move the definition of __io_address() into mach/hardware.h, just like Realview. Signed-off-by: Russell King diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c index 8b390e3..096f899 100644 --- a/arch/arm/mach-integrator/core.c +++ b/arch/arm/mach-integrator/core.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/arm/mach-integrator/cpu.c b/arch/arm/mach-integrator/cpu.c index 44d4c2e..b761879 100644 --- a/arch/arm/mach-integrator/cpu.c +++ b/arch/arm/mach-integrator/cpu.c @@ -20,6 +20,7 @@ #include #include +#include #include #include diff --git a/arch/arm/mach-integrator/include/mach/entry-macro.S b/arch/arm/mach-integrator/include/mach/entry-macro.S index 7649c57..3d029c9 100644 --- a/arch/arm/mach-integrator/include/mach/entry-macro.S +++ b/arch/arm/mach-integrator/include/mach/entry-macro.S @@ -8,6 +8,7 @@ * warranty of any kind, whether express or implied. */ #include +#include #include .macro disable_fiq diff --git a/arch/arm/mach-integrator/include/mach/hardware.h b/arch/arm/mach-integrator/include/mach/hardware.h index d795642..d44af72 100644 --- a/arch/arm/mach-integrator/include/mach/hardware.h +++ b/arch/arm/mach-integrator/include/mach/hardware.h @@ -23,7 +23,6 @@ #define __ASM_ARCH_HARDWARE_H #include -#include /* * Where in virtual memory the IO devices (timers, system controllers @@ -48,5 +47,7 @@ #define PCIBIOS_MIN_IO 0x6000 #define PCIBIOS_MIN_MEM 0x00100000 +#define __io_address(n) ((void __iomem *)IO_ADDRESS(n)) + #endif diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c index 8138a7e..018c32d 100644 --- a/arch/arm/mach-integrator/integrator_ap.c +++ b/arch/arm/mach-integrator/integrator_ap.c @@ -30,6 +30,7 @@ #include #include +#include #include #include #include /* HZ */ diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 66ef86d..c66e8fa 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/arm/mach-integrator/leds.c b/arch/arm/mach-integrator/leds.c index 8dcc823..28be186 100644 --- a/arch/arm/mach-integrator/leds.c +++ b/arch/arm/mach-integrator/leds.c @@ -27,6 +27,7 @@ #include #include +#include #include #include #include diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c index 148d25f..e87fe9f 100644 --- a/arch/arm/mach-integrator/pci_v3.c +++ b/arch/arm/mach-integrator/pci_v3.c @@ -30,6 +30,7 @@ #include #include +#include #include #include #include diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index 9ddb49b..b77bc40 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -35,7 +35,6 @@ #include #include -#include #include #include #include @@ -48,6 +47,8 @@ #include #include #include +#include +#include #include "core.h" #include "clock.h" @@ -58,7 +59,6 @@ * * Setup a VA for the Versatile Vectored Interrupt Controller. */ -#define __io_address(n) __io(IO_ADDRESS(n)) #define VA_VIC_BASE __io_address(VERSATILE_VIC_BASE) #define VA_SIC_BASE __io_address(VERSATILE_SIC_BASE) diff --git a/arch/arm/mach-versatile/include/mach/entry-macro.S b/arch/arm/mach-versatile/include/mach/entry-macro.S index 8c80209..e6f7c16 100644 --- a/arch/arm/mach-versatile/include/mach/entry-macro.S +++ b/arch/arm/mach-versatile/include/mach/entry-macro.S @@ -8,6 +8,7 @@ * warranty of any kind, whether express or implied. */ #include +#include #include .macro disable_fiq diff --git a/arch/arm/mach-versatile/include/mach/hardware.h b/arch/arm/mach-versatile/include/mach/hardware.h index 7aa906c..4f8f99a 100644 --- a/arch/arm/mach-versatile/include/mach/hardware.h +++ b/arch/arm/mach-versatile/include/mach/hardware.h @@ -23,7 +23,6 @@ #define __ASM_ARCH_HARDWARE_H #include -#include /* * PCI space virtual addresses @@ -49,4 +48,6 @@ /* macro to get at IO space when running virtually */ #define IO_ADDRESS(x) (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000) +#define __io_address(n) __io(IO_ADDRESS(n)) + #endif -- cgit v0.10.2 From ba02a21544b41a65e58506f1d79353203d94b8b6 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 16 Jan 2010 15:07:08 +0000 Subject: ARM: Improve documentation in arm_timer.h Signed-off-by: Russell King diff --git a/arch/arm/include/asm/hardware/arm_timer.h b/arch/arm/include/asm/hardware/arm_timer.h index 04be3bd..c0f4e7b 100644 --- a/arch/arm/include/asm/hardware/arm_timer.h +++ b/arch/arm/include/asm/hardware/arm_timer.h @@ -1,21 +1,30 @@ #ifndef __ASM_ARM_HARDWARE_ARM_TIMER_H #define __ASM_ARM_HARDWARE_ARM_TIMER_H -#define TIMER_LOAD 0x00 -#define TIMER_VALUE 0x04 -#define TIMER_CTRL 0x08 -#define TIMER_CTRL_ONESHOT (1 << 0) -#define TIMER_CTRL_32BIT (1 << 1) -#define TIMER_CTRL_DIV1 (0 << 2) -#define TIMER_CTRL_DIV16 (1 << 2) -#define TIMER_CTRL_DIV256 (2 << 2) -#define TIMER_CTRL_IE (1 << 5) /* Interrupt Enable (versatile only) */ -#define TIMER_CTRL_PERIODIC (1 << 6) -#define TIMER_CTRL_ENABLE (1 << 7) +/* + * ARM timer implementation, found in Integrator, Versatile and Realview + * platforms. Not all platforms support all registers and bits in these + * registers, so we mark them with A for Integrator AP, C for Integrator + * CP, V for Versatile and R for Realview. + * + * Integrator AP has 16-bit timers, Integrator CP, Versatile and Realview + * can have 16-bit or 32-bit selectable via a bit in the control register. + */ +#define TIMER_LOAD 0x00 /* ACVR rw */ +#define TIMER_VALUE 0x04 /* ACVR ro */ +#define TIMER_CTRL 0x08 /* ACVR rw */ +#define TIMER_CTRL_ONESHOT (1 << 0) /* CVR */ +#define TIMER_CTRL_32BIT (1 << 1) /* CVR */ +#define TIMER_CTRL_DIV1 (0 << 2) /* ACVR */ +#define TIMER_CTRL_DIV16 (1 << 2) /* ACVR */ +#define TIMER_CTRL_DIV256 (2 << 2) /* ACVR */ +#define TIMER_CTRL_IE (1 << 5) /* VR */ +#define TIMER_CTRL_PERIODIC (1 << 6) /* ACVR */ +#define TIMER_CTRL_ENABLE (1 << 7) /* ACVR */ -#define TIMER_INTCLR 0x0c -#define TIMER_RIS 0x10 -#define TIMER_MIS 0x14 -#define TIMER_BGLOAD 0x18 +#define TIMER_INTCLR 0x0c /* ACVR wo */ +#define TIMER_RIS 0x10 /* CVR ro */ +#define TIMER_MIS 0x14 /* CVR ro */ +#define TIMER_BGLOAD 0x18 /* CVR rw */ #endif -- cgit v0.10.2 From b9cedda230793cbf58eb012ddadedd490cc8e129 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 15 Jan 2010 18:10:33 +0000 Subject: ARM: Integrator: convert to generic time support Signed-off-by: Russell King diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c5408bf..7698d87 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -241,6 +241,7 @@ config ARCH_INTEGRATOR select HAVE_CLK select COMMON_CLKDEV select ICST525 + select GENERIC_TIME help Support for ARM's Integrator platform. diff --git a/arch/arm/mach-integrator/common.h b/arch/arm/mach-integrator/common.h index 609c49d..7dc24bb 100644 --- a/arch/arm/mach-integrator/common.h +++ b/arch/arm/mach-integrator/common.h @@ -1,2 +1 @@ extern void integrator_time_init(unsigned long, unsigned int); -extern unsigned long integrator_gettimeoffset(void); diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c index 096f899..87c6f98 100644 --- a/arch/arm/mach-integrator/core.c +++ b/arch/arm/mach-integrator/core.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -225,7 +226,6 @@ EXPORT_SYMBOL(cm_control); #define TIMER0_VA_BASE (IO_ADDRESS(INTEGRATOR_CT_BASE)+0x00000000) #define TIMER1_VA_BASE (IO_ADDRESS(INTEGRATOR_CT_BASE)+0x00000100) #define TIMER2_VA_BASE (IO_ADDRESS(INTEGRATOR_CT_BASE)+0x00000200) -#define VA_IC_BASE IO_ADDRESS(INTEGRATOR_IC_BASE) /* * How long is the timer interval? @@ -241,42 +241,38 @@ EXPORT_SYMBOL(cm_control); static unsigned long timer_reload; -/* - * Returns number of ms since last clock interrupt. Note that interrupts - * will have been disabled by do_gettimeoffset() - */ -unsigned long integrator_gettimeoffset(void) +static void __iomem * const clksrc_base = (void __iomem *)TIMER2_VA_BASE; + +static cycle_t timersp_read(struct clocksource *cs) { - unsigned long ticks1, ticks2, status; + return ~(readl(clksrc_base + TIMER_VALUE) & 0xffff); +} - /* - * Get the current number of ticks. Note that there is a race - * condition between us reading the timer and checking for - * an interrupt. We get around this by ensuring that the - * counter has not reloaded between our two reads. - */ - ticks2 = readl(TIMER1_VA_BASE + TIMER_VALUE) & 0xffff; - do { - ticks1 = ticks2; - status = __raw_readl(VA_IC_BASE + IRQ_RAW_STATUS); - ticks2 = readl(TIMER1_VA_BASE + TIMER_VALUE) & 0xffff; - } while (ticks2 > ticks1); +static struct clocksource clocksource_timersp = { + .name = "timer2", + .rating = 200, + .read = timersp_read, + .mask = CLOCKSOURCE_MASK(16), + .shift = 16, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; - /* - * Number of ticks since last interrupt. - */ - ticks1 = timer_reload - ticks2; +static void integrator_clocksource_init(u32 khz) +{ + struct clocksource *cs = &clocksource_timersp; + void __iomem *base = clksrc_base; + u32 ctrl = TIMER_CTRL_ENABLE; - /* - * Interrupt pending? If so, we've reloaded once already. - */ - if (status & (1 << IRQ_TIMERINT1)) - ticks1 += timer_reload; + if (khz >= 1500) { + khz /= 16; + ctrl = TIMER_CTRL_DIV16; + } - /* - * Convert the ticks to usecs - */ - return TICKS2USECS(ticks1); + writel(ctrl, base + TIMER_CTRL); + writel(0xffff, base + TIMER_LOAD); + + cs->mult = clocksource_khz2mult(khz, cs->shift); + clocksource_register(cs); } /* @@ -308,6 +304,8 @@ void __init integrator_time_init(unsigned long reload, unsigned int ctrl) { unsigned int timer_ctrl = TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC; + integrator_clocksource_init(reload * HZ / 1000); + timer_reload = reload; timer_ctrl |= ctrl; diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c index 018c32d..cfb718f 100644 --- a/arch/arm/mach-integrator/integrator_ap.c +++ b/arch/arm/mach-integrator/integrator_ap.c @@ -342,7 +342,6 @@ static void __init ap_init_timer(void) static struct sys_timer ap_timer = { .init = ap_init_timer, - .offset = integrator_gettimeoffset, }; MACHINE_START(INTEGRATOR, "ARM-Integrator") diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index c66e8fa..3e84732 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -577,7 +577,6 @@ static void __init intcp_timer_init(void) static struct sys_timer cp_timer = { .init = intcp_timer_init, - .offset = integrator_gettimeoffset, }; MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP") -- cgit v0.10.2 From 13edd86d7a8b64735c60c308faac785a6f2257b2 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 15 Jan 2010 21:49:23 +0000 Subject: ARM: Integrator: convert to generic clockevent support Signed-off-by: Russell King diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 7698d87..86fecec 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -242,6 +242,7 @@ config ARCH_INTEGRATOR select COMMON_CLKDEV select ICST525 select GENERIC_TIME + select GENERIC_CLOCKEVENTS help Support for ARM's Integrator platform. diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c index 87c6f98..b1ccbe3 100644 --- a/arch/arm/mach-integrator/core.c +++ b/arch/arm/mach-integrator/core.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -275,61 +276,99 @@ static void integrator_clocksource_init(u32 khz) clocksource_register(cs); } +static void __iomem * const clkevt_base = (void __iomem *)TIMER1_VA_BASE; + /* * IRQ handler for the timer */ -static irqreturn_t -integrator_timer_interrupt(int irq, void *dev_id) +static irqreturn_t integrator_timer_interrupt(int irq, void *dev_id) { - /* - * clear the interrupt - */ - writel(1, TIMER1_VA_BASE + TIMER_INTCLR); + struct clock_event_device *evt = dev_id; + + /* clear the interrupt */ + writel(1, clkevt_base + TIMER_INTCLR); - timer_tick(); + evt->event_handler(evt); return IRQ_HANDLED; } +static void clkevt_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) +{ + u32 ctrl = readl(clkevt_base + TIMER_CTRL) & ~TIMER_CTRL_ENABLE; + + BUG_ON(mode == CLOCK_EVT_MODE_ONESHOT); + + if (mode == CLOCK_EVT_MODE_PERIODIC) { + writel(ctrl, clkevt_base + TIMER_CTRL); + writel(timer_reload, clkevt_base + TIMER_LOAD); + ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE; + } + + writel(ctrl, clkevt_base + TIMER_CTRL); +} + +static int clkevt_set_next_event(unsigned long next, struct clock_event_device *evt) +{ + unsigned long ctrl = readl(clkevt_base + TIMER_CTRL); + + writel(ctrl & ~TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL); + writel(next, clkevt_base + TIMER_LOAD); + writel(ctrl | TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL); + + return 0; +} + +static struct clock_event_device integrator_clockevent = { + .name = "timer1", + .shift = 34, + .features = CLOCK_EVT_FEAT_PERIODIC, + .set_mode = clkevt_set_mode, + .set_next_event = clkevt_set_next_event, + .rating = 300, + .cpumask = cpu_all_mask, +}; + static struct irqaction integrator_timer_irq = { - .name = "Integrator Timer Tick", + .name = "timer", .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, .handler = integrator_timer_interrupt, + .dev_id = &integrator_clockevent, }; -/* - * Set up timer interrupt, and return the current time in seconds. - */ -void __init integrator_time_init(unsigned long reload, unsigned int ctrl) +static void integrator_clockevent_init(u32 khz, unsigned int ctrl) { - unsigned int timer_ctrl = TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC; + struct clock_event_device *evt = &integrator_clockevent; - integrator_clocksource_init(reload * HZ / 1000); + if (khz * 1000 > 0x100000 * HZ) { + khz /= 256; + ctrl |= TIMER_CTRL_DIV256; + } else if (khz * 1000 > 0x10000 * HZ) { + khz /= 16; + ctrl |= TIMER_CTRL_DIV16; + } - timer_reload = reload; - timer_ctrl |= ctrl; + timer_reload = khz * 1000 / HZ; + writel(ctrl, clkevt_base + TIMER_CTRL); - if (timer_reload > 0x100000) { - timer_reload >>= 8; - timer_ctrl |= TIMER_CTRL_DIV256; - } else if (timer_reload > 0x010000) { - timer_reload >>= 4; - timer_ctrl |= TIMER_CTRL_DIV16; - } + evt->irq = IRQ_TIMERINT1; + evt->mult = div_sc(khz, NSEC_PER_MSEC, evt->shift); + evt->max_delta_ns = clockevent_delta2ns(0xffff, evt); + evt->min_delta_ns = clockevent_delta2ns(0xf, evt); - /* - * Initialise to a known state (all timers off) - */ + setup_irq(IRQ_TIMERINT1, &integrator_timer_irq); + clockevents_register_device(evt); +} + +/* + * Set up timer(s). + */ +void __init integrator_time_init(unsigned long reload, unsigned int ctrl) +{ writel(0, TIMER0_VA_BASE + TIMER_CTRL); writel(0, TIMER1_VA_BASE + TIMER_CTRL); writel(0, TIMER2_VA_BASE + TIMER_CTRL); - writel(timer_reload, TIMER1_VA_BASE + TIMER_LOAD); - writel(timer_reload, TIMER1_VA_BASE + TIMER_VALUE); - writel(timer_ctrl, TIMER1_VA_BASE + TIMER_CTRL); - - /* - * Make irqs happen for the system timer - */ - setup_irq(IRQ_TIMERINT1, &integrator_timer_irq); + integrator_clocksource_init(reload * HZ / 1000); + integrator_clockevent_init(reload * HZ / 1000, ctrl); } -- cgit v0.10.2 From 861248d177145fc5861507e4607fec89fd0a0462 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 15 Jan 2010 22:12:46 +0000 Subject: ARM: Integrator: pass 'khz' to integrator_time_init This is now what the clocksource/clockevent initialization functions want, so give them the timer tick rate directly. Signed-off-by: Russell King diff --git a/arch/arm/mach-integrator/common.h b/arch/arm/mach-integrator/common.h index 7dc24bb..cdbe710 100644 --- a/arch/arm/mach-integrator/common.h +++ b/arch/arm/mach-integrator/common.h @@ -1 +1 @@ -extern void integrator_time_init(unsigned long, unsigned int); +extern void integrator_time_init(u32, unsigned int); diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c index b1ccbe3..d02f0e3 100644 --- a/arch/arm/mach-integrator/core.c +++ b/arch/arm/mach-integrator/core.c @@ -363,12 +363,12 @@ static void integrator_clockevent_init(u32 khz, unsigned int ctrl) /* * Set up timer(s). */ -void __init integrator_time_init(unsigned long reload, unsigned int ctrl) +void __init integrator_time_init(u32 khz, unsigned int ctrl) { writel(0, TIMER0_VA_BASE + TIMER_CTRL); writel(0, TIMER1_VA_BASE + TIMER_CTRL); writel(0, TIMER2_VA_BASE + TIMER_CTRL); - integrator_clocksource_init(reload * HZ / 1000); - integrator_clockevent_init(reload * HZ / 1000, ctrl); + integrator_clocksource_init(khz); + integrator_clockevent_init(khz, ctrl); } diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c index cfb718f..93da7d4 100644 --- a/arch/arm/mach-integrator/integrator_ap.c +++ b/arch/arm/mach-integrator/integrator_ap.c @@ -337,7 +337,7 @@ static void __init ap_init(void) static void __init ap_init_timer(void) { - integrator_time_init(1000000 * TICKS_PER_uSEC / HZ, 0); + integrator_time_init(TICKS_PER_uSEC * 1000, 0); } static struct sys_timer ap_timer = { diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 3e84732..108bc48 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -572,7 +572,7 @@ static void __init intcp_init(void) static void __init intcp_timer_init(void) { - integrator_time_init(1000000 / HZ, TIMER_CTRL_IE); + integrator_time_init(1000, TIMER_CTRL_IE); } static struct sys_timer cp_timer = { -- cgit v0.10.2 From 3e9cc70590287f7cb7e38793bbf968b3362b7612 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 9 Apr 2010 13:57:51 +0100 Subject: ARM: 6049/1: ARM: pxa: register PMU IRQs during board initialisation This patch adds an initcall for the pxa platforms so that they register their PMU IRQs with the PMU framework in the Kernel. Cc: Eric Miao Signed-off-by: Will Deacon Signed-off-by: Russell King diff --git a/arch/arm/plat-pxa/Makefile b/arch/arm/plat-pxa/Makefile index 0264bfb..f68da35 100644 --- a/arch/arm/plat-pxa/Makefile +++ b/arch/arm/plat-pxa/Makefile @@ -2,7 +2,7 @@ # Makefile for code common across different PXA processor families # -obj-y := dma.o +obj-y := dma.o pmu.o obj-$(CONFIG_GENERIC_GPIO) += gpio.o obj-$(CONFIG_PXA3xx) += mfp.o diff --git a/arch/arm/plat-pxa/pmu.c b/arch/arm/plat-pxa/pmu.c new file mode 100644 index 0000000..267ceb6 --- /dev/null +++ b/arch/arm/plat-pxa/pmu.c @@ -0,0 +1,33 @@ +/* + * PMU IRQ registration for the PXA xscale PMU families. + * Copyright (C) 2010 Will Deacon, ARM Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include + +static struct resource pmu_resource = { + .start = IRQ_PMU, + .end = IRQ_PMU, + .flags = IORESOURCE_IRQ, +}; + +static struct platform_device pmu_device = { + .name = "arm-pmu", + .id = ARM_PMU_DEVICE_CPU, + .resource = &pmu_resource, + .num_resources = 1, +}; + +static int __init pxa_pmu_init(void) +{ + platform_device_register(&pmu_device); + return 0; +} +arch_initcall(pxa_pmu_init); -- cgit v0.10.2 From 883413341e479d4e9f9c69def4884b4c6e1cef4e Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 9 Apr 2010 13:54:43 +0100 Subject: ARM: 6046/1: ARM: OMAP: register PMU IRQs during board initialisation This patch updates the initialisation routines for the OMAP2 and OMAP3 boards so that they register their PMU IRQs with the PMU framework in the Kernel. Cc: Tony Lindgren Signed-off-by: Will Deacon Signed-off-by: Russell King diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 23e4d77..4a1c232 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -17,8 +17,10 @@ #include #include +#include #include #include +#include #include #include @@ -453,6 +455,37 @@ static void omap_init_mcspi(void) static inline void omap_init_mcspi(void) {} #endif +static struct resource omap2_pmu_resource = { + .start = 3, + .end = 3, + .flags = IORESOURCE_IRQ, +}; + +static struct resource omap3_pmu_resource = { + .start = INT_34XX_BENCH_MPU_EMUL, + .end = INT_34XX_BENCH_MPU_EMUL, + .flags = IORESOURCE_IRQ, +}; + +static struct platform_device omap_pmu_device = { + .name = "arm-pmu", + .id = ARM_PMU_DEVICE_CPU, + .num_resources = 1, +}; + +static void omap_init_pmu(void) +{ + if (cpu_is_omap24xx()) + omap_pmu_device.resource = &omap2_pmu_resource; + else if (cpu_is_omap34xx()) + omap_pmu_device.resource = &omap3_pmu_resource; + else + return; + + platform_device_register(&omap_pmu_device); +} + + #ifdef CONFIG_OMAP_SHA1_MD5 static struct resource sha1_md5_resources[] = { { @@ -797,6 +830,7 @@ static int __init omap2_init_devices(void) omap_init_camera(); omap_init_mbox(); omap_init_mcspi(); + omap_init_pmu(); omap_hdq_init(); omap_init_sti(); omap_init_sha1_md5(); -- cgit v0.10.2 From 5c0541d53ef3897494768decb09eb8f1087953a5 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 29 Apr 2010 15:25:23 -0300 Subject: perf symbols: Add machine helper routines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created when writing the first 'perf test' regression testing routine. Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index 1563561..ee05dba 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c @@ -377,7 +377,7 @@ static void __print_result(struct rb_root *root, struct perf_session *session, if (is_caller) { addr = data->call_site; if (!raw_ip) - sym = machine__find_function(machine, addr, &map, NULL); + sym = machine__find_kernel_function(machine, addr, &map, NULL); } else addr = data->ptr; diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index 881dba4..f391345 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h @@ -30,6 +30,7 @@ struct map { u64 start; u64 end; enum map_type type; + u32 priv; u64 pgoff; /* ip -> dso rip */ @@ -66,6 +67,12 @@ struct machine { struct map *vmlinux_maps[MAP__NR_TYPES]; }; +static inline +struct map *machine__kernel_map(struct machine *self, enum map_type type) +{ + return self->vmlinux_maps[type]; +} + static inline struct kmap *map__kmap(struct map *self) { return (struct kmap *)(self + 1); @@ -173,11 +180,21 @@ struct symbol *map_groups__find_symbol_by_name(struct map_groups *self, struct map **mapp, symbol_filter_t filter); -static inline struct symbol *machine__find_function(struct machine *self, - u64 addr, struct map **mapp, - symbol_filter_t filter) +static inline +struct symbol *machine__find_kernel_symbol(struct machine *self, + enum map_type type, u64 addr, + struct map **mapp, + symbol_filter_t filter) +{ + return map_groups__find_symbol(&self->kmaps, type, addr, mapp, filter); +} + +static inline +struct symbol *machine__find_kernel_function(struct machine *self, u64 addr, + struct map **mapp, + symbol_filter_t filter) { - return map_groups__find_symbol(&self->kmaps, MAP__FUNCTION, addr, mapp, filter); + return machine__find_kernel_symbol(self, MAP__FUNCTION, addr, mapp, filter); } static inline diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index caa890f..4c0146a 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1983,23 +1983,23 @@ void dso__read_running_kernel_build_id(struct dso *self, struct machine *machine self->has_build_id = true; } -static struct dso *dsos__create_kernel(struct machine *machine) +static struct dso *machine__create_kernel(struct machine *self) { const char *vmlinux_name = NULL; struct dso *kernel; - if (machine__is_host(machine)) { + if (machine__is_host(self)) { vmlinux_name = symbol_conf.vmlinux_name; kernel = dso__new_kernel(vmlinux_name); } else { - if (machine__is_default_guest(machine)) + if (machine__is_default_guest(self)) vmlinux_name = symbol_conf.default_guest_vmlinux_name; - kernel = dso__new_guest_kernel(machine, vmlinux_name); + kernel = dso__new_guest_kernel(self, vmlinux_name); } if (kernel != NULL) { - dso__read_running_kernel_build_id(kernel, machine); - dsos__add(&machine->kernel_dsos, kernel); + dso__read_running_kernel_build_id(kernel, self); + dsos__add(&self->kernel_dsos, kernel); } return kernel; } @@ -2026,6 +2026,23 @@ int __machine__create_kernel_maps(struct machine *self, struct dso *kernel) return 0; } +int machine__create_kernel_maps(struct machine *self) +{ + struct dso *kernel = machine__create_kernel(self); + + if (kernel == NULL || + __machine__create_kernel_maps(self, kernel) < 0) + return -1; + + if (symbol_conf.use_modules && machine__create_modules(self) < 0) + pr_debug("Problems creating module maps, continuing anyway...\n"); + /* + * Now that we have all the maps created, just set the ->end of them: + */ + map_groups__fixup_end(&self->kmaps); + return 0; +} + static void vmlinux_path__exit(void) { while (--vmlinux_path__nr_entries >= 0) { @@ -2144,25 +2161,12 @@ out_free_comm_list: int machines__create_kernel_maps(struct rb_root *self, pid_t pid) { - struct dso *kernel; struct machine *machine = machines__findnew(self, pid); if (machine == NULL) return -1; - kernel = dsos__create_kernel(machine); - if (kernel == NULL) - return -1; - - if (__machine__create_kernel_maps(machine, kernel) < 0) - return -1; - if (symbol_conf.use_modules && machine__create_modules(machine) < 0) - pr_debug("Problems creating module maps, continuing anyway...\n"); - /* - * Now that we have all the maps created, just set the ->end of them: - */ - map_groups__fixup_end(&machine->kmaps); - return 0; + return machine__create_kernel_maps(machine); } static int hex(char ch) @@ -2248,3 +2252,36 @@ failure: return ret; } + +int machine__load_kallsyms(struct machine *self, const char *filename, + enum map_type type, symbol_filter_t filter) +{ + struct map *map = self->vmlinux_maps[type]; + int ret = dso__load_kallsyms(map->dso, filename, map, filter); + + if (ret > 0) { + dso__set_loaded(map->dso, type); + /* + * Since /proc/kallsyms will have multiple sessions for the + * kernel, with modules between them, fixup the end of all + * sections. + */ + __map_groups__fixup_end(&self->kmaps, type); + } + + return ret; +} + +int machine__load_vmlinux_path(struct machine *self, enum map_type type, + symbol_filter_t filter) +{ + struct map *map = self->vmlinux_maps[type]; + int ret = dso__load_vmlinux_path(map->dso, map, filter); + + if (ret > 0) { + dso__set_loaded(map->dso, type); + map__reloc_vmlinux(map); + } + + return ret; +} diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 2cec6a1..a517c17 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -162,6 +162,11 @@ int dso__load_vmlinux_path(struct dso *self, struct map *map, symbol_filter_t filter); int dso__load_kallsyms(struct dso *self, const char *filename, struct map *map, symbol_filter_t filter); +int machine__load_kallsyms(struct machine *self, const char *filename, + enum map_type type, symbol_filter_t filter); +int machine__load_vmlinux_path(struct machine *self, enum map_type type, + symbol_filter_t filter); + size_t machines__fprintf_dsos(struct rb_root *self, FILE *fp); size_t machines__fprintf_dsos_buildid(struct rb_root *self, FILE *fp, bool with_hits); @@ -199,6 +204,8 @@ int kallsyms__parse(const char *filename, void *arg, char type, u64 start)); int __machine__create_kernel_maps(struct machine *self, struct dso *kernel); +int machine__create_kernel_maps(struct machine *self); + int machines__create_kernel_maps(struct rb_root *self, pid_t pid); int machines__create_guest_kernel_maps(struct rb_root *self); -- cgit v0.10.2 From 1c6a800cde3b818fd8320b5d402f2d77d2948c00 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 29 Apr 2010 18:58:32 -0300 Subject: perf test: Initial regression testing command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit First an example with the first internal test: [acme@doppio linux-2.6-tip]$ perf test 1: vmlinux symtab matches kallsyms: Ok So it run just one test, that is "vmlinux symtab matches kallsyms", and it was successful. If we run it in verbose mode, we'll see details about errors and extra warnings for non-fatal problems: [acme@doppio linux-2.6-tip]$ perf test -v 1: vmlinux symtab matches kallsyms: --- start --- Looking at the vmlinux_path (5 entries long) No build_id in vmlinux, ignoring it No build_id in /boot/vmlinux, ignoring it No build_id in /boot/vmlinux-2.6.34-rc4-tip+, ignoring it Using /lib/modules/2.6.34-rc4-tip+/build/vmlinux for symbols Maps only in vmlinux: ffffffff81cb81b1-ffffffff81e1149b 0 [kernel].init.text ffffffff81e1149c-ffffffff9fffffff 0 [kernel].exit.text ffffffffff600000-ffffffffff6000ff 0 [kernel].vsyscall_0 ffffffffff600100-ffffffffff6003ff 0 [kernel].vsyscall_fn ffffffffff600400-ffffffffff6007ff 0 [kernel].vsyscall_1 ffffffffff600800-ffffffffffffffff 0 [kernel].vsyscall_2 Maps in vmlinux with a different name in kallsyms: ffffffffff600000-ffffffffff6000ff 0 [kernel].vsyscall_0 in kallsyms as [kernel].0 ffffffffff600100-ffffffffff6003ff 0 [kernel].vsyscall_fn in kallsyms as: *ffffffffff600100-ffffffffff60012f 0 [kernel].2 ffffffffff600400-ffffffffff6007ff 0 [kernel].vsyscall_1 in kallsyms as [kernel].6 ffffffffff600800-ffffffffffffffff 0 [kernel].vsyscall_2 in kallsyms as [kernel].8 Maps only in kallsyms: ffffffffff600130-ffffffffff6003ff 0 [kernel].4 ---- end ---- vmlinux symtab matches kallsyms: Ok [acme@doppio linux-2.6-tip]$ In the above case we only know the name of the non contiguous kernel ranges in the address space when reading the symbol information from the ELF symtab in vmlinux. The /proc/kallsyms file lack this, we only notice they are separate because there are modules after the kernel and after that more kernel functions, so we need to have a module rbtree backed by the module .ko path to get symtabs in the vmlinux case. The tool uses it to match by address to emit appropriate warning, but don't considers this fatal. The .init.text and .exit.text ines, of course, aren't in kallsyms, so I left these cases just as extra info in verbose mode. The end of the sections also aren't in kallsyms, so we the symbols layer does another pass and sets the end addresses as the next map start minus one, which sometimes pads, causing harmless mismatches. But at least the symbols match, tested it by copying /proc/kallsyms to /tmp/kallsyms and doing changes to see if they were detected. This first test also should serve as a first stab at documenting the symbol library by providing a self contained example that exercises it together with comments about what is being done. More tests to check if actions done on a monitored app, like doing mmaps, etc, makes the kernel generate the expected events should be added next. Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Documentation/perf-test.txt b/tools/perf/Documentation/perf-test.txt new file mode 100644 index 0000000..1c4b5f5 --- /dev/null +++ b/tools/perf/Documentation/perf-test.txt @@ -0,0 +1,22 @@ +perf-test(1) +============ + +NAME +---- +perf-test - Runs sanity tests. + +SYNOPSIS +-------- +[verse] +'perf test ' + +DESCRIPTION +----------- +This command does assorted sanity tests, initially thru linked routines but +also will look for a directory with more tests in the form of scripts. + +OPTIONS +------- +-v:: +--verbose:: + Be more verbose. diff --git a/tools/perf/Makefile b/tools/perf/Makefile index b86f2ad..739c441 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -490,6 +490,7 @@ BUILTIN_OBJS += $(OUTPUT)builtin-probe.o BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o BUILTIN_OBJS += $(OUTPUT)builtin-lock.o BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o +BUILTIN_OBJS += $(OUTPUT)builtin-test.o PERFLIBS = $(LIB_FILE) diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c new file mode 100644 index 0000000..0339612 --- /dev/null +++ b/tools/perf/builtin-test.c @@ -0,0 +1,281 @@ +/* + * builtin-test.c + * + * Builtin regression testing command: ever growing number of sanity tests + */ +#include "builtin.h" + +#include "util/cache.h" +#include "util/debug.h" +#include "util/parse-options.h" +#include "util/session.h" +#include "util/symbol.h" +#include "util/thread.h" + +static long page_size; + +static int vmlinux_matches_kallsyms_filter(struct map *map __used, struct symbol *sym) +{ + bool *visited = symbol__priv(sym); + *visited = true; + return 0; +} + +static int test__vmlinux_matches_kallsyms(void) +{ + int err = -1; + struct rb_node *nd; + struct symbol *sym; + struct map *kallsyms_map, *vmlinux_map; + struct machine kallsyms, vmlinux; + enum map_type type = MAP__FUNCTION; + struct ref_reloc_sym ref_reloc_sym = { .name = "_stext", }; + + /* + * Step 1: + * + * Init the machines that will hold kernel, modules obtained from + * both vmlinux + .ko files and from /proc/kallsyms split by modules. + */ + machine__init(&kallsyms, "", HOST_KERNEL_ID); + machine__init(&vmlinux, "", HOST_KERNEL_ID); + + /* + * Step 2: + * + * Create the kernel maps for kallsyms and the DSO where we will then + * load /proc/kallsyms. Also create the modules maps from /proc/modules + * and find the .ko files that match them in /lib/modules/`uname -r`/. + */ + if (machine__create_kernel_maps(&kallsyms) < 0) { + pr_debug("machine__create_kernel_maps "); + return -1; + } + + /* + * Step 3: + * + * Load and split /proc/kallsyms into multiple maps, one per module. + */ + if (machine__load_kallsyms(&kallsyms, "/proc/kallsyms", type, NULL) <= 0) { + pr_debug("dso__load_kallsyms "); + goto out; + } + + /* + * Step 4: + * + * kallsyms will be internally on demand sorted by name so that we can + * find the reference relocation * symbol, i.e. the symbol we will use + * to see if the running kernel was relocated by checking if it has the + * same value in the vmlinux file we load. + */ + kallsyms_map = machine__kernel_map(&kallsyms, type); + + sym = map__find_symbol_by_name(kallsyms_map, ref_reloc_sym.name, NULL); + if (sym == NULL) { + pr_debug("dso__find_symbol_by_name "); + goto out; + } + + ref_reloc_sym.addr = sym->start; + + /* + * Step 5: + * + * Now repeat step 2, this time for the vmlinux file we'll auto-locate. + */ + if (machine__create_kernel_maps(&vmlinux) < 0) { + pr_debug("machine__create_kernel_maps "); + goto out; + } + + vmlinux_map = machine__kernel_map(&vmlinux, type); + map__kmap(vmlinux_map)->ref_reloc_sym = &ref_reloc_sym; + + /* + * Step 6: + * + * Locate a vmlinux file in the vmlinux path that has a buildid that + * matches the one of the running kernel. + * + * While doing that look if we find the ref reloc symbol, if we find it + * we'll have its ref_reloc_symbol.unrelocated_addr and then + * maps__reloc_vmlinux will notice and set proper ->[un]map_ip routines + * to fixup the symbols. + */ + if (machine__load_vmlinux_path(&vmlinux, type, + vmlinux_matches_kallsyms_filter) <= 0) { + pr_debug("machine__load_vmlinux_path "); + goto out; + } + + err = 0; + /* + * Step 7: + * + * Now look at the symbols in the vmlinux DSO and check if we find all of them + * in the kallsyms dso. For the ones that are in both, check its names and + * end addresses too. + */ + for (nd = rb_first(&vmlinux_map->dso->symbols[type]); nd; nd = rb_next(nd)) { + struct symbol *pair; + + sym = rb_entry(nd, struct symbol, rb_node); + pair = machine__find_kernel_symbol(&kallsyms, type, sym->start, NULL, NULL); + + if (pair && pair->start == sym->start) { +next_pair: + if (strcmp(sym->name, pair->name) == 0) { + /* + * kallsyms don't have the symbol end, so we + * set that by using the next symbol start - 1, + * in some cases we get this up to a page + * wrong, trace_kmalloc when I was developing + * this code was one such example, 2106 bytes + * off the real size. More than that and we + * _really_ have a problem. + */ + s64 skew = sym->end - pair->end; + if (llabs(skew) < page_size) + continue; + + pr_debug("%#Lx: diff end addr for %s v: %#Lx k: %#Lx\n", + sym->start, sym->name, sym->end, pair->end); + } else { + struct rb_node *nnd = rb_prev(&pair->rb_node); + + if (nnd) { + struct symbol *next = rb_entry(nnd, struct symbol, rb_node); + + if (next->start == sym->start) { + pair = next; + goto next_pair; + } + } + pr_debug("%#Lx: diff name v: %s k: %s\n", + sym->start, sym->name, pair->name); + } + } else + pr_debug("%#Lx: %s not on kallsyms\n", sym->start, sym->name); + + err = -1; + } + + if (!verbose) + goto out; + + pr_info("Maps only in vmlinux:\n"); + + for (nd = rb_first(&vmlinux.kmaps.maps[type]); nd; nd = rb_next(nd)) { + struct map *pos = rb_entry(nd, struct map, rb_node), *pair; + /* + * If it is the kernel, kallsyms is always "[kernel.kallsyms]", while + * the kernel will have the path for the vmlinux file being used, + * so use the short name, less descriptive but the same ("[kernel]" in + * both cases. + */ + pair = map_groups__find_by_name(&kallsyms.kmaps, type, + (pos->dso->kernel ? + pos->dso->short_name : + pos->dso->name)); + if (pair) + pair->priv = 1; + else + map__fprintf(pos, stderr); + } + + pr_info("Maps in vmlinux with a different name in kallsyms:\n"); + + for (nd = rb_first(&vmlinux.kmaps.maps[type]); nd; nd = rb_next(nd)) { + struct map *pos = rb_entry(nd, struct map, rb_node), *pair; + + pair = map_groups__find(&kallsyms.kmaps, type, pos->start); + if (pair == NULL || pair->priv) + continue; + + if (pair->start == pos->start) { + pair->priv = 1; + pr_info(" %Lx-%Lx %Lx %s in kallsyms as", + pos->start, pos->end, pos->pgoff, pos->dso->name); + if (pos->pgoff != pair->pgoff || pos->end != pair->end) + pr_info(": \n*%Lx-%Lx %Lx", + pair->start, pair->end, pair->pgoff); + pr_info(" %s\n", pair->dso->name); + pair->priv = 1; + } + } + + pr_info("Maps only in kallsyms:\n"); + + for (nd = rb_first(&kallsyms.kmaps.maps[type]); + nd; nd = rb_next(nd)) { + struct map *pos = rb_entry(nd, struct map, rb_node); + + if (!pos->priv) + map__fprintf(pos, stderr); + } +out: + return err; +} + +static struct test { + const char *desc; + int (*func)(void); +} tests[] = { + { + .desc = "vmlinux symtab matches kallsyms", + .func = test__vmlinux_matches_kallsyms, + }, + { + .func = NULL, + }, +}; + +static int __cmd_test(void) +{ + int i = 0; + + page_size = sysconf(_SC_PAGE_SIZE); + + while (tests[i].func) { + int err; + pr_info("%2d: %s:", i + 1, tests[i].desc); + pr_debug("\n--- start ---\n"); + err = tests[i].func(); + pr_debug("---- end ----\n%s:", tests[i].desc); + pr_info(" %s\n", err ? "FAILED!\n" : "Ok"); + ++i; + } + + return 0; +} + +static const char * const test_usage[] = { + "perf test []", + NULL, +}; + +static const struct option test_options[] = { + OPT_BOOLEAN('v', "verbose", &verbose, + "be more verbose (show symbol address, etc)"), + OPT_END() +}; + +int cmd_test(int argc, const char **argv, const char *prefix __used) +{ + argc = parse_options(argc, argv, test_options, test_usage, 0); + if (argc) + usage_with_options(test_usage, test_options); + + symbol_conf.priv_size = sizeof(int); + symbol_conf.sort_by_name = true; + symbol_conf.try_vmlinux_path = true; + + if (symbol__init() < 0) + return -1; + + setup_pager(); + + return __cmd_test(); +} diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h index ab28bca..34a8a9a 100644 --- a/tools/perf/builtin.h +++ b/tools/perf/builtin.h @@ -33,5 +33,6 @@ extern int cmd_probe(int argc, const char **argv, const char *prefix); extern int cmd_kmem(int argc, const char **argv, const char *prefix); extern int cmd_lock(int argc, const char **argv, const char *prefix); extern int cmd_kvm(int argc, const char **argv, const char *prefix); +extern int cmd_test(int argc, const char **argv, const char *prefix); #endif diff --git a/tools/perf/command-list.txt b/tools/perf/command-list.txt index 2a1162d..80a1a44 100644 --- a/tools/perf/command-list.txt +++ b/tools/perf/command-list.txt @@ -20,3 +20,4 @@ perf-probe mainporcelain common perf-kmem mainporcelain common perf-lock mainporcelain common perf-kvm mainporcelain common +perf-test mainporcelain common diff --git a/tools/perf/perf.c b/tools/perf/perf.c index 985cdb4..5ff9b5b 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c @@ -308,6 +308,7 @@ static void handle_internal_command(int argc, const char **argv) { "kmem", cmd_kmem, 0 }, { "lock", cmd_lock, 0 }, { "kvm", cmd_kvm, 0 }, + { "test", cmd_test, 0 }, }; unsigned int i; static const char ext[] = STRIP_EXTENSION; -- cgit v0.10.2 From b701a47ba48b698976fb2fe05fb285b0edc1d26a Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Thu, 29 Apr 2010 16:03:57 -0700 Subject: x86: Fix LOCK_PREFIX_HERE for uniprocessor build Checkin b3ac891b67bd4b1fc728d1c784cad1212dea433d: x86: Add support for lock prefix in alternatives ... did not define LOCK_PREFIX_HERE in the case of a uniprocessor build. As a result, it would cause any of the usages of this macro to fail on a uniprocessor build. Fix this by defining LOCK_PREFIX_HERE as a null string. Signed-off-by: H. Peter Anvin Cc: Luca Barbieri LKML-Reference: <1267005265-27958-2-git-send-email-luca@luca-barbieri.com> diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h index 55fee12..e29a6c9 100644 --- a/arch/x86/include/asm/alternative.h +++ b/arch/x86/include/asm/alternative.h @@ -38,6 +38,7 @@ #define LOCK_PREFIX LOCK_PREFIX_HERE "\n\tlock; " #else /* ! CONFIG_SMP */ +#define LOCK_PREFIX_HERE "" #define LOCK_PREFIX "" #endif -- cgit v0.10.2 From 8795d7717c467bea7b0a0649d44a258e09f34db2 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Thu, 15 Apr 2010 23:10:42 +0200 Subject: lockdep: Fix redundant_hardirqs_on incremented with irqs enabled When a path restore the flags while irqs are already enabled, we update the per cpu var redundant_hardirqs_on in a racy fashion and debug_atomic_inc() warns about this situation. In this particular case, loosing a few hits in a stat is not a big deal, so increment it without protection. v2: Don't bother with disabling irq, we can miss one count in rare situations Reported-by: Stephen Rothwell Signed-off-by: Frederic Weisbecker Cc: Peter Zijlstra Cc: David Miller Cc: Benjamin Herrenschmidt diff --git a/kernel/lockdep.c b/kernel/lockdep.c index 78325f8..1b58a1b 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c @@ -2298,7 +2298,12 @@ void trace_hardirqs_on_caller(unsigned long ip) return; if (unlikely(curr->hardirqs_enabled)) { - debug_atomic_inc(redundant_hardirqs_on); + /* + * Neither irq nor preemption are disabled here + * so this is racy by nature but loosing one hit + * in a stat is not a big deal. + */ + this_cpu_inc(lockdep_stats.redundant_hardirqs_on); return; } /* we'll do an OFF -> ON transition: */ -- cgit v0.10.2 From 913769f24eadcd38a936ffae41d9b4895ec02e43 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Thu, 15 Apr 2010 23:10:43 +0200 Subject: lockdep: Simplify debug atomic ops Simplify debug_atomic_inc/dec by using this_cpu_inc/dec() instead of doing it through an indirect get_cpu_var() and a manual incrementation. Signed-off-by: Frederic Weisbecker Cc: Peter Zijlstra diff --git a/kernel/lockdep_internals.h b/kernel/lockdep_internals.h index 8d7d4b6..2b17476 100644 --- a/kernel/lockdep_internals.h +++ b/kernel/lockdep_internals.h @@ -140,19 +140,13 @@ struct lockdep_stats { DECLARE_PER_CPU(struct lockdep_stats, lockdep_stats); #define debug_atomic_inc(ptr) { \ - struct lockdep_stats *__cpu_lockdep_stats; \ - \ WARN_ON_ONCE(!irqs_disabled()); \ - __cpu_lockdep_stats = &__get_cpu_var(lockdep_stats); \ - __cpu_lockdep_stats->ptr++; \ + this_cpu_inc(lockdep_stats.ptr); \ } #define debug_atomic_dec(ptr) { \ - struct lockdep_stats *__cpu_lockdep_stats; \ - \ WARN_ON_ONCE(!irqs_disabled()); \ - __cpu_lockdep_stats = &__get_cpu_var(lockdep_stats); \ - __cpu_lockdep_stats->ptr--; \ + this_cpu_inc(lockdep_stats.ptr); \ } #define debug_atomic_read(ptr) ({ \ -- cgit v0.10.2 From e5a5f1f015cf435eb3d2f5712ba51ffdbb92cbef Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Fri, 30 Apr 2010 19:55:00 +0200 Subject: perf: Remove leftover useless options to record trace events from scripts -f, -c 1, -R are now useless for trace events recording, moreover -M is useless and event hurts. Remove them from the documentation examples and from record scripts. Signed-off-by: Frederic Weisbecker Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Tom Zanussi diff --git a/tools/perf/Documentation/perf-trace-perl.txt b/tools/perf/Documentation/perf-trace-perl.txt index d729cee..ee6525e 100644 --- a/tools/perf/Documentation/perf-trace-perl.txt +++ b/tools/perf/Documentation/perf-trace-perl.txt @@ -49,12 +49,10 @@ available as calls back into the perf executable (see below). As an example, the following perf record command can be used to record all sched_wakeup events in the system: - # perf record -c 1 -f -a -M -R -e sched:sched_wakeup + # perf record -a -e sched:sched_wakeup Traces meant to be processed using a script should be recorded with -the above options: -c 1 says to sample every event, -a to enable -system-wide collection, -M to multiplex the output, and -R to collect -raw samples. +the above option: -a to enable system-wide collection. The format file for the sched_wakep event defines the following fields (see /sys/kernel/debug/tracing/events/sched/sched_wakeup/format): diff --git a/tools/perf/Documentation/perf-trace-python.txt b/tools/perf/Documentation/perf-trace-python.txt index a241aca..16a8650 100644 --- a/tools/perf/Documentation/perf-trace-python.txt +++ b/tools/perf/Documentation/perf-trace-python.txt @@ -93,7 +93,7 @@ don't care how it exited, so we'll use 'perf record' to record only the sys_enter events: ---- -# perf record -c 1 -f -a -M -R -e raw_syscalls:sys_enter +# perf record -a -e raw_syscalls:sys_enter ^C[ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 56.545 MB perf.data (~2470503 samples) ] @@ -359,7 +359,7 @@ your script: # cat kernel-source/tools/perf/scripts/python/bin/syscall-counts-record #!/bin/bash -perf record -c 1 -f -a -M -R -e raw_syscalls:sys_enter +perf record -a -e raw_syscalls:sys_enter ---- The 'report' script is also a shell script with the same base name as @@ -449,12 +449,10 @@ available as calls back into the perf executable (see below). As an example, the following perf record command can be used to record all sched_wakeup events in the system: - # perf record -c 1 -f -a -M -R -e sched:sched_wakeup + # perf record -a -e sched:sched_wakeup Traces meant to be processed using a script should be recorded with -the above options: -c 1 says to sample every event, -a to enable -system-wide collection, -M to multiplex the output, and -R to collect -raw samples. +the above option: -a to enable system-wide collection. The format file for the sched_wakep event defines the following fields (see /sys/kernel/debug/tracing/events/sched/sched_wakeup/format): diff --git a/tools/perf/scripts/perl/bin/check-perf-trace-record b/tools/perf/scripts/perl/bin/check-perf-trace-record index e6cb147..423ad6a 100644 --- a/tools/perf/scripts/perl/bin/check-perf-trace-record +++ b/tools/perf/scripts/perl/bin/check-perf-trace-record @@ -1,2 +1,2 @@ #!/bin/bash -perf record -c 1 -f -a -M -R -e kmem:kmalloc -e irq:softirq_entry -e kmem:kfree +perf record -a -e kmem:kmalloc -e irq:softirq_entry -e kmem:kfree diff --git a/tools/perf/scripts/perl/bin/failed-syscalls-record b/tools/perf/scripts/perl/bin/failed-syscalls-record index 6ad9b8f..eb5846b 100644 --- a/tools/perf/scripts/perl/bin/failed-syscalls-record +++ b/tools/perf/scripts/perl/bin/failed-syscalls-record @@ -1,2 +1,2 @@ #!/bin/bash -perf record -c 1 -f -a -M -R -e raw_syscalls:sys_exit $@ +perf record -a -e raw_syscalls:sys_exit $@ diff --git a/tools/perf/scripts/perl/bin/rw-by-file-record b/tools/perf/scripts/perl/bin/rw-by-file-record index a828679..5bfaae5 100644 --- a/tools/perf/scripts/perl/bin/rw-by-file-record +++ b/tools/perf/scripts/perl/bin/rw-by-file-record @@ -1,3 +1,3 @@ #!/bin/bash -perf record -c 1 -f -a -M -R -e syscalls:sys_enter_read -e syscalls:sys_enter_write $@ +perf record -a -e syscalls:sys_enter_read -e syscalls:sys_enter_write $@ diff --git a/tools/perf/scripts/perl/bin/rw-by-pid-record b/tools/perf/scripts/perl/bin/rw-by-pid-record index 63976bf..6e0b2f7 100644 --- a/tools/perf/scripts/perl/bin/rw-by-pid-record +++ b/tools/perf/scripts/perl/bin/rw-by-pid-record @@ -1,2 +1,2 @@ #!/bin/bash -perf record -c 1 -f -a -M -R -e syscalls:sys_enter_read -e syscalls:sys_exit_read -e syscalls:sys_enter_write -e syscalls:sys_exit_write $@ +perf record -a -e syscalls:sys_enter_read -e syscalls:sys_exit_read -e syscalls:sys_enter_write -e syscalls:sys_exit_write $@ diff --git a/tools/perf/scripts/perl/bin/rwtop-record b/tools/perf/scripts/perl/bin/rwtop-record index 63976bf..6e0b2f7 100644 --- a/tools/perf/scripts/perl/bin/rwtop-record +++ b/tools/perf/scripts/perl/bin/rwtop-record @@ -1,2 +1,2 @@ #!/bin/bash -perf record -c 1 -f -a -M -R -e syscalls:sys_enter_read -e syscalls:sys_exit_read -e syscalls:sys_enter_write -e syscalls:sys_exit_write $@ +perf record -a -e syscalls:sys_enter_read -e syscalls:sys_exit_read -e syscalls:sys_enter_write -e syscalls:sys_exit_write $@ diff --git a/tools/perf/scripts/perl/bin/wakeup-latency-record b/tools/perf/scripts/perl/bin/wakeup-latency-record index 9c0cf58..9f2acaa 100644 --- a/tools/perf/scripts/perl/bin/wakeup-latency-record +++ b/tools/perf/scripts/perl/bin/wakeup-latency-record @@ -1,5 +1,5 @@ #!/bin/bash -perf record -c 1 -f -a -M -R -e sched:sched_switch -e sched:sched_wakeup $@ +perf record -a -e sched:sched_switch -e sched:sched_wakeup $@ diff --git a/tools/perf/scripts/perl/bin/workqueue-stats-record b/tools/perf/scripts/perl/bin/workqueue-stats-record index c2a1a94..85301f2 100644 --- a/tools/perf/scripts/perl/bin/workqueue-stats-record +++ b/tools/perf/scripts/perl/bin/workqueue-stats-record @@ -1,2 +1,2 @@ #!/bin/bash -perf record -c 1 -f -a -M -R -e workqueue:workqueue_creation -e workqueue:workqueue_destruction -e workqueue:workqueue_execution -e workqueue:workqueue_insertion $@ +perf record -a -e workqueue:workqueue_creation -e workqueue:workqueue_destruction -e workqueue:workqueue_execution -e workqueue:workqueue_insertion $@ diff --git a/tools/perf/scripts/python/bin/failed-syscalls-by-pid-record b/tools/perf/scripts/python/bin/failed-syscalls-by-pid-record index 6ad9b8f..eb5846b 100644 --- a/tools/perf/scripts/python/bin/failed-syscalls-by-pid-record +++ b/tools/perf/scripts/python/bin/failed-syscalls-by-pid-record @@ -1,2 +1,2 @@ #!/bin/bash -perf record -c 1 -f -a -M -R -e raw_syscalls:sys_exit $@ +perf record -a -e raw_syscalls:sys_exit $@ diff --git a/tools/perf/scripts/python/bin/sctop-record b/tools/perf/scripts/python/bin/sctop-record index 27ccffa..1fc5998 100644 --- a/tools/perf/scripts/python/bin/sctop-record +++ b/tools/perf/scripts/python/bin/sctop-record @@ -1,2 +1,2 @@ #!/bin/bash -perf record -c 1 -f -a -M -R -e raw_syscalls:sys_enter $@ +perf record -a -e raw_syscalls:sys_enter $@ diff --git a/tools/perf/scripts/python/bin/syscall-counts-by-pid-record b/tools/perf/scripts/python/bin/syscall-counts-by-pid-record index 27ccffa..1fc5998 100644 --- a/tools/perf/scripts/python/bin/syscall-counts-by-pid-record +++ b/tools/perf/scripts/python/bin/syscall-counts-by-pid-record @@ -1,2 +1,2 @@ #!/bin/bash -perf record -c 1 -f -a -M -R -e raw_syscalls:sys_enter $@ +perf record -a -e raw_syscalls:sys_enter $@ diff --git a/tools/perf/scripts/python/bin/syscall-counts-record b/tools/perf/scripts/python/bin/syscall-counts-record index 27ccffa..1fc5998 100644 --- a/tools/perf/scripts/python/bin/syscall-counts-record +++ b/tools/perf/scripts/python/bin/syscall-counts-record @@ -1,2 +1,2 @@ #!/bin/bash -perf record -c 1 -f -a -M -R -e raw_syscalls:sys_enter $@ +perf record -a -e raw_syscalls:sys_enter $@ -- cgit v0.10.2 From 96ff56419504ac6a610ff1af42330e0423242e16 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 30 Apr 2010 14:42:15 -0700 Subject: iwlwifi: work around passive scan issue Some firmware versions don't behave properly when passive scanning is requested on radar channels without enabling active scanning on receiving a good frame. Work around that issue by asking the firmware to only enable the active scanning after receiving a huge number of good frames, a number that can never be reached during our dwell time. Signed-off-by: Johannes Berg Signed-off-by: Reinette Chatre diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 6383d9f..f4e59ae 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -2621,7 +2621,9 @@ struct iwl_ssid_ie { #define PROBE_OPTION_MAX_3945 4 #define PROBE_OPTION_MAX 20 #define TX_CMD_LIFE_TIME_INFINITE cpu_to_le32(0xFFFFFFFF) -#define IWL_GOOD_CRC_TH cpu_to_le16(1) +#define IWL_GOOD_CRC_TH_DISABLED 0 +#define IWL_GOOD_CRC_TH_DEFAULT cpu_to_le16(1) +#define IWL_GOOD_CRC_TH_NEVER cpu_to_le16(0xffff) #define IWL_MAX_SCAN_SIZE 1024 #define IWL_MAX_CMD_SIZE 4096 #define IWL_MAX_PROBE_REQUEST 200 diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 5062f4e..2367286 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -812,16 +812,29 @@ static void iwl_bg_request_scan(struct work_struct *data) rate = IWL_RATE_1M_PLCP; rate_flags = RATE_MCS_CCK_MSK; } - scan->good_CRC_th = 0; + scan->good_CRC_th = IWL_GOOD_CRC_TH_DISABLED; } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) { band = IEEE80211_BAND_5GHZ; rate = IWL_RATE_6M_PLCP; /* - * If active scaning is requested but a certain channel - * is marked passive, we can do active scanning if we - * detect transmissions. + * If active scanning is requested but a certain channel is + * marked passive, we can do active scanning if we detect + * transmissions. + * + * There is an issue with some firmware versions that triggers + * a sysassert on a "good CRC threshold" of zero (== disabled), + * on a radar channel even though this means that we should NOT + * send probes. + * + * The "good CRC threshold" is the number of frames that we + * need to receive during our dwell time on a channel before + * sending out probes -- setting this to a huge value will + * mean we never reach it, but at the same time work around + * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER + * here instead of IWL_GOOD_CRC_TH_DISABLED. */ - scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0; + scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : + IWL_GOOD_CRC_TH_NEVER; /* Force use of chains B and C (0x6) for scan Rx for 4965 * Avoid A (0x1) because of its off-channel reception on A-band. diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index e276f2a..2f47d93 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2966,7 +2966,8 @@ static void iwl3945_bg_request_scan(struct work_struct *data) * is marked passive, we can do active scanning if we * detect transmissions. */ - scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0; + scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : + IWL_GOOD_CRC_TH_DISABLED; band = IEEE80211_BAND_5GHZ; } else { IWL_WARN(priv, "Invalid scan band count\n"); -- cgit v0.10.2 From d00a47cce569a3e660a8c9de5d57af28d6a9f0f7 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Sat, 1 May 2010 03:08:46 +0200 Subject: perf: Fix warning while reading ring buffer headers commit e9e94e3bd862d31777335722e747e97d9821bc1d "perf trace: Ignore "overwrite" field if present in /events/header_page" makes perf trace launching spurious warnings about unexpected tokens read: Warning: Error: expected type 6 but read 4 This change tries to handle the overcommit field in the header_page file whenever this field is present or not. The problem is that if this field is not present, we try to find it and give up in the middle of the line when we realize we are actually dealing with another field, which is the "data" one. And this failure abandons the file pointer in the middle of the "data" description line: field: u64 timestamp; offset:0; size:8; signed:0; field: local_t commit; offset:8; size:8; signed:1; field: char data; offset:16; size:4080; signed:1; ^^^ Here What happens next is that we want to read this line to parse the data field, but we fail because the pointer is not in the beginning of the line. We could probably fix that by rewinding the pointer. But in fact we don't care much about these headers that only concern the ftrace ring-buffer. We don't use them from perf. Just skip this part of perf.data, but don't remove it from recording to stay compatible with olders perf.data Signed-off-by: Frederic Weisbecker Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Stephane Eranian Cc: Steven Rostedt diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index d6ef414..069f261 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c @@ -691,11 +691,6 @@ static int __read_expected(enum event_type expect, const char *str, return ret; } -static int read_expected_warn(enum event_type expect, const char *str, bool warn) -{ - return __read_expected(expect, str, 1, warn); -} - static int read_expected(enum event_type expect, const char *str) { return __read_expected(expect, str, 1, true); @@ -3104,90 +3099,6 @@ static void print_args(struct print_arg *args) } } -static void parse_header_field(const char *field, - int *offset, int *size, bool warn) -{ - char *token; - int type; - - if (read_expected(EVENT_ITEM, "field") < 0) - return; - if (read_expected(EVENT_OP, ":") < 0) - return; - - /* type */ - if (read_expect_type(EVENT_ITEM, &token) < 0) - goto fail; - free_token(token); - - if (read_expected_warn(EVENT_ITEM, field, warn) < 0) - return; - if (read_expected(EVENT_OP, ";") < 0) - return; - if (read_expected(EVENT_ITEM, "offset") < 0) - return; - if (read_expected(EVENT_OP, ":") < 0) - return; - if (read_expect_type(EVENT_ITEM, &token) < 0) - goto fail; - *offset = atoi(token); - free_token(token); - if (read_expected(EVENT_OP, ";") < 0) - return; - if (read_expected(EVENT_ITEM, "size") < 0) - return; - if (read_expected(EVENT_OP, ":") < 0) - return; - if (read_expect_type(EVENT_ITEM, &token) < 0) - goto fail; - *size = atoi(token); - free_token(token); - if (read_expected(EVENT_OP, ";") < 0) - return; - type = read_token(&token); - if (type != EVENT_NEWLINE) { - /* newer versions of the kernel have a "signed" type */ - if (type != EVENT_ITEM) - goto fail; - - if (strcmp(token, "signed") != 0) - goto fail; - - free_token(token); - - if (read_expected(EVENT_OP, ":") < 0) - return; - - if (read_expect_type(EVENT_ITEM, &token)) - goto fail; - - free_token(token); - if (read_expected(EVENT_OP, ";") < 0) - return; - - if (read_expect_type(EVENT_NEWLINE, &token)) - goto fail; - } - fail: - free_token(token); -} - -int parse_header_page(char *buf, unsigned long size) -{ - init_input_buf(buf, size); - - parse_header_field("timestamp", &header_page_ts_offset, - &header_page_ts_size, true); - parse_header_field("commit", &header_page_size_offset, - &header_page_size_size, true); - parse_header_field("overwrite", &header_page_overwrite_offset, - &header_page_overwrite_size, false); - parse_header_field("data", &header_page_data_offset, - &header_page_data_size, true); - - return 0; -} - int parse_ftrace_file(char *buf, unsigned long size) { struct format_field *field; diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c index 44889c9..4606639 100644 --- a/tools/perf/util/trace-event-read.c +++ b/tools/perf/util/trace-event-read.c @@ -52,6 +52,12 @@ static unsigned long page_size; static ssize_t calc_data_size; +/* If it fails, the next read will report it */ +static void skip(int size) +{ + lseek(input_fd, size, SEEK_CUR); +} + static int do_read(int fd, void *buf, int size) { int rsize = size; @@ -169,7 +175,6 @@ static void read_ftrace_printk(void) static void read_header_files(void) { unsigned long long size; - char *header_page; char *header_event; char buf[BUFSIZ]; @@ -179,10 +184,7 @@ static void read_header_files(void) die("did not read header page"); size = read8(); - header_page = malloc_or_die(size); - read_or_die(header_page, size); - parse_header_page(header_page, size); - free(header_page); + skip(size); /* * The size field in the page is of type long, diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h index 1f45d46..4e1acc3 100644 --- a/tools/perf/util/trace-event.h +++ b/tools/perf/util/trace-event.h @@ -244,7 +244,6 @@ extern int header_page_data_size; extern bool latency_format; -int parse_header_page(char *buf, unsigned long size); int trace_parse_common_type(void *data); int trace_parse_common_pid(void *data); int parse_common_pc(void *data); -- cgit v0.10.2 From 73266fc1df2f94cf72b3beba3eee3b88ed0b0664 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Thu, 22 Apr 2010 05:05:45 +0200 Subject: hw-breakpoints: Tag ptrace breakpoint as exclude_kernel Tag ptrace breakpoints with the exclude_kernel attribute set. This will make it easier to set generic policies on breakpoints, when it comes to ensure nobody unpriviliged try to breakpoint on the kernel. Signed-off-by: Frederic Weisbecker Acked-by: Paul Mundt Cc: Will Deacon Cc: Mahesh Salgaonkar Cc: K. Prasad Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Ingo Molnar diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c index 7759a9a..d4104ce 100644 --- a/arch/sh/kernel/ptrace_32.c +++ b/arch/sh/kernel/ptrace_32.c @@ -85,7 +85,7 @@ static int set_single_step(struct task_struct *tsk, unsigned long addr) bp = thread->ptrace_bps[0]; if (!bp) { - hw_breakpoint_init(&attr); + ptrace_breakpoint_init(&attr); attr.bp_addr = addr; attr.bp_len = HW_BREAKPOINT_LEN_2; diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index 055be0a..70c4872 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -688,7 +688,7 @@ static int ptrace_set_breakpoint_addr(struct task_struct *tsk, int nr, struct perf_event_attr attr; if (!t->ptrace_bps[nr]) { - hw_breakpoint_init(&attr); + ptrace_breakpoint_init(&attr); /* * Put stub len and type to register (reserve) an inactive but * correct bp diff --git a/include/linux/hw_breakpoint.h b/include/linux/hw_breakpoint.h index c70d27a..a0aa5a9 100644 --- a/include/linux/hw_breakpoint.h +++ b/include/linux/hw_breakpoint.h @@ -34,6 +34,12 @@ static inline void hw_breakpoint_init(struct perf_event_attr *attr) attr->sample_period = 1; } +static inline void ptrace_breakpoint_init(struct perf_event_attr *attr) +{ + hw_breakpoint_init(attr); + attr->exclude_kernel = 1; +} + static inline unsigned long hw_breakpoint_addr(struct perf_event *bp) { return bp->attr.bp_addr; -- cgit v0.10.2 From 87e9b2024659c614a876ce359a57e98a47b5ef37 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Sat, 17 Apr 2010 18:11:59 +0200 Subject: hw-breakpoints: Check disabled breakpoints again We stopped checking disabled breakpoints because we weren't allowing breakpoints on NULL addresses. And gdb tends to set NULL addresses on inactive breakpoints. But refusing NULL addresses was actually a regression that has been fixed now. There is no reason anymore to not validate inactive breakpoint settings. Signed-off-by: Frederic Weisbecker Acked-by: Paul Mundt Cc: Will Deacon Cc: Mahesh Salgaonkar Cc: K. Prasad Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Jason Wessel Cc: Ingo Molnar diff --git a/kernel/hw_breakpoint.c b/kernel/hw_breakpoint.c index 03808ed..9ed9ae3a 100644 --- a/kernel/hw_breakpoint.c +++ b/kernel/hw_breakpoint.c @@ -316,17 +316,7 @@ int register_perf_hw_breakpoint(struct perf_event *bp) if (ret) return ret; - /* - * Ptrace breakpoints can be temporary perf events only - * meant to reserve a slot. In this case, it is created disabled and - * we don't want to check the params right now (as we put a null addr) - * But perf tools create events as disabled and we want to check - * the params for them. - * This is a quick hack that will be removed soon, once we remove - * the tmp breakpoints from ptrace - */ - if (!bp->attr.disabled || !bp->overflow_handler) - ret = arch_validate_hwbkpt_settings(bp, bp->ctx->task); + ret = arch_validate_hwbkpt_settings(bp, bp->ctx->task); /* if arch_validate_hwbkpt_settings() fails then release bp slot */ if (ret) -- cgit v0.10.2 From b2812d031dea86926e9c10f7714af33ac2f6b43d Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Sun, 18 Apr 2010 18:11:53 +0200 Subject: hw-breakpoints: Change/Enforce some breakpoints policies The current policies of breakpoints in x86 and SH are the following: - task bound breakpoints can only break on userspace addresses - cpu wide breakpoints can only break on kernel addresses The former rule prevents ptrace breakpoints to be set to trigger on kernel addresses, which is good. But as a side effect, we can't breakpoint on kernel addresses for task bound breakpoints. The latter rule simply makes no sense, there is no reason why we can't set breakpoints on userspace while performing cpu bound profiles. We want the following new policies: - task bound breakpoint can set userspace address breakpoints, with no particular privilege required. - task bound breakpoints can set kernelspace address breakpoints but must be privileged to do that. - cpu bound breakpoints can do what they want as they are privileged already. To implement these new policies, this patch checks if we are dealing with a kernel address breakpoint, if so and if the exclude_kernel parameter is set, we tell the user that the breakpoint is invalid, which makes a good generic ptrace protection. If we don't have exclude_kernel, ensure the user has the right privileges as kernel breakpoints are quite sensitive (risk of trap recursion attacks and global performance impacts). [ Paul Mundt: keep addr space check for sh signal delivery and fix double function declaration] Signed-off-by: Frederic Weisbecker Cc: Will Deacon Cc: Mahesh Salgaonkar Cc: K. Prasad Cc: Paul Mundt Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Jason Wessel Cc: Ingo Molnar Signed-off-by: Paul Mundt diff --git a/arch/sh/include/asm/hw_breakpoint.h b/arch/sh/include/asm/hw_breakpoint.h index 965dd78..382bad9 100644 --- a/arch/sh/include/asm/hw_breakpoint.h +++ b/arch/sh/include/asm/hw_breakpoint.h @@ -47,9 +47,8 @@ struct pmu; #define HBP_NUM 2 /* arch/sh/kernel/hw_breakpoint.c */ -extern int arch_check_va_in_userspace(unsigned long va, u16 hbp_len); -extern int arch_validate_hwbkpt_settings(struct perf_event *bp, - struct task_struct *tsk); +extern int arch_check_bp_in_kernelspace(struct perf_event *bp); +extern int arch_validate_hwbkpt_settings(struct perf_event *bp); extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused, unsigned long val, void *data); diff --git a/arch/sh/kernel/hw_breakpoint.c b/arch/sh/kernel/hw_breakpoint.c index 675eea7..1f2cf62 100644 --- a/arch/sh/kernel/hw_breakpoint.c +++ b/arch/sh/kernel/hw_breakpoint.c @@ -120,25 +120,16 @@ static int get_hbp_len(u16 hbp_len) } /* - * Check for virtual address in user space. - */ -int arch_check_va_in_userspace(unsigned long va, u16 hbp_len) -{ - unsigned int len; - - len = get_hbp_len(hbp_len); - - return (va <= TASK_SIZE - len); -} - -/* * Check for virtual address in kernel space. */ -static int arch_check_va_in_kernelspace(unsigned long va, u8 hbp_len) +int arch_check_bp_in_kernelspace(struct perf_event *bp) { unsigned int len; + unsigned long va; + struct arch_hw_breakpoint *info = counter_arch_bp(bp); - len = get_hbp_len(hbp_len); + va = info->address; + len = get_hbp_len(info->len); return (va >= TASK_SIZE) && ((va + len - 1) >= TASK_SIZE); } @@ -226,8 +217,7 @@ static int arch_build_bp_info(struct perf_event *bp) /* * Validate the arch-specific HW Breakpoint register settings */ -int arch_validate_hwbkpt_settings(struct perf_event *bp, - struct task_struct *tsk) +int arch_validate_hwbkpt_settings(struct perf_event *bp) { struct arch_hw_breakpoint *info = counter_arch_bp(bp); unsigned int align; @@ -270,15 +260,6 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp, if (info->address & align) return -EINVAL; - /* Check that the virtual address is in the proper range */ - if (tsk) { - if (!arch_check_va_in_userspace(info->address, info->len)) - return -EFAULT; - } else { - if (!arch_check_va_in_kernelspace(info->address, info->len)) - return -EFAULT; - } - return 0; } @@ -363,8 +344,7 @@ static int __kprobes hw_breakpoint_handler(struct die_args *args) perf_bp_event(bp, args->regs); /* Deliver the signal to userspace */ - if (arch_check_va_in_userspace(bp->attr.bp_addr, - bp->attr.bp_len)) { + if (!arch_check_bp_in_kernelspace(bp)) { siginfo_t info; info.si_signo = args->signr; diff --git a/arch/x86/include/asm/hw_breakpoint.h b/arch/x86/include/asm/hw_breakpoint.h index 2a1bd8f..c77a5a6 100644 --- a/arch/x86/include/asm/hw_breakpoint.h +++ b/arch/x86/include/asm/hw_breakpoint.h @@ -44,9 +44,8 @@ struct arch_hw_breakpoint { struct perf_event; struct pmu; -extern int arch_check_va_in_userspace(unsigned long va, u8 hbp_len); -extern int arch_validate_hwbkpt_settings(struct perf_event *bp, - struct task_struct *tsk); +extern int arch_check_bp_in_kernelspace(struct perf_event *bp); +extern int arch_validate_hwbkpt_settings(struct perf_event *bp); extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused, unsigned long val, void *data); diff --git a/arch/x86/kernel/hw_breakpoint.c b/arch/x86/kernel/hw_breakpoint.c index d6cc065..a8f1b80 100644 --- a/arch/x86/kernel/hw_breakpoint.c +++ b/arch/x86/kernel/hw_breakpoint.c @@ -189,25 +189,16 @@ static int get_hbp_len(u8 hbp_len) } /* - * Check for virtual address in user space. - */ -int arch_check_va_in_userspace(unsigned long va, u8 hbp_len) -{ - unsigned int len; - - len = get_hbp_len(hbp_len); - - return (va <= TASK_SIZE - len); -} - -/* * Check for virtual address in kernel space. */ -static int arch_check_va_in_kernelspace(unsigned long va, u8 hbp_len) +int arch_check_bp_in_kernelspace(struct perf_event *bp) { unsigned int len; + unsigned long va; + struct arch_hw_breakpoint *info = counter_arch_bp(bp); - len = get_hbp_len(hbp_len); + va = info->address; + len = get_hbp_len(info->len); return (va >= TASK_SIZE) && ((va + len - 1) >= TASK_SIZE); } @@ -300,8 +291,7 @@ static int arch_build_bp_info(struct perf_event *bp) /* * Validate the arch-specific HW Breakpoint register settings */ -int arch_validate_hwbkpt_settings(struct perf_event *bp, - struct task_struct *tsk) +int arch_validate_hwbkpt_settings(struct perf_event *bp) { struct arch_hw_breakpoint *info = counter_arch_bp(bp); unsigned int align; @@ -314,16 +304,6 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp, ret = -EINVAL; - if (info->type == X86_BREAKPOINT_EXECUTE) - /* - * Ptrace-refactoring code - * For now, we'll allow instruction breakpoint only for user-space - * addresses - */ - if ((!arch_check_va_in_userspace(info->address, info->len)) && - info->len != X86_BREAKPOINT_EXECUTE) - return ret; - switch (info->len) { case X86_BREAKPOINT_LEN_1: align = 0; @@ -350,15 +330,6 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp, if (info->address & align) return -EINVAL; - /* Check that the virtual address is in the proper range */ - if (tsk) { - if (!arch_check_va_in_userspace(info->address, info->len)) - return -EFAULT; - } else { - if (!arch_check_va_in_kernelspace(info->address, info->len)) - return -EFAULT; - } - return 0; } diff --git a/kernel/hw_breakpoint.c b/kernel/hw_breakpoint.c index 9ed9ae3a..89e8a05 100644 --- a/kernel/hw_breakpoint.c +++ b/kernel/hw_breakpoint.c @@ -308,6 +308,28 @@ int dbg_release_bp_slot(struct perf_event *bp) return 0; } +static int validate_hw_breakpoint(struct perf_event *bp) +{ + int ret; + + ret = arch_validate_hwbkpt_settings(bp); + if (ret) + return ret; + + if (arch_check_bp_in_kernelspace(bp)) { + if (bp->attr.exclude_kernel) + return -EINVAL; + /* + * Don't let unprivileged users set a breakpoint in the trap + * path to avoid trap recursion attacks. + */ + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + } + + return 0; +} + int register_perf_hw_breakpoint(struct perf_event *bp) { int ret; @@ -316,7 +338,7 @@ int register_perf_hw_breakpoint(struct perf_event *bp) if (ret) return ret; - ret = arch_validate_hwbkpt_settings(bp, bp->ctx->task); + ret = validate_hw_breakpoint(bp); /* if arch_validate_hwbkpt_settings() fails then release bp slot */ if (ret) @@ -363,7 +385,7 @@ int modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *att if (attr->disabled) goto end; - err = arch_validate_hwbkpt_settings(bp, bp->ctx->task); + err = validate_hw_breakpoint(bp); if (!err) perf_event_enable(bp); -- cgit v0.10.2 From 0102752e4c9e0655b39734550d4c35327954f7f9 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Sun, 11 Apr 2010 18:55:56 +0200 Subject: hw-breakpoints: Separate constraint space for data and instruction breakpoints There are two outstanding fashions for archs to implement hardware breakpoints. The first is to separate breakpoint address pattern definition space between data and instruction breakpoints. We then have typically distinct instruction address breakpoint registers and data address breakpoint registers, delivered with separate control registers for data and instruction breakpoints as well. This is the case of PowerPc and ARM for example. The second consists in having merged breakpoint address space definition between data and instruction breakpoint. Address registers can host either instruction or data address and the access mode for the breakpoint is defined in a control register. This is the case of x86 and Super H. This patch adds a new CONFIG_HAVE_MIXED_BREAKPOINTS_REGS config that archs can select if they belong to the second case. Those will have their slot allocation merged for instructions and data breakpoints. The others will have a separate slot tracking between data and instruction breakpoints. Signed-off-by: Frederic Weisbecker Acked-by: Paul Mundt Cc: Will Deacon Cc: Mahesh Salgaonkar Cc: K. Prasad Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Ingo Molnar diff --git a/arch/Kconfig b/arch/Kconfig index f06010f..acda512 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -137,6 +137,17 @@ config HAVE_HW_BREAKPOINT bool depends on PERF_EVENTS +config HAVE_MIXED_BREAKPOINTS_REGS + bool + depends on HAVE_HW_BREAKPOINT + help + Depending on the arch implementation of hardware breakpoints, + some of them have separate registers for data and instruction + breakpoints addresses, others have mixed registers to store + them but define the access type in a control register. + Select this option if your arch implements breakpoints under the + latter fashion. + config HAVE_USER_RETURN_NOTIFIER bool diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 8d90564..e6d8ab5 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -44,6 +44,7 @@ config SUPERH32 select HAVE_FUNCTION_GRAPH_TRACER select HAVE_ARCH_KGDB select HAVE_HW_BREAKPOINT + select HAVE_MIXED_BREAKPOINTS_REGS select PERF_EVENTS if HAVE_HW_BREAKPOINT select ARCH_HIBERNATION_POSSIBLE if MMU diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 97a95df..01177dc 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -53,6 +53,7 @@ config X86 select HAVE_KERNEL_LZMA select HAVE_KERNEL_LZO select HAVE_HW_BREAKPOINT + select HAVE_MIXED_BREAKPOINTS_REGS select PERF_EVENTS select ANON_INODES select HAVE_ARCH_KMEMCHECK diff --git a/include/linux/hw_breakpoint.h b/include/linux/hw_breakpoint.h index a0aa5a9..7e88990 100644 --- a/include/linux/hw_breakpoint.h +++ b/include/linux/hw_breakpoint.h @@ -9,9 +9,12 @@ enum { }; enum { - HW_BREAKPOINT_R = 1, - HW_BREAKPOINT_W = 2, - HW_BREAKPOINT_X = 4, + HW_BREAKPOINT_EMPTY = 0, + HW_BREAKPOINT_R = 1, + HW_BREAKPOINT_W = 2, + HW_BREAKPOINT_RW = HW_BREAKPOINT_R | HW_BREAKPOINT_W, + HW_BREAKPOINT_X = 4, + HW_BREAKPOINT_INVALID = HW_BREAKPOINT_RW | HW_BREAKPOINT_X, }; #ifdef __KERNEL__ diff --git a/kernel/hw_breakpoint.c b/kernel/hw_breakpoint.c index 89e8a05..8ead134 100644 --- a/kernel/hw_breakpoint.c +++ b/kernel/hw_breakpoint.c @@ -45,18 +45,28 @@ #include +enum bp_type_idx { + TYPE_INST = 0, +#ifdef CONFIG_HAVE_MIXED_BREAKPOINTS_REGS + TYPE_DATA = 0, +#else + TYPE_DATA = 1, +#endif + TYPE_MAX +}; + /* * Constraints data */ /* Number of pinned cpu breakpoints in a cpu */ -static DEFINE_PER_CPU(unsigned int, nr_cpu_bp_pinned); +static DEFINE_PER_CPU(unsigned int, nr_cpu_bp_pinned[TYPE_MAX]); /* Number of pinned task breakpoints in a cpu */ -static DEFINE_PER_CPU(unsigned int, nr_task_bp_pinned[HBP_NUM]); +static DEFINE_PER_CPU(unsigned int, nr_task_bp_pinned[TYPE_MAX][HBP_NUM]); /* Number of non-pinned cpu/task breakpoints in a cpu */ -static DEFINE_PER_CPU(unsigned int, nr_bp_flexible); +static DEFINE_PER_CPU(unsigned int, nr_bp_flexible[TYPE_MAX]); /* Gather the number of total pinned and un-pinned bp in a cpuset */ struct bp_busy_slots { @@ -67,14 +77,22 @@ struct bp_busy_slots { /* Serialize accesses to the above constraints */ static DEFINE_MUTEX(nr_bp_mutex); +static inline enum bp_type_idx find_slot_idx(struct perf_event *bp) +{ + if (bp->attr.bp_type & HW_BREAKPOINT_RW) + return TYPE_DATA; + + return TYPE_INST; +} + /* * Report the maximum number of pinned breakpoints a task * have in this cpu */ -static unsigned int max_task_bp_pinned(int cpu) +static unsigned int max_task_bp_pinned(int cpu, enum bp_type_idx type) { int i; - unsigned int *tsk_pinned = per_cpu(nr_task_bp_pinned, cpu); + unsigned int *tsk_pinned = per_cpu(nr_task_bp_pinned[type], cpu); for (i = HBP_NUM -1; i >= 0; i--) { if (tsk_pinned[i] > 0) @@ -84,7 +102,7 @@ static unsigned int max_task_bp_pinned(int cpu) return 0; } -static int task_bp_pinned(struct task_struct *tsk) +static int task_bp_pinned(struct task_struct *tsk, enum bp_type_idx type) { struct perf_event_context *ctx = tsk->perf_event_ctxp; struct list_head *list; @@ -105,7 +123,8 @@ static int task_bp_pinned(struct task_struct *tsk) */ list_for_each_entry(bp, list, event_entry) { if (bp->attr.type == PERF_TYPE_BREAKPOINT) - count++; + if (find_slot_idx(bp) == type) + count++; } raw_spin_unlock_irqrestore(&ctx->lock, flags); @@ -118,18 +137,19 @@ static int task_bp_pinned(struct task_struct *tsk) * a given cpu (cpu > -1) or in all of them (cpu = -1). */ static void -fetch_bp_busy_slots(struct bp_busy_slots *slots, struct perf_event *bp) +fetch_bp_busy_slots(struct bp_busy_slots *slots, struct perf_event *bp, + enum bp_type_idx type) { int cpu = bp->cpu; struct task_struct *tsk = bp->ctx->task; if (cpu >= 0) { - slots->pinned = per_cpu(nr_cpu_bp_pinned, cpu); + slots->pinned = per_cpu(nr_cpu_bp_pinned[type], cpu); if (!tsk) - slots->pinned += max_task_bp_pinned(cpu); + slots->pinned += max_task_bp_pinned(cpu, type); else - slots->pinned += task_bp_pinned(tsk); - slots->flexible = per_cpu(nr_bp_flexible, cpu); + slots->pinned += task_bp_pinned(tsk, type); + slots->flexible = per_cpu(nr_bp_flexible[type], cpu); return; } @@ -137,16 +157,16 @@ fetch_bp_busy_slots(struct bp_busy_slots *slots, struct perf_event *bp) for_each_online_cpu(cpu) { unsigned int nr; - nr = per_cpu(nr_cpu_bp_pinned, cpu); + nr = per_cpu(nr_cpu_bp_pinned[type], cpu); if (!tsk) - nr += max_task_bp_pinned(cpu); + nr += max_task_bp_pinned(cpu, type); else - nr += task_bp_pinned(tsk); + nr += task_bp_pinned(tsk, type); if (nr > slots->pinned) slots->pinned = nr; - nr = per_cpu(nr_bp_flexible, cpu); + nr = per_cpu(nr_bp_flexible[type], cpu); if (nr > slots->flexible) slots->flexible = nr; @@ -156,14 +176,15 @@ fetch_bp_busy_slots(struct bp_busy_slots *slots, struct perf_event *bp) /* * Add a pinned breakpoint for the given task in our constraint table */ -static void toggle_bp_task_slot(struct task_struct *tsk, int cpu, bool enable) +static void toggle_bp_task_slot(struct task_struct *tsk, int cpu, bool enable, + enum bp_type_idx type) { unsigned int *tsk_pinned; int count = 0; - count = task_bp_pinned(tsk); + count = task_bp_pinned(tsk, type); - tsk_pinned = per_cpu(nr_task_bp_pinned, cpu); + tsk_pinned = per_cpu(nr_task_bp_pinned[type], cpu); if (enable) { tsk_pinned[count]++; if (count > 0) @@ -178,7 +199,8 @@ static void toggle_bp_task_slot(struct task_struct *tsk, int cpu, bool enable) /* * Add/remove the given breakpoint in our constraint table */ -static void toggle_bp_slot(struct perf_event *bp, bool enable) +static void +toggle_bp_slot(struct perf_event *bp, bool enable, enum bp_type_idx type) { int cpu = bp->cpu; struct task_struct *tsk = bp->ctx->task; @@ -186,20 +208,20 @@ static void toggle_bp_slot(struct perf_event *bp, bool enable) /* Pinned counter task profiling */ if (tsk) { if (cpu >= 0) { - toggle_bp_task_slot(tsk, cpu, enable); + toggle_bp_task_slot(tsk, cpu, enable, type); return; } for_each_online_cpu(cpu) - toggle_bp_task_slot(tsk, cpu, enable); + toggle_bp_task_slot(tsk, cpu, enable, type); return; } /* Pinned counter cpu profiling */ if (enable) - per_cpu(nr_cpu_bp_pinned, bp->cpu)++; + per_cpu(nr_cpu_bp_pinned[type], bp->cpu)++; else - per_cpu(nr_cpu_bp_pinned, bp->cpu)--; + per_cpu(nr_cpu_bp_pinned[type], bp->cpu)--; } /* @@ -246,14 +268,21 @@ static void toggle_bp_slot(struct perf_event *bp, bool enable) static int __reserve_bp_slot(struct perf_event *bp) { struct bp_busy_slots slots = {0}; + enum bp_type_idx type; - fetch_bp_busy_slots(&slots, bp); + /* Basic checks */ + if (bp->attr.bp_type == HW_BREAKPOINT_EMPTY || + bp->attr.bp_type == HW_BREAKPOINT_INVALID) + return -EINVAL; + + type = find_slot_idx(bp); + fetch_bp_busy_slots(&slots, bp, type); /* Flexible counters need to keep at least one slot */ if (slots.pinned + (!!slots.flexible) == HBP_NUM) return -ENOSPC; - toggle_bp_slot(bp, true); + toggle_bp_slot(bp, true, type); return 0; } @@ -273,7 +302,10 @@ int reserve_bp_slot(struct perf_event *bp) static void __release_bp_slot(struct perf_event *bp) { - toggle_bp_slot(bp, false); + enum bp_type_idx type; + + type = find_slot_idx(bp); + toggle_bp_slot(bp, false, type); } void release_bp_slot(struct perf_event *bp) -- cgit v0.10.2 From f93a20541134fa767e8dc4eb32e956d30b9f6b92 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Tue, 13 Apr 2010 00:32:30 +0200 Subject: hw-breakpoints: Handle breakpoint weight in allocation constraints Depending on their nature and on what an arch supports, breakpoints may consume more than one address register. For example a simple absolute address match usually only requires one address register. But an address range match may consume two registers. Currently our slot allocation constraints, that tend to reflect the limited arch's resources, always consider that a breakpoint consumes one slot. Then provide a way for archs to tell us the weight of a breakpoint through a new hw_breakpoint_weight() helper. This weight will be computed against the generic allocation constraints instead of a constant value. Signed-off-by: Frederic Weisbecker Acked-by: Paul Mundt Cc: Will Deacon Cc: Mahesh Salgaonkar Cc: K. Prasad Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Ingo Molnar diff --git a/kernel/hw_breakpoint.c b/kernel/hw_breakpoint.c index 8ead134..974498b8 100644 --- a/kernel/hw_breakpoint.c +++ b/kernel/hw_breakpoint.c @@ -77,6 +77,11 @@ struct bp_busy_slots { /* Serialize accesses to the above constraints */ static DEFINE_MUTEX(nr_bp_mutex); +__weak int hw_breakpoint_weight(struct perf_event *bp) +{ + return 1; +} + static inline enum bp_type_idx find_slot_idx(struct perf_event *bp) { if (bp->attr.bp_type & HW_BREAKPOINT_RW) @@ -124,7 +129,7 @@ static int task_bp_pinned(struct task_struct *tsk, enum bp_type_idx type) list_for_each_entry(bp, list, event_entry) { if (bp->attr.type == PERF_TYPE_BREAKPOINT) if (find_slot_idx(bp) == type) - count++; + count += hw_breakpoint_weight(bp); } raw_spin_unlock_irqrestore(&ctx->lock, flags); @@ -174,25 +179,40 @@ fetch_bp_busy_slots(struct bp_busy_slots *slots, struct perf_event *bp, } /* + * For now, continue to consider flexible as pinned, until we can + * ensure no flexible event can ever be scheduled before a pinned event + * in a same cpu. + */ +static void +fetch_this_slot(struct bp_busy_slots *slots, int weight) +{ + slots->pinned += weight; +} + +/* * Add a pinned breakpoint for the given task in our constraint table */ static void toggle_bp_task_slot(struct task_struct *tsk, int cpu, bool enable, - enum bp_type_idx type) + enum bp_type_idx type, int weight) { unsigned int *tsk_pinned; - int count = 0; + int old_count = 0; + int old_idx = 0; + int idx = 0; - count = task_bp_pinned(tsk, type); + old_count = task_bp_pinned(tsk, type); + old_idx = old_count - 1; + idx = old_idx + weight; tsk_pinned = per_cpu(nr_task_bp_pinned[type], cpu); if (enable) { - tsk_pinned[count]++; - if (count > 0) - tsk_pinned[count-1]--; + tsk_pinned[idx]++; + if (old_count > 0) + tsk_pinned[old_idx]--; } else { - tsk_pinned[count]--; - if (count > 0) - tsk_pinned[count-1]++; + tsk_pinned[idx]--; + if (old_count > 0) + tsk_pinned[old_idx]++; } } @@ -200,7 +220,8 @@ static void toggle_bp_task_slot(struct task_struct *tsk, int cpu, bool enable, * Add/remove the given breakpoint in our constraint table */ static void -toggle_bp_slot(struct perf_event *bp, bool enable, enum bp_type_idx type) +toggle_bp_slot(struct perf_event *bp, bool enable, enum bp_type_idx type, + int weight) { int cpu = bp->cpu; struct task_struct *tsk = bp->ctx->task; @@ -208,20 +229,20 @@ toggle_bp_slot(struct perf_event *bp, bool enable, enum bp_type_idx type) /* Pinned counter task profiling */ if (tsk) { if (cpu >= 0) { - toggle_bp_task_slot(tsk, cpu, enable, type); + toggle_bp_task_slot(tsk, cpu, enable, type, weight); return; } for_each_online_cpu(cpu) - toggle_bp_task_slot(tsk, cpu, enable, type); + toggle_bp_task_slot(tsk, cpu, enable, type, weight); return; } /* Pinned counter cpu profiling */ if (enable) - per_cpu(nr_cpu_bp_pinned[type], bp->cpu)++; + per_cpu(nr_cpu_bp_pinned[type], bp->cpu) += weight; else - per_cpu(nr_cpu_bp_pinned[type], bp->cpu)--; + per_cpu(nr_cpu_bp_pinned[type], bp->cpu) -= weight; } /* @@ -269,6 +290,7 @@ static int __reserve_bp_slot(struct perf_event *bp) { struct bp_busy_slots slots = {0}; enum bp_type_idx type; + int weight; /* Basic checks */ if (bp->attr.bp_type == HW_BREAKPOINT_EMPTY || @@ -276,13 +298,16 @@ static int __reserve_bp_slot(struct perf_event *bp) return -EINVAL; type = find_slot_idx(bp); + weight = hw_breakpoint_weight(bp); + fetch_bp_busy_slots(&slots, bp, type); + fetch_this_slot(&slots, weight); /* Flexible counters need to keep at least one slot */ - if (slots.pinned + (!!slots.flexible) == HBP_NUM) + if (slots.pinned + (!!slots.flexible) > HBP_NUM) return -ENOSPC; - toggle_bp_slot(bp, true, type); + toggle_bp_slot(bp, true, type, weight); return 0; } @@ -303,9 +328,11 @@ int reserve_bp_slot(struct perf_event *bp) static void __release_bp_slot(struct perf_event *bp) { enum bp_type_idx type; + int weight; type = find_slot_idx(bp); - toggle_bp_slot(bp, false, type); + weight = hw_breakpoint_weight(bp); + toggle_bp_slot(bp, false, type, weight); } void release_bp_slot(struct perf_event *bp) -- cgit v0.10.2 From feef47d0cb530e8419dfa0b48141b538b89b1b1a Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Fri, 23 Apr 2010 05:59:55 +0200 Subject: hw-breakpoints: Get the number of available registers on boot dynamically The breakpoint generic layer assumes that archs always know in advance the static number of address registers available to host breakpoints through the HBP_NUM macro. However this is not true for every archs. For example Arm needs to get this information dynamically to handle the compatiblity between different versions. To solve this, this patch proposes to drop the static HBP_NUM macro and let the arch provide the number of available slots through a new hw_breakpoint_slots() function. For archs that have CONFIG_HAVE_MIXED_BREAKPOINTS_REGS selected, it will be called once as the number of registers fits for instruction and data breakpoints together. For the others it will be called first to get the number of instruction breakpoint registers and another time to get the data breakpoint registers, the targeted type is given as a parameter of hw_breakpoint_slots(). Reported-by: Will Deacon Signed-off-by: Frederic Weisbecker Acked-by: Paul Mundt Cc: Mahesh Salgaonkar Cc: K. Prasad Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Jason Wessel Cc: Ingo Molnar diff --git a/arch/sh/include/asm/hw_breakpoint.h b/arch/sh/include/asm/hw_breakpoint.h index 382bad9..e14cad9 100644 --- a/arch/sh/include/asm/hw_breakpoint.h +++ b/arch/sh/include/asm/hw_breakpoint.h @@ -46,6 +46,11 @@ struct pmu; /* Maximum number of UBC channels */ #define HBP_NUM 2 +static inline int hw_breakpoint_slots(int type) +{ + return HBP_NUM; +} + /* arch/sh/kernel/hw_breakpoint.c */ extern int arch_check_bp_in_kernelspace(struct perf_event *bp); extern int arch_validate_hwbkpt_settings(struct perf_event *bp); diff --git a/arch/x86/include/asm/hw_breakpoint.h b/arch/x86/include/asm/hw_breakpoint.h index c77a5a6..9422553 100644 --- a/arch/x86/include/asm/hw_breakpoint.h +++ b/arch/x86/include/asm/hw_breakpoint.h @@ -41,6 +41,11 @@ struct arch_hw_breakpoint { /* Total number of available HW breakpoint registers */ #define HBP_NUM 4 +static inline int hw_breakpoint_slots(int type) +{ + return HBP_NUM; +} + struct perf_event; struct pmu; diff --git a/include/linux/hw_breakpoint.h b/include/linux/hw_breakpoint.h index 7e88990..a2d6ea4 100644 --- a/include/linux/hw_breakpoint.h +++ b/include/linux/hw_breakpoint.h @@ -17,6 +17,16 @@ enum { HW_BREAKPOINT_INVALID = HW_BREAKPOINT_RW | HW_BREAKPOINT_X, }; +enum bp_type_idx { + TYPE_INST = 0, +#ifdef CONFIG_HAVE_MIXED_BREAKPOINTS_REGS + TYPE_DATA = 0, +#else + TYPE_DATA = 1, +#endif + TYPE_MAX +}; + #ifdef __KERNEL__ #include diff --git a/kernel/hw_breakpoint.c b/kernel/hw_breakpoint.c index 974498b8..684b710 100644 --- a/kernel/hw_breakpoint.c +++ b/kernel/hw_breakpoint.c @@ -40,20 +40,12 @@ #include #include #include +#include #include #include #include -enum bp_type_idx { - TYPE_INST = 0, -#ifdef CONFIG_HAVE_MIXED_BREAKPOINTS_REGS - TYPE_DATA = 0, -#else - TYPE_DATA = 1, -#endif - TYPE_MAX -}; /* * Constraints data @@ -63,11 +55,15 @@ enum bp_type_idx { static DEFINE_PER_CPU(unsigned int, nr_cpu_bp_pinned[TYPE_MAX]); /* Number of pinned task breakpoints in a cpu */ -static DEFINE_PER_CPU(unsigned int, nr_task_bp_pinned[TYPE_MAX][HBP_NUM]); +static DEFINE_PER_CPU(unsigned int, *nr_task_bp_pinned[TYPE_MAX]); /* Number of non-pinned cpu/task breakpoints in a cpu */ static DEFINE_PER_CPU(unsigned int, nr_bp_flexible[TYPE_MAX]); +static int nr_slots[TYPE_MAX]; + +static int constraints_initialized; + /* Gather the number of total pinned and un-pinned bp in a cpuset */ struct bp_busy_slots { unsigned int pinned; @@ -99,7 +95,7 @@ static unsigned int max_task_bp_pinned(int cpu, enum bp_type_idx type) int i; unsigned int *tsk_pinned = per_cpu(nr_task_bp_pinned[type], cpu); - for (i = HBP_NUM -1; i >= 0; i--) { + for (i = nr_slots[type] - 1; i >= 0; i--) { if (tsk_pinned[i] > 0) return i + 1; } @@ -292,6 +288,10 @@ static int __reserve_bp_slot(struct perf_event *bp) enum bp_type_idx type; int weight; + /* We couldn't initialize breakpoint constraints on boot */ + if (!constraints_initialized) + return -ENOMEM; + /* Basic checks */ if (bp->attr.bp_type == HW_BREAKPOINT_EMPTY || bp->attr.bp_type == HW_BREAKPOINT_INVALID) @@ -304,7 +304,7 @@ static int __reserve_bp_slot(struct perf_event *bp) fetch_this_slot(&slots, weight); /* Flexible counters need to keep at least one slot */ - if (slots.pinned + (!!slots.flexible) > HBP_NUM) + if (slots.pinned + (!!slots.flexible) > nr_slots[type]) return -ENOSPC; toggle_bp_slot(bp, true, type, weight); @@ -551,7 +551,36 @@ static struct notifier_block hw_breakpoint_exceptions_nb = { static int __init init_hw_breakpoint(void) { + unsigned int **task_bp_pinned; + int cpu, err_cpu; + int i; + + for (i = 0; i < TYPE_MAX; i++) + nr_slots[i] = hw_breakpoint_slots(i); + + for_each_possible_cpu(cpu) { + for (i = 0; i < TYPE_MAX; i++) { + task_bp_pinned = &per_cpu(nr_task_bp_pinned[i], cpu); + *task_bp_pinned = kzalloc(sizeof(int) * nr_slots[i], + GFP_KERNEL); + if (!*task_bp_pinned) + goto err_alloc; + } + } + + constraints_initialized = 1; + return register_die_notifier(&hw_breakpoint_exceptions_nb); + + err_alloc: + for_each_possible_cpu(err_cpu) { + if (err_cpu == cpu) + break; + for (i = 0; i < TYPE_MAX; i++) + kfree(per_cpu(nr_task_bp_pinned[i], cpu)); + } + + return -ENOMEM; } core_initcall(init_hw_breakpoint); diff --git a/kernel/trace/trace_ksym.c b/kernel/trace/trace_ksym.c index d59cd68..8eaf007 100644 --- a/kernel/trace/trace_ksym.c +++ b/kernel/trace/trace_ksym.c @@ -34,12 +34,6 @@ #include -/* - * For now, let us restrict the no. of symbols traced simultaneously to number - * of available hardware breakpoint registers. - */ -#define KSYM_TRACER_MAX HBP_NUM - #define KSYM_TRACER_OP_LEN 3 /* rw- */ struct trace_ksym { @@ -53,7 +47,6 @@ struct trace_ksym { static struct trace_array *ksym_trace_array; -static unsigned int ksym_filter_entry_count; static unsigned int ksym_tracing_enabled; static HLIST_HEAD(ksym_filter_head); @@ -181,13 +174,6 @@ int process_new_ksym_entry(char *ksymname, int op, unsigned long addr) struct trace_ksym *entry; int ret = -ENOMEM; - if (ksym_filter_entry_count >= KSYM_TRACER_MAX) { - printk(KERN_ERR "ksym_tracer: Maximum limit:(%d) reached. No" - " new requests for tracing can be accepted now.\n", - KSYM_TRACER_MAX); - return -ENOSPC; - } - entry = kzalloc(sizeof(struct trace_ksym), GFP_KERNEL); if (!entry) return -ENOMEM; @@ -203,13 +189,17 @@ int process_new_ksym_entry(char *ksymname, int op, unsigned long addr) if (IS_ERR(entry->ksym_hbp)) { ret = PTR_ERR(entry->ksym_hbp); - printk(KERN_INFO "ksym_tracer request failed. Try again" - " later!!\n"); + if (ret == -ENOSPC) { + printk(KERN_ERR "ksym_tracer: Maximum limit reached." + " No new requests for tracing can be accepted now.\n"); + } else { + printk(KERN_INFO "ksym_tracer request failed. Try again" + " later!!\n"); + } goto err; } hlist_add_head_rcu(&(entry->ksym_hlist), &ksym_filter_head); - ksym_filter_entry_count++; return 0; @@ -265,7 +255,6 @@ static void __ksym_trace_reset(void) hlist_for_each_entry_safe(entry, node, node1, &ksym_filter_head, ksym_hlist) { unregister_wide_hw_breakpoint(entry->ksym_hbp); - ksym_filter_entry_count--; hlist_del_rcu(&(entry->ksym_hlist)); synchronize_rcu(); kfree(entry); @@ -338,7 +327,6 @@ static ssize_t ksym_trace_filter_write(struct file *file, goto out_unlock; } /* Error or "symbol:---" case: drop it */ - ksym_filter_entry_count--; hlist_del_rcu(&(entry->ksym_hlist)); synchronize_rcu(); kfree(entry); -- cgit v0.10.2 From ad342631f13d40aa787b9e5aaf4800f10d6c3647 Mon Sep 17 00:00:00 2001 From: Joern Engel Date: Tue, 27 Apr 2010 13:45:31 +0200 Subject: logfs: Return -EINVAL if filesystem image doesn't match Signed-off-by: Joern Engel diff --git a/fs/logfs/super.c b/fs/logfs/super.c index 7fc4625..edd9948 100644 --- a/fs/logfs/super.c +++ b/fs/logfs/super.c @@ -413,7 +413,7 @@ static int __logfs_read_sb(struct super_block *sb) page = find_super_block(sb); if (!page) - return -EIO; + return -EINVAL; ds = page_address(page); super->s_size = be64_to_cpu(ds->ds_filesystem_size); -- cgit v0.10.2 From bd2b3f29594c50d7c5bd864d9af05d440394ee82 Mon Sep 17 00:00:00 2001 From: Joern Engel Date: Sat, 1 May 2010 17:33:06 +0200 Subject: logfs: fix logfs_seek_hole() logfs_seek_hole(inode, 0x200) would crap itself if the inode contained just 0x1ff (or fewer) blocks. Signed-off-by: Joern Engel diff --git a/fs/logfs/readwrite.c b/fs/logfs/readwrite.c index 8c663a5..e37cee3 100644 --- a/fs/logfs/readwrite.c +++ b/fs/logfs/readwrite.c @@ -892,6 +892,8 @@ u64 logfs_seek_hole(struct inode *inode, u64 bix) return bix; else if (li->li_data[INDIRECT_INDEX] & LOGFS_FULLY_POPULATED) bix = maxbix(li->li_height); + else if (bix >= maxbix(li->li_height)) + return bix; else { bix = seek_holedata_loop(inode, bix, 0); if (bix < maxbix(li->li_height)) -- cgit v0.10.2 From ccc0197b02178f7e1707e659cbc5242fc94b499a Mon Sep 17 00:00:00 2001 From: Joern Engel Date: Sat, 1 May 2010 17:00:34 +0200 Subject: logfs: Close i_ino reuse race logfs_seek_hole() may return the same offset it is passed as argument. Found by Prasad Joshi Signed-off-by: Joern Engel diff --git a/fs/logfs/inode.c b/fs/logfs/inode.c index 14ed272..45bf86f 100644 --- a/fs/logfs/inode.c +++ b/fs/logfs/inode.c @@ -326,7 +326,7 @@ static void logfs_set_ino_generation(struct super_block *sb, u64 ino; mutex_lock(&super->s_journal_mutex); - ino = logfs_seek_hole(super->s_master_inode, super->s_last_ino); + ino = logfs_seek_hole(super->s_master_inode, super->s_last_ino + 1); super->s_last_ino = ino; super->s_inos_till_wrap--; if (super->s_inos_till_wrap < 0) { -- cgit v0.10.2 From da7ba956c84d3c85c5ec619af794a6ca0ee3faae Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 17 Jan 2010 19:59:58 +0000 Subject: ARM: Integrator: fix Integrator/CP definitions, move to platform.h Signed-off-by: Russell King diff --git a/arch/arm/mach-integrator/include/mach/platform.h b/arch/arm/mach-integrator/include/mach/platform.h index e00a262..0e172e4 100644 --- a/arch/arm/mach-integrator/include/mach/platform.h +++ b/arch/arm/mach-integrator/include/mach/platform.h @@ -290,12 +290,14 @@ #define INTEGRATOR_DBG_LEDS (INTEGRATOR_DBG_BASE + INTEGRATOR_DBG_LEDS_OFFSET) #define INTEGRATOR_DBG_SWITCH (INTEGRATOR_DBG_BASE + INTEGRATOR_DBG_SWITCH_OFFSET) - -#if defined(CONFIG_ARCH_INTEGRATOR_AP) -#define INTEGRATOR_GPIO_BASE 0x1B000000 /* GPIO */ -#elif defined(CONFIG_ARCH_INTEGRATOR_CP) -#define INTEGRATOR_GPIO_BASE 0xC9000000 /* GPIO */ -#endif +#define INTEGRATOR_AP_GPIO_BASE 0x1B000000 /* GPIO */ + +#define INTEGRATOR_CP_MMC_BASE 0x1C000000 /* MMC */ +#define INTEGRATOR_CP_AACI_BASE 0x1D000000 /* AACI */ +#define INTEGRATOR_CP_ETH_BASE 0xC8000000 /* Ethernet */ +#define INTEGRATOR_CP_GPIO_BASE 0xC9000000 /* GPIO */ +#define INTEGRATOR_CP_SIC_BASE 0xCA000000 /* SIC */ +#define INTEGRATOR_CP_CTL_BASE 0xCB000000 /* CP system control */ /* ------------------------------------------------------------------------ * KMI keyboard/mouse definitions diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c index 93da7d4..45bba04 100644 --- a/arch/arm/mach-integrator/integrator_ap.c +++ b/arch/arm/mach-integrator/integrator_ap.c @@ -118,8 +118,8 @@ static struct map_desc ap_io_desc[] __initdata = { .length = SZ_4K, .type = MT_DEVICE }, { - .virtual = IO_ADDRESS(INTEGRATOR_GPIO_BASE), - .pfn = __phys_to_pfn(INTEGRATOR_GPIO_BASE), + .virtual = IO_ADDRESS(INTEGRATOR_AP_GPIO_BASE), + .pfn = __phys_to_pfn(INTEGRATOR_AP_GPIO_BASE), .length = SZ_4K, .type = MT_DEVICE }, { diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 108bc48..333c297 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -42,9 +42,6 @@ #include "common.h" -#define INTCP_PA_MMC_BASE 0x1c000000 -#define INTCP_PA_AACI_BASE 0x1d000000 - #define INTCP_PA_FLASH_BASE 0x24000000 #define INTCP_FLASH_SIZE SZ_32M @@ -52,12 +49,11 @@ #define INTCP_VA_CIC_BASE IO_ADDRESS(INTEGRATOR_HDR_BASE) + 0x40 #define INTCP_VA_PIC_BASE IO_ADDRESS(INTEGRATOR_IC_BASE) -#define INTCP_VA_SIC_BASE IO_ADDRESS(0xca000000) +#define INTCP_VA_SIC_BASE IO_ADDRESS(INTEGRATOR_CP_SIC_BASE) -#define INTCP_PA_ETH_BASE 0xc8000000 #define INTCP_ETH_SIZE 0x10 -#define INTCP_VA_CTRL_BASE IO_ADDRESS(0xcb000000) +#define INTCP_VA_CTRL_BASE IO_ADDRESS(INTEGRATOR_CP_CTL_BASE) #define INTCP_FLASHPROG 0x04 #define CINTEGRATOR_FLASHPROG_FLVPPEN (1 << 0) #define CINTEGRATOR_FLASHPROG_FLWREN (1 << 1) @@ -72,7 +68,9 @@ * f1600000 16000000 UART 0 * f1700000 17000000 UART 1 * f1a00000 1a000000 Debug LEDs - * f1b00000 1b000000 GPIO + * fc900000 c9000000 GPIO + * fca00000 ca000000 SIC + * fcb00000 cb000000 CP system control */ static struct map_desc intcp_io_desc[] __initdata = { @@ -117,18 +115,18 @@ static struct map_desc intcp_io_desc[] __initdata = { .length = SZ_4K, .type = MT_DEVICE }, { - .virtual = IO_ADDRESS(INTEGRATOR_GPIO_BASE), - .pfn = __phys_to_pfn(INTEGRATOR_GPIO_BASE), + .virtual = IO_ADDRESS(INTEGRATOR_CP_GPIO_BASE), + .pfn = __phys_to_pfn(INTEGRATOR_CP_GPIO_BASE), .length = SZ_4K, .type = MT_DEVICE }, { - .virtual = IO_ADDRESS(0xca000000), - .pfn = __phys_to_pfn(0xca000000), + .virtual = IO_ADDRESS(INTEGRATOR_CP_SIC_BASE), + .pfn = __phys_to_pfn(INTEGRATOR_CP_SIC_BASE), .length = SZ_4K, .type = MT_DEVICE }, { - .virtual = IO_ADDRESS(0xcb000000), - .pfn = __phys_to_pfn(0xcb000000), + .virtual = IO_ADDRESS(INTEGRATOR_CP_CTL_BASE), + .pfn = __phys_to_pfn(INTEGRATOR_CP_CTL_BASE), .length = SZ_4K, .type = MT_DEVICE } @@ -364,8 +362,8 @@ static struct platform_device intcp_flash_device = { static struct resource smc91x_resources[] = { [0] = { - .start = INTCP_PA_ETH_BASE, - .end = INTCP_PA_ETH_BASE + INTCP_ETH_SIZE - 1, + .start = INTEGRATOR_CP_ETH_BASE, + .end = INTEGRATOR_CP_ETH_BASE + INTCP_ETH_SIZE - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -396,7 +394,7 @@ static struct platform_device *intcp_devs[] __initdata = { static unsigned int mmc_status(struct device *dev) { unsigned int status = readl(IO_ADDRESS(0xca000000) + 4); - writel(8, IO_ADDRESS(0xcb000000) + 8); + writel(8, IO_ADDRESS(INTEGRATOR_CP_CTL_BASE) + 8); return status & 8; } @@ -414,8 +412,8 @@ static struct amba_device mmc_device = { .platform_data = &mmc_data, }, .res = { - .start = INTCP_PA_MMC_BASE, - .end = INTCP_PA_MMC_BASE + SZ_4K - 1, + .start = INTEGRATOR_CP_MMC_BASE, + .end = INTEGRATOR_CP_MMC_BASE + SZ_4K - 1, .flags = IORESOURCE_MEM, }, .irq = { IRQ_CP_MMCIINT0, IRQ_CP_MMCIINT1 }, @@ -427,8 +425,8 @@ static struct amba_device aaci_device = { .init_name = "mb:1d", }, .res = { - .start = INTCP_PA_AACI_BASE, - .end = INTCP_PA_AACI_BASE + SZ_4K - 1, + .start = INTEGRATOR_CP_AACI_BASE, + .end = INTEGRATOR_CP_AACI_BASE + SZ_4K - 1, .flags = IORESOURCE_MEM, }, .irq = { IRQ_CP_AACIINT, NO_IRQ }, -- cgit v0.10.2 From 7d60a044c8226d86fa93c2cf90ccdb97e3ba28fa Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 17 Jan 2010 20:23:57 +0000 Subject: ARM: Integrator: allow IO_ADDRESS() to be used for register addresses Signed-off-by: Russell King diff --git a/arch/arm/mach-integrator/include/mach/hardware.h b/arch/arm/mach-integrator/include/mach/hardware.h index d44af72..8e26360 100644 --- a/arch/arm/mach-integrator/include/mach/hardware.h +++ b/arch/arm/mach-integrator/include/mach/hardware.h @@ -35,18 +35,18 @@ #define PCIO_BASE PCI_IO_VADDR #define PCIMEM_BASE PCI_MEMORY_VADDR -#ifdef CONFIG_MMU -/* macro to get at IO space when running virtually */ -#define IO_ADDRESS(x) (((x) >> 4) + IO_BASE) -#else -#define IO_ADDRESS(x) (x) -#endif - #define pcibios_assign_all_busses() 1 #define PCIBIOS_MIN_IO 0x6000 #define PCIBIOS_MIN_MEM 0x00100000 +/* macro to get at IO space when running virtually */ +#ifdef CONFIG_MMU +#define IO_ADDRESS(x) (((x) & 0x000fffff) | (((x) >> 4) & 0x0ff00000) | IO_BASE) +#else +#define IO_ADDRESS(x) (x) +#endif + #define __io_address(n) ((void __iomem *)IO_ADDRESS(n)) #endif -- cgit v0.10.2 From b830b9b5b3d04bc22f0b9ded85b713f7d3c11b7f Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 17 Jan 2010 20:45:12 +0000 Subject: ARM: Integrator: convert to use register definitions Rather than using converted base address plus offset, use the register address itself now that IO_ADDRESS() can cope with these. Signed-off-by: Russell King diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c index d02f0e3..ac2b0c5 100644 --- a/arch/arm/mach-integrator/core.c +++ b/arch/arm/mach-integrator/core.c @@ -166,8 +166,8 @@ arch_initcall(integrator_init); * UART0 7 6 * UART1 5 4 */ -#define SC_CTRLC (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLC_OFFSET) -#define SC_CTRLS (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLS_OFFSET) +#define SC_CTRLC IO_ADDRESS(INTEGRATOR_SC_CTRLC) +#define SC_CTRLS IO_ADDRESS(INTEGRATOR_SC_CTRLS) static void integrator_uart_set_mctrl(struct amba_device *dev, void __iomem *base, unsigned int mctrl) { @@ -199,7 +199,7 @@ static struct amba_pl010_data integrator_uart_data = { .set_mctrl = integrator_uart_set_mctrl, }; -#define CM_CTRL IO_ADDRESS(INTEGRATOR_HDR_BASE) + INTEGRATOR_HDR_CTRL_OFFSET +#define CM_CTRL IO_ADDRESS(INTEGRATOR_HDR_CTRL) static DEFINE_SPINLOCK(cm_lock); @@ -224,9 +224,9 @@ EXPORT_SYMBOL(cm_control); /* * Where is the timer (VA)? */ -#define TIMER0_VA_BASE (IO_ADDRESS(INTEGRATOR_CT_BASE)+0x00000000) -#define TIMER1_VA_BASE (IO_ADDRESS(INTEGRATOR_CT_BASE)+0x00000100) -#define TIMER2_VA_BASE (IO_ADDRESS(INTEGRATOR_CT_BASE)+0x00000200) +#define TIMER0_VA_BASE IO_ADDRESS(INTEGRATOR_TIMER0_BASE) +#define TIMER1_VA_BASE IO_ADDRESS(INTEGRATOR_TIMER1_BASE) +#define TIMER2_VA_BASE IO_ADDRESS(INTEGRATOR_TIMER2_BASE) /* * How long is the timer interval? diff --git a/arch/arm/mach-integrator/cpu.c b/arch/arm/mach-integrator/cpu.c index b761879..7f1b73b 100644 --- a/arch/arm/mach-integrator/cpu.c +++ b/arch/arm/mach-integrator/cpu.c @@ -26,10 +26,10 @@ static struct cpufreq_driver integrator_driver; -#define CM_ID (IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_ID_OFFSET) -#define CM_OSC (IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_OSC_OFFSET) -#define CM_STAT (IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_STAT_OFFSET) -#define CM_LOCK (IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_LOCK_OFFSET) +#define CM_ID IO_ADDRESS(INTEGRATOR_HDR_ID) +#define CM_OSC IO_ADDRESS(INTEGRATOR_HDR_OSC) +#define CM_STAT IO_ADDRESS(INTEGRATOR_HDR_STAT) +#define CM_LOCK IO_ADDRESS(INTEGRATOR_HDR_LOCK) static const struct icst525_params lclk_params = { .ref = 24000, diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c index 45bba04..c89b231 100644 --- a/arch/arm/mach-integrator/integrator_ap.c +++ b/arch/arm/mach-integrator/integrator_ap.c @@ -56,7 +56,7 @@ #define VA_IC_BASE IO_ADDRESS(INTEGRATOR_IC_BASE) #define VA_SC_BASE IO_ADDRESS(INTEGRATOR_SC_BASE) #define VA_EBI_BASE IO_ADDRESS(INTEGRATOR_EBI_BASE) -#define VA_CMIC_BASE IO_ADDRESS(INTEGRATOR_HDR_BASE) + INTEGRATOR_HDR_IC_OFFSET +#define VA_CMIC_BASE IO_ADDRESS(INTEGRATOR_HDR_IC) /* * Logical Physical diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 333c297..c0161df 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -47,7 +47,7 @@ #define INTCP_PA_CLCD_BASE 0xc0000000 -#define INTCP_VA_CIC_BASE IO_ADDRESS(INTEGRATOR_HDR_BASE) + 0x40 +#define INTCP_VA_CIC_BASE IO_ADDRESS(INTEGRATOR_HDR_BASE + 0x40) #define INTCP_VA_PIC_BASE IO_ADDRESS(INTEGRATOR_IC_BASE) #define INTCP_VA_SIC_BASE IO_ADDRESS(INTEGRATOR_CP_SIC_BASE) @@ -265,8 +265,8 @@ static void __init intcp_init_irq(void) /* * Clock handling */ -#define CM_LOCK (IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_LOCK_OFFSET) -#define CM_AUXOSC (IO_ADDRESS(INTEGRATOR_HDR_BASE)+0x1c) +#define CM_LOCK IO_ADDRESS(INTEGRATOR_HDR_LOCK) +#define CM_AUXOSC IO_ADDRESS(INTEGRATOR_HDR_BASE + 0x1c) static const struct icst525_params cp_auxvco_params = { .ref = 24000, @@ -393,8 +393,8 @@ static struct platform_device *intcp_devs[] __initdata = { */ static unsigned int mmc_status(struct device *dev) { - unsigned int status = readl(IO_ADDRESS(0xca000000) + 4); - writel(8, IO_ADDRESS(INTEGRATOR_CP_CTL_BASE) + 8); + unsigned int status = readl(IO_ADDRESS(0xca000000 + 4)); + writel(8, IO_ADDRESS(INTEGRATOR_CP_CTL_BASE + 8)); return status & 8; } diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c index e87fe9f..e549162 100644 --- a/arch/arm/mach-integrator/pci_v3.c +++ b/arch/arm/mach-integrator/pci_v3.c @@ -391,9 +391,9 @@ static int __init pci_v3_setup_resources(struct resource **resource) * means I can't get additional information on the reason for the pm2fb * problems. I suppose I'll just have to mind-meld with the machine. ;) */ -#define SC_PCI (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_PCIENABLE_OFFSET) -#define SC_LBFADDR (IO_ADDRESS(INTEGRATOR_SC_BASE) + 0x20) -#define SC_LBFCODE (IO_ADDRESS(INTEGRATOR_SC_BASE) + 0x24) +#define SC_PCI IO_ADDRESS(INTEGRATOR_SC_PCIENABLE) +#define SC_LBFADDR IO_ADDRESS(INTEGRATOR_SC_BASE + 0x20) +#define SC_LBFCODE IO_ADDRESS(INTEGRATOR_SC_BASE + 0x24) static int v3_pci_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) -- cgit v0.10.2 From 39c0cb02db5b8fdfac76d506b7a008b70bc960e9 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 16 Jan 2010 16:27:28 +0000 Subject: ARM: ICST: merge common ICST VCO structures The structures for the ICST307 and ICST525 VCO devices are identical, so merge them together. Signed-off-by: Russell King diff --git a/arch/arm/common/icst307.c b/arch/arm/common/icst307.c index 6d094c1..2eebd96 100644 --- a/arch/arm/common/icst307.c +++ b/arch/arm/common/icst307.c @@ -24,7 +24,7 @@ */ static unsigned char s2div[8] = { 10, 2, 8, 4, 5, 7, 3, 6 }; -unsigned long icst307_khz(const struct icst307_params *p, struct icst307_vco vco) +unsigned long icst307_khz(const struct icst_params *p, struct icst_vco vco) { return p->ref * 2 * (vco.v + 8) / ((vco.r + 2) * s2div[vco.s]); } @@ -36,10 +36,10 @@ EXPORT_SYMBOL(icst307_khz); */ static unsigned char idx2s[8] = { 1, 6, 3, 4, 7, 5, 2, 0 }; -struct icst307_vco -icst307_khz_to_vco(const struct icst307_params *p, unsigned long freq) +struct icst_vco +icst307_khz_to_vco(const struct icst_params *p, unsigned long freq) { - struct icst307_vco vco = { .s = 1, .v = p->vd_max, .r = p->rd_max }; + struct icst_vco vco = { .s = 1, .v = p->vd_max, .r = p->rd_max }; unsigned long f; unsigned int i = 0, rd, best = (unsigned int)-1; @@ -96,10 +96,10 @@ icst307_khz_to_vco(const struct icst307_params *p, unsigned long freq) EXPORT_SYMBOL(icst307_khz_to_vco); -struct icst307_vco -icst307_ps_to_vco(const struct icst307_params *p, unsigned long period) +struct icst_vco +icst307_ps_to_vco(const struct icst_params *p, unsigned long period) { - struct icst307_vco vco = { .s = 1, .v = p->vd_max, .r = p->rd_max }; + struct icst_vco vco = { .s = 1, .v = p->vd_max, .r = p->rd_max }; unsigned long f, ps; unsigned int i = 0, rd, best = (unsigned int)-1; diff --git a/arch/arm/common/icst525.c b/arch/arm/common/icst525.c index 3d377c5..fd5c2e7 100644 --- a/arch/arm/common/icst525.c +++ b/arch/arm/common/icst525.c @@ -21,7 +21,7 @@ */ static unsigned char s2div[8] = { 10, 2, 8, 4, 5, 7, 9, 6 }; -unsigned long icst525_khz(const struct icst525_params *p, struct icst525_vco vco) +unsigned long icst525_khz(const struct icst_params *p, struct icst_vco vco) { return p->ref * 2 * (vco.v + 8) / ((vco.r + 2) * s2div[vco.s]); } @@ -33,10 +33,10 @@ EXPORT_SYMBOL(icst525_khz); */ static unsigned char idx2s[] = { 1, 3, 4, 7, 5, 2, 6, 0 }; -struct icst525_vco -icst525_khz_to_vco(const struct icst525_params *p, unsigned long freq) +struct icst_vco +icst525_khz_to_vco(const struct icst_params *p, unsigned long freq) { - struct icst525_vco vco = { .s = 1, .v = p->vd_max, .r = p->rd_max }; + struct icst_vco vco = { .s = 1, .v = p->vd_max, .r = p->rd_max }; unsigned long f; unsigned int i = 0, rd, best = (unsigned int)-1; @@ -94,10 +94,10 @@ icst525_khz_to_vco(const struct icst525_params *p, unsigned long freq) EXPORT_SYMBOL(icst525_khz_to_vco); -struct icst525_vco -icst525_ps_to_vco(const struct icst525_params *p, unsigned long period) +struct icst_vco +icst525_ps_to_vco(const struct icst_params *p, unsigned long period) { - struct icst525_vco vco = { .s = 1, .v = p->vd_max, .r = p->rd_max }; + struct icst_vco vco = { .s = 1, .v = p->vd_max, .r = p->rd_max }; unsigned long f, ps; unsigned int i = 0, rd, best = (unsigned int)-1; diff --git a/arch/arm/include/asm/hardware/icst.h b/arch/arm/include/asm/hardware/icst.h new file mode 100644 index 0000000..65b1edd --- /dev/null +++ b/arch/arm/include/asm/hardware/icst.h @@ -0,0 +1,32 @@ +/* + * arch/arm/include/asm/hardware/icst.h + * + * Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Support functions for calculating clocks/divisors for the ICST + * clock generators. See http://www.icst.com/ for more information + * on these devices. + */ +#ifndef ASMARM_HARDWARE_ICST_H +#define ASMARM_HARDWARE_ICST_H + +struct icst_params { + unsigned long ref; + unsigned long vco_max; /* inclusive */ + unsigned short vd_min; /* inclusive */ + unsigned short vd_max; /* inclusive */ + unsigned char rd_min; /* inclusive */ + unsigned char rd_max; /* inclusive */ +}; + +struct icst_vco { + unsigned short v; + unsigned char r; + unsigned char s; +}; + +#endif diff --git a/arch/arm/include/asm/hardware/icst307.h b/arch/arm/include/asm/hardware/icst307.h index 554f128..85932e9 100644 --- a/arch/arm/include/asm/hardware/icst307.h +++ b/arch/arm/include/asm/hardware/icst307.h @@ -16,23 +16,10 @@ #ifndef ASMARM_HARDWARE_ICST307_H #define ASMARM_HARDWARE_ICST307_H -struct icst307_params { - unsigned long ref; - unsigned long vco_max; /* inclusive */ - unsigned short vd_min; /* inclusive */ - unsigned short vd_max; /* inclusive */ - unsigned char rd_min; /* inclusive */ - unsigned char rd_max; /* inclusive */ -}; +#include -struct icst307_vco { - unsigned short v; - unsigned char r; - unsigned char s; -}; - -unsigned long icst307_khz(const struct icst307_params *p, struct icst307_vco vco); -struct icst307_vco icst307_khz_to_vco(const struct icst307_params *p, unsigned long freq); -struct icst307_vco icst307_ps_to_vco(const struct icst307_params *p, unsigned long period); +unsigned long icst307_khz(const struct icst_params *p, struct icst_vco vco); +struct icst_vco icst307_khz_to_vco(const struct icst_params *p, unsigned long freq); +struct icst_vco icst307_ps_to_vco(const struct icst_params *p, unsigned long period); #endif diff --git a/arch/arm/include/asm/hardware/icst525.h b/arch/arm/include/asm/hardware/icst525.h index 58f0dc4..170deb2 100644 --- a/arch/arm/include/asm/hardware/icst525.h +++ b/arch/arm/include/asm/hardware/icst525.h @@ -14,23 +14,10 @@ #ifndef ASMARM_HARDWARE_ICST525_H #define ASMARM_HARDWARE_ICST525_H -struct icst525_params { - unsigned long ref; - unsigned long vco_max; /* inclusive */ - unsigned short vd_min; /* inclusive */ - unsigned short vd_max; /* inclusive */ - unsigned char rd_min; /* inclusive */ - unsigned char rd_max; /* inclusive */ -}; +#include -struct icst525_vco { - unsigned short v; - unsigned char r; - unsigned char s; -}; - -unsigned long icst525_khz(const struct icst525_params *p, struct icst525_vco vco); -struct icst525_vco icst525_khz_to_vco(const struct icst525_params *p, unsigned long freq); -struct icst525_vco icst525_ps_to_vco(const struct icst525_params *p, unsigned long period); +unsigned long icst525_khz(const struct icst_params *p, struct icst_vco vco); +struct icst_vco icst525_khz_to_vco(const struct icst_params *p, unsigned long freq); +struct icst_vco icst525_ps_to_vco(const struct icst_params *p, unsigned long period); #endif diff --git a/arch/arm/mach-integrator/clock.c b/arch/arm/mach-integrator/clock.c index 989ecf5f..bb70b64 100644 --- a/arch/arm/mach-integrator/clock.c +++ b/arch/arm/mach-integrator/clock.c @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -36,7 +37,7 @@ EXPORT_SYMBOL(clk_get_rate); long clk_round_rate(struct clk *clk, unsigned long rate) { - struct icst525_vco vco; + struct icst_vco vco; vco = icst525_khz_to_vco(clk->params, rate / 1000); return icst525_khz(clk->params, vco) * 1000; } @@ -47,7 +48,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate) int ret = -EIO; if (clk->setvco) { - struct icst525_vco vco; + struct icst_vco vco; vco = icst525_khz_to_vco(clk->params, rate / 1000); clk->rate = icst525_khz(clk->params, vco) * 1000; diff --git a/arch/arm/mach-integrator/cpu.c b/arch/arm/mach-integrator/cpu.c index 7f1b73b..c4e5deb 100644 --- a/arch/arm/mach-integrator/cpu.c +++ b/arch/arm/mach-integrator/cpu.c @@ -31,7 +31,7 @@ static struct cpufreq_driver integrator_driver; #define CM_STAT IO_ADDRESS(INTEGRATOR_HDR_STAT) #define CM_LOCK IO_ADDRESS(INTEGRATOR_HDR_LOCK) -static const struct icst525_params lclk_params = { +static const struct icst_params lclk_params = { .ref = 24000, .vco_max = 320000, .vd_min = 8, @@ -40,7 +40,7 @@ static const struct icst525_params lclk_params = { .rd_max = 24, }; -static const struct icst525_params cclk_params = { +static const struct icst_params cclk_params = { .ref = 24000, .vco_max = 320000, .vd_min = 12, @@ -54,7 +54,7 @@ static const struct icst525_params cclk_params = { */ static int integrator_verify_policy(struct cpufreq_policy *policy) { - struct icst525_vco vco; + struct icst_vco vco; cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, @@ -80,7 +80,7 @@ static int integrator_set_target(struct cpufreq_policy *policy, { cpumask_t cpus_allowed; int cpu = policy->cpu; - struct icst525_vco vco; + struct icst_vco vco; struct cpufreq_freqs freqs; u_int cm_osc; @@ -156,7 +156,7 @@ static unsigned int integrator_get(unsigned int cpu) cpumask_t cpus_allowed; unsigned int current_freq; u_int cm_osc; - struct icst525_vco vco; + struct icst_vco vco; cpus_allowed = current->cpus_allowed; diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c index 0058c93..dfb961b 100644 --- a/arch/arm/mach-integrator/impd1.c +++ b/arch/arm/mach-integrator/impd1.c @@ -40,7 +40,7 @@ struct impd1_module { struct clk_lookup *clks[3]; }; -static const struct icst525_params impd1_vco_params = { +static const struct icst_params impd1_vco_params = { .ref = 24000, /* 24 MHz */ .vco_max = 200000, /* 200 MHz */ .vd_min = 12, @@ -49,7 +49,7 @@ static const struct icst525_params impd1_vco_params = { .rd_max = 120, }; -static void impd1_setvco(struct clk *clk, struct icst525_vco vco) +static void impd1_setvco(struct clk *clk, struct icst_vco vco) { struct impd1_module *impd1 = clk->data; int vconr = clk - impd1->vcos; diff --git a/arch/arm/mach-integrator/include/mach/clkdev.h b/arch/arm/mach-integrator/include/mach/clkdev.h index 9293e41..89ea938 100644 --- a/arch/arm/mach-integrator/include/mach/clkdev.h +++ b/arch/arm/mach-integrator/include/mach/clkdev.h @@ -2,14 +2,14 @@ #define __ASM_MACH_CLKDEV_H #include -#include +#include struct clk { unsigned long rate; struct module *owner; - const struct icst525_params *params; + const struct icst_params *params; void *data; - void (*setvco)(struct clk *, struct icst525_vco vco); + void (*setvco)(struct clk *, struct icst_vco vco); }; static inline int __clk_get(struct clk *clk) diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index c0161df..15bfbe2 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -268,7 +268,7 @@ static void __init intcp_init_irq(void) #define CM_LOCK IO_ADDRESS(INTEGRATOR_HDR_LOCK) #define CM_AUXOSC IO_ADDRESS(INTEGRATOR_HDR_BASE + 0x1c) -static const struct icst525_params cp_auxvco_params = { +static const struct icst_params cp_auxvco_params = { .ref = 24000, .vco_max = 320000, .vd_min = 8, @@ -277,7 +277,7 @@ static const struct icst525_params cp_auxvco_params = { .rd_max = 65, }; -static void cp_auxvco_set(struct clk *clk, struct icst525_vco vco) +static void cp_auxvco_set(struct clk *clk, struct icst_vco vco) { u32 val; diff --git a/arch/arm/mach-realview/clock.c b/arch/arm/mach-realview/clock.c index a704311..8364657 100644 --- a/arch/arm/mach-realview/clock.c +++ b/arch/arm/mach-realview/clock.c @@ -41,7 +41,7 @@ EXPORT_SYMBOL(clk_get_rate); long clk_round_rate(struct clk *clk, unsigned long rate) { - struct icst307_vco vco; + struct icst_vco vco; vco = icst307_khz_to_vco(clk->params, rate / 1000); return icst307_khz(clk->params, vco) * 1000; } @@ -52,7 +52,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate) int ret = -EIO; if (clk->setvco) { - struct icst307_vco vco; + struct icst_vco vco; vco = icst307_khz_to_vco(clk->params, rate / 1000); clk->rate = icst307_khz(clk->params, vco) * 1000; diff --git a/arch/arm/mach-realview/clock.h b/arch/arm/mach-realview/clock.h index ebbb0f0..fa64c85 100644 --- a/arch/arm/mach-realview/clock.h +++ b/arch/arm/mach-realview/clock.h @@ -8,12 +8,13 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#include + struct module; -struct icst307_params; struct clk { unsigned long rate; - const struct icst307_params *params; + const struct icst_params *params; void *data; - void (*setvco)(struct clk *, struct icst307_vco vco); + void (*setvco)(struct clk *, struct icst_vco vco); }; diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index 90bd4ef..ac50474 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c @@ -273,7 +273,7 @@ struct mmci_platform_data realview_mmc1_plat_data = { /* * Clock handling */ -static const struct icst307_params realview_oscvco_params = { +static const struct icst_params realview_oscvco_params = { .ref = 24000, .vco_max = 200000, .vd_min = 4 + 8, @@ -282,7 +282,7 @@ static const struct icst307_params realview_oscvco_params = { .rd_max = 127 + 2, }; -static void realview_oscvco_set(struct clk *clk, struct icst307_vco vco) +static void realview_oscvco_set(struct clk *clk, struct icst_vco vco) { void __iomem *sys_lock = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_LOCK_OFFSET; void __iomem *sys_osc; diff --git a/arch/arm/mach-versatile/clock.c b/arch/arm/mach-versatile/clock.c index c50a44e..530e16a 100644 --- a/arch/arm/mach-versatile/clock.c +++ b/arch/arm/mach-versatile/clock.c @@ -42,7 +42,7 @@ EXPORT_SYMBOL(clk_get_rate); long clk_round_rate(struct clk *clk, unsigned long rate) { - struct icst307_vco vco; + struct icst_vco vco; vco = icst307_khz_to_vco(clk->params, rate / 1000); return icst307_khz(clk->params, vco) * 1000; } @@ -53,7 +53,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate) int ret = -EIO; if (clk->setvco) { - struct icst307_vco vco; + struct icst_vco vco; vco = icst307_khz_to_vco(clk->params, rate / 1000); clk->rate = icst307_khz(clk->params, vco) * 1000; diff --git a/arch/arm/mach-versatile/clock.h b/arch/arm/mach-versatile/clock.h index 03468fdc..aed7e22 100644 --- a/arch/arm/mach-versatile/clock.h +++ b/arch/arm/mach-versatile/clock.h @@ -8,13 +8,14 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#include + struct module; -struct icst307_params; struct clk { unsigned long rate; - const struct icst307_params *params; + const struct icst_params *params; u32 oscoff; void *data; - void (*setvco)(struct clk *, struct icst307_vco vco); + void (*setvco)(struct clk *, struct icst_vco vco); }; diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index b77bc40..ded7134 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -379,7 +379,7 @@ static struct mmci_platform_data mmc0_plat_data = { /* * Clock handling */ -static const struct icst307_params versatile_oscvco_params = { +static const struct icst_params versatile_oscvco_params = { .ref = 24000, .vco_max = 200000, .vd_min = 4 + 8, @@ -388,7 +388,7 @@ static const struct icst307_params versatile_oscvco_params = { .rd_max = 127 + 2, }; -static void versatile_oscvco_set(struct clk *clk, struct icst307_vco vco) +static void versatile_oscvco_set(struct clk *clk, struct icst_vco vco) { void __iomem *sys = __io_address(VERSATILE_SYS_BASE); void __iomem *sys_lock = sys + VERSATILE_SYS_LOCK_OFFSET; -- cgit v0.10.2 From 643761ac43dfe4bea1195e966fc65a9403cdcb9f Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 16 Jan 2010 17:15:07 +0000 Subject: ARM: ICST: icst.*_ps_to_vco() functions are unused, remove them These functions were originally implemented for the CLCD driver before we had clk API support. Since the CLCD driver does not use these anymore, we can remove them. Signed-off-by: Russell King diff --git a/arch/arm/common/icst307.c b/arch/arm/common/icst307.c index 2eebd96..f78f5b5 100644 --- a/arch/arm/common/icst307.c +++ b/arch/arm/common/icst307.c @@ -95,67 +95,3 @@ icst307_khz_to_vco(const struct icst_params *p, unsigned long freq) } EXPORT_SYMBOL(icst307_khz_to_vco); - -struct icst_vco -icst307_ps_to_vco(const struct icst_params *p, unsigned long period) -{ - struct icst_vco vco = { .s = 1, .v = p->vd_max, .r = p->rd_max }; - unsigned long f, ps; - unsigned int i = 0, rd, best = (unsigned int)-1; - - ps = 1000000000UL / p->vco_max; - - /* - * First, find the PLL output divisor such - * that the PLL output is within spec. - */ - do { - f = period / s2div[idx2s[i]]; - - /* - * f must be between 6MHz and 200MHz (3.3 or 5V) - */ - if (f >= ps && f < 1000000000UL / 6000 + 1) - break; - } while (i < ARRAY_SIZE(idx2s)); - - if (i >= ARRAY_SIZE(idx2s)) - return vco; - - vco.s = idx2s[i]; - - ps = 500000000UL / p->ref; - - /* - * Now find the closest divisor combination - * which gives a PLL output of 'f'. - */ - for (rd = p->rd_min; rd <= p->rd_max; rd++) { - unsigned long f_in_div, f_pll; - unsigned int vd; - int f_diff; - - f_in_div = ps * rd; - - vd = (f_in_div + f / 2) / f; - if (vd < p->vd_min || vd > p->vd_max) - continue; - - f_pll = (f_in_div + vd / 2) / vd; - f_diff = f_pll - f; - if (f_diff < 0) - f_diff = -f_diff; - - if ((unsigned)f_diff < best) { - vco.v = vd - 8; - vco.r = rd - 2; - if (f_diff == 0) - break; - best = f_diff; - } - } - - return vco; -} - -EXPORT_SYMBOL(icst307_ps_to_vco); diff --git a/arch/arm/common/icst525.c b/arch/arm/common/icst525.c index fd5c2e7..eadf983 100644 --- a/arch/arm/common/icst525.c +++ b/arch/arm/common/icst525.c @@ -93,68 +93,3 @@ icst525_khz_to_vco(const struct icst_params *p, unsigned long freq) } EXPORT_SYMBOL(icst525_khz_to_vco); - -struct icst_vco -icst525_ps_to_vco(const struct icst_params *p, unsigned long period) -{ - struct icst_vco vco = { .s = 1, .v = p->vd_max, .r = p->rd_max }; - unsigned long f, ps; - unsigned int i = 0, rd, best = (unsigned int)-1; - - ps = 1000000000UL / p->vco_max; - - /* - * First, find the PLL output divisor such - * that the PLL output is within spec. - */ - do { - f = period / s2div[idx2s[i]]; - - /* - * f must be between 10MHz and - * 320MHz (5V) or 200MHz (3V) - */ - if (f >= ps && f < 100000) - break; - } while (i < ARRAY_SIZE(idx2s)); - - if (i >= ARRAY_SIZE(idx2s)) - return vco; - - vco.s = idx2s[i]; - - ps = 500000000UL / p->ref; - - /* - * Now find the closest divisor combination - * which gives a PLL output of 'f'. - */ - for (rd = p->rd_min; rd <= p->rd_max; rd++) { - unsigned long f_in_div, f_pll; - unsigned int vd; - int f_diff; - - f_in_div = ps * rd; - - vd = (f_in_div + f / 2) / f; - if (vd < p->vd_min || vd > p->vd_max) - continue; - - f_pll = (f_in_div + vd / 2) / vd; - f_diff = f_pll - f; - if (f_diff < 0) - f_diff = -f_diff; - - if ((unsigned)f_diff < best) { - vco.v = vd - 8; - vco.r = rd - 2; - if (f_diff == 0) - break; - best = f_diff; - } - } - - return vco; -} - -EXPORT_SYMBOL(icst525_ps_to_vco); diff --git a/arch/arm/include/asm/hardware/icst307.h b/arch/arm/include/asm/hardware/icst307.h index 85932e9..8d0820a 100644 --- a/arch/arm/include/asm/hardware/icst307.h +++ b/arch/arm/include/asm/hardware/icst307.h @@ -20,6 +20,5 @@ unsigned long icst307_khz(const struct icst_params *p, struct icst_vco vco); struct icst_vco icst307_khz_to_vco(const struct icst_params *p, unsigned long freq); -struct icst_vco icst307_ps_to_vco(const struct icst_params *p, unsigned long period); #endif diff --git a/arch/arm/include/asm/hardware/icst525.h b/arch/arm/include/asm/hardware/icst525.h index 170deb2..42a274e 100644 --- a/arch/arm/include/asm/hardware/icst525.h +++ b/arch/arm/include/asm/hardware/icst525.h @@ -18,6 +18,5 @@ unsigned long icst525_khz(const struct icst_params *p, struct icst_vco vco); struct icst_vco icst525_khz_to_vco(const struct icst_params *p, unsigned long freq); -struct icst_vco icst525_ps_to_vco(const struct icst_params *p, unsigned long period); #endif -- cgit v0.10.2 From 4de2edbd15ff70c77e1d018611d06f7801fc2b72 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 16 Jan 2010 18:08:47 +0000 Subject: ARM: ICST: provide definitions for max/min VCO frequencies Signed-off-by: Russell King diff --git a/arch/arm/common/icst307.c b/arch/arm/common/icst307.c index f78f5b5..f6063c9 100644 --- a/arch/arm/common/icst307.c +++ b/arch/arm/common/icst307.c @@ -53,7 +53,7 @@ icst307_khz_to_vco(const struct icst_params *p, unsigned long freq) /* * f must be between 6MHz and 200MHz (3.3 or 5V) */ - if (f > 6000 && f <= p->vco_max) + if (f > ICST307_VCO_MIN && f <= p->vco_max) break; } while (i < ARRAY_SIZE(idx2s)); diff --git a/arch/arm/common/icst525.c b/arch/arm/common/icst525.c index eadf983..34dc2e1 100644 --- a/arch/arm/common/icst525.c +++ b/arch/arm/common/icst525.c @@ -51,7 +51,7 @@ icst525_khz_to_vco(const struct icst_params *p, unsigned long freq) * f must be between 10MHz and * 320MHz (5V) or 200MHz (3V) */ - if (f > 10000 && f <= p->vco_max) + if (f > ICST525_VCO_MIN && f <= p->vco_max) break; } while (i < ARRAY_SIZE(idx2s)); diff --git a/arch/arm/include/asm/hardware/icst307.h b/arch/arm/include/asm/hardware/icst307.h index 8d0820a..0c4e37e 100644 --- a/arch/arm/include/asm/hardware/icst307.h +++ b/arch/arm/include/asm/hardware/icst307.h @@ -21,4 +21,11 @@ unsigned long icst307_khz(const struct icst_params *p, struct icst_vco vco); struct icst_vco icst307_khz_to_vco(const struct icst_params *p, unsigned long freq); +/* + * ICST307 VCO frequency must be between 6MHz and 200MHz (3.3 or 5V). + * This frequency is pre-output divider. + */ +#define ICST307_VCO_MIN 6000 +#define ICST307_VCO_MAX 200000 + #endif diff --git a/arch/arm/include/asm/hardware/icst525.h b/arch/arm/include/asm/hardware/icst525.h index 42a274e..3b72c13 100644 --- a/arch/arm/include/asm/hardware/icst525.h +++ b/arch/arm/include/asm/hardware/icst525.h @@ -19,4 +19,12 @@ unsigned long icst525_khz(const struct icst_params *p, struct icst_vco vco); struct icst_vco icst525_khz_to_vco(const struct icst_params *p, unsigned long freq); +/* + * ICST525 VCO frequency must be between 10MHz and 200MHz (3V) or 320MHz (5V). + * This frequency is pre-output divider. + */ +#define ICST525_VCO_MIN 10000 +#define ICST525_VCO_MAX_3V 200000 +#define ICST525_VCO_MAX_5V 320000 + #endif diff --git a/arch/arm/mach-integrator/cpu.c b/arch/arm/mach-integrator/cpu.c index c4e5deb..1671b4a 100644 --- a/arch/arm/mach-integrator/cpu.c +++ b/arch/arm/mach-integrator/cpu.c @@ -33,7 +33,7 @@ static struct cpufreq_driver integrator_driver; static const struct icst_params lclk_params = { .ref = 24000, - .vco_max = 320000, + .vco_max = ICST525_VCO_MAX_5V, .vd_min = 8, .vd_max = 132, .rd_min = 24, @@ -42,7 +42,7 @@ static const struct icst_params lclk_params = { static const struct icst_params cclk_params = { .ref = 24000, - .vco_max = 320000, + .vco_max = ICST525_VCO_MAX_5V, .vd_min = 12, .vd_max = 160, .rd_min = 24, diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c index dfb961b..5aca7eb 100644 --- a/arch/arm/mach-integrator/impd1.c +++ b/arch/arm/mach-integrator/impd1.c @@ -42,7 +42,7 @@ struct impd1_module { static const struct icst_params impd1_vco_params = { .ref = 24000, /* 24 MHz */ - .vco_max = 200000, /* 200 MHz */ + .vco_max = ICST525_VCO_MAX_3V, .vd_min = 12, .vd_max = 519, .rd_min = 3, diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 15bfbe2..27f9510 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -270,7 +270,7 @@ static void __init intcp_init_irq(void) static const struct icst_params cp_auxvco_params = { .ref = 24000, - .vco_max = 320000, + .vco_max = ICST525_VCO_MAX_5V, .vd_min = 8, .vd_max = 263, .rd_min = 3, diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index ac50474..5a850f0 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c @@ -275,7 +275,7 @@ struct mmci_platform_data realview_mmc1_plat_data = { */ static const struct icst_params realview_oscvco_params = { .ref = 24000, - .vco_max = 200000, + .vco_max = ICST307_VCO_MAX, .vd_min = 4 + 8, .vd_max = 511 + 8, .rd_min = 1 + 2, diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index ded7134..f8ed561 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -381,7 +381,7 @@ static struct mmci_platform_data mmc0_plat_data = { */ static const struct icst_params versatile_oscvco_params = { .ref = 24000, - .vco_max = 200000, + .vco_max = ICST307_VCO_MAX, .vd_min = 4 + 8, .vd_max = 511 + 8, .rd_min = 1 + 2, -- cgit v0.10.2 From 64fceb1dcd1aa6a9f2e53cf8830b38bb007b375b Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 16 Jan 2010 17:28:44 +0000 Subject: ARM: ICST: use Hz instead of kHz This makes the ICST support fit more nicely with the clk API, eliminating the need to *1000 and /1000 in places. Signed-off-by: Russell King diff --git a/arch/arm/common/icst307.c b/arch/arm/common/icst307.c index f6063c9..66c69e5 100644 --- a/arch/arm/common/icst307.c +++ b/arch/arm/common/icst307.c @@ -24,12 +24,12 @@ */ static unsigned char s2div[8] = { 10, 2, 8, 4, 5, 7, 3, 6 }; -unsigned long icst307_khz(const struct icst_params *p, struct icst_vco vco) +unsigned long icst307_hz(const struct icst_params *p, struct icst_vco vco) { return p->ref * 2 * (vco.v + 8) / ((vco.r + 2) * s2div[vco.s]); } -EXPORT_SYMBOL(icst307_khz); +EXPORT_SYMBOL(icst307_hz); /* * Ascending divisor S values. @@ -37,7 +37,7 @@ EXPORT_SYMBOL(icst307_khz); static unsigned char idx2s[8] = { 1, 6, 3, 4, 7, 5, 2, 0 }; struct icst_vco -icst307_khz_to_vco(const struct icst_params *p, unsigned long freq) +icst307_hz_to_vco(const struct icst_params *p, unsigned long freq) { struct icst_vco vco = { .s = 1, .v = p->vd_max, .r = p->rd_max }; unsigned long f; @@ -94,4 +94,4 @@ icst307_khz_to_vco(const struct icst_params *p, unsigned long freq) return vco; } -EXPORT_SYMBOL(icst307_khz_to_vco); +EXPORT_SYMBOL(icst307_hz_to_vco); diff --git a/arch/arm/common/icst525.c b/arch/arm/common/icst525.c index 34dc2e1..c1d22b7 100644 --- a/arch/arm/common/icst525.c +++ b/arch/arm/common/icst525.c @@ -21,12 +21,12 @@ */ static unsigned char s2div[8] = { 10, 2, 8, 4, 5, 7, 9, 6 }; -unsigned long icst525_khz(const struct icst_params *p, struct icst_vco vco) +unsigned long icst525_hz(const struct icst_params *p, struct icst_vco vco) { return p->ref * 2 * (vco.v + 8) / ((vco.r + 2) * s2div[vco.s]); } -EXPORT_SYMBOL(icst525_khz); +EXPORT_SYMBOL(icst525_hz); /* * Ascending divisor S values. @@ -34,7 +34,7 @@ EXPORT_SYMBOL(icst525_khz); static unsigned char idx2s[] = { 1, 3, 4, 7, 5, 2, 6, 0 }; struct icst_vco -icst525_khz_to_vco(const struct icst_params *p, unsigned long freq) +icst525_hz_to_vco(const struct icst_params *p, unsigned long freq) { struct icst_vco vco = { .s = 1, .v = p->vd_max, .r = p->rd_max }; unsigned long f; @@ -92,4 +92,4 @@ icst525_khz_to_vco(const struct icst_params *p, unsigned long freq) return vco; } -EXPORT_SYMBOL(icst525_khz_to_vco); +EXPORT_SYMBOL(icst525_hz_to_vco); diff --git a/arch/arm/include/asm/hardware/icst307.h b/arch/arm/include/asm/hardware/icst307.h index 0c4e37e..0f09618 100644 --- a/arch/arm/include/asm/hardware/icst307.h +++ b/arch/arm/include/asm/hardware/icst307.h @@ -18,14 +18,14 @@ #include -unsigned long icst307_khz(const struct icst_params *p, struct icst_vco vco); -struct icst_vco icst307_khz_to_vco(const struct icst_params *p, unsigned long freq); +unsigned long icst307_hz(const struct icst_params *p, struct icst_vco vco); +struct icst_vco icst307_hz_to_vco(const struct icst_params *p, unsigned long freq); /* * ICST307 VCO frequency must be between 6MHz and 200MHz (3.3 or 5V). * This frequency is pre-output divider. */ -#define ICST307_VCO_MIN 6000 -#define ICST307_VCO_MAX 200000 +#define ICST307_VCO_MIN 6000000 +#define ICST307_VCO_MAX 200000000 #endif diff --git a/arch/arm/include/asm/hardware/icst525.h b/arch/arm/include/asm/hardware/icst525.h index 3b72c13..1000a60 100644 --- a/arch/arm/include/asm/hardware/icst525.h +++ b/arch/arm/include/asm/hardware/icst525.h @@ -16,15 +16,15 @@ #include -unsigned long icst525_khz(const struct icst_params *p, struct icst_vco vco); -struct icst_vco icst525_khz_to_vco(const struct icst_params *p, unsigned long freq); +unsigned long icst525_hz(const struct icst_params *p, struct icst_vco vco); +struct icst_vco icst525_hz_to_vco(const struct icst_params *p, unsigned long freq); /* * ICST525 VCO frequency must be between 10MHz and 200MHz (3V) or 320MHz (5V). * This frequency is pre-output divider. */ -#define ICST525_VCO_MIN 10000 -#define ICST525_VCO_MAX_3V 200000 -#define ICST525_VCO_MAX_5V 320000 +#define ICST525_VCO_MIN 10000000 +#define ICST525_VCO_MAX_3V 200000000 +#define ICST525_VCO_MAX_5V 320000000 #endif diff --git a/arch/arm/mach-integrator/clock.c b/arch/arm/mach-integrator/clock.c index bb70b64..a4f80d3 100644 --- a/arch/arm/mach-integrator/clock.c +++ b/arch/arm/mach-integrator/clock.c @@ -38,8 +38,8 @@ EXPORT_SYMBOL(clk_get_rate); long clk_round_rate(struct clk *clk, unsigned long rate) { struct icst_vco vco; - vco = icst525_khz_to_vco(clk->params, rate / 1000); - return icst525_khz(clk->params, vco) * 1000; + vco = icst525_hz_to_vco(clk->params, rate); + return icst525_hz(clk->params, vco); } EXPORT_SYMBOL(clk_round_rate); @@ -50,8 +50,8 @@ int clk_set_rate(struct clk *clk, unsigned long rate) if (clk->setvco) { struct icst_vco vco; - vco = icst525_khz_to_vco(clk->params, rate / 1000); - clk->rate = icst525_khz(clk->params, vco) * 1000; + vco = icst525_hz_to_vco(clk->params, rate); + clk->rate = icst525_hz(clk->params, vco); clk->setvco(clk, vco); ret = 0; } diff --git a/arch/arm/mach-integrator/cpu.c b/arch/arm/mach-integrator/cpu.c index 1671b4a..3ebb785 100644 --- a/arch/arm/mach-integrator/cpu.c +++ b/arch/arm/mach-integrator/cpu.c @@ -32,7 +32,7 @@ static struct cpufreq_driver integrator_driver; #define CM_LOCK IO_ADDRESS(INTEGRATOR_HDR_LOCK) static const struct icst_params lclk_params = { - .ref = 24000, + .ref = 24000000, .vco_max = ICST525_VCO_MAX_5V, .vd_min = 8, .vd_max = 132, @@ -41,7 +41,7 @@ static const struct icst_params lclk_params = { }; static const struct icst_params cclk_params = { - .ref = 24000, + .ref = 24000000, .vco_max = ICST525_VCO_MAX_5V, .vd_min = 12, .vd_max = 160, @@ -60,11 +60,11 @@ static int integrator_verify_policy(struct cpufreq_policy *policy) policy->cpuinfo.min_freq, policy->cpuinfo.max_freq); - vco = icst525_khz_to_vco(&cclk_params, policy->max); - policy->max = icst525_khz(&cclk_params, vco); + vco = icst525_hz_to_vco(&cclk_params, policy->max * 1000); + policy->max = icst525_hz(&cclk_params, vco) / 1000; - vco = icst525_khz_to_vco(&cclk_params, policy->min); - policy->min = icst525_khz(&cclk_params, vco); + vco = icst525_hz_to_vco(&cclk_params, policy->min * 1000); + policy->min = icst525_hz(&cclk_params, vco) / 1000; cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, @@ -106,17 +106,17 @@ static int integrator_set_target(struct cpufreq_policy *policy, } vco.v = cm_osc & 255; vco.r = 22; - freqs.old = icst525_khz(&cclk_params, vco); + freqs.old = icst525_hz(&cclk_params, vco) / 1000; - /* icst525_khz_to_vco rounds down -- so we need the next + /* icst525_hz_to_vco rounds down -- so we need the next * larger freq in case of CPUFREQ_RELATION_L. */ if (relation == CPUFREQ_RELATION_L) target_freq += 999; if (target_freq > policy->max) target_freq = policy->max; - vco = icst525_khz_to_vco(&cclk_params, target_freq); - freqs.new = icst525_khz(&cclk_params, vco); + vco = icst525_hz_to_vco(&cclk_params, target_freq * 1000); + freqs.new = icst525_hz(&cclk_params, vco) / 1000; freqs.cpu = policy->cpu; @@ -174,7 +174,7 @@ static unsigned int integrator_get(unsigned int cpu) vco.v = cm_osc & 255; vco.r = 22; - current_freq = icst525_khz(&cclk_params, vco); /* current freq */ + current_freq = icst525_hz(&cclk_params, vco) / 1000; /* current freq */ set_cpus_allowed(current, cpus_allowed); diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c index 5aca7eb..ecce3eb 100644 --- a/arch/arm/mach-integrator/impd1.c +++ b/arch/arm/mach-integrator/impd1.c @@ -41,7 +41,7 @@ struct impd1_module { }; static const struct icst_params impd1_vco_params = { - .ref = 24000, /* 24 MHz */ + .ref = 24000000, /* 24 MHz */ .vco_max = ICST525_VCO_MAX_3V, .vd_min = 12, .vd_max = 519, @@ -73,8 +73,8 @@ static void impd1_setvco(struct clk *clk, struct icst_vco vco) vco.r = (val >> 9) & 0x7f; vco.s = (val >> 16) & 7; - pr_debug("IM-PD1: VCO%d clock is %ld kHz\n", - vconr, icst525_khz(&impd1_vco_params, vco)); + pr_debug("IM-PD1: VCO%d clock is %ld Hz\n", + vconr, icst525_hz(&impd1_vco_params, vco)); #endif } diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 27f9510..335af99 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -269,7 +269,7 @@ static void __init intcp_init_irq(void) #define CM_AUXOSC IO_ADDRESS(INTEGRATOR_HDR_BASE + 0x1c) static const struct icst_params cp_auxvco_params = { - .ref = 24000, + .ref = 24000000, .vco_max = ICST525_VCO_MAX_5V, .vd_min = 8, .vd_max = 263, diff --git a/arch/arm/mach-realview/clock.c b/arch/arm/mach-realview/clock.c index 8364657..2ba0667 100644 --- a/arch/arm/mach-realview/clock.c +++ b/arch/arm/mach-realview/clock.c @@ -42,8 +42,8 @@ EXPORT_SYMBOL(clk_get_rate); long clk_round_rate(struct clk *clk, unsigned long rate) { struct icst_vco vco; - vco = icst307_khz_to_vco(clk->params, rate / 1000); - return icst307_khz(clk->params, vco) * 1000; + vco = icst307_hz_to_vco(clk->params, rate); + return icst307_hz(clk->params, vco); } EXPORT_SYMBOL(clk_round_rate); @@ -54,8 +54,8 @@ int clk_set_rate(struct clk *clk, unsigned long rate) if (clk->setvco) { struct icst_vco vco; - vco = icst307_khz_to_vco(clk->params, rate / 1000); - clk->rate = icst307_khz(clk->params, vco) * 1000; + vco = icst307_hz_to_vco(clk->params, rate); + clk->rate = icst307_hz(clk->params, vco); clk->setvco(clk, vco); ret = 0; } diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index 5a850f0..02d4837 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c @@ -274,7 +274,7 @@ struct mmci_platform_data realview_mmc1_plat_data = { * Clock handling */ static const struct icst_params realview_oscvco_params = { - .ref = 24000, + .ref = 24000000, .vco_max = ICST307_VCO_MAX, .vd_min = 4 + 8, .vd_max = 511 + 8, diff --git a/arch/arm/mach-versatile/clock.c b/arch/arm/mach-versatile/clock.c index 530e16a..82753be 100644 --- a/arch/arm/mach-versatile/clock.c +++ b/arch/arm/mach-versatile/clock.c @@ -43,8 +43,8 @@ EXPORT_SYMBOL(clk_get_rate); long clk_round_rate(struct clk *clk, unsigned long rate) { struct icst_vco vco; - vco = icst307_khz_to_vco(clk->params, rate / 1000); - return icst307_khz(clk->params, vco) * 1000; + vco = icst307_hz_to_vco(clk->params, rate); + return icst307_hz(clk->params, vco); } EXPORT_SYMBOL(clk_round_rate); @@ -55,8 +55,8 @@ int clk_set_rate(struct clk *clk, unsigned long rate) if (clk->setvco) { struct icst_vco vco; - vco = icst307_khz_to_vco(clk->params, rate / 1000); - clk->rate = icst307_khz(clk->params, vco) * 1000; + vco = icst307_hz_to_vco(clk->params, rate); + clk->rate = icst307_hz(clk->params, vco); clk->setvco(clk, vco); ret = 0; } diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index f8ed561..ff5d24f 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -380,7 +380,7 @@ static struct mmci_platform_data mmc0_plat_data = { * Clock handling */ static const struct icst_params versatile_oscvco_params = { - .ref = 24000, + .ref = 24000000, .vco_max = ICST307_VCO_MAX, .vd_min = 4 + 8, .vd_max = 511 + 8, -- cgit v0.10.2 From e73a46a3d3df22b379d8adcb59999eafea1d60d5 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 16 Jan 2010 19:49:39 +0000 Subject: ARM: ICST: move minimum VCO frequency to icst_params Signed-off-by: Russell King diff --git a/arch/arm/common/icst307.c b/arch/arm/common/icst307.c index 66c69e5..312485f 100644 --- a/arch/arm/common/icst307.c +++ b/arch/arm/common/icst307.c @@ -53,7 +53,7 @@ icst307_hz_to_vco(const struct icst_params *p, unsigned long freq) /* * f must be between 6MHz and 200MHz (3.3 or 5V) */ - if (f > ICST307_VCO_MIN && f <= p->vco_max) + if (f > p->vco_min && f <= p->vco_max) break; } while (i < ARRAY_SIZE(idx2s)); diff --git a/arch/arm/common/icst525.c b/arch/arm/common/icst525.c index c1d22b7..da58965 100644 --- a/arch/arm/common/icst525.c +++ b/arch/arm/common/icst525.c @@ -51,7 +51,7 @@ icst525_hz_to_vco(const struct icst_params *p, unsigned long freq) * f must be between 10MHz and * 320MHz (5V) or 200MHz (3V) */ - if (f > ICST525_VCO_MIN && f <= p->vco_max) + if (f > p->vco_min && f <= p->vco_max) break; } while (i < ARRAY_SIZE(idx2s)); diff --git a/arch/arm/include/asm/hardware/icst.h b/arch/arm/include/asm/hardware/icst.h index 65b1edd..6707c6a 100644 --- a/arch/arm/include/asm/hardware/icst.h +++ b/arch/arm/include/asm/hardware/icst.h @@ -17,6 +17,7 @@ struct icst_params { unsigned long ref; unsigned long vco_max; /* inclusive */ + unsigned long vco_min; /* exclusive */ unsigned short vd_min; /* inclusive */ unsigned short vd_max; /* inclusive */ unsigned char rd_min; /* inclusive */ diff --git a/arch/arm/mach-integrator/cpu.c b/arch/arm/mach-integrator/cpu.c index 3ebb785..569306b 100644 --- a/arch/arm/mach-integrator/cpu.c +++ b/arch/arm/mach-integrator/cpu.c @@ -34,6 +34,7 @@ static struct cpufreq_driver integrator_driver; static const struct icst_params lclk_params = { .ref = 24000000, .vco_max = ICST525_VCO_MAX_5V, + .vco_min = ICST525_VCO_MIN, .vd_min = 8, .vd_max = 132, .rd_min = 24, @@ -43,6 +44,7 @@ static const struct icst_params lclk_params = { static const struct icst_params cclk_params = { .ref = 24000000, .vco_max = ICST525_VCO_MAX_5V, + .vco_min = ICST525_VCO_MIN, .vd_min = 12, .vd_max = 160, .rd_min = 24, diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c index ecce3eb..036cfb4 100644 --- a/arch/arm/mach-integrator/impd1.c +++ b/arch/arm/mach-integrator/impd1.c @@ -43,6 +43,7 @@ struct impd1_module { static const struct icst_params impd1_vco_params = { .ref = 24000000, /* 24 MHz */ .vco_max = ICST525_VCO_MAX_3V, + .vco_min = ICST525_VCO_MIN, .vd_min = 12, .vd_max = 519, .rd_min = 3, diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 335af99..34c120a 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -271,6 +271,7 @@ static void __init intcp_init_irq(void) static const struct icst_params cp_auxvco_params = { .ref = 24000000, .vco_max = ICST525_VCO_MAX_5V, + .vco_min = ICST525_VCO_MIN, .vd_min = 8, .vd_max = 263, .rd_min = 3, diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index 02d4837..3ac4413 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c @@ -276,6 +276,7 @@ struct mmci_platform_data realview_mmc1_plat_data = { static const struct icst_params realview_oscvco_params = { .ref = 24000000, .vco_max = ICST307_VCO_MAX, + .vco_min = ICST307_VCO_MIN, .vd_min = 4 + 8, .vd_max = 511 + 8, .rd_min = 1 + 2, diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index ff5d24f..c4bf680 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -382,6 +382,7 @@ static struct mmci_platform_data mmc0_plat_data = { static const struct icst_params versatile_oscvco_params = { .ref = 24000000, .vco_max = ICST307_VCO_MAX, + .vco_min = ICST307_VCO_MIN, .vd_min = 4 + 8, .vd_max = 511 + 8, .rd_min = 1 + 2, -- cgit v0.10.2 From 232eaf7f268f765b52170bec42bfa0c5825aa239 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 16 Jan 2010 19:46:19 +0000 Subject: ARM: ICST: indirect s2div and idx2s arrays via icst_params Signed-off-by: Russell King diff --git a/arch/arm/common/icst307.c b/arch/arm/common/icst307.c index 312485f..8332c07 100644 --- a/arch/arm/common/icst307.c +++ b/arch/arm/common/icst307.c @@ -22,11 +22,13 @@ /* * Divisors for each OD setting. */ -static unsigned char s2div[8] = { 10, 2, 8, 4, 5, 7, 3, 6 }; +const unsigned char icst307_s2div[8] = { 10, 2, 8, 4, 5, 7, 3, 6 }; + +EXPORT_SYMBOL(icst307_s2div); unsigned long icst307_hz(const struct icst_params *p, struct icst_vco vco) { - return p->ref * 2 * (vco.v + 8) / ((vco.r + 2) * s2div[vco.s]); + return p->ref * 2 * (vco.v + 8) / ((vco.r + 2) * p->s2div[vco.s]); } EXPORT_SYMBOL(icst307_hz); @@ -34,7 +36,9 @@ EXPORT_SYMBOL(icst307_hz); /* * Ascending divisor S values. */ -static unsigned char idx2s[8] = { 1, 6, 3, 4, 7, 5, 2, 0 }; +const unsigned char icst307_idx2s[8] = { 1, 6, 3, 4, 7, 5, 2, 0 }; + +EXPORT_SYMBOL(icst307_idx2s); struct icst_vco icst307_hz_to_vco(const struct icst_params *p, unsigned long freq) @@ -48,19 +52,19 @@ icst307_hz_to_vco(const struct icst_params *p, unsigned long freq) * that the PLL output is within spec. */ do { - f = freq * s2div[idx2s[i]]; + f = freq * p->s2div[p->idx2s[i]]; /* * f must be between 6MHz and 200MHz (3.3 or 5V) */ if (f > p->vco_min && f <= p->vco_max) break; - } while (i < ARRAY_SIZE(idx2s)); + } while (i < 8); - if (i >= ARRAY_SIZE(idx2s)) + if (i >= 8) return vco; - vco.s = idx2s[i]; + vco.s = p->idx2s[i]; /* * Now find the closest divisor combination diff --git a/arch/arm/common/icst525.c b/arch/arm/common/icst525.c index da58965..4180255 100644 --- a/arch/arm/common/icst525.c +++ b/arch/arm/common/icst525.c @@ -19,11 +19,13 @@ /* * Divisors for each OD setting. */ -static unsigned char s2div[8] = { 10, 2, 8, 4, 5, 7, 9, 6 }; +const unsigned char icst525_s2div[8] = { 10, 2, 8, 4, 5, 7, 9, 6 }; + +EXPORT_SYMBOL(icst525_s2div); unsigned long icst525_hz(const struct icst_params *p, struct icst_vco vco) { - return p->ref * 2 * (vco.v + 8) / ((vco.r + 2) * s2div[vco.s]); + return p->ref * 2 * (vco.v + 8) / ((vco.r + 2) * p->s2div[vco.s]); } EXPORT_SYMBOL(icst525_hz); @@ -31,7 +33,9 @@ EXPORT_SYMBOL(icst525_hz); /* * Ascending divisor S values. */ -static unsigned char idx2s[] = { 1, 3, 4, 7, 5, 2, 6, 0 }; +const unsigned char icst525_idx2s[8] = { 1, 3, 4, 7, 5, 2, 6, 0 }; + +EXPORT_SYMBOL(icst525_idx2s); struct icst_vco icst525_hz_to_vco(const struct icst_params *p, unsigned long freq) @@ -45,7 +49,7 @@ icst525_hz_to_vco(const struct icst_params *p, unsigned long freq) * that the PLL output is within spec. */ do { - f = freq * s2div[idx2s[i]]; + f = freq * p->s2div[p->idx2s[i]]; /* * f must be between 10MHz and @@ -53,12 +57,12 @@ icst525_hz_to_vco(const struct icst_params *p, unsigned long freq) */ if (f > p->vco_min && f <= p->vco_max) break; - } while (i < ARRAY_SIZE(idx2s)); + } while (i < 8); - if (i >= ARRAY_SIZE(idx2s)) + if (i >= 8) return vco; - vco.s = idx2s[i]; + vco.s = p->idx2s[i]; /* * Now find the closest divisor combination diff --git a/arch/arm/include/asm/hardware/icst.h b/arch/arm/include/asm/hardware/icst.h index 6707c6a..4d40368 100644 --- a/arch/arm/include/asm/hardware/icst.h +++ b/arch/arm/include/asm/hardware/icst.h @@ -22,6 +22,8 @@ struct icst_params { unsigned short vd_max; /* inclusive */ unsigned char rd_min; /* inclusive */ unsigned char rd_max; /* inclusive */ + const unsigned char *s2div; /* chip specific s2div array */ + const unsigned char *idx2s; /* chip specific idx2s array */ }; struct icst_vco { diff --git a/arch/arm/include/asm/hardware/icst307.h b/arch/arm/include/asm/hardware/icst307.h index 0f09618..d76fc6e 100644 --- a/arch/arm/include/asm/hardware/icst307.h +++ b/arch/arm/include/asm/hardware/icst307.h @@ -28,4 +28,7 @@ struct icst_vco icst307_hz_to_vco(const struct icst_params *p, unsigned long fre #define ICST307_VCO_MIN 6000000 #define ICST307_VCO_MAX 200000000 +extern const unsigned char icst307_s2div[]; +extern const unsigned char icst307_idx2s[]; + #endif diff --git a/arch/arm/include/asm/hardware/icst525.h b/arch/arm/include/asm/hardware/icst525.h index 1000a60..2f9b953 100644 --- a/arch/arm/include/asm/hardware/icst525.h +++ b/arch/arm/include/asm/hardware/icst525.h @@ -27,4 +27,7 @@ struct icst_vco icst525_hz_to_vco(const struct icst_params *p, unsigned long fre #define ICST525_VCO_MAX_3V 200000000 #define ICST525_VCO_MAX_5V 320000000 +extern const unsigned char icst525_s2div[]; +extern const unsigned char icst525_idx2s[]; + #endif diff --git a/arch/arm/mach-integrator/cpu.c b/arch/arm/mach-integrator/cpu.c index 569306b..9481c54 100644 --- a/arch/arm/mach-integrator/cpu.c +++ b/arch/arm/mach-integrator/cpu.c @@ -39,6 +39,8 @@ static const struct icst_params lclk_params = { .vd_max = 132, .rd_min = 24, .rd_max = 24, + .s2div = icst525_s2div, + .idx2s = icst525_idx2s, }; static const struct icst_params cclk_params = { @@ -49,6 +51,8 @@ static const struct icst_params cclk_params = { .vd_max = 160, .rd_min = 24, .rd_max = 24, + .s2div = icst525_s2div, + .idx2s = icst525_idx2s, }; /* diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c index 036cfb4..e24cfc3 100644 --- a/arch/arm/mach-integrator/impd1.c +++ b/arch/arm/mach-integrator/impd1.c @@ -48,6 +48,8 @@ static const struct icst_params impd1_vco_params = { .vd_max = 519, .rd_min = 3, .rd_max = 120, + .s2div = icst525_s2div, + .idx2s = icst525_idx2s, }; static void impd1_setvco(struct clk *clk, struct icst_vco vco) diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 34c120a..9997d1f 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -276,6 +276,8 @@ static const struct icst_params cp_auxvco_params = { .vd_max = 263, .rd_min = 3, .rd_max = 65, + .s2div = icst525_s2div, + .idx2s = icst525_idx2s, }; static void cp_auxvco_set(struct clk *clk, struct icst_vco vco) diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index 3ac4413..26d44ca 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c @@ -281,6 +281,8 @@ static const struct icst_params realview_oscvco_params = { .vd_max = 511 + 8, .rd_min = 1 + 2, .rd_max = 127 + 2, + .s2div = icst307_s2div, + .idx2s = icst307_idx2s, }; static void realview_oscvco_set(struct clk *clk, struct icst_vco vco) diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index c4bf680..51d7aeb 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -387,6 +387,8 @@ static const struct icst_params versatile_oscvco_params = { .vd_max = 511 + 8, .rd_min = 1 + 2, .rd_max = 127 + 2, + .s2div = icst307_s2div, + .idx2s = icst307_idx2s, }; static void versatile_oscvco_set(struct clk *clk, struct icst_vco vco) -- cgit v0.10.2 From c5a0adb51002e51a4254cb7f0ab7190d41d8b930 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 16 Jan 2010 20:16:10 +0000 Subject: ARM: ICST: kill duplicate icst code The only difference between ICST307 and ICST525 are the two arrays for calculating the S parameter; the code is now identical. Merge the two files and kill the duplicated code. Signed-off-by: Russell King diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 86fecec..3c436fd 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -240,7 +240,7 @@ config ARCH_INTEGRATOR select ARCH_HAS_CPUFREQ select HAVE_CLK select COMMON_CLKDEV - select ICST525 + select ICST select GENERIC_TIME select GENERIC_CLOCKEVENTS help @@ -251,7 +251,7 @@ config ARCH_REALVIEW select ARM_AMBA select HAVE_CLK select COMMON_CLKDEV - select ICST307 + select ICST select GENERIC_TIME select GENERIC_CLOCKEVENTS select ARCH_WANT_OPTIONAL_GPIOLIB @@ -264,7 +264,7 @@ config ARCH_VERSATILE select ARM_VIC select HAVE_CLK select COMMON_CLKDEV - select ICST307 + select ICST select GENERIC_TIME select GENERIC_CLOCKEVENTS select ARCH_WANT_OPTIONAL_GPIOLIB diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig index 4efbb9d..323d2d2 100644 --- a/arch/arm/common/Kconfig +++ b/arch/arm/common/Kconfig @@ -12,10 +12,7 @@ config ARM_VIC_NR The maximum number of VICs available in the system, for power management. -config ICST525 - bool - -config ICST307 +config ICST bool config SA1111 diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile index 76be7ff..5e8ad0d 100644 --- a/arch/arm/common/Makefile +++ b/arch/arm/common/Makefile @@ -4,8 +4,7 @@ obj-$(CONFIG_ARM_GIC) += gic.o obj-$(CONFIG_ARM_VIC) += vic.o -obj-$(CONFIG_ICST525) += icst525.o -obj-$(CONFIG_ICST307) += icst307.o +obj-$(CONFIG_ICST) += icst.o obj-$(CONFIG_SA1111) += sa1111.o obj-$(CONFIG_PCI_HOST_VIA82C505) += via82c505.o obj-$(CONFIG_DMABOUNCE) += dmabounce.o diff --git a/arch/arm/common/icst.c b/arch/arm/common/icst.c new file mode 100644 index 0000000..9a7f09c --- /dev/null +++ b/arch/arm/common/icst.c @@ -0,0 +1,100 @@ +/* + * linux/arch/arm/common/icst307.c + * + * Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Support functions for calculating clocks/divisors for the ICST307 + * clock generators. See http://www.icst.com/ for more information + * on these devices. + * + * This is an almost identical implementation to the ICST525 clock generator. + * The s2div and idx2s files are different + */ +#include +#include + +#include + +/* + * Divisors for each OD setting. + */ +const unsigned char icst307_s2div[8] = { 10, 2, 8, 4, 5, 7, 3, 6 }; +const unsigned char icst525_s2div[8] = { 10, 2, 8, 4, 5, 7, 9, 6 }; +EXPORT_SYMBOL(icst307_s2div); +EXPORT_SYMBOL(icst525_s2div); + +unsigned long icst_hz(const struct icst_params *p, struct icst_vco vco) +{ + return p->ref * 2 * (vco.v + 8) / ((vco.r + 2) * p->s2div[vco.s]); +} + +EXPORT_SYMBOL(icst_hz); + +/* + * Ascending divisor S values. + */ +const unsigned char icst307_idx2s[8] = { 1, 6, 3, 4, 7, 5, 2, 0 }; +const unsigned char icst525_idx2s[8] = { 1, 3, 4, 7, 5, 2, 6, 0 }; +EXPORT_SYMBOL(icst307_idx2s); +EXPORT_SYMBOL(icst525_idx2s); + +struct icst_vco +icst_hz_to_vco(const struct icst_params *p, unsigned long freq) +{ + struct icst_vco vco = { .s = 1, .v = p->vd_max, .r = p->rd_max }; + unsigned long f; + unsigned int i = 0, rd, best = (unsigned int)-1; + + /* + * First, find the PLL output divisor such + * that the PLL output is within spec. + */ + do { + f = freq * p->s2div[p->idx2s[i]]; + + if (f > p->vco_min && f <= p->vco_max) + break; + } while (i < 8); + + if (i >= 8) + return vco; + + vco.s = p->idx2s[i]; + + /* + * Now find the closest divisor combination + * which gives a PLL output of 'f'. + */ + for (rd = p->rd_min; rd <= p->rd_max; rd++) { + unsigned long fref_div, f_pll; + unsigned int vd; + int f_diff; + + fref_div = (2 * p->ref) / rd; + + vd = (f + fref_div / 2) / fref_div; + if (vd < p->vd_min || vd > p->vd_max) + continue; + + f_pll = fref_div * vd; + f_diff = f_pll - f; + if (f_diff < 0) + f_diff = -f_diff; + + if ((unsigned)f_diff < best) { + vco.v = vd - 8; + vco.r = rd - 2; + if (f_diff == 0) + break; + best = f_diff; + } + } + + return vco; +} + +EXPORT_SYMBOL(icst_hz_to_vco); diff --git a/arch/arm/common/icst307.c b/arch/arm/common/icst307.c deleted file mode 100644 index 8332c07..0000000 --- a/arch/arm/common/icst307.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * linux/arch/arm/common/icst307.c - * - * Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Support functions for calculating clocks/divisors for the ICST307 - * clock generators. See http://www.icst.com/ for more information - * on these devices. - * - * This is an almost identical implementation to the ICST525 clock generator. - * The s2div and idx2s files are different - */ -#include -#include - -#include - -/* - * Divisors for each OD setting. - */ -const unsigned char icst307_s2div[8] = { 10, 2, 8, 4, 5, 7, 3, 6 }; - -EXPORT_SYMBOL(icst307_s2div); - -unsigned long icst307_hz(const struct icst_params *p, struct icst_vco vco) -{ - return p->ref * 2 * (vco.v + 8) / ((vco.r + 2) * p->s2div[vco.s]); -} - -EXPORT_SYMBOL(icst307_hz); - -/* - * Ascending divisor S values. - */ -const unsigned char icst307_idx2s[8] = { 1, 6, 3, 4, 7, 5, 2, 0 }; - -EXPORT_SYMBOL(icst307_idx2s); - -struct icst_vco -icst307_hz_to_vco(const struct icst_params *p, unsigned long freq) -{ - struct icst_vco vco = { .s = 1, .v = p->vd_max, .r = p->rd_max }; - unsigned long f; - unsigned int i = 0, rd, best = (unsigned int)-1; - - /* - * First, find the PLL output divisor such - * that the PLL output is within spec. - */ - do { - f = freq * p->s2div[p->idx2s[i]]; - - /* - * f must be between 6MHz and 200MHz (3.3 or 5V) - */ - if (f > p->vco_min && f <= p->vco_max) - break; - } while (i < 8); - - if (i >= 8) - return vco; - - vco.s = p->idx2s[i]; - - /* - * Now find the closest divisor combination - * which gives a PLL output of 'f'. - */ - for (rd = p->rd_min; rd <= p->rd_max; rd++) { - unsigned long fref_div, f_pll; - unsigned int vd; - int f_diff; - - fref_div = (2 * p->ref) / rd; - - vd = (f + fref_div / 2) / fref_div; - if (vd < p->vd_min || vd > p->vd_max) - continue; - - f_pll = fref_div * vd; - f_diff = f_pll - f; - if (f_diff < 0) - f_diff = -f_diff; - - if ((unsigned)f_diff < best) { - vco.v = vd - 8; - vco.r = rd - 2; - if (f_diff == 0) - break; - best = f_diff; - } - } - - return vco; -} - -EXPORT_SYMBOL(icst307_hz_to_vco); diff --git a/arch/arm/common/icst525.c b/arch/arm/common/icst525.c deleted file mode 100644 index 4180255..0000000 --- a/arch/arm/common/icst525.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * linux/arch/arm/common/icst525.c - * - * Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Support functions for calculating clocks/divisors for the ICST525 - * clock generators. See http://www.icst.com/ for more information - * on these devices. - */ -#include -#include - -#include - -/* - * Divisors for each OD setting. - */ -const unsigned char icst525_s2div[8] = { 10, 2, 8, 4, 5, 7, 9, 6 }; - -EXPORT_SYMBOL(icst525_s2div); - -unsigned long icst525_hz(const struct icst_params *p, struct icst_vco vco) -{ - return p->ref * 2 * (vco.v + 8) / ((vco.r + 2) * p->s2div[vco.s]); -} - -EXPORT_SYMBOL(icst525_hz); - -/* - * Ascending divisor S values. - */ -const unsigned char icst525_idx2s[8] = { 1, 3, 4, 7, 5, 2, 6, 0 }; - -EXPORT_SYMBOL(icst525_idx2s); - -struct icst_vco -icst525_hz_to_vco(const struct icst_params *p, unsigned long freq) -{ - struct icst_vco vco = { .s = 1, .v = p->vd_max, .r = p->rd_max }; - unsigned long f; - unsigned int i = 0, rd, best = (unsigned int)-1; - - /* - * First, find the PLL output divisor such - * that the PLL output is within spec. - */ - do { - f = freq * p->s2div[p->idx2s[i]]; - - /* - * f must be between 10MHz and - * 320MHz (5V) or 200MHz (3V) - */ - if (f > p->vco_min && f <= p->vco_max) - break; - } while (i < 8); - - if (i >= 8) - return vco; - - vco.s = p->idx2s[i]; - - /* - * Now find the closest divisor combination - * which gives a PLL output of 'f'. - */ - for (rd = p->rd_min; rd <= p->rd_max; rd++) { - unsigned long fref_div, f_pll; - unsigned int vd; - int f_diff; - - fref_div = (2 * p->ref) / rd; - - vd = (f + fref_div / 2) / fref_div; - if (vd < p->vd_min || vd > p->vd_max) - continue; - - f_pll = fref_div * vd; - f_diff = f_pll - f; - if (f_diff < 0) - f_diff = -f_diff; - - if ((unsigned)f_diff < best) { - vco.v = vd - 8; - vco.r = rd - 2; - if (f_diff == 0) - break; - best = f_diff; - } - } - - return vco; -} - -EXPORT_SYMBOL(icst525_hz_to_vco); diff --git a/arch/arm/include/asm/hardware/icst.h b/arch/arm/include/asm/hardware/icst.h index 4d40368..10382a3 100644 --- a/arch/arm/include/asm/hardware/icst.h +++ b/arch/arm/include/asm/hardware/icst.h @@ -32,4 +32,28 @@ struct icst_vco { unsigned char s; }; +unsigned long icst_hz(const struct icst_params *p, struct icst_vco vco); +struct icst_vco icst_hz_to_vco(const struct icst_params *p, unsigned long freq); + +/* + * ICST307 VCO frequency must be between 6MHz and 200MHz (3.3 or 5V). + * This frequency is pre-output divider. + */ +#define ICST307_VCO_MIN 6000000 +#define ICST307_VCO_MAX 200000000 + +extern const unsigned char icst307_s2div[]; +extern const unsigned char icst307_idx2s[]; + +/* + * ICST525 VCO frequency must be between 10MHz and 200MHz (3V) or 320MHz (5V). + * This frequency is pre-output divider. + */ +#define ICST525_VCO_MIN 10000000 +#define ICST525_VCO_MAX_3V 200000000 +#define ICST525_VCO_MAX_5V 320000000 + +extern const unsigned char icst525_s2div[]; +extern const unsigned char icst525_idx2s[]; + #endif diff --git a/arch/arm/include/asm/hardware/icst307.h b/arch/arm/include/asm/hardware/icst307.h deleted file mode 100644 index d76fc6e..0000000 --- a/arch/arm/include/asm/hardware/icst307.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * arch/arm/include/asm/hardware/icst307.h - * - * Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Support functions for calculating clocks/divisors for the ICS307 - * clock generators. See http://www.icst.com/ for more information - * on these devices. - * - * This file is similar to the icst525.h file - */ -#ifndef ASMARM_HARDWARE_ICST307_H -#define ASMARM_HARDWARE_ICST307_H - -#include - -unsigned long icst307_hz(const struct icst_params *p, struct icst_vco vco); -struct icst_vco icst307_hz_to_vco(const struct icst_params *p, unsigned long freq); - -/* - * ICST307 VCO frequency must be between 6MHz and 200MHz (3.3 or 5V). - * This frequency is pre-output divider. - */ -#define ICST307_VCO_MIN 6000000 -#define ICST307_VCO_MAX 200000000 - -extern const unsigned char icst307_s2div[]; -extern const unsigned char icst307_idx2s[]; - -#endif diff --git a/arch/arm/include/asm/hardware/icst525.h b/arch/arm/include/asm/hardware/icst525.h deleted file mode 100644 index 2f9b953..0000000 --- a/arch/arm/include/asm/hardware/icst525.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * arch/arm/include/asm/hardware/icst525.h - * - * Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Support functions for calculating clocks/divisors for the ICST525 - * clock generators. See http://www.icst.com/ for more information - * on these devices. - */ -#ifndef ASMARM_HARDWARE_ICST525_H -#define ASMARM_HARDWARE_ICST525_H - -#include - -unsigned long icst525_hz(const struct icst_params *p, struct icst_vco vco); -struct icst_vco icst525_hz_to_vco(const struct icst_params *p, unsigned long freq); - -/* - * ICST525 VCO frequency must be between 10MHz and 200MHz (3V) or 320MHz (5V). - * This frequency is pre-output divider. - */ -#define ICST525_VCO_MIN 10000000 -#define ICST525_VCO_MAX_3V 200000000 -#define ICST525_VCO_MAX_5V 320000000 - -extern const unsigned char icst525_s2div[]; -extern const unsigned char icst525_idx2s[]; - -#endif diff --git a/arch/arm/mach-integrator/clock.c b/arch/arm/mach-integrator/clock.c index a4f80d3..52fc294 100644 --- a/arch/arm/mach-integrator/clock.c +++ b/arch/arm/mach-integrator/clock.c @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include @@ -38,8 +38,8 @@ EXPORT_SYMBOL(clk_get_rate); long clk_round_rate(struct clk *clk, unsigned long rate) { struct icst_vco vco; - vco = icst525_hz_to_vco(clk->params, rate); - return icst525_hz(clk->params, vco); + vco = icst_hz_to_vco(clk->params, rate); + return icst_hz(clk->params, vco); } EXPORT_SYMBOL(clk_round_rate); @@ -50,8 +50,8 @@ int clk_set_rate(struct clk *clk, unsigned long rate) if (clk->setvco) { struct icst_vco vco; - vco = icst525_hz_to_vco(clk->params, rate); - clk->rate = icst525_hz(clk->params, vco); + vco = icst_hz_to_vco(clk->params, rate); + clk->rate = icst_hz(clk->params, vco); clk->setvco(clk, vco); ret = 0; } diff --git a/arch/arm/mach-integrator/cpu.c b/arch/arm/mach-integrator/cpu.c index 9481c54..1cb222d 100644 --- a/arch/arm/mach-integrator/cpu.c +++ b/arch/arm/mach-integrator/cpu.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include static struct cpufreq_driver integrator_driver; @@ -66,11 +66,11 @@ static int integrator_verify_policy(struct cpufreq_policy *policy) policy->cpuinfo.min_freq, policy->cpuinfo.max_freq); - vco = icst525_hz_to_vco(&cclk_params, policy->max * 1000); - policy->max = icst525_hz(&cclk_params, vco) / 1000; + vco = icst_hz_to_vco(&cclk_params, policy->max * 1000); + policy->max = icst_hz(&cclk_params, vco) / 1000; - vco = icst525_hz_to_vco(&cclk_params, policy->min * 1000); - policy->min = icst525_hz(&cclk_params, vco) / 1000; + vco = icst_hz_to_vco(&cclk_params, policy->min * 1000); + policy->min = icst_hz(&cclk_params, vco) / 1000; cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, @@ -112,17 +112,17 @@ static int integrator_set_target(struct cpufreq_policy *policy, } vco.v = cm_osc & 255; vco.r = 22; - freqs.old = icst525_hz(&cclk_params, vco) / 1000; + freqs.old = icst_hz(&cclk_params, vco) / 1000; - /* icst525_hz_to_vco rounds down -- so we need the next + /* icst_hz_to_vco rounds down -- so we need the next * larger freq in case of CPUFREQ_RELATION_L. */ if (relation == CPUFREQ_RELATION_L) target_freq += 999; if (target_freq > policy->max) target_freq = policy->max; - vco = icst525_hz_to_vco(&cclk_params, target_freq * 1000); - freqs.new = icst525_hz(&cclk_params, vco) / 1000; + vco = icst_hz_to_vco(&cclk_params, target_freq * 1000); + freqs.new = icst_hz(&cclk_params, vco) / 1000; freqs.cpu = policy->cpu; @@ -180,7 +180,7 @@ static unsigned int integrator_get(unsigned int cpu) vco.v = cm_osc & 255; vco.r = 22; - current_freq = icst525_hz(&cclk_params, vco) / 1000; /* current freq */ + current_freq = icst_hz(&cclk_params, vco) / 1000; /* current freq */ set_cpus_allowed(current, cpus_allowed); diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c index e24cfc3..3e21102 100644 --- a/arch/arm/mach-integrator/impd1.c +++ b/arch/arm/mach-integrator/impd1.c @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include #include diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 9997d1f..a9ab8fd 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include diff --git a/arch/arm/mach-realview/clock.c b/arch/arm/mach-realview/clock.c index 2ba0667..18c5459 100644 --- a/arch/arm/mach-realview/clock.c +++ b/arch/arm/mach-realview/clock.c @@ -18,7 +18,7 @@ #include #include -#include +#include #include "clock.h" @@ -42,8 +42,8 @@ EXPORT_SYMBOL(clk_get_rate); long clk_round_rate(struct clk *clk, unsigned long rate) { struct icst_vco vco; - vco = icst307_hz_to_vco(clk->params, rate); - return icst307_hz(clk->params, vco); + vco = icst_hz_to_vco(clk->params, rate); + return icst_hz(clk->params, vco); } EXPORT_SYMBOL(clk_round_rate); @@ -54,8 +54,8 @@ int clk_set_rate(struct clk *clk, unsigned long rate) if (clk->setvco) { struct icst_vco vco; - vco = icst307_hz_to_vco(clk->params, rate); - clk->rate = icst307_hz(clk->params, vco); + vco = icst_hz_to_vco(clk->params, rate); + clk->rate = icst_hz(clk->params, vco); clk->setvco(clk, vco); ret = 0; } diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index 26d44ca..a8c215a 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include #include diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c index 7d857d3..39d953c 100644 --- a/arch/arm/mach-realview/realview_eb.c +++ b/arch/arm/mach-realview/realview_eb.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c index 44392e5..a93aac5 100644 --- a/arch/arm/mach-realview/realview_pb1176.c +++ b/arch/arm/mach-realview/realview_pb1176.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c index 3e02731..c7c656e 100644 --- a/arch/arm/mach-realview/realview_pb11mp.c +++ b/arch/arm/mach-realview/realview_pb11mp.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include diff --git a/arch/arm/mach-realview/realview_pba8.c b/arch/arm/mach-realview/realview_pba8.c index fe4e25c..3e3aaa3 100644 --- a/arch/arm/mach-realview/realview_pba8.c +++ b/arch/arm/mach-realview/realview_pba8.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include diff --git a/arch/arm/mach-versatile/clock.c b/arch/arm/mach-versatile/clock.c index 82753be..adc67d7 100644 --- a/arch/arm/mach-versatile/clock.c +++ b/arch/arm/mach-versatile/clock.c @@ -19,7 +19,7 @@ #include #include -#include +#include #include "clock.h" @@ -43,8 +43,8 @@ EXPORT_SYMBOL(clk_get_rate); long clk_round_rate(struct clk *clk, unsigned long rate) { struct icst_vco vco; - vco = icst307_hz_to_vco(clk->params, rate); - return icst307_hz(clk->params, vco); + vco = icst_hz_to_vco(clk->params, rate); + return icst_hz(clk->params, vco); } EXPORT_SYMBOL(clk_round_rate); @@ -55,8 +55,8 @@ int clk_set_rate(struct clk *clk, unsigned long rate) if (clk->setvco) { struct icst_vco vco; - vco = icst307_hz_to_vco(clk->params, rate); - clk->rate = icst307_hz(clk->params, vco); + vco = icst_hz_to_vco(clk->params, rate); + clk->rate = icst_hz(clk->params, vco); clk->setvco(clk, vco); ret = 0; } diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index 51d7aeb..3c67691 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include -- cgit v0.10.2 From f4b8b319bf21bf3576014ce7336763cd3e1684ef Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 14 Jan 2010 12:48:06 +0000 Subject: ARM: Realview/Versatile/Integrator: separate out common clock code Signed-off-by: Russell King diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 3c436fd..e8265f2 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -243,6 +243,7 @@ config ARCH_INTEGRATOR select ICST select GENERIC_TIME select GENERIC_CLOCKEVENTS + select PLAT_VERSATILE help Support for ARM's Integrator platform. @@ -255,6 +256,7 @@ config ARCH_REALVIEW select GENERIC_TIME select GENERIC_CLOCKEVENTS select ARCH_WANT_OPTIONAL_GPIOLIB + select PLAT_VERSATILE help This enables support for ARM Ltd RealView boards. @@ -268,6 +270,7 @@ config ARCH_VERSATILE select GENERIC_TIME select GENERIC_CLOCKEVENTS select ARCH_WANT_OPTIONAL_GPIOLIB + select PLAT_VERSATILE help This enables support for ARM Ltd Versatile board. @@ -938,6 +941,9 @@ config PLAT_ORION config PLAT_PXA bool +config PLAT_VERSATILE + bool + source arch/arm/mm/Kconfig config IWMMXT diff --git a/arch/arm/Makefile b/arch/arm/Makefile index ed820e7..1962deb 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -192,6 +192,7 @@ plat-$(CONFIG_PLAT_PXA) := pxa plat-$(CONFIG_PLAT_S3C24XX) := s3c24xx samsung plat-$(CONFIG_PLAT_S5PC1XX) := s5pc1xx samsung plat-$(CONFIG_PLAT_S5P) := s5p samsung +plat-$(CONFIG_PLAT_VERSATILE) := versatile ifeq ($(CONFIG_ARCH_EBSA110),y) # This is what happens if you forget the IOCS16 line. diff --git a/arch/arm/mach-integrator/Makefile b/arch/arm/mach-integrator/Makefile index 6a5ef8d..ebeef96 100644 --- a/arch/arm/mach-integrator/Makefile +++ b/arch/arm/mach-integrator/Makefile @@ -4,7 +4,7 @@ # Object file lists. -obj-y := clock.o core.o lm.o +obj-y := core.o lm.o obj-$(CONFIG_ARCH_INTEGRATOR_AP) += integrator_ap.o obj-$(CONFIG_ARCH_INTEGRATOR_CP) += integrator_cp.o diff --git a/arch/arm/mach-integrator/clock.c b/arch/arm/mach-integrator/clock.c deleted file mode 100644 index 52fc294..0000000 --- a/arch/arm/mach-integrator/clock.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * linux/arch/arm/mach-integrator/clock.c - * - * Copyright (C) 2004 ARM Limited. - * Written by Deep Blue Solutions Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include -#include -#include -#include -#include - -#include -#include -#include - -int clk_enable(struct clk *clk) -{ - return 0; -} -EXPORT_SYMBOL(clk_enable); - -void clk_disable(struct clk *clk) -{ -} -EXPORT_SYMBOL(clk_disable); - -unsigned long clk_get_rate(struct clk *clk) -{ - return clk->rate; -} -EXPORT_SYMBOL(clk_get_rate); - -long clk_round_rate(struct clk *clk, unsigned long rate) -{ - struct icst_vco vco; - vco = icst_hz_to_vco(clk->params, rate); - return icst_hz(clk->params, vco); -} -EXPORT_SYMBOL(clk_round_rate); - -int clk_set_rate(struct clk *clk, unsigned long rate) -{ - int ret = -EIO; - - if (clk->setvco) { - struct icst_vco vco; - - vco = icst_hz_to_vco(clk->params, rate); - clk->rate = icst_hz(clk->params, vco); - clk->setvco(clk, vco); - ret = 0; - } - return ret; -} -EXPORT_SYMBOL(clk_set_rate); diff --git a/arch/arm/mach-realview/Makefile b/arch/arm/mach-realview/Makefile index e704edb..a01b76b 100644 --- a/arch/arm/mach-realview/Makefile +++ b/arch/arm/mach-realview/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux kernel. # -obj-y := core.o clock.o +obj-y := core.o obj-$(CONFIG_MACH_REALVIEW_EB) += realview_eb.o obj-$(CONFIG_MACH_REALVIEW_PB11MP) += realview_pb11mp.o obj-$(CONFIG_MACH_REALVIEW_PB1176) += realview_pb1176.o diff --git a/arch/arm/mach-realview/clock.c b/arch/arm/mach-realview/clock.c deleted file mode 100644 index 18c5459..0000000 --- a/arch/arm/mach-realview/clock.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * linux/arch/arm/mach-realview/clock.c - * - * Copyright (C) 2004 ARM Limited. - * Written by Deep Blue Solutions Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "clock.h" - -int clk_enable(struct clk *clk) -{ - return 0; -} -EXPORT_SYMBOL(clk_enable); - -void clk_disable(struct clk *clk) -{ -} -EXPORT_SYMBOL(clk_disable); - -unsigned long clk_get_rate(struct clk *clk) -{ - return clk->rate; -} -EXPORT_SYMBOL(clk_get_rate); - -long clk_round_rate(struct clk *clk, unsigned long rate) -{ - struct icst_vco vco; - vco = icst_hz_to_vco(clk->params, rate); - return icst_hz(clk->params, vco); -} -EXPORT_SYMBOL(clk_round_rate); - -int clk_set_rate(struct clk *clk, unsigned long rate) -{ - int ret = -EIO; - - if (clk->setvco) { - struct icst_vco vco; - - vco = icst_hz_to_vco(clk->params, rate); - clk->rate = icst_hz(clk->params, vco); - clk->setvco(clk, vco); - ret = 0; - } - return ret; -} -EXPORT_SYMBOL(clk_set_rate); diff --git a/arch/arm/mach-realview/clock.h b/arch/arm/mach-realview/clock.h deleted file mode 100644 index fa64c85..0000000 --- a/arch/arm/mach-realview/clock.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * linux/arch/arm/mach-realview/clock.h - * - * Copyright (C) 2004 ARM Limited. - * Written by Deep Blue Solutions Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include - -struct module; - -struct clk { - unsigned long rate; - const struct icst_params *params; - void *data; - void (*setvco)(struct clk *, struct icst_vco vco); -}; diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index a8c215a..17eb7eb 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c @@ -48,11 +48,11 @@ #include +#include #include #include #include "core.h" -#include "clock.h" #define REALVIEW_REFCOUNTER (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_24MHz_OFFSET) diff --git a/arch/arm/mach-realview/include/mach/clkdev.h b/arch/arm/mach-realview/include/mach/clkdev.h index 04b37a8..fefe467 100644 --- a/arch/arm/mach-realview/include/mach/clkdev.h +++ b/arch/arm/mach-realview/include/mach/clkdev.h @@ -1,6 +1,15 @@ #ifndef __ASM_MACH_CLKDEV_H #define __ASM_MACH_CLKDEV_H +#include + +struct clk { + unsigned long rate; + const struct icst_params *params; + u32 oscoff; + void (*setvco)(struct clk *, struct icst_vco vco); +}; + #define __clk_get(clk) ({ 1; }) #define __clk_put(clk) do { } while (0) diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c index 39d953c..006765f 100644 --- a/arch/arm/mach-realview/realview_eb.c +++ b/arch/arm/mach-realview/realview_eb.c @@ -43,7 +43,6 @@ #include #include "core.h" -#include "clock.h" static struct map_desc realview_eb_io_desc[] __initdata = { { diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c index a93aac5..217f7c1 100644 --- a/arch/arm/mach-realview/realview_pb1176.c +++ b/arch/arm/mach-realview/realview_pb1176.c @@ -43,7 +43,6 @@ #include #include "core.h" -#include "clock.h" static struct map_desc realview_pb1176_io_desc[] __initdata = { { diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c index c7c656e..9ef2ecc 100644 --- a/arch/arm/mach-realview/realview_pb11mp.c +++ b/arch/arm/mach-realview/realview_pb11mp.c @@ -44,7 +44,6 @@ #include #include "core.h" -#include "clock.h" static struct map_desc realview_pb11mp_io_desc[] __initdata = { { diff --git a/arch/arm/mach-realview/realview_pba8.c b/arch/arm/mach-realview/realview_pba8.c index 3e3aaa3..2fab3a6 100644 --- a/arch/arm/mach-realview/realview_pba8.c +++ b/arch/arm/mach-realview/realview_pba8.c @@ -41,7 +41,6 @@ #include #include "core.h" -#include "clock.h" static struct map_desc realview_pba8_io_desc[] __initdata = { { diff --git a/arch/arm/mach-versatile/Makefile b/arch/arm/mach-versatile/Makefile index ba81e70..97cf4d8 100644 --- a/arch/arm/mach-versatile/Makefile +++ b/arch/arm/mach-versatile/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux kernel. # -obj-y := core.o clock.o +obj-y := core.o obj-$(CONFIG_ARCH_VERSATILE_PB) += versatile_pb.o obj-$(CONFIG_MACH_VERSATILE_AB) += versatile_ab.o obj-$(CONFIG_PCI) += pci.o diff --git a/arch/arm/mach-versatile/clock.c b/arch/arm/mach-versatile/clock.c deleted file mode 100644 index adc67d7..0000000 --- a/arch/arm/mach-versatile/clock.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * linux/arch/arm/mach-versatile/clock.c - * - * Copyright (C) 2004 ARM Limited. - * Written by Deep Blue Solutions Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "clock.h" - -int clk_enable(struct clk *clk) -{ - return 0; -} -EXPORT_SYMBOL(clk_enable); - -void clk_disable(struct clk *clk) -{ -} -EXPORT_SYMBOL(clk_disable); - -unsigned long clk_get_rate(struct clk *clk) -{ - return clk->rate; -} -EXPORT_SYMBOL(clk_get_rate); - -long clk_round_rate(struct clk *clk, unsigned long rate) -{ - struct icst_vco vco; - vco = icst_hz_to_vco(clk->params, rate); - return icst_hz(clk->params, vco); -} -EXPORT_SYMBOL(clk_round_rate); - -int clk_set_rate(struct clk *clk, unsigned long rate) -{ - int ret = -EIO; - - if (clk->setvco) { - struct icst_vco vco; - - vco = icst_hz_to_vco(clk->params, rate); - clk->rate = icst_hz(clk->params, vco); - clk->setvco(clk, vco); - ret = 0; - } - return ret; -} -EXPORT_SYMBOL(clk_set_rate); diff --git a/arch/arm/mach-versatile/clock.h b/arch/arm/mach-versatile/clock.h deleted file mode 100644 index aed7e22..0000000 --- a/arch/arm/mach-versatile/clock.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * linux/arch/arm/mach-versatile/clock.h - * - * Copyright (C) 2004 ARM Limited. - * Written by Deep Blue Solutions Limited. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include - -struct module; - -struct clk { - unsigned long rate; - const struct icst_params *params; - u32 oscoff; - void *data; - void (*setvco)(struct clk *, struct icst_vco vco); -}; diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index 3c67691..e9d255f 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -47,11 +47,11 @@ #include #include #include +#include #include #include #include "core.h" -#include "clock.h" /* * All IO addresses are mapped onto VA 0xFFFx.xxxx, where x.xxxx diff --git a/arch/arm/mach-versatile/include/mach/clkdev.h b/arch/arm/mach-versatile/include/mach/clkdev.h index 04b37a8..fefe467 100644 --- a/arch/arm/mach-versatile/include/mach/clkdev.h +++ b/arch/arm/mach-versatile/include/mach/clkdev.h @@ -1,6 +1,15 @@ #ifndef __ASM_MACH_CLKDEV_H #define __ASM_MACH_CLKDEV_H +#include + +struct clk { + unsigned long rate; + const struct icst_params *params; + u32 oscoff; + void (*setvco)(struct clk *, struct icst_vco vco); +}; + #define __clk_get(clk) ({ 1; }) #define __clk_put(clk) do { } while (0) diff --git a/arch/arm/plat-versatile/Makefile b/arch/arm/plat-versatile/Makefile new file mode 100644 index 0000000..2228fd1 --- /dev/null +++ b/arch/arm/plat-versatile/Makefile @@ -0,0 +1 @@ +obj-y := clock.o diff --git a/arch/arm/plat-versatile/clock.c b/arch/arm/plat-versatile/clock.c new file mode 100644 index 0000000..2fa34de --- /dev/null +++ b/arch/arm/plat-versatile/clock.c @@ -0,0 +1,60 @@ +/* + * linux/arch/arm/plat-versatile/clock.c + * + * Copyright (C) 2004 ARM Limited. + * Written by Deep Blue Solutions Limited. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include + +#include + +#include + +int clk_enable(struct clk *clk) +{ + return 0; +} +EXPORT_SYMBOL(clk_enable); + +void clk_disable(struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_disable); + +unsigned long clk_get_rate(struct clk *clk) +{ + return clk->rate; +} +EXPORT_SYMBOL(clk_get_rate); + +long clk_round_rate(struct clk *clk, unsigned long rate) +{ + struct icst_vco vco; + vco = icst_hz_to_vco(clk->params, rate); + return icst_hz(clk->params, vco); +} +EXPORT_SYMBOL(clk_round_rate); + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + int ret = -EIO; + + if (clk->setvco) { + struct icst_vco vco; + + vco = icst_hz_to_vco(clk->params, rate); + clk->rate = icst_hz(clk->params, vco); + clk->setvco(clk, vco); + ret = 0; + } + return ret; +} +EXPORT_SYMBOL(clk_set_rate); -- cgit v0.10.2 From e388771458b4ff3ad81ab70e390b24d069647da4 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 14 Jan 2010 13:30:16 +0000 Subject: ARM: Realview/Versatile: separate out common SP804 timer code Signed-off-by: Russell King diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index e8265f2..5534870 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -257,6 +257,7 @@ config ARCH_REALVIEW select GENERIC_CLOCKEVENTS select ARCH_WANT_OPTIONAL_GPIOLIB select PLAT_VERSATILE + select ARM_TIMER_SP804 help This enables support for ARM Ltd RealView boards. @@ -271,6 +272,7 @@ config ARCH_VERSATILE select GENERIC_CLOCKEVENTS select ARCH_WANT_OPTIONAL_GPIOLIB select PLAT_VERSATILE + select ARM_TIMER_SP804 help This enables support for ARM Ltd Versatile board. @@ -944,6 +946,9 @@ config PLAT_PXA config PLAT_VERSATILE bool +config ARM_TIMER_SP804 + bool + source arch/arm/mm/Kconfig config IWMMXT diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index 17eb7eb..80b8142 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c @@ -25,8 +25,6 @@ #include #include #include -#include -#include #include #include #include @@ -51,6 +49,7 @@ #include #include #include +#include #include "core.h" @@ -646,133 +645,6 @@ void __iomem *timer2_va_base; void __iomem *timer3_va_base; /* - * How long is the timer interval? - */ -#define TIMER_INTERVAL (TICKS_PER_uSEC * mSEC_10) -#if TIMER_INTERVAL >= 0x100000 -#define TIMER_RELOAD (TIMER_INTERVAL >> 8) -#define TIMER_DIVISOR (TIMER_CTRL_DIV256) -#define TICKS2USECS(x) (256 * (x) / TICKS_PER_uSEC) -#elif TIMER_INTERVAL >= 0x10000 -#define TIMER_RELOAD (TIMER_INTERVAL >> 4) /* Divide by 16 */ -#define TIMER_DIVISOR (TIMER_CTRL_DIV16) -#define TICKS2USECS(x) (16 * (x) / TICKS_PER_uSEC) -#else -#define TIMER_RELOAD (TIMER_INTERVAL) -#define TIMER_DIVISOR (TIMER_CTRL_DIV1) -#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC) -#endif - -static void timer_set_mode(enum clock_event_mode mode, - struct clock_event_device *clk) -{ - unsigned long ctrl; - - switch(mode) { - case CLOCK_EVT_MODE_PERIODIC: - writel(TIMER_RELOAD, timer0_va_base + TIMER_LOAD); - - ctrl = TIMER_CTRL_PERIODIC; - ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_IE | TIMER_CTRL_ENABLE; - break; - case CLOCK_EVT_MODE_ONESHOT: - /* period set, and timer enabled in 'next_event' hook */ - ctrl = TIMER_CTRL_ONESHOT; - ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_IE; - break; - case CLOCK_EVT_MODE_UNUSED: - case CLOCK_EVT_MODE_SHUTDOWN: - default: - ctrl = 0; - } - - writel(ctrl, timer0_va_base + TIMER_CTRL); -} - -static int timer_set_next_event(unsigned long evt, - struct clock_event_device *unused) -{ - unsigned long ctrl = readl(timer0_va_base + TIMER_CTRL); - - writel(evt, timer0_va_base + TIMER_LOAD); - writel(ctrl | TIMER_CTRL_ENABLE, timer0_va_base + TIMER_CTRL); - - return 0; -} - -static struct clock_event_device timer0_clockevent = { - .name = "timer0", - .shift = 32, - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .set_mode = timer_set_mode, - .set_next_event = timer_set_next_event, - .rating = 300, - .cpumask = cpu_all_mask, -}; - -static void __init realview_clockevents_init(unsigned int timer_irq) -{ - timer0_clockevent.irq = timer_irq; - timer0_clockevent.mult = - div_sc(1000000, NSEC_PER_SEC, timer0_clockevent.shift); - timer0_clockevent.max_delta_ns = - clockevent_delta2ns(0xffffffff, &timer0_clockevent); - timer0_clockevent.min_delta_ns = - clockevent_delta2ns(0xf, &timer0_clockevent); - - clockevents_register_device(&timer0_clockevent); -} - -/* - * IRQ handler for the timer - */ -static irqreturn_t realview_timer_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *evt = &timer0_clockevent; - - /* clear the interrupt */ - writel(1, timer0_va_base + TIMER_INTCLR); - - evt->event_handler(evt); - - return IRQ_HANDLED; -} - -static struct irqaction realview_timer_irq = { - .name = "RealView Timer Tick", - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, - .handler = realview_timer_interrupt, -}; - -static cycle_t realview_get_cycles(struct clocksource *cs) -{ - return ~readl(timer3_va_base + TIMER_VALUE); -} - -static struct clocksource clocksource_realview = { - .name = "timer3", - .rating = 200, - .read = realview_get_cycles, - .mask = CLOCKSOURCE_MASK(32), - .shift = 20, - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - -static void __init realview_clocksource_init(void) -{ - /* setup timer 0 as free-running clocksource */ - writel(0, timer3_va_base + TIMER_CTRL); - writel(0xffffffff, timer3_va_base + TIMER_LOAD); - writel(0xffffffff, timer3_va_base + TIMER_VALUE); - writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC, - timer3_va_base + TIMER_CTRL); - - clocksource_realview.mult = - clocksource_khz2mult(1000, clocksource_realview.shift); - clocksource_register(&clocksource_realview); -} - -/* * Set up the clock source and clock events devices */ void __init realview_timer_init(unsigned int timer_irq) @@ -799,13 +671,8 @@ void __init realview_timer_init(unsigned int timer_irq) writel(0, timer2_va_base + TIMER_CTRL); writel(0, timer3_va_base + TIMER_CTRL); - /* - * Make irqs happen for the system timer - */ - setup_irq(timer_irq, &realview_timer_irq); - - realview_clocksource_init(); - realview_clockevents_init(timer_irq); + sp804_clocksource_init(timer3_va_base); + sp804_clockevents_init(timer0_va_base, timer_irq); } /* diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index e9d255f..b68ddd3 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -28,8 +28,6 @@ #include #include #include -#include -#include #include #include @@ -50,6 +48,7 @@ #include #include #include +#include #include "core.h" @@ -877,120 +876,6 @@ void __init versatile_init(void) #define TIMER1_VA_BASE (__io_address(VERSATILE_TIMER0_1_BASE) + 0x20) #define TIMER2_VA_BASE __io_address(VERSATILE_TIMER2_3_BASE) #define TIMER3_VA_BASE (__io_address(VERSATILE_TIMER2_3_BASE) + 0x20) -#define VA_IC_BASE __io_address(VERSATILE_VIC_BASE) - -/* - * How long is the timer interval? - */ -#define TIMER_INTERVAL (TICKS_PER_uSEC * mSEC_10) -#if TIMER_INTERVAL >= 0x100000 -#define TIMER_RELOAD (TIMER_INTERVAL >> 8) -#define TIMER_DIVISOR (TIMER_CTRL_DIV256) -#define TICKS2USECS(x) (256 * (x) / TICKS_PER_uSEC) -#elif TIMER_INTERVAL >= 0x10000 -#define TIMER_RELOAD (TIMER_INTERVAL >> 4) /* Divide by 16 */ -#define TIMER_DIVISOR (TIMER_CTRL_DIV16) -#define TICKS2USECS(x) (16 * (x) / TICKS_PER_uSEC) -#else -#define TIMER_RELOAD (TIMER_INTERVAL) -#define TIMER_DIVISOR (TIMER_CTRL_DIV1) -#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC) -#endif - -static void timer_set_mode(enum clock_event_mode mode, - struct clock_event_device *clk) -{ - unsigned long ctrl; - - switch(mode) { - case CLOCK_EVT_MODE_PERIODIC: - writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD); - - ctrl = TIMER_CTRL_PERIODIC; - ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_IE | TIMER_CTRL_ENABLE; - break; - case CLOCK_EVT_MODE_ONESHOT: - /* period set, and timer enabled in 'next_event' hook */ - ctrl = TIMER_CTRL_ONESHOT; - ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_IE; - break; - case CLOCK_EVT_MODE_UNUSED: - case CLOCK_EVT_MODE_SHUTDOWN: - default: - ctrl = 0; - } - - writel(ctrl, TIMER0_VA_BASE + TIMER_CTRL); -} - -static int timer_set_next_event(unsigned long evt, - struct clock_event_device *unused) -{ - unsigned long ctrl = readl(TIMER0_VA_BASE + TIMER_CTRL); - - writel(evt, TIMER0_VA_BASE + TIMER_LOAD); - writel(ctrl | TIMER_CTRL_ENABLE, TIMER0_VA_BASE + TIMER_CTRL); - - return 0; -} - -static struct clock_event_device timer0_clockevent = { - .name = "timer0", - .shift = 32, - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .set_mode = timer_set_mode, - .set_next_event = timer_set_next_event, -}; - -/* - * IRQ handler for the timer - */ -static irqreturn_t versatile_timer_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *evt = &timer0_clockevent; - - writel(1, TIMER0_VA_BASE + TIMER_INTCLR); - - evt->event_handler(evt); - - return IRQ_HANDLED; -} - -static struct irqaction versatile_timer_irq = { - .name = "Versatile Timer Tick", - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, - .handler = versatile_timer_interrupt, -}; - -static cycle_t versatile_get_cycles(struct clocksource *cs) -{ - return ~readl(TIMER3_VA_BASE + TIMER_VALUE); -} - -static struct clocksource clocksource_versatile = { - .name = "timer3", - .rating = 200, - .read = versatile_get_cycles, - .mask = CLOCKSOURCE_MASK(32), - .shift = 20, - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - -static int __init versatile_clocksource_init(void) -{ - /* setup timer3 as free-running clocksource */ - writel(0, TIMER3_VA_BASE + TIMER_CTRL); - writel(0xffffffff, TIMER3_VA_BASE + TIMER_LOAD); - writel(0xffffffff, TIMER3_VA_BASE + TIMER_VALUE); - writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC, - TIMER3_VA_BASE + TIMER_CTRL); - - clocksource_versatile.mult = - clocksource_khz2mult(1000, clocksource_versatile.shift); - clocksource_register(&clocksource_versatile); - - return 0; -} /* * Set up timer interrupt, and return the current time in seconds. @@ -1019,22 +904,8 @@ static void __init versatile_timer_init(void) writel(0, TIMER2_VA_BASE + TIMER_CTRL); writel(0, TIMER3_VA_BASE + TIMER_CTRL); - /* - * Make irqs happen for the system timer - */ - setup_irq(IRQ_TIMERINT0_1, &versatile_timer_irq); - - versatile_clocksource_init(); - - timer0_clockevent.mult = - div_sc(1000000, NSEC_PER_SEC, timer0_clockevent.shift); - timer0_clockevent.max_delta_ns = - clockevent_delta2ns(0xffffffff, &timer0_clockevent); - timer0_clockevent.min_delta_ns = - clockevent_delta2ns(0xf, &timer0_clockevent); - - timer0_clockevent.cpumask = cpumask_of(0); - clockevents_register_device(&timer0_clockevent); + sp804_clocksource_init(TIMER3_VA_BASE); + sp804_clockevents_init(TIMER0_VA_BASE, IRQ_TIMERINT0_1); } struct sys_timer versatile_timer = { diff --git a/arch/arm/plat-versatile/Makefile b/arch/arm/plat-versatile/Makefile index 2228fd1..334d2f1 100644 --- a/arch/arm/plat-versatile/Makefile +++ b/arch/arm/plat-versatile/Makefile @@ -1 +1,2 @@ obj-y := clock.o +obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o diff --git a/arch/arm/plat-versatile/include/plat/timer-sp.h b/arch/arm/plat-versatile/include/plat/timer-sp.h new file mode 100644 index 0000000..21e75e3 --- /dev/null +++ b/arch/arm/plat-versatile/include/plat/timer-sp.h @@ -0,0 +1,2 @@ +void sp804_clocksource_init(void __iomem *); +void sp804_clockevents_init(void __iomem *, unsigned int); diff --git a/arch/arm/plat-versatile/timer-sp.c b/arch/arm/plat-versatile/timer-sp.c new file mode 100644 index 0000000..98722f4 --- /dev/null +++ b/arch/arm/plat-versatile/timer-sp.c @@ -0,0 +1,168 @@ +/* + * linux/arch/arm/plat-versatile/timer-sp.c + * + * Copyright (C) 1999 - 2003 ARM Limited + * Copyright (C) 2000 Deep Blue Solutions Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include + +#include + +#include + +#include + +/* + * How long is the timer interval? + */ +#define TIMER_INTERVAL (TICKS_PER_uSEC * mSEC_10) +#if TIMER_INTERVAL >= 0x100000 +#define TIMER_RELOAD (TIMER_INTERVAL >> 8) +#define TIMER_DIVISOR (TIMER_CTRL_DIV256) +#elif TIMER_INTERVAL >= 0x10000 +#define TIMER_RELOAD (TIMER_INTERVAL >> 4) /* Divide by 16 */ +#define TIMER_DIVISOR (TIMER_CTRL_DIV16) +#else +#define TIMER_RELOAD (TIMER_INTERVAL) +#define TIMER_DIVISOR (TIMER_CTRL_DIV1) +#endif + + +static void __iomem *clksrc_base; + +static cycle_t sp804_read(struct clocksource *cs) +{ + return ~readl(clksrc_base + TIMER_VALUE); +} + +static struct clocksource clocksource_sp804 = { + .name = "timer3", + .rating = 200, + .read = sp804_read, + .mask = CLOCKSOURCE_MASK(32), + .shift = 20, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +void __init sp804_clocksource_init(void __iomem *base) +{ + struct clocksource *cs = &clocksource_sp804; + + clksrc_base = base; + + /* setup timer 0 as free-running clocksource */ + writel(0, clksrc_base + TIMER_CTRL); + writel(0xffffffff, clksrc_base + TIMER_LOAD); + writel(0xffffffff, clksrc_base + TIMER_VALUE); + writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC, + clksrc_base + TIMER_CTRL); + + cs->mult = clocksource_khz2mult(1000, cs->shift); + clocksource_register(cs); +} + + +static void __iomem *clkevt_base; + +/* + * IRQ handler for the timer + */ +static irqreturn_t sp804_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = dev_id; + + /* clear the interrupt */ + writel(1, clkevt_base + TIMER_INTCLR); + + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +static void sp804_set_mode(enum clock_event_mode mode, + struct clock_event_device *evt) +{ + unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE; + + writel(ctrl, clkevt_base + TIMER_CTRL); + + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + writel(TIMER_RELOAD, clkevt_base + TIMER_LOAD); + ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE; + break; + + case CLOCK_EVT_MODE_ONESHOT: + /* period set, and timer enabled in 'next_event' hook */ + ctrl |= TIMER_CTRL_ONESHOT; + break; + + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + default: + break; + } + + writel(ctrl, clkevt_base + TIMER_CTRL); +} + +static int sp804_set_next_event(unsigned long next, + struct clock_event_device *evt) +{ + unsigned long ctrl = readl(clkevt_base + TIMER_CTRL); + + writel(next, clkevt_base + TIMER_LOAD); + writel(ctrl | TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL); + + return 0; +} + +static struct clock_event_device sp804_clockevent = { + .name = "timer0", + .shift = 32, + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + .set_mode = sp804_set_mode, + .set_next_event = sp804_set_next_event, + .rating = 300, + .cpumask = cpu_all_mask, +}; + +static struct irqaction sp804_timer_irq = { + .name = "timer", + .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .handler = sp804_timer_interrupt, + .dev_id = &sp804_clockevent, +}; + +void __init sp804_clockevents_init(void __iomem *base, unsigned int timer_irq) +{ + struct clock_event_device *evt = &sp804_clockevent; + + clkevt_base = base; + + evt->irq = timer_irq; + evt->mult = div_sc(1000000, NSEC_PER_SEC, evt->shift); + evt->max_delta_ns = clockevent_delta2ns(0xffffffff, evt); + evt->min_delta_ns = clockevent_delta2ns(0xf, evt); + + setup_irq(timer_irq, &sp804_timer_irq); + clockevents_register_device(evt); +} -- cgit v0.10.2 From fe8e1a57f0ccdaede41618ca9ced7d746b6298d3 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 14 Jan 2010 22:37:12 +0000 Subject: ARM: Realview/Versatile: remove useless TIMER_RELOAD calculations Realview/Versatile copied the Integrator timer code, including the calculations for ensuring that the reload value fits into the 16-bit counter. However, these platforms have a 32-bit counter which is clocked at a slower rate. The result is that the preprocessor conditions are never triggered: TICKS_PER_uSEC = 1, mSEC_10 = 10000, which is 0x2710 - less than 0x10000. So, remove the unnecessary complexity, reducing the TIMER_RELOAD calculation to just: TICKS_PER_uSEC * mSEC_10 Signed-off-by: Russell King diff --git a/arch/arm/plat-versatile/timer-sp.c b/arch/arm/plat-versatile/timer-sp.c index 98722f4..d1dbef5 100644 --- a/arch/arm/plat-versatile/timer-sp.c +++ b/arch/arm/plat-versatile/timer-sp.c @@ -33,17 +33,7 @@ /* * How long is the timer interval? */ -#define TIMER_INTERVAL (TICKS_PER_uSEC * mSEC_10) -#if TIMER_INTERVAL >= 0x100000 -#define TIMER_RELOAD (TIMER_INTERVAL >> 8) -#define TIMER_DIVISOR (TIMER_CTRL_DIV256) -#elif TIMER_INTERVAL >= 0x10000 -#define TIMER_RELOAD (TIMER_INTERVAL >> 4) /* Divide by 16 */ -#define TIMER_DIVISOR (TIMER_CTRL_DIV16) -#else -#define TIMER_RELOAD (TIMER_INTERVAL) -#define TIMER_DIVISOR (TIMER_CTRL_DIV1) -#endif +#define TIMER_RELOAD (TICKS_PER_uSEC * mSEC_10) static void __iomem *clksrc_base; -- cgit v0.10.2 From 4ce1755275c13eb0de90fe23c950bce5e81e680f Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 15 Jan 2010 18:19:56 +0000 Subject: ARM: Realview/Versatile: don't use magic numbers for timer frequency Signed-off-by: Russell King diff --git a/arch/arm/plat-versatile/timer-sp.c b/arch/arm/plat-versatile/timer-sp.c index d1dbef5..fb0d1c2 100644 --- a/arch/arm/plat-versatile/timer-sp.c +++ b/arch/arm/plat-versatile/timer-sp.c @@ -26,15 +26,13 @@ #include -#include - #include /* - * How long is the timer interval? + * These timers are currently always setup to be clocked at 1MHz. */ -#define TIMER_RELOAD (TICKS_PER_uSEC * mSEC_10) - +#define TIMER_FREQ_KHZ (1000) +#define TIMER_RELOAD (TIMER_FREQ_KHZ * 1000 / HZ) static void __iomem *clksrc_base; @@ -65,7 +63,7 @@ void __init sp804_clocksource_init(void __iomem *base) writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC, clksrc_base + TIMER_CTRL); - cs->mult = clocksource_khz2mult(1000, cs->shift); + cs->mult = clocksource_khz2mult(TIMER_FREQ_KHZ, cs->shift); clocksource_register(cs); } @@ -149,7 +147,7 @@ void __init sp804_clockevents_init(void __iomem *base, unsigned int timer_irq) clkevt_base = base; evt->irq = timer_irq; - evt->mult = div_sc(1000000, NSEC_PER_SEC, evt->shift); + evt->mult = div_sc(TIMER_FREQ_KHZ, NSEC_PER_MSEC, evt->shift); evt->max_delta_ns = clockevent_delta2ns(0xffffffff, evt); evt->min_delta_ns = clockevent_delta2ns(0xf, evt); -- cgit v0.10.2 From e606a940cba4083b9c382c17251636856e03346b Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 17 Jan 2010 19:27:09 +0000 Subject: ARM: Realview/Versatile/Integrator: remove unused definitions from platform.h Signed-off-by: Russell King diff --git a/arch/arm/mach-integrator/include/mach/platform.h b/arch/arm/mach-integrator/include/mach/platform.h index 0e172e4..5e6ea5c 100644 --- a/arch/arm/mach-integrator/include/mach/platform.h +++ b/arch/arm/mach-integrator/include/mach/platform.h @@ -23,9 +23,6 @@ * * Integrator address map * - * NOTE: This is a multi-hosted header file for use with uHAL and - * supported debuggers. - * * ***********************************************************************/ #ifndef __address_h @@ -330,20 +327,6 @@ */ #define PHYS_PCI_V3_BASE 0x62000000 -#define PCI_DRAMSIZE INTEGRATOR_SSRAM_SIZE - -/* 'export' these to UHAL */ -#define UHAL_PCI_IO PCI_IO_BASE -#define UHAL_PCI_MEM PCI_MEM_BASE -#define UHAL_PCI_ALLOC_IO_BASE 0x00004000 -#define UHAL_PCI_ALLOC_MEM_BASE PCI_MEM_BASE -#define UHAL_PCI_MAX_SLOT 20 - -/* ======================================================================== - * Start of uHAL definitions - * ======================================================================== - */ - /* ------------------------------------------------------------------------ * Integrator Interrupt Controllers * ------------------------------------------------------------------------ @@ -391,7 +374,7 @@ */ /* ------------------------------------------------------------------------ - * LED's - The header LED is not accessible via the uHAL API + * LED's * ------------------------------------------------------------------------ * */ @@ -404,34 +387,18 @@ #define LED_BANK INTEGRATOR_DBG_LEDS /* - * Memory definitions - run uHAL out of SSRAM. - * - */ -#define uHAL_MEMORY_SIZE INTEGRATOR_SSRAM_SIZE - -/* - * Clean base - dummy - * - */ -#define CLEAN_BASE INTEGRATOR_BOOT_ROM_HI - -/* * Timer definitions * * Only use timer 1 & 2 * (both run at 24MHz and will need the clock divider set to 16). * - * Timer 0 runs at bus frequency and therefore could vary and currently - * uHAL can't handle that. - * + * Timer 0 runs at bus frequency */ #define INTEGRATOR_TIMER0_BASE INTEGRATOR_CT_BASE #define INTEGRATOR_TIMER1_BASE (INTEGRATOR_CT_BASE + 0x100) #define INTEGRATOR_TIMER2_BASE (INTEGRATOR_CT_BASE + 0x200) -#define MAX_TIMER 2 -#define MAX_PERIOD 699050 #define TICKS_PER_uSEC 24 /* @@ -439,14 +406,9 @@ * */ #define mSEC_1 1000 -#define mSEC_5 (mSEC_1 * 5) #define mSEC_10 (mSEC_1 * 10) -#define mSEC_25 (mSEC_1 * 25) -#define SEC_1 (mSEC_1 * 1000) #define INTEGRATOR_CSR_BASE 0x10000000 #define INTEGRATOR_CSR_SIZE 0x10000000 #endif - -/* END */ diff --git a/arch/arm/mach-realview/include/mach/platform.h b/arch/arm/mach-realview/include/mach/platform.h index 86c0c44..1b77a27 100644 --- a/arch/arm/mach-realview/include/mach/platform.h +++ b/arch/arm/mach-realview/include/mach/platform.h @@ -231,12 +231,6 @@ #define REALVIEW_INTREG_OFFSET 0x8 /* Interrupt control */ #define REALVIEW_DECODE_OFFSET 0xC /* Fitted logic modules */ -/* - * Clean base - dummy - * - */ -#define CLEAN_BASE REALVIEW_BOOT_ROM_HI - /* * System controller bit assignment */ @@ -249,20 +243,6 @@ #define REALVIEW_TIMER4_EnSel 21 -#define MAX_TIMER 2 -#define MAX_PERIOD 699050 -#define TICKS_PER_uSEC 1 - -/* - * These are useconds NOT ticks. - * - */ -#define mSEC_1 1000 -#define mSEC_5 (mSEC_1 * 5) -#define mSEC_10 (mSEC_1 * 10) -#define mSEC_25 (mSEC_1 * 25) -#define SEC_1 (mSEC_1 * 1000) - #define REALVIEW_CSR_BASE 0x10000000 #define REALVIEW_CSR_SIZE 0x10000000 diff --git a/arch/arm/mach-versatile/include/mach/platform.h b/arch/arm/mach-versatile/include/mach/platform.h index 8320739..ec08740 100644 --- a/arch/arm/mach-versatile/include/mach/platform.h +++ b/arch/arm/mach-versatile/include/mach/platform.h @@ -205,7 +205,7 @@ #define VERSATILE_CLCD_BASE 0x10120000 /* CLCD */ #define VERSATILE_DMAC_BASE 0x10130000 /* DMA controller */ #define VERSATILE_VIC_BASE 0x10140000 /* Vectored interrupt controller */ -#define VERSATILE_PERIPH_BASE 0x10150000 /* off-chip peripherals alias from */ +#define VERSATILE_PERIPH_BASE 0x10150000 /* off-chip peripherals alias from */ /* 0x10000000 - 0x100FFFFF */ #define VERSATILE_AHBM_BASE 0x101D0000 /* AHB monitor */ #define VERSATILE_SCTL_BASE 0x101E0000 /* System controller */ @@ -213,7 +213,7 @@ #define VERSATILE_TIMER0_1_BASE 0x101E2000 /* Timer 0 and 1 */ #define VERSATILE_TIMER2_3_BASE 0x101E3000 /* Timer 2 and 3 */ #define VERSATILE_GPIO0_BASE 0x101E4000 /* GPIO port 0 */ -#define VERSATILE_GPIO1_BASE 0x101E5000 /* GPIO port 1 */ +#define VERSATILE_GPIO1_BASE 0x101E5000 /* GPIO port 1 */ #define VERSATILE_GPIO2_BASE 0x101E6000 /* GPIO port 2 */ #define VERSATILE_GPIO3_BASE 0x101E7000 /* GPIO port 3 */ #define VERSATILE_RTC_BASE 0x101E8000 /* Real Time Clock */ @@ -379,12 +379,6 @@ #define SIC_INT_PCI3 30 -/* - * Clean base - dummy - * - */ -#define CLEAN_BASE VERSATILE_BOOT_ROM_HI - /* * System controller bit assignment */ @@ -397,20 +391,6 @@ #define VERSATILE_TIMER4_EnSel 21 -#define MAX_TIMER 2 -#define MAX_PERIOD 699050 -#define TICKS_PER_uSEC 1 - -/* - * These are useconds NOT ticks. - * - */ -#define mSEC_1 1000 -#define mSEC_5 (mSEC_1 * 5) -#define mSEC_10 (mSEC_1 * 10) -#define mSEC_25 (mSEC_1 * 25) -#define SEC_1 (mSEC_1 * 1000) - #define VERSATILE_CSR_BASE 0x10000000 #define VERSATILE_CSR_SIZE 0x10000000 @@ -432,5 +412,3 @@ #endif #endif - -/* END */ -- cgit v0.10.2 From 5a46334ac688fb538b335599e1ff3b6cfaf769e9 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 16 Jan 2010 23:52:12 +0000 Subject: ARM: Integrator: convert Integrator/CP to use SP804 timer support The Integrator/CP board has SP804-compatible timer modules, so use the SP804-compatible code from Versatile and Realview. Signed-off-by: Russell King diff --git a/arch/arm/mach-integrator/Kconfig b/arch/arm/mach-integrator/Kconfig index df97d16..27db275 100644 --- a/arch/arm/mach-integrator/Kconfig +++ b/arch/arm/mach-integrator/Kconfig @@ -11,6 +11,7 @@ config ARCH_INTEGRATOR_AP config ARCH_INTEGRATOR_CP bool "Support Integrator/CP platform" select ARCH_CINTEGRATOR + select ARM_TIMER_SP804 help Include support for the ARM(R) Integrator CP platform. diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index a9ab8fd..a7575c4 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -40,6 +41,8 @@ #include #include +#include + #include "common.h" #define INTCP_PA_FLASH_BASE 0x24000000 @@ -569,11 +572,18 @@ static void __init intcp_init(void) } } -#define TIMER_CTRL_IE (1 << 5) /* Interrupt Enable */ +#define TIMER0_VA_BASE __io_address(INTEGRATOR_TIMER0_BASE) +#define TIMER1_VA_BASE __io_address(INTEGRATOR_TIMER1_BASE) +#define TIMER2_VA_BASE __io_address(INTEGRATOR_TIMER2_BASE) static void __init intcp_timer_init(void) { - integrator_time_init(1000, TIMER_CTRL_IE); + writel(0, TIMER0_VA_BASE + TIMER_CTRL); + writel(0, TIMER1_VA_BASE + TIMER_CTRL); + writel(0, TIMER2_VA_BASE + TIMER_CTRL); + + sp804_clocksource_init(TIMER2_VA_BASE); + sp804_clockevents_init(TIMER1_VA_BASE, IRQ_TIMERINT1); } static struct sys_timer cp_timer = { -- cgit v0.10.2 From 6be4826e37122b25cb10b215fc84c3a0b1fe1402 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 17 Jan 2010 16:20:56 +0000 Subject: ARM: Integrator: move 16-bit timer support to Integrator/AP Only Integrator/AP has 16-bit timers, so move the support into the Integrator/AP specific support files. Signed-off-by: Russell King diff --git a/arch/arm/mach-integrator/common.h b/arch/arm/mach-integrator/common.h deleted file mode 100644 index cdbe710..0000000 --- a/arch/arm/mach-integrator/common.h +++ /dev/null @@ -1 +0,0 @@ -extern void integrator_time_init(u32, unsigned int); diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c index ac2b0c5..b02cfc0 100644 --- a/arch/arm/mach-integrator/core.c +++ b/arch/arm/mach-integrator/core.c @@ -19,8 +19,6 @@ #include #include #include -#include -#include #include #include @@ -28,14 +26,11 @@ #include #include #include -#include #include #include #include #include -#include "common.h" - static struct amba_pl010_data integrator_uart_data; static struct amba_device rtc_device = { @@ -220,155 +215,3 @@ void cm_control(u32 mask, u32 set) } EXPORT_SYMBOL(cm_control); - -/* - * Where is the timer (VA)? - */ -#define TIMER0_VA_BASE IO_ADDRESS(INTEGRATOR_TIMER0_BASE) -#define TIMER1_VA_BASE IO_ADDRESS(INTEGRATOR_TIMER1_BASE) -#define TIMER2_VA_BASE IO_ADDRESS(INTEGRATOR_TIMER2_BASE) - -/* - * How long is the timer interval? - */ -#define TIMER_INTERVAL (TICKS_PER_uSEC * mSEC_10) -#if TIMER_INTERVAL >= 0x100000 -#define TICKS2USECS(x) (256 * (x) / TICKS_PER_uSEC) -#elif TIMER_INTERVAL >= 0x10000 -#define TICKS2USECS(x) (16 * (x) / TICKS_PER_uSEC) -#else -#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC) -#endif - -static unsigned long timer_reload; - -static void __iomem * const clksrc_base = (void __iomem *)TIMER2_VA_BASE; - -static cycle_t timersp_read(struct clocksource *cs) -{ - return ~(readl(clksrc_base + TIMER_VALUE) & 0xffff); -} - -static struct clocksource clocksource_timersp = { - .name = "timer2", - .rating = 200, - .read = timersp_read, - .mask = CLOCKSOURCE_MASK(16), - .shift = 16, - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - -static void integrator_clocksource_init(u32 khz) -{ - struct clocksource *cs = &clocksource_timersp; - void __iomem *base = clksrc_base; - u32 ctrl = TIMER_CTRL_ENABLE; - - if (khz >= 1500) { - khz /= 16; - ctrl = TIMER_CTRL_DIV16; - } - - writel(ctrl, base + TIMER_CTRL); - writel(0xffff, base + TIMER_LOAD); - - cs->mult = clocksource_khz2mult(khz, cs->shift); - clocksource_register(cs); -} - -static void __iomem * const clkevt_base = (void __iomem *)TIMER1_VA_BASE; - -/* - * IRQ handler for the timer - */ -static irqreturn_t integrator_timer_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *evt = dev_id; - - /* clear the interrupt */ - writel(1, clkevt_base + TIMER_INTCLR); - - evt->event_handler(evt); - - return IRQ_HANDLED; -} - -static void clkevt_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) -{ - u32 ctrl = readl(clkevt_base + TIMER_CTRL) & ~TIMER_CTRL_ENABLE; - - BUG_ON(mode == CLOCK_EVT_MODE_ONESHOT); - - if (mode == CLOCK_EVT_MODE_PERIODIC) { - writel(ctrl, clkevt_base + TIMER_CTRL); - writel(timer_reload, clkevt_base + TIMER_LOAD); - ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE; - } - - writel(ctrl, clkevt_base + TIMER_CTRL); -} - -static int clkevt_set_next_event(unsigned long next, struct clock_event_device *evt) -{ - unsigned long ctrl = readl(clkevt_base + TIMER_CTRL); - - writel(ctrl & ~TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL); - writel(next, clkevt_base + TIMER_LOAD); - writel(ctrl | TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL); - - return 0; -} - -static struct clock_event_device integrator_clockevent = { - .name = "timer1", - .shift = 34, - .features = CLOCK_EVT_FEAT_PERIODIC, - .set_mode = clkevt_set_mode, - .set_next_event = clkevt_set_next_event, - .rating = 300, - .cpumask = cpu_all_mask, -}; - -static struct irqaction integrator_timer_irq = { - .name = "timer", - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, - .handler = integrator_timer_interrupt, - .dev_id = &integrator_clockevent, -}; - -static void integrator_clockevent_init(u32 khz, unsigned int ctrl) -{ - struct clock_event_device *evt = &integrator_clockevent; - - if (khz * 1000 > 0x100000 * HZ) { - khz /= 256; - ctrl |= TIMER_CTRL_DIV256; - } else if (khz * 1000 > 0x10000 * HZ) { - khz /= 16; - ctrl |= TIMER_CTRL_DIV16; - } - - timer_reload = khz * 1000 / HZ; - writel(ctrl, clkevt_base + TIMER_CTRL); - - evt->irq = IRQ_TIMERINT1; - evt->mult = div_sc(khz, NSEC_PER_MSEC, evt->shift); - evt->max_delta_ns = clockevent_delta2ns(0xffff, evt); - evt->min_delta_ns = clockevent_delta2ns(0xf, evt); - - setup_irq(IRQ_TIMERINT1, &integrator_timer_irq); - clockevents_register_device(evt); -} - -/* - * Set up timer(s). - */ -void __init integrator_time_init(u32 khz, unsigned int ctrl) -{ - writel(0, TIMER0_VA_BASE + TIMER_CTRL); - writel(0, TIMER1_VA_BASE + TIMER_CTRL); - writel(0, TIMER2_VA_BASE + TIMER_CTRL); - - integrator_clocksource_init(khz); - integrator_clockevent_init(khz, ctrl); -} diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c index c89b231..227cf4d 100644 --- a/arch/arm/mach-integrator/integrator_ap.c +++ b/arch/arm/mach-integrator/integrator_ap.c @@ -27,10 +27,14 @@ #include #include #include +#include +#include +#include #include #include #include +#include #include #include #include /* HZ */ @@ -44,8 +48,6 @@ #include #include -#include "common.h" - /* * All IO addresses are mapped onto VA 0xFFFx.xxxx, where x.xxxx * is the (PA >> 12). @@ -335,9 +337,159 @@ static void __init ap_init(void) } } +/* + * Where is the timer (VA)? + */ +#define TIMER0_VA_BASE IO_ADDRESS(INTEGRATOR_TIMER0_BASE) +#define TIMER1_VA_BASE IO_ADDRESS(INTEGRATOR_TIMER1_BASE) +#define TIMER2_VA_BASE IO_ADDRESS(INTEGRATOR_TIMER2_BASE) + +/* + * How long is the timer interval? + */ +#define TIMER_INTERVAL (TICKS_PER_uSEC * mSEC_10) +#if TIMER_INTERVAL >= 0x100000 +#define TICKS2USECS(x) (256 * (x) / TICKS_PER_uSEC) +#elif TIMER_INTERVAL >= 0x10000 +#define TICKS2USECS(x) (16 * (x) / TICKS_PER_uSEC) +#else +#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC) +#endif + +static unsigned long timer_reload; + +static void __iomem * const clksrc_base = (void __iomem *)TIMER2_VA_BASE; + +static cycle_t timersp_read(struct clocksource *cs) +{ + return ~(readl(clksrc_base + TIMER_VALUE) & 0xffff); +} + +static struct clocksource clocksource_timersp = { + .name = "timer2", + .rating = 200, + .read = timersp_read, + .mask = CLOCKSOURCE_MASK(16), + .shift = 16, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static void integrator_clocksource_init(u32 khz) +{ + struct clocksource *cs = &clocksource_timersp; + void __iomem *base = clksrc_base; + u32 ctrl = TIMER_CTRL_ENABLE; + + if (khz >= 1500) { + khz /= 16; + ctrl = TIMER_CTRL_DIV16; + } + + writel(ctrl, base + TIMER_CTRL); + writel(0xffff, base + TIMER_LOAD); + + cs->mult = clocksource_khz2mult(khz, cs->shift); + clocksource_register(cs); +} + +static void __iomem * const clkevt_base = (void __iomem *)TIMER1_VA_BASE; + +/* + * IRQ handler for the timer + */ +static irqreturn_t integrator_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = dev_id; + + /* clear the interrupt */ + writel(1, clkevt_base + TIMER_INTCLR); + + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +static void clkevt_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) +{ + u32 ctrl = readl(clkevt_base + TIMER_CTRL) & ~TIMER_CTRL_ENABLE; + + BUG_ON(mode == CLOCK_EVT_MODE_ONESHOT); + + if (mode == CLOCK_EVT_MODE_PERIODIC) { + writel(ctrl, clkevt_base + TIMER_CTRL); + writel(timer_reload, clkevt_base + TIMER_LOAD); + ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE; + } + + writel(ctrl, clkevt_base + TIMER_CTRL); +} + +static int clkevt_set_next_event(unsigned long next, struct clock_event_device *evt) +{ + unsigned long ctrl = readl(clkevt_base + TIMER_CTRL); + + writel(ctrl & ~TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL); + writel(next, clkevt_base + TIMER_LOAD); + writel(ctrl | TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL); + + return 0; +} + +static struct clock_event_device integrator_clockevent = { + .name = "timer1", + .shift = 34, + .features = CLOCK_EVT_FEAT_PERIODIC, + .set_mode = clkevt_set_mode, + .set_next_event = clkevt_set_next_event, + .rating = 300, + .cpumask = cpu_all_mask, +}; + +static struct irqaction integrator_timer_irq = { + .name = "timer", + .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .handler = integrator_timer_interrupt, + .dev_id = &integrator_clockevent, +}; + +static void integrator_clockevent_init(u32 khz) +{ + struct clock_event_device *evt = &integrator_clockevent; + unsigned int ctrl = 0; + + if (khz * 1000 > 0x100000 * HZ) { + khz /= 256; + ctrl |= TIMER_CTRL_DIV256; + } else if (khz * 1000 > 0x10000 * HZ) { + khz /= 16; + ctrl |= TIMER_CTRL_DIV16; + } + + timer_reload = khz * 1000 / HZ; + writel(ctrl, clkevt_base + TIMER_CTRL); + + evt->irq = IRQ_TIMERINT1; + evt->mult = div_sc(khz, NSEC_PER_MSEC, evt->shift); + evt->max_delta_ns = clockevent_delta2ns(0xffff, evt); + evt->min_delta_ns = clockevent_delta2ns(0xf, evt); + + setup_irq(IRQ_TIMERINT1, &integrator_timer_irq); + clockevents_register_device(evt); +} + +/* + * Set up timer(s). + */ static void __init ap_init_timer(void) { - integrator_time_init(TICKS_PER_uSEC * 1000, 0); + u32 khz = TICKS_PER_uSEC * 1000; + + writel(0, TIMER0_VA_BASE + TIMER_CTRL); + writel(0, TIMER1_VA_BASE + TIMER_CTRL); + writel(0, TIMER2_VA_BASE + TIMER_CTRL); + + integrator_clocksource_init(khz); + integrator_clockevent_init(khz); } static struct sys_timer ap_timer = { diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index a7575c4..5a5a8c1 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -43,8 +43,6 @@ #include -#include "common.h" - #define INTCP_PA_FLASH_BASE 0x24000000 #define INTCP_FLASH_SIZE SZ_32M -- cgit v0.10.2 From f5fc00826d1e60af0e22cb9f65b933d823a8ed84 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 14 Jan 2010 20:07:35 +0000 Subject: ARM: Realview/Versatile: separate out common sched_clock() Provide a common sched_clock() implementation for Versatile and Realview. Signed-off-by: Russell King diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index 80b8142..f97f001 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c @@ -53,8 +53,6 @@ #include "core.h" -#define REALVIEW_REFCOUNTER (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_24MHz_OFFSET) - /* used by entry-macro.S and platsmp.c */ void __iomem *gic_cpu_base_addr; @@ -77,20 +75,6 @@ void __init realview_adjust_zones(int node, unsigned long *size, } #endif -/* - * This is the RealView sched_clock implementation. This has - * a resolution of 41.7ns, and a maximum value of about 179s. - */ -unsigned long long sched_clock(void) -{ - unsigned long long v; - - v = (unsigned long long)readl(REALVIEW_REFCOUNTER) * 125; - do_div(v, 3); - - return v; -} - #define REALVIEW_FLASHCTRL (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_FLASH_OFFSET) diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index b68ddd3..490fc75 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include @@ -227,27 +226,6 @@ void __init versatile_map_io(void) iotable_init(versatile_io_desc, ARRAY_SIZE(versatile_io_desc)); } -#define VERSATILE_REFCOUNTER (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_24MHz_OFFSET) - -/* - * This is the Versatile sched_clock implementation. This has - * a resolution of 41.7ns, and a maximum value of about 35583 days. - * - * The return value is guaranteed to be monotonic in that range as - * long as there is always less than 89 seconds between successive - * calls to this function. - */ -unsigned long long sched_clock(void) -{ - unsigned long long v = cnt32_to_63(readl(VERSATILE_REFCOUNTER)); - - /* the <<1 gets rid of the cnt_32_to_63 top bit saving on a bic insn */ - v *= 125<<1; - do_div(v, 3<<1); - - return v; -} - #define VERSATILE_FLASHCTRL (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_FLASH_OFFSET) diff --git a/arch/arm/plat-versatile/Makefile b/arch/arm/plat-versatile/Makefile index 334d2f1..9b1a668 100644 --- a/arch/arm/plat-versatile/Makefile +++ b/arch/arm/plat-versatile/Makefile @@ -1,2 +1,4 @@ obj-y := clock.o obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o +obj-$(CONFIG_ARCH_REALVIEW) += sched-clock.o +obj-$(CONFIG_ARCH_VERSATILE) += sched-clock.o diff --git a/arch/arm/plat-versatile/sched-clock.c b/arch/arm/plat-versatile/sched-clock.c new file mode 100644 index 0000000..9768cf7 --- /dev/null +++ b/arch/arm/plat-versatile/sched-clock.c @@ -0,0 +1,53 @@ +/* + * linux/arch/arm/plat-versatile/sched-clock.c + * + * Copyright (C) 1999 - 2003 ARM Limited + * Copyright (C) 2000 Deep Blue Solutions Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include + +#include +#include + +#ifdef VERSATILE_SYS_BASE +#define REFCOUNTER (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_24MHz_OFFSET) +#endif + +#ifdef REALVIEW_SYS_BASE +#define REFCOUNTER (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_24MHz_OFFSET) +#endif + +/* + * This is the Realview and Versatile sched_clock implementation. This + * has a resolution of 41.7ns, and a maximum value of about 35583 days. + * + * The return value is guaranteed to be monotonic in that range as + * long as there is always less than 89 seconds between successive + * calls to this function. + */ +unsigned long long sched_clock(void) +{ + unsigned long long v = cnt32_to_63(readl(REFCOUNTER)); + + /* the <<1 gets rid of the cnt_32_to_63 top bit saving on a bic insn */ + v *= 125<<1; + do_div(v, 3<<1); + + return v; +} -- cgit v0.10.2 From d1914c7e75cff736e2c2dac13ad2fe20c2567e68 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 14 Jan 2010 20:09:34 +0000 Subject: ARM: Make Integrator/Versatile/Reaview VCO code similar Signed-off-by: Russell King diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c index 3e21102..2f9de62 100644 --- a/arch/arm/mach-integrator/impd1.c +++ b/arch/arm/mach-integrator/impd1.c @@ -55,20 +55,10 @@ static const struct icst_params impd1_vco_params = { static void impd1_setvco(struct clk *clk, struct icst_vco vco) { struct impd1_module *impd1 = clk->data; - int vconr = clk - impd1->vcos; - u32 val; - - val = vco.v | (vco.r << 9) | (vco.s << 16); + u32 val = vco.v | (vco.r << 9) | (vco.s << 16); writel(0xa05f, impd1->base + IMPD1_LOCK); - switch (vconr) { - case 0: - writel(val, impd1->base + IMPD1_OSC1); - break; - case 1: - writel(val, impd1->base + IMPD1_OSC2); - break; - } + writel(val, clk->vcoreg); writel(0, impd1->base + IMPD1_LOCK); #ifdef DEBUG @@ -381,6 +371,8 @@ static int impd1_probe(struct lm_device *dev) impd1->vcos[i].data = impd1, impd1->vcos[i].setvco = impd1_setvco; } + impd1->vcos[0].vcoreg = impd1->base + IMPD1_OSC1; + impd1->vcos[1].vcoreg = impd1->base + IMPD1_OSC2; impd1->clks[0] = clkdev_alloc(&impd1->vcos[0], NULL, "lm%x:01000", dev->id); diff --git a/arch/arm/mach-integrator/include/mach/clkdev.h b/arch/arm/mach-integrator/include/mach/clkdev.h index 89ea938..ed67e8e 100644 --- a/arch/arm/mach-integrator/include/mach/clkdev.h +++ b/arch/arm/mach-integrator/include/mach/clkdev.h @@ -8,8 +8,9 @@ struct clk { unsigned long rate; struct module *owner; const struct icst_params *params; - void *data; + void __iomem *vcoreg; void (*setvco)(struct clk *, struct icst_vco vco); + void *data; }; static inline int __clk_get(struct clk *clk) diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 5a5a8c1..59085800 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -266,8 +266,8 @@ static void __init intcp_init_irq(void) /* * Clock handling */ -#define CM_LOCK IO_ADDRESS(INTEGRATOR_HDR_LOCK) -#define CM_AUXOSC IO_ADDRESS(INTEGRATOR_HDR_BASE + 0x1c) +#define CM_LOCK (__io_address(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_LOCK_OFFSET) +#define CM_AUXOSC (__io_address(INTEGRATOR_HDR_BASE)+0x1c) static const struct icst_params cp_auxvco_params = { .ref = 24000000, @@ -285,16 +285,17 @@ static void cp_auxvco_set(struct clk *clk, struct icst_vco vco) { u32 val; - val = readl(CM_AUXOSC) & ~0x7ffff; + val = readl(clk->vcoreg) & ~0x7ffff; val |= vco.v | (vco.r << 9) | (vco.s << 16); writel(0xa05f, CM_LOCK); - writel(val, CM_AUXOSC); + writel(val, clk->vcoreg); writel(0, CM_LOCK); } static struct clk cp_auxclk = { .params = &cp_auxvco_params, + .vcoreg = CM_AUXOSC, .setvco = cp_auxvco_set, }; diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index f97f001..043b93b 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c @@ -271,19 +271,13 @@ static const struct icst_params realview_oscvco_params = { static void realview_oscvco_set(struct clk *clk, struct icst_vco vco) { void __iomem *sys_lock = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_LOCK_OFFSET; - void __iomem *sys_osc; u32 val; - if (machine_is_realview_pb1176()) - sys_osc = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_OSC0_OFFSET; - else - sys_osc = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_OSC4_OFFSET; - - val = readl(sys_osc) & ~0x7ffff; + val = readl(clk->vcoreg) & ~0x7ffff; val |= vco.v | (vco.r << 9) | (vco.s << 16); writel(0xa05f, sys_lock); - writel(val, sys_osc); + writel(val, clk->vcoreg); writel(0, sys_lock); } @@ -332,7 +326,13 @@ static struct clk_lookup lookups[] = { static int __init clk_init(void) { + if (machine_is_realview_pb1176()) + oscvco_clk.vcoreg = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_OSC0_OFFSET; + else + oscvco_clk.vcoreg = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_OSC4_OFFSET; + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); + return 0; } arch_initcall(clk_init); diff --git a/arch/arm/mach-realview/include/mach/clkdev.h b/arch/arm/mach-realview/include/mach/clkdev.h index fefe467..baea03c 100644 --- a/arch/arm/mach-realview/include/mach/clkdev.h +++ b/arch/arm/mach-realview/include/mach/clkdev.h @@ -6,7 +6,7 @@ struct clk { unsigned long rate; const struct icst_params *params; - u32 oscoff; + void __iomem *vcoreg; void (*setvco)(struct clk *, struct icst_vco vco); }; diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index 490fc75..957bbde 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -370,21 +370,19 @@ static const struct icst_params versatile_oscvco_params = { static void versatile_oscvco_set(struct clk *clk, struct icst_vco vco) { - void __iomem *sys = __io_address(VERSATILE_SYS_BASE); - void __iomem *sys_lock = sys + VERSATILE_SYS_LOCK_OFFSET; + void __iomem *sys_lock = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_LOCK_OFFSET; u32 val; - val = readl(sys + clk->oscoff) & ~0x7ffff; + val = readl(clk->vcoreg) & ~0x7ffff; val |= vco.v | (vco.r << 9) | (vco.s << 16); writel(0xa05f, sys_lock); - writel(val, sys + clk->oscoff); + writel(val, clk->vcoreg); writel(0, sys_lock); } static struct clk osc4_clk = { .params = &versatile_oscvco_params, - .oscoff = VERSATILE_SYS_OSCCLCD_OFFSET, .setvco = versatile_oscvco_set, }; @@ -831,6 +829,8 @@ void __init versatile_init(void) { int i; + osc4_clk.vcoreg = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_OSCCLCD_OFFSET; + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); platform_device_register(&versatile_flash_device); diff --git a/arch/arm/mach-versatile/include/mach/clkdev.h b/arch/arm/mach-versatile/include/mach/clkdev.h index fefe467..baea03c 100644 --- a/arch/arm/mach-versatile/include/mach/clkdev.h +++ b/arch/arm/mach-versatile/include/mach/clkdev.h @@ -6,7 +6,7 @@ struct clk { unsigned long rate; const struct icst_params *params; - u32 oscoff; + void __iomem *vcoreg; void (*setvco)(struct clk *, struct icst_vco vco); }; -- cgit v0.10.2 From 3081e43b97cb50a80ebd98ce4b60e4853ad38424 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Wed, 20 Jan 2010 19:06:26 +0100 Subject: ARM: 5890/1: Fix incorrect Realview board IRQs for L220 and PMU In anticipation of PMU support for Realview boards, the IRQs defined for some of these boards need updating. This patch removes incorrect L220 IRQ definitions, corrects incorrect PMU IRQs and adds any missing IRQs that are required. Signed-off-by: Will Deacon Signed-off-by: Russell King diff --git a/arch/arm/mach-realview/include/mach/irqs-pb1176.h b/arch/arm/mach-realview/include/mach/irqs-pb1176.h index 2410d4f..830055b 100644 --- a/arch/arm/mach-realview/include/mach/irqs-pb1176.h +++ b/arch/arm/mach-realview/include/mach/irqs-pb1176.h @@ -31,6 +31,7 @@ #define IRQ_DC1176_SOFTINT (IRQ_DC1176_GIC_START + 1) /* Software interrupt */ #define IRQ_DC1176_COMMRx (IRQ_DC1176_GIC_START + 2) /* Debug Comm Rx interrupt */ #define IRQ_DC1176_COMMTx (IRQ_DC1176_GIC_START + 3) /* Debug Comm Tx interrupt */ +#define IRQ_DC1176_CORE_PMU (IRQ_DC1176_GIC_START + 7) /* Core PMU interrupt */ #define IRQ_DC1176_TIMER0 (IRQ_DC1176_GIC_START + 8) /* Timer 0 */ #define IRQ_DC1176_TIMER1 (IRQ_DC1176_GIC_START + 9) /* Timer 1 */ #define IRQ_DC1176_TIMER2 (IRQ_DC1176_GIC_START + 10) /* Timer 2 */ diff --git a/arch/arm/mach-realview/include/mach/irqs-pba8.h b/arch/arm/mach-realview/include/mach/irqs-pba8.h index 86792a9..4a88a4e 100644 --- a/arch/arm/mach-realview/include/mach/irqs-pba8.h +++ b/arch/arm/mach-realview/include/mach/irqs-pba8.h @@ -23,12 +23,6 @@ #define IRQ_PBA8_GIC_START 32 -/* L220 -#define IRQ_PBA8_L220_EVENT (IRQ_PBA8_GIC_START + 29) -#define IRQ_PBA8_L220_SLAVE (IRQ_PBA8_GIC_START + 30) -#define IRQ_PBA8_L220_DECODE (IRQ_PBA8_GIC_START + 31) -*/ - /* * PB-A8 on-board gic irq sources */ @@ -65,6 +59,8 @@ #define IRQ_PBA8_TSPEN (IRQ_PBA8_GIC_START + 30) /* Touchscreen pen */ #define IRQ_PBA8_TSKPAD (IRQ_PBA8_GIC_START + 31) /* Touchscreen keypad */ +#define IRQ_PBA8_PMU (IRQ_PBA8_GIC_START + 47) /* Cortex-A8 PMU */ + /* ... */ #define IRQ_PBA8_PCI0 (IRQ_PBA8_GIC_START + 50) #define IRQ_PBA8_PCI1 (IRQ_PBA8_GIC_START + 51) diff --git a/arch/arm/mach-realview/include/mach/irqs-pbx.h b/arch/arm/mach-realview/include/mach/irqs-pbx.h index deaad43..206a300 100644 --- a/arch/arm/mach-realview/include/mach/irqs-pbx.h +++ b/arch/arm/mach-realview/include/mach/irqs-pbx.h @@ -22,12 +22,6 @@ #define IRQ_PBX_GIC_START 32 -/* L220 -#define IRQ_PBX_L220_EVENT (IRQ_PBX_GIC_START + 29) -#define IRQ_PBX_L220_SLAVE (IRQ_PBX_GIC_START + 30) -#define IRQ_PBX_L220_DECODE (IRQ_PBX_GIC_START + 31) -*/ - /* * PBX on-board gic irq sources */ @@ -77,10 +71,10 @@ #define IRQ_PBX_TIMER4_5 (IRQ_PBX_GIC_START + 41) /* Timer 0/1 (default timer) */ #define IRQ_PBX_TIMER6_7 (IRQ_PBX_GIC_START + 42) /* Timer 2/3 */ /* ... */ -#define IRQ_PBX_PMU_CPU3 (IRQ_PBX_GIC_START + 44) /* CPU PMU Interrupts */ -#define IRQ_PBX_PMU_CPU2 (IRQ_PBX_GIC_START + 45) -#define IRQ_PBX_PMU_CPU1 (IRQ_PBX_GIC_START + 46) -#define IRQ_PBX_PMU_CPU0 (IRQ_PBX_GIC_START + 47) +#define IRQ_PBX_PMU_CPU0 (IRQ_PBX_GIC_START + 44) /* CPU PMU Interrupts */ +#define IRQ_PBX_PMU_CPU1 (IRQ_PBX_GIC_START + 45) +#define IRQ_PBX_PMU_CPU2 (IRQ_PBX_GIC_START + 46) +#define IRQ_PBX_PMU_CPU3 (IRQ_PBX_GIC_START + 47) /* ... */ #define IRQ_PBX_PCI0 (IRQ_PBX_GIC_START + 50) -- cgit v0.10.2 From 9bf5b2ef673237e0e43161c56f70ac8bf24e43f9 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 1 Mar 2010 16:18:39 +0000 Subject: ARM: Indirect round/set_rate operations through clk structure Signed-off-by: Russell King diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c index 2f9de62..1a0ee93 100644 --- a/arch/arm/mach-integrator/impd1.c +++ b/arch/arm/mach-integrator/impd1.c @@ -71,6 +71,12 @@ static void impd1_setvco(struct clk *clk, struct icst_vco vco) #endif } +static const struct clk_ops impd1_clk_ops = { + .round = icst_clk_round, + .set = icst_clk_set, + .setvco = impd1_setvco, +}; + void impd1_tweak_control(struct device *dev, u32 mask, u32 val) { struct impd1_module *impd1 = dev_get_drvdata(dev); @@ -366,10 +372,10 @@ static int impd1_probe(struct lm_device *dev) (unsigned long)dev->resource.start); for (i = 0; i < ARRAY_SIZE(impd1->vcos); i++) { + impd1->vcos[i].ops = &impd1_clk_ops, impd1->vcos[i].owner = THIS_MODULE, impd1->vcos[i].params = &impd1_vco_params, - impd1->vcos[i].data = impd1, - impd1->vcos[i].setvco = impd1_setvco; + impd1->vcos[i].data = impd1; } impd1->vcos[0].vcoreg = impd1->base + IMPD1_OSC1; impd1->vcos[1].vcoreg = impd1->base + IMPD1_OSC2; diff --git a/arch/arm/mach-integrator/include/mach/clkdev.h b/arch/arm/mach-integrator/include/mach/clkdev.h index ed67e8e..bfe0767 100644 --- a/arch/arm/mach-integrator/include/mach/clkdev.h +++ b/arch/arm/mach-integrator/include/mach/clkdev.h @@ -2,14 +2,14 @@ #define __ASM_MACH_CLKDEV_H #include -#include +#include struct clk { unsigned long rate; + const struct clk_ops *ops; struct module *owner; const struct icst_params *params; void __iomem *vcoreg; - void (*setvco)(struct clk *, struct icst_vco vco); void *data; }; diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 59085800..54edb6b 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -293,10 +293,16 @@ static void cp_auxvco_set(struct clk *clk, struct icst_vco vco) writel(0, CM_LOCK); } +static const struct clk_ops cp_auxclk_ops = { + .round = icst_clk_round, + .set = icst_clk_set, + .setvco = cp_auxvco_set, +}; + static struct clk cp_auxclk = { + .ops = &cp_auxclk_ops, .params = &cp_auxvco_params, .vcoreg = CM_AUXOSC, - .setvco = cp_auxvco_set, }; static struct clk_lookup cp_lookups[] = { diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c index 043b93b..1b468bd 100644 --- a/arch/arm/mach-realview/core.c +++ b/arch/arm/mach-realview/core.c @@ -281,9 +281,15 @@ static void realview_oscvco_set(struct clk *clk, struct icst_vco vco) writel(0, sys_lock); } +static const struct clk_ops oscvco_clk_ops = { + .round = icst_clk_round, + .set = icst_clk_set, + .setvco = realview_oscvco_set, +}; + static struct clk oscvco_clk = { + .ops = &oscvco_clk_ops, .params = &realview_oscvco_params, - .setvco = realview_oscvco_set, }; /* diff --git a/arch/arm/mach-realview/include/mach/clkdev.h b/arch/arm/mach-realview/include/mach/clkdev.h index baea03c..e58d077 100644 --- a/arch/arm/mach-realview/include/mach/clkdev.h +++ b/arch/arm/mach-realview/include/mach/clkdev.h @@ -1,13 +1,13 @@ #ifndef __ASM_MACH_CLKDEV_H #define __ASM_MACH_CLKDEV_H -#include +#include struct clk { unsigned long rate; + const struct clk_ops *ops; const struct icst_params *params; void __iomem *vcoreg; - void (*setvco)(struct clk *, struct icst_vco vco); }; #define __clk_get(clk) ({ 1; }) diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index 957bbde..60baba6 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -381,9 +381,15 @@ static void versatile_oscvco_set(struct clk *clk, struct icst_vco vco) writel(0, sys_lock); } +static const struct clk_ops osc4_clk_ops = { + .round = icst_clk_round, + .set = icst_clk_set, + .setvco = versatile_oscvco_set, +}; + static struct clk osc4_clk = { + .ops = &osc4_clk_ops, .params = &versatile_oscvco_params, - .setvco = versatile_oscvco_set, }; /* diff --git a/arch/arm/mach-versatile/include/mach/clkdev.h b/arch/arm/mach-versatile/include/mach/clkdev.h index baea03c..e58d077 100644 --- a/arch/arm/mach-versatile/include/mach/clkdev.h +++ b/arch/arm/mach-versatile/include/mach/clkdev.h @@ -1,13 +1,13 @@ #ifndef __ASM_MACH_CLKDEV_H #define __ASM_MACH_CLKDEV_H -#include +#include struct clk { unsigned long rate; + const struct clk_ops *ops; const struct icst_params *params; void __iomem *vcoreg; - void (*setvco)(struct clk *, struct icst_vco vco); }; #define __clk_get(clk) ({ 1; }) diff --git a/arch/arm/plat-versatile/clock.c b/arch/arm/plat-versatile/clock.c index 2fa34de..5c8b656 100644 --- a/arch/arm/plat-versatile/clock.c +++ b/arch/arm/plat-versatile/clock.c @@ -37,24 +37,38 @@ EXPORT_SYMBOL(clk_get_rate); long clk_round_rate(struct clk *clk, unsigned long rate) { - struct icst_vco vco; - vco = icst_hz_to_vco(clk->params, rate); - return icst_hz(clk->params, vco); + long ret = -EIO; + if (clk->ops && clk->ops->round) + ret = clk->ops->round(clk, rate); + return ret; } EXPORT_SYMBOL(clk_round_rate); int clk_set_rate(struct clk *clk, unsigned long rate) { int ret = -EIO; - - if (clk->setvco) { - struct icst_vco vco; - - vco = icst_hz_to_vco(clk->params, rate); - clk->rate = icst_hz(clk->params, vco); - clk->setvco(clk, vco); - ret = 0; - } + if (clk->ops && clk->ops->set) + ret = clk->ops->set(clk, rate); return ret; } EXPORT_SYMBOL(clk_set_rate); + +long icst_clk_round(struct clk *clk, unsigned long rate) +{ + struct icst_vco vco; + vco = icst_hz_to_vco(clk->params, rate); + return icst_hz(clk->params, vco); +} +EXPORT_SYMBOL(icst_clk_round); + +int icst_clk_set(struct clk *clk, unsigned long rate) +{ + struct icst_vco vco; + + vco = icst_hz_to_vco(clk->params, rate); + clk->rate = icst_hz(clk->params, vco); + clk->ops->setvco(clk, vco); + + return 0; +} +EXPORT_SYMBOL(icst_clk_set); diff --git a/arch/arm/plat-versatile/include/plat/clock.h b/arch/arm/plat-versatile/include/plat/clock.h new file mode 100644 index 0000000..3cfb024 --- /dev/null +++ b/arch/arm/plat-versatile/include/plat/clock.h @@ -0,0 +1,15 @@ +#ifndef PLAT_CLOCK_H +#define PLAT_CLOCK_H + +#include + +struct clk_ops { + long (*round)(struct clk *, unsigned long); + int (*set)(struct clk *, unsigned long); + void (*setvco)(struct clk *, struct icst_vco); +}; + +int icst_clk_set(struct clk *, unsigned long); +long icst_clk_round(struct clk *, unsigned long); + +#endif -- cgit v0.10.2 From ceade897f31b8bb66f378cc35859fcfd0d46aaa2 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 11 Feb 2010 21:44:53 +0000 Subject: ARM: Add Versatile Express support Signed-off-by: Russell King diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 5534870..58080e1 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -276,6 +276,20 @@ config ARCH_VERSATILE help This enables support for ARM Ltd Versatile board. +config ARCH_VEXPRESS + bool "ARM Ltd. Versatile Express family" + select ARCH_WANT_OPTIONAL_GPIOLIB + select ARM_AMBA + select ARM_TIMER_SP804 + select COMMON_CLKDEV + select GENERIC_CLOCKEVENTS + select GENERIC_TIME + select HAVE_CLK + select ICST + select PLAT_VERSATILE + help + This enables support for the ARM Ltd Versatile Express boards. + config ARCH_AT91 bool "Atmel AT91" select GENERIC_GPIO @@ -926,6 +940,8 @@ source "arch/arm/mach-ux500/Kconfig" source "arch/arm/mach-versatile/Kconfig" +source "arch/arm/mach-vexpress/Kconfig" + source "arch/arm/mach-w90x900/Kconfig" # Definitions to make life easier diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 1962deb..67c92ef 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -175,6 +175,7 @@ machine-$(CONFIG_ARCH_STMP37XX) := stmp37xx machine-$(CONFIG_ARCH_U300) := u300 machine-$(CONFIG_ARCH_U8500) := ux500 machine-$(CONFIG_ARCH_VERSATILE) := versatile +machine-$(CONFIG_ARCH_VEXPRESS) := vexpress machine-$(CONFIG_ARCH_W90X900) := w90x900 machine-$(CONFIG_ARCH_NUC93X) := nuc93x machine-$(CONFIG_FOOTBRIDGE) := footbridge diff --git a/arch/arm/mach-vexpress/Kconfig b/arch/arm/mach-vexpress/Kconfig new file mode 100644 index 0000000..751858c --- /dev/null +++ b/arch/arm/mach-vexpress/Kconfig @@ -0,0 +1,4 @@ +menu "Versatile Express platform type" + depends on ARCH_VEXPRESS + +endmenu diff --git a/arch/arm/mach-vexpress/Makefile b/arch/arm/mach-vexpress/Makefile new file mode 100644 index 0000000..b47cf73 --- /dev/null +++ b/arch/arm/mach-vexpress/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for the linux kernel. +# + +obj-y := v2m.o diff --git a/arch/arm/mach-vexpress/Makefile.boot b/arch/arm/mach-vexpress/Makefile.boot new file mode 100644 index 0000000..07c2d9c --- /dev/null +++ b/arch/arm/mach-vexpress/Makefile.boot @@ -0,0 +1,3 @@ + zreladdr-y := 0x60008000 +params_phys-y := 0x60000100 +initrd_phys-y := 0x60800000 diff --git a/arch/arm/mach-vexpress/core.h b/arch/arm/mach-vexpress/core.h new file mode 100644 index 0000000..57dd95c --- /dev/null +++ b/arch/arm/mach-vexpress/core.h @@ -0,0 +1,26 @@ +#define __MMIO_P2V(x) (((x) & 0xfffff) | (((x) & 0x0f000000) >> 4) | 0xf8000000) +#define MMIO_P2V(x) ((void __iomem *)__MMIO_P2V(x)) + +#define AMBA_DEVICE(name,busid,base,plat) \ +struct amba_device name##_device = { \ + .dev = { \ + .coherent_dma_mask = ~0UL, \ + .init_name = busid, \ + .platform_data = plat, \ + }, \ + .res = { \ + .start = base, \ + .end = base + SZ_4K - 1, \ + .flags = IORESOURCE_MEM, \ + }, \ + .dma_mask = ~0UL, \ + .irq = IRQ_##base, \ + /* .dma = DMA_##base,*/ \ +} + +struct map_desc; + +void v2m_map_io(struct map_desc *tile, size_t num); +extern struct sys_timer v2m_timer; + +extern void __iomem *gic_cpu_base_addr; diff --git a/arch/arm/mach-vexpress/include/mach/clkdev.h b/arch/arm/mach-vexpress/include/mach/clkdev.h new file mode 100644 index 0000000..3f8307d --- /dev/null +++ b/arch/arm/mach-vexpress/include/mach/clkdev.h @@ -0,0 +1,15 @@ +#ifndef __ASM_MACH_CLKDEV_H +#define __ASM_MACH_CLKDEV_H + +#include + +struct clk { + const struct clk_ops *ops; + unsigned long rate; + const struct icst_params *params; +}; + +#define __clk_get(clk) ({ 1; }) +#define __clk_put(clk) do { } while (0) + +#endif diff --git a/arch/arm/mach-vexpress/include/mach/debug-macro.S b/arch/arm/mach-vexpress/include/mach/debug-macro.S new file mode 100644 index 0000000..5167e2a --- /dev/null +++ b/arch/arm/mach-vexpress/include/mach/debug-macro.S @@ -0,0 +1,23 @@ +/* arch/arm/mach-realview/include/mach/debug-macro.S + * + * Debugging macro include header + * + * Copyright (C) 1994-1999 Russell King + * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define DEBUG_LL_UART_OFFSET 0x00009000 + + .macro addruart,rx,tmp + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 @ MMU enabled? + moveq \rx, #0x10000000 + movne \rx, #0xf8000000 @ virtual base + orr \rx, \rx, #DEBUG_LL_UART_OFFSET + .endm + +#include diff --git a/arch/arm/mach-vexpress/include/mach/entry-macro.S b/arch/arm/mach-vexpress/include/mach/entry-macro.S new file mode 100644 index 0000000..20e9fb5 --- /dev/null +++ b/arch/arm/mach-vexpress/include/mach/entry-macro.S @@ -0,0 +1,67 @@ +#include + + .macro disable_fiq + .endm + + .macro get_irqnr_preamble, base, tmp + ldr \base, =gic_cpu_base_addr + ldr \base, [\base] + .endm + + .macro arch_ret_to_user, tmp1, tmp2 + .endm + + /* + * The interrupt numbering scheme is defined in the + * interrupt controller spec. To wit: + * + * Interrupts 0-15 are IPI + * 16-28 are reserved + * 29-31 are local. We allow 30 to be used for the watchdog. + * 32-1020 are global + * 1021-1022 are reserved + * 1023 is "spurious" (no interrupt) + * + * For now, we ignore all local interrupts so only return an interrupt if it's + * between 30 and 1020. The test_for_ipi routine below will pick up on IPIs. + * + * A simple read from the controller will tell us the number of the highest + * priority enabled interrupt. We then just need to check whether it is in the + * valid range for an IRQ (30-1020 inclusive). + */ + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + ldr \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */ + ldr \tmp, =1021 + bic \irqnr, \irqstat, #0x1c00 + cmp \irqnr, #29 + cmpcc \irqnr, \irqnr + cmpne \irqnr, \tmp + cmpcs \irqnr, \irqnr + .endm + + /* We assume that irqstat (the raw value of the IRQ acknowledge + * register) is preserved from the macro above. + * If there is an IPI, we immediately signal end of interrupt on the + * controller, since this requires the original irqstat value which + * we won't easily be able to recreate later. + */ + + .macro test_for_ipi, irqnr, irqstat, base, tmp + bic \irqnr, \irqstat, #0x1c00 + cmp \irqnr, #16 + strcc \irqstat, [\base, #GIC_CPU_EOI] + cmpcs \irqnr, \irqnr + .endm + + /* As above, this assumes that irqstat and base are preserved.. */ + + .macro test_for_ltirq, irqnr, irqstat, base, tmp + bic \irqnr, \irqstat, #0x1c00 + mov \tmp, #0 + cmp \irqnr, #29 + moveq \tmp, #1 + streq \irqstat, [\base, #GIC_CPU_EOI] + cmp \tmp, #0 + .endm + diff --git a/arch/arm/mach-vexpress/include/mach/hardware.h b/arch/arm/mach-vexpress/include/mach/hardware.h new file mode 100644 index 0000000..40a8c17 --- /dev/null +++ b/arch/arm/mach-vexpress/include/mach/hardware.h @@ -0,0 +1 @@ +/* empty */ diff --git a/arch/arm/mach-vexpress/include/mach/io.h b/arch/arm/mach-vexpress/include/mach/io.h new file mode 100644 index 0000000..748bb52 --- /dev/null +++ b/arch/arm/mach-vexpress/include/mach/io.h @@ -0,0 +1,28 @@ +/* + * arch/arm/mach-vexpress/include/mach/io.h + * + * Copyright (C) 2003 ARM Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_ARM_ARCH_IO_H +#define __ASM_ARM_ARCH_IO_H + +#define IO_SPACE_LIMIT 0xffffffff + +#define __io(a) __typesafe_io(a) +#define __mem_pci(a) (a) + +#endif diff --git a/arch/arm/mach-vexpress/include/mach/irqs.h b/arch/arm/mach-vexpress/include/mach/irqs.h new file mode 100644 index 0000000..7054cbf --- /dev/null +++ b/arch/arm/mach-vexpress/include/mach/irqs.h @@ -0,0 +1,4 @@ +#define IRQ_LOCALTIMER 29 +#define IRQ_LOCALWDOG 30 + +#define NR_IRQS 128 diff --git a/arch/arm/mach-vexpress/include/mach/memory.h b/arch/arm/mach-vexpress/include/mach/memory.h new file mode 100644 index 0000000..be28232 --- /dev/null +++ b/arch/arm/mach-vexpress/include/mach/memory.h @@ -0,0 +1,25 @@ +/* + * arch/arm/mach-vexpress/include/mach/memory.h + * + * Copyright (C) 2003 ARM Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_ARCH_MEMORY_H +#define __ASM_ARCH_MEMORY_H + +#define PHYS_OFFSET UL(0x60000000) + +#endif diff --git a/arch/arm/mach-vexpress/include/mach/motherboard.h b/arch/arm/mach-vexpress/include/mach/motherboard.h new file mode 100644 index 0000000..98a8ded --- /dev/null +++ b/arch/arm/mach-vexpress/include/mach/motherboard.h @@ -0,0 +1,121 @@ +#ifndef __MACH_MOTHERBOARD_H +#define __MACH_MOTHERBOARD_H + +/* + * Physical addresses, offset from V2M_PA_CS0-3 + */ +#define V2M_NOR0 (V2M_PA_CS0) +#define V2M_NOR1 (V2M_PA_CS1) +#define V2M_SRAM (V2M_PA_CS2) +#define V2M_VIDEO_SRAM (V2M_PA_CS3 + 0x00000000) +#define V2M_LAN9118 (V2M_PA_CS3 + 0x02000000) +#define V2M_ISP1761 (V2M_PA_CS3 + 0x03000000) + +/* + * Physical addresses, offset from V2M_PA_CS7 + */ +#define V2M_SYSREGS (V2M_PA_CS7 + 0x00000000) +#define V2M_SYSCTL (V2M_PA_CS7 + 0x00001000) +#define V2M_SERIAL_BUS_PCI (V2M_PA_CS7 + 0x00002000) + +#define V2M_AACI (V2M_PA_CS7 + 0x00004000) +#define V2M_MMCI (V2M_PA_CS7 + 0x00005000) +#define V2M_KMI0 (V2M_PA_CS7 + 0x00006000) +#define V2M_KMI1 (V2M_PA_CS7 + 0x00007000) + +#define V2M_UART0 (V2M_PA_CS7 + 0x00009000) +#define V2M_UART1 (V2M_PA_CS7 + 0x0000a000) +#define V2M_UART2 (V2M_PA_CS7 + 0x0000b000) +#define V2M_UART3 (V2M_PA_CS7 + 0x0000c000) + +#define V2M_WDT (V2M_PA_CS7 + 0x0000f000) + +#define V2M_TIMER01 (V2M_PA_CS7 + 0x00011000) +#define V2M_TIMER23 (V2M_PA_CS7 + 0x00012000) + +#define V2M_SERIAL_BUS_DVI (V2M_PA_CS7 + 0x00016000) +#define V2M_RTC (V2M_PA_CS7 + 0x00017000) + +#define V2M_CF (V2M_PA_CS7 + 0x0001a000) +#define V2M_CLCD (V2M_PA_CS7 + 0x0001f000) + +#define V2M_SYS_ID (V2M_SYSREGS + 0x000) +#define V2M_SYS_SW (V2M_SYSREGS + 0x004) +#define V2M_SYS_LED (V2M_SYSREGS + 0x008) +#define V2M_SYS_100HZ (V2M_SYSREGS + 0x024) +#define V2M_SYS_FLAGS (V2M_SYSREGS + 0x030) +#define V2M_SYS_FLAGSSET (V2M_SYSREGS + 0x030) +#define V2M_SYS_FLAGSCLR (V2M_SYSREGS + 0x034) +#define V2M_SYS_NVFLAGS (V2M_SYSREGS + 0x038) +#define V2M_SYS_NVFLAGSSET (V2M_SYSREGS + 0x038) +#define V2M_SYS_NVFLAGSCLR (V2M_SYSREGS + 0x03c) +#define V2M_SYS_MCI (V2M_SYSREGS + 0x048) +#define V2M_SYS_FLASH (V2M_SYSREGS + 0x03c) +#define V2M_SYS_CFGSW (V2M_SYSREGS + 0x058) +#define V2M_SYS_24MHZ (V2M_SYSREGS + 0x05c) +#define V2M_SYS_MISC (V2M_SYSREGS + 0x060) +#define V2M_SYS_DMA (V2M_SYSREGS + 0x064) +#define V2M_SYS_PROCID0 (V2M_SYSREGS + 0x084) +#define V2M_SYS_PROCID1 (V2M_SYSREGS + 0x088) +#define V2M_SYS_CFGDATA (V2M_SYSREGS + 0x0a0) +#define V2M_SYS_CFGCTRL (V2M_SYSREGS + 0x0a4) +#define V2M_SYS_CFGSTAT (V2M_SYSREGS + 0x0a8) + +#define V2M_TIMER0 (V2M_TIMER01 + 0x000) +#define V2M_TIMER1 (V2M_TIMER01 + 0x020) + +#define V2M_TIMER2 (V2M_TIMER23 + 0x000) +#define V2M_TIMER3 (V2M_TIMER23 + 0x020) + + +/* + * Interrupts. Those in {} are for AMBA devices + */ +#define IRQ_V2M_WDT { (32 + 0) } +#define IRQ_V2M_TIMER0 (32 + 2) +#define IRQ_V2M_TIMER1 (32 + 2) +#define IRQ_V2M_TIMER2 (32 + 3) +#define IRQ_V2M_TIMER3 (32 + 3) +#define IRQ_V2M_RTC { (32 + 4) } +#define IRQ_V2M_UART0 { (32 + 5) } +#define IRQ_V2M_UART1 { (32 + 6) } +#define IRQ_V2M_UART2 { (32 + 7) } +#define IRQ_V2M_UART3 { (32 + 8) } +#define IRQ_V2M_MMCI { (32 + 9), (32 + 10) } +#define IRQ_V2M_AACI { (32 + 11) } +#define IRQ_V2M_KMI0 { (32 + 12) } +#define IRQ_V2M_KMI1 { (32 + 13) } +#define IRQ_V2M_CLCD { (32 + 14) } +#define IRQ_V2M_LAN9118 (32 + 15) +#define IRQ_V2M_ISP1761 (32 + 16) +#define IRQ_V2M_PCIE (32 + 17) + + +/* + * Configuration + */ +#define SYS_CFG_START (1 << 31) +#define SYS_CFG_WRITE (1 << 30) +#define SYS_CFG_OSC (1 << 20) +#define SYS_CFG_VOLT (2 << 20) +#define SYS_CFG_AMP (3 << 20) +#define SYS_CFG_TEMP (4 << 20) +#define SYS_CFG_RESET (5 << 20) +#define SYS_CFG_SCC (6 << 20) +#define SYS_CFG_MUXFPGA (7 << 20) +#define SYS_CFG_SHUTDOWN (8 << 20) +#define SYS_CFG_REBOOT (9 << 20) +#define SYS_CFG_DVIMODE (11 << 20) +#define SYS_CFG_POWER (12 << 20) +#define SYS_CFG_SITE_MB (0 << 16) +#define SYS_CFG_SITE_DB1 (1 << 16) +#define SYS_CFG_SITE_DB2 (2 << 16) +#define SYS_CFG_STACK(n) ((n) << 12) + +#define SYS_CFG_ERR (1 << 1) +#define SYS_CFG_COMPLETE (1 << 0) + +int v2m_cfg_write(u32 devfn, u32 data); +int v2m_cfg_read(u32 devfn, u32 *data); + +#endif diff --git a/arch/arm/mach-vexpress/include/mach/system.h b/arch/arm/mach-vexpress/include/mach/system.h new file mode 100644 index 0000000..899a4e6 --- /dev/null +++ b/arch/arm/mach-vexpress/include/mach/system.h @@ -0,0 +1,37 @@ +/* + * arch/arm/mach-vexpress/include/mach/system.h + * + * Copyright (C) 2003 ARM Limited + * Copyright (C) 2000 Deep Blue Solutions Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_ARCH_SYSTEM_H +#define __ASM_ARCH_SYSTEM_H + +static inline void arch_idle(void) +{ + /* + * This should do all the clock switching + * and wait for interrupt tricks + */ + cpu_do_idle(); +} + +static inline void arch_reset(char mode, const char *cmd) +{ +} + +#endif diff --git a/arch/arm/mach-vexpress/include/mach/timex.h b/arch/arm/mach-vexpress/include/mach/timex.h new file mode 100644 index 0000000..00029ba --- /dev/null +++ b/arch/arm/mach-vexpress/include/mach/timex.h @@ -0,0 +1,23 @@ +/* + * arch/arm/mach-vexpress/include/mach/timex.h + * + * RealView architecture timex specifications + * + * Copyright (C) 2003 ARM Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define CLOCK_TICK_RATE (50000000 / 16) diff --git a/arch/arm/mach-vexpress/include/mach/uncompress.h b/arch/arm/mach-vexpress/include/mach/uncompress.h new file mode 100644 index 0000000..7972c57 --- /dev/null +++ b/arch/arm/mach-vexpress/include/mach/uncompress.h @@ -0,0 +1,52 @@ +/* + * arch/arm/mach-vexpress/include/mach/uncompress.h + * + * Copyright (C) 2003 ARM Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#define AMBA_UART_DR(base) (*(volatile unsigned char *)((base) + 0x00)) +#define AMBA_UART_LCRH(base) (*(volatile unsigned char *)((base) + 0x2c)) +#define AMBA_UART_CR(base) (*(volatile unsigned char *)((base) + 0x30)) +#define AMBA_UART_FR(base) (*(volatile unsigned char *)((base) + 0x18)) + +#define get_uart_base() (0x10000000 + 0x00009000) + +/* + * This does not append a newline + */ +static inline void putc(int c) +{ + unsigned long base = get_uart_base(); + + while (AMBA_UART_FR(base) & (1 << 5)) + barrier(); + + AMBA_UART_DR(base) = c; +} + +static inline void flush(void) +{ + unsigned long base = get_uart_base(); + + while (AMBA_UART_FR(base) & (1 << 3)) + barrier(); +} + +/* + * nothing to do + */ +#define arch_decomp_setup() +#define arch_decomp_wdog() diff --git a/arch/arm/mach-vexpress/include/mach/vmalloc.h b/arch/arm/mach-vexpress/include/mach/vmalloc.h new file mode 100644 index 0000000..f43a36e --- /dev/null +++ b/arch/arm/mach-vexpress/include/mach/vmalloc.h @@ -0,0 +1,21 @@ +/* + * arch/arm/mach-vexpress/include/mach/vmalloc.h + * + * Copyright (C) 2003 ARM Limited + * Copyright (C) 2000 Russell King. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#define VMALLOC_END 0xf8000000UL diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c new file mode 100644 index 0000000..d250711 --- /dev/null +++ b/arch/arm/mach-vexpress/v2m.c @@ -0,0 +1,361 @@ +/* + * Versatile Express V2M Motherboard Support + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "core.h" + +#define V2M_PA_CS0 0x40000000 +#define V2M_PA_CS1 0x44000000 +#define V2M_PA_CS2 0x48000000 +#define V2M_PA_CS3 0x4c000000 +#define V2M_PA_CS7 0x10000000 + +static struct map_desc v2m_io_desc[] __initdata = { + { + .virtual = __MMIO_P2V(V2M_PA_CS7), + .pfn = __phys_to_pfn(V2M_PA_CS7), + .length = SZ_128K, + .type = MT_DEVICE, + }, +}; + +void __init v2m_map_io(struct map_desc *tile, size_t num) +{ + iotable_init(v2m_io_desc, ARRAY_SIZE(v2m_io_desc)); + iotable_init(tile, num); +} + + +static void v2m_timer_init(void) +{ + writel(0, MMIO_P2V(V2M_TIMER0) + TIMER_CTRL); + writel(0, MMIO_P2V(V2M_TIMER1) + TIMER_CTRL); + + sp804_clocksource_init(MMIO_P2V(V2M_TIMER1)); + sp804_clockevents_init(MMIO_P2V(V2M_TIMER0), IRQ_V2M_TIMER0); +} + +struct sys_timer v2m_timer = { + .init = v2m_timer_init, +}; + + +static DEFINE_SPINLOCK(v2m_cfg_lock); + +int v2m_cfg_write(u32 devfn, u32 data) +{ + /* Configuration interface broken? */ + u32 val; + + printk("%s: writing %08x to %08x\n", __func__, data, devfn); + + devfn |= SYS_CFG_START | SYS_CFG_WRITE; + + spin_lock(&v2m_cfg_lock); + val = readl(MMIO_P2V(V2M_SYS_CFGSTAT)); + writel(val & ~SYS_CFG_COMPLETE, MMIO_P2V(V2M_SYS_CFGSTAT)); + + writel(data, MMIO_P2V(V2M_SYS_CFGDATA)); + writel(devfn, MMIO_P2V(V2M_SYS_CFGCTRL)); + + do { + val = readl(MMIO_P2V(V2M_SYS_CFGSTAT)); + } while (val == 0); + spin_unlock(&v2m_cfg_lock); + + return !!(val & SYS_CFG_ERR); +} + +int v2m_cfg_read(u32 devfn, u32 *data) +{ + u32 val; + + devfn |= SYS_CFG_START; + + spin_lock(&v2m_cfg_lock); + writel(0, MMIO_P2V(V2M_SYS_CFGSTAT)); + writel(devfn, MMIO_P2V(V2M_SYS_CFGCTRL)); + + mb(); + + do { + cpu_relax(); + val = readl(MMIO_P2V(V2M_SYS_CFGSTAT)); + } while (val == 0); + + *data = readl(MMIO_P2V(V2M_SYS_CFGDATA)); + spin_unlock(&v2m_cfg_lock); + + return !!(val & SYS_CFG_ERR); +} + + +static struct resource v2m_pcie_i2c_resource = { + .start = V2M_SERIAL_BUS_PCI, + .end = V2M_SERIAL_BUS_PCI + SZ_4K - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device v2m_pcie_i2c_device = { + .name = "versatile-i2c", + .id = 0, + .num_resources = 1, + .resource = &v2m_pcie_i2c_resource, +}; + +static struct resource v2m_ddc_i2c_resource = { + .start = V2M_SERIAL_BUS_DVI, + .end = V2M_SERIAL_BUS_DVI + SZ_4K - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device v2m_ddc_i2c_device = { + .name = "versatile-i2c", + .id = 1, + .num_resources = 1, + .resource = &v2m_ddc_i2c_resource, +}; + +static struct resource v2m_eth_resources[] = { + { + .start = V2M_LAN9118, + .end = V2M_LAN9118 + SZ_64K - 1, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_V2M_LAN9118, + .end = IRQ_V2M_LAN9118, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct smsc911x_platform_config v2m_eth_config = { + .flags = SMSC911X_USE_32BIT, + .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH, + .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL, + .phy_interface = PHY_INTERFACE_MODE_MII, +}; + +static struct platform_device v2m_eth_device = { + .name = "smsc911x", + .id = -1, + .resource = v2m_eth_resources, + .num_resources = ARRAY_SIZE(v2m_eth_resources), + .dev.platform_data = &v2m_eth_config, +}; + +static struct resource v2m_usb_resources[] = { + { + .start = V2M_ISP1761, + .end = V2M_ISP1761 + SZ_128K - 1, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_V2M_ISP1761, + .end = IRQ_V2M_ISP1761, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct isp1760_platform_data v2m_usb_config = { + .is_isp1761 = true, + .bus_width_16 = false, + .port1_otg = true, + .analog_oc = false, + .dack_polarity_high = false, + .dreq_polarity_high = false, +}; + +static struct platform_device v2m_usb_device = { + .name = "isp1760", + .id = -1, + .resource = v2m_usb_resources, + .num_resources = ARRAY_SIZE(v2m_usb_resources), + .dev.platform_data = &v2m_usb_config, +}; + +static int v2m_flash_init(void) +{ + writel(0, MMIO_P2V(V2M_SYS_FLASH)); + return 0; +} + +static void v2m_flash_exit(void) +{ + writel(0, MMIO_P2V(V2M_SYS_FLASH)); +} + +static void v2m_flash_set_vpp(int on) +{ + writel(on != 0, MMIO_P2V(V2M_SYS_FLASH)); +} + +static struct flash_platform_data v2m_flash_data = { + .map_name = "cfi_probe", + .width = 4, + .init = v2m_flash_init, + .exit = v2m_flash_exit, + .set_vpp = v2m_flash_set_vpp, +}; + +static struct resource v2m_flash_resources[] = { + { + .start = V2M_NOR0, + .end = V2M_NOR0 + SZ_64M - 1, + .flags = IORESOURCE_MEM, + }, { + .start = V2M_NOR1, + .end = V2M_NOR1 + SZ_64M - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device v2m_flash_device = { + .name = "armflash", + .id = -1, + .resource = v2m_flash_resources, + .num_resources = ARRAY_SIZE(v2m_flash_resources), + .dev.platform_data = &v2m_flash_data, +}; + + +static unsigned int v2m_mmci_status(struct device *dev) +{ + return !(readl(MMIO_P2V(V2M_SYS_MCI)) & (1 << 0)); +} + +static struct mmci_platform_data v2m_mmci_data = { + .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, + .status = v2m_mmci_status, +}; + +static AMBA_DEVICE(aaci, "mb:aaci", V2M_AACI, NULL); +static AMBA_DEVICE(mmci, "mb:mmci", V2M_MMCI, &v2m_mmci_data); +static AMBA_DEVICE(kmi0, "mb:kmi0", V2M_KMI0, NULL); +static AMBA_DEVICE(kmi1, "mb:kmi1", V2M_KMI1, NULL); +static AMBA_DEVICE(uart0, "mb:uart0", V2M_UART0, NULL); +static AMBA_DEVICE(uart1, "mb:uart1", V2M_UART1, NULL); +static AMBA_DEVICE(uart2, "mb:uart2", V2M_UART2, NULL); +static AMBA_DEVICE(uart3, "mb:uart3", V2M_UART3, NULL); +static AMBA_DEVICE(wdt, "mb:wdt", V2M_WDT, NULL); +static AMBA_DEVICE(rtc, "mb:rtc", V2M_RTC, NULL); + +static struct amba_device *v2m_amba_devs[] __initdata = { + &aaci_device, + &mmci_device, + &kmi0_device, + &kmi1_device, + &uart0_device, + &uart1_device, + &uart2_device, + &uart3_device, + &wdt_device, + &rtc_device, +}; + + +static long v2m_osc_round(struct clk *clk, unsigned long rate) +{ + return rate; +} + +static int v2m_osc1_set(struct clk *clk, unsigned long rate) +{ + return v2m_cfg_write(SYS_CFG_OSC | SYS_CFG_SITE_MB | 1, rate); +} + +static const struct clk_ops osc1_clk_ops = { + .round = v2m_osc_round, + .set = v2m_osc1_set, +}; + +static struct clk osc1_clk = { + .ops = &osc1_clk_ops, + .rate = 24000000, +}; + +static struct clk osc2_clk = { + .rate = 24000000, +}; + +static struct clk_lookup v2m_lookups[] = { + { /* UART0 */ + .dev_id = "mb:uart0", + .clk = &osc2_clk, + }, { /* UART1 */ + .dev_id = "mb:uart1", + .clk = &osc2_clk, + }, { /* UART2 */ + .dev_id = "mb:uart2", + .clk = &osc2_clk, + }, { /* UART3 */ + .dev_id = "mb:uart3", + .clk = &osc2_clk, + }, { /* KMI0 */ + .dev_id = "mb:kmi0", + .clk = &osc2_clk, + }, { /* KMI1 */ + .dev_id = "mb:kmi1", + .clk = &osc2_clk, + }, { /* MMC0 */ + .dev_id = "mb:mmci", + .clk = &osc2_clk, + }, { /* CLCD */ + .dev_id = "mb:clcd", + .clk = &osc1_clk, + }, +}; + +static void v2m_power_off(void) +{ + if (v2m_cfg_write(SYS_CFG_SHUTDOWN | SYS_CFG_SITE_MB, 0)) + printk(KERN_EMERG "Unable to shutdown\n"); +} + +static void v2m_restart(char str, const char *cmd) +{ + if (v2m_cfg_write(SYS_CFG_REBOOT | SYS_CFG_SITE_MB, 0)) + printk(KERN_EMERG "Unable to reboot\n"); +} + +static int __init v2m_init(void) +{ + int i; + + clkdev_add_table(v2m_lookups, ARRAY_SIZE(v2m_lookups)); + + platform_device_register(&v2m_pcie_i2c_device); + platform_device_register(&v2m_ddc_i2c_device); + platform_device_register(&v2m_flash_device); + platform_device_register(&v2m_eth_device); + platform_device_register(&v2m_usb_device); + + for (i = 0; i < ARRAY_SIZE(v2m_amba_devs); i++) + amba_device_register(v2m_amba_devs[i], &iomem_resource); + + pm_power_off = v2m_power_off; + arm_pm_restart = v2m_restart; + + return 0; +} +arch_initcall(v2m_init); diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 9c6170c..87ab056 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -564,7 +564,7 @@ config I2C_STU300 config I2C_VERSATILE tristate "ARM Versatile/Realview I2C bus support" - depends on ARCH_VERSATILE || ARCH_REALVIEW + depends on ARCH_VERSATILE || ARCH_REALVIEW || ARCH_VEXPRESS select I2C_ALGOBIT help Say yes if you want to support the I2C serial bus on ARMs Versatile -- cgit v0.10.2 From fef88f10767cfd9f9b4eebb5d5490214c5e13ad5 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 28 Feb 2010 17:26:25 +0000 Subject: ARM: Add Versatile Express CA9x4 processor support Signed-off-by: Russell King diff --git a/arch/arm/mach-vexpress/Kconfig b/arch/arm/mach-vexpress/Kconfig index 751858c..3f19b66 100644 --- a/arch/arm/mach-vexpress/Kconfig +++ b/arch/arm/mach-vexpress/Kconfig @@ -1,4 +1,9 @@ menu "Versatile Express platform type" depends on ARCH_VEXPRESS +config ARCH_VEXPRESS_CA9X4 + bool "Versatile Express Cortex-A9x4 tile" + select CPU_V7 + select ARM_GIC + endmenu diff --git a/arch/arm/mach-vexpress/Makefile b/arch/arm/mach-vexpress/Makefile index b47cf73..3c5e160 100644 --- a/arch/arm/mach-vexpress/Makefile +++ b/arch/arm/mach-vexpress/Makefile @@ -3,3 +3,4 @@ # obj-y := v2m.o +obj-$(CONFIG_ARCH_VEXPRESS_CA9X4) += ct-ca9x4.o diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c new file mode 100644 index 0000000..5a0449c --- /dev/null +++ b/arch/arm/mach-vexpress/ct-ca9x4.c @@ -0,0 +1,215 @@ +/* + * Versatile Express Core Tile Cortex A9x4 Support + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include + +#include "core.h" + +#include + +#define V2M_PA_CS7 0x10000000 + +static struct map_desc ct_ca9x4_io_desc[] __initdata = { + { + .virtual = __MMIO_P2V(CT_CA9X4_MPIC), + .pfn = __phys_to_pfn(CT_CA9X4_MPIC), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = __MMIO_P2V(CT_CA9X4_SP804_TIMER), + .pfn = __phys_to_pfn(CT_CA9X4_SP804_TIMER), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = __MMIO_P2V(CT_CA9X4_L2CC), + .pfn = __phys_to_pfn(CT_CA9X4_L2CC), + .length = SZ_4K, + .type = MT_DEVICE, + }, +}; + +static void __init ct_ca9x4_map_io(void) +{ + v2m_map_io(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc)); +} + +void __iomem *gic_cpu_base_addr; + +static void __init ct_ca9x4_init_irq(void) +{ + gic_cpu_base_addr = MMIO_P2V(A9_MPCORE_GIC_CPU); + gic_dist_init(0, MMIO_P2V(A9_MPCORE_GIC_DIST), 29); + gic_cpu_init(0, gic_cpu_base_addr); +} + +#if 0 +static void ct_ca9x4_timer_init(void) +{ + writel(0, MMIO_P2V(CT_CA9X4_TIMER0) + TIMER_CTRL); + writel(0, MMIO_P2V(CT_CA9X4_TIMER1) + TIMER_CTRL); + + sp804_clocksource_init(MMIO_P2V(CT_CA9X4_TIMER1)); + sp804_clockevents_init(MMIO_P2V(CT_CA9X4_TIMER0), IRQ_CT_CA9X4_TIMER0); +} + +static struct sys_timer ct_ca9x4_timer = { + .init = ct_ca9x4_timer_init, +}; +#endif + +static struct clcd_panel xvga_panel = { + .mode = { + .name = "XVGA", + .refresh = 60, + .xres = 1024, + .yres = 768, + .pixclock = 15384, + .left_margin = 168, + .right_margin = 8, + .upper_margin = 29, + .lower_margin = 3, + .hsync_len = 144, + .vsync_len = 6, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = TIM2_BCD | TIM2_IPC, + .cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1), + .bpp = 16, +}; + +static void ct_ca9x4_clcd_enable(struct clcd_fb *fb) +{ + v2m_cfg_write(SYS_CFG_MUXFPGA | SYS_CFG_SITE_DB1, 0); + v2m_cfg_write(SYS_CFG_DVIMODE | SYS_CFG_SITE_DB1, 2); +} + +static int ct_ca9x4_clcd_setup(struct clcd_fb *fb) +{ + unsigned long framesize = 1024 * 768 * 2; + dma_addr_t dma; + + fb->panel = &xvga_panel; + + fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize, + &dma, GFP_KERNEL); + if (!fb->fb.screen_base) { + printk(KERN_ERR "CLCD: unable to map frame buffer\n"); + return -ENOMEM; + } + fb->fb.fix.smem_start = dma; + fb->fb.fix.smem_len = framesize; + + return 0; +} + +static int ct_ca9x4_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma) +{ + return dma_mmap_writecombine(&fb->dev->dev, vma, fb->fb.screen_base, + fb->fb.fix.smem_start, fb->fb.fix.smem_len); +} + +static void ct_ca9x4_clcd_remove(struct clcd_fb *fb) +{ + dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len, + fb->fb.screen_base, fb->fb.fix.smem_start); +} + +static struct clcd_board ct_ca9x4_clcd_data = { + .name = "CT-CA9X4", + .check = clcdfb_check, + .decode = clcdfb_decode, + .enable = ct_ca9x4_clcd_enable, + .setup = ct_ca9x4_clcd_setup, + .mmap = ct_ca9x4_clcd_mmap, + .remove = ct_ca9x4_clcd_remove, +}; + +static AMBA_DEVICE(clcd, "ct:clcd", CT_CA9X4_CLCDC, &ct_ca9x4_clcd_data); +static AMBA_DEVICE(dmc, "ct:dmc", CT_CA9X4_DMC, NULL); +static AMBA_DEVICE(smc, "ct:smc", CT_CA9X4_SMC, NULL); +static AMBA_DEVICE(gpio, "ct:gpio", CT_CA9X4_GPIO, NULL); + +static struct amba_device *ct_ca9x4_amba_devs[] __initdata = { + &clcd_device, + &dmc_device, + &smc_device, + &gpio_device, +}; + + +static long ct_round(struct clk *clk, unsigned long rate) +{ + return rate; +} + +static int ct_set(struct clk *clk, unsigned long rate) +{ + return v2m_cfg_write(SYS_CFG_OSC | SYS_CFG_SITE_DB1 | 1, rate); +} + +static const struct clk_ops osc1_clk_ops = { + .round = ct_round, + .set = ct_set, +}; + +static struct clk osc1_clk = { + .ops = &osc1_clk_ops, + .rate = 24000000, +}; + +static struct clk_lookup lookups[] = { + { /* CLCD */ + .dev_id = "ct:clcd", + .clk = &osc1_clk, + }, +}; + +static void ct_ca9x4_init(void) +{ + int i; + +#ifdef CONFIG_CACHE_L2X0 + l2x0_init(MMIO_P2V(CT_CA9X4_L2CC), 0x00000000, 0xfe0fffff); +#endif + + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); + + for (i = 0; i < ARRAY_SIZE(ct_ca9x4_amba_devs); i++) + amba_device_register(ct_ca9x4_amba_devs[i], &iomem_resource); +} + +MACHINE_START(VEXPRESS, "ARM-Versatile Express CA9x4") + .phys_io = V2M_UART0, + .io_pg_offst = (__MMIO_P2V(V2M_UART0) >> 18) & 0xfffc, + .boot_params = PHYS_OFFSET + 0x00000100, + .map_io = ct_ca9x4_map_io, + .init_irq = ct_ca9x4_init_irq, +#if 0 + .timer = &ct_ca9x4_timer, +#else + .timer = &v2m_timer, +#endif + .init_machine = ct_ca9x4_init, +MACHINE_END diff --git a/arch/arm/mach-vexpress/include/mach/ct-ca9x4.h b/arch/arm/mach-vexpress/include/mach/ct-ca9x4.h new file mode 100644 index 0000000..10718e6 --- /dev/null +++ b/arch/arm/mach-vexpress/include/mach/ct-ca9x4.h @@ -0,0 +1,43 @@ +#ifndef __MACH_CT_CA9X4_H +#define __MACH_CT_CA9X4_H + +/* + * Physical base addresses + */ +#define CT_CA9X4_CLCDC (0x10020000) +#define CT_CA9X4_AXIRAM (0x10060000) +#define CT_CA9X4_DMC (0x100e0000) +#define CT_CA9X4_SMC (0x100e1000) +#define CT_CA9X4_SCC (0x100e2000) +#define CT_CA9X4_SP804_TIMER (0x100e4000) +#define CT_CA9X4_SP805_WDT (0x100e5000) +#define CT_CA9X4_TZPC (0x100e6000) +#define CT_CA9X4_GPIO (0x100e8000) +#define CT_CA9X4_FASTAXI (0x100e9000) +#define CT_CA9X4_SLOWAXI (0x100ea000) +#define CT_CA9X4_TZASC (0x100ec000) +#define CT_CA9X4_CORESIGHT (0x10200000) +#define CT_CA9X4_MPIC (0x1e000000) +#define CT_CA9X4_SYSTIMER (0x1e004000) +#define CT_CA9X4_SYSWDT (0x1e007000) +#define CT_CA9X4_L2CC (0x1e00a000) + +#define CT_CA9X4_TIMER0 (CT_CA9X4_SP804_TIMER + 0x000) +#define CT_CA9X4_TIMER1 (CT_CA9X4_SP804_TIMER + 0x020) + +#define A9_MPCORE_SCU (CT_CA9X4_MPIC + 0x0000) +#define A9_MPCORE_GIC_CPU (CT_CA9X4_MPIC + 0x0100) +#define A9_MPCORE_GIT (CT_CA9X4_MPIC + 0x0200) +#define A9_MPCORE_GIC_DIST (CT_CA9X4_MPIC + 0x1000) + +/* + * Interrupts. Those in {} are for AMBA devices + */ +#define IRQ_CT_CA9X4_CLCDC { 76 } +#define IRQ_CT_CA9X4_DMC { -1 } +#define IRQ_CT_CA9X4_SMC { 77, 78 } +#define IRQ_CT_CA9X4_TIMER0 80 +#define IRQ_CT_CA9X4_TIMER1 81 +#define IRQ_CT_CA9X4_GPIO { 82 } + +#endif diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index c4ed9f9..270c8e2 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -754,7 +754,8 @@ config CACHE_FEROCEON_L2_WRITETHROUGH config CACHE_L2X0 bool "Enable the L2x0 outer cache controller" depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \ - REALVIEW_EB_A9MP || ARCH_MX35 || ARCH_MX31 || MACH_REALVIEW_PBX || ARCH_NOMADIK || ARCH_OMAP4 + REALVIEW_EB_A9MP || ARCH_MX35 || ARCH_MX31 || MACH_REALVIEW_PBX || \ + ARCH_NOMADIK || ARCH_OMAP4 || ARCH_VEXPRESS_CA9X4 default y select OUTER_CACHE help -- cgit v0.10.2 From 59ac59f6f1432aa9417d2592bdfd17c99804dd66 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 11 Feb 2010 21:56:07 +0000 Subject: ARM: Add Versatile Express SMP support Signed-off-by: Russell King diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 58080e1..4bb7730 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1121,10 +1121,11 @@ source "kernel/time/Kconfig" config SMP bool "Symmetric Multi-Processing (EXPERIMENTAL)" depends on EXPERIMENTAL && (REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP ||\ - MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || ARCH_U8500) + MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 ||\ + ARCH_U8500 || ARCH_VEXPRESS_CA9X4) depends on GENERIC_CLOCKEVENTS select USE_GENERIC_SMP_HELPERS - select HAVE_ARM_SCU if (ARCH_REALVIEW || ARCH_OMAP4 || ARCH_U8500) + select HAVE_ARM_SCU if (ARCH_REALVIEW || ARCH_OMAP4 || ARCH_U8500 || ARCH_VEXPRESS_CA9X4) help This enables support for systems with more than one CPU. If you have a system with only one CPU, like most personal computers, say N. If diff --git a/arch/arm/mach-vexpress/Makefile b/arch/arm/mach-vexpress/Makefile index 3c5e160..1b71b77 100644 --- a/arch/arm/mach-vexpress/Makefile +++ b/arch/arm/mach-vexpress/Makefile @@ -4,3 +4,5 @@ obj-y := v2m.o obj-$(CONFIG_ARCH_VEXPRESS_CA9X4) += ct-ca9x4.o +obj-$(CONFIG_SMP) += platsmp.o headsmp.o +obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o diff --git a/arch/arm/mach-vexpress/headsmp.S b/arch/arm/mach-vexpress/headsmp.S new file mode 100644 index 0000000..8a78ff6 --- /dev/null +++ b/arch/arm/mach-vexpress/headsmp.S @@ -0,0 +1,39 @@ +/* + * linux/arch/arm/mach-vexpress/headsmp.S + * + * Copyright (c) 2003 ARM Limited + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include + + __INIT + +/* + * Versatile Express specific entry point for secondary CPUs. This + * provides a "holding pen" into which all secondary cores are held + * until we're ready for them to initialise. + */ +ENTRY(vexpress_secondary_startup) + mrc p15, 0, r0, c0, c0, 5 + and r0, r0, #15 + adr r4, 1f + ldmia r4, {r5, r6} + sub r4, r4, r5 + add r6, r6, r4 +pen: ldr r7, [r6] + cmp r7, r0 + bne pen + + /* + * we've been released from the holding pen: secondary_stack + * should now contain the SVC stack for this core + */ + b secondary_startup + +1: .long . + .long pen_release diff --git a/arch/arm/mach-vexpress/include/mach/smp.h b/arch/arm/mach-vexpress/include/mach/smp.h new file mode 100644 index 0000000..72a9621 --- /dev/null +++ b/arch/arm/mach-vexpress/include/mach/smp.h @@ -0,0 +1,21 @@ +#ifndef __MACH_SMP_H +#define __MACH_SMP_H + +#include + +#define hard_smp_processor_id() \ + ({ \ + unsigned int cpunum; \ + __asm__("mrc p15, 0, %0, c0, c0, 5" \ + : "=r" (cpunum)); \ + cpunum &= 0x0F; \ + }) + +/* + * We use IRQ1 as the IPI + */ +static inline void smp_cross_call(const struct cpumask *mask) +{ + gic_raise_softirq(mask, 1); +} +#endif diff --git a/arch/arm/mach-vexpress/localtimer.c b/arch/arm/mach-vexpress/localtimer.c new file mode 100644 index 0000000..c0e3a59 --- /dev/null +++ b/arch/arm/mach-vexpress/localtimer.c @@ -0,0 +1,26 @@ +/* + * linux/arch/arm/mach-vexpress/localtimer.c + * + * Copyright (C) 2002 ARM Ltd. + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include + +#include +#include +#include + +/* + * Setup the local clock events for a CPU. + */ +void __cpuinit local_timer_setup(struct clock_event_device *evt) +{ + evt->irq = IRQ_LOCALTIMER; + twd_timer_setup(evt); +} diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c new file mode 100644 index 0000000..6709706 --- /dev/null +++ b/arch/arm/mach-vexpress/platsmp.c @@ -0,0 +1,190 @@ +/* + * linux/arch/arm/mach-vexpress/platsmp.c + * + * Copyright (C) 2002 ARM Ltd. + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#define V2M_PA_CS7 0x10000000 + +#include "core.h" + +extern void vexpress_secondary_startup(void); + +/* + * control for which core is the next to come out of the secondary + * boot "holding pen" + */ +volatile int __cpuinitdata pen_release = -1; + +static void __iomem *scu_base_addr(void) +{ + return MMIO_P2V(A9_MPCORE_SCU); +} + +static DEFINE_SPINLOCK(boot_lock); + +void __cpuinit platform_secondary_init(unsigned int cpu) +{ + trace_hardirqs_off(); + + /* + * if any interrupts are already enabled for the primary + * core (e.g. timer irq), then they will not have been enabled + * for us: do so + */ + gic_cpu_init(0, gic_cpu_base_addr); + + /* + * let the primary processor know we're out of the + * pen, then head off into the C entry point + */ + pen_release = -1; + smp_wmb(); + + /* + * Synchronise with the boot thread. + */ + spin_lock(&boot_lock); + spin_unlock(&boot_lock); +} + +int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) +{ + unsigned long timeout; + + /* + * Set synchronisation state between this boot processor + * and the secondary one + */ + spin_lock(&boot_lock); + + /* + * This is really belt and braces; we hold unintended secondary + * CPUs in the holding pen until we're ready for them. However, + * since we haven't sent them a soft interrupt, they shouldn't + * be there. + */ + pen_release = cpu; + __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release)); + outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1)); + + /* + * Send the secondary CPU a soft interrupt, thereby causing + * the boot monitor to read the system wide flags register, + * and branch to the address found there. + */ + smp_cross_call(cpumask_of(cpu)); + + timeout = jiffies + (1 * HZ); + while (time_before(jiffies, timeout)) { + smp_rmb(); + if (pen_release == -1) + break; + + udelay(10); + } + + /* + * now the secondary core is starting up let it run its + * calibrations, then wait for it to finish + */ + spin_unlock(&boot_lock); + + return pen_release != -1 ? -ENOSYS : 0; +} + +/* + * Initialise the CPU possible map early - this describes the CPUs + * which may be present or become present in the system. + */ +void __init smp_init_cpus(void) +{ + void __iomem *scu_base = scu_base_addr(); + unsigned int i, ncores; + + ncores = scu_base ? scu_get_core_count(scu_base) : 1; + + /* sanity check */ + if (ncores == 0) { + printk(KERN_ERR + "vexpress: strange CM count of 0? Default to 1\n"); + + ncores = 1; + } + + if (ncores > NR_CPUS) { + printk(KERN_WARNING + "vexpress: no. of cores (%d) greater than configured " + "maximum of %d - clipping\n", + ncores, NR_CPUS); + ncores = NR_CPUS; + } + + for (i = 0; i < ncores; i++) + set_cpu_possible(i, true); +} + +void __init smp_prepare_cpus(unsigned int max_cpus) +{ + unsigned int ncores = num_possible_cpus(); + unsigned int cpu = smp_processor_id(); + int i; + + smp_store_cpu_info(cpu); + + /* + * are we trying to boot more cores than exist? + */ + if (max_cpus > ncores) + max_cpus = ncores; + + /* + * Initialise the present map, which describes the set of CPUs + * actually populated at the present time. + */ + for (i = 0; i < max_cpus; i++) + set_cpu_present(i, true); + + /* + * Initialise the SCU if there are more than one CPU and let + * them know where to start. + */ + if (max_cpus > 1) { + /* + * Enable the local timer or broadcast device for the + * boot CPU, but only if we have more than one CPU. + */ + percpu_timer_setup(); + + scu_enable(scu_base_addr()); + + /* + * Write the address of secondary startup into the + * system-wide flags register. The boot monitor waits + * until it receives a soft interrupt, and then the + * secondary CPU branches to this address. + */ + writel(~0, MMIO_P2V(V2M_SYS_FLAGSCLR)); + writel(BSYM(virt_to_phys(vexpress_secondary_startup)), + MMIO_P2V(V2M_SYS_FLAGSSET)); + } +} -- cgit v0.10.2 From f417cbad7394fdccec850d13d7d5621516d693ce Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Thu, 15 Apr 2010 10:16:26 +0100 Subject: ARM: 6057/1: Realview: register PMU IRQs during board initialisation This patch updates the initialisation routines for the Realview boards and the Versatile Express board [ca9x4 tile] so that they register their PMU IRQs with the PMU framework in the Kernel. Signed-off-by: Will Deacon Signed-off-by: Russell King diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c index 006765f..422ccd7 100644 --- a/arch/arm/mach-realview/realview_eb.c +++ b/arch/arm/mach-realview/realview_eb.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -292,6 +293,36 @@ static struct resource realview_eb_isp1761_resources[] = { }, }; +static struct resource pmu_resources[] = { + [0] = { + .start = IRQ_EB11MP_PMU_CPU0, + .end = IRQ_EB11MP_PMU_CPU0, + .flags = IORESOURCE_IRQ, + }, + [1] = { + .start = IRQ_EB11MP_PMU_CPU1, + .end = IRQ_EB11MP_PMU_CPU1, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IRQ_EB11MP_PMU_CPU2, + .end = IRQ_EB11MP_PMU_CPU2, + .flags = IORESOURCE_IRQ, + }, + [3] = { + .start = IRQ_EB11MP_PMU_CPU3, + .end = IRQ_EB11MP_PMU_CPU3, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device pmu_device = { + .name = "arm-pmu", + .id = ARM_PMU_DEVICE_CPU, + .num_resources = ARRAY_SIZE(pmu_resources), + .resource = pmu_resources, +}; + static void __init gic_init_irq(void) { if (core_tile_eb11mp() || core_tile_a9mp()) { @@ -405,6 +436,7 @@ static void __init realview_eb_init(void) * Bits: .... ...0 0111 1001 0000 .... .... .... */ l2x0_init(__io_address(REALVIEW_EB11MP_L220_BASE), 0x00790000, 0xfe000fff); #endif + platform_device_register(&pmu_device); } realview_flash_register(&realview_eb_flash_resource, 1); diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c index 217f7c1..96568eb 100644 --- a/arch/arm/mach-realview/realview_pb1176.c +++ b/arch/arm/mach-realview/realview_pb1176.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -261,6 +262,19 @@ static struct resource realview_pb1176_isp1761_resources[] = { }, }; +static struct resource pmu_resource = { + .start = IRQ_DC1176_CORE_PMU, + .end = IRQ_DC1176_CORE_PMU, + .flags = IORESOURCE_IRQ, +}; + +static struct platform_device pmu_device = { + .name = "arm-pmu", + .id = ARM_PMU_DEVICE_CPU, + .num_resources = 1, + .resource = &pmu_resource, +}; + static void __init gic_init_irq(void) { /* ARM1176 DevChip GIC, primary */ @@ -322,6 +336,7 @@ static void __init realview_pb1176_init(void) realview_eth_register(NULL, realview_pb1176_smsc911x_resources); platform_device_register(&realview_i2c_device); realview_usb_register(realview_pb1176_isp1761_resources); + platform_device_register(&pmu_device); for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { struct amba_device *d = amba_devs[i]; diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c index 9ef2ecc..7fbefbb 100644 --- a/arch/arm/mach-realview/realview_pb11mp.c +++ b/arch/arm/mach-realview/realview_pb11mp.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -258,6 +259,36 @@ static struct resource realview_pb11mp_isp1761_resources[] = { }, }; +static struct resource pmu_resources[] = { + [0] = { + .start = IRQ_TC11MP_PMU_CPU0, + .end = IRQ_TC11MP_PMU_CPU0, + .flags = IORESOURCE_IRQ, + }, + [1] = { + .start = IRQ_TC11MP_PMU_CPU1, + .end = IRQ_TC11MP_PMU_CPU1, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IRQ_TC11MP_PMU_CPU2, + .end = IRQ_TC11MP_PMU_CPU2, + .flags = IORESOURCE_IRQ, + }, + [3] = { + .start = IRQ_TC11MP_PMU_CPU3, + .end = IRQ_TC11MP_PMU_CPU3, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device pmu_device = { + .name = "arm-pmu", + .id = ARM_PMU_DEVICE_CPU, + .num_resources = ARRAY_SIZE(pmu_resources), + .resource = pmu_resources, +}; + static void __init gic_init_irq(void) { unsigned int pldctrl; @@ -327,6 +358,7 @@ static void __init realview_pb11mp_init(void) platform_device_register(&realview_i2c_device); platform_device_register(&realview_cf_device); realview_usb_register(realview_pb11mp_isp1761_resources); + platform_device_register(&pmu_device); for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { struct amba_device *d = amba_devs[i]; diff --git a/arch/arm/mach-realview/realview_pba8.c b/arch/arm/mach-realview/realview_pba8.c index 2fab3a6..d3c113b 100644 --- a/arch/arm/mach-realview/realview_pba8.c +++ b/arch/arm/mach-realview/realview_pba8.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -248,6 +249,19 @@ static struct resource realview_pba8_isp1761_resources[] = { }, }; +static struct resource pmu_resource = { + .start = IRQ_PBA8_PMU, + .end = IRQ_PBA8_PMU, + .flags = IORESOURCE_IRQ, +}; + +static struct platform_device pmu_device = { + .name = "arm-pmu", + .id = ARM_PMU_DEVICE_CPU, + .num_resources = 1, + .resource = &pmu_resource, +}; + static void __init gic_init_irq(void) { /* ARM PB-A8 on-board GIC */ @@ -294,6 +308,7 @@ static void __init realview_pba8_init(void) platform_device_register(&realview_i2c_device); platform_device_register(&realview_cf_device); realview_usb_register(realview_pba8_isp1761_resources); + platform_device_register(&pmu_device); for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { struct amba_device *d = amba_devs[i]; diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c index d94857e..a235ba3 100644 --- a/arch/arm/mach-realview/realview_pbx.c +++ b/arch/arm/mach-realview/realview_pbx.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -270,6 +271,36 @@ static struct resource realview_pbx_isp1761_resources[] = { }, }; +static struct resource pmu_resources[] = { + [0] = { + .start = IRQ_PBX_PMU_CPU0, + .end = IRQ_PBX_PMU_CPU0, + .flags = IORESOURCE_IRQ, + }, + [1] = { + .start = IRQ_PBX_PMU_CPU1, + .end = IRQ_PBX_PMU_CPU1, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IRQ_PBX_PMU_CPU2, + .end = IRQ_PBX_PMU_CPU2, + .flags = IORESOURCE_IRQ, + }, + [3] = { + .start = IRQ_PBX_PMU_CPU3, + .end = IRQ_PBX_PMU_CPU3, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device pmu_device = { + .name = "arm-pmu", + .id = ARM_PMU_DEVICE_CPU, + .num_resources = ARRAY_SIZE(pmu_resources), + .resource = pmu_resources, +}; + static void __init gic_init_irq(void) { /* ARM PBX on-board GIC */ @@ -354,6 +385,7 @@ static void __init realview_pbx_init(void) /* 16KB way size, 8-way associativity, parity disabled * Bits: .. 0 0 0 0 1 00 1 0 1 001 0 000 0 .... .... .... */ l2x0_init(l2x0_base, 0x02520000, 0xc0000fff); + platform_device_register(&pmu_device); } #endif diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c index 5a0449c..e6f7303 100644 --- a/arch/arm/mach-vexpress/ct-ca9x4.c +++ b/arch/arm/mach-vexpress/ct-ca9x4.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -12,6 +13,7 @@ #include #include #include +#include #include #include @@ -186,6 +188,36 @@ static struct clk_lookup lookups[] = { }, }; +static struct resource pmu_resources[] = { + [0] = { + .start = IRQ_CT_CA9X4_PMU_CPU0, + .end = IRQ_CT_CA9X4_PMU_CPU0, + .flags = IORESOURCE_IRQ, + }, + [1] = { + .start = IRQ_CT_CA9X4_PMU_CPU1, + .end = IRQ_CT_CA9X4_PMU_CPU1, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IRQ_CT_CA9X4_PMU_CPU2, + .end = IRQ_CT_CA9X4_PMU_CPU2, + .flags = IORESOURCE_IRQ, + }, + [3] = { + .start = IRQ_CT_CA9X4_PMU_CPU3, + .end = IRQ_CT_CA9X4_PMU_CPU3, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device pmu_device = { + .name = "arm-pmu", + .id = ARM_PMU_DEVICE_CPU, + .num_resources = ARRAY_SIZE(pmu_resources), + .resource = pmu_resources, +}; + static void ct_ca9x4_init(void) { int i; @@ -198,6 +230,8 @@ static void ct_ca9x4_init(void) for (i = 0; i < ARRAY_SIZE(ct_ca9x4_amba_devs); i++) amba_device_register(ct_ca9x4_amba_devs[i], &iomem_resource); + + platform_device_register(&pmu_device); } MACHINE_START(VEXPRESS, "ARM-Versatile Express CA9x4") diff --git a/arch/arm/mach-vexpress/include/mach/ct-ca9x4.h b/arch/arm/mach-vexpress/include/mach/ct-ca9x4.h index 10718e6..8650f04 100644 --- a/arch/arm/mach-vexpress/include/mach/ct-ca9x4.h +++ b/arch/arm/mach-vexpress/include/mach/ct-ca9x4.h @@ -39,5 +39,9 @@ #define IRQ_CT_CA9X4_TIMER0 80 #define IRQ_CT_CA9X4_TIMER1 81 #define IRQ_CT_CA9X4_GPIO { 82 } +#define IRQ_CT_CA9X4_PMU_CPU0 92 +#define IRQ_CT_CA9X4_PMU_CPU1 93 +#define IRQ_CT_CA9X4_PMU_CPU2 94 +#define IRQ_CT_CA9X4_PMU_CPU3 95 #endif -- cgit v0.10.2 From fb72014d98afd51e85aab9c061344ef32d615606 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 30 Apr 2010 19:31:12 -0300 Subject: perf tools: Don't use code surrounded by __KERNEL__ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to refactor code to be explicitely shared by the kernel and at least the tools/ userspace programs, so, till we do that, copy the bare minimum bitmap/bitops code needed by tools/perf. Reported-by: "H. Peter Anvin" Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 739c441..c5ac0a9 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -377,9 +377,9 @@ LIB_H += util/include/linux/rbtree.h LIB_H += util/include/linux/string.h LIB_H += util/include/linux/types.h LIB_H += util/include/asm/asm-offsets.h -LIB_H += util/include/asm/bitops.h LIB_H += util/include/asm/bug.h LIB_H += util/include/asm/byteorder.h +LIB_H += util/include/asm/hweight.h LIB_H += util/include/asm/swab.h LIB_H += util/include/asm/system.h LIB_H += util/include/asm/uaccess.h @@ -435,7 +435,6 @@ LIB_OBJS += $(OUTPUT)util/path.o LIB_OBJS += $(OUTPUT)util/rbtree.o LIB_OBJS += $(OUTPUT)util/bitmap.o LIB_OBJS += $(OUTPUT)util/hweight.o -LIB_OBJS += $(OUTPUT)util/find_next_bit.o LIB_OBJS += $(OUTPUT)util/run-command.o LIB_OBJS += $(OUTPUT)util/quote.o LIB_OBJS += $(OUTPUT)util/strbuf.o @@ -948,19 +947,6 @@ $(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS $(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< -# some perf warning policies can't fit to lib/bitmap.c, eg: it warns about variable shadowing -# from that comes from kernel headers wrapping. -KBITMAP_FLAGS=`echo $(ALL_CFLAGS) | sed s/-Wshadow// | sed s/-Wswitch-default// | sed s/-Wextra//` - -$(OUTPUT)util/bitmap.o: ../../lib/bitmap.c $(OUTPUT)PERF-CFLAGS - $(QUIET_CC)$(CC) -o $@ -c $(KBITMAP_FLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< - -$(OUTPUT)util/hweight.o: ../../lib/hweight.c $(OUTPUT)PERF-CFLAGS - $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< - -$(OUTPUT)util/find_next_bit.o: ../../lib/find_next_bit.c $(OUTPUT)PERF-CFLAGS - $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< - $(OUTPUT)util/scripting-engines/trace-event-perl.o: util/scripting-engines/trace-event-perl.c $(OUTPUT)PERF-CFLAGS $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $< diff --git a/tools/perf/util/bitmap.c b/tools/perf/util/bitmap.c new file mode 100644 index 0000000..5e230ac --- /dev/null +++ b/tools/perf/util/bitmap.c @@ -0,0 +1,21 @@ +/* + * From lib/bitmap.c + * Helper functions for bitmap.h. + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + */ +#include + +int __bitmap_weight(const unsigned long *bitmap, int bits) +{ + int k, w = 0, lim = bits/BITS_PER_LONG; + + for (k = 0; k < lim; k++) + w += hweight_long(bitmap[k]); + + if (bits % BITS_PER_LONG) + w += hweight_long(bitmap[k] & BITMAP_LAST_WORD_MASK(bits)); + + return w; +} diff --git a/tools/perf/util/hweight.c b/tools/perf/util/hweight.c new file mode 100644 index 0000000..5c1d0d0 --- /dev/null +++ b/tools/perf/util/hweight.c @@ -0,0 +1,31 @@ +#include + +/** + * hweightN - returns the hamming weight of a N-bit word + * @x: the word to weigh + * + * The Hamming Weight of a number is the total number of bits set in it. + */ + +unsigned int hweight32(unsigned int w) +{ + unsigned int res = w - ((w >> 1) & 0x55555555); + res = (res & 0x33333333) + ((res >> 2) & 0x33333333); + res = (res + (res >> 4)) & 0x0F0F0F0F; + res = res + (res >> 8); + return (res + (res >> 16)) & 0x000000FF; +} + +unsigned long hweight64(__u64 w) +{ +#if BITS_PER_LONG == 32 + return hweight32((unsigned int)(w >> 32)) + hweight32((unsigned int)w); +#elif BITS_PER_LONG == 64 + __u64 res = w - ((w >> 1) & 0x5555555555555555ul); + res = (res & 0x3333333333333333ul) + ((res >> 2) & 0x3333333333333333ul); + res = (res + (res >> 4)) & 0x0F0F0F0F0F0F0F0Ful; + res = res + (res >> 8); + res = res + (res >> 16); + return (res + (res >> 32)) & 0x00000000000000FFul; +#endif +} diff --git a/tools/perf/util/include/asm/bitops.h b/tools/perf/util/include/asm/bitops.h deleted file mode 100644 index 58e9817..0000000 --- a/tools/perf/util/include/asm/bitops.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _PERF_ASM_BITOPS_H_ -#define _PERF_ASM_BITOPS_H_ - -#include -#include "../../types.h" -#include - -/* CHECKME: Not sure both always match */ -#define BITS_PER_LONG __WORDSIZE - -#include "../../../../include/asm-generic/bitops/__fls.h" -#include "../../../../include/asm-generic/bitops/fls.h" -#include "../../../../include/asm-generic/bitops/fls64.h" -#include "../../../../include/asm-generic/bitops/__ffs.h" -#include "../../../../include/asm-generic/bitops/ffz.h" -#include "../../../../include/asm-generic/bitops/hweight.h" - -#endif diff --git a/tools/perf/util/include/asm/hweight.h b/tools/perf/util/include/asm/hweight.h new file mode 100644 index 0000000..36cf26d --- /dev/null +++ b/tools/perf/util/include/asm/hweight.h @@ -0,0 +1,8 @@ +#ifndef PERF_HWEIGHT_H +#define PERF_HWEIGHT_H + +#include +unsigned int hweight32(unsigned int w); +unsigned long hweight64(__u64 w); + +#endif /* PERF_HWEIGHT_H */ diff --git a/tools/perf/util/include/linux/bitmap.h b/tools/perf/util/include/linux/bitmap.h index 9450763..eda4416 100644 --- a/tools/perf/util/include/linux/bitmap.h +++ b/tools/perf/util/include/linux/bitmap.h @@ -1,3 +1,35 @@ -#include "../../../../include/linux/bitmap.h" -#include "../../../../include/asm-generic/bitops/find.h" -#include +#ifndef _PERF_BITOPS_H +#define _PERF_BITOPS_H + +#include +#include + +int __bitmap_weight(const unsigned long *bitmap, int bits); + +#define BITMAP_LAST_WORD_MASK(nbits) \ +( \ + ((nbits) % BITS_PER_LONG) ? \ + (1UL<<((nbits) % BITS_PER_LONG))-1 : ~0UL \ +) + +#define small_const_nbits(nbits) \ + (__builtin_constant_p(nbits) && (nbits) <= BITS_PER_LONG) + +static inline void bitmap_zero(unsigned long *dst, int nbits) +{ + if (small_const_nbits(nbits)) + *dst = 0UL; + else { + int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long); + memset(dst, 0, len); + } +} + +static inline int bitmap_weight(const unsigned long *src, int nbits) +{ + if (small_const_nbits(nbits)) + return hweight_long(*src & BITMAP_LAST_WORD_MASK(nbits)); + return __bitmap_weight(src, nbits); +} + +#endif /* _PERF_BITOPS_H */ diff --git a/tools/perf/util/include/linux/bitops.h b/tools/perf/util/include/linux/bitops.h index 8d63116..bb4ac2e 100644 --- a/tools/perf/util/include/linux/bitops.h +++ b/tools/perf/util/include/linux/bitops.h @@ -1,13 +1,12 @@ #ifndef _PERF_LINUX_BITOPS_H_ #define _PERF_LINUX_BITOPS_H_ -#define __KERNEL__ +#include +#include -#define CONFIG_GENERIC_FIND_NEXT_BIT -#define CONFIG_GENERIC_FIND_FIRST_BIT -#include "../../../../include/linux/bitops.h" - -#undef __KERNEL__ +#define BITS_PER_LONG __WORDSIZE +#define BITS_PER_BYTE 8 +#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) static inline void set_bit(int nr, unsigned long *addr) { @@ -20,10 +19,9 @@ static __always_inline int test_bit(unsigned int nr, const unsigned long *addr) (((unsigned long *)addr)[nr / BITS_PER_LONG])) != 0; } -unsigned long generic_find_next_zero_le_bit(const unsigned long *addr, unsigned - long size, unsigned long offset); - -unsigned long generic_find_next_le_bit(const unsigned long *addr, unsigned - long size, unsigned long offset); +static inline unsigned long hweight_long(unsigned long w) +{ + return sizeof(w) == 4 ? hweight32(w) : hweight64(w); +} #endif -- cgit v0.10.2 From 789688faef5b3ba78065beaf2f3d6f1c839f74a3 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Sat, 1 May 2010 01:41:19 -0500 Subject: perf/live: don't synthesize build ids at the end of a live mode trace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It doesn't really make sense to record the build ids at the end of a live mode session - live mode samples need that information during the trace rather than at the end. Leave event__synthesize_build_id() in place, however; we'll still be using that to synthesize build ids in a more timely fashion in a future patch. Cc: Frédéric Weisbecker Cc: Ingo Molnar Cc: Steven Rostedt LKML-Reference: <1272696080-16435-2-git-send-email-tzanussi@gmail.com> Signed-off-by: Tom Zanussi Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 83b308a..1a73796 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -446,13 +446,6 @@ static void atexit_header(void) process_buildids(); perf_header__write(&session->header, output, true); - } else { - int err; - - err = event__synthesize_build_ids(process_synthesized_event, - session); - if (err < 0) - pr_err("Couldn't synthesize build ids.\n"); } } diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 6227dc4..2d1d97e 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -1136,67 +1136,6 @@ int event__synthesize_build_id(struct dso *pos, u16 misc, return err; } -static int __event_synthesize_build_ids(struct list_head *head, u16 misc, - event__handler_t process, - struct machine *machine, - struct perf_session *session) -{ - struct dso *pos; - - dsos__for_each_with_build_id(pos, head) { - int err; - if (!pos->hit) - continue; - - err = event__synthesize_build_id(pos, misc, process, - machine, session); - if (err < 0) - return err; - } - - return 0; -} - -int event__synthesize_build_ids(event__handler_t process, - struct perf_session *session) -{ - int err = 0; - u16 kmisc, umisc; - struct machine *pos; - struct rb_node *nd; - - if (!dsos__read_build_ids(&session->header, true)) - return 0; - - for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) { - pos = rb_entry(nd, struct machine, rb_node); - if (machine__is_host(pos)) { - kmisc = PERF_RECORD_MISC_KERNEL; - umisc = PERF_RECORD_MISC_USER; - } else { - kmisc = PERF_RECORD_MISC_GUEST_KERNEL; - umisc = PERF_RECORD_MISC_GUEST_USER; - } - - err = __event_synthesize_build_ids(&pos->kernel_dsos, kmisc, - process, pos, session); - if (err == 0) - err = __event_synthesize_build_ids(&pos->user_dsos, umisc, - process, pos, session); - if (err) - break; - } - - if (err < 0) { - pr_debug("failed to synthesize build ids\n"); - return err; - } - - dsos__cache_build_ids(&session->header); - - return 0; -} - int event__process_build_id(event_t *self, struct perf_session *session) { diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index f39443d..402ac24 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h @@ -122,8 +122,6 @@ int event__synthesize_build_id(struct dso *pos, u16 misc, event__handler_t process, struct machine *machine, struct perf_session *session); -int event__synthesize_build_ids(event__handler_t process, - struct perf_session *session); int event__process_build_id(event_t *self, struct perf_session *session); #endif /* __PERF_HEADER_H */ -- cgit v0.10.2 From 454c407ec17a0c63e4023ac0877d687945a7df4a Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Sat, 1 May 2010 01:41:20 -0500 Subject: perf: add perf-inject builtin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, perf 'live mode' writes build-ids at the end of the session, which isn't actually useful for processing live mode events. What would be better would be to have the build-ids sent before any of the samples that reference them, which can be done by processing the event stream and retrieving the build-ids on the first hit. Doing that in perf-record itself, however, is off-limits. This patch introduces perf-inject, which does the same job while leaving perf-record untouched. Normal mode perf still records the build-ids at the end of the session as it should, but for live mode, perf-inject can be injected in between the record and report steps e.g.: perf record -o - ./hackbench 10 | perf inject -v -b | perf report -v -i - perf-inject reads a perf-record event stream and repipes it to stdout. At any point the processing code can inject other events into the event stream - in this case build-ids (-b option) are read and injected as needed into the event stream. Build-ids are just the first user of perf-inject - potentially anything that needs userspace processing to augment the trace stream with additional information could make use of this facility. Cc: Ingo Molnar Cc: Steven Rostedt Cc: Frédéric Weisbecker LKML-Reference: <1272696080-16435-3-git-send-email-tzanussi@gmail.com> Signed-off-by: Tom Zanussi Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Makefile b/tools/perf/Makefile index c5ac0a9..0ef5cfe 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -490,6 +490,7 @@ BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o BUILTIN_OBJS += $(OUTPUT)builtin-lock.o BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o BUILTIN_OBJS += $(OUTPUT)builtin-test.o +BUILTIN_OBJS += $(OUTPUT)builtin-inject.o PERFLIBS = $(LIB_FILE) diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index b57dbcf..ee154b5 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -554,7 +554,7 @@ static int __cmd_annotate(void) int ret; struct perf_session *session; - session = perf_session__new(input_name, O_RDONLY, force); + session = perf_session__new(input_name, O_RDONLY, force, false); if (session == NULL) return -ENOMEM; diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c index 7dc3b2e..44a47e1 100644 --- a/tools/perf/builtin-buildid-list.c +++ b/tools/perf/builtin-buildid-list.c @@ -39,7 +39,7 @@ static int __cmd_buildid_list(void) int err = -1; struct perf_session *session; - session = perf_session__new(input_name, O_RDONLY, force); + session = perf_session__new(input_name, O_RDONLY, force, false); if (session == NULL) return -1; diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 207e860..4cce68f 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -156,8 +156,8 @@ static int __cmd_diff(void) int ret, i; struct perf_session *session[2]; - session[0] = perf_session__new(input_old, O_RDONLY, force); - session[1] = perf_session__new(input_new, O_RDONLY, force); + session[0] = perf_session__new(input_old, O_RDONLY, force, false); + session[1] = perf_session__new(input_new, O_RDONLY, force, false); if (session[0] == NULL || session[1] == NULL) return -ENOMEM; diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c new file mode 100644 index 0000000..a5902a3 --- /dev/null +++ b/tools/perf/builtin-inject.c @@ -0,0 +1,228 @@ +/* + * builtin-inject.c + * + * Builtin inject command: Examine the live mode (stdin) event stream + * and repipe it to stdout while optionally injecting additional + * events into it. + */ +#include "builtin.h" + +#include "perf.h" +#include "util/session.h" +#include "util/debug.h" + +#include "util/parse-options.h" + +static char const *input_name = "-"; +static bool inject_build_ids; + +static int event__repipe(event_t *event __used, + struct perf_session *session __used) +{ + uint32_t size; + void *buf = event; + + size = event->header.size; + + while (size) { + int ret = write(STDOUT_FILENO, buf, size); + if (ret < 0) + return -errno; + + size -= ret; + buf += ret; + } + + return 0; +} + +static int event__repipe_mmap(event_t *self, struct perf_session *session) +{ + int err; + + err = event__process_mmap(self, session); + event__repipe(self, session); + + return err; +} + +static int event__repipe_task(event_t *self, struct perf_session *session) +{ + int err; + + err = event__process_task(self, session); + event__repipe(self, session); + + return err; +} + +static int event__repipe_tracing_data(event_t *self, + struct perf_session *session) +{ + int err; + + event__repipe(self, session); + err = event__process_tracing_data(self, session); + + return err; +} + +static int read_buildid(struct map *self, struct perf_session *session) +{ + const char *name = self->dso->long_name; + int err; + + if (filename__read_build_id(self->dso->long_name, self->dso->build_id, + sizeof(self->dso->build_id)) > 0) { + char sbuild_id[BUILD_ID_SIZE * 2 + 1]; + + self->dso->has_build_id = true; + + build_id__sprintf(self->dso->build_id, + sizeof(self->dso->build_id), + sbuild_id); + pr_debug("build id found for %s: %s\n", self->dso->long_name, + sbuild_id); + } + + if (self->dso->has_build_id) { + u16 misc = PERF_RECORD_MISC_USER; + struct machine *machine; + + misc = self->dso->kernel ? PERF_RECORD_MISC_KERNEL : misc; + + machine = perf_session__find_host_machine(session); + if (!machine) { + pr_err("Can't find machine for session\n"); + return -1; + } + + err = event__synthesize_build_id(self->dso, misc, + event__repipe, machine, + session); + if (err) { + pr_err("Can't synthesize build_id event for %s\n", + name); + return -1; + } + } else { + pr_debug("no build_id found for %s\n", name); + return -1; + } + + return 0; +} + +static int event__inject_buildid(event_t *event, struct perf_session *session) +{ + struct addr_location al; + struct thread *thread; + u8 cpumode; + int err = 0; + + cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; + + thread = perf_session__findnew(session, event->ip.pid); + if (thread == NULL) { + pr_err("problem processing %d event, skipping it.\n", + event->header.type); + err = -1; + goto repipe; + } + + thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION, + event->ip.pid, event->ip.ip, &al); + + if (al.map != NULL) { + if (!al.map->dso->hit) { + al.map->dso->hit = 1; + if (map__load(al.map, NULL) >= 0) + read_buildid(al.map, session); + else + pr_warning("no symbols found in %s, maybe " + "install a debug package?\n", + al.map->dso->long_name); + } + } + +repipe: + event__repipe(event, session); + return err; +} + +struct perf_event_ops inject_ops = { + .sample = event__repipe, + .mmap = event__repipe, + .comm = event__repipe, + .fork = event__repipe, + .exit = event__repipe, + .lost = event__repipe, + .read = event__repipe, + .throttle = event__repipe, + .unthrottle = event__repipe, + .attr = event__repipe, + .event_type = event__repipe, + .tracing_data = event__repipe, + .build_id = event__repipe, +}; + +extern volatile int session_done; + +static void sig_handler(int sig __attribute__((__unused__))) +{ + session_done = 1; +} + +static int __cmd_inject(void) +{ + struct perf_session *session; + int ret = -EINVAL; + + signal(SIGINT, sig_handler); + + if (inject_build_ids) { + inject_ops.sample = event__inject_buildid; + inject_ops.mmap = event__repipe_mmap; + inject_ops.fork = event__repipe_task; + inject_ops.tracing_data = event__repipe_tracing_data; + } + + session = perf_session__new(input_name, O_RDONLY, false, true); + if (session == NULL) + return -ENOMEM; + + ret = perf_session__process_events(session, &inject_ops); + + perf_session__delete(session); + + return ret; +} + +static const char * const report_usage[] = { + "perf inject []", + NULL +}; + +static const struct option options[] = { + OPT_BOOLEAN('b', "inject build-ids", &inject_build_ids, + "Inject build-ids into the output stream"), + OPT_INCR('v', "verbose", &verbose, + "be more verbose (show build ids, etc)"), + OPT_END() +}; + +int cmd_inject(int argc, const char **argv, const char *prefix __used) +{ + argc = parse_options(argc, argv, options, report_usage, 0); + + /* + * Any (unrecognized) arguments left? + */ + if (argc) + usage_with_options(report_usage, options); + + if (symbol__init() < 0) + return -1; + + return __cmd_inject(); +} diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index ee05dba..31f60a2 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c @@ -492,7 +492,7 @@ static void sort_result(void) static int __cmd_kmem(void) { int err = -EINVAL; - struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0); + struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0, false); if (session == NULL) return -ENOMEM; diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index ce27675..6605000 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c @@ -818,7 +818,7 @@ static struct perf_event_ops eops = { static int read_events(void) { - session = perf_session__new(input_name, O_RDONLY, 0); + session = perf_session__new(input_name, O_RDONLY, 0, false); if (!session) die("Initializing perf session failed\n"); diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 1a73796..e382d93 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -548,7 +548,7 @@ static int __cmd_record(int argc, const char **argv) } session = perf_session__new(output_name, O_WRONLY, - write_mode == WRITE_FORCE); + write_mode == WRITE_FORCE, false); if (session == NULL) { pr_err("Not enough memory for reading perf file header\n"); return -1; diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index f1b46eb..0152b54 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -289,7 +289,7 @@ static int __cmd_report(void) signal(SIGINT, sig_handler); - session = perf_session__new(input_name, O_RDONLY, force); + session = perf_session__new(input_name, O_RDONLY, force, false); if (session == NULL) return -ENOMEM; diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 94453f1..aef6ed0 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -1660,7 +1660,7 @@ static struct perf_event_ops event_ops = { static int read_events(void) { int err = -EINVAL; - struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0); + struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0, false); if (session == NULL) return -ENOMEM; diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index c35aa44..5a52ed9 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c @@ -936,7 +936,7 @@ static struct perf_event_ops event_ops = { static int __cmd_timechart(void) { - struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0); + struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0, false); int ret = -EINVAL; if (session == NULL) diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index d95281f..3de3977 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -1287,7 +1287,7 @@ static int __cmd_top(void) * FIXME: perf_session__new should allow passing a O_MMAP, so that all this * mmap reading, etc is encapsulated in it. Use O_WRONLY for now. */ - struct perf_session *session = perf_session__new(NULL, O_WRONLY, false); + struct perf_session *session = perf_session__new(NULL, O_WRONLY, false, false); if (session == NULL) return -ENOMEM; diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 77f556f..9c483e9 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -661,7 +661,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used) if (!script_name) setup_pager(); - session = perf_session__new(input_name, O_RDONLY, 0); + session = perf_session__new(input_name, O_RDONLY, 0, false); if (session == NULL) return -ENOMEM; diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h index 34a8a9a..921245b 100644 --- a/tools/perf/builtin.h +++ b/tools/perf/builtin.h @@ -34,5 +34,6 @@ extern int cmd_kmem(int argc, const char **argv, const char *prefix); extern int cmd_lock(int argc, const char **argv, const char *prefix); extern int cmd_kvm(int argc, const char **argv, const char *prefix); extern int cmd_test(int argc, const char **argv, const char *prefix); +extern int cmd_inject(int argc, const char **argv, const char *prefix); #endif diff --git a/tools/perf/perf.c b/tools/perf/perf.c index 5ff9b5b..08e0e5d 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c @@ -309,6 +309,7 @@ static void handle_internal_command(int argc, const char **argv) { "lock", cmd_lock, 0 }, { "kvm", cmd_kvm, 0 }, { "test", cmd_test, 0 }, + { "inject", cmd_inject, 0 }, }; unsigned int i; static const char ext[] = STRIP_EXTENSION; diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 2d1d97e..79da0e5 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -713,10 +713,18 @@ static int __event_process_build_id(struct build_id_event *bev, dso = __dsos__findnew(head, filename); if (dso != NULL) { + char sbuild_id[BUILD_ID_SIZE * 2 + 1]; + dso__set_build_id(dso, &bev->build_id); - if (filename[0] == '[') - dso->kernel = dso_type; - } + + if (filename[0] == '[') + dso->kernel = dso_type; + + build_id__sprintf(dso->build_id, sizeof(dso->build_id), + sbuild_id); + pr_debug("build id event received for %s: %s\n", + dso->long_name, sbuild_id); + } err = 0; out: @@ -767,7 +775,7 @@ static int perf_file_section__process(struct perf_file_section *self, switch (feat) { case HEADER_TRACE_INFO: - trace_report(fd); + trace_report(fd, false); break; case HEADER_BUILD_ID: @@ -782,12 +790,16 @@ static int perf_file_section__process(struct perf_file_section *self, } static int perf_file_header__read_pipe(struct perf_pipe_file_header *self, - struct perf_header *ph, int fd) + struct perf_header *ph, int fd, + bool repipe) { if (do_read(fd, self, sizeof(*self)) <= 0 || memcmp(&self->magic, __perf_magic, sizeof(self->magic))) return -1; + if (repipe && do_write(STDOUT_FILENO, self, sizeof(*self)) < 0) + return -1; + if (self->size != sizeof(*self)) { u64 size = bswap_64(self->size); @@ -805,7 +817,8 @@ static int perf_header__read_pipe(struct perf_session *session, int fd) struct perf_header *self = &session->header; struct perf_pipe_file_header f_header; - if (perf_file_header__read_pipe(&f_header, self, fd) < 0) { + if (perf_file_header__read_pipe(&f_header, self, fd, + session->repipe) < 0) { pr_debug("incompatible file format\n"); return -EINVAL; } @@ -1096,12 +1109,17 @@ int event__process_tracing_data(event_t *self, lseek(session->fd, offset + sizeof(struct tracing_data_event), SEEK_SET); - size_read = trace_report(session->fd); + size_read = trace_report(session->fd, session->repipe); padding = ALIGN(size_read, sizeof(u64)) - size_read; if (read(session->fd, buf, padding) < 0) die("reading input file"); + if (session->repipe) { + int retw = write(STDOUT_FILENO, buf, padding); + if (retw <= 0 || retw != padding) + die("repiping tracing data padding"); + } if (size_read + padding != size) die("tracing data size mismatch"); @@ -1110,7 +1128,8 @@ int event__process_tracing_data(event_t *self, } int event__synthesize_build_id(struct dso *pos, u16 misc, - event__handler_t process, struct machine *machine, + event__handler_t process, + struct machine *machine, struct perf_session *session) { event_t ev; diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index a8dd73e..5d353e7 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -77,7 +77,7 @@ int perf_session__create_kernel_maps(struct perf_session *self) return ret; } -struct perf_session *perf_session__new(const char *filename, int mode, bool force) +struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe) { size_t len = filename ? strlen(filename) + 1 : 0; struct perf_session *self = zalloc(sizeof(*self) + len); @@ -97,6 +97,7 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc self->cwdlen = 0; self->unknown_events = 0; self->machines = RB_ROOT; + self->repipe = repipe; self->ordered_samples.flush_limit = ULLONG_MAX; INIT_LIST_HEAD(&self->ordered_samples.samples_head); diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 61ca92e..f2b2c6a 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -34,6 +34,7 @@ struct perf_session { u64 sample_type; int fd; bool fd_pipe; + bool repipe; int cwdlen; char *cwd; struct ordered_samples ordered_samples; @@ -59,7 +60,7 @@ struct perf_event_ops { bool ordered_samples; }; -struct perf_session *perf_session__new(const char *filename, int mode, bool force); +struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe); void perf_session__delete(struct perf_session *self); void perf_event_header__bswap(struct perf_event_header *self); diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c index 44889c9..43f19c1 100644 --- a/tools/perf/util/trace-event-read.c +++ b/tools/perf/util/trace-event-read.c @@ -51,6 +51,7 @@ static int long_size; static unsigned long page_size; static ssize_t calc_data_size; +static bool repipe; static int do_read(int fd, void *buf, int size) { @@ -62,6 +63,13 @@ static int do_read(int fd, void *buf, int size) if (ret <= 0) return -1; + if (repipe) { + int retw = write(STDOUT_FILENO, buf, ret); + + if (retw <= 0 || retw != ret) + die("repiping input file"); + } + size -= ret; buf += ret; } @@ -116,6 +124,13 @@ static char *read_string(void) if (!r) die("no data"); + if (repipe) { + int retw = write(STDOUT_FILENO, &c, 1); + + if (retw <= 0 || retw != r) + die("repiping input file string"); + } + buf[size++] = c; if (!c) @@ -454,7 +469,7 @@ struct record *trace_read_data(int cpu) return data; } -ssize_t trace_report(int fd) +ssize_t trace_report(int fd, bool __repipe) { char buf[BUFSIZ]; char test[] = { 23, 8, 68 }; @@ -465,6 +480,7 @@ ssize_t trace_report(int fd) ssize_t size; calc_data_size = 1; + repipe = __repipe; input_fd = fd; @@ -499,6 +515,7 @@ ssize_t trace_report(int fd) size = calc_data_size - 1; calc_data_size = 0; + repipe = false; if (show_funcs) { print_funcs(); diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h index 1f45d46..ebfee80 100644 --- a/tools/perf/util/trace-event.h +++ b/tools/perf/util/trace-event.h @@ -163,7 +163,7 @@ struct record *trace_read_data(int cpu); void parse_set_info(int nr_cpus, int long_sz); -ssize_t trace_report(int fd); +ssize_t trace_report(int fd, bool repipe); void *malloc_or_die(unsigned int size); -- cgit v0.10.2 From 2c9faa060064343a4a0b16f5b77f3c61d1d17e23 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 2 May 2010 13:37:24 -0300 Subject: perf record: Don't exit in live mode when no tracepoints are enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With this I was able to actually test Tom Zanussi's two previous patches in my usual perf testing ways, i.e. without any tracepoints activated. Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index e382d93..ac989e9 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -666,12 +666,15 @@ static int __cmd_record(int argc, const char **argv) nr_counters, process_synthesized_event, session); - if (err <= 0) { - pr_err("Couldn't record tracing data.\n"); - return err; - } - - advance_output(err); + /* + * FIXME err <= 0 here actually means that there were no tracepoints + * so its not really an error, just that we don't need to synthesize + * anything. + * We really have to return this more properly and also propagate + * errors that now are calling die() + */ + if (err > 0) + advance_output(err); } machine = perf_session__find_host_machine(session); -- cgit v0.10.2 From d94f944e108da21badabd99f527b25e03b677b96 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Thu, 25 Mar 2010 17:12:41 +0300 Subject: ARM: cns3xxx: Add basic support for Cavium Networks CNS3xxx processors This patch adds very basic support for ECONA CNS3xxx ARM11 MPcore (ARMv6) dual-core processors. Note that SMP is not yet supported, as well as many peripheral devices. Support for these features will be added later. Signed-off-by: Anton Vorontsov diff --git a/MAINTAINERS b/MAINTAINERS index d5b0b1b..27299d1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -586,6 +586,12 @@ F: drivers/mtd/nand/bcm_umi_bch.c F: drivers/mtd/nand/bcm_umi_hamming.c F: drivers/mtd/nand/nand_bcm_umi.h +ARM/CAVIUM NETWORKS CNS3XXX MACHINE SUPPORT +M: Anton Vorontsov +S: Maintained +F: arch/arm/mach-cns3xxx/ +T: git git://git.infradead.org/users/cbou/linux-cns3xxx.git + ARM/CIRRUS LOGIC EP93XX ARM ARCHITECTURE M: Hartley Sweeten M: Ryan Mallon diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 92622eb..572e6cc 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -297,6 +297,15 @@ config ARCH_CLPS711X help Support for Cirrus Logic 711x/721x based boards. +config ARCH_CNS3XXX + bool "Cavium Networks CNS3XXX family" + select CPU_V6 + select GENERIC_TIME + select GENERIC_CLOCKEVENTS + select ARM_GIC + help + Support for Cavium Networks CNS3XXX platform. + config ARCH_GEMINI bool "Cortina Systems Gemini" select CPU_FA526 @@ -817,6 +826,8 @@ source "arch/arm/mach-bcmring/Kconfig" source "arch/arm/mach-clps711x/Kconfig" +source "arch/arm/mach-cns3xxx/Kconfig" + source "arch/arm/mach-davinci/Kconfig" source "arch/arm/mach-dove/Kconfig" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index ed820e7..3e312ec 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -121,6 +121,7 @@ machine-$(CONFIG_ARCH_AAEC2000) := aaec2000 machine-$(CONFIG_ARCH_AT91) := at91 machine-$(CONFIG_ARCH_BCMRING) := bcmring machine-$(CONFIG_ARCH_CLPS711X) := clps711x +machine-$(CONFIG_ARCH_CNS3XXX) := cns3xxx machine-$(CONFIG_ARCH_DAVINCI) := davinci machine-$(CONFIG_ARCH_DOVE) := dove machine-$(CONFIG_ARCH_EBSA110) := ebsa110 diff --git a/arch/arm/mach-cns3xxx/Kconfig b/arch/arm/mach-cns3xxx/Kconfig new file mode 100644 index 0000000..20284cd --- /dev/null +++ b/arch/arm/mach-cns3xxx/Kconfig @@ -0,0 +1,4 @@ +menu "CNS3XXX platform type" + depends on ARCH_CNS3XXX + +endmenu diff --git a/arch/arm/mach-cns3xxx/Makefile b/arch/arm/mach-cns3xxx/Makefile new file mode 100644 index 0000000..e5e76dd --- /dev/null +++ b/arch/arm/mach-cns3xxx/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_ARCH_CNS3XXX) += core.o pm.o diff --git a/arch/arm/mach-cns3xxx/Makefile.boot b/arch/arm/mach-cns3xxx/Makefile.boot new file mode 100644 index 0000000..7770128 --- /dev/null +++ b/arch/arm/mach-cns3xxx/Makefile.boot @@ -0,0 +1,3 @@ + zreladdr-y := 0x00008000 +params_phys-y := 0x00000100 +initrd_phys-y := 0x00C00000 diff --git a/arch/arm/mach-cns3xxx/core.c b/arch/arm/mach-cns3xxx/core.c new file mode 100644 index 0000000..9ca4d58 --- /dev/null +++ b/arch/arm/mach-cns3xxx/core.c @@ -0,0 +1,249 @@ +/* + * Copyright 1999 - 2003 ARM Limited + * Copyright 2000 Deep Blue Solutions Ltd + * Copyright 2008 Cavium Networks + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, Version 2, as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "core.h" + +static struct map_desc cns3xxx_io_desc[] __initdata = { + { + .virtual = CNS3XXX_TC11MP_TWD_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_TC11MP_TWD_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_TC11MP_GIC_CPU_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_TC11MP_GIC_DIST_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_TIMER1_2_3_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_TIMER1_2_3_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_GPIOA_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_GPIOA_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_GPIOB_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_GPIOB_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_MISC_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_MISC_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = CNS3XXX_PM_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_PM_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, +}; + +void __init cns3xxx_map_io(void) +{ + iotable_init(cns3xxx_io_desc, ARRAY_SIZE(cns3xxx_io_desc)); +} + +/* used by entry-macro.S */ +void __iomem *gic_cpu_base_addr; + +void __init cns3xxx_init_irq(void) +{ + gic_cpu_base_addr = __io(CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT); + gic_dist_init(0, __io(CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT), 29); + gic_cpu_init(0, gic_cpu_base_addr); +} + +void cns3xxx_power_off(void) +{ + u32 __iomem *pm_base = __io(CNS3XXX_PM_BASE_VIRT); + u32 clkctrl; + + printk(KERN_INFO "powering system down...\n"); + + clkctrl = readl(pm_base + PM_SYS_CLK_CTRL_OFFSET); + clkctrl &= 0xfffff1ff; + clkctrl |= (0x5 << 9); /* Hibernate */ + writel(clkctrl, pm_base + PM_SYS_CLK_CTRL_OFFSET); + +} + +/* + * Timer + */ +static void __iomem *cns3xxx_tmr1; + +static void cns3xxx_timer_set_mode(enum clock_event_mode mode, + struct clock_event_device *clk) +{ + unsigned long ctrl = readl(cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET); + int pclk = cns3xxx_cpu_clock() / 8; + int reload; + + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + reload = pclk * 20 / (3 * HZ) * 0x25000; + writel(reload, cns3xxx_tmr1 + TIMER1_AUTO_RELOAD_OFFSET); + ctrl |= (1 << 0) | (1 << 2) | (1 << 9); + break; + case CLOCK_EVT_MODE_ONESHOT: + /* period set, and timer enabled in 'next_event' hook */ + ctrl |= (1 << 2) | (1 << 9); + break; + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + default: + ctrl = 0; + } + + writel(ctrl, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET); +} + +static int cns3xxx_timer_set_next_event(unsigned long evt, + struct clock_event_device *unused) +{ + unsigned long ctrl = readl(cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET); + + writel(evt, cns3xxx_tmr1 + TIMER1_AUTO_RELOAD_OFFSET); + writel(ctrl | (1 << 0), cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET); + + return 0; +} + +static struct clock_event_device cns3xxx_tmr1_clockevent = { + .name = "cns3xxx timer1", + .shift = 8, + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + .set_mode = cns3xxx_timer_set_mode, + .set_next_event = cns3xxx_timer_set_next_event, + .rating = 350, + .cpumask = cpu_all_mask, +}; + +static void __init cns3xxx_clockevents_init(unsigned int timer_irq) +{ + cns3xxx_tmr1_clockevent.irq = timer_irq; + cns3xxx_tmr1_clockevent.mult = + div_sc((cns3xxx_cpu_clock() >> 3) * 1000000, NSEC_PER_SEC, + cns3xxx_tmr1_clockevent.shift); + cns3xxx_tmr1_clockevent.max_delta_ns = + clockevent_delta2ns(0xffffffff, &cns3xxx_tmr1_clockevent); + cns3xxx_tmr1_clockevent.min_delta_ns = + clockevent_delta2ns(0xf, &cns3xxx_tmr1_clockevent); + + clockevents_register_device(&cns3xxx_tmr1_clockevent); +} + +/* + * IRQ handler for the timer + */ +static irqreturn_t cns3xxx_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = &cns3xxx_tmr1_clockevent; + u32 __iomem *stat = cns3xxx_tmr1 + TIMER1_2_INTERRUPT_STATUS_OFFSET; + u32 val; + + /* Clear the interrupt */ + val = readl(stat); + writel(val & ~(1 << 2), stat); + + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +static struct irqaction cns3xxx_timer_irq = { + .name = "timer", + .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .handler = cns3xxx_timer_interrupt, +}; + +/* + * Set up the clock source and clock events devices + */ +static void __init __cns3xxx_timer_init(unsigned int timer_irq) +{ + u32 val; + u32 irq_mask; + + /* + * Initialise to a known state (all timers off) + */ + + /* disable timer1 and timer2 */ + writel(0, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET); + /* stop free running timer3 */ + writel(0, cns3xxx_tmr1 + TIMER_FREERUN_CONTROL_OFFSET); + + /* timer1 */ + writel(0x5C800, cns3xxx_tmr1 + TIMER1_COUNTER_OFFSET); + writel(0x5C800, cns3xxx_tmr1 + TIMER1_AUTO_RELOAD_OFFSET); + + writel(0, cns3xxx_tmr1 + TIMER1_MATCH_V1_OFFSET); + writel(0, cns3xxx_tmr1 + TIMER1_MATCH_V2_OFFSET); + + /* mask irq, non-mask timer1 overflow */ + irq_mask = readl(cns3xxx_tmr1 + TIMER1_2_INTERRUPT_MASK_OFFSET); + irq_mask &= ~(1 << 2); + irq_mask |= 0x03; + writel(irq_mask, cns3xxx_tmr1 + TIMER1_2_INTERRUPT_MASK_OFFSET); + + /* down counter */ + val = readl(cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET); + val |= (1 << 9); + writel(val, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET); + + /* timer2 */ + writel(0, cns3xxx_tmr1 + TIMER2_MATCH_V1_OFFSET); + writel(0, cns3xxx_tmr1 + TIMER2_MATCH_V2_OFFSET); + + /* mask irq */ + irq_mask = readl(cns3xxx_tmr1 + TIMER1_2_INTERRUPT_MASK_OFFSET); + irq_mask |= ((1 << 3) | (1 << 4) | (1 << 5)); + writel(irq_mask, cns3xxx_tmr1 + TIMER1_2_INTERRUPT_MASK_OFFSET); + + /* down counter */ + val = readl(cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET); + val |= (1 << 10); + writel(val, cns3xxx_tmr1 + TIMER1_2_CONTROL_OFFSET); + + /* Make irqs happen for the system timer */ + setup_irq(timer_irq, &cns3xxx_timer_irq); + + cns3xxx_clockevents_init(timer_irq); +} + +static void __init cns3xxx_timer_init(void) +{ + cns3xxx_tmr1 = __io(CNS3XXX_TIMER1_2_3_BASE_VIRT); + + __cns3xxx_timer_init(IRQ_CNS3XXX_TIMER0); +} + +struct sys_timer cns3xxx_timer = { + .init = cns3xxx_timer_init, +}; diff --git a/arch/arm/mach-cns3xxx/core.h b/arch/arm/mach-cns3xxx/core.h new file mode 100644 index 0000000..6b33ec1 --- /dev/null +++ b/arch/arm/mach-cns3xxx/core.h @@ -0,0 +1,23 @@ +/* + * Copyright 2000 Deep Blue Solutions Ltd + * Copyright 2004 ARM Limited + * Copyright 2008 Cavium Networks + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, Version 2, as + * published by the Free Software Foundation. + */ + +#ifndef __CNS3XXX_CORE_H +#define __CNS3XXX_CORE_H + +extern void __iomem *gic_cpu_base_addr; +extern struct sys_timer cns3xxx_timer; + +void __init cns3xxx_map_io(void); +void __init cns3xxx_init_irq(void); +void cns3xxx_power_off(void); +void cns3xxx_pwr_power_up(unsigned int block); +void cns3xxx_pwr_power_down(unsigned int block); + +#endif /* __CNS3XXX_CORE_H */ diff --git a/arch/arm/mach-cns3xxx/include/mach/cns3xxx.h b/arch/arm/mach-cns3xxx/include/mach/cns3xxx.h new file mode 100644 index 0000000..8a2f5a2 --- /dev/null +++ b/arch/arm/mach-cns3xxx/include/mach/cns3xxx.h @@ -0,0 +1,635 @@ +/* + * Copyright 2008 Cavium Networks + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, Version 2, as + * published by the Free Software Foundation. + */ + +#ifndef __MACH_BOARD_CNS3XXXH +#define __MACH_BOARD_CNS3XXXH + +/* + * Memory map + */ +#define CNS3XXX_FLASH_BASE 0x10000000 /* Flash/SRAM Memory Bank 0 */ +#define CNS3XXX_FLASH_SIZE SZ_256M + +#define CNS3XXX_DDR2SDRAM_BASE 0x20000000 /* DDR2 SDRAM Memory */ + +#define CNS3XXX_SPI_FLASH_BASE 0x60000000 /* SPI Serial Flash Memory */ + +#define CNS3XXX_SWITCH_BASE 0x70000000 /* Switch and HNAT Control */ +#define CNS3XXX_SWITCH_BASE_VIRT 0xFFF00000 + +#define CNS3XXX_PPE_BASE 0x70001000 /* HANT */ +#define CNS3XXX_PPE_BASE_VIRT 0xFFF50000 + +#define CNS3XXX_EMBEDDED_SRAM_BASE 0x70002000 /* HANT Embedded SRAM */ +#define CNS3XXX_EMBEDDED_SRAM_BASE_VIRT 0xFFF60000 + +#define CNS3XXX_SSP_BASE 0x71000000 /* Synchronous Serial Port - SPI/PCM/I2C */ +#define CNS3XXX_SSP_BASE_VIRT 0xFFF01000 + +#define CNS3XXX_DMC_BASE 0x72000000 /* DMC Control (DDR2 SDRAM) */ +#define CNS3XXX_DMC_BASE_VIRT 0xFFF02000 + +#define CNS3XXX_SMC_BASE 0x73000000 /* SMC Control */ +#define CNS3XXX_SMC_BASE_VIRT 0xFFF03000 + +#define SMC_MEMC_STATUS_OFFSET 0x000 +#define SMC_MEMIF_CFG_OFFSET 0x004 +#define SMC_MEMC_CFG_SET_OFFSET 0x008 +#define SMC_MEMC_CFG_CLR_OFFSET 0x00C +#define SMC_DIRECT_CMD_OFFSET 0x010 +#define SMC_SET_CYCLES_OFFSET 0x014 +#define SMC_SET_OPMODE_OFFSET 0x018 +#define SMC_REFRESH_PERIOD_0_OFFSET 0x020 +#define SMC_REFRESH_PERIOD_1_OFFSET 0x024 +#define SMC_SRAM_CYCLES0_0_OFFSET 0x100 +#define SMC_NAND_CYCLES0_0_OFFSET 0x100 +#define SMC_OPMODE0_0_OFFSET 0x104 +#define SMC_SRAM_CYCLES0_1_OFFSET 0x120 +#define SMC_NAND_CYCLES0_1_OFFSET 0x120 +#define SMC_OPMODE0_1_OFFSET 0x124 +#define SMC_USER_STATUS_OFFSET 0x200 +#define SMC_USER_CONFIG_OFFSET 0x204 +#define SMC_ECC_STATUS_OFFSET 0x300 +#define SMC_ECC_MEMCFG_OFFSET 0x304 +#define SMC_ECC_MEMCOMMAND1_OFFSET 0x308 +#define SMC_ECC_MEMCOMMAND2_OFFSET 0x30C +#define SMC_ECC_ADDR0_OFFSET 0x310 +#define SMC_ECC_ADDR1_OFFSET 0x314 +#define SMC_ECC_VALUE0_OFFSET 0x318 +#define SMC_ECC_VALUE1_OFFSET 0x31C +#define SMC_ECC_VALUE2_OFFSET 0x320 +#define SMC_ECC_VALUE3_OFFSET 0x324 +#define SMC_PERIPH_ID_0_OFFSET 0xFE0 +#define SMC_PERIPH_ID_1_OFFSET 0xFE4 +#define SMC_PERIPH_ID_2_OFFSET 0xFE8 +#define SMC_PERIPH_ID_3_OFFSET 0xFEC +#define SMC_PCELL_ID_0_OFFSET 0xFF0 +#define SMC_PCELL_ID_1_OFFSET 0xFF4 +#define SMC_PCELL_ID_2_OFFSET 0xFF8 +#define SMC_PCELL_ID_3_OFFSET 0xFFC + +#define CNS3XXX_GPIOA_BASE 0x74000000 /* GPIO port A */ +#define CNS3XXX_GPIOA_BASE_VIRT 0xFFF04000 + +#define CNS3XXX_GPIOB_BASE 0x74800000 /* GPIO port B */ +#define CNS3XXX_GPIOB_BASE_VIRT 0xFFF05000 + +#define CNS3XXX_RTC_BASE 0x75000000 /* Real Time Clock */ +#define CNS3XXX_RTC_BASE_VIRT 0xFFF06000 + +#define RTC_SEC_OFFSET 0x00 +#define RTC_MIN_OFFSET 0x04 +#define RTC_HOUR_OFFSET 0x08 +#define RTC_DAY_OFFSET 0x0C +#define RTC_SEC_ALM_OFFSET 0x10 +#define RTC_MIN_ALM_OFFSET 0x14 +#define RTC_HOUR_ALM_OFFSET 0x18 +#define RTC_REC_OFFSET 0x1C +#define RTC_CTRL_OFFSET 0x20 +#define RTC_INTR_STS_OFFSET 0x34 + +#define CNS3XXX_MISC_BASE 0x76000000 /* Misc Control */ +#define CNS3XXX_MISC_BASE_VIRT 0xFFF07000 /* Misc Control */ + +#define CNS3XXX_PM_BASE 0x77000000 /* Power Management Control */ +#define CNS3XXX_PM_BASE_VIRT 0xFFF08000 + +#define PM_CLK_GATE_OFFSET 0x00 +#define PM_SOFT_RST_OFFSET 0x04 +#define PM_HS_CFG_OFFSET 0x08 +#define PM_CACTIVE_STA_OFFSET 0x0C +#define PM_PWR_STA_OFFSET 0x10 +#define PM_SYS_CLK_CTRL_OFFSET 0x14 +#define PM_PLL_LCD_I2S_CTRL_OFFSET 0x18 +#define PM_PLL_HM_PD_OFFSET 0x1C + +#define CNS3XXX_UART0_BASE 0x78000000 /* UART 0 */ +#define CNS3XXX_UART0_BASE_VIRT 0xFFF09000 + +#define CNS3XXX_UART1_BASE 0x78400000 /* UART 1 */ +#define CNS3XXX_UART1_BASE_VIRT 0xFFF0A000 + +#define CNS3XXX_UART2_BASE 0x78800000 /* UART 2 */ +#define CNS3XXX_UART2_BASE_VIRT 0xFFF0B000 + +#define CNS3XXX_DMAC_BASE 0x79000000 /* Generic DMA Control */ +#define CNS3XXX_DMAC_BASE_VIRT 0xFFF0D000 + +#define CNS3XXX_CORESIGHT_BASE 0x7A000000 /* CoreSight */ +#define CNS3XXX_CORESIGHT_BASE_VIRT 0xFFF0E000 + +#define CNS3XXX_CRYPTO_BASE 0x7B000000 /* Crypto */ +#define CNS3XXX_CRYPTO_BASE_VIRT 0xFFF0F000 + +#define CNS3XXX_I2S_BASE 0x7C000000 /* I2S */ +#define CNS3XXX_I2S_BASE_VIRT 0xFFF10000 + +#define CNS3XXX_TIMER1_2_3_BASE 0x7C800000 /* Timer */ +#define CNS3XXX_TIMER1_2_3_BASE_VIRT 0xFFF10800 + +#define TIMER1_COUNTER_OFFSET 0x00 +#define TIMER1_AUTO_RELOAD_OFFSET 0x04 +#define TIMER1_MATCH_V1_OFFSET 0x08 +#define TIMER1_MATCH_V2_OFFSET 0x0C + +#define TIMER2_COUNTER_OFFSET 0x10 +#define TIMER2_AUTO_RELOAD_OFFSET 0x14 +#define TIMER2_MATCH_V1_OFFSET 0x18 +#define TIMER2_MATCH_V2_OFFSET 0x1C + +#define TIMER1_2_CONTROL_OFFSET 0x30 +#define TIMER1_2_INTERRUPT_STATUS_OFFSET 0x34 +#define TIMER1_2_INTERRUPT_MASK_OFFSET 0x38 + +#define TIMER_FREERUN_OFFSET 0x40 +#define TIMER_FREERUN_CONTROL_OFFSET 0x44 + +#define CNS3XXX_HCIE_BASE 0x7D000000 /* HCIE Control */ +#define CNS3XXX_HCIE_BASE_VIRT 0xFFF30000 + +#define CNS3XXX_RAID_BASE 0x7E000000 /* RAID Control */ +#define CNS3XXX_RAID_BASE_VIRT 0xFFF12000 + +#define CNS3XXX_AXI_IXC_BASE 0x7F000000 /* AXI IXC */ +#define CNS3XXX_AXI_IXC_BASE_VIRT 0xFFF13000 + +#define CNS3XXX_CLCD_BASE 0x80000000 /* LCD Control */ +#define CNS3XXX_CLCD_BASE_VIRT 0xFFF14000 + +#define CNS3XXX_USBOTG_BASE 0x81000000 /* USB OTG Control */ +#define CNS3XXX_USBOTG_BASE_VIRT 0xFFF15000 + +#define CNS3XXX_USB_BASE 0x82000000 /* USB Host Control */ +#define CNS3XXX_USB_BASE_VIRT 0xFFF16000 + +#define CNS3XXX_SATA2_BASE 0x83000000 /* SATA */ +#define CNS3XXX_SATA2_SIZE SZ_16M +#define CNS3XXX_SATA2_BASE_VIRT 0xFFF17000 + +#define CNS3XXX_CAMERA_BASE 0x84000000 /* Camera Interface */ +#define CNS3XXX_CAMERA_BASE_VIRT 0xFFF18000 + +#define CNS3XXX_SDIO_BASE 0x85000000 /* SDIO */ +#define CNS3XXX_SDIO_BASE_VIRT 0xFFF19000 + +#define CNS3XXX_I2S_TDM_BASE 0x86000000 /* I2S TDM */ +#define CNS3XXX_I2S_TDM_BASE_VIRT 0xFFF1A000 + +#define CNS3XXX_2DG_BASE 0x87000000 /* 2D Graphic Control */ +#define CNS3XXX_2DG_BASE_VIRT 0xFFF1B000 + +#define CNS3XXX_USB_OHCI_BASE 0x88000000 /* USB OHCI */ +#define CNS3XXX_USB_OHCI_BASE_VIRT 0xFFF1C000 + +#define CNS3XXX_L2C_BASE 0x92000000 /* L2 Cache Control */ +#define CNS3XXX_L2C_BASE_VIRT 0xFFF27000 + +#define CNS3XXX_PCIE0_MEM_BASE 0xA0000000 /* PCIe Port 0 IO/Memory Space */ +#define CNS3XXX_PCIE0_MEM_BASE_VIRT 0xE0000000 + +#define CNS3XXX_PCIE0_HOST_BASE 0xAB000000 /* PCIe Port 0 RC Base */ +#define CNS3XXX_PCIE0_HOST_BASE_VIRT 0xE1000000 + +#define CNS3XXX_PCIE0_IO_BASE 0xAC000000 /* PCIe Port 0 */ +#define CNS3XXX_PCIE0_IO_BASE_VIRT 0xE2000000 + +#define CNS3XXX_PCIE0_CFG0_BASE 0xAD000000 /* PCIe Port 0 CFG Type 0 */ +#define CNS3XXX_PCIE0_CFG0_BASE_VIRT 0xE3000000 + +#define CNS3XXX_PCIE0_CFG1_BASE 0xAE000000 /* PCIe Port 0 CFG Type 1 */ +#define CNS3XXX_PCIE0_CFG1_BASE_VIRT 0xE4000000 + +#define CNS3XXX_PCIE0_MSG_BASE 0xAF000000 /* PCIe Port 0 Message Space */ +#define CNS3XXX_PCIE0_MSG_BASE_VIRT 0xE5000000 + +#define CNS3XXX_PCIE1_MEM_BASE 0xB0000000 /* PCIe Port 1 IO/Memory Space */ +#define CNS3XXX_PCIE1_MEM_BASE_VIRT 0xE8000000 + +#define CNS3XXX_PCIE1_HOST_BASE 0xBB000000 /* PCIe Port 1 RC Base */ +#define CNS3XXX_PCIE1_HOST_BASE_VIRT 0xE9000000 + +#define CNS3XXX_PCIE1_IO_BASE 0xBC000000 /* PCIe Port 1 */ +#define CNS3XXX_PCIE1_IO_BASE_VIRT 0xEA000000 + +#define CNS3XXX_PCIE1_CFG0_BASE 0xBD000000 /* PCIe Port 1 CFG Type 0 */ +#define CNS3XXX_PCIE1_CFG0_BASE_VIRT 0xEB000000 + +#define CNS3XXX_PCIE1_CFG1_BASE 0xBE000000 /* PCIe Port 1 CFG Type 1 */ +#define CNS3XXX_PCIE1_CFG1_BASE_VIRT 0xEC000000 + +#define CNS3XXX_PCIE1_MSG_BASE 0xBF000000 /* PCIe Port 1 Message Space */ +#define CNS3XXX_PCIE1_MSG_BASE_VIRT 0xED000000 + +/* + * Testchip peripheral and fpga gic regions + */ +#define CNS3XXX_TC11MP_SCU_BASE 0x90000000 /* IRQ, Test chip */ +#define CNS3XXX_TC11MP_SCU_BASE_VIRT 0xFF000000 + +#define CNS3XXX_TC11MP_GIC_CPU_BASE 0x90000100 /* Test chip interrupt controller CPU interface */ +#define CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT 0xFF000100 + +#define CNS3XXX_TC11MP_TWD_BASE 0x90000600 +#define CNS3XXX_TC11MP_TWD_BASE_VIRT 0xFF000600 + +#define CNS3XXX_TC11MP_GIC_DIST_BASE 0x90001000 /* Test chip interrupt controller distributor */ +#define CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT 0xFF001000 + +#define CNS3XXX_TC11MP_L220_BASE 0x92002000 /* L220 registers */ +#define CNS3XXX_TC11MP_L220_BASE_VIRT 0xFF002000 + +/* + * Misc block + */ +#define MISC_MEM_MAP(offs) (void __iomem *)(CNS3XXX_MISC_BASE_VIRT + (offs)) +#define MISC_MEM_MAP_VALUE(offset) (*((volatile unsigned int *)(CNS3XXX_MISC_BASE_VIRT + (offset)))) + +#define MISC_MEMORY_REMAP_REG MISC_MEM_MAP_VALUE(0x00) +#define MISC_CHIP_CONFIG_REG MISC_MEM_MAP_VALUE(0x04) +#define MISC_DEBUG_PROBE_DATA_REG MISC_MEM_MAP_VALUE(0x08) +#define MISC_DEBUG_PROBE_SELECTION_REG MISC_MEM_MAP_VALUE(0x0C) +#define MISC_IO_PIN_FUNC_SELECTION_REG MISC_MEM_MAP_VALUE(0x10) +#define MISC_GPIOA_PIN_ENABLE_REG MISC_MEM_MAP_VALUE(0x14) +#define MISC_GPIOB_PIN_ENABLE_REG MISC_MEM_MAP_VALUE(0x18) +#define MISC_IO_PAD_DRIVE_STRENGTH_CTRL_A MISC_MEM_MAP_VALUE(0x1C) +#define MISC_IO_PAD_DRIVE_STRENGTH_CTRL_B MISC_MEM_MAP_VALUE(0x20) +#define MISC_GPIOA_15_0_PULL_CTRL_REG MISC_MEM_MAP_VALUE(0x24) +#define MISC_GPIOA_16_31_PULL_CTRL_REG MISC_MEM_MAP_VALUE(0x28) +#define MISC_GPIOB_15_0_PULL_CTRL_REG MISC_MEM_MAP_VALUE(0x2C) +#define MISC_GPIOB_16_31_PULL_CTRL_REG MISC_MEM_MAP_VALUE(0x30) +#define MISC_IO_PULL_CTRL_REG MISC_MEM_MAP_VALUE(0x34) +#define MISC_E_FUSE_31_0_REG MISC_MEM_MAP_VALUE(0x40) +#define MISC_E_FUSE_63_32_REG MISC_MEM_MAP_VALUE(0x44) +#define MISC_E_FUSE_95_64_REG MISC_MEM_MAP_VALUE(0x48) +#define MISC_E_FUSE_127_96_REG MISC_MEM_MAP_VALUE(0x4C) +#define MISC_SOFTWARE_TEST_1_REG MISC_MEM_MAP_VALUE(0x50) +#define MISC_SOFTWARE_TEST_2_REG MISC_MEM_MAP_VALUE(0x54) + +#define MISC_SATA_POWER_MODE MISC_MEM_MAP_VALUE(0x310) + +#define MISC_USB_CFG_REG MISC_MEM_MAP_VALUE(0x800) +#define MISC_USB_STS_REG MISC_MEM_MAP_VALUE(0x804) +#define MISC_USBPHY00_CFG_REG MISC_MEM_MAP_VALUE(0x808) +#define MISC_USBPHY01_CFG_REG MISC_MEM_MAP_VALUE(0x80c) +#define MISC_USBPHY10_CFG_REG MISC_MEM_MAP_VALUE(0x810) +#define MISC_USBPHY11_CFG_REG MISC_MEM_MAP_VALUE(0x814) + +#define MISC_PCIEPHY_CMCTL(x) MISC_MEM_MAP(0x900 + (x) * 0x004) +#define MISC_PCIEPHY_CTL(x) MISC_MEM_MAP(0x940 + (x) * 0x100) +#define MISC_PCIE_AXIS_AWMISC(x) MISC_MEM_MAP(0x944 + (x) * 0x100) +#define MISC_PCIE_AXIS_ARMISC(x) MISC_MEM_MAP(0x948 + (x) * 0x100) +#define MISC_PCIE_AXIS_RMISC(x) MISC_MEM_MAP(0x94C + (x) * 0x100) +#define MISC_PCIE_AXIS_BMISC(x) MISC_MEM_MAP(0x950 + (x) * 0x100) +#define MISC_PCIE_AXIM_RMISC(x) MISC_MEM_MAP(0x954 + (x) * 0x100) +#define MISC_PCIE_AXIM_BMISC(x) MISC_MEM_MAP(0x958 + (x) * 0x100) +#define MISC_PCIE_CTRL(x) MISC_MEM_MAP(0x95C + (x) * 0x100) +#define MISC_PCIE_PM_DEBUG(x) MISC_MEM_MAP(0x960 + (x) * 0x100) +#define MISC_PCIE_RFC_DEBUG(x) MISC_MEM_MAP(0x964 + (x) * 0x100) +#define MISC_PCIE_CXPL_DEBUGL(x) MISC_MEM_MAP(0x968 + (x) * 0x100) +#define MISC_PCIE_CXPL_DEBUGH(x) MISC_MEM_MAP(0x96C + (x) * 0x100) +#define MISC_PCIE_DIAG_DEBUGH(x) MISC_MEM_MAP(0x970 + (x) * 0x100) +#define MISC_PCIE_W1CLR(x) MISC_MEM_MAP(0x974 + (x) * 0x100) +#define MISC_PCIE_INT_MASK(x) MISC_MEM_MAP(0x978 + (x) * 0x100) +#define MISC_PCIE_INT_STATUS(x) MISC_MEM_MAP(0x97C + (x) * 0x100) + +/* + * Power management and clock control + */ +#define PMU_REG_VALUE(offset) (*((volatile unsigned int *)(CNS3XXX_PM_BASE_VIRT + (offset)))) + +#define PM_CLK_GATE_REG PMU_REG_VALUE(0x000) +#define PM_SOFT_RST_REG PMU_REG_VALUE(0x004) +#define PM_HS_CFG_REG PMU_REG_VALUE(0x008) +#define PM_CACTIVE_STA_REG PMU_REG_VALUE(0x00C) +#define PM_PWR_STA_REG PMU_REG_VALUE(0x010) +#define PM_CLK_CTRL_REG PMU_REG_VALUE(0x014) +#define PM_PLL_LCD_I2S_CTRL_REG PMU_REG_VALUE(0x018) +#define PM_PLL_HM_PD_CTRL_REG PMU_REG_VALUE(0x01C) +#define PM_REGULAT_CTRL_REG PMU_REG_VALUE(0x020) +#define PM_WDT_CTRL_REG PMU_REG_VALUE(0x024) +#define PM_WU_CTRL0_REG PMU_REG_VALUE(0x028) +#define PM_WU_CTRL1_REG PMU_REG_VALUE(0x02C) +#define PM_CSR_REG PMU_REG_VALUE(0x030) + +/* PM_CLK_GATE_REG */ +#define PM_CLK_GATE_REG_OFFSET_SDIO (25) +#define PM_CLK_GATE_REG_OFFSET_GPU (24) +#define PM_CLK_GATE_REG_OFFSET_CIM (23) +#define PM_CLK_GATE_REG_OFFSET_LCDC (22) +#define PM_CLK_GATE_REG_OFFSET_I2S (21) +#define PM_CLK_GATE_REG_OFFSET_RAID (20) +#define PM_CLK_GATE_REG_OFFSET_SATA (19) +#define PM_CLK_GATE_REG_OFFSET_PCIE(x) (17 + (x)) +#define PM_CLK_GATE_REG_OFFSET_USB_HOST (16) +#define PM_CLK_GATE_REG_OFFSET_USB_OTG (15) +#define PM_CLK_GATE_REG_OFFSET_TIMER (14) +#define PM_CLK_GATE_REG_OFFSET_CRYPTO (13) +#define PM_CLK_GATE_REG_OFFSET_HCIE (12) +#define PM_CLK_GATE_REG_OFFSET_SWITCH (11) +#define PM_CLK_GATE_REG_OFFSET_GPIO (10) +#define PM_CLK_GATE_REG_OFFSET_UART3 (9) +#define PM_CLK_GATE_REG_OFFSET_UART2 (8) +#define PM_CLK_GATE_REG_OFFSET_UART1 (7) +#define PM_CLK_GATE_REG_OFFSET_RTC (5) +#define PM_CLK_GATE_REG_OFFSET_GDMA (4) +#define PM_CLK_GATE_REG_OFFSET_SPI_PCM_I2C (3) +#define PM_CLK_GATE_REG_OFFSET_SMC_NFI (1) +#define PM_CLK_GATE_REG_MASK (0x03FFFFBA) + +/* PM_SOFT_RST_REG */ +#define PM_SOFT_RST_REG_OFFST_WARM_RST_FLAG (31) +#define PM_SOFT_RST_REG_OFFST_CPU1 (29) +#define PM_SOFT_RST_REG_OFFST_CPU0 (28) +#define PM_SOFT_RST_REG_OFFST_SDIO (25) +#define PM_SOFT_RST_REG_OFFST_GPU (24) +#define PM_SOFT_RST_REG_OFFST_CIM (23) +#define PM_SOFT_RST_REG_OFFST_LCDC (22) +#define PM_SOFT_RST_REG_OFFST_I2S (21) +#define PM_SOFT_RST_REG_OFFST_RAID (20) +#define PM_SOFT_RST_REG_OFFST_SATA (19) +#define PM_SOFT_RST_REG_OFFST_PCIE(x) (17 + (x)) +#define PM_SOFT_RST_REG_OFFST_USB_HOST (16) +#define PM_SOFT_RST_REG_OFFST_USB_OTG (15) +#define PM_SOFT_RST_REG_OFFST_TIMER (14) +#define PM_SOFT_RST_REG_OFFST_CRYPTO (13) +#define PM_SOFT_RST_REG_OFFST_HCIE (12) +#define PM_SOFT_RST_REG_OFFST_SWITCH (11) +#define PM_SOFT_RST_REG_OFFST_GPIO (10) +#define PM_SOFT_RST_REG_OFFST_UART3 (9) +#define PM_SOFT_RST_REG_OFFST_UART2 (8) +#define PM_SOFT_RST_REG_OFFST_UART1 (7) +#define PM_SOFT_RST_REG_OFFST_RTC (5) +#define PM_SOFT_RST_REG_OFFST_GDMA (4) +#define PM_SOFT_RST_REG_OFFST_SPI_PCM_I2C (3) +#define PM_SOFT_RST_REG_OFFST_DMC (2) +#define PM_SOFT_RST_REG_OFFST_SMC_NFI (1) +#define PM_SOFT_RST_REG_OFFST_GLOBAL (0) +#define PM_SOFT_RST_REG_MASK (0xF3FFFFBF) + +/* PMHS_CFG_REG */ +#define PM_HS_CFG_REG_OFFSET_SDIO (25) +#define PM_HS_CFG_REG_OFFSET_GPU (24) +#define PM_HS_CFG_REG_OFFSET_CIM (23) +#define PM_HS_CFG_REG_OFFSET_LCDC (22) +#define PM_HS_CFG_REG_OFFSET_I2S (21) +#define PM_HS_CFG_REG_OFFSET_RAID (20) +#define PM_HS_CFG_REG_OFFSET_SATA (19) +#define PM_HS_CFG_REG_OFFSET_PCIE1 (18) +#define PM_HS_CFG_REG_OFFSET_PCIE0 (17) +#define PM_HS_CFG_REG_OFFSET_USB_HOST (16) +#define PM_HS_CFG_REG_OFFSET_USB_OTG (15) +#define PM_HS_CFG_REG_OFFSET_TIMER (14) +#define PM_HS_CFG_REG_OFFSET_CRYPTO (13) +#define PM_HS_CFG_REG_OFFSET_HCIE (12) +#define PM_HS_CFG_REG_OFFSET_SWITCH (11) +#define PM_HS_CFG_REG_OFFSET_GPIO (10) +#define PM_HS_CFG_REG_OFFSET_UART3 (9) +#define PM_HS_CFG_REG_OFFSET_UART2 (8) +#define PM_HS_CFG_REG_OFFSET_UART1 (7) +#define PM_HS_CFG_REG_OFFSET_RTC (5) +#define PM_HS_CFG_REG_OFFSET_GDMA (4) +#define PM_HS_CFG_REG_OFFSET_SPI_PCM_I2S (3) +#define PM_HS_CFG_REG_OFFSET_DMC (2) +#define PM_HS_CFG_REG_OFFSET_SMC_NFI (1) +#define PM_HS_CFG_REG_MASK (0x03FFFFBE) +#define PM_HS_CFG_REG_MASK_SUPPORT (0x01100806) + +/* PM_CACTIVE_STA_REG */ +#define PM_CACTIVE_STA_REG_OFFSET_SDIO (25) +#define PM_CACTIVE_STA_REG_OFFSET_GPU (24) +#define PM_CACTIVE_STA_REG_OFFSET_CIM (23) +#define PM_CACTIVE_STA_REG_OFFSET_LCDC (22) +#define PM_CACTIVE_STA_REG_OFFSET_I2S (21) +#define PM_CACTIVE_STA_REG_OFFSET_RAID (20) +#define PM_CACTIVE_STA_REG_OFFSET_SATA (19) +#define PM_CACTIVE_STA_REG_OFFSET_PCIE1 (18) +#define PM_CACTIVE_STA_REG_OFFSET_PCIE0 (17) +#define PM_CACTIVE_STA_REG_OFFSET_USB_HOST (16) +#define PM_CACTIVE_STA_REG_OFFSET_USB_OTG (15) +#define PM_CACTIVE_STA_REG_OFFSET_TIMER (14) +#define PM_CACTIVE_STA_REG_OFFSET_CRYPTO (13) +#define PM_CACTIVE_STA_REG_OFFSET_HCIE (12) +#define PM_CACTIVE_STA_REG_OFFSET_SWITCH (11) +#define PM_CACTIVE_STA_REG_OFFSET_GPIO (10) +#define PM_CACTIVE_STA_REG_OFFSET_UART3 (9) +#define PM_CACTIVE_STA_REG_OFFSET_UART2 (8) +#define PM_CACTIVE_STA_REG_OFFSET_UART1 (7) +#define PM_CACTIVE_STA_REG_OFFSET_RTC (5) +#define PM_CACTIVE_STA_REG_OFFSET_GDMA (4) +#define PM_CACTIVE_STA_REG_OFFSET_SPI_PCM_I2S (3) +#define PM_CACTIVE_STA_REG_OFFSET_DMC (2) +#define PM_CACTIVE_STA_REG_OFFSET_SMC_NFI (1) +#define PM_CACTIVE_STA_REG_MASK (0x03FFFFBE) + +/* PM_PWR_STA_REG */ +#define PM_PWR_STA_REG_REG_OFFSET_SDIO (25) +#define PM_PWR_STA_REG_REG_OFFSET_GPU (24) +#define PM_PWR_STA_REG_REG_OFFSET_CIM (23) +#define PM_PWR_STA_REG_REG_OFFSET_LCDC (22) +#define PM_PWR_STA_REG_REG_OFFSET_I2S (21) +#define PM_PWR_STA_REG_REG_OFFSET_RAID (20) +#define PM_PWR_STA_REG_REG_OFFSET_SATA (19) +#define PM_PWR_STA_REG_REG_OFFSET_PCIE1 (18) +#define PM_PWR_STA_REG_REG_OFFSET_PCIE0 (17) +#define PM_PWR_STA_REG_REG_OFFSET_USB_HOST (16) +#define PM_PWR_STA_REG_REG_OFFSET_USB_OTG (15) +#define PM_PWR_STA_REG_REG_OFFSET_TIMER (14) +#define PM_PWR_STA_REG_REG_OFFSET_CRYPTO (13) +#define PM_PWR_STA_REG_REG_OFFSET_HCIE (12) +#define PM_PWR_STA_REG_REG_OFFSET_SWITCH (11) +#define PM_PWR_STA_REG_REG_OFFSET_GPIO (10) +#define PM_PWR_STA_REG_REG_OFFSET_UART3 (9) +#define PM_PWR_STA_REG_REG_OFFSET_UART2 (8) +#define PM_PWR_STA_REG_REG_OFFSET_UART1 (7) +#define PM_PWR_STA_REG_REG_OFFSET_RTC (5) +#define PM_PWR_STA_REG_REG_OFFSET_GDMA (4) +#define PM_PWR_STA_REG_REG_OFFSET_SPI_PCM_I2S (3) +#define PM_PWR_STA_REG_REG_OFFSET_DMC (2) +#define PM_PWR_STA_REG_REG_OFFSET_SMC_NFI (1) +#define PM_PWR_STA_REG_REG_MASK (0x03FFFFBE) + +/* PM_CLK_CTRL_REG */ +#define PM_CLK_CTRL_REG_OFFSET_I2S_MCLK (31) +#define PM_CLK_CTRL_REG_OFFSET_DDR2_CHG_EN (30) +#define PM_CLK_CTRL_REG_OFFSET_PCIE_REF1_EN (29) +#define PM_CLK_CTRL_REG_OFFSET_PCIE_REF0_EN (28) +#define PM_CLK_CTRL_REG_OFFSET_TIMER_SIM_MODE (27) +#define PM_CLK_CTRL_REG_OFFSET_I2SCLK_DIV (24) +#define PM_CLK_CTRL_REG_OFFSET_I2SCLK_SEL (22) +#define PM_CLK_CTRL_REG_OFFSET_CLKOUT_DIV (20) +#define PM_CLK_CTRL_REG_OFFSET_CLKOUT_SEL (16) +#define PM_CLK_CTRL_REG_OFFSET_MDC_DIV (14) +#define PM_CLK_CTRL_REG_OFFSET_CRYPTO_CLK_SEL (12) +#define PM_CLK_CTRL_REG_OFFSET_CPU_PWR_MODE (9) +#define PM_CLK_CTRL_REG_OFFSET_PLL_DDR2_SEL (7) +#define PM_CLK_CTRL_REG_OFFSET_DIV_IMMEDIATE (6) +#define PM_CLK_CTRL_REG_OFFSET_CPU_CLK_DIV (4) +#define PM_CLK_CTRL_REG_OFFSET_PLL_CPU_SEL (0) + +#define PM_CPU_CLK_DIV(DIV) { \ + PM_CLK_CTRL_REG &= ~((0x3) << PM_CLK_CTRL_REG_OFFSET_CPU_CLK_DIV); \ + PM_CLK_CTRL_REG |= (((DIV)&0x3) << PM_CLK_CTRL_REG_OFFSET_CPU_CLK_DIV); \ +} + +#define PM_PLL_CPU_SEL(CPU) { \ + PM_CLK_CTRL_REG &= ~((0xF) << PM_CLK_CTRL_REG_OFFSET_PLL_CPU_SEL); \ + PM_CLK_CTRL_REG |= (((CPU)&0xF) << PM_CLK_CTRL_REG_OFFSET_PLL_CPU_SEL); \ +} + +/* PM_PLL_LCD_I2S_CTRL_REG */ +#define PM_PLL_LCD_I2S_CTRL_REG_OFFSET_MCLK_SMC_DIV (22) +#define PM_PLL_LCD_I2S_CTRL_REG_OFFSET_R_SEL (17) +#define PM_PLL_LCD_I2S_CTRL_REG_OFFSET_PLL_LCD_P (11) +#define PM_PLL_LCD_I2S_CTRL_REG_OFFSET_PLL_LCD_M (3) +#define PM_PLL_LCD_I2S_CTRL_REG_OFFSET_PLL_LCD_S (0) + +/* PM_PLL_HM_PD_CTRL_REG */ +#define PM_PLL_HM_PD_CTRL_REG_OFFSET_SATA_PHY1 (11) +#define PM_PLL_HM_PD_CTRL_REG_OFFSET_SATA_PHY0 (10) +#define PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_I2SCD (6) +#define PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_I2S (5) +#define PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_LCD (4) +#define PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB (3) +#define PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_RGMII (2) +#define PM_PLL_HM_PD_CTRL_REG_MASK (0x00000C7C) + +/* PM_WDT_CTRL_REG */ +#define PM_WDT_CTRL_REG_OFFSET_RESET_CPU_ONLY (0) + +/* PM_CSR_REG - Clock Scaling Register*/ +#define PM_CSR_REG_OFFSET_CSR_EN (30) +#define PM_CSR_REG_OFFSET_CSR_NUM (0) + +#define CNS3XXX_PWR_CLK_EN(BLOCK) (0x1< diff --git a/arch/arm/mach-cns3xxx/include/mach/entry-macro.S b/arch/arm/mach-cns3xxx/include/mach/entry-macro.S new file mode 100644 index 0000000..5e1c554 --- /dev/null +++ b/arch/arm/mach-cns3xxx/include/mach/entry-macro.S @@ -0,0 +1,82 @@ +/* + * Low-level IRQ helper macros for Cavium Networks platforms + * + * Copyright 2008 Cavium Networks + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, Version 2, as + * published by the Free Software Foundation. + */ + +#include +#include + + .macro disable_fiq + .endm + + .macro get_irqnr_preamble, base, tmp + ldr \base, =gic_cpu_base_addr + ldr \base, [\base] + .endm + + .macro arch_ret_to_user, tmp1, tmp2 + .endm + + /* + * The interrupt numbering scheme is defined in the + * interrupt controller spec. To wit: + * + * Interrupts 0-15 are IPI + * 16-28 are reserved + * 29-31 are local. We allow 30 to be used for the watchdog. + * 32-1020 are global + * 1021-1022 are reserved + * 1023 is "spurious" (no interrupt) + * + * For now, we ignore all local interrupts so only return an interrupt if it's + * between 30 and 1020. The test_for_ipi routine below will pick up on IPIs. + * + * A simple read from the controller will tell us the number of the highest + * priority enabled interrupt. We then just need to check whether it is in the + * valid range for an IRQ (30-1020 inclusive). + */ + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + + ldr \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */ + + ldr \tmp, =1021 + + bic \irqnr, \irqstat, #0x1c00 + + cmp \irqnr, #29 + cmpcc \irqnr, \irqnr + cmpne \irqnr, \tmp + cmpcs \irqnr, \irqnr + + .endm + + /* We assume that irqstat (the raw value of the IRQ acknowledge + * register) is preserved from the macro above. + * If there is an IPI, we immediately signal end of interrupt on the + * controller, since this requires the original irqstat value which + * we won't easily be able to recreate later. + */ + + .macro test_for_ipi, irqnr, irqstat, base, tmp + bic \irqnr, \irqstat, #0x1c00 + cmp \irqnr, #16 + strcc \irqstat, [\base, #GIC_CPU_EOI] + cmpcs \irqnr, \irqnr + .endm + + /* As above, this assumes that irqstat and base are preserved.. */ + + .macro test_for_ltirq, irqnr, irqstat, base, tmp + bic \irqnr, \irqstat, #0x1c00 + mov \tmp, #0 + cmp \irqnr, #29 + moveq \tmp, #1 + streq \irqstat, [\base, #GIC_CPU_EOI] + cmp \tmp, #0 + .endm diff --git a/arch/arm/mach-cns3xxx/include/mach/hardware.h b/arch/arm/mach-cns3xxx/include/mach/hardware.h new file mode 100644 index 0000000..57e0983 --- /dev/null +++ b/arch/arm/mach-cns3xxx/include/mach/hardware.h @@ -0,0 +1,22 @@ +/* + * This file contains the hardware definitions of the Cavium Networks boards. + * + * Copyright 2003 ARM Limited. + * Copyright 2008 Cavium Networks + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, Version 2, as + * published by the Free Software Foundation. + */ + +#ifndef __MACH_HARDWARE_H +#define __MACH_HARDWARE_H + +#include + +/* macro to get at IO space when running virtually */ +#define PCIBIOS_MIN_IO 0x00000000 +#define PCIBIOS_MIN_MEM 0x00000000 +#define pcibios_assign_all_busses() 1 + +#endif diff --git a/arch/arm/mach-cns3xxx/include/mach/io.h b/arch/arm/mach-cns3xxx/include/mach/io.h new file mode 100644 index 0000000..33b6fc1 --- /dev/null +++ b/arch/arm/mach-cns3xxx/include/mach/io.h @@ -0,0 +1,17 @@ +/* + * Copyright 2008 Cavium Networks + * Copyright 2003 ARM Limited + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, Version 2, as + * published by the Free Software Foundation. + */ +#ifndef __MACH_IO_H +#define __MACH_IO_H + +#define IO_SPACE_LIMIT 0xffffffff + +#define __io(a) __typesafe_io(a) +#define __mem_pci(a) (a) + +#endif diff --git a/arch/arm/mach-cns3xxx/include/mach/irqs.h b/arch/arm/mach-cns3xxx/include/mach/irqs.h new file mode 100644 index 0000000..2ab96f8 --- /dev/null +++ b/arch/arm/mach-cns3xxx/include/mach/irqs.h @@ -0,0 +1,24 @@ +/* + * Copyright 2000 Deep Blue Solutions Ltd. + * Copyright 2003 ARM Limited + * Copyright 2008 Cavium Networks + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, Version 2, as + * published by the Free Software Foundation. + */ + +#ifndef __MACH_IRQS_H +#define __MACH_IRQS_H + +#define IRQ_LOCALTIMER 29 +#define IRQ_LOCALWDOG 30 +#define IRQ_TC11MP_GIC_START 32 + +#include + +#ifndef NR_IRQS +#error "NR_IRQS not defined by the board-specific files" +#endif + +#endif diff --git a/arch/arm/mach-cns3xxx/include/mach/memory.h b/arch/arm/mach-cns3xxx/include/mach/memory.h new file mode 100644 index 0000000..3b6b769 --- /dev/null +++ b/arch/arm/mach-cns3xxx/include/mach/memory.h @@ -0,0 +1,26 @@ +/* + * Copyright 2003 ARM Limited + * Copyright 2008 Cavium Networks + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, Version 2, as + * published by the Free Software Foundation. + */ + +#ifndef __MACH_MEMORY_H +#define __MACH_MEMORY_H + +/* + * Physical DRAM offset. + */ +#define PHYS_OFFSET UL(0x00000000) + +#define __phys_to_bus(x) ((x) + PHYS_OFFSET) +#define __bus_to_phys(x) ((x) - PHYS_OFFSET) + +#define __virt_to_bus(v) __phys_to_bus(__virt_to_phys(v)) +#define __bus_to_virt(b) __phys_to_virt(__bus_to_phys(b)) +#define __pfn_to_bus(p) __phys_to_bus(__pfn_to_phys(p)) +#define __bus_to_pfn(b) __phys_to_pfn(__bus_to_phys(b)) + +#endif diff --git a/arch/arm/mach-cns3xxx/include/mach/system.h b/arch/arm/mach-cns3xxx/include/mach/system.h new file mode 100644 index 0000000..58bb03a --- /dev/null +++ b/arch/arm/mach-cns3xxx/include/mach/system.h @@ -0,0 +1,29 @@ +/* + * Copyright 2000 Deep Blue Solutions Ltd + * Copyright 2003 ARM Limited + * Copyright 2008 Cavium Networks + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, Version 2, as + * published by the Free Software Foundation. + */ + +#ifndef __MACH_SYSTEM_H +#define __MACH_SYSTEM_H + +#include +#include +#include + +static inline void arch_idle(void) +{ + /* + * This should do all the clock switching + * and wait for interrupt tricks + */ + cpu_do_idle(); +} + +void arch_reset(char mode, const char *cmd); + +#endif diff --git a/arch/arm/mach-cns3xxx/include/mach/timex.h b/arch/arm/mach-cns3xxx/include/mach/timex.h new file mode 100644 index 0000000..1fd0421 --- /dev/null +++ b/arch/arm/mach-cns3xxx/include/mach/timex.h @@ -0,0 +1,12 @@ +/* + * Cavium Networks architecture timex specifications + * + * Copyright 2003 ARM Limited + * Copyright 2008 Cavium Networks + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, Version 2, as + * published by the Free Software Foundation. + */ + +#define CLOCK_TICK_RATE (50000000 / 16) diff --git a/arch/arm/mach-cns3xxx/include/mach/uncompress.h b/arch/arm/mach-cns3xxx/include/mach/uncompress.h new file mode 100644 index 0000000..de8ead9 --- /dev/null +++ b/arch/arm/mach-cns3xxx/include/mach/uncompress.h @@ -0,0 +1,55 @@ +/* + * Copyright 2003 ARM Limited + * Copyright 2008 Cavium Networks + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, Version 2, as + * published by the Free Software Foundation. + */ + +#include +#include +#include + +#define AMBA_UART_DR(base) (*(volatile unsigned char *)((base) + 0x00)) +#define AMBA_UART_LCRH(base) (*(volatile unsigned char *)((base) + 0x2c)) +#define AMBA_UART_CR(base) (*(volatile unsigned char *)((base) + 0x30)) +#define AMBA_UART_FR(base) (*(volatile unsigned char *)((base) + 0x18)) + +/* + * Return the UART base address + */ +static inline unsigned long get_uart_base(void) +{ + if (machine_is_cns3420vb()) + return CNS3XXX_UART0_BASE; + else + return 0; +} + +/* + * This does not append a newline + */ +static inline void putc(int c) +{ + unsigned long base = get_uart_base(); + + while (AMBA_UART_FR(base) & (1 << 5)) + barrier(); + + AMBA_UART_DR(base) = c; +} + +static inline void flush(void) +{ + unsigned long base = get_uart_base(); + + while (AMBA_UART_FR(base) & (1 << 3)) + barrier(); +} + +/* + * nothing to do + */ +#define arch_decomp_setup() +#define arch_decomp_wdog() diff --git a/arch/arm/mach-cns3xxx/include/mach/vmalloc.h b/arch/arm/mach-cns3xxx/include/mach/vmalloc.h new file mode 100644 index 0000000..4d381ec --- /dev/null +++ b/arch/arm/mach-cns3xxx/include/mach/vmalloc.h @@ -0,0 +1,11 @@ +/* + * Copyright 2000 Russell King. + * Copyright 2003 ARM Limited + * Copyright 2008 Cavium Networks + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, Version 2, as + * published by the Free Software Foundation. + */ + +#define VMALLOC_END 0xd8000000 diff --git a/arch/arm/mach-cns3xxx/pm.c b/arch/arm/mach-cns3xxx/pm.c new file mode 100644 index 0000000..725e1a4 --- /dev/null +++ b/arch/arm/mach-cns3xxx/pm.c @@ -0,0 +1,86 @@ +/* + * Copyright 2008 Cavium Networks + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, Version 2, as + * published by the Free Software Foundation. + */ + +#include +#include +#include + +void cns3xxx_pwr_clk_en(unsigned int block) +{ + PM_CLK_GATE_REG |= (block & PM_CLK_GATE_REG_MASK); +} + +void cns3xxx_pwr_power_up(unsigned int block) +{ + PM_PLL_HM_PD_CTRL_REG &= ~(block & CNS3XXX_PWR_PLL_ALL); + + /* Wait for 300us for the PLL output clock locked. */ + udelay(300); +}; + +void cns3xxx_pwr_power_down(unsigned int block) +{ + /* write '1' to power down */ + PM_PLL_HM_PD_CTRL_REG |= (block & CNS3XXX_PWR_PLL_ALL); +}; + +static void cns3xxx_pwr_soft_rst_force(unsigned int block) +{ + /* + * bit 0, 28, 29 => program low to reset, + * the other else program low and then high + */ + if (block & 0x30000001) { + PM_SOFT_RST_REG &= ~(block & PM_SOFT_RST_REG_MASK); + } else { + PM_SOFT_RST_REG &= ~(block & PM_SOFT_RST_REG_MASK); + PM_SOFT_RST_REG |= (block & PM_SOFT_RST_REG_MASK); + } +} + +void cns3xxx_pwr_soft_rst(unsigned int block) +{ + static unsigned int soft_reset; + + if (soft_reset & block) { + /* SPI/I2C/GPIO use the same block, reset once. */ + return; + } else { + soft_reset |= block; + } + cns3xxx_pwr_soft_rst_force(block); +} + +void arch_reset(char mode, const char *cmd) +{ + /* + * To reset, we hit the on-board reset register + * in the system FPGA. + */ + cns3xxx_pwr_soft_rst(CNS3XXX_PWR_SOFTWARE_RST(GLOBAL)); +} + +/* + * cns3xxx_cpu_clock - return CPU/L2 clock + * aclk: cpu clock/2 + * hclk: cpu clock/4 + * pclk: cpu clock/8 + */ +int cns3xxx_cpu_clock(void) +{ + int cpu; + int cpu_sel; + int div_sel; + + cpu_sel = (PM_CLK_CTRL_REG >> PM_CLK_CTRL_REG_OFFSET_PLL_CPU_SEL) & 0xf; + div_sel = (PM_CLK_CTRL_REG >> PM_CLK_CTRL_REG_OFFSET_CPU_CLK_DIV) & 0x3; + + cpu = (300 + ((cpu_sel / 3) * 100) + ((cpu_sel % 3) * 33)) >> div_sel; + + return cpu; +} -- cgit v0.10.2 From e94cdef039d4b141dffdbf5adde705f8c14dc53f Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Fri, 26 Mar 2010 21:19:02 +0300 Subject: ARM: cns3xxx: Add CNS3420 Validation Board support This patch adds support for CNS3420VB rev 1.3 boards. With this patch CNS3420VB boards are able to boot up to the userspace, with a console available on UART0. Signed-off-by: Anton Vorontsov diff --git a/arch/arm/mach-cns3xxx/Kconfig b/arch/arm/mach-cns3xxx/Kconfig index 20284cd..9ebfcc4 100644 --- a/arch/arm/mach-cns3xxx/Kconfig +++ b/arch/arm/mach-cns3xxx/Kconfig @@ -1,4 +1,12 @@ menu "CNS3XXX platform type" depends on ARCH_CNS3XXX +config MACH_CNS3420VB + bool "Support for CNS3420 Validation Board" + help + Include support for the Cavium Networks CNS3420 MPCore Platform + Baseboard. + This is a platform with an on-board ARM11 MPCore and has support + for USB, USB-OTG, MMC/SD/SDIO, SATA, PCI-E, etc. + endmenu diff --git a/arch/arm/mach-cns3xxx/Makefile b/arch/arm/mach-cns3xxx/Makefile index e5e76dd..427507a 100644 --- a/arch/arm/mach-cns3xxx/Makefile +++ b/arch/arm/mach-cns3xxx/Makefile @@ -1 +1,2 @@ obj-$(CONFIG_ARCH_CNS3XXX) += core.o pm.o +obj-$(CONFIG_MACH_CNS3420VB) += cns3420vb.o diff --git a/arch/arm/mach-cns3xxx/cns3420vb.c b/arch/arm/mach-cns3xxx/cns3420vb.c new file mode 100644 index 0000000..2e30c82 --- /dev/null +++ b/arch/arm/mach-cns3xxx/cns3420vb.c @@ -0,0 +1,148 @@ +/* + * Cavium Networks CNS3420 Validation Board + * + * Copyright 2000 Deep Blue Solutions Ltd + * Copyright 2008 ARM Limited + * Copyright 2008 Cavium Networks + * Scott Shu + * Copyright 2010 MontaVista Software, LLC. + * Anton Vorontsov + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, Version 2, as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "core.h" + +/* + * NOR Flash + */ +static struct mtd_partition cns3420_nor_partitions[] = { + { + .name = "uboot", + .size = 0x00040000, + .offset = 0, + .mask_flags = MTD_WRITEABLE, + }, { + .name = "kernel", + .size = 0x004C0000, + .offset = MTDPART_OFS_APPEND, + }, { + .name = "filesystem", + .size = 0x7000000, + .offset = MTDPART_OFS_APPEND, + }, { + .name = "filesystem2", + .size = 0x0AE0000, + .offset = MTDPART_OFS_APPEND, + }, { + .name = "ubootenv", + .size = MTDPART_SIZ_FULL, + .offset = MTDPART_OFS_APPEND, + }, +}; + +static struct physmap_flash_data cns3420_nor_pdata = { + .width = 2, + .parts = cns3420_nor_partitions, + .nr_parts = ARRAY_SIZE(cns3420_nor_partitions), +}; + +static struct resource cns3420_nor_res = { + .start = CNS3XXX_FLASH_BASE, + .end = CNS3XXX_FLASH_BASE + SZ_128M - 1, + .flags = IORESOURCE_MEM | IORESOURCE_MEM_32BIT, +}; + +static struct platform_device cns3420_nor_pdev = { + .name = "physmap-flash", + .id = 0, + .resource = &cns3420_nor_res, + .num_resources = 1, + .dev = { + .platform_data = &cns3420_nor_pdata, + }, +}; + +/* + * UART + */ +static void __init cns3420_early_serial_setup(void) +{ +#ifdef CONFIG_SERIAL_8250_CONSOLE + static struct uart_port cns3420_serial_port = { + .membase = (void __iomem *)CNS3XXX_UART0_BASE_VIRT, + .mapbase = CNS3XXX_UART0_BASE, + .irq = IRQ_CNS3XXX_UART0, + .iotype = UPIO_MEM, + .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE, + .regshift = 2, + .uartclk = 24000000, + .line = 0, + .type = PORT_16550A, + .fifosize = 16, + }; + + early_serial_setup(&cns3420_serial_port); +#endif +} + +/* + * Initialization + */ +static struct platform_device *cns3420_pdevs[] __initdata = { + &cns3420_nor_pdev, +}; + +static void __init cns3420_init(void) +{ + platform_add_devices(cns3420_pdevs, ARRAY_SIZE(cns3420_pdevs)); + + pm_power_off = cns3xxx_power_off; +} + +static struct map_desc cns3420_io_desc[] __initdata = { + { + .virtual = CNS3XXX_UART0_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_UART0_BASE), + .length = SZ_4K, + .type = MT_DEVICE, + }, +}; + +static void __init cns3420_map_io(void) +{ + cns3xxx_map_io(); + iotable_init(cns3420_io_desc, ARRAY_SIZE(cns3420_io_desc)); + + cns3420_early_serial_setup(); +} + +MACHINE_START(CNS3420VB, "Cavium Networks CNS3420 Validation Board") + .phys_io = CNS3XXX_UART0_BASE, + .io_pg_offst = (CNS3XXX_UART0_BASE_VIRT >> 18) & 0xfffc, + .boot_params = 0x00000100, + .map_io = cns3420_map_io, + .init_irq = cns3xxx_init_irq, + .timer = &cns3xxx_timer, + .init_machine = cns3420_init, +MACHINE_END -- cgit v0.10.2 From 478ea14466fb524b4cd90cdf0b8845f8c5ee6015 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Thu, 25 Mar 2010 20:51:49 +0300 Subject: ARM: cns3xxx: Add defconfig for CNS3420 validation board Signed-off-by: Anton Vorontsov diff --git a/arch/arm/configs/cns3420vb_defconfig b/arch/arm/configs/cns3420vb_defconfig new file mode 100644 index 0000000..d5c0881 --- /dev/null +++ b/arch/arm/configs/cns3420vb_defconfig @@ -0,0 +1,831 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.34-rc6 +# Sun May 2 21:58:08 2010 +# +CONFIG_ARM=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_HAVE_PROC_CPU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_OPROFILE_ARMV6=y +CONFIG_OPROFILE_ARM11_CORE=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_CONSTRUCTORS=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_BZIP2 is not set +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_BSD_PROCESS_ACCT is not set + +# +# RCU Subsystem +# +CONFIG_TREE_RCU=y +# CONFIG_TREE_PREEMPT_RCU is not set +# CONFIG_TINY_RCU is not set +# CONFIG_RCU_TRACE is not set +CONFIG_RCU_FANOUT=32 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_TREE_RCU_TRACE is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_CGROUPS=y +# CONFIG_CGROUP_DEBUG is not set +# CONFIG_CGROUP_NS is not set +# CONFIG_CGROUP_FREEZER is not set +# CONFIG_CGROUP_DEVICE is not set +# CONFIG_CPUSETS is not set +# CONFIG_CGROUP_CPUACCT is not set +# CONFIG_RESOURCE_COUNTERS is not set +# CONFIG_CGROUP_SCHED is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +CONFIG_RELAY=y +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +CONFIG_RD_LZO=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +# CONFIG_PERF_EVENTS is not set +# CONFIG_PERF_COUNTERS is not set +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_COMPAT_BRK=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +CONFIG_PROFILING=y +CONFIG_OPROFILE=m +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_SLOW_WORK=y +# CONFIG_SLOW_WORK_DEBUG is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_BLOCK=y +CONFIG_LBDAF=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=m +# CONFIG_CFQ_GROUP_IOSCHED is not set +CONFIG_DEFAULT_DEADLINE=y +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="deadline" +# CONFIG_INLINE_SPIN_TRYLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK is not set +# CONFIG_INLINE_SPIN_LOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK_IRQ is not set +# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set +CONFIG_INLINE_SPIN_UNLOCK=y +# CONFIG_INLINE_SPIN_UNLOCK_BH is not set +CONFIG_INLINE_SPIN_UNLOCK_IRQ=y +# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_READ_TRYLOCK is not set +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set +# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set +CONFIG_INLINE_READ_UNLOCK=y +# CONFIG_INLINE_READ_UNLOCK_BH is not set +CONFIG_INLINE_READ_UNLOCK_IRQ=y +# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_WRITE_TRYLOCK is not set +# CONFIG_INLINE_WRITE_LOCK is not set +# CONFIG_INLINE_WRITE_LOCK_BH is not set +# CONFIG_INLINE_WRITE_LOCK_IRQ is not set +# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set +CONFIG_INLINE_WRITE_UNLOCK=y +# CONFIG_INLINE_WRITE_UNLOCK_BH is not set +CONFIG_INLINE_WRITE_UNLOCK_IRQ=y +# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set +# CONFIG_MUTEX_SPIN_ON_OWNER is not set +# CONFIG_FREEZER is not set + +# +# System Type +# +CONFIG_MMU=y +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_BCMRING is not set +# CONFIG_ARCH_CLPS711X is not set +CONFIG_ARCH_CNS3XXX=y +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_STMP3XXX is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_DOVE is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_NUC93X is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_SHMOBILE is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5P6440 is not set +# CONFIG_ARCH_S5P6442 is not set +# CONFIG_ARCH_S5PC1XX is not set +# CONFIG_ARCH_S5PV210 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_U8500 is not set +# CONFIG_ARCH_NOMADIK is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set + +# +# CNS3XXX platform type +# +CONFIG_MACH_CNS3420VB=y + +# +# Processor Type +# +CONFIG_CPU_V6=y +# CONFIG_CPU_32v6K is not set +CONFIG_CPU_32v6=y +CONFIG_CPU_ABRT_EV6=y +CONFIG_CPU_PABRT_V6=y +CONFIG_CPU_CACHE_V6=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V6=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_ARM_L1_CACHE_SHIFT=5 +CONFIG_CPU_HAS_PMU=y +# CONFIG_ARM_ERRATA_411920 is not set +CONFIG_ARM_GIC=y + +# +# Bus support +# +# CONFIG_PCI_SYSCALL is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +# CONFIG_NO_HZ is not set +# CONFIG_HIGH_RES_TIMERS is not set +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_HZ=100 +CONFIG_AEABI=y +CONFIG_OABI_COMPAT=y +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +# CONFIG_HIGHMEM is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="console=ttyS0,38400 mem=128M root=/dev/mmcblk0p1 ro rootwait" +# CONFIG_XIP_KERNEL is not set +# CONFIG_KEXEC is not set + +# +# CPU Power Management +# +# CONFIG_CPU_IDLE is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +# CONFIG_FPE_NWFPE is not set +# CONFIG_FPE_FASTFPE is not set +# CONFIG_VFP is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +# CONFIG_PM is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +# CONFIG_NET is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_DEVTMPFS is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_SYS_HYPERVISOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +# CONFIG_MTD_PHYSMAP_COMPAT is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set + +# +# DRBD disabled because PROC_FS, INET or CONNECTOR not selected +# +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=20000 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_MISC_DEVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_LIBFC is not set +# CONFIG_LIBFCOE is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +CONFIG_ATA=y +# CONFIG_ATA_NONSTANDARD is not set +CONFIG_ATA_VERBOSE_ERROR=y +# CONFIG_SATA_PMP is not set +# CONFIG_ATA_SFF is not set +# CONFIG_MD is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set +# CONFIG_INPUT_SPARSEKMAP is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=16 +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_I2C is not set +# CONFIG_SPI is not set + +# +# PPS support +# +# CONFIG_PPS is not set +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_REGULATOR is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_SOUND is not set +# CONFIG_HID_SUPPORT is not set +# CONFIG_USB_SUPPORT is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_UNSAFE_RESUME is not set + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_BOUNCE=y +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set + +# +# TI VLYNQ +# +# CONFIG_STAGING is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +# CONFIG_EXT2_FS_POSIX_ACL is not set +# CONFIG_EXT2_FS_SECURITY is not set +# CONFIG_EXT2_FS_XIP is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4_FS is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS4_FS=y +# CONFIG_FUSE_FS is not set + +# +# Caches +# +CONFIG_FSCACHE=y +# CONFIG_FSCACHE_STATS is not set +# CONFIG_FSCACHE_HISTOGRAM is not set +# CONFIG_FSCACHE_DEBUG is not set +# CONFIG_FSCACHE_OBJECT_LIST is not set +# CONFIG_CACHEFILES is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_NLS is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_KERNEL is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_FRAME_POINTER=y +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_LKDTM is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_RING_BUFFER=y +CONFIG_RING_BUFFER_ALLOW_SWAP=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_ARM_UNWIND is not set +# CONFIG_DEBUG_USER is not set +# CONFIG_OC_ETM is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_DEFAULT_SECURITY_SELINUX is not set +# CONFIG_DEFAULT_SECURITY_SMACK is not set +# CONFIG_DEFAULT_SECURITY_TOMOYO is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +# CONFIG_CRYPTO is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y +CONFIG_CRC_CCITT=y +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_LZO_DECOMPRESS=y +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_DECOMPRESS_LZO=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_GENERIC_ATOMIC64=y -- cgit v0.10.2 From aec9562f3db8ece218125042e0b2b7ac5b7091e7 Mon Sep 17 00:00:00 2001 From: Anders Larsen Date: Tue, 13 Apr 2010 12:05:32 +0100 Subject: ARM: 6053/1: AT91: Save power by disabling the processor clock when CPU is idle Disable the processor clock when the CPU is idle. This saves much more power than merely entering 'Wait for Interrupt' mode. Since JTAG-debugging doesn't work when the processor clock is switched off, make it conditional on CONFIG_DEBUG_KERNEL. Signed-off-by: Anders Larsen Acked-by: Andrew Victor Signed-off-by: Russell King diff --git a/arch/arm/mach-at91/include/mach/system.h b/arch/arm/mach-at91/include/mach/system.h index 5268af3..c80e090 100644 --- a/arch/arm/mach-at91/include/mach/system.h +++ b/arch/arm/mach-at91/include/mach/system.h @@ -24,21 +24,24 @@ #include #include #include +#include static inline void arch_idle(void) { +#ifndef CONFIG_DEBUG_KERNEL /* * Disable the processor clock. The processor will be automatically * re-enabled by an interrupt or by a reset. */ -// at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK); - + at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK); +#else /* * Set the processor (CP15) into 'Wait for Interrupt' mode. * Unlike disabling the processor clock via the PMC (above) * this allows the processor to be woken via JTAG. */ cpu_do_idle(); +#endif } void (*at91_arch_reset)(void); -- cgit v0.10.2 From 090f7204dfdb5d7f18208ea81dfdba845897cedd Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 2 May 2010 19:46:36 -0300 Subject: perf inject: Refactor read_buildid function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Into two functions, one that actually reads the build_id for the dso if it wasn't already read, and another taht will inject the event if the build_id is available. Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index a5902a3..59e981a 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -67,46 +67,44 @@ static int event__repipe_tracing_data(event_t *self, return err; } -static int read_buildid(struct map *self, struct perf_session *session) +static int dso__read_build_id(struct dso *self) { - const char *name = self->dso->long_name; - int err; + if (self->has_build_id) + return 0; - if (filename__read_build_id(self->dso->long_name, self->dso->build_id, - sizeof(self->dso->build_id)) > 0) { - char sbuild_id[BUILD_ID_SIZE * 2 + 1]; + if (filename__read_build_id(self->long_name, self->build_id, + sizeof(self->build_id)) > 0) { + self->has_build_id = true; + return 0; + } - self->dso->has_build_id = true; + return -1; +} - build_id__sprintf(self->dso->build_id, - sizeof(self->dso->build_id), - sbuild_id); - pr_debug("build id found for %s: %s\n", self->dso->long_name, - sbuild_id); - } +static int dso__inject_build_id(struct dso *self, struct perf_session *session) +{ + u16 misc = PERF_RECORD_MISC_USER; + struct machine *machine; + int err; - if (self->dso->has_build_id) { - u16 misc = PERF_RECORD_MISC_USER; - struct machine *machine; + if (dso__read_build_id(self) < 0) { + pr_debug("no build_id found for %s\n", self->long_name); + return -1; + } - misc = self->dso->kernel ? PERF_RECORD_MISC_KERNEL : misc; + machine = perf_session__find_host_machine(session); + if (machine == NULL) { + pr_err("Can't find machine for session\n"); + return -1; + } - machine = perf_session__find_host_machine(session); - if (!machine) { - pr_err("Can't find machine for session\n"); - return -1; - } + if (self->kernel) + misc = PERF_RECORD_MISC_KERNEL; - err = event__synthesize_build_id(self->dso, misc, - event__repipe, machine, - session); - if (err) { - pr_err("Can't synthesize build_id event for %s\n", - name); - return -1; - } - } else { - pr_debug("no build_id found for %s\n", name); + err = event__synthesize_build_id(self, misc, event__repipe, + machine, session); + if (err) { + pr_err("Can't synthesize build_id event for %s\n", self->long_name); return -1; } @@ -118,7 +116,6 @@ static int event__inject_buildid(event_t *event, struct perf_session *session) struct addr_location al; struct thread *thread; u8 cpumode; - int err = 0; cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; @@ -126,7 +123,6 @@ static int event__inject_buildid(event_t *event, struct perf_session *session) if (thread == NULL) { pr_err("problem processing %d event, skipping it.\n", event->header.type); - err = -1; goto repipe; } @@ -136,9 +132,13 @@ static int event__inject_buildid(event_t *event, struct perf_session *session) if (al.map != NULL) { if (!al.map->dso->hit) { al.map->dso->hit = 1; - if (map__load(al.map, NULL) >= 0) - read_buildid(al.map, session); - else + if (map__load(al.map, NULL) >= 0) { + dso__inject_build_id(al.map->dso, session); + /* + * If this fails, too bad, let the other side + * account this as unresolved. + */ + } else pr_warning("no symbols found in %s, maybe " "install a debug package?\n", al.map->dso->long_name); @@ -147,7 +147,7 @@ static int event__inject_buildid(event_t *event, struct perf_session *session) repipe: event__repipe(event, session); - return err; + return 0; } struct perf_event_ops inject_ops = { -- cgit v0.10.2 From 250d377522fd81459a4ea2350a794b453f37ce7d Mon Sep 17 00:00:00 2001 From: Rafi Rubin Date: Mon, 3 May 2010 05:08:29 -0400 Subject: HID: ntrig: TipSwitch for single touch mode touch. Include TipSwitch in the touch detection decision for some single touch firmwares. Confidence and InRange are high for all finger events including those used to indicate the finger is no longer in contact with the sensor. Signed-off-by: Rafi Rubin Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c index 58ba0d3..10b08d6 100644 --- a/drivers/hid/hid-ntrig.c +++ b/drivers/hid/hid-ntrig.c @@ -31,10 +31,12 @@ struct ntrig_data { /* Incoming raw values for a single contact */ __u16 x, y, w, h; __u16 id; - __u8 confidence; + + bool tipswitch; + bool confidence; + bool first_contact_touch; bool reading_mt; - __u8 first_contact_confidence; __u8 mt_footer[4]; __u8 mt_foot_count; @@ -141,9 +143,10 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field, case 0xff000001: /* Tag indicating the start of a multitouch group */ nd->reading_mt = 1; - nd->first_contact_confidence = 0; + nd->first_contact_touch = 0; break; case HID_DG_TIPSWITCH: + nd->tipswitch = value; /* Prevent emission of touch until validated */ return 1; case HID_DG_CONFIDENCE: @@ -171,10 +174,14 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field, * to emit a normal (X, Y) position */ if (!nd->reading_mt) { - input_report_key(input, BTN_TOOL_DOUBLETAP, - (nd->confidence != 0)); + /* + * TipSwitch indicates the presence of a + * finger in single touch mode. + */ input_report_key(input, BTN_TOUCH, - (nd->confidence != 0)); + nd->tipswitch); + input_report_key(input, BTN_TOOL_DOUBLETAP, + nd->tipswitch); input_event(input, EV_ABS, ABS_X, nd->x); input_event(input, EV_ABS, ABS_Y, nd->y); } @@ -213,7 +220,13 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field, /* emit a normal (X, Y) for the first point only */ if (nd->id == 0) { - nd->first_contact_confidence = nd->confidence; + /* + * TipSwitch is superfluous in multitouch + * mode. The footer events tell us + * if there is a finger on the screen or + * not. + */ + nd->first_contact_touch = nd->confidence; input_event(input, EV_ABS, ABS_X, nd->x); input_event(input, EV_ABS, ABS_Y, nd->y); } @@ -243,7 +256,7 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field, nd->reading_mt = 0; - if (nd->first_contact_confidence) { + if (nd->first_contact_touch) { switch (value) { case 0: /* for single touch devices */ case 1: -- cgit v0.10.2 From ed7e2ca24bfff5c7a09de8a05c536f68560b34fb Mon Sep 17 00:00:00 2001 From: Rafi Rubin Date: Mon, 3 May 2010 05:08:30 -0400 Subject: HID: ntrig: Remove unused macro, TripleTap and QuadTap Removing the higher number taps. Their usage was incorrect and even if correct they should not be used for a touch screen. _MT_ events should be used to communicate multiple fingers. Signed-off-by: Rafi Rubin Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c index 10b08d6..4777bbf 100644 --- a/drivers/hid/hid-ntrig.c +++ b/drivers/hid/hid-ntrig.c @@ -24,9 +24,6 @@ #define NTRIG_DUPLICATE_USAGES 0x001 -#define nt_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ - EV_KEY, (c)) - struct ntrig_data { /* Incoming raw values for a single contact */ __u16 x, y, w, h; @@ -257,29 +254,10 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field, nd->reading_mt = 0; if (nd->first_contact_touch) { - switch (value) { - case 0: /* for single touch devices */ - case 1: - input_report_key(input, - BTN_TOOL_DOUBLETAP, 1); - break; - case 2: - input_report_key(input, - BTN_TOOL_TRIPLETAP, 1); - break; - case 3: - default: - input_report_key(input, - BTN_TOOL_QUADTAP, 1); - } + input_report_key(input, BTN_TOOL_DOUBLETAP, 1); input_report_key(input, BTN_TOUCH, 1); } else { - input_report_key(input, - BTN_TOOL_DOUBLETAP, 0); - input_report_key(input, - BTN_TOOL_TRIPLETAP, 0); - input_report_key(input, - BTN_TOOL_QUADTAP, 0); + input_report_key(input, BTN_TOOL_DOUBLETAP, 0); input_report_key(input, BTN_TOUCH, 0); } break; @@ -345,13 +323,7 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id) __clear_bit(BTN_TOOL_PEN, input->keybit); __clear_bit(BTN_TOOL_FINGER, input->keybit); __clear_bit(BTN_0, input->keybit); - /* - * A little something special to enable - * two and three finger taps. - */ __set_bit(BTN_TOOL_DOUBLETAP, input->keybit); - __set_bit(BTN_TOOL_TRIPLETAP, input->keybit); - __set_bit(BTN_TOOL_QUADTAP, input->keybit); /* * The physical touchscreen (single touch) * input has a value for physical, whereas -- cgit v0.10.2 From 63e0c7715aab6085faa487d498889f4361dc6542 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Mon, 3 May 2010 00:14:48 -0500 Subject: perf: record TRACE_INFO only if using tracepoints and SAMPLE_RAW MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current perf code implicitly assumes SAMPLE_RAW means tracepoints are being used, but doesn't check for that. It happily records the TRACE_INFO even if SAMPLE_RAW is used without tracepoints, but when the perf data is read it won't go any further when it finds TRACE_INFO but no tracepoints, and displays misleading errors. This adds a check for both in perf-record, and won't record TRACE_INFO unless both are true. This at least allows perf report -D to dump raw events, and avoids triggering a misleading error condition in perf trace. It doesn't actually enable the non-tracepoint raw events to be displayed in perf trace, since perf trace currently only deals with tracepoint events. Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra LKML-Reference: <1272865861.7932.16.camel@tropicana> Signed-off-by: Tom Zanussi Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index ac989e9..0ff67d1 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -560,11 +560,12 @@ static int __cmd_record(int argc, const char **argv) return err; } - if (raw_samples) { + if (raw_samples && have_tracepoints(attrs, nr_counters)) { perf_header__set_feat(&session->header, HEADER_TRACE_INFO); } else { for (i = 0; i < nr_counters; i++) { - if (attrs[i].sample_type & PERF_SAMPLE_RAW) { + if (attrs[i].sample_type & PERF_SAMPLE_RAW && + attrs[i].type == PERF_TYPE_TRACEPOINT) { perf_header__set_feat(&session->header, HEADER_TRACE_INFO); break; } @@ -662,19 +663,25 @@ static int __cmd_record(int argc, const char **argv) return err; } - err = event__synthesize_tracing_data(output, attrs, - nr_counters, - process_synthesized_event, - session); - /* - * FIXME err <= 0 here actually means that there were no tracepoints - * so its not really an error, just that we don't need to synthesize - * anything. - * We really have to return this more properly and also propagate - * errors that now are calling die() - */ - if (err > 0) + if (have_tracepoints(attrs, nr_counters)) { + /* + * FIXME err <= 0 here actually means that + * there were no tracepoints so its not really + * an error, just that we don't need to + * synthesize anything. We really have to + * return this more properly and also + * propagate errors that now are calling die() + */ + err = event__synthesize_tracing_data(output, attrs, + nr_counters, + process_synthesized_event, + session); + if (err <= 0) { + pr_err("Couldn't record tracing data.\n"); + return err; + } advance_output(err); + } } machine = perf_session__find_host_machine(session); diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 79da0e5..2b9f898 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -436,7 +436,6 @@ static int perf_header__adds_write(struct perf_header *self, int fd) trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset; } - if (perf_header__has_feat(self, HEADER_BUILD_ID)) { struct perf_file_section *buildid_sec; diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index b8c1f64..fc4ab3f 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -13,6 +13,7 @@ struct tracepoint_path { }; extern struct tracepoint_path *tracepoint_id_to_path(u64 config); +extern bool have_tracepoints(struct perf_event_attr *pattrs, int nb_events); extern int nr_counters; diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c index 30cd9b5..0a1fb9d 100644 --- a/tools/perf/util/trace-event-info.c +++ b/tools/perf/util/trace-event-info.c @@ -487,6 +487,11 @@ get_tracepoints_path(struct perf_event_attr *pattrs, int nb_events) return nr_tracepoints > 0 ? path.next : NULL; } +bool have_tracepoints(struct perf_event_attr *pattrs, int nb_events) +{ + return get_tracepoints_path(pattrs, nb_events) ? true : false; +} + int read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events) { char buf[BUFSIZ]; -- cgit v0.10.2 From fddb33f2e8872fa4857dd29f0b71a523c9ed5577 Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Mon, 3 May 2010 17:19:03 +0200 Subject: HID: sony: fix sony_set_operational_bt Don't send the report type as part of the data, this prevents the controller from going into the operational state at all. This is completely equivalent to what the code originally meant to accomplish: as per in net/bluetooth/hidp/core.c::hidp_output_raw_report(), by using HID_FEATURE_REPORT here, what will be actually sent is (HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE) which is exactly 0x53. Signed-off-by: Antonio Ospite Signed-off-by: Bastien Nocera Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 7502a4b..402d557 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -76,7 +76,7 @@ static int sony_set_operational_usb(struct hid_device *hdev) static int sony_set_operational_bt(struct hid_device *hdev) { - unsigned char buf[] = { 0x53, 0xf4, 0x42, 0x03, 0x00, 0x00 }; + unsigned char buf[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 }; return hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); } -- cgit v0.10.2 From 4b53eb4f5d78416456bb969ce30e3bed2731d744 Mon Sep 17 00:00:00 2001 From: Daniel Walker Date: Fri, 1 Jan 2010 15:11:43 -0800 Subject: arm: msm: allow ARCH_MSM to have v7 cpus ARCH_MSM supports armv7 cpus, so we're pushed the CPU_V6/CPU_V7 selection down into the arch/arm/mach-msm/Kconfig. Also update the description to be a bit more accurate. Signed-off-by: Daniel Walker diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 92622eb..9264d01 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -601,14 +601,14 @@ config ARCH_PXA config ARCH_MSM bool "Qualcomm MSM" - select CPU_V6 select GENERIC_TIME select GENERIC_CLOCKEVENTS help - Support for Qualcomm MSM7K based systems. This runs on the ARM11 - apps processor of the MSM7K and depends on a shared memory - interface to the ARM9 modem processor which runs the baseband stack - and controls some vital subsystems (clock and power control, etc). + Support for Qualcomm MSM/QSD based systems. This runs on the + apps processor of the MSM/QSD and depends on a shared memory + interface to the modem processor which runs the baseband + stack and controls some vital subsystems + (clock and power control, etc). config ARCH_SHMOBILE bool "Renesas SH-Mobile" diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig index f780086..b9fd5c5 100644 --- a/arch/arm/mach-msm/Kconfig +++ b/arch/arm/mach-msm/Kconfig @@ -29,12 +29,14 @@ endchoice config MACH_HALIBUT depends on ARCH_MSM + select CPU_V6 default y bool "Halibut Board (QCT SURF7201A)" help Support for the Qualcomm SURF7201A eval board. config MACH_TROUT + select CPU_V6 default y bool "HTC Dream (aka trout)" help -- cgit v0.10.2 From 4b536b8d909f4e3dfa84fa7a63fbc5896e3490e8 Mon Sep 17 00:00:00 2001 From: Steve Muckle Date: Mon, 29 Dec 2008 16:17:22 -0500 Subject: arm: msm: define HAVE_CLK for ARCH_MSM MSM supports the interface. Acked-by: David Brown Signed-off-by: Steve Muckle diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 9264d01..355bc5e 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -601,6 +601,7 @@ config ARCH_PXA config ARCH_MSM bool "Qualcomm MSM" + select HAVE_CLK select GENERIC_TIME select GENERIC_CLOCKEVENTS help -- cgit v0.10.2 From ee3c454b8da04815c1884ed85fe89d2d131c0e51 Mon Sep 17 00:00:00 2001 From: Daniel Walker Date: Fri, 1 Jan 2010 14:52:30 -0800 Subject: arm: msm: add oprofile pmu support add oprofile pmu support for msm. Signed-off-by: Daniel Walker diff --git a/arch/arm/kernel/pmu.c b/arch/arm/kernel/pmu.c index a124312..4f0eb4c 100644 --- a/arch/arm/kernel/pmu.c +++ b/arch/arm/kernel/pmu.c @@ -44,6 +44,8 @@ static const int irqs[] = { IRQ_IOP33X_CORE_PMU, #elif defined(CONFIG_ARCH_PXA) IRQ_PMU, +#elif defined(CONFIG_ARCH_MSM_ARM11) + INT_ARM11_PMU, #endif }; -- cgit v0.10.2 From e220ba60223a9d63e70217e5b112160df8c21cea Mon Sep 17 00:00:00 2001 From: Dave Estes Date: Tue, 11 Aug 2009 17:58:49 -0400 Subject: arm: mm: qsd8x50: Fix incorrect permission faults Handle incorrectly reported permission faults for qsd8650. On permission faults, retry MVA to PA conversion. If retry detects translation fault. Report as translation fault. Cc: Jamie Lokier Signed-off-by: Dave Estes diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 5bd7c89..d3022da 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -572,6 +572,8 @@ config CPU_TLB_V6 config CPU_TLB_V7 bool +config VERIFY_PERMISSION_FAULT + bool endif config CPU_HAS_ASID diff --git a/arch/arm/mm/abort-ev7.S b/arch/arm/mm/abort-ev7.S index 2e6dc04..ec88b15 100644 --- a/arch/arm/mm/abort-ev7.S +++ b/arch/arm/mm/abort-ev7.S @@ -29,5 +29,26 @@ ENTRY(v7_early_abort) * V6 code adjusts the returned DFSR. * New designs should not need to patch up faults. */ + +#if defined(CONFIG_VERIFY_PERMISSION_FAULT) + /* + * Detect erroneous permission failures and fix + */ + ldr r3, =0x40d @ On permission fault + and r3, r1, r3 + cmp r3, #0x0d + movne pc, lr + + mcr p15, 0, r0, c7, c8, 0 @ Retranslate FAR + isb + mrc p15, 0, r2, c7, c4, 0 @ Read the PAR + and r3, r2, #0x7b @ On translation fault + cmp r3, #0x0b + movne pc, lr + bic r1, r1, #0xf @ Fix up FSR FS[5:0] + and r2, r2, #0x7e + orr r1, r1, r2, LSR #1 +#endif + mov pc, lr ENDPROC(v7_early_abort) -- cgit v0.10.2 From d8f089d2ad35861c432618900fa08ca70c168d76 Mon Sep 17 00:00:00 2001 From: Siddarth Gore Date: Mon, 22 Mar 2010 02:28:20 -0700 Subject: [ARM] Kirkwood: Marvell GuruPlug support GuruPlug Standard: 1 Gb Ethernet, 2 USB 2.0 GuruPlug Plus: 2 Gb Ethernet, 2 USB 2.0, 1 eSATA, 1 uSD slot References: http://www.globalscaletechnologies.com/t-guruplugdetails.aspx http://plugcomputer.org This patch is for GuruPlug Plus, but it supports Standard version as well. Signed-off-by: Siddarth Gore Signed-off-by: Nicolas Pitre diff --git a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig index 17879a8..05a8552 100644 --- a/arch/arm/mach-kirkwood/Kconfig +++ b/arch/arm/mach-kirkwood/Kconfig @@ -38,6 +38,12 @@ config MACH_ESATA_SHEEVAPLUG Say 'Y' here if you want your kernel to support the Marvell eSATA SheevaPlug Reference Board. +config MACH_GURUPLUG + bool "Marvell GuruPlug Reference Board" + help + Say 'Y' here if you want your kernel to support the + Marvell GuruPlug Reference Board. + config MACH_TS219 bool "QNAP TS-110, TS-119, TS-210, TS-219 and TS-219P Turbo NAS" help diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile index a5530e3..85b3a39 100644 --- a/arch/arm/mach-kirkwood/Makefile +++ b/arch/arm/mach-kirkwood/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_MACH_RD88F6281) += rd88f6281-setup.o obj-$(CONFIG_MACH_MV88F6281GTW_GE) += mv88f6281gtw_ge-setup.o obj-$(CONFIG_MACH_SHEEVAPLUG) += sheevaplug-setup.o obj-$(CONFIG_MACH_ESATA_SHEEVAPLUG) += sheevaplug-setup.o +obj-$(CONFIG_MACH_GURUPLUG) += guruplug-setup.o obj-$(CONFIG_MACH_TS219) += ts219-setup.o tsx1x-common.o obj-$(CONFIG_MACH_TS41X) += ts41x-setup.o tsx1x-common.o obj-$(CONFIG_MACH_OPENRD) += openrd-setup.o diff --git a/arch/arm/mach-kirkwood/guruplug-setup.c b/arch/arm/mach-kirkwood/guruplug-setup.c new file mode 100644 index 0000000..54d07c8 --- /dev/null +++ b/arch/arm/mach-kirkwood/guruplug-setup.c @@ -0,0 +1,131 @@ +/* + * arch/arm/mach-kirkwood/guruplug-setup.c + * + * Marvell GuruPlug Reference Board Setup + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" +#include "mpp.h" + +static struct mtd_partition guruplug_nand_parts[] = { + { + .name = "u-boot", + .offset = 0, + .size = SZ_1M + }, { + .name = "uImage", + .offset = MTDPART_OFS_NXTBLK, + .size = SZ_4M + }, { + .name = "root", + .offset = MTDPART_OFS_NXTBLK, + .size = MTDPART_SIZ_FULL + }, +}; + +static struct mv643xx_eth_platform_data guruplug_ge00_data = { + .phy_addr = MV643XX_ETH_PHY_ADDR(0), +}; + +static struct mv643xx_eth_platform_data guruplug_ge01_data = { + .phy_addr = MV643XX_ETH_PHY_ADDR(1), +}; + +static struct mv_sata_platform_data guruplug_sata_data = { + .n_ports = 1, +}; + +static struct mvsdio_platform_data guruplug_mvsdio_data = { + /* unfortunately the CD signal has not been connected */ +}; + +static struct gpio_led guruplug_led_pins[] = { + { + .name = "guruplug:red:health", + .gpio = 46, + .active_low = 1, + }, + { + .name = "guruplug:green:health", + .gpio = 47, + .active_low = 1, + }, + { + .name = "guruplug:red:wmode", + .gpio = 48, + .active_low = 1, + }, + { + .name = "guruplug:green:wmode", + .gpio = 49, + .active_low = 1, + }, +}; + +static struct gpio_led_platform_data guruplug_led_data = { + .leds = guruplug_led_pins, + .num_leds = ARRAY_SIZE(guruplug_led_pins), +}; + +static struct platform_device guruplug_leds = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &guruplug_led_data, + } +}; + +static unsigned int guruplug_mpp_config[] __initdata = { + MPP46_GPIO, /* M_RLED */ + MPP47_GPIO, /* M_GLED */ + MPP48_GPIO, /* B_RLED */ + MPP49_GPIO, /* B_GLED */ + 0 +}; + +static void __init guruplug_init(void) +{ + /* + * Basic setup. Needs to be called early. + */ + kirkwood_init(); + kirkwood_mpp_conf(guruplug_mpp_config); + + kirkwood_uart0_init(); + kirkwood_nand_init(ARRAY_AND_SIZE(guruplug_nand_parts), 25); + + kirkwood_ehci_init(); + kirkwood_ge00_init(&guruplug_ge00_data); + kirkwood_ge01_init(&guruplug_ge01_data); + kirkwood_sata_init(&guruplug_sata_data); + kirkwood_sdio_init(&guruplug_mvsdio_data); + + platform_device_register(&guruplug_leds); +} + +MACHINE_START(GURUPLUG, "Marvell GuruPlug Reference Board") + /* Maintainer: Siddarth Gore */ + .phys_io = KIRKWOOD_REGS_PHYS_BASE, + .io_pg_offst = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0x00000100, + .init_machine = guruplug_init, + .map_io = kirkwood_map_io, + .init_irq = kirkwood_init_irq, + .timer = &kirkwood_timer, +MACHINE_END -- cgit v0.10.2 From 5ccc8dab611fcd1d0961b73e22d6c2d108967862 Mon Sep 17 00:00:00 2001 From: Arnaud Patard Date: Sat, 3 Apr 2010 10:31:33 +0200 Subject: [ARM] dns323-setup.c: fix WARN() when booting Since commit b2a731aa5cbca7e0252da75e16de7ae5feb1313a, dns323_init() is setting the power led gpio direction with gpio_direction_output() but doesn't request the gpio before (which is not permitted by the gpio layer afaik). This behaviour is triggering a WARN() at boot time. Tested-by: Christian Samsel Cc: Martin Michlmayr Signed-off-by: Arnaud Patard Signed-off-by: Nicolas Pitre [ Part 2: "Attached Text" ] diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c index 421b82f..685f34a 100644 --- a/arch/arm/mach-orion5x/dns323-setup.c +++ b/arch/arm/mach-orion5x/dns323-setup.c @@ -439,6 +439,7 @@ static void __init dns323_init(void) */ if (dns323_dev_id() == MV88F5181_DEV_ID) { dns323_leds[0].active_low = 1; + gpio_request(DNS323_GPIO_LED_POWER1, "Power Led Enable"); gpio_direction_output(DNS323_GPIO_LED_POWER1, 0); } -- cgit v0.10.2 From 40d2e76315da38993129090dc5d56377e573c312 Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Sun, 21 Mar 2010 09:00:43 -0400 Subject: x86-32: Rework cache flush denied handler The cache flush denied error is an erratum on some AMD 486 clones. If an invd instruction is executed in userspace, the processor calls exception 19 (13 hex) instead of #GP (13 decimal). On cpus where XMM is not supported, redirect exception 19 to do_general_protection(). Also, remove die_if_kernel(), since this was the last user. Signed-off-by: Brian Gerst LKML-Reference: <1269176446-2489-2-git-send-email-brgerst@gmail.com> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu index a198293..6f6792c 100644 --- a/arch/x86/Kconfig.cpu +++ b/arch/x86/Kconfig.cpu @@ -338,6 +338,10 @@ config X86_F00F_BUG def_bool y depends on M586MMX || M586TSC || M586 || M486 || M386 +config X86_INVD_BUG + def_bool y + depends on M486 || M386 + config X86_WP_WORKS_OK def_bool y depends on !M386 diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index 44a8e0d..cd49141 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S @@ -53,6 +53,7 @@ #include #include #include +#include /* Avoid __ASSEMBLER__'ifying just for this. */ #include @@ -905,7 +906,25 @@ ENTRY(simd_coprocessor_error) RING0_INT_FRAME pushl $0 CFI_ADJUST_CFA_OFFSET 4 +#ifdef CONFIG_X86_INVD_BUG + /* AMD 486 bug: invd from userspace calls exception 19 instead of #GP */ +661: pushl $do_general_protection +662: +.section .altinstructions,"a" + .balign 4 + .long 661b + .long 663f + .byte X86_FEATURE_XMM + .byte 662b-661b + .byte 664f-663f +.previous +.section .altinstr_replacement,"ax" +663: pushl $do_simd_coprocessor_error +664: +.previous +#else pushl $do_simd_coprocessor_error +#endif CFI_ADJUST_CFA_OFFSET 4 jmp error_code CFI_ENDPROC diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 1168e44..a16c9df 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -108,15 +108,6 @@ static inline void preempt_conditional_cli(struct pt_regs *regs) dec_preempt_count(); } -#ifdef CONFIG_X86_32 -static inline void -die_if_kernel(const char *str, struct pt_regs *regs, long err) -{ - if (!user_mode_vm(regs)) - die(str, regs, err); -} -#endif - static void __kprobes do_trap(int trapnr, int signr, char *str, struct pt_regs *regs, long error_code, siginfo_t *info) @@ -729,30 +720,14 @@ do_simd_coprocessor_error(struct pt_regs *regs, long error_code) conditional_sti(regs); #ifdef CONFIG_X86_32 - if (cpu_has_xmm) { - /* Handle SIMD FPU exceptions on PIII+ processors. */ - ignore_fpu_irq = 1; - simd_math_error((void __user *)regs->ip); - return; - } - /* - * Handle strange cache flush from user space exception - * in all other cases. This is undocumented behaviour. - */ - if (regs->flags & X86_VM_MASK) { - handle_vm86_fault((struct kernel_vm86_regs *)regs, error_code); - return; - } - current->thread.trap_no = 19; - current->thread.error_code = error_code; - die_if_kernel("cache flush denied", regs, error_code); - force_sig(SIGSEGV, current); + ignore_fpu_irq = 1; #else if (!user_mode(regs) && kernel_math_error(regs, "kernel simd math error", 19)) return; - simd_math_error((void __user *)regs->ip); #endif + + simd_math_error((void __user *)regs->ip); } dotraplinkage void -- cgit v0.10.2 From 9b6dba9e0798325dab427b9d60c61630ccc39b28 Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Sun, 21 Mar 2010 09:00:44 -0400 Subject: x86: Merge simd_math_error() into math_error() The only difference between FPU and SIMD exceptions is where the status bits are read from (cwd/swd vs. mxcsr). This also fixes the discrepency introduced by commit adf77bac, which fixed FPU but not SIMD. Signed-off-by: Brian Gerst LKML-Reference: <1269176446-2489-3-git-send-email-brgerst@gmail.com> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h index 4da91ad..f66cda5 100644 --- a/arch/x86/include/asm/traps.h +++ b/arch/x86/include/asm/traps.h @@ -79,7 +79,7 @@ static inline int get_si_code(unsigned long condition) extern int panic_on_unrecovered_nmi; -void math_error(void __user *); +void math_error(struct pt_regs *, int, int); void math_emulate(struct math_emu_info *); #ifndef CONFIG_X86_32 asmlinkage void smp_thermal_interrupt(void); diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c index 0ed2d30..990ae7c 100644 --- a/arch/x86/kernel/irqinit.c +++ b/arch/x86/kernel/irqinit.c @@ -60,7 +60,7 @@ static irqreturn_t math_error_irq(int cpl, void *dev_id) outb(0, 0xF0); if (ignore_fpu_irq || !boot_cpu_data.hard_math) return IRQ_NONE; - math_error((void __user *)get_irq_regs()->ip); + math_error(get_irq_regs(), 0, 16); return IRQ_HANDLED; } diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index a16c9df..a472992 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -595,36 +595,48 @@ static int kernel_math_error(struct pt_regs *regs, const char *str, int trapnr) * the correct behaviour even in the presence of the asynchronous * IRQ13 behaviour */ -void math_error(void __user *ip) +void math_error(struct pt_regs *regs, int error_code, int trapnr) { struct task_struct *task; siginfo_t info; - unsigned short cwd, swd, err; + unsigned short err; /* * Save the info for the exception handler and clear the error. */ task = current; save_init_fpu(task); - task->thread.trap_no = 16; - task->thread.error_code = 0; + task->thread.trap_no = trapnr; + task->thread.error_code = error_code; info.si_signo = SIGFPE; info.si_errno = 0; - info.si_addr = ip; - /* - * (~cwd & swd) will mask out exceptions that are not set to unmasked - * status. 0x3f is the exception bits in these regs, 0x200 is the - * C1 reg you need in case of a stack fault, 0x040 is the stack - * fault bit. We should only be taking one exception at a time, - * so if this combination doesn't produce any single exception, - * then we have a bad program that isn't synchronizing its FPU usage - * and it will suffer the consequences since we won't be able to - * fully reproduce the context of the exception - */ - cwd = get_fpu_cwd(task); - swd = get_fpu_swd(task); + info.si_addr = (void __user *)regs->ip; + if (trapnr == 16) { + unsigned short cwd, swd; + /* + * (~cwd & swd) will mask out exceptions that are not set to unmasked + * status. 0x3f is the exception bits in these regs, 0x200 is the + * C1 reg you need in case of a stack fault, 0x040 is the stack + * fault bit. We should only be taking one exception at a time, + * so if this combination doesn't produce any single exception, + * then we have a bad program that isn't synchronizing its FPU usage + * and it will suffer the consequences since we won't be able to + * fully reproduce the context of the exception + */ + cwd = get_fpu_cwd(task); + swd = get_fpu_swd(task); - err = swd & ~cwd; + err = swd & ~cwd; + } else { + /* + * The SIMD FPU exceptions are handled a little differently, as there + * is only a single status/control register. Thus, to determine which + * unmasked exception was caught we must mask the exception mask bits + * at 0x1f80, and then use these to mask the exception bits at 0x3f. + */ + unsigned short mxcsr = get_fpu_mxcsr(task); + err = ~(mxcsr >> 7) & mxcsr; + } if (err & 0x001) { /* Invalid op */ /* @@ -663,55 +675,7 @@ dotraplinkage void do_coprocessor_error(struct pt_regs *regs, long error_code) return; #endif - math_error((void __user *)regs->ip); -} - -static void simd_math_error(void __user *ip) -{ - struct task_struct *task; - siginfo_t info; - unsigned short mxcsr; - - /* - * Save the info for the exception handler and clear the error. - */ - task = current; - save_init_fpu(task); - task->thread.trap_no = 19; - task->thread.error_code = 0; - info.si_signo = SIGFPE; - info.si_errno = 0; - info.si_code = __SI_FAULT; - info.si_addr = ip; - /* - * The SIMD FPU exceptions are handled a little differently, as there - * is only a single status/control register. Thus, to determine which - * unmasked exception was caught we must mask the exception mask bits - * at 0x1f80, and then use these to mask the exception bits at 0x3f. - */ - mxcsr = get_fpu_mxcsr(task); - switch (~((mxcsr & 0x1f80) >> 7) & (mxcsr & 0x3f)) { - case 0x000: - default: - break; - case 0x001: /* Invalid Op */ - info.si_code = FPE_FLTINV; - break; - case 0x002: /* Denormalize */ - case 0x010: /* Underflow */ - info.si_code = FPE_FLTUND; - break; - case 0x004: /* Zero Divide */ - info.si_code = FPE_FLTDIV; - break; - case 0x008: /* Overflow */ - info.si_code = FPE_FLTOVF; - break; - case 0x020: /* Precision */ - info.si_code = FPE_FLTRES; - break; - } - force_sig_info(SIGFPE, &info, task); + math_error(regs, error_code, 16); } dotraplinkage void @@ -727,7 +691,7 @@ do_simd_coprocessor_error(struct pt_regs *regs, long error_code) return; #endif - simd_math_error((void __user *)regs->ip); + math_error(regs, error_code, 19); } dotraplinkage void -- cgit v0.10.2 From e2e75c915de045f0785387dc32f55e92fab0614c Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Sun, 21 Mar 2010 09:00:45 -0400 Subject: x86: Merge kernel_math_error() into math_error() Clean up the kernel exception handling and make it more similar to the other traps. Signed-off-by: Brian Gerst LKML-Reference: <1269176446-2489-4-git-send-email-brgerst@gmail.com> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index a472992..53ba86f 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -576,20 +576,6 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) return; } -#ifdef CONFIG_X86_64 -static int kernel_math_error(struct pt_regs *regs, const char *str, int trapnr) -{ - if (fixup_exception(regs)) - return 1; - - notify_die(DIE_GPF, str, regs, 0, trapnr, SIGFPE); - /* Illegal floating point operation in the kernel */ - current->thread.trap_no = trapnr; - die(str, regs, 0); - return 0; -} -#endif - /* * Note that we play around with the 'TS' bit in an attempt to get * the correct behaviour even in the presence of the asynchronous @@ -597,14 +583,28 @@ static int kernel_math_error(struct pt_regs *regs, const char *str, int trapnr) */ void math_error(struct pt_regs *regs, int error_code, int trapnr) { - struct task_struct *task; + struct task_struct *task = current; siginfo_t info; unsigned short err; + char *str = (trapnr == 16) ? "fpu exception" : "simd exception"; + + if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, SIGFPE) == NOTIFY_STOP) + return; + conditional_sti(regs); + + if (!user_mode_vm(regs)) + { + if (!fixup_exception(regs)) { + task->thread.error_code = error_code; + task->thread.trap_no = trapnr; + die(str, regs, error_code); + } + return; + } /* * Save the info for the exception handler and clear the error. */ - task = current; save_init_fpu(task); task->thread.trap_no = trapnr; task->thread.error_code = error_code; @@ -665,14 +665,8 @@ void math_error(struct pt_regs *regs, int error_code, int trapnr) dotraplinkage void do_coprocessor_error(struct pt_regs *regs, long error_code) { - conditional_sti(regs); - #ifdef CONFIG_X86_32 ignore_fpu_irq = 1; -#else - if (!user_mode(regs) && - kernel_math_error(regs, "kernel x87 math error", 16)) - return; #endif math_error(regs, error_code, 16); @@ -681,14 +675,8 @@ dotraplinkage void do_coprocessor_error(struct pt_regs *regs, long error_code) dotraplinkage void do_simd_coprocessor_error(struct pt_regs *regs, long error_code) { - conditional_sti(regs); - #ifdef CONFIG_X86_32 ignore_fpu_irq = 1; -#else - if (!user_mode(regs) && - kernel_math_error(regs, "kernel simd math error", 19)) - return; #endif math_error(regs, error_code, 19); -- cgit v0.10.2 From 250825008f1f94887bc039e9227a8adfb5ba366e Mon Sep 17 00:00:00 2001 From: Brian Gerst Date: Sun, 21 Mar 2010 09:00:46 -0400 Subject: x86-32: Don't set ignore_fpu_irq in simd exception Any processor that supports simd will have an internal fpu, and the irq13 handler will not be enabled. Signed-off-by: Brian Gerst LKML-Reference: <1269176446-2489-5-git-send-email-brgerst@gmail.com> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 53ba86f..00516e1 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -675,10 +675,6 @@ dotraplinkage void do_coprocessor_error(struct pt_regs *regs, long error_code) dotraplinkage void do_simd_coprocessor_error(struct pt_regs *regs, long error_code) { -#ifdef CONFIG_X86_32 - ignore_fpu_irq = 1; -#endif - math_error(regs, error_code, 19); } -- cgit v0.10.2 From 18e2842b85a00158054b5751c4e5a1b56906895f Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 3 May 2010 16:43:47 -0400 Subject: update MAINTAINERS file I'm no longer at Marvell. Ditto for Lennert. I don't hack on SMC91x much either these days. Signed-off-by: Nicolas Pitre diff --git a/MAINTAINERS b/MAINTAINERS index d5b0b1b..d634cb0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -775,11 +775,10 @@ M: Philipp Zabel S: Maintained ARM/Marvell Loki/Kirkwood/MV78xx0/Orion SOC support -M: Lennert Buytenhek -M: Nicolas Pitre +M: Lennert Buytenhek +M: Nicolas Pitre L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -T: git git://git.marvell.com/orion -S: Maintained +S: Odd Fixes F: arch/arm/mach-loki/ F: arch/arm/mach-kirkwood/ F: arch/arm/mach-mv78xx0/ @@ -3624,7 +3623,8 @@ F: drivers/net/wireless/mwl8k.c MARVELL SOC MMC/SD/SDIO CONTROLLER DRIVER M: Nicolas Pitre -S: Maintained +S: Odd Fixes +F: drivers/mmc/host/mvsdio.* MARVELL YUKON / SYSKONNECT DRIVER M: Mirko Lindner @@ -5121,7 +5121,7 @@ F: mm/sl?b.c SMC91x ETHERNET DRIVER M: Nicolas Pitre -S: Maintained +S: Odd Fixes F: drivers/net/smc91x.* SMSC47B397 HARDWARE MONITOR DRIVER -- cgit v0.10.2 From 2a49456fdae0cc9e4286de38b8fcb85f9c7c7559 Mon Sep 17 00:00:00 2001 From: Simon Guinot Date: Wed, 3 Feb 2010 01:41:09 +0100 Subject: [ARM] Kirkwood: add LaCie 2Big Network v2 support Signed-off-by: Nicolas Pitre diff --git a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig index 05a8552..953681a 100644 --- a/arch/arm/mach-kirkwood/Kconfig +++ b/arch/arm/mach-kirkwood/Kconfig @@ -87,6 +87,12 @@ config MACH_INETSPACE_V2 Say 'Y' here if you want your kernel to support the LaCie Internet Space v2 NAS. +config MACH_NET2BIG_V2 + bool "LaCie 2Big Network v2 NAS Board" + help + Say 'Y' here if you want your kernel to support the + LaCie 2Big Network v2 NAS. + endmenu endif diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile index 85b3a39..3697d8e 100644 --- a/arch/arm/mach-kirkwood/Makefile +++ b/arch/arm/mach-kirkwood/Makefile @@ -12,5 +12,6 @@ obj-$(CONFIG_MACH_TS41X) += ts41x-setup.o tsx1x-common.o obj-$(CONFIG_MACH_OPENRD) += openrd-setup.o obj-$(CONFIG_MACH_NETSPACE_V2) += netspace_v2-setup.o obj-$(CONFIG_MACH_INETSPACE_V2) += netspace_v2-setup.o +obj-$(CONFIG_MACH_NET2BIG_V2) += net2big_v2-setup.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o diff --git a/arch/arm/mach-kirkwood/net2big_v2-setup.c b/arch/arm/mach-kirkwood/net2big_v2-setup.c new file mode 100644 index 0000000..359bb19 --- /dev/null +++ b/arch/arm/mach-kirkwood/net2big_v2-setup.c @@ -0,0 +1,334 @@ +/* + * arch/arm/mach-kirkwood/net2big_v2-setup.c + * + * LaCie 2Big Network v2 board setup + * + * Copyright (C) 2010 Simon Guinot + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" +#include "mpp.h" + +/***************************************************************************** + * 512KB SPI Flash on Boot Device (MACRONIX MX25L4005) + ****************************************************************************/ + +static struct mtd_partition net2big_v2_flash_parts[] = { + { + .name = "u-boot", + .size = MTDPART_SIZ_FULL, + .offset = 0, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, +}; + +static const struct flash_platform_data net2big_v2_flash = { + .type = "mx25l4005a", + .name = "spi_flash", + .parts = net2big_v2_flash_parts, + .nr_parts = ARRAY_SIZE(net2big_v2_flash_parts), +}; + +static struct spi_board_info __initdata net2big_v2_spi_slave_info[] = { + { + .modalias = "m25p80", + .platform_data = &net2big_v2_flash, + .irq = -1, + .max_speed_hz = 20000000, + .bus_num = 0, + .chip_select = 0, + }, +}; + +/***************************************************************************** + * Ethernet + ****************************************************************************/ + +static struct mv643xx_eth_platform_data net2big_v2_ge00_data = { + .phy_addr = MV643XX_ETH_PHY_ADDR(8), +}; + +/***************************************************************************** + * I2C devices + ****************************************************************************/ + +static struct at24_platform_data at24c04 = { + .byte_len = SZ_4K / 8, + .page_size = 16, +}; + +/* + * i2c addr | chip | description + * 0x50 | HT24LC04 | eeprom (512B) + */ + +static struct i2c_board_info __initdata net2big_v2_i2c_info[] = { + { + I2C_BOARD_INFO("24c04", 0x50), + .platform_data = &at24c04, + } +}; + +/***************************************************************************** + * SATA + ****************************************************************************/ + +static struct mv_sata_platform_data net2big_v2_sata_data = { + .n_ports = 2, +}; + +static int __initdata net2big_v2_gpio_hdd_power[] = { 16, 17 }; + +static void __init net2big_v2_sata_power_init(void) +{ + int i; + int err; + + /* Power up all hard disks. */ + for (i = 0; i < ARRAY_SIZE(net2big_v2_gpio_hdd_power); i++) { + err = gpio_request(net2big_v2_gpio_hdd_power[i], NULL); + if (err == 0) { + err = gpio_direction_output( + net2big_v2_gpio_hdd_power[i], 1); + /* Free the HDD power GPIOs. This allow user-space to + * configure them via the gpiolib sysfs interface. */ + gpio_free(net2big_v2_gpio_hdd_power[i]); + } + if (err) + pr_err("net2big_v2: failed to power-up HDD%d\n", i + 1); + } +} + +/***************************************************************************** + * GPIO keys + ****************************************************************************/ + +#define NET2BIG_V2_GPIO_SWITCH_POWER_ON 13 +#define NET2BIG_V2_GPIO_SWITCH_POWER_OFF 15 +#define NET2BIG_V2_GPIO_FUNC_BUTTON 34 + +#define NET2BIG_V2_SWITCH_POWER_ON 0x1 +#define NET2BIG_V2_SWITCH_POWER_OFF 0x2 + +static struct gpio_keys_button net2big_v2_buttons[] = { + [0] = { + .type = EV_SW, + .code = NET2BIG_V2_SWITCH_POWER_ON, + .gpio = NET2BIG_V2_GPIO_SWITCH_POWER_ON, + .desc = "Back power switch (on|auto)", + .active_low = 1, + }, + [1] = { + .type = EV_SW, + .code = NET2BIG_V2_SWITCH_POWER_OFF, + .gpio = NET2BIG_V2_GPIO_SWITCH_POWER_OFF, + .desc = "Back power switch (auto|off)", + .active_low = 1, + }, + [2] = { + .code = KEY_OPTION, + .gpio = NET2BIG_V2_GPIO_FUNC_BUTTON, + .desc = "Function button", + .active_low = 1, + }, +}; + +static struct gpio_keys_platform_data net2big_v2_button_data = { + .buttons = net2big_v2_buttons, + .nbuttons = ARRAY_SIZE(net2big_v2_buttons), +}; + +static struct platform_device net2big_v2_gpio_buttons = { + .name = "gpio-keys", + .id = -1, + .dev = { + .platform_data = &net2big_v2_button_data, + }, +}; + +/***************************************************************************** + * GPIO LEDs + ****************************************************************************/ + +/* + * The LEDs are controlled by a CPLD and can be configured through a GPIO + * extension bus: + * + * - address register : bit [0-2] -> GPIO [47-49] + * - data register : bit [0-2] -> GPIO [44-46] + * - enable register : GPIO 29 + * + * Address register selection: + * + * addr | register + * ---------------------------- + * 0 | front LED + * 1 | front LED brightness + * 2 | HDD LED brightness + * 3 | HDD1 LED + * 4 | HDD2 LED + * + * Data register configuration: + * + * data | LED brightness + * ------------------------------------------------- + * 0 | min (off) + * - | - + * 7 | max + * + * data | front LED mode + * ------------------------------------------------- + * 0 | fix off + * 1 | fix blue on + * 2 | fix red on + * 3 | blink blue on=1 sec and blue off=1 sec + * 4 | blink red on=1 sec and red off=1 sec + * 5 | blink blue on=2.5 sec and red on=0.5 sec + * 6 | blink blue on=1 sec and red on=1 sec + * 7 | blink blue on=0.5 sec and blue off=2.5 sec + * + * data | HDD LED mode + * ------------------------------------------------- + * 0 | fix blue on + * 1 | SATA activity blink + * 2 | fix red on + * 3 | blink blue on=1 sec and blue off=1 sec + * 4 | blink red on=1 sec and red off=1 sec + * 5 | blink blue on=2.5 sec and red on=0.5 sec + * 6 | blink blue on=1 sec and red on=1 sec + * 7 | blink blue on=0.5 sec and blue off=2.5 sec + */ + +/***************************************************************************** + * Timer + ****************************************************************************/ + +static void net2big_v2_timer_init(void) +{ + kirkwood_tclk = 166666667; + orion_time_init(IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk); +} + +struct sys_timer net2big_v2_timer = { + .init = net2big_v2_timer_init, +}; + +/***************************************************************************** + * General Setup + ****************************************************************************/ + +static unsigned int net2big_v2_mpp_config[] __initdata = { + MPP0_SPI_SCn, + MPP1_SPI_MOSI, + MPP2_SPI_SCK, + MPP3_SPI_MISO, + MPP6_SYSRST_OUTn, + MPP7_GPO, /* Request power-off */ + MPP8_TW_SDA, + MPP9_TW_SCK, + MPP10_UART0_TXD, + MPP11_UART0_RXD, + MPP13_GPIO, /* Rear power switch (on|auto) */ + MPP14_GPIO, /* USB fuse alarm */ + MPP15_GPIO, /* Rear power switch (auto|off) */ + MPP16_GPIO, /* SATA HDD1 power */ + MPP17_GPIO, /* SATA HDD2 power */ + MPP20_SATA1_ACTn, + MPP21_SATA0_ACTn, + MPP24_GPIO, /* USB mode select */ + MPP26_GPIO, /* USB device vbus */ + MPP28_GPIO, /* USB enable host vbus */ + MPP29_GPIO, /* GPIO extension ALE */ + MPP34_GPIO, /* Rear Push button */ + MPP35_GPIO, /* Inhibit switch power-off */ + MPP36_GPIO, /* SATA HDD1 presence */ + MPP37_GPIO, /* SATA HDD2 presence */ + MPP40_GPIO, /* eSATA presence */ + MPP44_GPIO, /* GPIO extension (data 0) */ + MPP45_GPIO, /* GPIO extension (data 1) */ + MPP46_GPIO, /* GPIO extension (data 2) */ + MPP47_GPIO, /* GPIO extension (addr 0) */ + MPP48_GPIO, /* GPIO extension (addr 1) */ + MPP49_GPIO, /* GPIO extension (addr 2) */ + 0 +}; + +#define NET2BIG_V2_GPIO_POWER_OFF 7 + +static void net2big_v2_power_off(void) +{ + gpio_set_value(NET2BIG_V2_GPIO_POWER_OFF, 1); +} + +static void __init net2big_v2_init(void) +{ + /* + * Basic setup. Needs to be called early. + */ + kirkwood_init(); + kirkwood_mpp_conf(net2big_v2_mpp_config); + + net2big_v2_sata_power_init(); + + kirkwood_ehci_init(); + kirkwood_ge00_init(&net2big_v2_ge00_data); + kirkwood_sata_init(&net2big_v2_sata_data); + kirkwood_uart0_init(); + spi_register_board_info(net2big_v2_spi_slave_info, + ARRAY_SIZE(net2big_v2_spi_slave_info)); + kirkwood_spi_init(); + kirkwood_i2c_init(); + i2c_register_board_info(0, net2big_v2_i2c_info, + ARRAY_SIZE(net2big_v2_i2c_info)); + + platform_device_register(&net2big_v2_gpio_buttons); + + if (gpio_request(NET2BIG_V2_GPIO_POWER_OFF, "power-off") == 0 && + gpio_direction_output(NET2BIG_V2_GPIO_POWER_OFF, 0) == 0) + pm_power_off = net2big_v2_power_off; + else + pr_err("net2big_v2: failed to configure power-off GPIO\n"); +} + +MACHINE_START(NET2BIG_V2, "LaCie 2Big Network v2") + .phys_io = KIRKWOOD_REGS_PHYS_BASE, + .io_pg_offst = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0x00000100, + .init_machine = net2big_v2_init, + .map_io = kirkwood_map_io, + .init_irq = kirkwood_init_irq, + .timer = &net2big_v2_timer, +MACHINE_END -- cgit v0.10.2 From 9414e99672271adcc661f3c160a30b374179b92f Mon Sep 17 00:00:00 2001 From: Phil Carmody Date: Wed, 28 Apr 2010 12:09:16 -0500 Subject: oprofile: protect from not being in an IRQ context http://lkml.org/lkml/2010/4/27/285 Protect against dereferencing regs when it's NULL, and force a magic number into pc to prevent too deep processing. This approach permits the dropped samples to be tallied as invalid Instruction Pointer events. e.g. output from about 15mins at 10kHz sample rate: Nr. samples received: 2565380 Nr. samples lost invalid pc: 4 Signed-off-by: Phil Carmody Signed-off-by: Robert Richter diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index 0ac8b06..219f79e 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -319,8 +319,16 @@ void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs, void oprofile_add_sample(struct pt_regs * const regs, unsigned long event) { - int is_kernel = !user_mode(regs); - unsigned long pc = profile_pc(regs); + int is_kernel; + unsigned long pc; + + if (likely(regs)) { + is_kernel = !user_mode(regs); + pc = profile_pc(regs); + } else { + is_kernel = 0; /* This value will not be used */ + pc = ESCAPE_CODE; /* as this causes an early return. */ + } __oprofile_add_ext_sample(pc, regs, event, is_kernel); } -- cgit v0.10.2 From 3e05ec1b93cd839fa1d1a9961b155b0dbc9a4055 Mon Sep 17 00:00:00 2001 From: Simon Guinot Date: Mon, 4 Jan 2010 20:20:07 +0100 Subject: [ARM] Kirkwood: add LaCie 5Big Network v2 support Signed-off-by: Nicolas Pitre diff --git a/arch/arm/mach-kirkwood/Kconfig b/arch/arm/mach-kirkwood/Kconfig index 953681a..29b2163 100644 --- a/arch/arm/mach-kirkwood/Kconfig +++ b/arch/arm/mach-kirkwood/Kconfig @@ -93,6 +93,12 @@ config MACH_NET2BIG_V2 Say 'Y' here if you want your kernel to support the LaCie 2Big Network v2 NAS. +config MACH_NET5BIG_V2 + bool "LaCie 5Big Network v2 NAS Board" + help + Say 'Y' here if you want your kernel to support the + LaCie 5Big Network v2 NAS. + endmenu endif diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile index 3697d8e..bbb8dd3 100644 --- a/arch/arm/mach-kirkwood/Makefile +++ b/arch/arm/mach-kirkwood/Makefile @@ -13,5 +13,6 @@ obj-$(CONFIG_MACH_OPENRD) += openrd-setup.o obj-$(CONFIG_MACH_NETSPACE_V2) += netspace_v2-setup.o obj-$(CONFIG_MACH_INETSPACE_V2) += netspace_v2-setup.o obj-$(CONFIG_MACH_NET2BIG_V2) += net2big_v2-setup.o +obj-$(CONFIG_MACH_NET5BIG_V2) += net5big_v2-setup.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o diff --git a/arch/arm/mach-kirkwood/net5big_v2-setup.c b/arch/arm/mach-kirkwood/net5big_v2-setup.c new file mode 100644 index 0000000..f0617ec --- /dev/null +++ b/arch/arm/mach-kirkwood/net5big_v2-setup.c @@ -0,0 +1,355 @@ +/* + * arch/arm/mach-kirkwood/net5big_v2-setup.c + * + * LaCie 5Big Network v2 board setup + * + * Copyright (C) 2010 Simon Guinot + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" +#include "mpp.h" + +/***************************************************************************** + * 512KB SPI Flash on Boot Device (MACRONIX MX25L4005) + ****************************************************************************/ + +static struct mtd_partition net5big_v2_flash_parts[] = { + { + .name = "u-boot", + .size = MTDPART_SIZ_FULL, + .offset = 0, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, +}; + +static const struct flash_platform_data net5big_v2_flash = { + .type = "mx25l4005a", + .name = "spi_flash", + .parts = net5big_v2_flash_parts, + .nr_parts = ARRAY_SIZE(net5big_v2_flash_parts), +}; + +static struct spi_board_info __initdata net5big_v2_spi_slave_info[] = { + { + .modalias = "m25p80", + .platform_data = &net5big_v2_flash, + .irq = -1, + .max_speed_hz = 20000000, + .bus_num = 0, + .chip_select = 0, + }, +}; + +/***************************************************************************** + * Ethernet + ****************************************************************************/ + +static struct mv643xx_eth_platform_data net5big_v2_ge00_data = { + .phy_addr = MV643XX_ETH_PHY_ADDR(8), +}; + +static struct mv643xx_eth_platform_data net5big_v2_ge01_data = { + .phy_addr = MV643XX_ETH_PHY_ADDR(0), +}; + +/***************************************************************************** + * I2C devices + ****************************************************************************/ + +static struct at24_platform_data at24c04 = { + .byte_len = SZ_4K / 8, + .page_size = 16, +}; + +/* + * i2c addr | chip | description + * 0x50 | HT24LC04 | eeprom (512B) + */ + +static struct i2c_board_info __initdata net5big_v2_i2c_info[] = { + { + I2C_BOARD_INFO("24c04", 0x50), + .platform_data = &at24c04, + } +}; + +/***************************************************************************** + * SATA + ****************************************************************************/ + +static struct mv_sata_platform_data net5big_v2_sata_data = { + .n_ports = 2, +}; + +static int __initdata net5big_v2_gpio_hdd_power[] = { 16, 17, 41, 42, 43 }; + +static void __init net5big_v2_sata_power_init(void) +{ + int i; + int err; + + /* Power up all hard disks. */ + for (i = 0; i < ARRAY_SIZE(net5big_v2_gpio_hdd_power); i++) { + err = gpio_request(net5big_v2_gpio_hdd_power[i], NULL); + if (err == 0) { + err = gpio_direction_output( + net5big_v2_gpio_hdd_power[i], 1); + /* Free the HDD power GPIOs. This allow user-space to + * configure them via the gpiolib sysfs interface. */ + gpio_free(net5big_v2_gpio_hdd_power[i]); + } + if (err) + pr_err("net5big_v2: failed to power up HDD%d\n", i + 1); + } +} + +/***************************************************************************** + * GPIO keys + ****************************************************************************/ + +#define NET5BIG_V2_GPIO_SWITCH_POWER_ON 13 +#define NET5BIG_V2_GPIO_SWITCH_POWER_OFF 15 +#define NET5BIG_V2_GPIO_FUNC_BUTTON 34 + +#define NET5BIG_V2_SWITCH_POWER_ON 0x1 +#define NET5BIG_V2_SWITCH_POWER_OFF 0x2 + +static struct gpio_keys_button net5big_v2_buttons[] = { + [0] = { + .type = EV_SW, + .code = NET5BIG_V2_SWITCH_POWER_ON, + .gpio = NET5BIG_V2_GPIO_SWITCH_POWER_ON, + .desc = "Back power switch (on|auto)", + .active_low = 1, + }, + [1] = { + .type = EV_SW, + .code = NET5BIG_V2_SWITCH_POWER_OFF, + .gpio = NET5BIG_V2_GPIO_SWITCH_POWER_OFF, + .desc = "Back power switch (auto|off)", + .active_low = 1, + }, + [2] = { + .code = KEY_OPTION, + .gpio = NET5BIG_V2_GPIO_FUNC_BUTTON, + .desc = "Function button", + .active_low = 1, + }, +}; + +static struct gpio_keys_platform_data net5big_v2_button_data = { + .buttons = net5big_v2_buttons, + .nbuttons = ARRAY_SIZE(net5big_v2_buttons), +}; + +static struct platform_device net5big_v2_gpio_buttons = { + .name = "gpio-keys", + .id = -1, + .dev = { + .platform_data = &net5big_v2_button_data, + }, +}; + +/***************************************************************************** + * GPIO LEDs + ****************************************************************************/ + +/* + * The LEDs are controlled by a CPLD and can be configured through a GPIO + * extension bus: + * + * - address register : bit [0-2] -> GPIO [47-49] + * - data register : bit [0-2] -> GPIO [44-46] + * - enable register : GPIO 29 + * + * Address register selection: + * + * addr | register + * ---------------------------- + * 0 | front LED + * 1 | front LED brightness + * 2 | HDD LED brightness + * 3 | HDD1 LED + * 4 | HDD2 LED + * 5 | HDD3 LED + * 6 | HDD4 LED + * 7 | HDD5 LED + * + * Data register configuration: + * + * data | LED brightness + * ------------------------------------------------- + * 0 | min (off) + * - | - + * 7 | max + * + * data | front LED mode + * ------------------------------------------------- + * 0 | fix off + * 1 | fix blue on + * 2 | fix red on + * 3 | blink blue on=1 sec and blue off=1 sec + * 4 | blink red on=1 sec and red off=1 sec + * 5 | blink blue on=2.5 sec and red on=0.5 sec + * 6 | blink blue on=1 sec and red on=1 sec + * 7 | blink blue on=0.5 sec and blue off=2.5 sec + * + * data | HDD LED mode + * ------------------------------------------------- + * 0 | fix blue on + * 1 | SATA activity blink + * 2 | fix red on + * 3 | blink blue on=1 sec and blue off=1 sec + * 4 | blink red on=1 sec and red off=1 sec + * 5 | blink blue on=2.5 sec and red on=0.5 sec + * 6 | blink blue on=1 sec and red on=1 sec + * 7 | blink blue on=0.5 sec and blue off=2.5 sec + */ + +/***************************************************************************** + * Timer + ****************************************************************************/ + +static void net5big_v2_timer_init(void) +{ + kirkwood_tclk = 166666667; + orion_time_init(IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk); +} + +struct sys_timer net5big_v2_timer = { + .init = net5big_v2_timer_init, +}; + +/***************************************************************************** + * General Setup + ****************************************************************************/ + +static unsigned int net5big_v2_mpp_config[] __initdata = { + MPP0_SPI_SCn, + MPP1_SPI_MOSI, + MPP2_SPI_SCK, + MPP3_SPI_MISO, + MPP6_SYSRST_OUTn, + MPP7_GPO, /* Request power-off */ + MPP8_TW_SDA, + MPP9_TW_SCK, + MPP10_UART0_TXD, + MPP11_UART0_RXD, + MPP13_GPIO, /* Rear power switch (on|auto) */ + MPP14_GPIO, /* USB fuse alarm */ + MPP15_GPIO, /* Rear power switch (auto|off) */ + MPP16_GPIO, /* SATA HDD1 power */ + MPP17_GPIO, /* SATA HDD2 power */ + MPP20_GE1_0, + MPP21_GE1_1, + MPP22_GE1_2, + MPP23_GE1_3, + MPP24_GE1_4, + MPP25_GE1_5, + MPP26_GE1_6, + MPP27_GE1_7, + MPP28_GPIO, /* USB enable host vbus */ + MPP29_GPIO, /* CPLD extension ALE */ + MPP30_GE1_10, + MPP31_GE1_11, + MPP32_GE1_12, + MPP33_GE1_13, + MPP34_GPIO, /* Rear Push button */ + MPP35_GPIO, /* Inhibit switch power-off */ + MPP36_GPIO, /* SATA HDD1 presence */ + MPP37_GPIO, /* SATA HDD2 presence */ + MPP38_GPIO, /* SATA HDD3 presence */ + MPP39_GPIO, /* SATA HDD4 presence */ + MPP40_GPIO, /* SATA HDD5 presence */ + MPP41_GPIO, /* SATA HDD3 power */ + MPP42_GPIO, /* SATA HDD4 power */ + MPP43_GPIO, /* SATA HDD5 power */ + MPP44_GPIO, /* CPLD extension (data 0) */ + MPP45_GPIO, /* CPLD extension (data 1) */ + MPP46_GPIO, /* CPLD extension (data 2) */ + MPP47_GPIO, /* CPLD extension (addr 0) */ + MPP48_GPIO, /* CPLD extension (addr 1) */ + MPP49_GPIO, /* CPLD extension (addr 2) */ + 0 +}; + +#define NET5BIG_V2_GPIO_POWER_OFF 7 + +static void net5big_v2_power_off(void) +{ + gpio_set_value(NET5BIG_V2_GPIO_POWER_OFF, 1); +} + +static void __init net5big_v2_init(void) +{ + /* + * Basic setup. Needs to be called early. + */ + kirkwood_init(); + kirkwood_mpp_conf(net5big_v2_mpp_config); + + net5big_v2_sata_power_init(); + + kirkwood_ehci_init(); + kirkwood_ge00_init(&net5big_v2_ge00_data); + kirkwood_ge01_init(&net5big_v2_ge01_data); + kirkwood_sata_init(&net5big_v2_sata_data); + kirkwood_uart0_init(); + spi_register_board_info(net5big_v2_spi_slave_info, + ARRAY_SIZE(net5big_v2_spi_slave_info)); + kirkwood_spi_init(); + kirkwood_i2c_init(); + i2c_register_board_info(0, net5big_v2_i2c_info, + ARRAY_SIZE(net5big_v2_i2c_info)); + + platform_device_register(&net5big_v2_gpio_buttons); + + if (gpio_request(NET5BIG_V2_GPIO_POWER_OFF, "power-off") == 0 && + gpio_direction_output(NET5BIG_V2_GPIO_POWER_OFF, 0) == 0) + pm_power_off = net5big_v2_power_off; + else + pr_err("net5big_v2: failed to configure power-off GPIO\n"); +} + +MACHINE_START(NET5BIG_V2, "LaCie 5Big Network v2") + .phys_io = KIRKWOOD_REGS_PHYS_BASE, + .io_pg_offst = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0x00000100, + .init_machine = net5big_v2_init, + .map_io = kirkwood_map_io, + .init_irq = kirkwood_init_irq, + .timer = &net5big_v2_timer, +MACHINE_END -- cgit v0.10.2 From 57475b1a47b3e891ce087ca3c6fc93f5a446a244 Mon Sep 17 00:00:00 2001 From: Simon Guinot Date: Mon, 8 Feb 2010 19:08:34 +0100 Subject: [ARM] Kirkwood: merge net2big_v2 and net5big_v2 board setups Signed-off-by: Nicolas Pitre diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile index bbb8dd3..c0cd5d3 100644 --- a/arch/arm/mach-kirkwood/Makefile +++ b/arch/arm/mach-kirkwood/Makefile @@ -12,7 +12,7 @@ obj-$(CONFIG_MACH_TS41X) += ts41x-setup.o tsx1x-common.o obj-$(CONFIG_MACH_OPENRD) += openrd-setup.o obj-$(CONFIG_MACH_NETSPACE_V2) += netspace_v2-setup.o obj-$(CONFIG_MACH_INETSPACE_V2) += netspace_v2-setup.o -obj-$(CONFIG_MACH_NET2BIG_V2) += net2big_v2-setup.o -obj-$(CONFIG_MACH_NET5BIG_V2) += net5big_v2-setup.o +obj-$(CONFIG_MACH_NET2BIG_V2) += netxbig_v2-setup.o +obj-$(CONFIG_MACH_NET5BIG_V2) += netxbig_v2-setup.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o diff --git a/arch/arm/mach-kirkwood/net2big_v2-setup.c b/arch/arm/mach-kirkwood/net2big_v2-setup.c deleted file mode 100644 index 359bb19..0000000 --- a/arch/arm/mach-kirkwood/net2big_v2-setup.c +++ /dev/null @@ -1,334 +0,0 @@ -/* - * arch/arm/mach-kirkwood/net2big_v2-setup.c - * - * LaCie 2Big Network v2 board setup - * - * Copyright (C) 2010 Simon Guinot - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "common.h" -#include "mpp.h" - -/***************************************************************************** - * 512KB SPI Flash on Boot Device (MACRONIX MX25L4005) - ****************************************************************************/ - -static struct mtd_partition net2big_v2_flash_parts[] = { - { - .name = "u-boot", - .size = MTDPART_SIZ_FULL, - .offset = 0, - .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, -}; - -static const struct flash_platform_data net2big_v2_flash = { - .type = "mx25l4005a", - .name = "spi_flash", - .parts = net2big_v2_flash_parts, - .nr_parts = ARRAY_SIZE(net2big_v2_flash_parts), -}; - -static struct spi_board_info __initdata net2big_v2_spi_slave_info[] = { - { - .modalias = "m25p80", - .platform_data = &net2big_v2_flash, - .irq = -1, - .max_speed_hz = 20000000, - .bus_num = 0, - .chip_select = 0, - }, -}; - -/***************************************************************************** - * Ethernet - ****************************************************************************/ - -static struct mv643xx_eth_platform_data net2big_v2_ge00_data = { - .phy_addr = MV643XX_ETH_PHY_ADDR(8), -}; - -/***************************************************************************** - * I2C devices - ****************************************************************************/ - -static struct at24_platform_data at24c04 = { - .byte_len = SZ_4K / 8, - .page_size = 16, -}; - -/* - * i2c addr | chip | description - * 0x50 | HT24LC04 | eeprom (512B) - */ - -static struct i2c_board_info __initdata net2big_v2_i2c_info[] = { - { - I2C_BOARD_INFO("24c04", 0x50), - .platform_data = &at24c04, - } -}; - -/***************************************************************************** - * SATA - ****************************************************************************/ - -static struct mv_sata_platform_data net2big_v2_sata_data = { - .n_ports = 2, -}; - -static int __initdata net2big_v2_gpio_hdd_power[] = { 16, 17 }; - -static void __init net2big_v2_sata_power_init(void) -{ - int i; - int err; - - /* Power up all hard disks. */ - for (i = 0; i < ARRAY_SIZE(net2big_v2_gpio_hdd_power); i++) { - err = gpio_request(net2big_v2_gpio_hdd_power[i], NULL); - if (err == 0) { - err = gpio_direction_output( - net2big_v2_gpio_hdd_power[i], 1); - /* Free the HDD power GPIOs. This allow user-space to - * configure them via the gpiolib sysfs interface. */ - gpio_free(net2big_v2_gpio_hdd_power[i]); - } - if (err) - pr_err("net2big_v2: failed to power-up HDD%d\n", i + 1); - } -} - -/***************************************************************************** - * GPIO keys - ****************************************************************************/ - -#define NET2BIG_V2_GPIO_SWITCH_POWER_ON 13 -#define NET2BIG_V2_GPIO_SWITCH_POWER_OFF 15 -#define NET2BIG_V2_GPIO_FUNC_BUTTON 34 - -#define NET2BIG_V2_SWITCH_POWER_ON 0x1 -#define NET2BIG_V2_SWITCH_POWER_OFF 0x2 - -static struct gpio_keys_button net2big_v2_buttons[] = { - [0] = { - .type = EV_SW, - .code = NET2BIG_V2_SWITCH_POWER_ON, - .gpio = NET2BIG_V2_GPIO_SWITCH_POWER_ON, - .desc = "Back power switch (on|auto)", - .active_low = 1, - }, - [1] = { - .type = EV_SW, - .code = NET2BIG_V2_SWITCH_POWER_OFF, - .gpio = NET2BIG_V2_GPIO_SWITCH_POWER_OFF, - .desc = "Back power switch (auto|off)", - .active_low = 1, - }, - [2] = { - .code = KEY_OPTION, - .gpio = NET2BIG_V2_GPIO_FUNC_BUTTON, - .desc = "Function button", - .active_low = 1, - }, -}; - -static struct gpio_keys_platform_data net2big_v2_button_data = { - .buttons = net2big_v2_buttons, - .nbuttons = ARRAY_SIZE(net2big_v2_buttons), -}; - -static struct platform_device net2big_v2_gpio_buttons = { - .name = "gpio-keys", - .id = -1, - .dev = { - .platform_data = &net2big_v2_button_data, - }, -}; - -/***************************************************************************** - * GPIO LEDs - ****************************************************************************/ - -/* - * The LEDs are controlled by a CPLD and can be configured through a GPIO - * extension bus: - * - * - address register : bit [0-2] -> GPIO [47-49] - * - data register : bit [0-2] -> GPIO [44-46] - * - enable register : GPIO 29 - * - * Address register selection: - * - * addr | register - * ---------------------------- - * 0 | front LED - * 1 | front LED brightness - * 2 | HDD LED brightness - * 3 | HDD1 LED - * 4 | HDD2 LED - * - * Data register configuration: - * - * data | LED brightness - * ------------------------------------------------- - * 0 | min (off) - * - | - - * 7 | max - * - * data | front LED mode - * ------------------------------------------------- - * 0 | fix off - * 1 | fix blue on - * 2 | fix red on - * 3 | blink blue on=1 sec and blue off=1 sec - * 4 | blink red on=1 sec and red off=1 sec - * 5 | blink blue on=2.5 sec and red on=0.5 sec - * 6 | blink blue on=1 sec and red on=1 sec - * 7 | blink blue on=0.5 sec and blue off=2.5 sec - * - * data | HDD LED mode - * ------------------------------------------------- - * 0 | fix blue on - * 1 | SATA activity blink - * 2 | fix red on - * 3 | blink blue on=1 sec and blue off=1 sec - * 4 | blink red on=1 sec and red off=1 sec - * 5 | blink blue on=2.5 sec and red on=0.5 sec - * 6 | blink blue on=1 sec and red on=1 sec - * 7 | blink blue on=0.5 sec and blue off=2.5 sec - */ - -/***************************************************************************** - * Timer - ****************************************************************************/ - -static void net2big_v2_timer_init(void) -{ - kirkwood_tclk = 166666667; - orion_time_init(IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk); -} - -struct sys_timer net2big_v2_timer = { - .init = net2big_v2_timer_init, -}; - -/***************************************************************************** - * General Setup - ****************************************************************************/ - -static unsigned int net2big_v2_mpp_config[] __initdata = { - MPP0_SPI_SCn, - MPP1_SPI_MOSI, - MPP2_SPI_SCK, - MPP3_SPI_MISO, - MPP6_SYSRST_OUTn, - MPP7_GPO, /* Request power-off */ - MPP8_TW_SDA, - MPP9_TW_SCK, - MPP10_UART0_TXD, - MPP11_UART0_RXD, - MPP13_GPIO, /* Rear power switch (on|auto) */ - MPP14_GPIO, /* USB fuse alarm */ - MPP15_GPIO, /* Rear power switch (auto|off) */ - MPP16_GPIO, /* SATA HDD1 power */ - MPP17_GPIO, /* SATA HDD2 power */ - MPP20_SATA1_ACTn, - MPP21_SATA0_ACTn, - MPP24_GPIO, /* USB mode select */ - MPP26_GPIO, /* USB device vbus */ - MPP28_GPIO, /* USB enable host vbus */ - MPP29_GPIO, /* GPIO extension ALE */ - MPP34_GPIO, /* Rear Push button */ - MPP35_GPIO, /* Inhibit switch power-off */ - MPP36_GPIO, /* SATA HDD1 presence */ - MPP37_GPIO, /* SATA HDD2 presence */ - MPP40_GPIO, /* eSATA presence */ - MPP44_GPIO, /* GPIO extension (data 0) */ - MPP45_GPIO, /* GPIO extension (data 1) */ - MPP46_GPIO, /* GPIO extension (data 2) */ - MPP47_GPIO, /* GPIO extension (addr 0) */ - MPP48_GPIO, /* GPIO extension (addr 1) */ - MPP49_GPIO, /* GPIO extension (addr 2) */ - 0 -}; - -#define NET2BIG_V2_GPIO_POWER_OFF 7 - -static void net2big_v2_power_off(void) -{ - gpio_set_value(NET2BIG_V2_GPIO_POWER_OFF, 1); -} - -static void __init net2big_v2_init(void) -{ - /* - * Basic setup. Needs to be called early. - */ - kirkwood_init(); - kirkwood_mpp_conf(net2big_v2_mpp_config); - - net2big_v2_sata_power_init(); - - kirkwood_ehci_init(); - kirkwood_ge00_init(&net2big_v2_ge00_data); - kirkwood_sata_init(&net2big_v2_sata_data); - kirkwood_uart0_init(); - spi_register_board_info(net2big_v2_spi_slave_info, - ARRAY_SIZE(net2big_v2_spi_slave_info)); - kirkwood_spi_init(); - kirkwood_i2c_init(); - i2c_register_board_info(0, net2big_v2_i2c_info, - ARRAY_SIZE(net2big_v2_i2c_info)); - - platform_device_register(&net2big_v2_gpio_buttons); - - if (gpio_request(NET2BIG_V2_GPIO_POWER_OFF, "power-off") == 0 && - gpio_direction_output(NET2BIG_V2_GPIO_POWER_OFF, 0) == 0) - pm_power_off = net2big_v2_power_off; - else - pr_err("net2big_v2: failed to configure power-off GPIO\n"); -} - -MACHINE_START(NET2BIG_V2, "LaCie 2Big Network v2") - .phys_io = KIRKWOOD_REGS_PHYS_BASE, - .io_pg_offst = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc, - .boot_params = 0x00000100, - .init_machine = net2big_v2_init, - .map_io = kirkwood_map_io, - .init_irq = kirkwood_init_irq, - .timer = &net2big_v2_timer, -MACHINE_END diff --git a/arch/arm/mach-kirkwood/net5big_v2-setup.c b/arch/arm/mach-kirkwood/net5big_v2-setup.c deleted file mode 100644 index f0617ec..0000000 --- a/arch/arm/mach-kirkwood/net5big_v2-setup.c +++ /dev/null @@ -1,355 +0,0 @@ -/* - * arch/arm/mach-kirkwood/net5big_v2-setup.c - * - * LaCie 5Big Network v2 board setup - * - * Copyright (C) 2010 Simon Guinot - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "common.h" -#include "mpp.h" - -/***************************************************************************** - * 512KB SPI Flash on Boot Device (MACRONIX MX25L4005) - ****************************************************************************/ - -static struct mtd_partition net5big_v2_flash_parts[] = { - { - .name = "u-boot", - .size = MTDPART_SIZ_FULL, - .offset = 0, - .mask_flags = MTD_WRITEABLE, /* force read-only */ - }, -}; - -static const struct flash_platform_data net5big_v2_flash = { - .type = "mx25l4005a", - .name = "spi_flash", - .parts = net5big_v2_flash_parts, - .nr_parts = ARRAY_SIZE(net5big_v2_flash_parts), -}; - -static struct spi_board_info __initdata net5big_v2_spi_slave_info[] = { - { - .modalias = "m25p80", - .platform_data = &net5big_v2_flash, - .irq = -1, - .max_speed_hz = 20000000, - .bus_num = 0, - .chip_select = 0, - }, -}; - -/***************************************************************************** - * Ethernet - ****************************************************************************/ - -static struct mv643xx_eth_platform_data net5big_v2_ge00_data = { - .phy_addr = MV643XX_ETH_PHY_ADDR(8), -}; - -static struct mv643xx_eth_platform_data net5big_v2_ge01_data = { - .phy_addr = MV643XX_ETH_PHY_ADDR(0), -}; - -/***************************************************************************** - * I2C devices - ****************************************************************************/ - -static struct at24_platform_data at24c04 = { - .byte_len = SZ_4K / 8, - .page_size = 16, -}; - -/* - * i2c addr | chip | description - * 0x50 | HT24LC04 | eeprom (512B) - */ - -static struct i2c_board_info __initdata net5big_v2_i2c_info[] = { - { - I2C_BOARD_INFO("24c04", 0x50), - .platform_data = &at24c04, - } -}; - -/***************************************************************************** - * SATA - ****************************************************************************/ - -static struct mv_sata_platform_data net5big_v2_sata_data = { - .n_ports = 2, -}; - -static int __initdata net5big_v2_gpio_hdd_power[] = { 16, 17, 41, 42, 43 }; - -static void __init net5big_v2_sata_power_init(void) -{ - int i; - int err; - - /* Power up all hard disks. */ - for (i = 0; i < ARRAY_SIZE(net5big_v2_gpio_hdd_power); i++) { - err = gpio_request(net5big_v2_gpio_hdd_power[i], NULL); - if (err == 0) { - err = gpio_direction_output( - net5big_v2_gpio_hdd_power[i], 1); - /* Free the HDD power GPIOs. This allow user-space to - * configure them via the gpiolib sysfs interface. */ - gpio_free(net5big_v2_gpio_hdd_power[i]); - } - if (err) - pr_err("net5big_v2: failed to power up HDD%d\n", i + 1); - } -} - -/***************************************************************************** - * GPIO keys - ****************************************************************************/ - -#define NET5BIG_V2_GPIO_SWITCH_POWER_ON 13 -#define NET5BIG_V2_GPIO_SWITCH_POWER_OFF 15 -#define NET5BIG_V2_GPIO_FUNC_BUTTON 34 - -#define NET5BIG_V2_SWITCH_POWER_ON 0x1 -#define NET5BIG_V2_SWITCH_POWER_OFF 0x2 - -static struct gpio_keys_button net5big_v2_buttons[] = { - [0] = { - .type = EV_SW, - .code = NET5BIG_V2_SWITCH_POWER_ON, - .gpio = NET5BIG_V2_GPIO_SWITCH_POWER_ON, - .desc = "Back power switch (on|auto)", - .active_low = 1, - }, - [1] = { - .type = EV_SW, - .code = NET5BIG_V2_SWITCH_POWER_OFF, - .gpio = NET5BIG_V2_GPIO_SWITCH_POWER_OFF, - .desc = "Back power switch (auto|off)", - .active_low = 1, - }, - [2] = { - .code = KEY_OPTION, - .gpio = NET5BIG_V2_GPIO_FUNC_BUTTON, - .desc = "Function button", - .active_low = 1, - }, -}; - -static struct gpio_keys_platform_data net5big_v2_button_data = { - .buttons = net5big_v2_buttons, - .nbuttons = ARRAY_SIZE(net5big_v2_buttons), -}; - -static struct platform_device net5big_v2_gpio_buttons = { - .name = "gpio-keys", - .id = -1, - .dev = { - .platform_data = &net5big_v2_button_data, - }, -}; - -/***************************************************************************** - * GPIO LEDs - ****************************************************************************/ - -/* - * The LEDs are controlled by a CPLD and can be configured through a GPIO - * extension bus: - * - * - address register : bit [0-2] -> GPIO [47-49] - * - data register : bit [0-2] -> GPIO [44-46] - * - enable register : GPIO 29 - * - * Address register selection: - * - * addr | register - * ---------------------------- - * 0 | front LED - * 1 | front LED brightness - * 2 | HDD LED brightness - * 3 | HDD1 LED - * 4 | HDD2 LED - * 5 | HDD3 LED - * 6 | HDD4 LED - * 7 | HDD5 LED - * - * Data register configuration: - * - * data | LED brightness - * ------------------------------------------------- - * 0 | min (off) - * - | - - * 7 | max - * - * data | front LED mode - * ------------------------------------------------- - * 0 | fix off - * 1 | fix blue on - * 2 | fix red on - * 3 | blink blue on=1 sec and blue off=1 sec - * 4 | blink red on=1 sec and red off=1 sec - * 5 | blink blue on=2.5 sec and red on=0.5 sec - * 6 | blink blue on=1 sec and red on=1 sec - * 7 | blink blue on=0.5 sec and blue off=2.5 sec - * - * data | HDD LED mode - * ------------------------------------------------- - * 0 | fix blue on - * 1 | SATA activity blink - * 2 | fix red on - * 3 | blink blue on=1 sec and blue off=1 sec - * 4 | blink red on=1 sec and red off=1 sec - * 5 | blink blue on=2.5 sec and red on=0.5 sec - * 6 | blink blue on=1 sec and red on=1 sec - * 7 | blink blue on=0.5 sec and blue off=2.5 sec - */ - -/***************************************************************************** - * Timer - ****************************************************************************/ - -static void net5big_v2_timer_init(void) -{ - kirkwood_tclk = 166666667; - orion_time_init(IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk); -} - -struct sys_timer net5big_v2_timer = { - .init = net5big_v2_timer_init, -}; - -/***************************************************************************** - * General Setup - ****************************************************************************/ - -static unsigned int net5big_v2_mpp_config[] __initdata = { - MPP0_SPI_SCn, - MPP1_SPI_MOSI, - MPP2_SPI_SCK, - MPP3_SPI_MISO, - MPP6_SYSRST_OUTn, - MPP7_GPO, /* Request power-off */ - MPP8_TW_SDA, - MPP9_TW_SCK, - MPP10_UART0_TXD, - MPP11_UART0_RXD, - MPP13_GPIO, /* Rear power switch (on|auto) */ - MPP14_GPIO, /* USB fuse alarm */ - MPP15_GPIO, /* Rear power switch (auto|off) */ - MPP16_GPIO, /* SATA HDD1 power */ - MPP17_GPIO, /* SATA HDD2 power */ - MPP20_GE1_0, - MPP21_GE1_1, - MPP22_GE1_2, - MPP23_GE1_3, - MPP24_GE1_4, - MPP25_GE1_5, - MPP26_GE1_6, - MPP27_GE1_7, - MPP28_GPIO, /* USB enable host vbus */ - MPP29_GPIO, /* CPLD extension ALE */ - MPP30_GE1_10, - MPP31_GE1_11, - MPP32_GE1_12, - MPP33_GE1_13, - MPP34_GPIO, /* Rear Push button */ - MPP35_GPIO, /* Inhibit switch power-off */ - MPP36_GPIO, /* SATA HDD1 presence */ - MPP37_GPIO, /* SATA HDD2 presence */ - MPP38_GPIO, /* SATA HDD3 presence */ - MPP39_GPIO, /* SATA HDD4 presence */ - MPP40_GPIO, /* SATA HDD5 presence */ - MPP41_GPIO, /* SATA HDD3 power */ - MPP42_GPIO, /* SATA HDD4 power */ - MPP43_GPIO, /* SATA HDD5 power */ - MPP44_GPIO, /* CPLD extension (data 0) */ - MPP45_GPIO, /* CPLD extension (data 1) */ - MPP46_GPIO, /* CPLD extension (data 2) */ - MPP47_GPIO, /* CPLD extension (addr 0) */ - MPP48_GPIO, /* CPLD extension (addr 1) */ - MPP49_GPIO, /* CPLD extension (addr 2) */ - 0 -}; - -#define NET5BIG_V2_GPIO_POWER_OFF 7 - -static void net5big_v2_power_off(void) -{ - gpio_set_value(NET5BIG_V2_GPIO_POWER_OFF, 1); -} - -static void __init net5big_v2_init(void) -{ - /* - * Basic setup. Needs to be called early. - */ - kirkwood_init(); - kirkwood_mpp_conf(net5big_v2_mpp_config); - - net5big_v2_sata_power_init(); - - kirkwood_ehci_init(); - kirkwood_ge00_init(&net5big_v2_ge00_data); - kirkwood_ge01_init(&net5big_v2_ge01_data); - kirkwood_sata_init(&net5big_v2_sata_data); - kirkwood_uart0_init(); - spi_register_board_info(net5big_v2_spi_slave_info, - ARRAY_SIZE(net5big_v2_spi_slave_info)); - kirkwood_spi_init(); - kirkwood_i2c_init(); - i2c_register_board_info(0, net5big_v2_i2c_info, - ARRAY_SIZE(net5big_v2_i2c_info)); - - platform_device_register(&net5big_v2_gpio_buttons); - - if (gpio_request(NET5BIG_V2_GPIO_POWER_OFF, "power-off") == 0 && - gpio_direction_output(NET5BIG_V2_GPIO_POWER_OFF, 0) == 0) - pm_power_off = net5big_v2_power_off; - else - pr_err("net5big_v2: failed to configure power-off GPIO\n"); -} - -MACHINE_START(NET5BIG_V2, "LaCie 5Big Network v2") - .phys_io = KIRKWOOD_REGS_PHYS_BASE, - .io_pg_offst = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc, - .boot_params = 0x00000100, - .init_machine = net5big_v2_init, - .map_io = kirkwood_map_io, - .init_irq = kirkwood_init_irq, - .timer = &net5big_v2_timer, -MACHINE_END diff --git a/arch/arm/mach-kirkwood/netxbig_v2-setup.c b/arch/arm/mach-kirkwood/netxbig_v2-setup.c new file mode 100644 index 0000000..8a2bb02 --- /dev/null +++ b/arch/arm/mach-kirkwood/netxbig_v2-setup.c @@ -0,0 +1,415 @@ +/* + * arch/arm/mach-kirkwood/netxbig_v2-setup.c + * + * LaCie 2Big and 5Big Network v2 board setup + * + * Copyright (C) 2010 Simon Guinot + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" +#include "mpp.h" + +/***************************************************************************** + * 512KB SPI Flash on Boot Device (MACRONIX MX25L4005) + ****************************************************************************/ + +static struct mtd_partition netxbig_v2_flash_parts[] = { + { + .name = "u-boot", + .size = MTDPART_SIZ_FULL, + .offset = 0, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, +}; + +static const struct flash_platform_data netxbig_v2_flash = { + .type = "mx25l4005a", + .name = "spi_flash", + .parts = netxbig_v2_flash_parts, + .nr_parts = ARRAY_SIZE(netxbig_v2_flash_parts), +}; + +static struct spi_board_info __initdata netxbig_v2_spi_slave_info[] = { + { + .modalias = "m25p80", + .platform_data = &netxbig_v2_flash, + .irq = -1, + .max_speed_hz = 20000000, + .bus_num = 0, + .chip_select = 0, + }, +}; + +/***************************************************************************** + * Ethernet + ****************************************************************************/ + +static struct mv643xx_eth_platform_data netxbig_v2_ge00_data = { + .phy_addr = MV643XX_ETH_PHY_ADDR(8), +}; + +static struct mv643xx_eth_platform_data netxbig_v2_ge01_data = { + .phy_addr = MV643XX_ETH_PHY_ADDR(0), +}; + +/***************************************************************************** + * I2C devices + ****************************************************************************/ + +static struct at24_platform_data at24c04 = { + .byte_len = SZ_4K / 8, + .page_size = 16, +}; + +/* + * i2c addr | chip | description + * 0x50 | HT24LC04 | eeprom (512B) + */ + +static struct i2c_board_info __initdata netxbig_v2_i2c_info[] = { + { + I2C_BOARD_INFO("24c04", 0x50), + .platform_data = &at24c04, + } +}; + +/***************************************************************************** + * SATA + ****************************************************************************/ + +static struct mv_sata_platform_data netxbig_v2_sata_data = { + .n_ports = 2, +}; + +static int __initdata netxbig_v2_gpio_hdd_power[] = { 16, 17, 41, 42, 43 }; + +static void __init netxbig_v2_sata_power_init(void) +{ + int i; + int err; + int hdd_nb; + + if (machine_is_net2big_v2()) + hdd_nb = 2; + else + hdd_nb = 5; + + /* Power up all hard disks. */ + for (i = 0; i < hdd_nb; i++) { + err = gpio_request(netxbig_v2_gpio_hdd_power[i], NULL); + if (err == 0) { + err = gpio_direction_output( + netxbig_v2_gpio_hdd_power[i], 1); + /* Free the HDD power GPIOs. This allow user-space to + * configure them via the gpiolib sysfs interface. */ + gpio_free(netxbig_v2_gpio_hdd_power[i]); + } + if (err) + pr_err("netxbig_v2: failed to power up HDD%d\n", i + 1); + } +} + +/***************************************************************************** + * GPIO keys + ****************************************************************************/ + +#define NETXBIG_V2_GPIO_SWITCH_POWER_ON 13 +#define NETXBIG_V2_GPIO_SWITCH_POWER_OFF 15 +#define NETXBIG_V2_GPIO_FUNC_BUTTON 34 + +#define NETXBIG_V2_SWITCH_POWER_ON 0x1 +#define NETXBIG_V2_SWITCH_POWER_OFF 0x2 + +static struct gpio_keys_button netxbig_v2_buttons[] = { + [0] = { + .type = EV_SW, + .code = NETXBIG_V2_SWITCH_POWER_ON, + .gpio = NETXBIG_V2_GPIO_SWITCH_POWER_ON, + .desc = "Back power switch (on|auto)", + .active_low = 1, + }, + [1] = { + .type = EV_SW, + .code = NETXBIG_V2_SWITCH_POWER_OFF, + .gpio = NETXBIG_V2_GPIO_SWITCH_POWER_OFF, + .desc = "Back power switch (auto|off)", + .active_low = 1, + }, + [2] = { + .code = KEY_OPTION, + .gpio = NETXBIG_V2_GPIO_FUNC_BUTTON, + .desc = "Function button", + .active_low = 1, + }, +}; + +static struct gpio_keys_platform_data netxbig_v2_button_data = { + .buttons = netxbig_v2_buttons, + .nbuttons = ARRAY_SIZE(netxbig_v2_buttons), +}; + +static struct platform_device netxbig_v2_gpio_buttons = { + .name = "gpio-keys", + .id = -1, + .dev = { + .platform_data = &netxbig_v2_button_data, + }, +}; + +/***************************************************************************** + * GPIO LEDs + ****************************************************************************/ + +/* + * The LEDs are controlled by a CPLD and can be configured through a GPIO + * extension bus: + * + * - address register : bit [0-2] -> GPIO [47-49] + * - data register : bit [0-2] -> GPIO [44-46] + * - enable register : GPIO 29 + * + * Address register selection: + * + * addr | register + * ---------------------------- + * 0 | front LED + * 1 | front LED brightness + * 2 | HDD LED brightness + * 3 | HDD1 LED + * 4 | HDD2 LED + * 5 | HDD3 LED + * 6 | HDD4 LED + * 7 | HDD5 LED + * + * Data register configuration: + * + * data | LED brightness + * ------------------------------------------------- + * 0 | min (off) + * - | - + * 7 | max + * + * data | front LED mode + * ------------------------------------------------- + * 0 | fix off + * 1 | fix blue on + * 2 | fix red on + * 3 | blink blue on=1 sec and blue off=1 sec + * 4 | blink red on=1 sec and red off=1 sec + * 5 | blink blue on=2.5 sec and red on=0.5 sec + * 6 | blink blue on=1 sec and red on=1 sec + * 7 | blink blue on=0.5 sec and blue off=2.5 sec + * + * data | HDD LED mode + * ------------------------------------------------- + * 0 | fix blue on + * 1 | SATA activity blink + * 2 | fix red on + * 3 | blink blue on=1 sec and blue off=1 sec + * 4 | blink red on=1 sec and red off=1 sec + * 5 | blink blue on=2.5 sec and red on=0.5 sec + * 6 | blink blue on=1 sec and red on=1 sec + * 7 | blink blue on=0.5 sec and blue off=2.5 sec + */ + +/***************************************************************************** + * Timer + ****************************************************************************/ + +static void netxbig_v2_timer_init(void) +{ + kirkwood_tclk = 166666667; + orion_time_init(IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk); +} + +struct sys_timer netxbig_v2_timer = { + .init = netxbig_v2_timer_init, +}; + +/***************************************************************************** + * General Setup + ****************************************************************************/ + +static unsigned int net2big_v2_mpp_config[] __initdata = { + MPP0_SPI_SCn, + MPP1_SPI_MOSI, + MPP2_SPI_SCK, + MPP3_SPI_MISO, + MPP6_SYSRST_OUTn, + MPP7_GPO, /* Request power-off */ + MPP8_TW_SDA, + MPP9_TW_SCK, + MPP10_UART0_TXD, + MPP11_UART0_RXD, + MPP13_GPIO, /* Rear power switch (on|auto) */ + MPP14_GPIO, /* USB fuse alarm */ + MPP15_GPIO, /* Rear power switch (auto|off) */ + MPP16_GPIO, /* SATA HDD1 power */ + MPP17_GPIO, /* SATA HDD2 power */ + MPP20_SATA1_ACTn, + MPP21_SATA0_ACTn, + MPP24_GPIO, /* USB mode select */ + MPP26_GPIO, /* USB device vbus */ + MPP28_GPIO, /* USB enable host vbus */ + MPP29_GPIO, /* CPLD extension ALE */ + MPP34_GPIO, /* Rear Push button */ + MPP35_GPIO, /* Inhibit switch power-off */ + MPP36_GPIO, /* SATA HDD1 presence */ + MPP37_GPIO, /* SATA HDD2 presence */ + MPP40_GPIO, /* eSATA presence */ + MPP44_GPIO, /* CPLD extension (data 0) */ + MPP45_GPIO, /* CPLD extension (data 1) */ + MPP46_GPIO, /* CPLD extension (data 2) */ + MPP47_GPIO, /* CPLD extension (addr 0) */ + MPP48_GPIO, /* CPLD extension (addr 1) */ + MPP49_GPIO, /* CPLD extension (addr 2) */ + 0 +}; + +static unsigned int net5big_v2_mpp_config[] __initdata = { + MPP0_SPI_SCn, + MPP1_SPI_MOSI, + MPP2_SPI_SCK, + MPP3_SPI_MISO, + MPP6_SYSRST_OUTn, + MPP7_GPO, /* Request power-off */ + MPP8_TW_SDA, + MPP9_TW_SCK, + MPP10_UART0_TXD, + MPP11_UART0_RXD, + MPP13_GPIO, /* Rear power switch (on|auto) */ + MPP14_GPIO, /* USB fuse alarm */ + MPP15_GPIO, /* Rear power switch (auto|off) */ + MPP16_GPIO, /* SATA HDD1 power */ + MPP17_GPIO, /* SATA HDD2 power */ + MPP20_GE1_0, + MPP21_GE1_1, + MPP22_GE1_2, + MPP23_GE1_3, + MPP24_GE1_4, + MPP25_GE1_5, + MPP26_GE1_6, + MPP27_GE1_7, + MPP28_GPIO, /* USB enable host vbus */ + MPP29_GPIO, /* CPLD extension ALE */ + MPP30_GE1_10, + MPP31_GE1_11, + MPP32_GE1_12, + MPP33_GE1_13, + MPP34_GPIO, /* Rear Push button */ + MPP35_GPIO, /* Inhibit switch power-off */ + MPP36_GPIO, /* SATA HDD1 presence */ + MPP37_GPIO, /* SATA HDD2 presence */ + MPP38_GPIO, /* SATA HDD3 presence */ + MPP39_GPIO, /* SATA HDD4 presence */ + MPP40_GPIO, /* SATA HDD5 presence */ + MPP41_GPIO, /* SATA HDD3 power */ + MPP42_GPIO, /* SATA HDD4 power */ + MPP43_GPIO, /* SATA HDD5 power */ + MPP44_GPIO, /* CPLD extension (data 0) */ + MPP45_GPIO, /* CPLD extension (data 1) */ + MPP46_GPIO, /* CPLD extension (data 2) */ + MPP47_GPIO, /* CPLD extension (addr 0) */ + MPP48_GPIO, /* CPLD extension (addr 1) */ + MPP49_GPIO, /* CPLD extension (addr 2) */ + 0 +}; + +#define NETXBIG_V2_GPIO_POWER_OFF 7 + +static void netxbig_v2_power_off(void) +{ + gpio_set_value(NETXBIG_V2_GPIO_POWER_OFF, 1); +} + +static void __init netxbig_v2_init(void) +{ + /* + * Basic setup. Needs to be called early. + */ + kirkwood_init(); + if (machine_is_net2big_v2()) + kirkwood_mpp_conf(net2big_v2_mpp_config); + else + kirkwood_mpp_conf(net5big_v2_mpp_config); + + netxbig_v2_sata_power_init(); + + kirkwood_ehci_init(); + kirkwood_ge00_init(&netxbig_v2_ge00_data); + if (machine_is_net5big_v2()) + kirkwood_ge01_init(&netxbig_v2_ge01_data); + kirkwood_sata_init(&netxbig_v2_sata_data); + kirkwood_uart0_init(); + spi_register_board_info(netxbig_v2_spi_slave_info, + ARRAY_SIZE(netxbig_v2_spi_slave_info)); + kirkwood_spi_init(); + kirkwood_i2c_init(); + i2c_register_board_info(0, netxbig_v2_i2c_info, + ARRAY_SIZE(netxbig_v2_i2c_info)); + + platform_device_register(&netxbig_v2_gpio_buttons); + + if (gpio_request(NETXBIG_V2_GPIO_POWER_OFF, "power-off") == 0 && + gpio_direction_output(NETXBIG_V2_GPIO_POWER_OFF, 0) == 0) + pm_power_off = netxbig_v2_power_off; + else + pr_err("netxbig_v2: failed to configure power-off GPIO\n"); +} + +#ifdef CONFIG_MACH_NET2BIG_V2 +MACHINE_START(NET2BIG_V2, "LaCie 2Big Network v2") + .phys_io = KIRKWOOD_REGS_PHYS_BASE, + .io_pg_offst = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0x00000100, + .init_machine = netxbig_v2_init, + .map_io = kirkwood_map_io, + .init_irq = kirkwood_init_irq, + .timer = &netxbig_v2_timer, +MACHINE_END +#endif + +#ifdef CONFIG_MACH_NET5BIG_V2 +MACHINE_START(NET5BIG_V2, "LaCie 5Big Network v2") + .phys_io = KIRKWOOD_REGS_PHYS_BASE, + .io_pg_offst = ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0x00000100, + .init_machine = netxbig_v2_init, + .map_io = kirkwood_map_io, + .init_irq = kirkwood_init_irq, + .timer = &netxbig_v2_timer, +MACHINE_END +#endif -- cgit v0.10.2 From 81c4a8a6733ad2ff49c0e077b51403367601b3e7 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Thu, 22 Apr 2010 19:14:49 +0200 Subject: oprofile: update file list in MAINTAINERS file File list now catches: $ xargs | eval ls -d $(cat) | sort -u arch/*/include/asm/oprofile*.h arch/*/oprofile/ drivers/oprofile/ include/linux/oprofile.h arch/alpha/oprofile/ arch/arm/oprofile/ arch/avr32/oprofile/ arch/blackfin/oprofile/ arch/ia64/oprofile/ arch/m32r/oprofile/ arch/microblaze/oprofile/ arch/mips/oprofile/ arch/mn10300/oprofile/ arch/parisc/oprofile/ arch/powerpc/include/asm/oprofile_impl.h arch/powerpc/oprofile/ arch/s390/oprofile/ arch/sh/oprofile/ arch/sparc/oprofile/ arch/x86/oprofile/ drivers/oprofile/ include/linux/oprofile.h Signed-off-by: Robert Richter diff --git a/MAINTAINERS b/MAINTAINERS index a0e3c3a..31e8586 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4165,6 +4165,7 @@ OPROFILE M: Robert Richter L: oprofile-list@lists.sf.net S: Maintained +F: arch/*/include/asm/oprofile*.h F: arch/*/oprofile/ F: drivers/oprofile/ F: include/linux/oprofile.h -- cgit v0.10.2 From d88d95eb1c2a72b6126a550debe0883ff723a948 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Sat, 24 Apr 2010 09:56:53 +0200 Subject: x86, k8: Fix build error when K8_NB is disabled K8_NB depends on PCI and when the last is disabled (allnoconfig) we fail at the final linking stage due to missing exported num_k8_northbridges. Add a header stub for that. Signed-off-by: Borislav Petkov LKML-Reference: <20100503183036.GJ26107@aftab> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/include/asm/k8.h b/arch/x86/include/asm/k8.h index f70e600..af00bd1 100644 --- a/arch/x86/include/asm/k8.h +++ b/arch/x86/include/asm/k8.h @@ -16,11 +16,16 @@ extern int k8_numa_init(unsigned long start_pfn, unsigned long end_pfn); extern int k8_scan_nodes(void); #ifdef CONFIG_K8_NB +extern int num_k8_northbridges; + static inline struct pci_dev *node_to_k8_nb_misc(int node) { return (node < num_k8_northbridges) ? k8_northbridges[node] : NULL; } + #else +#define num_k8_northbridges 0 + static inline struct pci_dev *node_to_k8_nb_misc(int node) { return NULL; -- cgit v0.10.2 From 097c1bd5673edaf2a162724636858b71f658fdd2 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 3 May 2010 15:49:31 -0700 Subject: x86, cpu: Make APERF/MPERF a normal table-driven flag APERF/MPERF can be handled via the table like all the other scattered CPU flags. Signed-off-by: H. Peter Anvin Cc: Thomas Renninger Cc: Borislav Petkov LKML-Reference: <1270065406-1814-4-git-send-email-bp@amd64.org> diff --git a/arch/x86/kernel/cpu/addon_cpuid_features.c b/arch/x86/kernel/cpu/addon_cpuid_features.c index fd1fc19..10fa568 100644 --- a/arch/x86/kernel/cpu/addon_cpuid_features.c +++ b/arch/x86/kernel/cpu/addon_cpuid_features.c @@ -30,13 +30,14 @@ void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c) const struct cpuid_bit *cb; static const struct cpuid_bit __cpuinitconst cpuid_bits[] = { - { X86_FEATURE_IDA, CR_EAX, 1, 0x00000006 }, - { X86_FEATURE_ARAT, CR_EAX, 2, 0x00000006 }, - { X86_FEATURE_CPB, CR_EDX, 9, 0x80000007 }, - { X86_FEATURE_NPT, CR_EDX, 0, 0x8000000a }, - { X86_FEATURE_LBRV, CR_EDX, 1, 0x8000000a }, - { X86_FEATURE_SVML, CR_EDX, 2, 0x8000000a }, - { X86_FEATURE_NRIPS, CR_EDX, 3, 0x8000000a }, + { X86_FEATURE_IDA, CR_EAX, 1, 0x00000006 }, + { X86_FEATURE_ARAT, CR_EAX, 2, 0x00000006 }, + { X86_FEATURE_APERFMPERF, CR_ECX, 0, 0x00000006 }, + { X86_FEATURE_CPB, CR_EDX, 9, 0x80000007 }, + { X86_FEATURE_NPT, CR_EDX, 0, 0x8000000a }, + { X86_FEATURE_LBRV, CR_EDX, 1, 0x8000000a }, + { X86_FEATURE_SVML, CR_EDX, 2, 0x8000000a }, + { X86_FEATURE_NRIPS, CR_EDX, 3, 0x8000000a }, { 0, 0, 0, 0 } }; @@ -54,14 +55,6 @@ void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c) if (regs[cb->reg] & (1 << cb->bit)) set_cpu_cap(c, cb->feature); } - - /* - * common AMD/Intel features - */ - if (c->cpuid_level >= 6) { - if (cpuid_ecx(6) & 0x1) - set_cpu_cap(c, X86_FEATURE_APERFMPERF); - } } /* leaf 0xb SMT level */ -- cgit v0.10.2 From ba697f40dbb704956a4cf67a7845b538015a01ea Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Tue, 4 May 2010 04:47:25 +0200 Subject: lockdep: Provide off case for redundant_hardirqs_on increment We forgot to provide a !CONFIG_DEBUG_LOCKDEP case for the redundant_hardirqs_on stat handling. Manage that in the headers with a new __debug_atomic_inc() helper. Fixes: kernel/lockdep.c:2306: error: 'lockdep_stats' undeclared (first use in this function) kernel/lockdep.c:2306: error: (Each undeclared identifier is reported only once kernel/lockdep.c:2306: error: for each function it appears in.) Reported-by: Ingo Molnar Signed-off-by: Frederic Weisbecker Cc: Peter Zijlstra diff --git a/kernel/lockdep.c b/kernel/lockdep.c index 1b58a1b..9cf7985 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c @@ -2303,7 +2303,7 @@ void trace_hardirqs_on_caller(unsigned long ip) * so this is racy by nature but loosing one hit * in a stat is not a big deal. */ - this_cpu_inc(lockdep_stats.redundant_hardirqs_on); + __debug_atomic_inc(redundant_hardirqs_on); return; } /* we'll do an OFF -> ON transition: */ diff --git a/kernel/lockdep_internals.h b/kernel/lockdep_internals.h index 2b17476..7de27a8 100644 --- a/kernel/lockdep_internals.h +++ b/kernel/lockdep_internals.h @@ -139,6 +139,9 @@ struct lockdep_stats { DECLARE_PER_CPU(struct lockdep_stats, lockdep_stats); +#define __debug_atomic_inc(ptr) \ + this_cpu_inc(lockdep_stats.ptr); + #define debug_atomic_inc(ptr) { \ WARN_ON_ONCE(!irqs_disabled()); \ this_cpu_inc(lockdep_stats.ptr); \ @@ -160,6 +163,7 @@ DECLARE_PER_CPU(struct lockdep_stats, lockdep_stats); __total; \ }) #else +# define __debug_atomic_inc(ptr) do { } while (0) # define debug_atomic_inc(ptr) do { } while (0) # define debug_atomic_dec(ptr) do { } while (0) # define debug_atomic_read(ptr) 0 -- cgit v0.10.2 From fa9a97dec611c5356301645d576b523ce3919eba Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Tue, 4 May 2010 04:52:48 +0200 Subject: lockdep: Actually _dec_ in debug_atomic_dec Fix a silly copy-paste mistake that was making debug_atomic_dec use this_cpu_inc instead of this_cpu_dec. Signed-off-by: Frederic Weisbecker Cc: Peter Zijlstra diff --git a/kernel/lockdep_internals.h b/kernel/lockdep_internals.h index 7de27a8..8d929c7 100644 --- a/kernel/lockdep_internals.h +++ b/kernel/lockdep_internals.h @@ -149,7 +149,7 @@ DECLARE_PER_CPU(struct lockdep_stats, lockdep_stats); #define debug_atomic_dec(ptr) { \ WARN_ON_ONCE(!irqs_disabled()); \ - this_cpu_inc(lockdep_stats.ptr); \ + this_cpu_dec(lockdep_stats.ptr); \ } #define debug_atomic_read(ptr) ({ \ -- cgit v0.10.2 From 54d47a2be5e7f928fb77b2f5a0761f6bd3c9dbff Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Tue, 4 May 2010 04:54:47 +0200 Subject: lockdep: No need to disable preemption in debug atomic ops No need to disable preemption in the debug_atomic_* ops, as we ensure interrupts are disabled already. So let's use the __this_cpu_ops() rather than this_cpu_ops() that enclose the ops in a preempt disabled section. Signed-off-by: Frederic Weisbecker Cc: Peter Zijlstra diff --git a/kernel/lockdep_internals.h b/kernel/lockdep_internals.h index 8d929c7..4f560cf 100644 --- a/kernel/lockdep_internals.h +++ b/kernel/lockdep_internals.h @@ -144,12 +144,12 @@ DECLARE_PER_CPU(struct lockdep_stats, lockdep_stats); #define debug_atomic_inc(ptr) { \ WARN_ON_ONCE(!irqs_disabled()); \ - this_cpu_inc(lockdep_stats.ptr); \ + __this_cpu_inc(lockdep_stats.ptr); \ } #define debug_atomic_dec(ptr) { \ WARN_ON_ONCE(!irqs_disabled()); \ - this_cpu_dec(lockdep_stats.ptr); \ + __this_cpu_dec(lockdep_stats.ptr); \ } #define debug_atomic_read(ptr) ({ \ -- cgit v0.10.2 From b8b14c66765ccba884c5c4570bf8be361d211d95 Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Mon, 3 May 2010 07:36:22 -0500 Subject: powerpc/swiotlb: Fix off by one in determining boundary of which ops to use When we compare the devices DMA mask to the amount of memory we need to make sure we treat the DMA mask as an address boundary. For example if the DMA_MASK(32) and we have 4G of memory we'd incorrectly set the dma ops to swiotlb. We need to add one to the dma mask when we convert it. Signed-off-by: Kumar Gala diff --git a/arch/powerpc/kernel/dma-swiotlb.c b/arch/powerpc/kernel/dma-swiotlb.c index 59c9285..4ff4da2c 100644 --- a/arch/powerpc/kernel/dma-swiotlb.c +++ b/arch/powerpc/kernel/dma-swiotlb.c @@ -1,7 +1,8 @@ /* * Contains routines needed to support swiotlb for ppc. * - * Copyright (C) 2009 Becky Bruce, Freescale Semiconductor + * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. + * Author: Becky Bruce * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -70,7 +71,7 @@ static int ppc_swiotlb_bus_notify(struct notifier_block *nb, sd->max_direct_dma_addr = 0; /* May need to bounce if the device can't address all of DRAM */ - if (dma_get_mask(dev) < lmb_end_of_DRAM()) + if ((dma_get_mask(dev) + 1) < lmb_end_of_DRAM()) set_dma_ops(dev, &swiotlb_dma_ops); return NOTIFY_DONE; -- cgit v0.10.2 From 777d0411cd1e384115985dac5ccd42031e3eee2b Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Mon, 3 May 2010 15:39:45 +0200 Subject: hw_breakpoints: Fix percpu build failure Fix this build error: kernel/hw_breakpoint.c:58:1: error: pasting "__pcpu_scope_" and "*" does not give a valid preprocessing token It happens if CONFIG_DEBUG_FORCE_WEAK_PER_CPU, because we concatenate someting with the name and we have the "*" in the name. Cc: Frederic Weisbecker Cc: Will Deacon Cc: Paul Mundt Cc: Mahesh Salgaonkar Cc: K. Prasad Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Jason Wessel LKML-Reference: <20100503133942.GA5497@nowhere> Signed-off-by: Ingo Molnar diff --git a/kernel/hw_breakpoint.c b/kernel/hw_breakpoint.c index 684b710..7a56b22 100644 --- a/kernel/hw_breakpoint.c +++ b/kernel/hw_breakpoint.c @@ -55,7 +55,7 @@ static DEFINE_PER_CPU(unsigned int, nr_cpu_bp_pinned[TYPE_MAX]); /* Number of pinned task breakpoints in a cpu */ -static DEFINE_PER_CPU(unsigned int, *nr_task_bp_pinned[TYPE_MAX]); +static DEFINE_PER_CPU(unsigned int *, nr_task_bp_pinned[TYPE_MAX]); /* Number of non-pinned cpu/task breakpoints in a cpu */ static DEFINE_PER_CPU(unsigned int, nr_bp_flexible[TYPE_MAX]); -- cgit v0.10.2 From 8f5a2dd83a1f8e89fdc17eb0f2f07c2e713e635a Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 23 Mar 2010 19:09:51 +0100 Subject: oprofile/x86: rework error handler in nmi_setup() This patch improves the error handler in nmi_setup(). Most parts of the code are moved to allocate_msrs(). In case of an error allocate_msrs() also frees already allocated memory. nmi_setup() becomes easier and better extendable. Signed-off-by: Robert Richter diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index 2c505ee..c0c21f2 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -295,6 +295,7 @@ static void free_msrs(void) kfree(per_cpu(cpu_msrs, i).controls); per_cpu(cpu_msrs, i).controls = NULL; } + nmi_shutdown_mux(); } static int allocate_msrs(void) @@ -307,14 +308,21 @@ static int allocate_msrs(void) per_cpu(cpu_msrs, i).counters = kzalloc(counters_size, GFP_KERNEL); if (!per_cpu(cpu_msrs, i).counters) - return 0; + goto fail; per_cpu(cpu_msrs, i).controls = kzalloc(controls_size, GFP_KERNEL); if (!per_cpu(cpu_msrs, i).controls) - return 0; + goto fail; } + if (!nmi_setup_mux()) + goto fail; + return 1; + +fail: + free_msrs(); + return 0; } static void nmi_cpu_setup(void *dummy) @@ -342,17 +350,7 @@ static int nmi_setup(void) int cpu; if (!allocate_msrs()) - err = -ENOMEM; - else if (!nmi_setup_mux()) - err = -ENOMEM; - else - err = register_die_notifier(&profile_exceptions_nb); - - if (err) { - free_msrs(); - nmi_shutdown_mux(); - return err; - } + return -ENOMEM; /* We need to serialize save and setup for HT because the subset * of msrs are distinct for save and setup operations @@ -374,9 +372,17 @@ static int nmi_setup(void) mux_clone(cpu); } + + err = register_die_notifier(&profile_exceptions_nb); + if (err) + goto fail; + on_each_cpu(nmi_cpu_setup, NULL, 1); nmi_enabled = 1; return 0; +fail: + free_msrs(); + return err; } static void nmi_cpu_restore_registers(struct op_msrs *msrs) @@ -421,7 +427,6 @@ static void nmi_shutdown(void) nmi_enabled = 0; on_each_cpu(nmi_cpu_shutdown, NULL, 1); unregister_die_notifier(&profile_exceptions_nb); - nmi_shutdown_mux(); msrs = &get_cpu_var(cpu_msrs); model->shutdown(msrs); free_msrs(); -- cgit v0.10.2 From d0e4120fda6f87eead438eed4d49032e12060e58 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 23 Mar 2010 19:33:21 +0100 Subject: oprofile/x86: reserve counter msrs pairwise For AMD's and Intel's P6 generic performance counters have pairwise counter and control msrs. This patch changes the counter reservation in a way that both msrs must be registered. It joins some counter loops and also removes the unnecessary NUM_CONTROLS macro in the AMD implementation. Signed-off-by: Robert Richter diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c index 090cbbe..2e2bc90 100644 --- a/arch/x86/oprofile/op_model_amd.c +++ b/arch/x86/oprofile/op_model_amd.c @@ -30,13 +30,10 @@ #include "op_counter.h" #define NUM_COUNTERS 4 -#define NUM_CONTROLS 4 #ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX #define NUM_VIRT_COUNTERS 32 -#define NUM_VIRT_CONTROLS 32 #else #define NUM_VIRT_COUNTERS NUM_COUNTERS -#define NUM_VIRT_CONTROLS NUM_CONTROLS #endif #define OP_EVENT_MASK 0x0FFF @@ -134,13 +131,15 @@ static void op_amd_fill_in_addresses(struct op_msrs * const msrs) int i; for (i = 0; i < NUM_COUNTERS; i++) { - if (reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i)) - msrs->counters[i].addr = MSR_K7_PERFCTR0 + i; - } - - for (i = 0; i < NUM_CONTROLS; i++) { - if (reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i)) - msrs->controls[i].addr = MSR_K7_EVNTSEL0 + i; + if (!reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i)) + continue; + if (!reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i)) { + release_perfctr_nmi(MSR_K7_PERFCTR0 + i); + continue; + } + /* both registers must be reserved */ + msrs->counters[i].addr = MSR_K7_PERFCTR0 + i; + msrs->controls[i].addr = MSR_K7_EVNTSEL0 + i; } } @@ -160,7 +159,7 @@ static void op_amd_setup_ctrs(struct op_x86_model_spec const *model, } /* clear all counters */ - for (i = 0; i < NUM_CONTROLS; ++i) { + for (i = 0; i < NUM_COUNTERS; ++i) { if (unlikely(!msrs->controls[i].addr)) { if (counter_config[i].enabled && !smp_processor_id()) /* @@ -175,12 +174,10 @@ static void op_amd_setup_ctrs(struct op_x86_model_spec const *model, op_x86_warn_in_use(i); val &= model->reserved; wrmsrl(msrs->controls[i].addr, val); - } - - /* avoid a false detection of ctr overflows in NMI handler */ - for (i = 0; i < NUM_COUNTERS; ++i) { - if (unlikely(!msrs->counters[i].addr)) - continue; + /* + * avoid a false detection of ctr overflows in NMI + * handler + */ wrmsrl(msrs->counters[i].addr, -1LL); } @@ -430,12 +427,10 @@ static void op_amd_shutdown(struct op_msrs const * const msrs) int i; for (i = 0; i < NUM_COUNTERS; ++i) { - if (msrs->counters[i].addr) - release_perfctr_nmi(MSR_K7_PERFCTR0 + i); - } - for (i = 0; i < NUM_CONTROLS; ++i) { - if (msrs->controls[i].addr) - release_evntsel_nmi(MSR_K7_EVNTSEL0 + i); + if (!msrs->counters[i].addr) + continue; + release_perfctr_nmi(MSR_K7_PERFCTR0 + i); + release_evntsel_nmi(MSR_K7_EVNTSEL0 + i); } } @@ -583,7 +578,7 @@ static void op_amd_exit(void) struct op_x86_model_spec op_amd_spec = { .num_counters = NUM_COUNTERS, - .num_controls = NUM_CONTROLS, + .num_controls = NUM_COUNTERS, .num_virt_counters = NUM_VIRT_COUNTERS, .reserved = MSR_AMD_EVENTSEL_RESERVED, .event_mask = OP_EVENT_MASK, diff --git a/arch/x86/oprofile/op_model_ppro.c b/arch/x86/oprofile/op_model_ppro.c index 2bf90fa..f8e268e 100644 --- a/arch/x86/oprofile/op_model_ppro.c +++ b/arch/x86/oprofile/op_model_ppro.c @@ -35,13 +35,15 @@ static void ppro_fill_in_addresses(struct op_msrs * const msrs) int i; for (i = 0; i < num_counters; i++) { - if (reserve_perfctr_nmi(MSR_P6_PERFCTR0 + i)) - msrs->counters[i].addr = MSR_P6_PERFCTR0 + i; - } - - for (i = 0; i < num_counters; i++) { - if (reserve_evntsel_nmi(MSR_P6_EVNTSEL0 + i)) - msrs->controls[i].addr = MSR_P6_EVNTSEL0 + i; + if (!reserve_perfctr_nmi(MSR_P6_PERFCTR0 + i)) + continue; + if (!reserve_evntsel_nmi(MSR_P6_EVNTSEL0 + i)) { + release_perfctr_nmi(MSR_P6_PERFCTR0 + i); + continue; + } + /* both registers must be reserved */ + msrs->counters[i].addr = MSR_P6_PERFCTR0 + i; + msrs->controls[i].addr = MSR_P6_EVNTSEL0 + i; } } @@ -92,12 +94,10 @@ static void ppro_setup_ctrs(struct op_x86_model_spec const *model, op_x86_warn_in_use(i); val &= model->reserved; wrmsrl(msrs->controls[i].addr, val); - } - - /* avoid a false detection of ctr overflows in NMI handler */ - for (i = 0; i < num_counters; ++i) { - if (unlikely(!msrs->counters[i].addr)) - continue; + /* + * avoid a false detection of ctr overflows in NMI * + * handler + */ wrmsrl(msrs->counters[i].addr, -1LL); } @@ -194,12 +194,10 @@ static void ppro_shutdown(struct op_msrs const * const msrs) int i; for (i = 0; i < num_counters; ++i) { - if (msrs->counters[i].addr) - release_perfctr_nmi(MSR_P6_PERFCTR0 + i); - } - for (i = 0; i < num_counters; ++i) { - if (msrs->controls[i].addr) - release_evntsel_nmi(MSR_P6_EVNTSEL0 + i); + if (!msrs->counters[i].addr) + continue; + release_perfctr_nmi(MSR_P6_PERFCTR0 + i); + release_evntsel_nmi(MSR_P6_EVNTSEL0 + i); } if (reset_value) { kfree(reset_value); -- cgit v0.10.2 From 83300ce0df6b72e156b386457aa0f0902b8c0a98 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 23 Mar 2010 20:01:54 +0100 Subject: oprofile/x86: moving shutdown functions Moving some code in preparation of the next patch. Signed-off-by: Robert Richter diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c index 2e2bc90..7e5886d 100644 --- a/arch/x86/oprofile/op_model_amd.c +++ b/arch/x86/oprofile/op_model_amd.c @@ -126,6 +126,18 @@ static void op_mux_switch_ctrl(struct op_x86_model_spec const *model, /* functions for op_amd_spec */ +static void op_amd_shutdown(struct op_msrs const * const msrs) +{ + int i; + + for (i = 0; i < NUM_COUNTERS; ++i) { + if (!msrs->counters[i].addr) + continue; + release_perfctr_nmi(MSR_K7_PERFCTR0 + i); + release_evntsel_nmi(MSR_K7_EVNTSEL0 + i); + } +} + static void op_amd_fill_in_addresses(struct op_msrs * const msrs) { int i; @@ -422,18 +434,6 @@ static void op_amd_stop(struct op_msrs const * const msrs) op_amd_stop_ibs(); } -static void op_amd_shutdown(struct op_msrs const * const msrs) -{ - int i; - - for (i = 0; i < NUM_COUNTERS; ++i) { - if (!msrs->counters[i].addr) - continue; - release_perfctr_nmi(MSR_K7_PERFCTR0 + i); - release_evntsel_nmi(MSR_K7_EVNTSEL0 + i); - } -} - static u8 ibs_eilvt_off; static inline void apic_init_ibs_nmi_per_cpu(void *arg) diff --git a/arch/x86/oprofile/op_model_p4.c b/arch/x86/oprofile/op_model_p4.c index e6a160a..7cc80df 100644 --- a/arch/x86/oprofile/op_model_p4.c +++ b/arch/x86/oprofile/op_model_p4.c @@ -385,6 +385,24 @@ static unsigned int get_stagger(void) static unsigned long reset_value[NUM_COUNTERS_NON_HT]; +static void p4_shutdown(struct op_msrs const * const msrs) +{ + int i; + + for (i = 0; i < num_counters; ++i) { + if (msrs->counters[i].addr) + release_perfctr_nmi(msrs->counters[i].addr); + } + /* + * some of the control registers are specially reserved in + * conjunction with the counter registers (hence the starting offset). + * This saves a few bits. + */ + for (i = num_counters; i < num_controls; ++i) { + if (msrs->controls[i].addr) + release_evntsel_nmi(msrs->controls[i].addr); + } +} static void p4_fill_in_addresses(struct op_msrs * const msrs) { @@ -668,26 +686,6 @@ static void p4_stop(struct op_msrs const * const msrs) } } -static void p4_shutdown(struct op_msrs const * const msrs) -{ - int i; - - for (i = 0; i < num_counters; ++i) { - if (msrs->counters[i].addr) - release_perfctr_nmi(msrs->counters[i].addr); - } - /* - * some of the control registers are specially reserved in - * conjunction with the counter registers (hence the starting offset). - * This saves a few bits. - */ - for (i = num_counters; i < num_controls; ++i) { - if (msrs->controls[i].addr) - release_evntsel_nmi(msrs->controls[i].addr); - } -} - - #ifdef CONFIG_SMP struct op_x86_model_spec op_p4_ht2_spec = { .num_counters = NUM_COUNTERS_HT2, diff --git a/arch/x86/oprofile/op_model_ppro.c b/arch/x86/oprofile/op_model_ppro.c index f8e268e..b07d25a 100644 --- a/arch/x86/oprofile/op_model_ppro.c +++ b/arch/x86/oprofile/op_model_ppro.c @@ -30,6 +30,22 @@ static int counter_width = 32; static u64 *reset_value; +static void ppro_shutdown(struct op_msrs const * const msrs) +{ + int i; + + for (i = 0; i < num_counters; ++i) { + if (!msrs->counters[i].addr) + continue; + release_perfctr_nmi(MSR_P6_PERFCTR0 + i); + release_evntsel_nmi(MSR_P6_EVNTSEL0 + i); + } + if (reset_value) { + kfree(reset_value); + reset_value = NULL; + } +} + static void ppro_fill_in_addresses(struct op_msrs * const msrs) { int i; @@ -189,23 +205,6 @@ static void ppro_stop(struct op_msrs const * const msrs) } } -static void ppro_shutdown(struct op_msrs const * const msrs) -{ - int i; - - for (i = 0; i < num_counters; ++i) { - if (!msrs->counters[i].addr) - continue; - release_perfctr_nmi(MSR_P6_PERFCTR0 + i); - release_evntsel_nmi(MSR_P6_EVNTSEL0 + i); - } - if (reset_value) { - kfree(reset_value); - reset_value = NULL; - } -} - - struct op_x86_model_spec op_ppro_spec = { .num_counters = 2, .num_controls = 2, -- cgit v0.10.2 From 8617f98c001d00b176422d707e6a67b88bcd7e0d Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Fri, 26 Feb 2010 17:20:55 +0100 Subject: oprofile/x86: return -EBUSY if counters are already reserved In case a counter is already reserved by the watchdog or perf_event subsystem, oprofile ignored this counters silently. This case is handled now and oprofile_setup() now reports an error. Signed-off-by: Robert Richter diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index c0c21f2..9f001d9 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -357,7 +357,10 @@ static int nmi_setup(void) */ /* Assume saved/restored counters are the same on all CPUs */ - model->fill_in_addresses(&per_cpu(cpu_msrs, 0)); + err = model->fill_in_addresses(&per_cpu(cpu_msrs, 0)); + if (err) + goto fail; + for_each_possible_cpu(cpu) { if (!cpu) continue; diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c index 7e5886d..536d0b0 100644 --- a/arch/x86/oprofile/op_model_amd.c +++ b/arch/x86/oprofile/op_model_amd.c @@ -138,21 +138,30 @@ static void op_amd_shutdown(struct op_msrs const * const msrs) } } -static void op_amd_fill_in_addresses(struct op_msrs * const msrs) +static int op_amd_fill_in_addresses(struct op_msrs * const msrs) { int i; for (i = 0; i < NUM_COUNTERS; i++) { if (!reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i)) - continue; + goto fail; if (!reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i)) { release_perfctr_nmi(MSR_K7_PERFCTR0 + i); - continue; + goto fail; } /* both registers must be reserved */ msrs->counters[i].addr = MSR_K7_PERFCTR0 + i; msrs->controls[i].addr = MSR_K7_EVNTSEL0 + i; + continue; + fail: + if (!counter_config[i].enabled) + continue; + op_x86_warn_reserved(i); + op_amd_shutdown(msrs); + return -EBUSY; } + + return 0; } static void op_amd_setup_ctrs(struct op_x86_model_spec const *model, @@ -172,15 +181,8 @@ static void op_amd_setup_ctrs(struct op_x86_model_spec const *model, /* clear all counters */ for (i = 0; i < NUM_COUNTERS; ++i) { - if (unlikely(!msrs->controls[i].addr)) { - if (counter_config[i].enabled && !smp_processor_id()) - /* - * counter is reserved, this is on all - * cpus, so report only for cpu #0 - */ - op_x86_warn_reserved(i); + if (!msrs->controls[i].addr) continue; - } rdmsrl(msrs->controls[i].addr, val); if (val & ARCH_PERFMON_EVENTSEL_ENABLE) op_x86_warn_in_use(i); diff --git a/arch/x86/oprofile/op_model_p4.c b/arch/x86/oprofile/op_model_p4.c index 7cc80df..182558d 100644 --- a/arch/x86/oprofile/op_model_p4.c +++ b/arch/x86/oprofile/op_model_p4.c @@ -404,7 +404,7 @@ static void p4_shutdown(struct op_msrs const * const msrs) } } -static void p4_fill_in_addresses(struct op_msrs * const msrs) +static int p4_fill_in_addresses(struct op_msrs * const msrs) { unsigned int i; unsigned int addr, cccraddr, stag; @@ -486,6 +486,18 @@ static void p4_fill_in_addresses(struct op_msrs * const msrs) msrs->controls[i++].addr = MSR_P4_CRU_ESCR5; } } + + for (i = 0; i < num_counters; ++i) { + if (!counter_config[i].enabled) + continue; + if (msrs->controls[i].addr) + continue; + op_x86_warn_reserved(i); + p4_shutdown(msrs); + return -EBUSY; + } + + return 0; } diff --git a/arch/x86/oprofile/op_model_ppro.c b/arch/x86/oprofile/op_model_ppro.c index b07d25a..1fd17cf 100644 --- a/arch/x86/oprofile/op_model_ppro.c +++ b/arch/x86/oprofile/op_model_ppro.c @@ -46,21 +46,30 @@ static void ppro_shutdown(struct op_msrs const * const msrs) } } -static void ppro_fill_in_addresses(struct op_msrs * const msrs) +static int ppro_fill_in_addresses(struct op_msrs * const msrs) { int i; for (i = 0; i < num_counters; i++) { if (!reserve_perfctr_nmi(MSR_P6_PERFCTR0 + i)) - continue; + goto fail; if (!reserve_evntsel_nmi(MSR_P6_EVNTSEL0 + i)) { release_perfctr_nmi(MSR_P6_PERFCTR0 + i); - continue; + goto fail; } /* both registers must be reserved */ msrs->counters[i].addr = MSR_P6_PERFCTR0 + i; msrs->controls[i].addr = MSR_P6_EVNTSEL0 + i; + continue; + fail: + if (!counter_config[i].enabled) + continue; + op_x86_warn_reserved(i); + ppro_shutdown(msrs); + return -EBUSY; } + + return 0; } @@ -96,15 +105,8 @@ static void ppro_setup_ctrs(struct op_x86_model_spec const *model, /* clear all counters */ for (i = 0; i < num_counters; ++i) { - if (unlikely(!msrs->controls[i].addr)) { - if (counter_config[i].enabled && !smp_processor_id()) - /* - * counter is reserved, this is on all - * cpus, so report only for cpu #0 - */ - op_x86_warn_reserved(i); + if (!msrs->controls[i].addr) continue; - } rdmsrl(msrs->controls[i].addr, val); if (val & ARCH_PERFMON_EVENTSEL_ENABLE) op_x86_warn_in_use(i); diff --git a/arch/x86/oprofile/op_x86_model.h b/arch/x86/oprofile/op_x86_model.h index ff82a75..5514013 100644 --- a/arch/x86/oprofile/op_x86_model.h +++ b/arch/x86/oprofile/op_x86_model.h @@ -41,7 +41,7 @@ struct op_x86_model_spec { u16 event_mask; int (*init)(struct oprofile_operations *ops); void (*exit)(void); - void (*fill_in_addresses)(struct op_msrs * const msrs); + int (*fill_in_addresses)(struct op_msrs * const msrs); void (*setup_ctrs)(struct op_x86_model_spec const *model, struct op_msrs const * const msrs); int (*check_ctrs)(struct pt_regs * const regs, -- cgit v0.10.2 From da759fe5be24ec3b236a76c007b460cf6caf2009 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Fri, 26 Feb 2010 10:54:56 +0100 Subject: oprofile/x86: move IBS code Moving code to make future changes easier. This groups all IBS code together. Signed-off-by: Robert Richter diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c index 536d0b0..e159254 100644 --- a/arch/x86/oprofile/op_model_amd.c +++ b/arch/x86/oprofile/op_model_amd.c @@ -102,116 +102,6 @@ static u32 get_ibs_caps(void) return ibs_caps; } -#ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX - -static void op_mux_switch_ctrl(struct op_x86_model_spec const *model, - struct op_msrs const * const msrs) -{ - u64 val; - int i; - - /* enable active counters */ - for (i = 0; i < NUM_COUNTERS; ++i) { - int virt = op_x86_phys_to_virt(i); - if (!reset_value[virt]) - continue; - rdmsrl(msrs->controls[i].addr, val); - val &= model->reserved; - val |= op_x86_get_ctrl(model, &counter_config[virt]); - wrmsrl(msrs->controls[i].addr, val); - } -} - -#endif - -/* functions for op_amd_spec */ - -static void op_amd_shutdown(struct op_msrs const * const msrs) -{ - int i; - - for (i = 0; i < NUM_COUNTERS; ++i) { - if (!msrs->counters[i].addr) - continue; - release_perfctr_nmi(MSR_K7_PERFCTR0 + i); - release_evntsel_nmi(MSR_K7_EVNTSEL0 + i); - } -} - -static int op_amd_fill_in_addresses(struct op_msrs * const msrs) -{ - int i; - - for (i = 0; i < NUM_COUNTERS; i++) { - if (!reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i)) - goto fail; - if (!reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i)) { - release_perfctr_nmi(MSR_K7_PERFCTR0 + i); - goto fail; - } - /* both registers must be reserved */ - msrs->counters[i].addr = MSR_K7_PERFCTR0 + i; - msrs->controls[i].addr = MSR_K7_EVNTSEL0 + i; - continue; - fail: - if (!counter_config[i].enabled) - continue; - op_x86_warn_reserved(i); - op_amd_shutdown(msrs); - return -EBUSY; - } - - return 0; -} - -static void op_amd_setup_ctrs(struct op_x86_model_spec const *model, - struct op_msrs const * const msrs) -{ - u64 val; - int i; - - /* setup reset_value */ - for (i = 0; i < NUM_VIRT_COUNTERS; ++i) { - if (counter_config[i].enabled - && msrs->counters[op_x86_virt_to_phys(i)].addr) - reset_value[i] = counter_config[i].count; - else - reset_value[i] = 0; - } - - /* clear all counters */ - for (i = 0; i < NUM_COUNTERS; ++i) { - if (!msrs->controls[i].addr) - continue; - rdmsrl(msrs->controls[i].addr, val); - if (val & ARCH_PERFMON_EVENTSEL_ENABLE) - op_x86_warn_in_use(i); - val &= model->reserved; - wrmsrl(msrs->controls[i].addr, val); - /* - * avoid a false detection of ctr overflows in NMI - * handler - */ - wrmsrl(msrs->counters[i].addr, -1LL); - } - - /* enable active counters */ - for (i = 0; i < NUM_COUNTERS; ++i) { - int virt = op_x86_phys_to_virt(i); - if (!reset_value[virt]) - continue; - - /* setup counter registers */ - wrmsrl(msrs->counters[i].addr, -(u64)reset_value[virt]); - - /* setup control registers */ - rdmsrl(msrs->controls[i].addr, val); - val &= model->reserved; - val |= op_x86_get_ctrl(model, &counter_config[virt]); - wrmsrl(msrs->controls[i].addr, val); - } -} - /* * 16-bit Linear Feedback Shift Register (LFSR) * @@ -376,6 +266,116 @@ static void op_amd_stop_ibs(void) wrmsrl(MSR_AMD64_IBSOPCTL, 0); } +#ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX + +static void op_mux_switch_ctrl(struct op_x86_model_spec const *model, + struct op_msrs const * const msrs) +{ + u64 val; + int i; + + /* enable active counters */ + for (i = 0; i < NUM_COUNTERS; ++i) { + int virt = op_x86_phys_to_virt(i); + if (!reset_value[virt]) + continue; + rdmsrl(msrs->controls[i].addr, val); + val &= model->reserved; + val |= op_x86_get_ctrl(model, &counter_config[virt]); + wrmsrl(msrs->controls[i].addr, val); + } +} + +#endif + +/* functions for op_amd_spec */ + +static void op_amd_shutdown(struct op_msrs const * const msrs) +{ + int i; + + for (i = 0; i < NUM_COUNTERS; ++i) { + if (!msrs->counters[i].addr) + continue; + release_perfctr_nmi(MSR_K7_PERFCTR0 + i); + release_evntsel_nmi(MSR_K7_EVNTSEL0 + i); + } +} + +static int op_amd_fill_in_addresses(struct op_msrs * const msrs) +{ + int i; + + for (i = 0; i < NUM_COUNTERS; i++) { + if (!reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i)) + goto fail; + if (!reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i)) { + release_perfctr_nmi(MSR_K7_PERFCTR0 + i); + goto fail; + } + /* both registers must be reserved */ + msrs->counters[i].addr = MSR_K7_PERFCTR0 + i; + msrs->controls[i].addr = MSR_K7_EVNTSEL0 + i; + continue; + fail: + if (!counter_config[i].enabled) + continue; + op_x86_warn_reserved(i); + op_amd_shutdown(msrs); + return -EBUSY; + } + + return 0; +} + +static void op_amd_setup_ctrs(struct op_x86_model_spec const *model, + struct op_msrs const * const msrs) +{ + u64 val; + int i; + + /* setup reset_value */ + for (i = 0; i < NUM_VIRT_COUNTERS; ++i) { + if (counter_config[i].enabled + && msrs->counters[op_x86_virt_to_phys(i)].addr) + reset_value[i] = counter_config[i].count; + else + reset_value[i] = 0; + } + + /* clear all counters */ + for (i = 0; i < NUM_COUNTERS; ++i) { + if (!msrs->controls[i].addr) + continue; + rdmsrl(msrs->controls[i].addr, val); + if (val & ARCH_PERFMON_EVENTSEL_ENABLE) + op_x86_warn_in_use(i); + val &= model->reserved; + wrmsrl(msrs->controls[i].addr, val); + /* + * avoid a false detection of ctr overflows in NMI + * handler + */ + wrmsrl(msrs->counters[i].addr, -1LL); + } + + /* enable active counters */ + for (i = 0; i < NUM_COUNTERS; ++i) { + int virt = op_x86_phys_to_virt(i); + if (!reset_value[virt]) + continue; + + /* setup counter registers */ + wrmsrl(msrs->counters[i].addr, -(u64)reset_value[virt]); + + /* setup control registers */ + rdmsrl(msrs->controls[i].addr, val); + val &= model->reserved; + val |= op_x86_get_ctrl(model, &counter_config[virt]); + wrmsrl(msrs->controls[i].addr, val); + } +} + static int op_amd_check_ctrs(struct pt_regs * const regs, struct op_msrs const * const msrs) { -- cgit v0.10.2 From 5bdb7934ca4115a12c7d585c5a45312b1c36909b Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Wed, 31 Mar 2010 11:58:36 +0200 Subject: oprofile/x86: remove duplicate IBS capability check The check is already done in ibs_exit(). Signed-off-by: Robert Richter diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c index e159254..384c524 100644 --- a/arch/x86/oprofile/op_model_amd.c +++ b/arch/x86/oprofile/op_model_amd.c @@ -490,8 +490,7 @@ static int init_ibs_nmi(void) /* uninitialize the APIC for the IBS interrupts if needed */ static void clear_ibs_nmi(void) { - if (ibs_caps) - on_each_cpu(apic_clear_ibs_nmi_per_cpu, NULL, 1); + on_each_cpu(apic_clear_ibs_nmi_per_cpu, NULL, 1); } /* initialize the APIC for the IBS interrupts if available */ -- cgit v0.10.2 From 2623a1d55a6260c855e1f6d1895900b50b40a896 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Mon, 3 May 2010 19:44:32 +0200 Subject: oprofile/x86: fix uninitialized counter usage during cpu hotplug This fixes a NULL pointer dereference that is triggered when taking a cpu offline after oprofile was initialized, e.g.: $ opcontrol --init $ opcontrol --start-daemon $ opcontrol --shutdown $ opcontrol --deinit $ echo 0 > /sys/devices/system/cpu/cpu1/online See the crash dump below. Though the counter has been disabled the cpu notifier is still active and trying to use already freed counter data. This fix is for linux-stable. To proper fix this, the hotplug code must be rewritten. Thus I will leave a WARN_ON_ONCE() message with this patch. BUG: unable to handle kernel NULL pointer dereference at (null) IP: [] op_amd_stop+0x2d/0x8e PGD 0 Oops: 0000 [#1] SMP last sysfs file: /sys/devices/system/cpu/cpu1/online CPU 1 Modules linked in: Pid: 0, comm: swapper Not tainted 2.6.34-rc5-oprofile-x86_64-standard-00210-g8c00f06 #16 Anaheim/Anaheim RIP: 0010:[] [] op_amd_stop+0x2d/0x8e RSP: 0018:ffff880001843f28 EFLAGS: 00010006 RAX: 0000000000000000 RBX: 0000000000000000 RCX: dead000000200200 RDX: ffff880001843f68 RSI: dead000000100100 RDI: 0000000000000000 RBP: ffff880001843f48 R08: 0000000000000000 R09: ffff880001843f08 R10: ffffffff8102c9a5 R11: ffff88000184ea80 R12: 0000000000000000 R13: ffff88000184f6c0 R14: 0000000000000000 R15: 0000000000000000 FS: 00007fec6a92e6f0(0000) GS:ffff880001840000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 0000000000000000 CR3: 000000000163b000 CR4: 00000000000006e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process swapper (pid: 0, threadinfo ffff88042fcd8000, task ffff88042fcd51d0) Stack: ffff880001843f48 0000000000000001 ffff88042e9f7d38 ffff880001843f68 <0> ffff880001843f58 ffffffff8132a602 ffff880001843f98 ffffffff810521b3 <0> ffff880001843f68 ffff880001843f68 ffff880001843f88 ffff88042fcd9fd8 Call Trace: [] nmi_cpu_stop+0x21/0x23 [] generic_smp_call_function_single_interrupt+0xdf/0x11b [] smp_call_function_single_interrupt+0x22/0x31 [] call_function_single_interrupt+0x13/0x20 [] ? wake_up_process+0x10/0x12 [] ? default_idle+0x22/0x37 [] c1e_idle+0xdf/0xe6 [] ? atomic_notifier_call_chain+0x13/0x15 [] cpu_idle+0x4b/0x7e [] start_secondary+0x1ae/0x1b2 Code: 89 e5 41 55 49 89 fd 41 54 45 31 e4 53 31 db 48 83 ec 08 89 df e8 be f8 ff ff 48 98 48 83 3c c5 10 67 7a 81 00 74 1f 49 8b 45 08 <42> 8b 0c 20 0f 32 48 c1 e2 20 25 ff ff bf ff 48 09 d0 48 89 c2 RIP [] op_amd_stop+0x2d/0x8e RSP CR2: 0000000000000000 ---[ end trace 679ac372d674b757 ]--- Kernel panic - not syncing: Fatal exception in interrupt Pid: 0, comm: swapper Tainted: G D 2.6.34-rc5-oprofile-x86_64-standard-00210-g8c00f06 #16 Call Trace: [] panic+0x9e/0x10c [] ? up+0x34/0x39 [] ? kmsg_dump+0x112/0x12c [] oops_end+0x81/0x8e [] no_context+0x1f3/0x202 [] __bad_area_nosemaphore+0x1ba/0x1e0 [] ? enqueue_task_fair+0x16d/0x17a [] ? activate_task+0x42/0x53 [] ? try_to_wake_up+0x272/0x284 [] bad_area_nosemaphore+0xe/0x10 [] do_page_fault+0x1c8/0x37c [] ? enqueue_task_fair+0x16d/0x17a [] page_fault+0x1f/0x30 [] ? wake_up_process+0x10/0x12 [] ? op_amd_stop+0x2d/0x8e [] ? op_amd_stop+0x1c/0x8e [] nmi_cpu_stop+0x21/0x23 [] generic_smp_call_function_single_interrupt+0xdf/0x11b [] smp_call_function_single_interrupt+0x22/0x31 [] call_function_single_interrupt+0x13/0x20 [] ? wake_up_process+0x10/0x12 [] ? default_idle+0x22/0x37 [] c1e_idle+0xdf/0xe6 [] ? atomic_notifier_call_chain+0x13/0x15 [] cpu_idle+0x4b/0x7e [] start_secondary+0x1ae/0x1b2 ------------[ cut here ]------------ WARNING: at /local/rrichter/.source/linux/arch/x86/kernel/smp.c:118 native_smp_send_reschedule+0x27/0x53() Hardware name: Anaheim Modules linked in: Pid: 0, comm: swapper Tainted: G D 2.6.34-rc5-oprofile-x86_64-standard-00210-g8c00f06 #16 Call Trace: [] ? native_smp_send_reschedule+0x27/0x53 [] warn_slowpath_common+0x77/0xa4 [] warn_slowpath_null+0xf/0x11 [] native_smp_send_reschedule+0x27/0x53 [] resched_task+0x60/0x62 [] check_preempt_curr_idle+0x10/0x12 [] try_to_wake_up+0x1f5/0x284 [] default_wake_function+0xd/0xf [] pollwake+0x57/0x5a [] ? default_wake_function+0x0/0xf [] __wake_up_common+0x46/0x75 [] __wake_up+0x38/0x50 [] printk_tick+0x39/0x3b [] update_process_times+0x3f/0x5c [] tick_periodic+0x5d/0x69 [] tick_handle_periodic+0x21/0x71 [] smp_apic_timer_interrupt+0x82/0x95 [] apic_timer_interrupt+0x13/0x20 [] ? panic_blink_one_second+0x0/0x7b [] ? panic+0x10a/0x10c [] ? up+0x34/0x39 [] ? kmsg_dump+0x112/0x12c [] ? oops_end+0x81/0x8e [] ? no_context+0x1f3/0x202 [] ? __bad_area_nosemaphore+0x1ba/0x1e0 [] ? enqueue_task_fair+0x16d/0x17a [] ? activate_task+0x42/0x53 [] ? try_to_wake_up+0x272/0x284 [] ? bad_area_nosemaphore+0xe/0x10 [] ? do_page_fault+0x1c8/0x37c [] ? enqueue_task_fair+0x16d/0x17a [] ? page_fault+0x1f/0x30 [] ? wake_up_process+0x10/0x12 [] ? op_amd_stop+0x2d/0x8e [] ? op_amd_stop+0x1c/0x8e [] ? nmi_cpu_stop+0x21/0x23 [] ? generic_smp_call_function_single_interrupt+0xdf/0x11b [] ? smp_call_function_single_interrupt+0x22/0x31 [] ? call_function_single_interrupt+0x13/0x20 [] ? wake_up_process+0x10/0x12 [] ? default_idle+0x22/0x37 [] ? c1e_idle+0xdf/0xe6 [] ? atomic_notifier_call_chain+0x13/0x15 [] ? cpu_idle+0x4b/0x7e [] ? start_secondary+0x1ae/0x1b2 ---[ end trace 679ac372d674b758 ]--- Cc: Andi Kleen Cc: stable Signed-off-by: Robert Richter diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index 9f001d9..24582040 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -95,7 +95,10 @@ static void nmi_cpu_save_registers(struct op_msrs *msrs) static void nmi_cpu_start(void *dummy) { struct op_msrs const *msrs = &__get_cpu_var(cpu_msrs); - model->start(msrs); + if (!msrs->controls) + WARN_ON_ONCE(1); + else + model->start(msrs); } static int nmi_start(void) @@ -107,7 +110,10 @@ static int nmi_start(void) static void nmi_cpu_stop(void *dummy) { struct op_msrs const *msrs = &__get_cpu_var(cpu_msrs); - model->stop(msrs); + if (!msrs->controls) + WARN_ON_ONCE(1); + else + model->stop(msrs); } static void nmi_stop(void) -- cgit v0.10.2 From 216f3d9b4e5121feea4b13fae9d4c83e8d7e1c8a Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Mon, 3 May 2010 11:58:46 +0200 Subject: oprofile/x86: remove CONFIG_SMP macros CPU notifier register functions also exist if CONFIG_SMP is disabled. This change is part of hotplug code rework and also necessary for later patches. Cc: Andi Kleen Signed-off-by: Robert Richter diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index 24582040..c5df8ee 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -471,7 +471,6 @@ static int nmi_create_files(struct super_block *sb, struct dentry *root) return 0; } -#ifdef CONFIG_SMP static int oprofile_cpu_notifier(struct notifier_block *b, unsigned long action, void *data) { @@ -491,7 +490,6 @@ static int oprofile_cpu_notifier(struct notifier_block *b, unsigned long action, static struct notifier_block oprofile_cpu_nb = { .notifier_call = oprofile_cpu_notifier }; -#endif #ifdef CONFIG_PM @@ -701,9 +699,8 @@ int __init op_nmi_init(struct oprofile_operations *ops) return -ENODEV; } -#ifdef CONFIG_SMP register_cpu_notifier(&oprofile_cpu_nb); -#endif + /* default values, can be overwritten by model */ ops->create_files = nmi_create_files; ops->setup = nmi_setup; @@ -732,9 +729,7 @@ void op_nmi_exit(void) { if (using_nmi) { exit_sysfs(); -#ifdef CONFIG_SMP unregister_cpu_notifier(&oprofile_cpu_nb); -#endif } if (model->exit) model->exit(); -- cgit v0.10.2 From 6ae56b55bc364bc2f2342f599b46581627ba22da Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Thu, 29 Apr 2010 14:55:55 +0200 Subject: oprofile/x86: protect cpu hotplug sections This patch reworks oprofile cpu hotplug code as follows: Introduce ctr_running variable to check, if counters are running or not. The state must be known for taking a cpu on or offline and when switching counters during counter multiplexing. Protect on_each_cpu() sections with get_online_cpus()/put_online_cpu() functions. This is necessary if notifiers or states are modified. Within these sections the cpu mask may not change. Switch only between counters in nmi_cpu_switch(), if counters are running. Otherwise the switch may restart a counter though they are disabled. Add nmi_cpu_setup() and nmi_cpu_shutdown() to cpu hotplug code. The function must also be called to avoid uninitialzed counter usage. Cc: Andi Kleen Signed-off-by: Robert Richter diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index c5df8ee..b56601e 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -31,8 +31,9 @@ static struct op_x86_model_spec *model; static DEFINE_PER_CPU(struct op_msrs, cpu_msrs); static DEFINE_PER_CPU(unsigned long, saved_lvtpc); -/* 0 == registered but off, 1 == registered and on */ -static int nmi_enabled = 0; +/* must be protected with get_online_cpus()/put_online_cpus(): */ +static int nmi_enabled; +static int ctr_running; struct op_counter_config counter_config[OP_MAX_COUNTER]; @@ -103,7 +104,10 @@ static void nmi_cpu_start(void *dummy) static int nmi_start(void) { + get_online_cpus(); on_each_cpu(nmi_cpu_start, NULL, 1); + ctr_running = 1; + put_online_cpus(); return 0; } @@ -118,7 +122,10 @@ static void nmi_cpu_stop(void *dummy) static void nmi_stop(void) { + get_online_cpus(); on_each_cpu(nmi_cpu_stop, NULL, 1); + ctr_running = 0; + put_online_cpus(); } #ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX @@ -258,7 +265,10 @@ static int nmi_switch_event(void) if (nmi_multiplex_on() < 0) return -EINVAL; /* not necessary */ - on_each_cpu(nmi_cpu_switch, NULL, 1); + get_online_cpus(); + if (ctr_running) + on_each_cpu(nmi_cpu_switch, NULL, 1); + put_online_cpus(); return 0; } @@ -386,8 +396,11 @@ static int nmi_setup(void) if (err) goto fail; + get_online_cpus(); on_each_cpu(nmi_cpu_setup, NULL, 1); nmi_enabled = 1; + put_online_cpus(); + return 0; fail: free_msrs(); @@ -433,8 +446,11 @@ static void nmi_shutdown(void) { struct op_msrs *msrs; - nmi_enabled = 0; + get_online_cpus(); on_each_cpu(nmi_cpu_shutdown, NULL, 1); + nmi_enabled = 0; + ctr_running = 0; + put_online_cpus(); unregister_die_notifier(&profile_exceptions_nb); msrs = &get_cpu_var(cpu_msrs); model->shutdown(msrs); @@ -442,6 +458,22 @@ static void nmi_shutdown(void) put_cpu_var(cpu_msrs); } +static void nmi_cpu_up(void *dummy) +{ + if (nmi_enabled) + nmi_cpu_setup(dummy); + if (ctr_running) + nmi_cpu_start(dummy); +} + +static void nmi_cpu_down(void *dummy) +{ + if (ctr_running) + nmi_cpu_stop(dummy); + if (nmi_enabled) + nmi_cpu_shutdown(dummy); +} + static int nmi_create_files(struct super_block *sb, struct dentry *root) { unsigned int i; @@ -478,10 +510,10 @@ static int oprofile_cpu_notifier(struct notifier_block *b, unsigned long action, switch (action) { case CPU_DOWN_FAILED: case CPU_ONLINE: - smp_call_function_single(cpu, nmi_cpu_start, NULL, 0); + smp_call_function_single(cpu, nmi_cpu_up, NULL, 0); break; case CPU_DOWN_PREPARE: - smp_call_function_single(cpu, nmi_cpu_stop, NULL, 1); + smp_call_function_single(cpu, nmi_cpu_down, NULL, 1); break; } return NOTIFY_DONE; @@ -699,7 +731,11 @@ int __init op_nmi_init(struct oprofile_operations *ops) return -ENODEV; } + get_online_cpus(); register_cpu_notifier(&oprofile_cpu_nb); + nmi_enabled = 0; + ctr_running = 0; + put_online_cpus(); /* default values, can be overwritten by model */ ops->create_files = nmi_create_files; @@ -729,7 +765,11 @@ void op_nmi_exit(void) { if (using_nmi) { exit_sysfs(); + get_online_cpus(); unregister_cpu_notifier(&oprofile_cpu_nb); + nmi_enabled = 0; + ctr_running = 0; + put_online_cpus(); } if (model->exit) model->exit(); -- cgit v0.10.2 From de654649737696ecf32873c341b305e30f3dc777 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Mon, 3 May 2010 14:41:22 +0200 Subject: oprofile/x86: stop disabled counters in nmi handler This patch adds checks to the nmi handler. Now samples are only generated and counters reenabled, if the counters are running. Otherwise the counters are stopped, if oprofile is using the nmi. In other cases it will ignore the nmi notification. Cc: Andi Kleen Signed-off-by: Robert Richter diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index b56601e..94b5481 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -62,12 +62,16 @@ static int profile_exceptions_notify(struct notifier_block *self, { struct die_args *args = (struct die_args *)data; int ret = NOTIFY_DONE; - int cpu = smp_processor_id(); switch (val) { case DIE_NMI: case DIE_NMI_IPI: - model->check_ctrs(args->regs, &per_cpu(cpu_msrs, cpu)); + if (ctr_running) + model->check_ctrs(args->regs, &__get_cpu_var(cpu_msrs)); + else if (!nmi_enabled) + break; + else + model->stop(&__get_cpu_var(cpu_msrs)); ret = NOTIFY_STOP; break; default: @@ -392,6 +396,9 @@ static int nmi_setup(void) mux_clone(cpu); } + nmi_enabled = 0; + ctr_running = 0; + barrier(); err = register_die_notifier(&profile_exceptions_nb); if (err) goto fail; @@ -451,6 +458,7 @@ static void nmi_shutdown(void) nmi_enabled = 0; ctr_running = 0; put_online_cpus(); + barrier(); unregister_die_notifier(&profile_exceptions_nb); msrs = &get_cpu_var(cpu_msrs); model->shutdown(msrs); -- cgit v0.10.2 From d30d64c6da3ec7a0708bfffa7e05752d5b9a1093 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Mon, 3 May 2010 15:52:26 +0200 Subject: oprofile/x86: reordering some functions Reordering some functions. Necessary for the next patch. No functional changes. Cc: Andi Kleen Signed-off-by: Robert Richter diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index 94b5481..7de0572 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -364,56 +364,6 @@ static struct notifier_block profile_exceptions_nb = { .priority = 2 }; -static int nmi_setup(void) -{ - int err = 0; - int cpu; - - if (!allocate_msrs()) - return -ENOMEM; - - /* We need to serialize save and setup for HT because the subset - * of msrs are distinct for save and setup operations - */ - - /* Assume saved/restored counters are the same on all CPUs */ - err = model->fill_in_addresses(&per_cpu(cpu_msrs, 0)); - if (err) - goto fail; - - for_each_possible_cpu(cpu) { - if (!cpu) - continue; - - memcpy(per_cpu(cpu_msrs, cpu).counters, - per_cpu(cpu_msrs, 0).counters, - sizeof(struct op_msr) * model->num_counters); - - memcpy(per_cpu(cpu_msrs, cpu).controls, - per_cpu(cpu_msrs, 0).controls, - sizeof(struct op_msr) * model->num_controls); - - mux_clone(cpu); - } - - nmi_enabled = 0; - ctr_running = 0; - barrier(); - err = register_die_notifier(&profile_exceptions_nb); - if (err) - goto fail; - - get_online_cpus(); - on_each_cpu(nmi_cpu_setup, NULL, 1); - nmi_enabled = 1; - put_online_cpus(); - - return 0; -fail: - free_msrs(); - return err; -} - static void nmi_cpu_restore_registers(struct op_msrs *msrs) { struct op_msr *counters = msrs->counters; @@ -449,23 +399,6 @@ static void nmi_cpu_shutdown(void *dummy) nmi_cpu_restore_registers(msrs); } -static void nmi_shutdown(void) -{ - struct op_msrs *msrs; - - get_online_cpus(); - on_each_cpu(nmi_cpu_shutdown, NULL, 1); - nmi_enabled = 0; - ctr_running = 0; - put_online_cpus(); - barrier(); - unregister_die_notifier(&profile_exceptions_nb); - msrs = &get_cpu_var(cpu_msrs); - model->shutdown(msrs); - free_msrs(); - put_cpu_var(cpu_msrs); -} - static void nmi_cpu_up(void *dummy) { if (nmi_enabled) @@ -531,6 +464,73 @@ static struct notifier_block oprofile_cpu_nb = { .notifier_call = oprofile_cpu_notifier }; +static int nmi_setup(void) +{ + int err = 0; + int cpu; + + if (!allocate_msrs()) + return -ENOMEM; + + /* We need to serialize save and setup for HT because the subset + * of msrs are distinct for save and setup operations + */ + + /* Assume saved/restored counters are the same on all CPUs */ + err = model->fill_in_addresses(&per_cpu(cpu_msrs, 0)); + if (err) + goto fail; + + for_each_possible_cpu(cpu) { + if (!cpu) + continue; + + memcpy(per_cpu(cpu_msrs, cpu).counters, + per_cpu(cpu_msrs, 0).counters, + sizeof(struct op_msr) * model->num_counters); + + memcpy(per_cpu(cpu_msrs, cpu).controls, + per_cpu(cpu_msrs, 0).controls, + sizeof(struct op_msr) * model->num_controls); + + mux_clone(cpu); + } + + nmi_enabled = 0; + ctr_running = 0; + barrier(); + err = register_die_notifier(&profile_exceptions_nb); + if (err) + goto fail; + + get_online_cpus(); + on_each_cpu(nmi_cpu_setup, NULL, 1); + nmi_enabled = 1; + put_online_cpus(); + + return 0; +fail: + free_msrs(); + return err; +} + +static void nmi_shutdown(void) +{ + struct op_msrs *msrs; + + get_online_cpus(); + on_each_cpu(nmi_cpu_shutdown, NULL, 1); + nmi_enabled = 0; + ctr_running = 0; + put_online_cpus(); + barrier(); + unregister_die_notifier(&profile_exceptions_nb); + msrs = &get_cpu_var(cpu_msrs); + model->shutdown(msrs); + free_msrs(); + put_cpu_var(cpu_msrs); +} + #ifdef CONFIG_PM static int nmi_suspend(struct sys_device *dev, pm_message_t state) -- cgit v0.10.2 From 11d232ec285b07860670277c8ab3f6076f7bce1e Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 4 May 2010 10:48:22 -0300 Subject: perf inject: Add missing bits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New commands need to have Documentation and be added to command-list.txt so that they can appear when 'perf' is called withouth any subcommand: [root@doppio linux-2.6-tip]# perf usage: perf [--version] [--help] COMMAND [ARGS] The most commonly used perf commands are: annotate Read perf.data (created by perf record) and display annotated code archive Create archive with object files with build-ids found in perf.data file bench General framework for benchmark suites buildid-cache Manage build-id cache. buildid-list List the buildids in a perf.data file diff Read two perf.data files and display the differential profile inject Filter to augment the events stream with additional information kmem Tool to trace/measure kernel memory(slab) properties kvm Tool to trace/measure kvm guest os list List all symbolic event types lock Analyze lock events probe Define new dynamic tracepoints record Run a command and record its profile into perf.data report Read perf.data (created by perf record) and display the profile sched Tool to trace/measure scheduler properties (latencies) stat Run a command and gather performance counter statistics test Runs sanity tests. timechart Tool to visualize total system behavior during a workload top System profiling tool. trace Read perf.data (created by perf record) and display trace output See 'perf help COMMAND' for more information on a specific command. [root@doppio linux-2.6-tip]# The new 'perf inject' command hadn't so it wasn't appearing on that list. Also fix the long option, that should have no spaces in it, rename the faulty one to be '--build-ids', instead of '--inject build-ids'. Reported-by: Ingo Molnar Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Documentation/perf-buildid-cache.txt b/tools/perf/Documentation/perf-buildid-cache.txt index 88bc3b5..5d1a950 100644 --- a/tools/perf/Documentation/perf-buildid-cache.txt +++ b/tools/perf/Documentation/perf-buildid-cache.txt @@ -8,7 +8,7 @@ perf-buildid-cache - Manage build-id cache. SYNOPSIS -------- [verse] -'perf buildid-list ' +'perf buildid-cache ' DESCRIPTION ----------- @@ -30,4 +30,4 @@ OPTIONS SEE ALSO -------- -linkperf:perf-record[1], linkperf:perf-report[1] +linkperf:perf-record[1], linkperf:perf-report[1], linkperf:perf-buildid-list[1] diff --git a/tools/perf/Documentation/perf-inject.txt b/tools/perf/Documentation/perf-inject.txt new file mode 100644 index 0000000..025630d --- /dev/null +++ b/tools/perf/Documentation/perf-inject.txt @@ -0,0 +1,35 @@ +perf-inject(1) +============== + +NAME +---- +perf-inject - Filter to augment the events stream with additional information + +SYNOPSIS +-------- +[verse] +'perf inject ' + +DESCRIPTION +----------- +perf-inject reads a perf-record event stream and repipes it to stdout. At any +point the processing code can inject other events into the event stream - in +this case build-ids (-b option) are read and injected as needed into the event +stream. + +Build-ids are just the first user of perf-inject - potentially anything that +needs userspace processing to augment the events stream with additional +information could make use of this facility. + +OPTIONS +------- +-b:: +--build-ids=:: + Inject build-ids into the output stream +-v:: +--verbose:: + Be more verbose. + +SEE ALSO +-------- +linkperf:perf-record[1], linkperf:perf-report[1], linkperf:perf-archive[1] diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 59e981a..8e3e47b 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -204,7 +204,7 @@ static const char * const report_usage[] = { }; static const struct option options[] = { - OPT_BOOLEAN('b', "inject build-ids", &inject_build_ids, + OPT_BOOLEAN('b', "build-ids", &inject_build_ids, "Inject build-ids into the output stream"), OPT_INCR('v', "verbose", &verbose, "be more verbose (show build ids, etc)"), diff --git a/tools/perf/command-list.txt b/tools/perf/command-list.txt index 80a1a44..949d77f 100644 --- a/tools/perf/command-list.txt +++ b/tools/perf/command-list.txt @@ -8,6 +8,7 @@ perf-bench mainporcelain common perf-buildid-cache mainporcelain common perf-buildid-list mainporcelain common perf-diff mainporcelain common +perf-inject mainporcelain common perf-list mainporcelain common perf-sched mainporcelain common perf-record mainporcelain common -- cgit v0.10.2 From 02bf60aad7d5912dfcdbe0154f1bd67ea7a8301e Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Tue, 4 May 2010 21:19:15 +1000 Subject: perf: Fix performance issue with perf report On a large machine we spend a lot of time in perf_header__find_attr when running perf report. If we are parsing a file without PERF_SAMPLE_ID then for each sample we call perf_header__find_attr and loop through all counter IDs, never finding a match. As the machine gets larger there are more per cpu counters and we spend an awful lot of time in there. The patch below initialises each sample id to -1ULL and checks for this in perf_header__find_attr. We may need to do something more intelligent eventually (eg a hash lookup from counter id to attr) but this at least fixes the most common usage of perf report. Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Ingo Molnar Cc: Frederic Weisbecker Cc: Eric B Munson Acked-by: Eric B Munson LKML-Reference: <20100504111915.GB14636@kryten> Signed-off-by: Anton Blanchard -- Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 1757b0f..2477270 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -713,6 +713,7 @@ int event__parse_sample(event_t *event, u64 type, struct sample_data *data) array++; } + data->id = -1ULL; if (type & PERF_SAMPLE_ID) { data->id = *array; array++; diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 2b9f898..8847bec 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -922,6 +922,14 @@ perf_header__find_attr(u64 id, struct perf_header *header) { int i; + /* + * We set id to -1 if the data file doesn't contain sample + * ids. Check for this and avoid walking through the entire + * list of ids which may be large. + */ + if (id == -1ULL) + return NULL; + for (i = 0; i < header->attrs; i++) { struct perf_header_attr *attr = header->attr[i]; int j; -- cgit v0.10.2 From 4dbf6bc239c169b032777616806ecc648058f6b2 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 4 May 2010 11:24:01 -0400 Subject: tracing: Convert nop macros to static inlines The ftrace.h file contains several functions as macros when the functions are disabled due to config options. This patch converts most of them to static inlines. There are two exceptions: register_ftrace_function() and unregister_ftrace_function() This is because their parameter "ops" must not be evaluated since code using the function is allowed to #ifdef out the creation of the parameter. This also fixes an error caused by recent changes: kernel/trace/trace_irqsoff.c: In function 'start_irqsoff_tracer': kernel/trace/trace_irqsoff.c:571: error: expected expression before 'do' Reported-by: Ingo Molnar Signed-off-by: Steven Rostedt diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index 8415a52..e0ae83b 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h @@ -82,9 +82,13 @@ void clear_ftrace_function(void); extern void ftrace_stub(unsigned long a0, unsigned long a1); #else /* !CONFIG_FUNCTION_TRACER */ -# define register_ftrace_function(ops) do { } while (0) -# define unregister_ftrace_function(ops) do { } while (0) -# define clear_ftrace_function(ops) do { } while (0) +/* + * (un)register_ftrace_function must be a macro since the ops parameter + * must not be evaluated. + */ +#define register_ftrace_function(ops) ({ 0; }) +#define unregister_ftrace_function(ops) ({ 0; }) +static inline void clear_ftrace_function(void) { } static inline void ftrace_kill(void) { } static inline void ftrace_stop(void) { } static inline void ftrace_start(void) { } @@ -237,11 +241,13 @@ extern int skip_trace(unsigned long ip); extern void ftrace_disable_daemon(void); extern void ftrace_enable_daemon(void); #else -# define skip_trace(ip) ({ 0; }) -# define ftrace_force_update() ({ 0; }) -# define ftrace_set_filter(buf, len, reset) do { } while (0) -# define ftrace_disable_daemon() do { } while (0) -# define ftrace_enable_daemon() do { } while (0) +static inline int skip_trace(unsigned long ip) { return 0; } +static inline int ftrace_force_update(void) { return 0; } +static inline void ftrace_set_filter(unsigned char *buf, int len, int reset) +{ +} +static inline void ftrace_disable_daemon(void) { } +static inline void ftrace_enable_daemon(void) { } static inline void ftrace_release_mod(struct module *mod) {} static inline int register_ftrace_command(struct ftrace_func_command *cmd) { @@ -314,16 +320,16 @@ static inline void __ftrace_enabled_restore(int enabled) extern void time_hardirqs_on(unsigned long a0, unsigned long a1); extern void time_hardirqs_off(unsigned long a0, unsigned long a1); #else -# define time_hardirqs_on(a0, a1) do { } while (0) -# define time_hardirqs_off(a0, a1) do { } while (0) + static inline void time_hardirqs_on(unsigned long a0, unsigned long a1) { } + static inline void time_hardirqs_off(unsigned long a0, unsigned long a1) { } #endif #ifdef CONFIG_PREEMPT_TRACER extern void trace_preempt_on(unsigned long a0, unsigned long a1); extern void trace_preempt_off(unsigned long a0, unsigned long a1); #else -# define trace_preempt_on(a0, a1) do { } while (0) -# define trace_preempt_off(a0, a1) do { } while (0) + static inline void trace_preempt_on(unsigned long a0, unsigned long a1) { } + static inline void trace_preempt_off(unsigned long a0, unsigned long a1) { } #endif #ifdef CONFIG_FTRACE_MCOUNT_RECORD -- cgit v0.10.2 From 4c18e77f718cdda33363132127db4df795eadbd9 Mon Sep 17 00:00:00 2001 From: viresh kumar Date: Mon, 3 May 2010 09:24:30 +0100 Subject: ARM: 6091/1: ST SPEAr: Adding support for shared irq layer Multiple peripherals in SPEAr share common hardware interrupt lines. This patch adds support for a shared irq layer, which registers hardware irqs by itself and exposes virtual irq numbers to peripherals. Signed-off-by: Viresh Kumar Signed-off-by: Russell King diff --git a/arch/arm/mach-spear3xx/include/mach/irqs.h b/arch/arm/mach-spear3xx/include/mach/irqs.h index fe980e0..7f940b8 100644 --- a/arch/arm/mach-spear3xx/include/mach/irqs.h +++ b/arch/arm/mach-spear3xx/include/mach/irqs.h @@ -14,7 +14,7 @@ #ifndef __MACH_IRQS_H #define __MACH_IRQS_H -/* IRQ definitions */ +/* SPEAr3xx IRQ definitions */ #define IRQ_HW_ACCEL_MOD_0 0 #define IRQ_INTRCOMM_RAS_ARM 1 #define IRQ_CPU_GPT1_1 2 @@ -50,16 +50,103 @@ #define IRQ_HW_ACCEL_MOD_1 31 #define IRQ_VIC_END 32 -#define SPEAR_GPIO_INT_BASE IRQ_VIC_END +#define VIRQ_START IRQ_VIC_END +/* SPEAr300 Virtual irq definitions */ #ifdef CONFIG_MACH_SPEAR300 -#define SPEAR_GPIO1_INT_BASE (SPEAR_GPIO_INT_BASE + 8) -#define SPEAR_GPIO_INT_END (SPEAR_GPIO1_INT_BASE + 8) +/* IRQs sharing IRQ_GEN_RAS_1 */ +#define VIRQ_IT_PERS_S (VIRQ_START + 0) +#define VIRQ_IT_CHANGE_S (VIRQ_START + 1) +#define VIRQ_I2S (VIRQ_START + 2) +#define VIRQ_TDM (VIRQ_START + 3) +#define VIRQ_CAMERA_L (VIRQ_START + 4) +#define VIRQ_CAMERA_F (VIRQ_START + 5) +#define VIRQ_CAMERA_V (VIRQ_START + 6) +#define VIRQ_KEYBOARD (VIRQ_START + 7) +#define VIRQ_GPIO1 (VIRQ_START + 8) + +/* IRQs sharing IRQ_GEN_RAS_3 */ +#define IRQ_CLCD IRQ_GEN_RAS_3 + +/* IRQs sharing IRQ_INTRCOMM_RAS_ARM */ +#define IRQ_SDIO IRQ_INTRCOMM_RAS_ARM + +/* GPIO pins virtual irqs */ +#define SPEAR_GPIO_INT_BASE (VIRQ_START + 9) +#define SPEAR_GPIO1_INT_BASE (SPEAR_GPIO_INT_BASE + 8) +#define SPEAR_GPIO_INT_END (SPEAR_GPIO1_INT_BASE + 8) + +/* SPEAr310 Virtual irq definitions */ +#elif defined(CONFIG_MACH_SPEAR310) +/* IRQs sharing IRQ_GEN_RAS_1 */ +#define VIRQ_SMII0 (VIRQ_START + 0) +#define VIRQ_SMII1 (VIRQ_START + 1) +#define VIRQ_SMII2 (VIRQ_START + 2) +#define VIRQ_SMII3 (VIRQ_START + 3) +#define VIRQ_WAKEUP_SMII0 (VIRQ_START + 4) +#define VIRQ_WAKEUP_SMII1 (VIRQ_START + 5) +#define VIRQ_WAKEUP_SMII2 (VIRQ_START + 6) +#define VIRQ_WAKEUP_SMII3 (VIRQ_START + 7) + +/* IRQs sharing IRQ_GEN_RAS_2 */ +#define VIRQ_UART1 (VIRQ_START + 8) +#define VIRQ_UART2 (VIRQ_START + 9) +#define VIRQ_UART3 (VIRQ_START + 10) +#define VIRQ_UART4 (VIRQ_START + 11) +#define VIRQ_UART5 (VIRQ_START + 12) + +/* IRQs sharing IRQ_GEN_RAS_3 */ +#define VIRQ_EMI (VIRQ_START + 13) +#define VIRQ_PLGPIO (VIRQ_START + 14) + +/* IRQs sharing IRQ_INTRCOMM_RAS_ARM */ +#define VIRQ_TDM_HDLC (VIRQ_START + 15) +#define VIRQ_RS485_0 (VIRQ_START + 16) +#define VIRQ_RS485_1 (VIRQ_START + 17) + +/* GPIO pins virtual irqs */ +#define SPEAR_GPIO_INT_BASE (VIRQ_START + 18) + +/* SPEAr320 Virtual irq definitions */ #else -#define SPEAR_GPIO_INT_END (SPEAR_GPIO_INT_BASE + 8) +/* IRQs sharing IRQ_GEN_RAS_1 */ +#define VIRQ_EMI (VIRQ_START + 0) +#define VIRQ_CLCD (VIRQ_START + 1) +#define VIRQ_SPP (VIRQ_START + 2) + +/* IRQs sharing IRQ_GEN_RAS_2 */ +#define IRQ_SDIO IRQ_GEN_RAS_2 + +/* IRQs sharing IRQ_GEN_RAS_3 */ +#define VIRQ_PLGPIO (VIRQ_START + 3) +#define VIRQ_I2S_PLAY (VIRQ_START + 4) +#define VIRQ_I2S_REC (VIRQ_START + 5) + +/* IRQs sharing IRQ_INTRCOMM_RAS_ARM */ +#define VIRQ_CANU (VIRQ_START + 6) +#define VIRQ_CANL (VIRQ_START + 7) +#define VIRQ_UART1 (VIRQ_START + 8) +#define VIRQ_UART2 (VIRQ_START + 9) +#define VIRQ_SSP1 (VIRQ_START + 10) +#define VIRQ_SSP2 (VIRQ_START + 11) +#define VIRQ_SMII0 (VIRQ_START + 12) +#define VIRQ_MII1_SMII1 (VIRQ_START + 13) +#define VIRQ_WAKEUP_SMII0 (VIRQ_START + 14) +#define VIRQ_WAKEUP_MII1_SMII1 (VIRQ_START + 15) +#define VIRQ_I2C (VIRQ_START + 16) + +/* GPIO pins virtual irqs */ +#define SPEAR_GPIO_INT_BASE (VIRQ_START + 17) + +#endif + +/* PLGPIO Virtual IRQs */ +#if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320) +#define SPEAR_PLGPIO_INT_BASE (SPEAR_GPIO_INT_BASE + 8) +#define SPEAR_GPIO_INT_END (SPEAR_PLGPIO_INT_BASE + 102) #endif -#define VIRTUAL_IRQS (SPEAR_GPIO_INT_END - IRQ_VIC_END) -#define NR_IRQS (IRQ_VIC_END + VIRTUAL_IRQS) +#define VIRQ_END SPEAR_GPIO_INT_END +#define NR_IRQS VIRQ_END #endif /* __MACH_IRQS_H */ diff --git a/arch/arm/mach-spear3xx/include/mach/spear300.h b/arch/arm/mach-spear3xx/include/mach/spear300.h index 40c16f3..ccaa765 100644 --- a/arch/arm/mach-spear3xx/include/mach/spear300.h +++ b/arch/arm/mach-spear3xx/include/mach/spear300.h @@ -20,6 +20,22 @@ #define SPEAR300_TELECOM_BASE 0x50000000 #define SPEAR300_TELECOM_SIZE 0x10000000 +/* Interrupt registers offsets and masks */ +#define SPEAR300_TELECOM_REG_SIZE 0x00010000 +#define INT_ENB_MASK_REG 0x54 +#define INT_STS_MASK_REG 0x58 +#define IT_PERS_S_IRQ_MASK (1 << 0) +#define IT_CHANGE_S_IRQ_MASK (1 << 1) +#define I2S_IRQ_MASK (1 << 2) +#define TDM_IRQ_MASK (1 << 3) +#define CAMERA_L_IRQ_MASK (1 << 4) +#define CAMERA_F_IRQ_MASK (1 << 5) +#define CAMERA_V_IRQ_MASK (1 << 6) +#define KEYBOARD_IRQ_MASK (1 << 7) +#define GPIO1_IRQ_MASK (1 << 8) + +#define SHIRQ_RAS1_MASK 0x1FF + #define SPEAR300_CLCD_BASE 0x60000000 #define SPEAR300_CLCD_SIZE 0x10000000 diff --git a/arch/arm/mach-spear3xx/include/mach/spear310.h b/arch/arm/mach-spear3xx/include/mach/spear310.h index d4f58d6..b27bb8a 100644 --- a/arch/arm/mach-spear3xx/include/mach/spear310.h +++ b/arch/arm/mach-spear3xx/include/mach/spear310.h @@ -40,6 +40,30 @@ #define SPEAR310_SOC_CONFIG_BASE 0xB4000000 #define SPEAR310_SOC_CONFIG_SIZE 0x00000070 +/* Interrupt registers offsets and masks */ +#define INT_STS_MASK_REG 0x04 +#define SMII0_IRQ_MASK (1 << 0) +#define SMII1_IRQ_MASK (1 << 1) +#define SMII2_IRQ_MASK (1 << 2) +#define SMII3_IRQ_MASK (1 << 3) +#define WAKEUP_SMII0_IRQ_MASK (1 << 4) +#define WAKEUP_SMII1_IRQ_MASK (1 << 5) +#define WAKEUP_SMII2_IRQ_MASK (1 << 6) +#define WAKEUP_SMII3_IRQ_MASK (1 << 7) +#define UART1_IRQ_MASK (1 << 8) +#define UART2_IRQ_MASK (1 << 9) +#define UART3_IRQ_MASK (1 << 10) +#define UART4_IRQ_MASK (1 << 11) +#define UART5_IRQ_MASK (1 << 12) +#define EMI_IRQ_MASK (1 << 13) +#define TDM_HDLC_IRQ_MASK (1 << 14) +#define RS485_0_IRQ_MASK (1 << 15) +#define RS485_1_IRQ_MASK (1 << 16) + +#define SHIRQ_RAS1_MASK 0x000FF +#define SHIRQ_RAS2_MASK 0x01F00 +#define SHIRQ_RAS3_MASK 0x02000 +#define SHIRQ_INTRCOMM_RAS_MASK 0x1C000 #endif /* __MACH_SPEAR310_H */ diff --git a/arch/arm/mach-spear3xx/include/mach/spear320.h b/arch/arm/mach-spear3xx/include/mach/spear320.h index e8ad2ed..cacf17a 100644 --- a/arch/arm/mach-spear3xx/include/mach/spear320.h +++ b/arch/arm/mach-spear3xx/include/mach/spear320.h @@ -64,6 +64,32 @@ #define SPEAR320_SOC_CONFIG_BASE 0xB4000000 #define SPEAR320_SOC_CONFIG_SIZE 0x00000070 +/* Interrupt registers offsets and masks */ +#define INT_STS_MASK_REG 0x04 +#define INT_CLR_MASK_REG 0x04 +#define INT_ENB_MASK_REG 0x08 +#define GPIO_IRQ_MASK (1 << 0) +#define I2S_PLAY_IRQ_MASK (1 << 1) +#define I2S_REC_IRQ_MASK (1 << 2) +#define EMI_IRQ_MASK (1 << 7) +#define CLCD_IRQ_MASK (1 << 8) +#define SPP_IRQ_MASK (1 << 9) +#define SDIO_IRQ_MASK (1 << 10) +#define CAN_U_IRQ_MASK (1 << 11) +#define CAN_L_IRQ_MASK (1 << 12) +#define UART1_IRQ_MASK (1 << 13) +#define UART2_IRQ_MASK (1 << 14) +#define SSP1_IRQ_MASK (1 << 15) +#define SSP2_IRQ_MASK (1 << 16) +#define SMII0_IRQ_MASK (1 << 17) +#define MII1_SMII1_IRQ_MASK (1 << 18) +#define WAKEUP_SMII0_IRQ_MASK (1 << 19) +#define WAKEUP_MII1_SMII1_IRQ_MASK (1 << 20) +#define I2C1_IRQ_MASK (1 << 21) + +#define SHIRQ_RAS1_MASK 0x000380 +#define SHIRQ_RAS3_MASK 0x000007 +#define SHIRQ_INTRCOMM_RAS_MASK 0x3FF800 #endif /* __MACH_SPEAR320_H */ diff --git a/arch/arm/mach-spear3xx/spear300.c b/arch/arm/mach-spear3xx/spear300.c index 66e7fcd..3560f8c 100644 --- a/arch/arm/mach-spear3xx/spear300.c +++ b/arch/arm/mach-spear3xx/spear300.c @@ -17,6 +17,7 @@ #include #include #include +#include /* pad multiplexing support */ /* muxing registers */ @@ -386,14 +387,78 @@ struct amba_device gpio1_device = { .end = SPEAR300_GPIO_BASE + SPEAR300_GPIO_SIZE - 1, .flags = IORESOURCE_MEM, }, - .irq = {IRQ_GEN_RAS_1, NO_IRQ}, + .irq = {VIRQ_GPIO1, NO_IRQ}, +}; + +/* spear3xx shared irq */ +struct shirq_dev_config shirq_ras1_config[] = { + { + .virq = VIRQ_IT_PERS_S, + .enb_mask = IT_PERS_S_IRQ_MASK, + .status_mask = IT_PERS_S_IRQ_MASK, + }, { + .virq = VIRQ_IT_CHANGE_S, + .enb_mask = IT_CHANGE_S_IRQ_MASK, + .status_mask = IT_CHANGE_S_IRQ_MASK, + }, { + .virq = VIRQ_I2S, + .enb_mask = I2S_IRQ_MASK, + .status_mask = I2S_IRQ_MASK, + }, { + .virq = VIRQ_TDM, + .enb_mask = TDM_IRQ_MASK, + .status_mask = TDM_IRQ_MASK, + }, { + .virq = VIRQ_CAMERA_L, + .enb_mask = CAMERA_L_IRQ_MASK, + .status_mask = CAMERA_L_IRQ_MASK, + }, { + .virq = VIRQ_CAMERA_F, + .enb_mask = CAMERA_F_IRQ_MASK, + .status_mask = CAMERA_F_IRQ_MASK, + }, { + .virq = VIRQ_CAMERA_V, + .enb_mask = CAMERA_V_IRQ_MASK, + .status_mask = CAMERA_V_IRQ_MASK, + }, { + .virq = VIRQ_KEYBOARD, + .enb_mask = KEYBOARD_IRQ_MASK, + .status_mask = KEYBOARD_IRQ_MASK, + }, { + .virq = VIRQ_GPIO1, + .enb_mask = GPIO1_IRQ_MASK, + .status_mask = GPIO1_IRQ_MASK, + }, +}; + +struct spear_shirq shirq_ras1 = { + .irq = IRQ_GEN_RAS_1, + .dev_config = shirq_ras1_config, + .dev_count = ARRAY_SIZE(shirq_ras1_config), + .regs = { + .enb_reg = INT_ENB_MASK_REG, + .status_reg = INT_STS_MASK_REG, + .status_reg_mask = SHIRQ_RAS1_MASK, + .clear_reg = -1, + }, }; /* spear300 routines */ void __init spear300_init(void) { + int ret = 0; + /* call spear3xx family common init function */ spear3xx_init(); + + /* shared irq registeration */ + shirq_ras1.regs.base = + ioremap(SPEAR300_TELECOM_BASE, SPEAR300_TELECOM_REG_SIZE); + if (shirq_ras1.regs.base) { + ret = spear_shirq_register(&shirq_ras1); + if (ret) + printk(KERN_ERR "Error registering Shared IRQ\n"); + } } void spear300_pmx_init(void) diff --git a/arch/arm/mach-spear3xx/spear310.c b/arch/arm/mach-spear3xx/spear310.c index dd5a572..96a1ab8 100644 --- a/arch/arm/mach-spear3xx/spear310.c +++ b/arch/arm/mach-spear3xx/spear310.c @@ -15,6 +15,7 @@ #include #include #include +#include /* pad multiplexing support */ /* muxing registers */ @@ -140,11 +141,158 @@ struct pmx_driver pmx_driver = { /* Add spear310 specific devices here */ +/* spear3xx shared irq */ +struct shirq_dev_config shirq_ras1_config[] = { + { + .virq = VIRQ_SMII0, + .status_mask = SMII0_IRQ_MASK, + }, { + .virq = VIRQ_SMII1, + .status_mask = SMII1_IRQ_MASK, + }, { + .virq = VIRQ_SMII2, + .status_mask = SMII2_IRQ_MASK, + }, { + .virq = VIRQ_SMII3, + .status_mask = SMII3_IRQ_MASK, + }, { + .virq = VIRQ_WAKEUP_SMII0, + .status_mask = WAKEUP_SMII0_IRQ_MASK, + }, { + .virq = VIRQ_WAKEUP_SMII1, + .status_mask = WAKEUP_SMII1_IRQ_MASK, + }, { + .virq = VIRQ_WAKEUP_SMII2, + .status_mask = WAKEUP_SMII2_IRQ_MASK, + }, { + .virq = VIRQ_WAKEUP_SMII3, + .status_mask = WAKEUP_SMII3_IRQ_MASK, + }, +}; + +struct spear_shirq shirq_ras1 = { + .irq = IRQ_GEN_RAS_1, + .dev_config = shirq_ras1_config, + .dev_count = ARRAY_SIZE(shirq_ras1_config), + .regs = { + .enb_reg = -1, + .status_reg = INT_STS_MASK_REG, + .status_reg_mask = SHIRQ_RAS1_MASK, + .clear_reg = -1, + }, +}; + +struct shirq_dev_config shirq_ras2_config[] = { + { + .virq = VIRQ_UART1, + .status_mask = UART1_IRQ_MASK, + }, { + .virq = VIRQ_UART2, + .status_mask = UART2_IRQ_MASK, + }, { + .virq = VIRQ_UART3, + .status_mask = UART3_IRQ_MASK, + }, { + .virq = VIRQ_UART4, + .status_mask = UART4_IRQ_MASK, + }, { + .virq = VIRQ_UART5, + .status_mask = UART5_IRQ_MASK, + }, +}; + +struct spear_shirq shirq_ras2 = { + .irq = IRQ_GEN_RAS_2, + .dev_config = shirq_ras2_config, + .dev_count = ARRAY_SIZE(shirq_ras2_config), + .regs = { + .enb_reg = -1, + .status_reg = INT_STS_MASK_REG, + .status_reg_mask = SHIRQ_RAS2_MASK, + .clear_reg = -1, + }, +}; + +struct shirq_dev_config shirq_ras3_config[] = { + { + .virq = VIRQ_EMI, + .status_mask = EMI_IRQ_MASK, + }, +}; + +struct spear_shirq shirq_ras3 = { + .irq = IRQ_GEN_RAS_3, + .dev_config = shirq_ras3_config, + .dev_count = ARRAY_SIZE(shirq_ras3_config), + .regs = { + .enb_reg = -1, + .status_reg = INT_STS_MASK_REG, + .status_reg_mask = SHIRQ_RAS3_MASK, + .clear_reg = -1, + }, +}; + +struct shirq_dev_config shirq_intrcomm_ras_config[] = { + { + .virq = VIRQ_TDM_HDLC, + .status_mask = TDM_HDLC_IRQ_MASK, + }, { + .virq = VIRQ_RS485_0, + .status_mask = RS485_0_IRQ_MASK, + }, { + .virq = VIRQ_RS485_1, + .status_mask = RS485_1_IRQ_MASK, + }, +}; + +struct spear_shirq shirq_intrcomm_ras = { + .irq = IRQ_INTRCOMM_RAS_ARM, + .dev_config = shirq_intrcomm_ras_config, + .dev_count = ARRAY_SIZE(shirq_intrcomm_ras_config), + .regs = { + .enb_reg = -1, + .status_reg = INT_STS_MASK_REG, + .status_reg_mask = SHIRQ_INTRCOMM_RAS_MASK, + .clear_reg = -1, + }, +}; + /* spear310 routines */ void __init spear310_init(void) { + void __iomem *base; + int ret = 0; + /* call spear3xx family common init function */ spear3xx_init(); + + /* shared irq registeration */ + base = ioremap(SPEAR310_SOC_CONFIG_BASE, SPEAR310_SOC_CONFIG_SIZE); + if (base) { + /* shirq 1 */ + shirq_ras1.regs.base = base; + ret = spear_shirq_register(&shirq_ras1); + if (ret) + printk(KERN_ERR "Error registering Shared IRQ 1\n"); + + /* shirq 2 */ + shirq_ras2.regs.base = base; + ret = spear_shirq_register(&shirq_ras2); + if (ret) + printk(KERN_ERR "Error registering Shared IRQ 2\n"); + + /* shirq 3 */ + shirq_ras3.regs.base = base; + ret = spear_shirq_register(&shirq_ras3); + if (ret) + printk(KERN_ERR "Error registering Shared IRQ 3\n"); + + /* shirq 4 */ + shirq_intrcomm_ras.regs.base = base; + ret = spear_shirq_register(&shirq_intrcomm_ras); + if (ret) + printk(KERN_ERR "Error registering Shared IRQ 4\n"); + } } void spear310_pmx_init(void) diff --git a/arch/arm/mach-spear3xx/spear320.c b/arch/arm/mach-spear3xx/spear320.c index 2cedf5e..6a12195 100644 --- a/arch/arm/mach-spear3xx/spear320.c +++ b/arch/arm/mach-spear3xx/spear320.c @@ -15,6 +15,7 @@ #include #include #include +#include /* pad multiplexing support */ /* muxing registers */ @@ -385,11 +386,160 @@ struct pmx_driver pmx_driver = { /* Add spear320 specific devices here */ +/* spear3xx shared irq */ +struct shirq_dev_config shirq_ras1_config[] = { + { + .virq = VIRQ_EMI, + .status_mask = EMI_IRQ_MASK, + .clear_mask = EMI_IRQ_MASK, + }, { + .virq = VIRQ_CLCD, + .status_mask = CLCD_IRQ_MASK, + .clear_mask = CLCD_IRQ_MASK, + }, { + .virq = VIRQ_SPP, + .status_mask = SPP_IRQ_MASK, + .clear_mask = SPP_IRQ_MASK, + }, +}; + +struct spear_shirq shirq_ras1 = { + .irq = IRQ_GEN_RAS_1, + .dev_config = shirq_ras1_config, + .dev_count = ARRAY_SIZE(shirq_ras1_config), + .regs = { + .enb_reg = -1, + .status_reg = INT_STS_MASK_REG, + .status_reg_mask = SHIRQ_RAS1_MASK, + .clear_reg = INT_CLR_MASK_REG, + .reset_to_clear = 1, + }, +}; + +struct shirq_dev_config shirq_ras3_config[] = { + { + .virq = VIRQ_PLGPIO, + .enb_mask = GPIO_IRQ_MASK, + .status_mask = GPIO_IRQ_MASK, + .clear_mask = GPIO_IRQ_MASK, + }, { + .virq = VIRQ_I2S_PLAY, + .enb_mask = I2S_PLAY_IRQ_MASK, + .status_mask = I2S_PLAY_IRQ_MASK, + .clear_mask = I2S_PLAY_IRQ_MASK, + }, { + .virq = VIRQ_I2S_REC, + .enb_mask = I2S_REC_IRQ_MASK, + .status_mask = I2S_REC_IRQ_MASK, + .clear_mask = I2S_REC_IRQ_MASK, + }, +}; + +struct spear_shirq shirq_ras3 = { + .irq = IRQ_GEN_RAS_3, + .dev_config = shirq_ras3_config, + .dev_count = ARRAY_SIZE(shirq_ras3_config), + .regs = { + .enb_reg = INT_ENB_MASK_REG, + .reset_to_enb = 1, + .status_reg = INT_STS_MASK_REG, + .status_reg_mask = SHIRQ_RAS3_MASK, + .clear_reg = INT_CLR_MASK_REG, + .reset_to_clear = 1, + }, +}; + +struct shirq_dev_config shirq_intrcomm_ras_config[] = { + { + .virq = VIRQ_CANU, + .status_mask = CAN_U_IRQ_MASK, + .clear_mask = CAN_U_IRQ_MASK, + }, { + .virq = VIRQ_CANL, + .status_mask = CAN_L_IRQ_MASK, + .clear_mask = CAN_L_IRQ_MASK, + }, { + .virq = VIRQ_UART1, + .status_mask = UART1_IRQ_MASK, + .clear_mask = UART1_IRQ_MASK, + }, { + .virq = VIRQ_UART2, + .status_mask = UART2_IRQ_MASK, + .clear_mask = UART2_IRQ_MASK, + }, { + .virq = VIRQ_SSP1, + .status_mask = SSP1_IRQ_MASK, + .clear_mask = SSP1_IRQ_MASK, + }, { + .virq = VIRQ_SSP2, + .status_mask = SSP2_IRQ_MASK, + .clear_mask = SSP2_IRQ_MASK, + }, { + .virq = VIRQ_SMII0, + .status_mask = SMII0_IRQ_MASK, + .clear_mask = SMII0_IRQ_MASK, + }, { + .virq = VIRQ_MII1_SMII1, + .status_mask = MII1_SMII1_IRQ_MASK, + .clear_mask = MII1_SMII1_IRQ_MASK, + }, { + .virq = VIRQ_WAKEUP_SMII0, + .status_mask = WAKEUP_SMII0_IRQ_MASK, + .clear_mask = WAKEUP_SMII0_IRQ_MASK, + }, { + .virq = VIRQ_WAKEUP_MII1_SMII1, + .status_mask = WAKEUP_MII1_SMII1_IRQ_MASK, + .clear_mask = WAKEUP_MII1_SMII1_IRQ_MASK, + }, { + .virq = VIRQ_I2C, + .status_mask = I2C1_IRQ_MASK, + .clear_mask = I2C1_IRQ_MASK, + }, +}; + +struct spear_shirq shirq_intrcomm_ras = { + .irq = IRQ_INTRCOMM_RAS_ARM, + .dev_config = shirq_intrcomm_ras_config, + .dev_count = ARRAY_SIZE(shirq_intrcomm_ras_config), + .regs = { + .enb_reg = -1, + .status_reg = INT_STS_MASK_REG, + .status_reg_mask = SHIRQ_INTRCOMM_RAS_MASK, + .clear_reg = INT_CLR_MASK_REG, + .reset_to_clear = 1, + }, +}; + /* spear320 routines */ void __init spear320_init(void) { + void __iomem *base; + int ret = 0; + /* call spear3xx family common init function */ spear3xx_init(); + + /* shared irq registeration */ + base = ioremap(SPEAR320_SOC_CONFIG_BASE, SPEAR320_SOC_CONFIG_SIZE); + if (base) { + /* shirq 1 */ + shirq_ras1.regs.base = base; + ret = spear_shirq_register(&shirq_ras1); + if (ret) + printk(KERN_ERR "Error registering Shared IRQ 1\n"); + + /* shirq 3 */ + shirq_ras3.regs.base = base; + ret = spear_shirq_register(&shirq_ras3); + if (ret) + printk(KERN_ERR "Error registering Shared IRQ 3\n"); + + /* shirq 4 */ + shirq_intrcomm_ras.regs.base = base; + ret = spear_shirq_register(&shirq_intrcomm_ras); + if (ret) + printk(KERN_ERR "Error registering Shared IRQ 4\n"); + } } void spear320_pmx_init(void) diff --git a/arch/arm/mach-spear6xx/include/mach/irqs.h b/arch/arm/mach-spear6xx/include/mach/irqs.h index 08a3abc..8f214b0 100644 --- a/arch/arm/mach-spear6xx/include/mach/irqs.h +++ b/arch/arm/mach-spear6xx/include/mach/irqs.h @@ -85,6 +85,7 @@ #define IRQ_VIC_END 64 +/* GPIO pins virtual irqs */ #define SPEAR_GPIO_INT_BASE IRQ_VIC_END #define SPEAR_GPIO0_INT_BASE SPEAR_GPIO_INT_BASE #define SPEAR_GPIO1_INT_BASE (SPEAR_GPIO0_INT_BASE + 8) diff --git a/arch/arm/plat-spear/Makefile b/arch/arm/plat-spear/Makefile index 6f4ad5e..eb89540 100644 --- a/arch/arm/plat-spear/Makefile +++ b/arch/arm/plat-spear/Makefile @@ -4,3 +4,5 @@ # Common support obj-y := clock.o padmux.o time.o + +obj-$(CONFIG_ARCH_SPEAR3XX) += shirq.o diff --git a/arch/arm/plat-spear/include/plat/shirq.h b/arch/arm/plat-spear/include/plat/shirq.h new file mode 100644 index 0000000..03ed8b5 --- /dev/null +++ b/arch/arm/plat-spear/include/plat/shirq.h @@ -0,0 +1,73 @@ +/* + * arch/arm/plat-spear/include/plat/shirq.h + * + * SPEAr platform shared irq layer header file + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __PLAT_SHIRQ_H +#define __PLAT_SHIRQ_H + +#include +#include + +/* + * struct shirq_dev_config: shared irq device configuration + * + * virq: virtual irq number of device + * enb_mask: enable mask of device + * status_mask: status mask of device + * clear_mask: clear mask of device + */ +struct shirq_dev_config { + u32 virq; + u32 enb_mask; + u32 status_mask; + u32 clear_mask; +}; + +/* + * struct shirq_regs: shared irq register configuration + * + * base: base address of shared irq register + * enb_reg: enable register offset + * reset_to_enb: val 1 indicates, we need to clear bit for enabling interrupt + * status_reg: status register offset + * status_reg_mask: status register valid mask + * clear_reg: clear register offset + * reset_to_clear: val 1 indicates, we need to clear bit for clearing interrupt + */ +struct shirq_regs { + void __iomem *base; + u32 enb_reg; + u32 reset_to_enb; + u32 status_reg; + u32 status_reg_mask; + u32 clear_reg; + u32 reset_to_clear; +}; + +/* + * struct spear_shirq: shared irq structure + * + * irq: hardware irq number + * dev_config: array of device config structures which are using "irq" line + * dev_count: size of dev_config array + * regs: register configuration for shared irq block + */ +struct spear_shirq { + u32 irq; + struct shirq_dev_config *dev_config; + u32 dev_count; + struct shirq_regs regs; +}; + +int spear_shirq_register(struct spear_shirq *shirq); + +#endif /* __PLAT_SHIRQ_H */ diff --git a/arch/arm/plat-spear/shirq.c b/arch/arm/plat-spear/shirq.c new file mode 100644 index 0000000..2172d69 --- /dev/null +++ b/arch/arm/plat-spear/shirq.c @@ -0,0 +1,118 @@ +/* + * arch/arm/plat-spear/shirq.c + * + * SPEAr platform shared irq layer source file + * + * Copyright (C) 2009 ST Microelectronics + * Viresh Kumar + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include + +struct spear_shirq *shirq; +static DEFINE_SPINLOCK(lock); + +static void shirq_irq_mask(unsigned irq) +{ + struct spear_shirq *shirq = get_irq_chip_data(irq); + u32 val, id = irq - shirq->dev_config[0].virq; + unsigned long flags; + + if ((shirq->regs.enb_reg == -1) || shirq->dev_config[id].enb_mask == -1) + return; + + spin_lock_irqsave(&lock, flags); + val = readl(shirq->regs.base + shirq->regs.enb_reg); + if (shirq->regs.reset_to_enb) + val |= shirq->dev_config[id].enb_mask; + else + val &= ~(shirq->dev_config[id].enb_mask); + writel(val, shirq->regs.base + shirq->regs.enb_reg); + spin_unlock_irqrestore(&lock, flags); +} + +static void shirq_irq_unmask(unsigned irq) +{ + struct spear_shirq *shirq = get_irq_chip_data(irq); + u32 val, id = irq - shirq->dev_config[0].virq; + unsigned long flags; + + if ((shirq->regs.enb_reg == -1) || shirq->dev_config[id].enb_mask == -1) + return; + + spin_lock_irqsave(&lock, flags); + val = readl(shirq->regs.base + shirq->regs.enb_reg); + if (shirq->regs.reset_to_enb) + val &= ~(shirq->dev_config[id].enb_mask); + else + val |= shirq->dev_config[id].enb_mask; + writel(val, shirq->regs.base + shirq->regs.enb_reg); + spin_unlock_irqrestore(&lock, flags); +} + +static struct irq_chip shirq_chip = { + .name = "spear_shirq", + .ack = shirq_irq_mask, + .mask = shirq_irq_mask, + .unmask = shirq_irq_unmask, +}; + +static void shirq_handler(unsigned irq, struct irq_desc *desc) +{ + u32 i, val, mask; + struct spear_shirq *shirq = get_irq_data(irq); + + desc->chip->ack(irq); + while ((val = readl(shirq->regs.base + shirq->regs.status_reg) & + shirq->regs.status_reg_mask)) { + for (i = 0; (i < shirq->dev_count) && val; i++) { + if (!(shirq->dev_config[i].status_mask & val)) + continue; + + generic_handle_irq(shirq->dev_config[i].virq); + + /* clear interrupt */ + val &= ~shirq->dev_config[i].status_mask; + if ((shirq->regs.clear_reg == -1) || + shirq->dev_config[i].clear_mask == -1) + continue; + mask = readl(shirq->regs.base + shirq->regs.clear_reg); + if (shirq->regs.reset_to_clear) + mask &= ~shirq->dev_config[i].clear_mask; + else + mask |= shirq->dev_config[i].clear_mask; + writel(mask, shirq->regs.base + shirq->regs.clear_reg); + } + } + desc->chip->unmask(irq); +} + +int spear_shirq_register(struct spear_shirq *shirq) +{ + int i; + + if (!shirq || !shirq->dev_config || !shirq->regs.base) + return -EFAULT; + + if (!shirq->dev_count) + return -EINVAL; + + set_irq_chained_handler(shirq->irq, shirq_handler); + for (i = 0; i < shirq->dev_count; i++) { + set_irq_chip(shirq->dev_config[i].virq, &shirq_chip); + set_irq_handler(shirq->dev_config[i].virq, handle_simple_irq); + set_irq_flags(shirq->dev_config[i].virq, IRQF_VALID); + set_irq_chip_data(shirq->dev_config[i].virq, shirq); + } + + set_irq_data(shirq->irq, shirq); + return 0; +} -- cgit v0.10.2 From e8faff7330a3501eafc9bfe5f4f15af444be29f5 Mon Sep 17 00:00:00 2001 From: Claudio Scordino Date: Mon, 3 May 2010 13:31:28 +0100 Subject: ARM: 6092/1: atmel_serial: support for RS485 communications Final version of the patch that adds support for RS485 communications to the atmel_serial driver. The patch has been already sent and discussed on both linux-kernel and linux-arm-kernel mailing lists several times. Many people collaborated to improve and test the code: Tested-by: Sebastian Heutling Tested-by: Bernhard Roth Reviewed-by: Ryan Mallon Signed-off-by: Claudio Scordino Signed-off-by: Michael Trimarchi Signed-off-by: Rick Bronson Signed-off-by: Sebastian Heutling Signed-off-by: Russell King diff --git a/arch/arm/include/asm/ioctls.h b/arch/arm/include/asm/ioctls.h index a91d8a1..7f0b6d1 100644 --- a/arch/arm/include/asm/ioctls.h +++ b/arch/arm/include/asm/ioctls.h @@ -53,6 +53,9 @@ #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ +#define TIOCGRS485 0x542E +#define TIOCSRS485 0x542F + #define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ #define FIOCLEX 0x5451 #define FIOASYNC 0x5452 diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h index ceaec6c..df2ed84 100644 --- a/arch/arm/mach-at91/include/mach/board.h +++ b/arch/arm/mach-at91/include/mach/board.h @@ -39,6 +39,7 @@ #include #include #include +#include /* USB Device */ struct at91_udc_data { @@ -143,9 +144,10 @@ extern struct platform_device *atmel_default_console_device; extern void __init __deprecated at91_init_serial(struct at91_uart_config *config); struct atmel_uart_data { - short use_dma_tx; /* use transmit DMA? */ - short use_dma_rx; /* use receive DMA? */ - void __iomem *regs; /* virtual base address, if any */ + short use_dma_tx; /* use transmit DMA? */ + short use_dma_rx; /* use receive DMA? */ + void __iomem *regs; /* virt. base address, if any */ + struct serial_rs485 rs485; /* rs485 settings */ }; extern void __init at91_add_device_serial(void); diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index 2c9bf9b..eed3c2d 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c @@ -38,6 +38,7 @@ #include #include #include +#include #include @@ -59,6 +60,9 @@ #include +static void atmel_start_rx(struct uart_port *port); +static void atmel_stop_rx(struct uart_port *port); + #ifdef CONFIG_SERIAL_ATMEL_TTYAT /* Use device name ttyAT, major 204 and minor 154-169. This is necessary if we @@ -93,6 +97,7 @@ #define UART_GET_BRGR(port) __raw_readl((port)->membase + ATMEL_US_BRGR) #define UART_PUT_BRGR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_BRGR) #define UART_PUT_RTOR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_RTOR) +#define UART_PUT_TTGR(port, v) __raw_writel(v, (port)->membase + ATMEL_US_TTGR) /* PDC registers */ #define UART_PUT_PTCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_PTCR) @@ -147,6 +152,9 @@ struct atmel_uart_port { unsigned int irq_status_prev; struct circ_buf rx_ring; + + struct serial_rs485 rs485; /* rs485 settings */ + unsigned int tx_done_mask; }; static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART]; @@ -187,6 +195,46 @@ static bool atmel_use_dma_tx(struct uart_port *port) } #endif +/* Enable or disable the rs485 support */ +void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf) +{ + struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); + unsigned int mode; + + spin_lock(&port->lock); + + /* Disable interrupts */ + UART_PUT_IDR(port, atmel_port->tx_done_mask); + + mode = UART_GET_MR(port); + + /* Resetting serial mode to RS232 (0x0) */ + mode &= ~ATMEL_US_USMODE; + + atmel_port->rs485 = *rs485conf; + + if (rs485conf->flags & SER_RS485_ENABLED) { + dev_dbg(port->dev, "Setting UART to RS485\n"); + atmel_port->tx_done_mask = ATMEL_US_TXEMPTY; + UART_PUT_TTGR(port, rs485conf->delay_rts_before_send); + mode |= ATMEL_US_USMODE_RS485; + } else { + dev_dbg(port->dev, "Setting UART to RS232\n"); + if (atmel_use_dma_tx(port)) + atmel_port->tx_done_mask = ATMEL_US_ENDTX | + ATMEL_US_TXBUFE; + else + atmel_port->tx_done_mask = ATMEL_US_TXRDY; + } + UART_PUT_MR(port, mode); + + /* Enable interrupts */ + UART_PUT_IER(port, atmel_port->tx_done_mask); + + spin_unlock(&port->lock); + +} + /* * Return TIOCSER_TEMT when transmitter FIFO and Shift register is empty. */ @@ -202,6 +250,7 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl) { unsigned int control = 0; unsigned int mode; + struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); #ifdef CONFIG_ARCH_AT91RM9200 if (cpu_is_at91rm9200()) { @@ -236,6 +285,17 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl) mode |= ATMEL_US_CHMODE_LOC_LOOP; else mode |= ATMEL_US_CHMODE_NORMAL; + + /* Resetting serial mode to RS232 (0x0) */ + mode &= ~ATMEL_US_USMODE; + + if (atmel_port->rs485.flags & SER_RS485_ENABLED) { + dev_dbg(port->dev, "Setting UART to RS485\n"); + UART_PUT_TTGR(port, atmel_port->rs485.delay_rts_before_send); + mode |= ATMEL_US_USMODE_RS485; + } else { + dev_dbg(port->dev, "Setting UART to RS232\n"); + } UART_PUT_MR(port, mode); } @@ -268,12 +328,17 @@ static u_int atmel_get_mctrl(struct uart_port *port) */ static void atmel_stop_tx(struct uart_port *port) { + struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); + if (atmel_use_dma_tx(port)) { /* disable PDC transmit */ UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS); - UART_PUT_IDR(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE); - } else - UART_PUT_IDR(port, ATMEL_US_TXRDY); + } + /* Disable interrupts */ + UART_PUT_IDR(port, atmel_port->tx_done_mask); + + if (atmel_port->rs485.flags & SER_RS485_ENABLED) + atmel_start_rx(port); } /* @@ -281,17 +346,39 @@ static void atmel_stop_tx(struct uart_port *port) */ static void atmel_start_tx(struct uart_port *port) { + struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); + if (atmel_use_dma_tx(port)) { if (UART_GET_PTSR(port) & ATMEL_PDC_TXTEN) /* The transmitter is already running. Yes, we really need this.*/ return; - UART_PUT_IER(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE); + if (atmel_port->rs485.flags & SER_RS485_ENABLED) + atmel_stop_rx(port); + /* re-enable PDC transmit */ UART_PUT_PTCR(port, ATMEL_PDC_TXTEN); - } else - UART_PUT_IER(port, ATMEL_US_TXRDY); + } + /* Enable interrupts */ + UART_PUT_IER(port, atmel_port->tx_done_mask); +} + +/* + * start receiving - port is in process of being opened. + */ +static void atmel_start_rx(struct uart_port *port) +{ + UART_PUT_CR(port, ATMEL_US_RSTSTA); /* reset status and receiver */ + + if (atmel_use_dma_rx(port)) { + /* enable PDC controller */ + UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT | + port->read_status_mask); + UART_PUT_PTCR(port, ATMEL_PDC_RXTEN); + } else { + UART_PUT_IER(port, ATMEL_US_RXRDY); + } } /* @@ -302,9 +389,11 @@ static void atmel_stop_rx(struct uart_port *port) if (atmel_use_dma_rx(port)) { /* disable PDC receive */ UART_PUT_PTCR(port, ATMEL_PDC_RXTDIS); - UART_PUT_IDR(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT); - } else + UART_PUT_IDR(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT | + port->read_status_mask); + } else { UART_PUT_IDR(port, ATMEL_US_RXRDY); + } } /* @@ -428,8 +517,9 @@ static void atmel_rx_chars(struct uart_port *port) static void atmel_tx_chars(struct uart_port *port) { struct circ_buf *xmit = &port->state->xmit; + struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); - if (port->x_char && UART_GET_CSR(port) & ATMEL_US_TXRDY) { + if (port->x_char && UART_GET_CSR(port) & atmel_port->tx_done_mask) { UART_PUT_CHAR(port, port->x_char); port->icount.tx++; port->x_char = 0; @@ -437,7 +527,7 @@ static void atmel_tx_chars(struct uart_port *port) if (uart_circ_empty(xmit) || uart_tx_stopped(port)) return; - while (UART_GET_CSR(port) & ATMEL_US_TXRDY) { + while (UART_GET_CSR(port) & atmel_port->tx_done_mask) { UART_PUT_CHAR(port, xmit->buf[xmit->tail]); xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); port->icount.tx++; @@ -449,7 +539,8 @@ static void atmel_tx_chars(struct uart_port *port) uart_write_wakeup(port); if (!uart_circ_empty(xmit)) - UART_PUT_IER(port, ATMEL_US_TXRDY); + /* Enable interrupts */ + UART_PUT_IER(port, atmel_port->tx_done_mask); } /* @@ -501,18 +592,10 @@ atmel_handle_transmit(struct uart_port *port, unsigned int pending) { struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); - if (atmel_use_dma_tx(port)) { - /* PDC transmit */ - if (pending & (ATMEL_US_ENDTX | ATMEL_US_TXBUFE)) { - UART_PUT_IDR(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE); - tasklet_schedule(&atmel_port->tasklet); - } - } else { - /* Interrupt transmit */ - if (pending & ATMEL_US_TXRDY) { - UART_PUT_IDR(port, ATMEL_US_TXRDY); - tasklet_schedule(&atmel_port->tasklet); - } + if (pending & atmel_port->tx_done_mask) { + /* Either PDC or interrupt transmission */ + UART_PUT_IDR(port, atmel_port->tx_done_mask); + tasklet_schedule(&atmel_port->tasklet); } } @@ -590,9 +673,15 @@ static void atmel_tx_dma(struct uart_port *port) UART_PUT_TPR(port, pdc->dma_addr + xmit->tail); UART_PUT_TCR(port, count); - /* re-enable PDC transmit and interrupts */ + /* re-enable PDC transmit */ UART_PUT_PTCR(port, ATMEL_PDC_TXTEN); - UART_PUT_IER(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE); + /* Enable interrupts */ + UART_PUT_IER(port, atmel_port->tx_done_mask); + } else { + if (atmel_port->rs485.flags & SER_RS485_ENABLED) { + /* DMA done, stop TX, start RX for RS485 */ + atmel_start_rx(port); + } } if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) @@ -1017,6 +1106,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, { unsigned long flags; unsigned int mode, imr, quot, baud; + struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); /* Get current mode register */ mode = UART_GET_MR(port) & ~(ATMEL_US_USCLKS | ATMEL_US_CHRL @@ -1115,6 +1205,17 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, /* disable receiver and transmitter */ UART_PUT_CR(port, ATMEL_US_TXDIS | ATMEL_US_RXDIS); + /* Resetting serial mode to RS232 (0x0) */ + mode &= ~ATMEL_US_USMODE; + + if (atmel_port->rs485.flags & SER_RS485_ENABLED) { + dev_dbg(port->dev, "Setting UART to RS485\n"); + UART_PUT_TTGR(port, atmel_port->rs485.delay_rts_before_send); + mode |= ATMEL_US_USMODE_RS485; + } else { + dev_dbg(port->dev, "Setting UART to RS232\n"); + } + /* set the parity, stop bits and data size */ UART_PUT_MR(port, mode); @@ -1231,6 +1332,35 @@ static void atmel_poll_put_char(struct uart_port *port, unsigned char ch) } #endif +static int +atmel_ioctl(struct uart_port *port, unsigned int cmd, unsigned long arg) +{ + struct serial_rs485 rs485conf; + + switch (cmd) { + case TIOCSRS485: + if (copy_from_user(&rs485conf, (struct serial_rs485 *) arg, + sizeof(rs485conf))) + return -EFAULT; + + atmel_config_rs485(port, &rs485conf); + break; + + case TIOCGRS485: + if (copy_to_user((struct serial_rs485 *) arg, + &(to_atmel_uart_port(port)->rs485), + sizeof(rs485conf))) + return -EFAULT; + break; + + default: + return -ENOIOCTLCMD; + } + return 0; +} + + + static struct uart_ops atmel_pops = { .tx_empty = atmel_tx_empty, .set_mctrl = atmel_set_mctrl, @@ -1250,6 +1380,7 @@ static struct uart_ops atmel_pops = { .config_port = atmel_config_port, .verify_port = atmel_verify_port, .pm = atmel_serial_pm, + .ioctl = atmel_ioctl, #ifdef CONFIG_CONSOLE_POLL .poll_get_char = atmel_poll_get_char, .poll_put_char = atmel_poll_put_char, @@ -1265,13 +1396,12 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, struct uart_port *port = &atmel_port->uart; struct atmel_uart_data *data = pdev->dev.platform_data; - port->iotype = UPIO_MEM; - port->flags = UPF_BOOT_AUTOCONF; - port->ops = &atmel_pops; - port->fifosize = 1; - port->line = pdev->id; - port->dev = &pdev->dev; - + port->iotype = UPIO_MEM; + port->flags = UPF_BOOT_AUTOCONF; + port->ops = &atmel_pops; + port->fifosize = 1; + port->line = pdev->id; + port->dev = &pdev->dev; port->mapbase = pdev->resource[0].start; port->irq = pdev->resource[1].start; @@ -1299,8 +1429,16 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, atmel_port->use_dma_rx = data->use_dma_rx; atmel_port->use_dma_tx = data->use_dma_tx; - if (atmel_use_dma_tx(port)) + atmel_port->rs485 = data->rs485; + /* Use TXEMPTY for interrupt when rs485 else TXRDY or ENDTX|TXBUFE */ + if (atmel_port->rs485.flags & SER_RS485_ENABLED) + atmel_port->tx_done_mask = ATMEL_US_TXEMPTY; + else if (atmel_use_dma_tx(port)) { port->fifosize = PDC_BUFFER_SIZE; + atmel_port->tx_done_mask = ATMEL_US_ENDTX | ATMEL_US_TXBUFE; + } else { + atmel_port->tx_done_mask = ATMEL_US_TXRDY; + } } /* @@ -1334,6 +1472,7 @@ static void atmel_console_putchar(struct uart_port *port, int ch) static void atmel_console_write(struct console *co, const char *s, u_int count) { struct uart_port *port = &atmel_ports[co->index].uart; + struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); unsigned int status, imr; unsigned int pdc_tx; @@ -1341,7 +1480,7 @@ static void atmel_console_write(struct console *co, const char *s, u_int count) * First, save IMR and then disable interrupts */ imr = UART_GET_IMR(port); - UART_PUT_IDR(port, ATMEL_US_RXRDY | ATMEL_US_TXRDY); + UART_PUT_IDR(port, ATMEL_US_RXRDY | atmel_port->tx_done_mask); /* Store PDC transmit status and disable it */ pdc_tx = UART_GET_PTSR(port) & ATMEL_PDC_TXTEN; -- cgit v0.10.2 From 956097912c40a03bf22603a3be73503fd9ea9e44 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Sun, 2 May 2010 08:03:54 +0200 Subject: ring-buffer: Wrap open-coded WARN_ONCE Wrap open-coded WARN_ONCE functionality into the equivalent macro. Signed-off-by: Borislav Petkov LKML-Reference: <20100502060354.GA5281@liondog.tnic> Signed-off-by: Steven Rostedt diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 2a09044..7f6059c 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -2000,17 +2000,13 @@ rb_add_time_stamp(struct ring_buffer_per_cpu *cpu_buffer, u64 *ts, u64 *delta) { struct ring_buffer_event *event; - static int once; int ret; - if (unlikely(*delta > (1ULL << 59) && !once++)) { - printk(KERN_WARNING "Delta way too big! %llu" - " ts=%llu write stamp = %llu\n", - (unsigned long long)*delta, - (unsigned long long)*ts, - (unsigned long long)cpu_buffer->write_stamp); - WARN_ON(1); - } + WARN_ONCE(*delta > (1ULL << 59), + KERN_WARNING "Delta way too big! %llu ts=%llu write stamp = %llu\n", + (unsigned long long)*delta, + (unsigned long long)*ts, + (unsigned long long)cpu_buffer->write_stamp); /* * The delta is too big, we to add a -- cgit v0.10.2 From f38406bbfc5e1d4bd9726454ecb60ba52aa9da11 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Mon, 3 May 2010 07:27:31 +0100 Subject: ARM: 6077/1: ux500: add SOC Kconfig variables This adds the different config options for SoCs DB8500 and DB5500 and refines the SoC/CPU detection code to support the DB5500 as well via these. The selection between DB5500 and DB8500 is currently a simple compile-time choice. Acked-by: Linus Walleij Acked-by: Srinidhi Kasagar Signed-off-by: Rabin Vincent Signed-off-by: Russell King diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig index cd412a3..699588f 100644 --- a/arch/arm/mach-ux500/Kconfig +++ b/arch/arm/mach-ux500/Kconfig @@ -1,16 +1,30 @@ +if ARCH_U8500 + +config UX500_SOC_COMMON + bool + default y + select ARM_GIC + select HAS_MTU + select NOMADIK_GPIO + +config UX500_SOC_DB8500 + bool + +config UX500_SOC_DB5500 + bool + menu "ST-Ericsson platform type" - depends on ARCH_U8500 comment "ST-Ericsson Multicore Mobile Platforms" config MACH_U8500_MOP bool "U8500 Early Development platform" default y - select ARM_GIC - select HAS_MTU - select NOMADIK_GPIO + select UX500_SOC_DB8500 help Include support for mop500 development platform based on U8500 architecture. The platform is based on early drop silicon version of 8500. endmenu + +endif diff --git a/arch/arm/mach-ux500/include/mach/hardware.h b/arch/arm/mach-ux500/include/mach/hardware.h index 99ca89f..d86b354 100644 --- a/arch/arm/mach-ux500/include/mach/hardware.h +++ b/arch/arm/mach-ux500/include/mach/hardware.h @@ -147,14 +147,23 @@ #include +static inline bool cpu_is_u8500(void) +{ +#ifdef CONFIG_UX500_SOC_DB8500 + return 1; +#else + return 0; +#endif +} + static inline bool cpu_is_u8500ed(void) { - return (read_cpuid_id() & 15) == 0; + return cpu_is_u8500() && (read_cpuid_id() & 15) == 0; } static inline bool cpu_is_u8500v1(void) { - return (read_cpuid_id() & 15) == 1; + return cpu_is_u8500() && (read_cpuid_id() & 15) == 1; } #endif -- cgit v0.10.2 From c9c0957286e73d01e98503f714d32180e6963757 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Mon, 3 May 2010 07:34:53 +0100 Subject: ARM: 6078/1: ux500: add per-SoC register definitions Split up all the hardware register definitions previously found in hardware.h into per-SoC files db8500-regs.h and db5500-regs.h. Rename a couple of macros to prepare for sharing code between the variants. Acked-by: Linus Walleij Acked-by: Srinidhi Kasagar Signed-off-by: Rabin Vincent Signed-off-by: Russell King diff --git a/arch/arm/mach-ux500/cpu-u8500.c b/arch/arm/mach-ux500/cpu-u8500.c index 979f1c3..8919af4 100644 --- a/arch/arm/mach-ux500/cpu-u8500.c +++ b/arch/arm/mach-ux500/cpu-u8500.c @@ -124,10 +124,10 @@ static struct map_desc u8500_io_desc[] __initdata = { __IO_DEV_DESC(U8500_CLKRST3_BASE, SZ_4K), __IO_DEV_DESC(U8500_CLKRST5_BASE, SZ_4K), __IO_DEV_DESC(U8500_CLKRST6_BASE, SZ_4K), + __IO_DEV_DESC(U8500_GPIO0_BASE, SZ_4K), __IO_DEV_DESC(U8500_GPIO1_BASE, SZ_4K), __IO_DEV_DESC(U8500_GPIO2_BASE, SZ_4K), __IO_DEV_DESC(U8500_GPIO3_BASE, SZ_4K), - __IO_DEV_DESC(U8500_GPIO5_BASE, SZ_4K), __IO_DEV_DESC(U8500_L2CC_BASE, SZ_4K), }; @@ -137,7 +137,7 @@ static struct map_desc u8500ed_io_desc[] __initdata = { }; static struct map_desc u8500v1_io_desc[] __initdata = { - __IO_DEV_DESC(U8500_MTU0_BASE_V1, SZ_4K), + __IO_DEV_DESC(U8500_MTU0_BASE, SZ_4K), }; void __init u8500_map_io(void) @@ -177,7 +177,7 @@ static void __init u8500_timer_init(void) if (cpu_is_u8500ed()) mtu_base = __io_address(U8500_MTU0_BASE_ED); else - mtu_base = __io_address(U8500_MTU0_BASE_V1); + mtu_base = __io_address(U8500_MTU0_BASE); nmdk_timer_init(); } diff --git a/arch/arm/mach-ux500/include/mach/db5500-regs.h b/arch/arm/mach-ux500/include/mach/db5500-regs.h new file mode 100644 index 0000000..545c80f --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/db5500-regs.h @@ -0,0 +1,103 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * License terms: GNU General Public License (GPL) version 2 + */ + +#ifndef __MACH_DB5500_REGS_H +#define __MACH_DB5500_REGS_H + +#define U5500_PER1_BASE 0xA0020000 +#define U5500_PER2_BASE 0xA0010000 +#define U5500_PER3_BASE 0x80140000 +#define U5500_PER4_BASE 0x80150000 +#define U5500_PER5_BASE 0x80100000 +#define U5500_PER6_BASE 0x80120000 + +#define U5500_GIC_DIST_BASE 0xA0411000 +#define U5500_GIC_CPU_BASE 0xA0410100 +#define U5500_DMA_BASE 0x90030000 +#define U5500_MCDE_BASE 0xA0400000 +#define U5500_MODEM_BASE 0xB0000000 +#define U5500_L2CC_BASE 0xA0412000 +#define U5500_SCU_BASE 0xA0410000 +#define U5500_DSI1_BASE 0xA0401000 +#define U5500_DSI2_BASE 0xA0402000 +#define U5500_SIA_BASE 0xA0100000 +#define U5500_SVA_BASE 0x80200000 +#define U5500_HSEM_BASE 0xA0000000 +#define U5500_NAND0_BASE 0x60000000 +#define U5500_NAND1_BASE 0x70000000 +#define U5500_TWD_BASE 0xa0410600 +#define U5500_B2R2_BASE 0xa0200000 + +#define U5500_FSMC_BASE (U5500_PER1_BASE + 0x0000) +#define U5500_SDI0_BASE (U5500_PER1_BASE + 0x1000) +#define U5500_SDI2_BASE (U5500_PER1_BASE + 0x2000) +#define U5500_UART0_BASE (U5500_PER1_BASE + 0x3000) +#define U5500_I2C1_BASE (U5500_PER1_BASE + 0x4000) +#define U5500_MSP0_BASE (U5500_PER1_BASE + 0x5000) +#define U5500_GPIO0_BASE (U5500_PER1_BASE + 0xE000) +#define U5500_CLKRST1_BASE (U5500_PER1_BASE + 0xF000) + +#define U5500_USBOTG_BASE (U5500_PER2_BASE + 0x0000) +#define U5500_GPIO1_BASE (U5500_PER2_BASE + 0xE000) +#define U5500_CLKRST2_BASE (U5500_PER2_BASE + 0xF000) + +#define U5500_KEYPAD_BASE (U5500_PER3_BASE + 0x0000) +#define U5500_PWM_BASE (U5500_PER3_BASE + 0x1000) +#define U5500_GPIO3_BASE (U5500_PER3_BASE + 0xE000) +#define U5500_CLKRST3_BASE (U5500_PER3_BASE + 0xF000) + +#define U5500_BACKUPRAM0_BASE (U5500_PER4_BASE + 0x0000) +#define U5500_BACKUPRAM1_BASE (U5500_PER4_BASE + 0x1000) +#define U5500_RTT0_BASE (U5500_PER4_BASE + 0x2000) +#define U5500_RTT1_BASE (U5500_PER4_BASE + 0x3000) +#define U5500_RTC_BASE (U5500_PER4_BASE + 0x4000) +#define U5500_SCR_BASE (U5500_PER4_BASE + 0x5000) +#define U5500_DMC_BASE (U5500_PER4_BASE + 0x6000) +#define U5500_PRCMU_BASE (U5500_PER4_BASE + 0x7000) +#define U5500_MSP1_BASE (U5500_PER4_BASE + 0x9000) +#define U5500_GPIO2_BASE (U5500_PER4_BASE + 0xA000) +#define U5500_CDETECT_BASE (U5500_PER4_BASE + 0xF000) + +#define U5500_SPI0_BASE (U5500_PER5_BASE + 0x0000) +#define U5500_SPI1_BASE (U5500_PER5_BASE + 0x1000) +#define U5500_SPI2_BASE (U5500_PER5_BASE + 0x2000) +#define U5500_SPI3_BASE (U5500_PER5_BASE + 0x3000) +#define U5500_UART1_BASE (U5500_PER5_BASE + 0x4000) +#define U5500_UART2_BASE (U5500_PER5_BASE + 0x5000) +#define U5500_UART3_BASE (U5500_PER5_BASE + 0x6000) +#define U5500_SDI1_BASE (U5500_PER5_BASE + 0x7000) +#define U5500_SDI3_BASE (U5500_PER5_BASE + 0x8000) +#define U5500_SDI4_BASE (U5500_PER5_BASE + 0x9000) +#define U5500_I2C2_BASE (U5500_PER5_BASE + 0xA000) +#define U5500_I2C3_BASE (U5500_PER5_BASE + 0xB000) +#define U5500_MSP2_BASE (U5500_PER5_BASE + 0xC000) +#define U5500_IRDA_BASE (U5500_PER5_BASE + 0xD000) +#define U5500_IRRC_BASE (U5500_PER5_BASE + 0x10000) +#define U5500_GPIO4_BASE (U5500_PER5_BASE + 0x1E000) +#define U5500_CLKRST5_BASE (U5500_PER5_BASE + 0x1F000) + +#define U5500_RNG_BASE (U5500_PER6_BASE + 0x0000) +#define U5500_HASH0_BASE (U5500_PER6_BASE + 0x1000) +#define U5500_HASH1_BASE (U5500_PER6_BASE + 0x2000) +#define U5500_PKA_BASE (U5500_PER6_BASE + 0x4000) +#define U5500_PKAM_BASE (U5500_PER6_BASE + 0x5000) +#define U5500_MTU0_BASE (U5500_PER6_BASE + 0x6000) +#define U5500_MTU1_BASE (U5500_PER6_BASE + 0x7000) +#define U5500_CR_BASE (U5500_PER6_BASE + 0x8000) +#define U5500_CRYP0_BASE (U5500_PER6_BASE + 0xA000) +#define U5500_CRYP1_BASE (U5500_PER6_BASE + 0xB000) +#define U5500_CLKRST6_BASE (U5500_PER6_BASE + 0xF000) + +#define U5500_GPIOBANK0_BASE U5500_GPIO0_BASE +#define U5500_GPIOBANK1_BASE (U5500_GPIO0_BASE + 0x80) +#define U5500_GPIOBANK2_BASE U5500_GPIO1_BASE +#define U5500_GPIOBANK3_BASE U5500_GPIO2_BASE +#define U5500_GPIOBANK4_BASE U5500_GPIO3_BASE +#define U5500_GPIOBANK5_BASE U5500_GPIO4_BASE +#define U5500_GPIOBANK6_BASE (U5500_GPIO4_BASE + 0x80) +#define U5500_GPIOBANK7_BASE (U5500_GPIO4_BASE + 0x100) + +#endif diff --git a/arch/arm/mach-ux500/include/mach/db8500-regs.h b/arch/arm/mach-ux500/include/mach/db8500-regs.h new file mode 100644 index 0000000..9169e1e --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/db8500-regs.h @@ -0,0 +1,135 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * License terms: GNU General Public License (GPL) version 2 + */ + +#ifndef __MACH_DB8500_REGS_H +#define __MACH_DB8500_REGS_H + +#define U8500_PER3_BASE 0x80000000 +#define U8500_STM_BASE 0x80100000 +#define U8500_STM_REG_BASE (U8500_STM_BASE + 0xF000) +#define U8500_PER2_BASE 0x80110000 +#define U8500_PER1_BASE 0x80120000 +#define U8500_B2R2_BASE 0x80130000 +#define U8500_HSEM_BASE 0x80140000 +#define U8500_PER4_BASE 0x80150000 +#define U8500_ICN_BASE 0x81000000 + +#define U8500_BOOT_ROM_BASE 0x90000000 +/* ASIC ID is at 0xff4 offset within this region */ +#define U8500_ASIC_ID_BASE 0x9001F000 + +#define U8500_PER6_BASE 0xa03c0000 +#define U8500_PER5_BASE 0xa03e0000 +#define U8500_PER7_BASE_ED 0xa03d0000 + +#define U8500_SVA_BASE 0xa0100000 +#define U8500_SIA_BASE 0xa0200000 + +#define U8500_SGA_BASE 0xa0300000 +#define U8500_MCDE_BASE 0xa0350000 +#define U8500_DMA_BASE_ED 0xa0362000 +#define U8500_DMA_BASE 0x801C0000 /* v1 */ + +#define U8500_SBAG_BASE 0xa0390000 + +#define U8500_SCU_BASE 0xa0410000 +#define U8500_GIC_CPU_BASE 0xa0410100 +#define U8500_TWD_BASE 0xa0410600 +#define U8500_GIC_DIST_BASE 0xa0411000 +#define U8500_L2CC_BASE 0xa0412000 + +#define U8500_MODEM_I2C 0xb7e02000 + +#define U8500_GPIO0_BASE (U8500_PER1_BASE + 0xE000) +#define U8500_GPIO1_BASE (U8500_PER3_BASE + 0xE000) +#define U8500_GPIO2_BASE (U8500_PER2_BASE + 0xE000) +#define U8500_GPIO3_BASE (U8500_PER5_BASE + 0x1E000) + +/* per7 base addressess */ +#define U8500_CR_BASE_ED (U8500_PER7_BASE_ED + 0x8000) +#define U8500_MTU0_BASE_ED (U8500_PER7_BASE_ED + 0xa000) +#define U8500_MTU1_BASE_ED (U8500_PER7_BASE_ED + 0xb000) +#define U8500_TZPC0_BASE_ED (U8500_PER7_BASE_ED + 0xc000) +#define U8500_CLKRST7_BASE_ED (U8500_PER7_BASE_ED + 0xf000) + +#define U8500_UART0_BASE (U8500_PER1_BASE + 0x0000) +#define U8500_UART1_BASE (U8500_PER1_BASE + 0x1000) + +/* per6 base addressess */ +#define U8500_RNG_BASE (U8500_PER6_BASE + 0x0000) +#define U8500_PKA_BASE (U8500_PER6_BASE + 0x1000) +#define U8500_PKAM_BASE (U8500_PER6_BASE + 0x2000) +#define U8500_MTU0_BASE (U8500_PER6_BASE + 0x6000) /* v1 */ +#define U8500_MTU1_BASE (U8500_PER6_BASE + 0x7000) /* v1 */ +#define U8500_CR_BASE (U8500_PER6_BASE + 0x8000) /* v1 */ +#define U8500_CRYPTO0_BASE (U8500_PER6_BASE + 0xa000) +#define U8500_CRYPTO1_BASE (U8500_PER6_BASE + 0xb000) +#define U8500_CLKRST6_BASE (U8500_PER6_BASE + 0xf000) + +/* per5 base addressess */ +#define U8500_USBOTG_BASE (U8500_PER5_BASE + 0x00000) +#define U8500_CLKRST5_BASE (U8500_PER5_BASE + 0x1f000) + +/* per4 base addressess */ +#define U8500_BACKUPRAM0_BASE (U8500_PER4_BASE + 0x00000) +#define U8500_BACKUPRAM1_BASE (U8500_PER4_BASE + 0x01000) +#define U8500_RTT0_BASE (U8500_PER4_BASE + 0x02000) +#define U8500_RTT1_BASE (U8500_PER4_BASE + 0x03000) +#define U8500_RTC_BASE (U8500_PER4_BASE + 0x04000) +#define U8500_SCR_BASE (U8500_PER4_BASE + 0x05000) +#define U8500_DMC_BASE (U8500_PER4_BASE + 0x06000) +#define U8500_PRCMU_BASE (U8500_PER4_BASE + 0x07000) +#define U8500_PRCMU_TCDM_BASE (U8500_PER4_BASE + 0x0f000) + +/* per3 base addresses */ +#define U8500_FSMC_BASE (U8500_PER3_BASE + 0x0000) +#define U8500_SSP0_BASE (U8500_PER3_BASE + 0x2000) +#define U8500_SSP1_BASE (U8500_PER3_BASE + 0x3000) +#define U8500_I2C0_BASE (U8500_PER3_BASE + 0x4000) +#define U8500_SDI2_BASE (U8500_PER3_BASE + 0x5000) +#define U8500_SKE_BASE (U8500_PER3_BASE + 0x6000) +#define U8500_UART2_BASE (U8500_PER3_BASE + 0x7000) +#define U8500_SDI5_BASE (U8500_PER3_BASE + 0x8000) +#define U8500_CLKRST3_BASE (U8500_PER3_BASE + 0xf000) + +/* per2 base addressess */ +#define U8500_I2C3_BASE (U8500_PER2_BASE + 0x0000) +#define U8500_SPI2_BASE (U8500_PER2_BASE + 0x1000) +#define U8500_SPI1_BASE (U8500_PER2_BASE + 0x2000) +#define U8500_PWL_BASE (U8500_PER2_BASE + 0x3000) +#define U8500_SDI4_BASE (U8500_PER2_BASE + 0x4000) +#define U8500_MSP2_BASE (U8500_PER2_BASE + 0x7000) +#define U8500_SDI1_BASE (U8500_PER2_BASE + 0x8000) +#define U8500_SDI3_BASE (U8500_PER2_BASE + 0x9000) +#define U8500_SPI0_BASE (U8500_PER2_BASE + 0xa000) +#define U8500_HSIR_BASE (U8500_PER2_BASE + 0xb000) +#define U8500_HSIT_BASE (U8500_PER2_BASE + 0xc000) +#define U8500_CLKRST2_BASE (U8500_PER2_BASE + 0xf000) + +/* per1 base addresses */ +#define U8500_I2C1_BASE (U8500_PER1_BASE + 0x2000) +#define U8500_MSP0_BASE (U8500_PER1_BASE + 0x3000) +#define U8500_MSP1_BASE (U8500_PER1_BASE + 0x4000) +#define U8500_SDI0_BASE (U8500_PER1_BASE + 0x6000) +#define U8500_I2C2_BASE (U8500_PER1_BASE + 0x8000) +#define U8500_SPI3_BASE (U8500_PER1_BASE + 0x9000) +#define U8500_I2C4_BASE (U8500_PER1_BASE + 0xa000) +#define U8500_SLIM0_BASE (U8500_PER1_BASE + 0xb000) +#define U8500_CLKRST1_BASE (U8500_PER1_BASE + 0xf000) + +#define U8500_SHRM_GOP_INTERRUPT_BASE 0xB7C00040 + +#define U8500_GPIOBANK0_BASE U8500_GPIO0_BASE +#define U8500_GPIOBANK1_BASE (U8500_GPIO0_BASE + 0x80) +#define U8500_GPIOBANK2_BASE U8500_GPIO1_BASE +#define U8500_GPIOBANK3_BASE (U8500_GPIO1_BASE + 0x80) +#define U8500_GPIOBANK4_BASE (U8500_GPIO1_BASE + 0x100) +#define U8500_GPIOBANK5_BASE (U8500_GPIO1_BASE + 0x180) +#define U8500_GPIOBANK6_BASE U8500_GPIO2_BASE +#define U8500_GPIOBANK7_BASE (U8500_GPIO2_BASE + 0x80) +#define U8500_GPIOBANK8_BASE U8500_GPIO3_BASE + +#endif diff --git a/arch/arm/mach-ux500/include/mach/hardware.h b/arch/arm/mach-ux500/include/mach/hardware.h index d86b354..1353f17 100644 --- a/arch/arm/mach-ux500/include/mach/hardware.h +++ b/arch/arm/mach-ux500/include/mach/hardware.h @@ -26,119 +26,67 @@ /* used by some plat-nomadik code */ #define io_p2v(n) __io_address(n) -/* - * Base address definitions for U8500 Onchip IPs. All the - * peripherals are contained in a single 1 Mbyte region, with - * AHB peripherals at the bottom and APB peripherals at the - * top of the region. PER stands for PERIPHERAL region which - * itself divided into sub regions. - */ -#define U8500_PER3_BASE 0x80000000 -#define U8500_PER2_BASE 0x80110000 -#define U8500_PER1_BASE 0x80120000 -#define U8500_PER4_BASE 0x80150000 - -#define U8500_PER6_BASE 0xa03c0000 -#define U8500_PER5_BASE 0xa03e0000 -#define U8500_PER7_BASE 0xa03d0000 - -#define U8500_SVA_BASE 0xa0100000 -#define U8500_SIA_BASE 0xa0200000 - -#define U8500_SGA_BASE 0xa0300000 -#define U8500_MCDE_BASE 0xa0350000 -#define U8500_DMA_BASE 0xa0362000 - -#define U8500_SCU_BASE 0xa0410000 -#define U8500_GIC_CPU_BASE 0xa0410100 -#define U8500_TWD_BASE 0xa0410600 -#define U8500_GIC_DIST_BASE 0xa0411000 -#define U8500_L2CC_BASE 0xa0412000 - -#define U8500_TWD_SIZE 0x100 - -/* per7 base addressess */ -#define U8500_CR_BASE_ED (U8500_PER7_BASE + 0x8000) -#define U8500_MTU0_BASE_ED (U8500_PER7_BASE + 0xa000) -#define U8500_MTU1_BASE_ED (U8500_PER7_BASE + 0xb000) -#define U8500_TZPC0_BASE_ED (U8500_PER7_BASE + 0xc000) -#define U8500_CLKRST7_BASE_ED (U8500_PER7_BASE + 0xf000) - -/* per6 base addressess */ -#define U8500_RNG_BASE (U8500_PER6_BASE + 0x0000) -#define U8500_PKA_BASE (U8500_PER6_BASE + 0x1000) -#define U8500_PKAM_BASE (U8500_PER6_BASE + 0x2000) -#define U8500_MTU0_BASE_V1 (U8500_PER6_BASE + 0x6000) -#define U8500_MTU1_BASE_V1 (U8500_PER6_BASE + 0x7000) -#define U8500_CR_BASE_V1 (U8500_PER6_BASE + 0x8000) -#define U8500_CRYPTO0_BASE (U8500_PER6_BASE + 0xa000) -#define U8500_CRYPTO1_BASE (U8500_PER6_BASE + 0xb000) -#define U8500_CLKRST6_BASE (U8500_PER6_BASE + 0xf000) - -/* per5 base addressess */ -#define U8500_USBOTG_BASE (U8500_PER5_BASE + 0x00000) -#define U8500_GPIO5_BASE (U8500_PER5_BASE + 0x1e000) -#define U8500_CLKRST5_BASE (U8500_PER5_BASE + 0x1f000) - -/* per4 base addressess */ -#define U8500_BACKUPRAM0_BASE (U8500_PER4_BASE + 0x0000) -#define U8500_BACKUPRAM1_BASE (U8500_PER4_BASE + 0x1000) -#define U8500_RTT0_BASE (U8500_PER4_BASE + 0x2000) -#define U8500_RTT1_BASE (U8500_PER4_BASE + 0x3000) -#define U8500_RTC_BASE (U8500_PER4_BASE + 0x4000) -#define U8500_SCR_BASE (U8500_PER4_BASE + 0x5000) -#define U8500_DMC_BASE (U8500_PER4_BASE + 0x6000) -#define U8500_PRCMU_BASE (U8500_PER4_BASE + 0x7000) - -/* per3 base addressess */ -#define U8500_FSMC_BASE (U8500_PER3_BASE + 0x0000) -#define U8500_SSP0_BASE (U8500_PER3_BASE + 0x2000) -#define U8500_SSP1_BASE (U8500_PER3_BASE + 0x3000) -#define U8500_I2C0_BASE (U8500_PER3_BASE + 0x4000) -#define U8500_SDI2_BASE (U8500_PER3_BASE + 0x5000) -#define U8500_SKE_BASE (U8500_PER3_BASE + 0x6000) -#define U8500_UART2_BASE (U8500_PER3_BASE + 0x7000) -#define U8500_SDI5_BASE (U8500_PER3_BASE + 0x8000) -#define U8500_GPIO3_BASE (U8500_PER3_BASE + 0xe000) -#define U8500_CLKRST3_BASE (U8500_PER3_BASE + 0xf000) - -/* per2 base addressess */ -#define U8500_I2C3_BASE (U8500_PER2_BASE + 0x0000) -#define U8500_SPI2_BASE (U8500_PER2_BASE + 0x1000) -#define U8500_SPI1_BASE (U8500_PER2_BASE + 0x2000) -#define U8500_PWL_BASE (U8500_PER2_BASE + 0x3000) -#define U8500_SDI4_BASE (U8500_PER2_BASE + 0x4000) -#define U8500_MSP2_BASE (U8500_PER2_BASE + 0x7000) -#define U8500_SDI1_BASE (U8500_PER2_BASE + 0x8000) -#define U8500_SDI3_BASE (U8500_PER2_BASE + 0x9000) -#define U8500_SPI0_BASE (U8500_PER2_BASE + 0xa000) -#define U8500_HSIR_BASE (U8500_PER2_BASE + 0xb000) -#define U8500_HSIT_BASE (U8500_PER2_BASE + 0xc000) -#define U8500_GPIO2_BASE (U8500_PER2_BASE + 0xe000) -#define U8500_CLKRST2_BASE (U8500_PER2_BASE + 0xf000) - -/* per1 base addresses */ -#define U8500_UART0_BASE (U8500_PER1_BASE + 0x0000) -#define U8500_UART1_BASE (U8500_PER1_BASE + 0x1000) -#define U8500_I2C1_BASE (U8500_PER1_BASE + 0x2000) -#define U8500_MSP0_BASE (U8500_PER1_BASE + 0x3000) -#define U8500_MSP1_BASE (U8500_PER1_BASE + 0x4000) -#define U8500_SDI0_BASE (U8500_PER1_BASE + 0x6000) -#define U8500_I2C2_BASE (U8500_PER1_BASE + 0x8000) -#define U8500_SPI3_BASE (U8500_PER1_BASE + 0x9000) -#define U8500_SLIM0_BASE (U8500_PER1_BASE + 0xa000) -#define U8500_GPIO1_BASE (U8500_PER1_BASE + 0xe000) -#define U8500_CLKRST1_BASE (U8500_PER1_BASE + 0xf000) - -#define U8500_GPIOBANK0_BASE U8500_GPIO1_BASE -#define U8500_GPIOBANK1_BASE (U8500_GPIO1_BASE + 0x80) -#define U8500_GPIOBANK2_BASE U8500_GPIO3_BASE -#define U8500_GPIOBANK3_BASE (U8500_GPIO3_BASE + 0x80) -#define U8500_GPIOBANK4_BASE (U8500_GPIO3_BASE + 0x100) -#define U8500_GPIOBANK5_BASE (U8500_GPIO3_BASE + 0x180) -#define U8500_GPIOBANK6_BASE U8500_GPIO2_BASE -#define U8500_GPIOBANK7_BASE (U8500_GPIO2_BASE + 0x80) -#define U8500_GPIOBANK8_BASE U8500_GPIO5_BASE +#include +#include + +#ifdef CONFIG_UX500_SOC_DB8500 +#define UX500(periph) U8500_##periph##_BASE +#elif defined(CONFIG_UX500_SOC_DB5500) +#define UX500(periph) U5500_##periph##_BASE +#endif + +#define UX500_BACKUPRAM0_BASE UX500(BACKUPRAM0) +#define UX500_BACKUPRAM1_BASE UX500(BACKUPRAM1) +#define UX500_B2R2_BASE UX500(B2R2) + +#define UX500_CLKRST1_BASE UX500(CLKRST1) +#define UX500_CLKRST2_BASE UX500(CLKRST2) +#define UX500_CLKRST3_BASE UX500(CLKRST3) +#define UX500_CLKRST5_BASE UX500(CLKRST5) +#define UX500_CLKRST6_BASE UX500(CLKRST6) + +#define UX500_DMA_BASE UX500(DMA) +#define UX500_FSMC_BASE UX500(FSMC) + +#define UX500_GIC_CPU_BASE UX500(GIC_CPU) +#define UX500_GIC_DIST_BASE UX500(GIC_DIST) + +#define UX500_I2C1_BASE UX500(I2C1) +#define UX500_I2C2_BASE UX500(I2C2) +#define UX500_I2C3_BASE UX500(I2C3) + +#define UX500_L2CC_BASE UX500(L2CC) +#define UX500_MCDE_BASE UX500(MCDE) +#define UX500_MTU0_BASE UX500(MTU0) +#define UX500_MTU1_BASE UX500(MTU1) +#define UX500_PRCMU_BASE UX500(PRCMU) + +#define UX500_RNG_BASE UX500(RNG) +#define UX500_RTC_BASE UX500(RTC) + +#define UX500_SCU_BASE UX500(SCU) + +#define UX500_SDI0_BASE UX500(SDI0) +#define UX500_SDI1_BASE UX500(SDI1) +#define UX500_SDI2_BASE UX500(SDI2) +#define UX500_SDI3_BASE UX500(SDI3) +#define UX500_SDI4_BASE UX500(SDI4) + +#define UX500_SPI0_BASE UX500(SPI0) +#define UX500_SPI1_BASE UX500(SPI1) +#define UX500_SPI2_BASE UX500(SPI2) +#define UX500_SPI3_BASE UX500(SPI3) + +#define UX500_SIA_BASE UX500(SIA) +#define UX500_SVA_BASE UX500(SVA) + +#define UX500_TWD_BASE UX500(TWD) + +#define UX500_UART0_BASE UX500(UART0) +#define UX500_UART1_BASE UX500(UART1) +#define UX500_UART2_BASE UX500(UART2) + +#define UX500_USBOTG_BASE UX500(USBOTG) /* ST-Ericsson modified pl022 id */ #define SSP_PER_ID 0x01080022 -- cgit v0.10.2 From 39a982b4cda1b9c129094a411962348827412d50 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Mon, 3 May 2010 07:38:06 +0100 Subject: ARM: 6079/1: ux500: allow choice of the DEBUG_LL UART Allow the UART used for DEBUG_LL to be selected. Acked-by: Linus Walleij Acked-by: Srinidhi Kasagar Signed-off-by: Rabin Vincent Signed-off-by: Russell King diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig index 699588f..8ad5ee8 100644 --- a/arch/arm/mach-ux500/Kconfig +++ b/arch/arm/mach-ux500/Kconfig @@ -27,4 +27,11 @@ config MACH_U8500_MOP on early drop silicon version of 8500. endmenu +config UX500_DEBUG_UART + int "Ux500 UART to use for low-level debug" + default 2 + help + Choose the UART on which kernel low-level debug messages should be + output. + endif diff --git a/arch/arm/mach-ux500/include/mach/debug-macro.S b/arch/arm/mach-ux500/include/mach/debug-macro.S index 09cbfda..c5203b7 100644 --- a/arch/arm/mach-ux500/include/mach/debug-macro.S +++ b/arch/arm/mach-ux500/include/mach/debug-macro.S @@ -10,11 +10,19 @@ */ #include +#if CONFIG_UX500_DEBUG_UART > 2 +#error Invalid Ux500 debug UART +#endif + +#define __UX500_UART(n) UX500_UART##n##_BASE +#define UX500_UART(n) __UX500_UART(n) +#define UART_BASE UX500_UART(CONFIG_UX500_DEBUG_UART) + .macro addruart, rx, tmp mrc p15, 0, \rx, c1, c0 tst \rx, #1 @ MMU enabled? - ldreq \rx, =U8500_UART2_BASE @ no, physical address - ldrne \rx, =IO_ADDRESS(U8500_UART2_BASE) @ yes, virtual address + ldreq \rx, =UART_BASE @ no, physical address + ldrne \rx, =IO_ADDRESS(UART_BASE) @ yes, virtual address .endm #include -- cgit v0.10.2 From 178980f98eef58607647eb66e178bf984bf81f4c Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Mon, 3 May 2010 07:39:02 +0100 Subject: ARM: 6080/1: ux500: move irq and common maps to cpu.c Move IRQ initialization and common io mapping setup code to cpu.c, renaming U8500* to UX500* along the way. Acked-by: Linus Walleij Acked-by: Srinidhi Kasagar Signed-off-by: Rabin Vincent Signed-off-by: Russell King diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index 95e6e24..6deee85 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux kernel, U8500 machine. # -obj-y := clock.o +obj-y := clock.o cpu.o obj-$(CONFIG_ARCH_U8500) += cpu-u8500.o obj-$(CONFIG_MACH_U8500_MOP) += board-mop500.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o localtimer.o diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 4335186..9ca4709 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -221,7 +221,7 @@ MACHINE_START(U8500, "ST-Ericsson MOP500 platform") .io_pg_offst = (IO_ADDRESS(U8500_UART2_BASE) >> 18) & 0xfffc, .boot_params = 0x100, .map_io = u8500_map_io, - .init_irq = u8500_init_irq, + .init_irq = ux500_init_irq, /* we re-use nomadik timer here */ .timer = &u8500_timer, .init_machine = u8500_init_machine, diff --git a/arch/arm/mach-ux500/cpu-u8500.c b/arch/arm/mach-ux500/cpu-u8500.c index 8919af4..2c8aa93 100644 --- a/arch/arm/mach-ux500/cpu-u8500.c +++ b/arch/arm/mach-ux500/cpu-u8500.c @@ -18,9 +18,7 @@ #include #include -#include #include -#include #include #include #include @@ -103,32 +101,13 @@ static struct platform_device *platform_devs[] __initdata = { &u8500_gpio_devs[8], }; -#define __IO_DEV_DESC(x, sz) { \ - .virtual = IO_ADDRESS(x), \ - .pfn = __phys_to_pfn(x), \ - .length = sz, \ - .type = MT_DEVICE, \ -} - /* minimum static i/o mapping required to boot U8500 platforms */ static struct map_desc u8500_io_desc[] __initdata = { - __IO_DEV_DESC(U8500_UART2_BASE, SZ_4K), - __IO_DEV_DESC(U8500_GIC_CPU_BASE, SZ_4K), - __IO_DEV_DESC(U8500_GIC_DIST_BASE, SZ_4K), - __IO_DEV_DESC(U8500_TWD_BASE, SZ_4K), - __IO_DEV_DESC(U8500_SCU_BASE, SZ_4K), - __IO_DEV_DESC(U8500_BACKUPRAM0_BASE, SZ_8K), __IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K), - __IO_DEV_DESC(U8500_CLKRST1_BASE, SZ_4K), - __IO_DEV_DESC(U8500_CLKRST2_BASE, SZ_4K), - __IO_DEV_DESC(U8500_CLKRST3_BASE, SZ_4K), - __IO_DEV_DESC(U8500_CLKRST5_BASE, SZ_4K), - __IO_DEV_DESC(U8500_CLKRST6_BASE, SZ_4K), __IO_DEV_DESC(U8500_GPIO0_BASE, SZ_4K), __IO_DEV_DESC(U8500_GPIO1_BASE, SZ_4K), __IO_DEV_DESC(U8500_GPIO2_BASE, SZ_4K), __IO_DEV_DESC(U8500_GPIO3_BASE, SZ_4K), - __IO_DEV_DESC(U8500_L2CC_BASE, SZ_4K), }; static struct map_desc u8500ed_io_desc[] __initdata = { @@ -142,6 +121,8 @@ static struct map_desc u8500v1_io_desc[] __initdata = { void __init u8500_map_io(void) { + ux500_map_io(); + iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc)); if (cpu_is_u8500ed()) @@ -150,12 +131,6 @@ void __init u8500_map_io(void) iotable_init(u8500v1_io_desc, ARRAY_SIZE(u8500v1_io_desc)); } -void __init u8500_init_irq(void) -{ - gic_dist_init(0, __io_address(U8500_GIC_DIST_BASE), 29); - gic_cpu_init(0, __io_address(U8500_GIC_CPU_BASE)); -} - /* * This function is called from the board init */ @@ -185,18 +160,3 @@ static void __init u8500_timer_init(void) struct sys_timer u8500_timer = { .init = u8500_timer_init, }; - -#ifdef CONFIG_CACHE_L2X0 -static int u8500_l2x0_init(void) -{ - void __iomem *l2x0_base; - - l2x0_base = __io_address(U8500_L2CC_BASE); - - /* 64KB way size, 8 way associativity, force WA */ - l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff); - - return 0; -} -early_initcall(u8500_l2x0_init); -#endif diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c new file mode 100644 index 0000000..e6a8058 --- /dev/null +++ b/arch/arm/mach-ux500/cpu.c @@ -0,0 +1,68 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Rabin Vincent for ST-Ericsson + * License terms: GNU General Public License (GPL) version 2 + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "clock.h" + +static struct map_desc ux500_io_desc[] __initdata = { + __IO_DEV_DESC(UX500_UART0_BASE, SZ_4K), + __IO_DEV_DESC(UX500_UART2_BASE, SZ_4K), + + __IO_DEV_DESC(UX500_GIC_CPU_BASE, SZ_4K), + __IO_DEV_DESC(UX500_GIC_DIST_BASE, SZ_4K), + __IO_DEV_DESC(UX500_L2CC_BASE, SZ_4K), + __IO_DEV_DESC(UX500_TWD_BASE, SZ_4K), + __IO_DEV_DESC(UX500_SCU_BASE, SZ_4K), + + __IO_DEV_DESC(UX500_CLKRST1_BASE, SZ_4K), + __IO_DEV_DESC(UX500_CLKRST2_BASE, SZ_4K), + __IO_DEV_DESC(UX500_CLKRST3_BASE, SZ_4K), + __IO_DEV_DESC(UX500_CLKRST5_BASE, SZ_4K), + __IO_DEV_DESC(UX500_CLKRST6_BASE, SZ_4K), + + __IO_DEV_DESC(UX500_MTU0_BASE, SZ_4K), + __IO_DEV_DESC(UX500_MTU1_BASE, SZ_4K), + + __IO_DEV_DESC(UX500_BACKUPRAM0_BASE, SZ_8K), +}; + +void __init ux500_map_io(void) +{ + iotable_init(ux500_io_desc, ARRAY_SIZE(ux500_io_desc)); +} + +void __init ux500_init_irq(void) +{ + gic_dist_init(0, __io_address(UX500_GIC_DIST_BASE), 29); + gic_cpu_init(0, __io_address(UX500_GIC_CPU_BASE)); +} + +#ifdef CONFIG_CACHE_L2X0 +static int ux500_l2x0_init(void) +{ + void __iomem *l2x0_base; + + l2x0_base = __io_address(UX500_L2CC_BASE); + + /* 64KB way size, 8 way associativity, force WA */ + l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff); + + return 0; +} +early_initcall(ux500_l2x0_init); +#endif diff --git a/arch/arm/mach-ux500/include/mach/setup.h b/arch/arm/mach-ux500/include/mach/setup.h index 65112bf..6c4c348 100644 --- a/arch/arm/mach-ux500/include/mach/setup.h +++ b/arch/arm/mach-ux500/include/mach/setup.h @@ -14,13 +14,22 @@ #include #include -extern void u8500_map_io(void); +extern void __init ux500_map_io(void); +extern void __init u8500_map_io(void); + extern void u8500_init_devices(void); -extern void u8500_init_irq(void); +extern void __init ux500_init_irq(void); /* We re-use nomadik_timer for this platform */ extern void nmdk_timer_init(void); struct sys_timer; extern struct sys_timer u8500_timer; +#define __IO_DEV_DESC(x, sz) { \ + .virtual = IO_ADDRESS(x), \ + .pfn = __phys_to_pfn(x), \ + .length = sz, \ + .type = MT_DEVICE, \ +} + #endif /* __ASM_ARCH_SETUP_H */ -- cgit v0.10.2 From d67d1127a625cc5ebc3802180b19cc74f35b5578 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Mon, 3 May 2010 07:43:48 +0100 Subject: ARM: 6081/1: ux500: move gpio macros to common header Move GPIO macros to a common header, and allow them to use the correct macros for the appropriate SoC, and be named accordingly. Acked-by: Linus Walleij Acked-by: Srinidhi Kasagar Signed-off-by: Rabin Vincent Signed-off-by: Russell King diff --git a/arch/arm/mach-ux500/cpu-u8500.c b/arch/arm/mach-ux500/cpu-u8500.c index 2c8aa93..c80beca 100644 --- a/arch/arm/mach-ux500/cpu-u8500.c +++ b/arch/arm/mach-ux500/cpu-u8500.c @@ -23,36 +23,6 @@ #include #include -#define GPIO_RESOURCE(block) \ - { \ - .start = U8500_GPIOBANK##block##_BASE, \ - .end = U8500_GPIOBANK##block##_BASE + 127, \ - .flags = IORESOURCE_MEM, \ - }, \ - { \ - .start = IRQ_GPIO##block, \ - .end = IRQ_GPIO##block, \ - .flags = IORESOURCE_IRQ, \ - } - -#define GPIO_DEVICE(block) \ - { \ - .name = "gpio", \ - .id = block, \ - .num_resources = 2, \ - .resource = &u8500_gpio_resources[block * 2], \ - .dev = { \ - .platform_data = &u8500_gpio_data[block], \ - }, \ - } - -#define GPIO_DATA(_name, first) \ - { \ - .name = _name, \ - .first_gpio = first, \ - .first_irq = NOMADIK_GPIO_TO_IRQ(first), \ - } - static struct nmk_gpio_platform_data u8500_gpio_data[] = { GPIO_DATA("GPIO-0-31", 0), GPIO_DATA("GPIO-32-63", 32), /* 37..63 not routed to pin */ diff --git a/arch/arm/mach-ux500/include/mach/gpio.h b/arch/arm/mach-ux500/include/mach/gpio.h index 3c4cd31..d548a62 100644 --- a/arch/arm/mach-ux500/include/mach/gpio.h +++ b/arch/arm/mach-ux500/include/mach/gpio.h @@ -9,4 +9,42 @@ #include +#define __GPIO_RESOURCE(soc, block) \ + { \ + .start = soc##_GPIOBANK##block##_BASE, \ + .end = soc##_GPIOBANK##block##_BASE + 127, \ + .flags = IORESOURCE_MEM, \ + }, \ + { \ + .start = IRQ_GPIO##block, \ + .end = IRQ_GPIO##block, \ + .flags = IORESOURCE_IRQ, \ + } + +#define __GPIO_DEVICE(soc, block) \ + { \ + .name = "gpio", \ + .id = block, \ + .num_resources = 2, \ + .resource = &soc##_gpio_resources[block * 2], \ + .dev = { \ + .platform_data = &soc##_gpio_data[block], \ + }, \ + } + +#define GPIO_DATA(_name, first) \ + { \ + .name = _name, \ + .first_gpio = first, \ + .first_irq = NOMADIK_GPIO_TO_IRQ(first), \ + } + +#ifdef CONFIG_UX500_SOC_DB8500 +#define GPIO_RESOURCE(block) __GPIO_RESOURCE(U8500, block) +#define GPIO_DEVICE(block) __GPIO_DEVICE(u8500, block) +#elif defined(CONFIG_UX500_SOC_DB5500) +#define GPIO_RESOURCE(block) __GPIO_RESOURCE(U5500, block) +#define GPIO_DEVICE(block) __GPIO_DEVICE(u5500, block) +#endif + #endif /* __ASM_ARCH_GPIO_H */ -- cgit v0.10.2 From d48fd006e6d9394e9abd14f4747034f73bb6a386 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Mon, 3 May 2010 07:46:56 +0100 Subject: ARM: 6082/1: ux500: put common devices into devices.c Introduce devices.c, for placing devices common among Ux500 SoCs. Start with the PL031 device. Acked-by: Linus Walleij Acked-by: Srinidhi Kasagar Signed-off-by: Rabin Vincent Signed-off-by: Russell King diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index 6deee85..e5b9f74 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux kernel, U8500 machine. # -obj-y := clock.o cpu.o +obj-y := clock.o cpu.o devices.o obj-$(CONFIG_ARCH_U8500) += cpu-u8500.o obj-$(CONFIG_MACH_U8500_MOP) += board-mop500.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o localtimer.o diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 9ca4709..cc52d53 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -107,18 +107,6 @@ static struct amba_device pl022_device = { .periphid = SSP_PER_ID, }; -static struct amba_device pl031_device = { - .dev = { - .init_name = "pl031", - }, - .res = { - .start = U8500_RTC_BASE, - .end = U8500_RTC_BASE + SZ_4K - 1, - .flags = IORESOURCE_MEM, - }, - .irq = {IRQ_RTC_RTT, NO_IRQ}, -}; - #define U8500_I2C_RESOURCES(id, size) \ static struct resource u8500_i2c_resources_##id[] = { \ [0] = { \ @@ -188,7 +176,6 @@ static struct amba_device *amba_devs[] __initdata = { &uart1_device, &uart2_device, &pl022_device, - &pl031_device, }; /* add any platform devices here - TODO */ diff --git a/arch/arm/mach-ux500/cpu-u8500.c b/arch/arm/mach-ux500/cpu-u8500.c index c80beca..730d020 100644 --- a/arch/arm/mach-ux500/cpu-u8500.c +++ b/arch/arm/mach-ux500/cpu-u8500.c @@ -106,6 +106,8 @@ void __init u8500_map_io(void) */ void __init u8500_init_devices(void) { + ux500_init_devices(); + /* Register the platform devices */ platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c index e6a8058..05615c0 100644 --- a/arch/arm/mach-ux500/cpu.c +++ b/arch/arm/mach-ux500/cpu.c @@ -16,6 +16,7 @@ #include #include +#include #include "clock.h" @@ -41,11 +42,20 @@ static struct map_desc ux500_io_desc[] __initdata = { __IO_DEV_DESC(UX500_BACKUPRAM0_BASE, SZ_8K), }; +static struct amba_device *ux500_amba_devs[] __initdata = { + &ux500_pl031_device, +}; + void __init ux500_map_io(void) { iotable_init(ux500_io_desc, ARRAY_SIZE(ux500_io_desc)); } +void __init ux500_init_devices(void) +{ + amba_add_devices(ux500_amba_devs, ARRAY_SIZE(ux500_amba_devs)); +} + void __init ux500_init_irq(void) { gic_dist_init(0, __io_address(UX500_GIC_DIST_BASE), 29); diff --git a/arch/arm/mach-ux500/devices.c b/arch/arm/mach-ux500/devices.c new file mode 100644 index 0000000..eef686a4 --- /dev/null +++ b/arch/arm/mach-ux500/devices.c @@ -0,0 +1,37 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Rabin Vincent for ST-Ericsson + * License terms: GNU General Public License (GPL) version 2 + */ + +#include +#include +#include +#include +#include + +#include +#include + +struct amba_device ux500_pl031_device = { + .dev = { + .init_name = "pl031", + }, + .res = { + .start = UX500_RTC_BASE, + .end = UX500_RTC_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + .irq = {IRQ_RTC_RTT, NO_IRQ}, +}; + +void __init amba_add_devices(struct amba_device *devs[], int num) +{ + int i; + + for (i = 0; i < num; i++) { + struct amba_device *d = devs[i]; + amba_device_register(d, &iomem_resource); + } +} diff --git a/arch/arm/mach-ux500/include/mach/devices.h b/arch/arm/mach-ux500/include/mach/devices.h new file mode 100644 index 0000000..5bca7c6 --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/devices.h @@ -0,0 +1,15 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * License terms: GNU General Public License (GPL) version 2 + */ + +#ifndef __ASM_ARCH_DEVICES_H__ +#define __ASM_ARCH_DEVICES_H__ + +struct platform_device; +struct amba_device; + +extern struct amba_device ux500_pl031_device; + +#endif diff --git a/arch/arm/mach-ux500/include/mach/setup.h b/arch/arm/mach-ux500/include/mach/setup.h index 6c4c348..6187eff 100644 --- a/arch/arm/mach-ux500/include/mach/setup.h +++ b/arch/arm/mach-ux500/include/mach/setup.h @@ -17,11 +17,15 @@ extern void __init ux500_map_io(void); extern void __init u8500_map_io(void); -extern void u8500_init_devices(void); +extern void __init ux500_init_devices(void); +extern void __init u8500_init_devices(void); + extern void __init ux500_init_irq(void); /* We re-use nomadik_timer for this platform */ extern void nmdk_timer_init(void); +extern void __init amba_add_devices(struct amba_device *devs[], int num); + struct sys_timer; extern struct sys_timer u8500_timer; -- cgit v0.10.2 From 9e4e7fe1a97191e373257ab59e3d6bbcce9a9f1e Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Mon, 3 May 2010 08:03:52 +0100 Subject: ARM: 6083/1: ux500: put DB8500-specific devices in devices-db8500.c Add devices-db8500.c for DB8500-specific devices, starting with SSP0. Acked-by: Linus Walleij Acked-by: Srinidhi Kasagar Signed-off-by: Rabin Vincent Signed-off-by: Russell King diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index e5b9f74..55651e0 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -3,6 +3,6 @@ # obj-y := clock.o cpu.o devices.o -obj-$(CONFIG_ARCH_U8500) += cpu-u8500.o +obj-$(CONFIG_ARCH_U8500) += cpu-u8500.o devices-db8500.o obj-$(CONFIG_MACH_U8500_MOP) += board-mop500.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o localtimer.o diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index cc52d53..6bb9a3d 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -24,6 +24,7 @@ #include #include +#include #define __MEM_4K_RESOURCE(x) \ .res = {.start = (x), .end = (x) + SZ_4K - 1, .flags = IORESOURCE_MEM} @@ -91,22 +92,6 @@ static struct pl022_ssp_controller ssp0_platform_data = { .num_chipselect = 5, }; -static struct amba_device pl022_device = { - .dev = { - .coherent_dma_mask = ~0, - .init_name = "ssp0", - .platform_data = &ssp0_platform_data, - }, - .res = { - .start = U8500_SSP0_BASE, - .end = U8500_SSP0_BASE + SZ_4K - 1, - .flags = IORESOURCE_MEM, - }, - .irq = {IRQ_SSP0, NO_IRQ }, - /* ST-Ericsson modified id */ - .periphid = SSP_PER_ID, -}; - #define U8500_I2C_RESOURCES(id, size) \ static struct resource u8500_i2c_resources_##id[] = { \ [0] = { \ @@ -175,7 +160,7 @@ static struct amba_device *amba_devs[] __initdata = { &uart0_device, &uart1_device, &uart2_device, - &pl022_device, + &u8500_ssp0_device, }; /* add any platform devices here - TODO */ @@ -190,6 +175,8 @@ static void __init u8500_init_machine(void) { int i; + u8500_ssp0_device.dev.platform_data = &ssp0_platform_data; + /* Register the active AMBA devices on this board */ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) amba_device_register(amba_devs[i], &iomem_resource); diff --git a/arch/arm/mach-ux500/devices-db8500.c b/arch/arm/mach-ux500/devices-db8500.c new file mode 100644 index 0000000..f4a2dda --- /dev/null +++ b/arch/arm/mach-ux500/devices-db8500.c @@ -0,0 +1,30 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Rabin Vincent for ST-Ericsson + * License terms: GNU General Public License (GPL) version 2 + */ + +#include +#include +#include +#include +#include + +#include +#include + +struct amba_device u8500_ssp0_device = { + .dev = { + .coherent_dma_mask = ~0, + .init_name = "ssp0", + }, + .res = { + .start = U8500_SSP0_BASE, + .end = U8500_SSP0_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + .irq = {IRQ_SSP0, NO_IRQ }, + /* ST-Ericsson modified id */ + .periphid = SSP_PER_ID, +}; diff --git a/arch/arm/mach-ux500/include/mach/devices.h b/arch/arm/mach-ux500/include/mach/devices.h index 5bca7c6..90229b1 100644 --- a/arch/arm/mach-ux500/include/mach/devices.h +++ b/arch/arm/mach-ux500/include/mach/devices.h @@ -11,5 +11,6 @@ struct platform_device; struct amba_device; extern struct amba_device ux500_pl031_device; +extern struct amba_device u8500_ssp0_device; #endif -- cgit v0.10.2 From 4b27aa4140c20380a67ecefaa48cf3714cc0b8ea Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Mon, 3 May 2010 08:18:38 +0100 Subject: ARM: 6084/1: ux500: move UART devices to devices.c The three PL011 UARTs are common among Ux500 SoCs, so move them to devices.c. Acked-by: Linus Walleij Acked-by: Srinidhi Kasagar Signed-off-by: Rabin Vincent Signed-off-by: Russell King diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 6bb9a3d..0e595bf 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -26,28 +26,6 @@ #include #include -#define __MEM_4K_RESOURCE(x) \ - .res = {.start = (x), .end = (x) + SZ_4K - 1, .flags = IORESOURCE_MEM} - -/* These are active devices on this board */ -static struct amba_device uart0_device = { - .dev = { .init_name = "uart0" }, - __MEM_4K_RESOURCE(U8500_UART0_BASE), - .irq = {IRQ_UART0, NO_IRQ}, -}; - -static struct amba_device uart1_device = { - .dev = { .init_name = "uart1" }, - __MEM_4K_RESOURCE(U8500_UART1_BASE), - .irq = {IRQ_UART1, NO_IRQ}, -}; - -static struct amba_device uart2_device = { - .dev = { .init_name = "uart2" }, - __MEM_4K_RESOURCE(U8500_UART2_BASE), - .irq = {IRQ_UART2, NO_IRQ}, -}; - static void ab4500_spi_cs_control(u32 command) { /* set the FRM signal, which is CS - TODO */ @@ -157,9 +135,9 @@ U8500_I2C_PDEVICE(2); U8500_I2C_PDEVICE(3); static struct amba_device *amba_devs[] __initdata = { - &uart0_device, - &uart1_device, - &uart2_device, + &ux500_uart0_device, + &ux500_uart1_device, + &ux500_uart2_device, &u8500_ssp0_device, }; diff --git a/arch/arm/mach-ux500/devices.c b/arch/arm/mach-ux500/devices.c index eef686a4..374fcce 100644 --- a/arch/arm/mach-ux500/devices.c +++ b/arch/arm/mach-ux500/devices.c @@ -14,6 +14,9 @@ #include #include +#define __MEM_4K_RESOURCE(x) \ + .res = {.start = (x), .end = (x) + SZ_4K - 1, .flags = IORESOURCE_MEM} + struct amba_device ux500_pl031_device = { .dev = { .init_name = "pl031", @@ -26,6 +29,24 @@ struct amba_device ux500_pl031_device = { .irq = {IRQ_RTC_RTT, NO_IRQ}, }; +struct amba_device ux500_uart0_device = { + .dev = { .init_name = "uart0" }, + __MEM_4K_RESOURCE(UX500_UART0_BASE), + .irq = {IRQ_UART0, NO_IRQ}, +}; + +struct amba_device ux500_uart1_device = { + .dev = { .init_name = "uart1" }, + __MEM_4K_RESOURCE(UX500_UART1_BASE), + .irq = {IRQ_UART1, NO_IRQ}, +}; + +struct amba_device ux500_uart2_device = { + .dev = { .init_name = "uart2" }, + __MEM_4K_RESOURCE(UX500_UART2_BASE), + .irq = {IRQ_UART2, NO_IRQ}, +}; + void __init amba_add_devices(struct amba_device *devs[], int num) { int i; diff --git a/arch/arm/mach-ux500/include/mach/devices.h b/arch/arm/mach-ux500/include/mach/devices.h index 90229b1..7cc4983 100644 --- a/arch/arm/mach-ux500/include/mach/devices.h +++ b/arch/arm/mach-ux500/include/mach/devices.h @@ -12,5 +12,8 @@ struct amba_device; extern struct amba_device ux500_pl031_device; extern struct amba_device u8500_ssp0_device; +extern struct amba_device ux500_uart0_device; +extern struct amba_device ux500_uart1_device; +extern struct amba_device ux500_uart2_device; #endif -- cgit v0.10.2 From f9faf23799d0726afb56ee6c6c53fbea00ec7de3 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Mon, 3 May 2010 08:24:37 +0100 Subject: ARM: 6085/1: ux500: reorganize i2c devices Move common i2c devices to devices.c and DB8500-specific I2C devices to devices-db8500.c. Acked-by: Linus Walleij Acked-by: Srinidhi Kasagar Signed-off-by: Rabin Vincent Signed-off-by: Russell King diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 0e595bf..cd0bd36 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -70,27 +70,8 @@ static struct pl022_ssp_controller ssp0_platform_data = { .num_chipselect = 5, }; -#define U8500_I2C_RESOURCES(id, size) \ -static struct resource u8500_i2c_resources_##id[] = { \ - [0] = { \ - .start = U8500_I2C##id##_BASE, \ - .end = U8500_I2C##id##_BASE + size - 1, \ - .flags = IORESOURCE_MEM, \ - }, \ - [1] = { \ - .start = IRQ_I2C##id, \ - .end = IRQ_I2C##id, \ - .flags = IORESOURCE_IRQ \ - } \ -} - -U8500_I2C_RESOURCES(0, SZ_4K); -U8500_I2C_RESOURCES(1, SZ_4K); -U8500_I2C_RESOURCES(2, SZ_4K); -U8500_I2C_RESOURCES(3, SZ_4K); - #define U8500_I2C_CONTROLLER(id, _slsu, _tft, _rft, clk, _sm) \ -static struct nmk_i2c_controller u8500_i2c_##id = { \ +static struct nmk_i2c_controller u8500_i2c##id##_data = { \ /* \ * slave data setup time, which is \ * 250 ns,100ns,10ns which is 14,6,2 \ @@ -118,22 +99,6 @@ U8500_I2C_CONTROLLER(1, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD); U8500_I2C_CONTROLLER(2, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD); U8500_I2C_CONTROLLER(3, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD); -#define U8500_I2C_PDEVICE(cid) \ -static struct platform_device i2c_controller##cid = { \ - .name = "nmk-i2c", \ - .id = cid, \ - .num_resources = 2, \ - .resource = u8500_i2c_resources_##cid, \ - .dev = { \ - .platform_data = &u8500_i2c_##cid \ - } \ -} - -U8500_I2C_PDEVICE(0); -U8500_I2C_PDEVICE(1); -U8500_I2C_PDEVICE(2); -U8500_I2C_PDEVICE(3); - static struct amba_device *amba_devs[] __initdata = { &ux500_uart0_device, &ux500_uart1_device, @@ -143,16 +108,21 @@ static struct amba_device *amba_devs[] __initdata = { /* add any platform devices here - TODO */ static struct platform_device *platform_devs[] __initdata = { - &i2c_controller0, - &i2c_controller1, - &i2c_controller2, - &i2c_controller3, + &u8500_i2c0_device, + &ux500_i2c1_device, + &ux500_i2c2_device, + &ux500_i2c3_device, }; static void __init u8500_init_machine(void) { int i; + u8500_i2c0_device.dev.platform_data = &u8500_i2c0_data; + ux500_i2c1_device.dev.platform_data = &u8500_i2c1_data; + ux500_i2c2_device.dev.platform_data = &u8500_i2c2_data; + ux500_i2c3_device.dev.platform_data = &u8500_i2c3_data; + u8500_ssp0_device.dev.platform_data = &ssp0_platform_data; /* Register the active AMBA devices on this board */ diff --git a/arch/arm/mach-ux500/devices-db8500.c b/arch/arm/mach-ux500/devices-db8500.c index f4a2dda..397f862 100644 --- a/arch/arm/mach-ux500/devices-db8500.c +++ b/arch/arm/mach-ux500/devices-db8500.c @@ -28,3 +28,43 @@ struct amba_device u8500_ssp0_device = { /* ST-Ericsson modified id */ .periphid = SSP_PER_ID, }; + +static struct resource u8500_i2c0_resources[] = { + [0] = { + .start = U8500_I2C0_BASE, + .end = U8500_I2C0_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_I2C0, + .end = IRQ_I2C0, + .flags = IORESOURCE_IRQ, + } +}; + +struct platform_device u8500_i2c0_device = { + .name = "nmk-i2c", + .id = 0, + .resource = u8500_i2c0_resources, + .num_resources = ARRAY_SIZE(u8500_i2c0_resources), +}; + +static struct resource u8500_i2c4_resources[] = { + [0] = { + .start = U8500_I2C4_BASE, + .end = U8500_I2C4_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_I2C4, + .end = IRQ_I2C4, + .flags = IORESOURCE_IRQ, + } +}; + +struct platform_device u8500_i2c4_device = { + .name = "nmk-i2c", + .id = 4, + .resource = u8500_i2c4_resources, + .num_resources = ARRAY_SIZE(u8500_i2c4_resources), +}; diff --git a/arch/arm/mach-ux500/devices.c b/arch/arm/mach-ux500/devices.c index 374fcce..8a26889 100644 --- a/arch/arm/mach-ux500/devices.c +++ b/arch/arm/mach-ux500/devices.c @@ -47,6 +47,36 @@ struct amba_device ux500_uart2_device = { .irq = {IRQ_UART2, NO_IRQ}, }; +#define UX500_I2C_RESOURCES(id, size) \ +static struct resource ux500_i2c##id##_resources[] = { \ + [0] = { \ + .start = UX500_I2C##id##_BASE, \ + .end = UX500_I2C##id##_BASE + size - 1, \ + .flags = IORESOURCE_MEM, \ + }, \ + [1] = { \ + .start = IRQ_I2C##id, \ + .end = IRQ_I2C##id, \ + .flags = IORESOURCE_IRQ \ + } \ +} + +UX500_I2C_RESOURCES(1, SZ_4K); +UX500_I2C_RESOURCES(2, SZ_4K); +UX500_I2C_RESOURCES(3, SZ_4K); + +#define UX500_I2C_PDEVICE(cid) \ +struct platform_device ux500_i2c##cid##_device = { \ + .name = "nmk-i2c", \ + .id = cid, \ + .num_resources = 2, \ + .resource = ux500_i2c##cid##_resources, \ +} + +UX500_I2C_PDEVICE(1); +UX500_I2C_PDEVICE(2); +UX500_I2C_PDEVICE(3); + void __init amba_add_devices(struct amba_device *devs[], int num) { int i; diff --git a/arch/arm/mach-ux500/include/mach/devices.h b/arch/arm/mach-ux500/include/mach/devices.h index 7cc4983..251b4eb 100644 --- a/arch/arm/mach-ux500/include/mach/devices.h +++ b/arch/arm/mach-ux500/include/mach/devices.h @@ -16,4 +16,11 @@ extern struct amba_device ux500_uart0_device; extern struct amba_device ux500_uart1_device; extern struct amba_device ux500_uart2_device; +extern struct platform_device ux500_i2c1_device; +extern struct platform_device ux500_i2c2_device; +extern struct platform_device ux500_i2c3_device; + +extern struct platform_device u8500_i2c0_device; +extern struct platform_device u8500_i2c4_device; + #endif diff --git a/arch/arm/mach-ux500/include/mach/irqs.h b/arch/arm/mach-ux500/include/mach/irqs.h index 8a1f697..7970684 100644 --- a/arch/arm/mach-ux500/include/mach/irqs.h +++ b/arch/arm/mach-ux500/include/mach/irqs.h @@ -42,6 +42,7 @@ #define IRQ_AB4500 (IRQ_SHPI_START + 40) #define IRQ_DISP (IRQ_SHPI_START + 48) #define IRQ_SiPI3 (IRQ_SHPI_START + 49) +#define IRQ_I2C4 (IRQ_SHPI_START + 51) #define IRQ_SSP1 (IRQ_SHPI_START + 52) #define IRQ_I2C2 (IRQ_SHPI_START + 55) #define IRQ_SDMMC0 (IRQ_SHPI_START + 60) -- cgit v0.10.2 From 5b1f7ddf18b75adeb433ef9d91a2e4bd7580facc Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Mon, 3 May 2010 08:25:52 +0100 Subject: ARM: 6086/1: ux500: move gpio devices to devices-db8500.c The GPIO layout is different on DB5500, so move the current one to devices-db8500.c. Acked-by: Linus Walleij Acked-by: Srinidhi Kasagar Signed-off-by: Rabin Vincent Signed-off-by: Russell King diff --git a/arch/arm/mach-ux500/cpu-u8500.c b/arch/arm/mach-ux500/cpu-u8500.c index 730d020..51e9bf2 100644 --- a/arch/arm/mach-ux500/cpu-u8500.c +++ b/arch/arm/mach-ux500/cpu-u8500.c @@ -22,42 +22,7 @@ #include #include #include - -static struct nmk_gpio_platform_data u8500_gpio_data[] = { - GPIO_DATA("GPIO-0-31", 0), - GPIO_DATA("GPIO-32-63", 32), /* 37..63 not routed to pin */ - GPIO_DATA("GPIO-64-95", 64), - GPIO_DATA("GPIO-96-127", 96), /* 97..127 not routed to pin */ - GPIO_DATA("GPIO-128-159", 128), - GPIO_DATA("GPIO-160-191", 160), /* 172..191 not routed to pin */ - GPIO_DATA("GPIO-192-223", 192), - GPIO_DATA("GPIO-224-255", 224), /* 231..255 not routed to pin */ - GPIO_DATA("GPIO-256-288", 256), /* 258..288 not routed to pin */ -}; - -static struct resource u8500_gpio_resources[] = { - GPIO_RESOURCE(0), - GPIO_RESOURCE(1), - GPIO_RESOURCE(2), - GPIO_RESOURCE(3), - GPIO_RESOURCE(4), - GPIO_RESOURCE(5), - GPIO_RESOURCE(6), - GPIO_RESOURCE(7), - GPIO_RESOURCE(8), -}; - -static struct platform_device u8500_gpio_devs[] = { - GPIO_DEVICE(0), - GPIO_DEVICE(1), - GPIO_DEVICE(2), - GPIO_DEVICE(3), - GPIO_DEVICE(4), - GPIO_DEVICE(5), - GPIO_DEVICE(6), - GPIO_DEVICE(7), - GPIO_DEVICE(8), -}; +#include static struct platform_device *platform_devs[] __initdata = { &u8500_gpio_devs[0], diff --git a/arch/arm/mach-ux500/devices-db8500.c b/arch/arm/mach-ux500/devices-db8500.c index 397f862..2033423 100644 --- a/arch/arm/mach-ux500/devices-db8500.c +++ b/arch/arm/mach-ux500/devices-db8500.c @@ -9,11 +9,48 @@ #include #include #include +#include #include #include #include +static struct nmk_gpio_platform_data u8500_gpio_data[] = { + GPIO_DATA("GPIO-0-31", 0), + GPIO_DATA("GPIO-32-63", 32), /* 37..63 not routed to pin */ + GPIO_DATA("GPIO-64-95", 64), + GPIO_DATA("GPIO-96-127", 96), /* 98..127 not routed to pin */ + GPIO_DATA("GPIO-128-159", 128), + GPIO_DATA("GPIO-160-191", 160), /* 172..191 not routed to pin */ + GPIO_DATA("GPIO-192-223", 192), + GPIO_DATA("GPIO-224-255", 224), /* 231..255 not routed to pin */ + GPIO_DATA("GPIO-256-288", 256), /* 268..288 not routed to pin */ +}; + +static struct resource u8500_gpio_resources[] = { + GPIO_RESOURCE(0), + GPIO_RESOURCE(1), + GPIO_RESOURCE(2), + GPIO_RESOURCE(3), + GPIO_RESOURCE(4), + GPIO_RESOURCE(5), + GPIO_RESOURCE(6), + GPIO_RESOURCE(7), + GPIO_RESOURCE(8), +}; + +struct platform_device u8500_gpio_devs[] = { + GPIO_DEVICE(0), + GPIO_DEVICE(1), + GPIO_DEVICE(2), + GPIO_DEVICE(3), + GPIO_DEVICE(4), + GPIO_DEVICE(5), + GPIO_DEVICE(6), + GPIO_DEVICE(7), + GPIO_DEVICE(8), +}; + struct amba_device u8500_ssp0_device = { .dev = { .coherent_dma_mask = ~0, diff --git a/arch/arm/mach-ux500/include/mach/devices.h b/arch/arm/mach-ux500/include/mach/devices.h index 251b4eb..76b3569 100644 --- a/arch/arm/mach-ux500/include/mach/devices.h +++ b/arch/arm/mach-ux500/include/mach/devices.h @@ -10,6 +10,8 @@ struct platform_device; struct amba_device; +extern struct platform_device u8500_gpio_devs[]; + extern struct amba_device ux500_pl031_device; extern struct amba_device u8500_ssp0_device; extern struct amba_device ux500_uart0_device; -- cgit v0.10.2 From 41ac329f607add059ae8b063375c5d9d6e7471cf Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Mon, 3 May 2010 08:28:05 +0100 Subject: ARM: 6087/1: ux500: move sys_timer to cpu.c Move the common system timer setup code to cpu.c. Acked-by: Linus Walleij Acked-by: Srinidhi Kasagar Signed-off-by: Rabin Vincent Signed-off-by: Russell King diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index cd0bd36..072196c 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -145,6 +145,6 @@ MACHINE_START(U8500, "ST-Ericsson MOP500 platform") .map_io = u8500_map_io, .init_irq = ux500_init_irq, /* we re-use nomadik timer here */ - .timer = &u8500_timer, + .timer = &ux500_timer, .init_machine = u8500_init_machine, MACHINE_END diff --git a/arch/arm/mach-ux500/cpu-u8500.c b/arch/arm/mach-ux500/cpu-u8500.c index 51e9bf2..d04299f 100644 --- a/arch/arm/mach-ux500/cpu-u8500.c +++ b/arch/arm/mach-ux500/cpu-u8500.c @@ -17,9 +17,7 @@ #include #include -#include #include -#include #include #include #include @@ -78,22 +76,3 @@ void __init u8500_init_devices(void) return ; } - -static void __init u8500_timer_init(void) -{ -#ifdef CONFIG_LOCAL_TIMERS - /* Setup the local timer base */ - twd_base = __io_address(U8500_TWD_BASE); -#endif - /* Setup the MTU base */ - if (cpu_is_u8500ed()) - mtu_base = __io_address(U8500_MTU0_BASE_ED); - else - mtu_base = __io_address(U8500_MTU0_BASE); - - nmdk_timer_init(); -} - -struct sys_timer u8500_timer = { - .init = u8500_timer_init, -}; diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c index 05615c0..d81ad02 100644 --- a/arch/arm/mach-ux500/cpu.c +++ b/arch/arm/mach-ux500/cpu.c @@ -13,7 +13,9 @@ #include #include #include +#include +#include #include #include #include @@ -76,3 +78,22 @@ static int ux500_l2x0_init(void) } early_initcall(ux500_l2x0_init); #endif + +static void __init ux500_timer_init(void) +{ +#ifdef CONFIG_LOCAL_TIMERS + /* Setup the local timer base */ + twd_base = __io_address(UX500_TWD_BASE); +#endif + /* Setup the MTU base */ + if (cpu_is_u8500ed()) + mtu_base = __io_address(U8500_MTU0_BASE_ED); + else + mtu_base = __io_address(UX500_MTU0_BASE); + + nmdk_timer_init(); +} + +struct sys_timer ux500_timer = { + .init = ux500_timer_init, +}; diff --git a/arch/arm/mach-ux500/include/mach/setup.h b/arch/arm/mach-ux500/include/mach/setup.h index 6187eff..c730d07 100644 --- a/arch/arm/mach-ux500/include/mach/setup.h +++ b/arch/arm/mach-ux500/include/mach/setup.h @@ -27,7 +27,7 @@ extern void nmdk_timer_init(void); extern void __init amba_add_devices(struct amba_device *devs[], int num); struct sys_timer; -extern struct sys_timer u8500_timer; +extern struct sys_timer ux500_timer; #define __IO_DEV_DESC(x, sz) { \ .virtual = IO_ADDRESS(x), \ -- cgit v0.10.2 From 817412d3a1391d4667494f16cd49455c62453c78 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Mon, 3 May 2010 08:31:35 +0100 Subject: ARM: 6088/1: ux500: use UX500_* macros instead of U8500_* So that the correct addresses get used on U5500. Acked-by: Linus Walleij Acked-by: Srinidhi Kasagar Signed-off-by: Rabin Vincent Signed-off-by: Russell King diff --git a/arch/arm/mach-ux500/include/mach/entry-macro.S b/arch/arm/mach-ux500/include/mach/entry-macro.S index eece330..60ea88d 100644 --- a/arch/arm/mach-ux500/include/mach/entry-macro.S +++ b/arch/arm/mach-ux500/include/mach/entry-macro.S @@ -17,7 +17,7 @@ .endm .macro get_irqnr_preamble, base, tmp - ldr \base, =IO_ADDRESS(U8500_GIC_CPU_BASE) + ldr \base, =IO_ADDRESS(UX500_GIC_CPU_BASE) .endm .macro arch_ret_to_user, tmp1, tmp2 diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c index 76dd935..438ef16 100644 --- a/arch/arm/mach-ux500/platsmp.c +++ b/arch/arm/mach-ux500/platsmp.c @@ -30,7 +30,7 @@ volatile int __cpuinitdata pen_release = -1; static unsigned int __init get_core_count(void) { - return scu_get_core_count(__io_address(U8500_SCU_BASE)); + return scu_get_core_count(__io_address(UX500_SCU_BASE)); } static DEFINE_SPINLOCK(boot_lock); @@ -44,7 +44,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu) * core (e.g. timer irq), then they will not have been enabled * for us: do so */ - gic_cpu_init(0, __io_address(U8500_GIC_CPU_BASE)); + gic_cpu_init(0, __io_address(UX500_GIC_CPU_BASE)); /* * let the primary processor know we're out of the @@ -106,12 +106,12 @@ static void __init wakeup_secondary(void) */ #define U8500_CPU1_JUMPADDR_OFFSET 0x1FF4 __raw_writel(virt_to_phys(u8500_secondary_startup), - (void __iomem *)IO_ADDRESS(U8500_BACKUPRAM0_BASE) + + __io_address(UX500_BACKUPRAM0_BASE) + U8500_CPU1_JUMPADDR_OFFSET); #define U8500_CPU1_WAKEMAGIC_OFFSET 0x1FF0 __raw_writel(0xA1FEED01, - (void __iomem *)IO_ADDRESS(U8500_BACKUPRAM0_BASE) + + __io_address(UX500_BACKUPRAM0_BASE) + U8500_CPU1_WAKEMAGIC_OFFSET); /* make sure write buffer is drained */ @@ -172,7 +172,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) * boot CPU, but only if we have more than one CPU. */ percpu_timer_setup(); - scu_enable(__io_address(U8500_SCU_BASE)); + scu_enable(__io_address(UX500_SCU_BASE)); wakeup_secondary(); } } -- cgit v0.10.2 From cb165c52561fd5947747fdbdb0c7ad22c6138175 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Mon, 3 May 2010 08:42:07 +0100 Subject: ARM: 6089/1: ux500: rename cpu-u8500.c to cpu-db8500.c Move the DB8500-specific file to a more appropriate name. Acked-by: Linus Walleij Acked-by: Srinidhi Kasagar Signed-off-by: Rabin Vincent Signed-off-by: Russell King diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index 55651e0..2eb7685 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -3,6 +3,6 @@ # obj-y := clock.o cpu.o devices.o -obj-$(CONFIG_ARCH_U8500) += cpu-u8500.o devices-db8500.o +obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o obj-$(CONFIG_MACH_U8500_MOP) += board-mop500.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o localtimer.o diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c new file mode 100644 index 0000000..d04299f --- /dev/null +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2008-2009 ST-Ericsson + * + * Author: Srinidhi KASAGAR + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static struct platform_device *platform_devs[] __initdata = { + &u8500_gpio_devs[0], + &u8500_gpio_devs[1], + &u8500_gpio_devs[2], + &u8500_gpio_devs[3], + &u8500_gpio_devs[4], + &u8500_gpio_devs[5], + &u8500_gpio_devs[6], + &u8500_gpio_devs[7], + &u8500_gpio_devs[8], +}; + +/* minimum static i/o mapping required to boot U8500 platforms */ +static struct map_desc u8500_io_desc[] __initdata = { + __IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K), + __IO_DEV_DESC(U8500_GPIO0_BASE, SZ_4K), + __IO_DEV_DESC(U8500_GPIO1_BASE, SZ_4K), + __IO_DEV_DESC(U8500_GPIO2_BASE, SZ_4K), + __IO_DEV_DESC(U8500_GPIO3_BASE, SZ_4K), +}; + +static struct map_desc u8500ed_io_desc[] __initdata = { + __IO_DEV_DESC(U8500_MTU0_BASE_ED, SZ_4K), + __IO_DEV_DESC(U8500_CLKRST7_BASE_ED, SZ_8K), +}; + +static struct map_desc u8500v1_io_desc[] __initdata = { + __IO_DEV_DESC(U8500_MTU0_BASE, SZ_4K), +}; + +void __init u8500_map_io(void) +{ + ux500_map_io(); + + iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc)); + + if (cpu_is_u8500ed()) + iotable_init(u8500ed_io_desc, ARRAY_SIZE(u8500ed_io_desc)); + else + iotable_init(u8500v1_io_desc, ARRAY_SIZE(u8500v1_io_desc)); +} + +/* + * This function is called from the board init + */ +void __init u8500_init_devices(void) +{ + ux500_init_devices(); + + /* Register the platform devices */ + platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); + + return ; +} diff --git a/arch/arm/mach-ux500/cpu-u8500.c b/arch/arm/mach-ux500/cpu-u8500.c deleted file mode 100644 index d04299f..0000000 --- a/arch/arm/mach-ux500/cpu-u8500.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2008-2009 ST-Ericsson - * - * Author: Srinidhi KASAGAR - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -static struct platform_device *platform_devs[] __initdata = { - &u8500_gpio_devs[0], - &u8500_gpio_devs[1], - &u8500_gpio_devs[2], - &u8500_gpio_devs[3], - &u8500_gpio_devs[4], - &u8500_gpio_devs[5], - &u8500_gpio_devs[6], - &u8500_gpio_devs[7], - &u8500_gpio_devs[8], -}; - -/* minimum static i/o mapping required to boot U8500 platforms */ -static struct map_desc u8500_io_desc[] __initdata = { - __IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K), - __IO_DEV_DESC(U8500_GPIO0_BASE, SZ_4K), - __IO_DEV_DESC(U8500_GPIO1_BASE, SZ_4K), - __IO_DEV_DESC(U8500_GPIO2_BASE, SZ_4K), - __IO_DEV_DESC(U8500_GPIO3_BASE, SZ_4K), -}; - -static struct map_desc u8500ed_io_desc[] __initdata = { - __IO_DEV_DESC(U8500_MTU0_BASE_ED, SZ_4K), - __IO_DEV_DESC(U8500_CLKRST7_BASE_ED, SZ_8K), -}; - -static struct map_desc u8500v1_io_desc[] __initdata = { - __IO_DEV_DESC(U8500_MTU0_BASE, SZ_4K), -}; - -void __init u8500_map_io(void) -{ - ux500_map_io(); - - iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc)); - - if (cpu_is_u8500ed()) - iotable_init(u8500ed_io_desc, ARRAY_SIZE(u8500ed_io_desc)); - else - iotable_init(u8500v1_io_desc, ARRAY_SIZE(u8500v1_io_desc)); -} - -/* - * This function is called from the board init - */ -void __init u8500_init_devices(void) -{ - ux500_init_devices(); - - /* Register the platform devices */ - platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); - - return ; -} -- cgit v0.10.2 From 591d8dd71cc265465ac706ac11e5f613c6181a43 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Mon, 3 May 2010 08:46:51 +0100 Subject: ARM: 6090/1: ux500: add U5500 support Add basic support for the U5500 platform. Acked-by: Linus Walleij Acked-by: Srinidhi Kasagar Signed-off-by: Rabin Vincent Signed-off-by: Russell King diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig index 8ad5ee8..6625e5b 100644 --- a/arch/arm/mach-ux500/Kconfig +++ b/arch/arm/mach-ux500/Kconfig @@ -13,19 +13,24 @@ config UX500_SOC_DB8500 config UX500_SOC_DB5500 bool -menu "ST-Ericsson platform type" - -comment "ST-Ericsson Multicore Mobile Platforms" +choice + prompt "Ux500 target platform" + default MACH_U8500_MOP config MACH_U8500_MOP - bool "U8500 Early Development platform" - default y + bool "U8500 Development platform" select UX500_SOC_DB8500 help Include support for mop500 development platform based on U8500 architecture. The platform is based on early drop silicon version of 8500. -endmenu + +config MACH_U5500 + bool "U5500 Development platform" + select UX500_SOC_DB5500 + help + Include support for the U5500 development platform. +endchoice config UX500_DEBUG_UART int "Ux500 UART to use for low-level debug" diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index 2eb7685..c7bc419 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -3,6 +3,8 @@ # obj-y := clock.o cpu.o devices.o +obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o devices-db5500.o obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o obj-$(CONFIG_MACH_U8500_MOP) += board-mop500.o +obj-$(CONFIG_MACH_U5500) += board-u5500.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o localtimer.o diff --git a/arch/arm/mach-ux500/board-u5500.c b/arch/arm/mach-ux500/board-u5500.c new file mode 100644 index 0000000..4430e69 --- /dev/null +++ b/arch/arm/mach-ux500/board-u5500.c @@ -0,0 +1,41 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Rabin Vincent for ST-Ericsson + * License terms: GNU General Public License (GPL) version 2 + */ + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +static struct amba_device *amba_board_devs[] __initdata = { + &ux500_uart0_device, + &ux500_uart1_device, + &ux500_uart2_device, +}; + +static void __init u5500_init_machine(void) +{ + u5500_init_devices(); + + amba_add_devices(amba_board_devs, ARRAY_SIZE(amba_board_devs)); +} + +MACHINE_START(U8500, "ST-Ericsson U5500 Platform") + .phys_io = UX500_UART0_BASE, + .io_pg_offst = (IO_ADDRESS(UX500_UART0_BASE) >> 18) & 0xfffc, + .boot_params = 0x00000100, + .map_io = u5500_map_io, + .init_irq = ux500_init_irq, + .timer = &ux500_timer, + .init_machine = u5500_init_machine, +MACHINE_END diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c index d16b8b5..c325dad 100644 --- a/arch/arm/mach-ux500/clock.c +++ b/arch/arm/mach-ux500/clock.c @@ -502,6 +502,10 @@ static int __init clk_init(void) if (cpu_is_u8500ed()) { clk_prcmu_ops.enable = clk_prcmu_ed_enable; clk_prcmu_ops.disable = clk_prcmu_ed_disable; + } else if (cpu_is_u5500()) { + /* Clock tree for U5500 not implemented yet */ + clk_prcc_ops.enable = clk_prcc_ops.disable = NULL; + clk_prcmu_ops.enable = clk_prcmu_ops.disable = NULL; } clkdev_add_table(u8500_common_clks, ARRAY_SIZE(u8500_common_clks)); diff --git a/arch/arm/mach-ux500/cpu-db5500.c b/arch/arm/mach-ux500/cpu-db5500.c new file mode 100644 index 0000000..6a3ac45 --- /dev/null +++ b/arch/arm/mach-ux500/cpu-db5500.c @@ -0,0 +1,50 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Rabin Vincent for ST-Ericsson + * License terms: GNU General Public License (GPL) version 2 + */ + +#include +#include +#include + +#include + +#include +#include +#include + +static struct map_desc u5500_io_desc[] __initdata = { + __IO_DEV_DESC(U5500_GPIO0_BASE, SZ_4K), + __IO_DEV_DESC(U5500_GPIO1_BASE, SZ_4K), + __IO_DEV_DESC(U5500_GPIO2_BASE, SZ_4K), + __IO_DEV_DESC(U5500_GPIO3_BASE, SZ_4K), + __IO_DEV_DESC(U5500_GPIO4_BASE, SZ_4K), +}; + +static struct platform_device *u5500_platform_devs[] __initdata = { + &u5500_gpio_devs[0], + &u5500_gpio_devs[1], + &u5500_gpio_devs[2], + &u5500_gpio_devs[3], + &u5500_gpio_devs[4], + &u5500_gpio_devs[5], + &u5500_gpio_devs[6], + &u5500_gpio_devs[7], +}; + +void __init u5500_map_io(void) +{ + ux500_map_io(); + + iotable_init(u5500_io_desc, ARRAY_SIZE(u5500_io_desc)); +} + +void __init u5500_init_devices(void) +{ + ux500_init_devices(); + + platform_add_devices(u5500_platform_devs, + ARRAY_SIZE(u5500_platform_devs)); +} diff --git a/arch/arm/mach-ux500/devices-db5500.c b/arch/arm/mach-ux500/devices-db5500.c new file mode 100644 index 0000000..33e5b56 --- /dev/null +++ b/arch/arm/mach-ux500/devices-db5500.c @@ -0,0 +1,46 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Rabin Vincent for ST-Ericsson + * License terms: GNU General Public License (GPL) version 2 + */ + +#include +#include +#include + +#include +#include + +static struct nmk_gpio_platform_data u5500_gpio_data[] = { + GPIO_DATA("GPIO-0-31", 0), + GPIO_DATA("GPIO-32-63", 32), /* 36..63 not routed to pin */ + GPIO_DATA("GPIO-64-95", 64), /* 83..95 not routed to pin */ + GPIO_DATA("GPIO-96-127", 96), /* 102..127 not routed to pin */ + GPIO_DATA("GPIO-128-159", 128), /* 149..159 not routed to pin */ + GPIO_DATA("GPIO-160-191", 160), + GPIO_DATA("GPIO-192-223", 192), + GPIO_DATA("GPIO-224-255", 224), /* 228..255 not routed to pin */ +}; + +static struct resource u5500_gpio_resources[] = { + GPIO_RESOURCE(0), + GPIO_RESOURCE(1), + GPIO_RESOURCE(2), + GPIO_RESOURCE(3), + GPIO_RESOURCE(4), + GPIO_RESOURCE(5), + GPIO_RESOURCE(6), + GPIO_RESOURCE(7), +}; + +struct platform_device u5500_gpio_devs[] = { + GPIO_DEVICE(0), + GPIO_DEVICE(1), + GPIO_DEVICE(2), + GPIO_DEVICE(3), + GPIO_DEVICE(4), + GPIO_DEVICE(5), + GPIO_DEVICE(6), + GPIO_DEVICE(7), +}; diff --git a/arch/arm/mach-ux500/include/mach/devices.h b/arch/arm/mach-ux500/include/mach/devices.h index 76b3569..0422af0 100644 --- a/arch/arm/mach-ux500/include/mach/devices.h +++ b/arch/arm/mach-ux500/include/mach/devices.h @@ -10,6 +10,7 @@ struct platform_device; struct amba_device; +extern struct platform_device u5500_gpio_devs[]; extern struct platform_device u8500_gpio_devs[]; extern struct amba_device ux500_pl031_device; diff --git a/arch/arm/mach-ux500/include/mach/hardware.h b/arch/arm/mach-ux500/include/mach/hardware.h index 1353f17..8656379 100644 --- a/arch/arm/mach-ux500/include/mach/hardware.h +++ b/arch/arm/mach-ux500/include/mach/hardware.h @@ -114,6 +114,15 @@ static inline bool cpu_is_u8500v1(void) return cpu_is_u8500() && (read_cpuid_id() & 15) == 1; } +static inline bool cpu_is_u5500(void) +{ +#ifdef CONFIG_UX500_SOC_DB5500 + return 1; +#else + return 0; +#endif +} + #endif #endif /* __MACH_HARDWARE_H */ diff --git a/arch/arm/mach-ux500/include/mach/setup.h b/arch/arm/mach-ux500/include/mach/setup.h index c730d07..e978dbd 100644 --- a/arch/arm/mach-ux500/include/mach/setup.h +++ b/arch/arm/mach-ux500/include/mach/setup.h @@ -15,9 +15,11 @@ #include extern void __init ux500_map_io(void); +extern void __init u5500_map_io(void); extern void __init u8500_map_io(void); extern void __init ux500_init_devices(void); +extern void __init u5500_init_devices(void); extern void __init u8500_init_devices(void); extern void __init ux500_init_irq(void); -- cgit v0.10.2 From 4677d4a53e0d565742277e8913e91c821453e63e Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 3 May 2010 14:57:11 +0200 Subject: arch, hweight: Fix compilation errors Fix function prototype visibility issues when compiling for non-x86 architectures. Tested with crosstool (ftp://ftp.kernel.org/pub/tools/crosstool/) with alpha, ia64 and sparc targets. Signed-off-by: Borislav Petkov LKML-Reference: <20100503130736.GD26107@aftab> Signed-off-by: H. Peter Anvin diff --git a/include/asm-generic/bitops/arch_hweight.h b/include/asm-generic/bitops/arch_hweight.h index 9a81c1e..6a211f4 100644 --- a/include/asm-generic/bitops/arch_hweight.h +++ b/include/asm-generic/bitops/arch_hweight.h @@ -3,22 +3,22 @@ #include -inline unsigned int __arch_hweight32(unsigned int w) +static inline unsigned int __arch_hweight32(unsigned int w) { return __sw_hweight32(w); } -inline unsigned int __arch_hweight16(unsigned int w) +static inline unsigned int __arch_hweight16(unsigned int w) { return __sw_hweight16(w); } -inline unsigned int __arch_hweight8(unsigned int w) +static inline unsigned int __arch_hweight8(unsigned int w) { return __sw_hweight8(w); } -inline unsigned long __arch_hweight64(__u64 w) +static inline unsigned long __arch_hweight64(__u64 w) { return __sw_hweight64(w); } diff --git a/include/linux/bitops.h b/include/linux/bitops.h index c55d5bc..26caa60 100644 --- a/include/linux/bitops.h +++ b/include/linux/bitops.h @@ -10,6 +10,11 @@ #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) #endif +extern unsigned int __sw_hweight8(unsigned int w); +extern unsigned int __sw_hweight16(unsigned int w); +extern unsigned int __sw_hweight32(unsigned int w); +extern unsigned long __sw_hweight64(__u64 w); + /* * Include this here because some architectures need generic_ffs/fls in * scope -- cgit v0.10.2 From 20503664b008e17976bff1fdbc693c77ebd6f6c9 Mon Sep 17 00:00:00 2001 From: Joern Engel Date: Mon, 3 May 2010 20:54:34 +0200 Subject: logfs: survive logfs_buf_recover read errors Refusing to mount beats a kernel crash. Signed-off-by: Joern Engel diff --git a/fs/logfs/journal.c b/fs/logfs/journal.c index fb0a613..4b0e061 100644 --- a/fs/logfs/journal.c +++ b/fs/logfs/journal.c @@ -132,10 +132,9 @@ static int read_area(struct super_block *sb, struct logfs_je_area *a) ofs = dev_ofs(sb, area->a_segno, area->a_written_bytes); if (super->s_writesize > 1) - logfs_buf_recover(area, ofs, a + 1, super->s_writesize); + return logfs_buf_recover(area, ofs, a + 1, super->s_writesize); else - logfs_buf_recover(area, ofs, NULL, 0); - return 0; + return logfs_buf_recover(area, ofs, NULL, 0); } static void *unpack(void *from, void *to) @@ -245,7 +244,7 @@ static int read_je(struct super_block *sb, u64 ofs) read_erasecount(sb, unpack(jh, scratch)); break; case JE_AREA: - read_area(sb, unpack(jh, scratch)); + err = read_area(sb, unpack(jh, scratch)); break; case JE_OBJ_ALIAS: err = logfs_load_object_aliases(sb, unpack(jh, scratch), diff --git a/fs/logfs/logfs.h b/fs/logfs/logfs.h index 0a3df1a..32bf556 100644 --- a/fs/logfs/logfs.h +++ b/fs/logfs/logfs.h @@ -598,19 +598,19 @@ void freeseg(struct super_block *sb, u32 segno); int logfs_init_areas(struct super_block *sb); void logfs_cleanup_areas(struct super_block *sb); int logfs_open_area(struct logfs_area *area, size_t bytes); -void __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len, +int __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len, int use_filler); -static inline void logfs_buf_write(struct logfs_area *area, u64 ofs, +static inline int logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len) { - __logfs_buf_write(area, ofs, buf, len, 0); + return __logfs_buf_write(area, ofs, buf, len, 0); } -static inline void logfs_buf_recover(struct logfs_area *area, u64 ofs, +static inline int logfs_buf_recover(struct logfs_area *area, u64 ofs, void *buf, size_t len) { - __logfs_buf_write(area, ofs, buf, len, 1); + return __logfs_buf_write(area, ofs, buf, len, 1); } /* super.c */ diff --git a/fs/logfs/segment.c b/fs/logfs/segment.c index f77ce2b..a9657af 100644 --- a/fs/logfs/segment.c +++ b/fs/logfs/segment.c @@ -67,7 +67,7 @@ static struct page *get_mapping_page(struct super_block *sb, pgoff_t index, return page; } -void __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len, +int __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len, int use_filler) { pgoff_t index = ofs >> PAGE_SHIFT; @@ -81,8 +81,10 @@ void __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len, copylen = min((ulong)len, PAGE_SIZE - offset); page = get_mapping_page(area->a_sb, index, use_filler); - SetPageUptodate(page); + if (IS_ERR(page)) + return PTR_ERR(page); BUG_ON(!page); /* FIXME: reserve a pool */ + SetPageUptodate(page); memcpy(page_address(page) + offset, buf, copylen); SetPagePrivate(page); page_cache_release(page); @@ -92,6 +94,7 @@ void __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len, offset = 0; index++; } while (len); + return 0; } static void pad_partial_page(struct logfs_area *area) -- cgit v0.10.2 From 05ebad852901cf9127a743df6ea10c0e8b1590c3 Mon Sep 17 00:00:00 2001 From: Joern Engel Date: Tue, 4 May 2010 19:41:09 +0200 Subject: logfs: commit reservations under space pressure Ensures we only return -ENOSPC when there really is no space. Signed-off-by: Joern Engel diff --git a/fs/logfs/file.c b/fs/logfs/file.c index 370f367..bf9b1cf 100644 --- a/fs/logfs/file.c +++ b/fs/logfs/file.c @@ -161,7 +161,17 @@ static int logfs_writepage(struct page *page, struct writeback_control *wbc) static void logfs_invalidatepage(struct page *page, unsigned long offset) { - move_page_to_btree(page); + struct logfs_block *block = logfs_block(page); + + if (block->reserved_bytes) { + struct super_block *sb = page->mapping->host->i_sb; + struct logfs_super *super = logfs_super(sb); + + super->s_dirty_pages -= block->reserved_bytes; + block->ops->free_block(sb, block); + BUG_ON(bitmap_weight(block->alias_map, LOGFS_BLOCK_FACTOR)); + } else + move_page_to_btree(page); BUG_ON(PagePrivate(page) || page->private); } diff --git a/fs/logfs/logfs.h b/fs/logfs/logfs.h index 32bf556..26a9458 100644 --- a/fs/logfs/logfs.h +++ b/fs/logfs/logfs.h @@ -394,6 +394,7 @@ struct logfs_super { int s_lock_count; mempool_t *s_block_pool; /* struct logfs_block pool */ mempool_t *s_shadow_pool; /* struct logfs_shadow pool */ + struct list_head s_writeback_list; /* writeback pages */ /* * Space accounting: * - s_used_bytes specifies space used to store valid data objects. diff --git a/fs/logfs/readwrite.c b/fs/logfs/readwrite.c index e37cee3..0718d11 100644 --- a/fs/logfs/readwrite.c +++ b/fs/logfs/readwrite.c @@ -1095,17 +1095,25 @@ static int logfs_reserve_bytes(struct inode *inode, int bytes) int get_page_reserve(struct inode *inode, struct page *page) { struct logfs_super *super = logfs_super(inode->i_sb); + struct logfs_block *block = logfs_block(page); int ret; - if (logfs_block(page) && logfs_block(page)->reserved_bytes) + if (block && block->reserved_bytes) return 0; logfs_get_wblocks(inode->i_sb, page, WF_LOCK); - ret = logfs_reserve_bytes(inode, 6 * LOGFS_MAX_OBJECTSIZE); + while ((ret = logfs_reserve_bytes(inode, 6 * LOGFS_MAX_OBJECTSIZE)) && + !list_empty(&super->s_writeback_list)) { + block = list_entry(super->s_writeback_list.next, + struct logfs_block, alias_list); + block->ops->write_block(block); + } if (!ret) { alloc_data_block(inode, page); - logfs_block(page)->reserved_bytes += 6 * LOGFS_MAX_OBJECTSIZE; + block = logfs_block(page); + block->reserved_bytes += 6 * LOGFS_MAX_OBJECTSIZE; super->s_dirty_pages += 6 * LOGFS_MAX_OBJECTSIZE; + list_move_tail(&block->alias_list, &super->s_writeback_list); } logfs_put_wblocks(inode->i_sb, page, WF_LOCK); return ret; @@ -2251,6 +2259,7 @@ int logfs_init_rw(struct super_block *sb) int min_fill = 3 * super->s_no_blocks; INIT_LIST_HEAD(&super->s_object_alias); + INIT_LIST_HEAD(&super->s_writeback_list); mutex_init(&super->s_write_mutex); super->s_block_pool = mempool_create_kmalloc_pool(min_fill, sizeof(struct logfs_block)); -- cgit v0.10.2 From 24797535e18ae219be1fc2632959327075bef5da Mon Sep 17 00:00:00 2001 From: Prasad Joshi Date: Tue, 4 May 2010 22:13:59 +0200 Subject: logfs: initialize li->li_refcount li_refcount was not re-initialized in function logfs_init_inode(), small patch that will fix the problem Signed-off-by: Prasad Joshi Signed-off-by: Joern Engel diff --git a/fs/logfs/inode.c b/fs/logfs/inode.c index 45bf86f..af78b6e 100644 --- a/fs/logfs/inode.c +++ b/fs/logfs/inode.c @@ -193,6 +193,7 @@ static void logfs_init_inode(struct super_block *sb, struct inode *inode) inode->i_ctime = CURRENT_TIME; inode->i_mtime = CURRENT_TIME; inode->i_nlink = 1; + li->li_refcount = 1; INIT_LIST_HEAD(&li->li_freeing_list); for (i = 0; i < LOGFS_EMBEDDED_FIELDS; i++) -- cgit v0.10.2 From 03d646e62b06e9364e2dbb939d67934c6c9826cd Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Mon, 21 Dec 2009 14:27:24 +0800 Subject: tracing: Make the documentation clear on trace_event boot option Make it clear that event-list is a comma separated list of events. Reported-by: KOSAKI Motohiro Signed-off-by: Li Zefan LKML-Reference: <4B2F154C.2060503@cn.fujitsu.com> Signed-off-by: Steven Rostedt diff --git a/Documentation/trace/events.txt b/Documentation/trace/events.txt index 02ac6ed..778ddf3 100644 --- a/Documentation/trace/events.txt +++ b/Documentation/trace/events.txt @@ -90,7 +90,8 @@ In order to facilitate early boot debugging, use boot option: trace_event=[event-list] -The format of this boot option is the same as described in section 2.1. +event-list is a comma separated list of events. See section 2.1 for event +format. 3. Defining an event-enabled tracepoint ======================================= -- cgit v0.10.2 From 2c2df8418ac7908eec4558407b83f16739006c54 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 30 Mar 2010 01:07:02 -0700 Subject: x86, acpi/irq: Introduce apci_isa_irq_to_gsi There are a number of cases where the current code makes the assumption that isa irqs identity map to the first 16 acpi global system intereupts. In most instances that assumption is correct as that is the required behaviour in dual i8259 mode and the default behavior in ioapic mode. However there are some systems out there that take advantage of acpis interrupt remapping for the isa irqs to have a completely different mapping of isa_irq to gsi. Introduce acpi_isa_irq_to_gsi to perform this mapping explicitly in the code that needs it. Initially this will be just the current assumed identity mapping to ensure it's introduction does not cause regressions. Signed-off-by: Eric W. Biederman LKML-Reference: <1269936436-7039-1-git-send-email-ebiederm@xmission.com> Signed-off-by: H. Peter Anvin diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 4d1a7e9..c6c90f3 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -785,6 +785,14 @@ int acpi_gsi_to_irq(u32 gsi, unsigned int *irq) return 0; } +int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi) +{ + if (isa_irq >= 16) + return -1; + *gsi = isa_irq; + return 0; +} + /* * ACPI based hotplug CPU support */ diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index cd40aba..da718d6 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -458,6 +458,14 @@ int acpi_gsi_to_irq(u32 gsi, unsigned int *irq) return 0; } +int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi) +{ + if (isa_irq >= 16) + return -1; + *gsi = isa_irq; + return 0; +} + /* * success: return IRQ number (>=0) * failure: return < 0 diff --git a/include/linux/acpi.h b/include/linux/acpi.h index b926afe..7a937da 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -116,6 +116,7 @@ extern unsigned long acpi_realmode_flags; int acpi_register_gsi (struct device *dev, u32 gsi, int triggering, int polarity); int acpi_gsi_to_irq (u32 gsi, unsigned int *irq); +int acpi_isa_irq_to_gsi (unsigned isa_irq, u32 *gsi); #ifdef CONFIG_X86_IO_APIC extern int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity); -- cgit v0.10.2 From 9a0a91bb56d2915cdb8585717de38376ad20fef9 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 30 Mar 2010 01:07:03 -0700 Subject: x86, acpi/irq: Teach acpi_get_override_irq to take a gsi not an isa_irq In perverse acpi implementations the isa irqs are not identity mapped to the first 16 gsi. Furthermore at least the extended interrupt resource capability may return gsi's and not isa irqs. So since what we get from acpi is a gsi teach acpi_get_overrride_irq to operate on a gsi instead of an isa_irq. Signed-off-by: Eric W. Biederman LKML-Reference: <1269936436-7039-2-git-send-email-ebiederm@xmission.com> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 127b871..73ec928 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -4082,22 +4082,27 @@ int __init io_apic_get_version(int ioapic) return reg_01.bits.version; } -int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity) +int acpi_get_override_irq(u32 gsi, int *trigger, int *polarity) { - int i; + int ioapic, pin, idx; if (skip_ioapic_setup) return -1; - for (i = 0; i < mp_irq_entries; i++) - if (mp_irqs[i].irqtype == mp_INT && - mp_irqs[i].srcbusirq == bus_irq) - break; - if (i >= mp_irq_entries) + ioapic = mp_find_ioapic(gsi); + if (ioapic < 0) + return -1; + + pin = mp_find_ioapic_pin(ioapic, gsi); + if (pin < 0) + return -1; + + idx = find_irq_entry(ioapic, pin, mp_INT); + if (idx < 0) return -1; - *trigger = irq_trigger(i); - *polarity = irq_polarity(i); + *trigger = irq_trigger(idx); + *polarity = irq_polarity(idx); return 0; } diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 7a937da..3da73f5 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -119,9 +119,9 @@ int acpi_gsi_to_irq (u32 gsi, unsigned int *irq); int acpi_isa_irq_to_gsi (unsigned isa_irq, u32 *gsi); #ifdef CONFIG_X86_IO_APIC -extern int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity); +extern int acpi_get_override_irq(u32 gsi, int *trigger, int *polarity); #else -#define acpi_get_override_irq(bus, trigger, polarity) (-1) +#define acpi_get_override_irq(gsi, trigger, polarity) (-1) #endif /* * This function undoes the effect of one call to acpi_register_gsi(). -- cgit v0.10.2 From 414d3448dbcb40807a1265ace64b2576ef919fbe Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 30 Mar 2010 01:07:04 -0700 Subject: x86, acpi/irq: pci device dev->irq is an isa irq not a gsi Strictly speaking on x86 (where acpi is used) dev->irq must be a dual i8259 irq input aka an isa irq. Therefore we should translate that isa irq into a gsi before passing it to a function that takes a gsi. Signed-off-by: Eric W. Biederman LKML-Reference: <1269936436-7039-3-git-send-email-ebiederm@xmission.com> Signed-off-by: H. Peter Anvin diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index b0a71ec..e4804fb 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -401,11 +401,13 @@ int acpi_pci_irq_enable(struct pci_dev *dev) * driver reported one, then use it. Exit in any case. */ if (gsi < 0) { + u32 dev_gsi; dev_warn(&dev->dev, "PCI INT %c: no GSI", pin_name(pin)); /* Interrupt Line values above 0xF are forbidden */ - if (dev->irq > 0 && (dev->irq <= 0xF)) { - printk(" - using IRQ %d\n", dev->irq); - acpi_register_gsi(&dev->dev, dev->irq, + if (dev->irq > 0 && (dev->irq <= 0xF) && + (acpi_isa_irq_to_gsi(dev->irq, &dev_gsi) == 0)) { + printk(" - using ISA IRQ %d\n", dev->irq); + acpi_register_gsi(&dev->dev, dev_gsi, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW); return 0; -- cgit v0.10.2 From 9d2062b879495649bb525cf7979126da2e45d288 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 30 Mar 2010 01:07:05 -0700 Subject: x86, acpi/irq: Fix acpi_sci_ioapic_setup so it has both bus_irq and gsi Currently acpi_sci_ioapic_setup calls mp_override_legacy_irq with bus_irq == gsi, which is wrong if we are comming from an override Instead pass the bus_irq into acpi_sci_ioapic_setup. This fix was inspired by a similar fix from: Yinghai Lu Signed-off-by: Eric W. Biederman LKML-Reference: <1269936436-7039-4-git-send-email-ebiederm@xmission.com> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index da718d6..0a036dc 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -313,7 +313,7 @@ acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end) /* * Parse Interrupt Source Override for the ACPI SCI */ -static void __init acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger) +static void __init acpi_sci_ioapic_setup(u8 bus_irq, u16 polarity, u16 trigger, u32 gsi) { if (trigger == 0) /* compatible SCI trigger is level */ trigger = 3; @@ -333,7 +333,7 @@ static void __init acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger) * If GSI is < 16, this will update its flags, * else it will create a new mp_irqs[] entry. */ - mp_override_legacy_irq(gsi, polarity, trigger, gsi); + mp_override_legacy_irq(bus_irq, polarity, trigger, gsi); /* * stash over-ride to indicate we've been here @@ -357,9 +357,10 @@ acpi_parse_int_src_ovr(struct acpi_subtable_header * header, acpi_table_print_madt_entry(header); if (intsrc->source_irq == acpi_gbl_FADT.sci_interrupt) { - acpi_sci_ioapic_setup(intsrc->global_irq, + acpi_sci_ioapic_setup(intsrc->source_irq, intsrc->inti_flags & ACPI_MADT_POLARITY_MASK, - (intsrc->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2); + (intsrc->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2, + intsrc->global_irq); return 0; } @@ -1162,7 +1163,8 @@ static int __init acpi_parse_madt_ioapic_entries(void) * pretend we got one so we can set the SCI flags. */ if (!acpi_sci_override_gsi) - acpi_sci_ioapic_setup(acpi_gbl_FADT.sci_interrupt, 0, 0); + acpi_sci_ioapic_setup(acpi_gbl_FADT.sci_interrupt, 0, 0, + acpi_gbl_FADT.sci_interrupt); /* Fill in identity legacy mappings where no override */ mp_config_acpi_legacy_irqs(); -- cgit v0.10.2 From 0fd52670fb6400be0996ac492b5ed77f3d83d69a Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 30 Mar 2010 01:07:06 -0700 Subject: x86, acpi/irq: Generalize mp_config_acpi_legacy_irqs Remove the assumption that there is not an override for isa irq 0. Instead lookup the gsi and from that lookup the ioapic and pin of each isa irq indivdually. In general this should not have any behavioural affect but in perverse cases this gets all of the details correct, instead of doing something weird. Signed-off-by: Eric W. Biederman LKML-Reference: <1269936436-7039-5-git-send-email-ebiederm@xmission.com> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 0a036dc..3ee92f2 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -961,8 +961,6 @@ void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi) void __init mp_config_acpi_legacy_irqs(void) { int i; - int ioapic; - unsigned int dstapic; struct mpc_intsrc mp_irq; #if defined (CONFIG_MCA) || defined (CONFIG_EISA) @@ -983,19 +981,27 @@ void __init mp_config_acpi_legacy_irqs(void) #endif /* - * Locate the IOAPIC that manages the ISA IRQs (0-15). - */ - ioapic = mp_find_ioapic(0); - if (ioapic < 0) - return; - dstapic = mp_ioapics[ioapic].apicid; - - /* * Use the default configuration for the IRQs 0-15. Unless * overridden by (MADT) interrupt source override entries. */ for (i = 0; i < 16; i++) { + int ioapic, pin; + unsigned int dstapic; int idx; + u32 gsi; + + /* Locate the gsi that irq i maps to. */ + if (acpi_isa_irq_to_gsi(i, &gsi)) + continue; + + /* + * Locate the IOAPIC that manages the ISA IRQ. + */ + ioapic = mp_find_ioapic(gsi); + if (ioapic < 0) + continue; + pin = mp_find_ioapic_pin(ioapic, gsi); + dstapic = mp_ioapics[ioapic].apicid; for (idx = 0; idx < mp_irq_entries; idx++) { struct mpc_intsrc *irq = mp_irqs + idx; @@ -1005,7 +1011,7 @@ void __init mp_config_acpi_legacy_irqs(void) break; /* Do we already have a mapping for this IOAPIC pin */ - if (irq->dstapic == dstapic && irq->dstirq == i) + if (irq->dstapic == dstapic && irq->dstirq == pin) break; } @@ -1020,7 +1026,7 @@ void __init mp_config_acpi_legacy_irqs(void) mp_irq.dstapic = dstapic; mp_irq.irqtype = mp_INT; mp_irq.srcbusirq = i; /* Identity mapped */ - mp_irq.dstirq = i; + mp_irq.dstirq = pin; save_mp_irq(&mp_irq); } -- cgit v0.10.2 From 9638fa521e42c9281c874c6b5a382b1ced4ee496 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 30 Mar 2010 01:07:07 -0700 Subject: x86, ioapic: Only export mp_find_ioapic and mp_find_ioapic_pin in io_apic.h Multiple declarations of the same function in different headers is a pain to maintain. Signed-off-by: Eric W. Biederman LKML-Reference: <1269936436-7039-6-git-send-email-ebiederm@xmission.com> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h index d8bf23a..29994f0 100644 --- a/arch/x86/include/asm/mpspec.h +++ b/arch/x86/include/asm/mpspec.h @@ -106,10 +106,6 @@ struct device; extern int mp_register_gsi(struct device *dev, u32 gsi, int edge_level, int active_high_low); extern int acpi_probe_gsi(void); -#ifdef CONFIG_X86_IO_APIC -extern int mp_find_ioapic(int gsi); -extern int mp_find_ioapic_pin(int ioapic, int gsi); -#endif #else /* !CONFIG_ACPI: */ static inline int acpi_probe_gsi(void) { -- cgit v0.10.2 From 4b6b19a1c7302477653d799a53d48063dd53d555 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 30 Mar 2010 01:07:08 -0700 Subject: x86, ioapic: Fix io_apic_redir_entries to return the number of entries. io_apic_redir_entries has a huge conceptual bug. It returns the maximum redirection entry not the number of redirection entries. Which simply does not match what the name of the function. This just caught me and it caught Feng Tang, and Len Brown when they wrote sfi_parse_ioapic. Modify io_apic_redir_entries to actually return the number of redirection entries, and fix the callers so that they properly handle receiving the number of the number of redirection table entries, instead of the number of redirection table entries less one. While the usage in sfi.c does not show up in this patch it is fixed by virtue of the fact that io_apic_redir_entries now has the semantics sfi_parse_ioapic most reasonably expects. Signed-off-by: Eric W. Biederman LKML-Reference: <1269936436-7039-7-git-send-email-ebiederm@xmission.com> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 73ec928..0a053e6 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -3855,7 +3855,11 @@ int __init io_apic_get_redir_entries (int ioapic) reg_01.raw = io_apic_read(ioapic, 1); raw_spin_unlock_irqrestore(&ioapic_lock, flags); - return reg_01.bits.entries; + /* The register returns the maximum index redir index + * supported, which is one less than the total number of redir + * entries. + */ + return reg_01.bits.entries + 1; } void __init probe_nr_irqs_gsi(void) @@ -3871,7 +3875,7 @@ void __init probe_nr_irqs_gsi(void) nr = 0; for (idx = 0; idx < nr_ioapics; idx++) - nr += io_apic_get_redir_entries(idx) + 1; + nr += io_apic_get_redir_entries(idx); if (nr > nr_irqs_gsi) nr_irqs_gsi = nr; @@ -4306,7 +4310,7 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base) */ mp_gsi_routing[idx].gsi_base = gsi_base; mp_gsi_routing[idx].gsi_end = gsi_base + - io_apic_get_redir_entries(idx); + io_apic_get_redir_entries(idx) - 1; printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, " "GSI %d-%d\n", idx, mp_ioapics[idx].apicid, -- cgit v0.10.2 From eddb0c55a14074d6bac8c2ef169aefd7e2c6f139 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 30 Mar 2010 01:07:09 -0700 Subject: x86, ioapic: Fix the types of gsi values This patches fixes the types of gsi_base and gsi_end values in struct mp_ioapic_gsi, and the gsi parameter of mp_find_ioapic and mp_find_ioapic_pin A gsi is cannonically a u32, not an int. Signed-off-by: Eric W. Biederman LKML-Reference: <1269936436-7039-8-git-send-email-ebiederm@xmission.com> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h index 35832a0..feeaf0d 100644 --- a/arch/x86/include/asm/io_apic.h +++ b/arch/x86/include/asm/io_apic.h @@ -180,12 +180,12 @@ extern void ioapic_write_entry(int apic, int pin, extern void setup_ioapic_ids_from_mpc(void); struct mp_ioapic_gsi{ - int gsi_base; - int gsi_end; + u32 gsi_base; + u32 gsi_end; }; extern struct mp_ioapic_gsi mp_gsi_routing[]; -int mp_find_ioapic(int gsi); -int mp_find_ioapic_pin(int ioapic, int gsi); +int mp_find_ioapic(u32 gsi); +int mp_find_ioapic_pin(int ioapic, u32 gsi); void __init mp_register_ioapic(int id, u32 address, u32 gsi_base); extern void __init pre_init_apic_IRQ0(void); @@ -197,7 +197,7 @@ static const int timer_through_8259 = 0; static inline void ioapic_init_mappings(void) { } static inline void ioapic_insert_resources(void) { } static inline void probe_nr_irqs_gsi(void) { } -static inline int mp_find_ioapic(int gsi) { return 0; } +static inline int mp_find_ioapic(u32 gsi) { return 0; } struct io_apic_irq_attr; static inline int io_apic_set_pci_routing(struct device *dev, int irq, diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 0a053e6..9ab9762 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -4247,7 +4247,7 @@ void __init ioapic_insert_resources(void) } } -int mp_find_ioapic(int gsi) +int mp_find_ioapic(u32 gsi) { int i = 0; @@ -4262,7 +4262,7 @@ int mp_find_ioapic(int gsi) return -1; } -int mp_find_ioapic_pin(int ioapic, int gsi) +int mp_find_ioapic_pin(int ioapic, u32 gsi) { if (WARN_ON(ioapic == -1)) return -1; -- cgit v0.10.2 From 5777372af5c929b8f3c706ed7b295b7279537c88 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 30 Mar 2010 01:07:10 -0700 Subject: x86, ioapic: Teach mp_register_ioapic to compute a global gsi_end Add the global variable gsi_end and teach mp_register_ioapic to keep it uptodate as we add more ioapics into the system. ioapics can only be added early in boot so the code that runs later can treat gsi_end as a constant. Remove the have hacks in sfi.c to second guess mp_register_ioapic by keeping t's own running total of how many gsi's have been seen, and instead use the gsi_end. Signed-off-by: Eric W. Biederman LKML-Reference: <1269936436-7039-9-git-send-email-ebiederm@xmission.com> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h index feeaf0d..37b0f2b 100644 --- a/arch/x86/include/asm/io_apic.h +++ b/arch/x86/include/asm/io_apic.h @@ -184,6 +184,7 @@ struct mp_ioapic_gsi{ u32 gsi_end; }; extern struct mp_ioapic_gsi mp_gsi_routing[]; +extern u32 gsi_end; int mp_find_ioapic(u32 gsi); int mp_find_ioapic_pin(int ioapic, u32 gsi); void __init mp_register_ioapic(int id, u32 address, u32 gsi_base); diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 9ab9762..f807255 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -89,6 +89,9 @@ int nr_ioapics; /* IO APIC gsi routing info */ struct mp_ioapic_gsi mp_gsi_routing[MAX_IO_APICS]; +/* The last gsi number used */ +u32 gsi_end; + /* MP IRQ source entries */ struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCES]; @@ -4312,6 +4315,9 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base) mp_gsi_routing[idx].gsi_end = gsi_base + io_apic_get_redir_entries(idx) - 1; + if (mp_gsi_routing[idx].gsi_end > gsi_end) + gsi_end = mp_gsi_routing[idx].gsi_end; + printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, " "GSI %d-%d\n", idx, mp_ioapics[idx].apicid, mp_ioapics[idx].apicver, mp_ioapics[idx].apicaddr, diff --git a/arch/x86/kernel/sfi.c b/arch/x86/kernel/sfi.c index 34e0993..7ded578 100644 --- a/arch/x86/kernel/sfi.c +++ b/arch/x86/kernel/sfi.c @@ -81,7 +81,6 @@ static int __init sfi_parse_cpus(struct sfi_table_header *table) #endif /* CONFIG_X86_LOCAL_APIC */ #ifdef CONFIG_X86_IO_APIC -static u32 gsi_base; static int __init sfi_parse_ioapic(struct sfi_table_header *table) { @@ -94,8 +93,7 @@ static int __init sfi_parse_ioapic(struct sfi_table_header *table) pentry = (struct sfi_apic_table_entry *)sb->pentry; for (i = 0; i < num; i++) { - mp_register_ioapic(i, pentry->phys_addr, gsi_base); - gsi_base += io_apic_get_redir_entries(i); + mp_register_ioapic(i, pentry->phys_addr, gsi_end + 1); pentry++; } -- cgit v0.10.2 From cf7500c0ea133d66f8449d86392d83f840102632 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 30 Mar 2010 01:07:11 -0700 Subject: x86, ioapic: In mpparse use mp_register_ioapic Long ago MP_ioapic_info was the primary way of setting up our ioapic data structures and mp_register_ioapic was a compatibility shim for acpi code. Now the situation is reversed and and mp_register_ioapic is the primary way of setting up our ioapic data structures. Keep the setting up of ioapic data structures uniform by having mp_register_ioapic call mp_register_ioapic. This changes a few fields: - type: is now hardset to MP_IOAPIC but type had to bey MP_IOAPIC or MP_ioapic_info would not have been called. - flags: is now hard coded to MPC_APIC_USABLE. We require flags to contain at least MPC_APIC_USEBLE in MP_ioapic_info and we don't ever examine flags so dropping a few flags that might possibly exist that we have never used is harmless. - apicaddr: Unchanged - apicver: Read from the ioapic instead of using the cached hardware value in the MP table. The real hardware value will be more accurate. - apicid: Now verified to be unique and changed if it is not. If the BIOS got this right this is a noop. If the BIOS did not fixing things appears to be the better solution. This adds gsi_base and gsi_end values to our ioapics defined with the mpatable, which will make our lives simpler later since we can always assume gsi_base and gsi_end are valid. Signed-off-by: Eric W. Biederman LKML-Reference: <1269936436-7039-10-git-send-email-ebiederm@xmission.com> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index e81030f..5ae5d24 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c @@ -115,21 +115,6 @@ static void __init MP_bus_info(struct mpc_bus *m) printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str); } -static int bad_ioapic(unsigned long address) -{ - if (nr_ioapics >= MAX_IO_APICS) { - printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded " - "(found %d)\n", MAX_IO_APICS, nr_ioapics); - panic("Recompile kernel with bigger MAX_IO_APICS!\n"); - } - if (!address) { - printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address" - " found in table, skipping!\n"); - return 1; - } - return 0; -} - static void __init MP_ioapic_info(struct mpc_ioapic *m) { if (!(m->flags & MPC_APIC_USABLE)) @@ -138,15 +123,7 @@ static void __init MP_ioapic_info(struct mpc_ioapic *m) printk(KERN_INFO "I/O APIC #%d Version %d at 0x%X.\n", m->apicid, m->apicver, m->apicaddr); - if (bad_ioapic(m->apicaddr)) - return; - - mp_ioapics[nr_ioapics].apicaddr = m->apicaddr; - mp_ioapics[nr_ioapics].apicid = m->apicid; - mp_ioapics[nr_ioapics].type = m->type; - mp_ioapics[nr_ioapics].apicver = m->apicver; - mp_ioapics[nr_ioapics].flags = m->flags; - nr_ioapics++; + mp_register_ioapic(m->apicid, m->apicaddr, gsi_end + 1); } static void print_MP_intsrc_info(struct mpc_intsrc *m) -- cgit v0.10.2 From 7716a5c4ff5f1f3dc5e9edcab125cbf7fceef0af Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 30 Mar 2010 01:07:12 -0700 Subject: x86, ioapic: Move nr_ioapic_registers calculation to mp_register_ioapic. Now that all ioapic registration happens in mp_register_ioapic we can move the calculation of nr_ioapic_registers there from enable_IO_APIC. The number of ioapic registers is already calucated in mp_register_ioapic so all that really needs to be done is to save the caluclated value in nr_ioapic_registers. Signed-off-by: Eric W. Biederman LKML-Reference: <1269936436-7039-11-git-send-email-ebiederm@xmission.com> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index f807255..dae9240 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -1953,20 +1953,8 @@ static struct { int pin, apic; } ioapic_i8259 = { -1, -1 }; void __init enable_IO_APIC(void) { - union IO_APIC_reg_01 reg_01; int i8259_apic, i8259_pin; int apic; - unsigned long flags; - - /* - * The number of IO-APIC IRQ registers (== #pins): - */ - for (apic = 0; apic < nr_ioapics; apic++) { - raw_spin_lock_irqsave(&ioapic_lock, flags); - reg_01.raw = io_apic_read(apic, 1); - raw_spin_unlock_irqrestore(&ioapic_lock, flags); - nr_ioapic_registers[apic] = reg_01.bits.entries+1; - } if (!legacy_pic->nr_legacy_irqs) return; @@ -4293,6 +4281,7 @@ static int bad_ioapic(unsigned long address) void __init mp_register_ioapic(int id, u32 address, u32 gsi_base) { int idx = 0; + int entries; if (bad_ioapic(address)) return; @@ -4311,9 +4300,14 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base) * Build basic GSI lookup table to facilitate gsi->io_apic lookups * and to prevent reprogramming of IOAPIC pins (PCI GSIs). */ + entries = io_apic_get_redir_entries(idx); mp_gsi_routing[idx].gsi_base = gsi_base; - mp_gsi_routing[idx].gsi_end = gsi_base + - io_apic_get_redir_entries(idx) - 1; + mp_gsi_routing[idx].gsi_end = gsi_base + entries - 1; + + /* + * The number of IO-APIC IRQ registers (== #pins): + */ + nr_ioapic_registers[idx] = entries; if (mp_gsi_routing[idx].gsi_end > gsi_end) gsi_end = mp_gsi_routing[idx].gsi_end; -- cgit v0.10.2 From d464207c4fdd70c2a0febd4f9c58206fa915bb36 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 30 Mar 2010 01:07:13 -0700 Subject: x86, ioapic: Optimize pin_2_irq Now that all ioapics have valid gsi_base values use this to accellerate pin_2_irq. In the case of acpi this also ensures that pin_2_irq will compute the same irq value for an ioapic pin as acpi will. Signed-off-by: Eric W. Biederman LKML-Reference: <1269936436-7039-12-git-send-email-ebiederm@xmission.com> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index dae9240..0d35f46 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -1019,7 +1019,7 @@ static inline int irq_trigger(int idx) int (*ioapic_renumber_irq)(int ioapic, int irq); static int pin_2_irq(int idx, int apic, int pin) { - int irq, i; + int irq; int bus = mp_irqs[idx].srcbus; /* @@ -1031,18 +1031,13 @@ static int pin_2_irq(int idx, int apic, int pin) if (test_bit(bus, mp_bus_not_pci)) { irq = mp_irqs[idx].srcbusirq; } else { - /* - * PCI IRQs are mapped in order - */ - i = irq = 0; - while (i < apic) - irq += nr_ioapic_registers[i++]; - irq += pin; + u32 gsi = mp_gsi_routing[apic].gsi_base + pin; /* * For MPS mode, so far only needed by ES7000 platform */ if (ioapic_renumber_irq) - irq = ioapic_renumber_irq(apic, irq); + gsi = ioapic_renumber_irq(apic, gsi); + irq = gsi; } #ifdef CONFIG_X86_32 -- cgit v0.10.2 From 4afc51a835d3aeba11c35090f524e05c84586d27 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 30 Mar 2010 01:07:14 -0700 Subject: x86, ioapic: Simplify probe_nr_irqs_gsi. Use the global gsi_end value now that all ioapics have valid gsi numbers instead of a combination of acpi_probe_gsi and walking all of the ioapics and couting their number of entries by hand if acpi_probe_gsi gave us an answer we did not like. Signed-off-by: Eric W. Biederman LKML-Reference: <1269936436-7039-13-git-send-email-ebiederm@xmission.com> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h index 29994f0..c82868e 100644 --- a/arch/x86/include/asm/mpspec.h +++ b/arch/x86/include/asm/mpspec.h @@ -105,12 +105,6 @@ extern void mp_config_acpi_legacy_irqs(void); struct device; extern int mp_register_gsi(struct device *dev, u32 gsi, int edge_level, int active_high_low); -extern int acpi_probe_gsi(void); -#else /* !CONFIG_ACPI: */ -static inline int acpi_probe_gsi(void) -{ - return 0; -} #endif /* CONFIG_ACPI */ #define PHYSID_ARRAY_SIZE BITS_TO_LONGS(MAX_APICS) diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 3ee92f2..07a63ce 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -876,29 +876,6 @@ static int __init acpi_parse_madt_lapic_entries(void) extern int es7000_plat; #endif -int __init acpi_probe_gsi(void) -{ - int idx; - int gsi; - int max_gsi = 0; - - if (acpi_disabled) - return 0; - - if (!acpi_ioapic) - return 0; - - max_gsi = 0; - for (idx = 0; idx < nr_ioapics; idx++) { - gsi = mp_gsi_routing[idx].gsi_end; - - if (gsi > max_gsi) - max_gsi = gsi; - } - - return max_gsi + 1; -} - static void assign_to_mp_irq(struct mpc_intsrc *m, struct mpc_intsrc *mp_irq) { diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 0d35f46..9f3f6ca 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -3850,22 +3850,11 @@ int __init io_apic_get_redir_entries (int ioapic) void __init probe_nr_irqs_gsi(void) { - int nr = 0; + int nr; - nr = acpi_probe_gsi(); - if (nr > nr_irqs_gsi) { + nr = gsi_end + 1; + if (nr > nr_irqs_gsi) nr_irqs_gsi = nr; - } else { - /* for acpi=off or acpi is not compiled in */ - int idx; - - nr = 0; - for (idx = 0; idx < nr_ioapics; idx++) - nr += io_apic_get_redir_entries(idx); - - if (nr > nr_irqs_gsi) - nr_irqs_gsi = nr; - } printk(KERN_DEBUG "nr_irqs_gsi: %d\n", nr_irqs_gsi); } -- cgit v0.10.2 From 988856ee1623bd37e384105f7bb2b7fe44c009f6 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 30 Mar 2010 01:07:15 -0700 Subject: x86, acpi/irq: Handle isa irqs that are not identity mapped to gsi's. ACPI irq source overrides are allowed for the 16 isa irqs and are allowed to map any gsi to any isa irq. A few motherboards have been seen to take advantage of this and put the isa irqs on the 2nd or 3rd ioapic. This causes some problems, most notably the fact that we can not use any gsi < 16. To correct this move the gsis that are not isa irqs and have a gsi number < 16 into the linux irq space just past gsi_end. This is what the es7000 platform is doing today. Moving only the low 16 gsis above the rest of the gsi's only penalizes weird platforms, leaving sane acpi implementations with a 1-1 mapping of gsis and irqs. Signed-off-by: Eric W. Biederman LKML-Reference: <1269936436-7039-14-git-send-email-ebiederm@xmission.com> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 07a63ce..325fbba 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -94,6 +94,53 @@ enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_PIC; /* + * ISA irqs by default are the first 16 gsis but can be + * any gsi as specified by an interrupt source override. + */ +static u32 isa_irq_to_gsi[NR_IRQS_LEGACY] __read_mostly = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 +}; + +static unsigned int gsi_to_irq(unsigned int gsi) +{ + unsigned int irq = gsi + NR_IRQS_LEGACY; + unsigned int i; + + for (i = 0; i < NR_IRQS_LEGACY; i++) { + if (isa_irq_to_gsi[i] == gsi) { + return i; + } + } + + /* Provide an identity mapping of gsi == irq + * except on truly weird platforms that have + * non isa irqs in the first 16 gsis. + */ + if (gsi >= NR_IRQS_LEGACY) + irq = gsi; + else + irq = gsi_end + 1 + gsi; + + return irq; +} + +static u32 irq_to_gsi(int irq) +{ + unsigned int gsi; + + if (irq < NR_IRQS_LEGACY) + gsi = isa_irq_to_gsi[irq]; + else if (irq <= gsi_end) + gsi = irq; + else if (irq <= (gsi_end + NR_IRQS_LEGACY)) + gsi = irq - gsi_end; + else + gsi = 0xffffffff; + + return gsi; +} + +/* * Temporarily use the virtual area starting from FIX_IO_APIC_BASE_END, * to map the target physical address. The problem is that set_fixmap() * provides a single page, and it is possible that the page is not @@ -449,7 +496,7 @@ void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger) int acpi_gsi_to_irq(u32 gsi, unsigned int *irq) { - *irq = gsi; + *irq = gsi_to_irq(gsi); #ifdef CONFIG_X86_IO_APIC if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) @@ -463,7 +510,7 @@ int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi) { if (isa_irq >= 16) return -1; - *gsi = isa_irq; + *gsi = irq_to_gsi(isa_irq); return 0; } @@ -491,7 +538,7 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity) plat_gsi = mp_register_gsi(dev, gsi, trigger, polarity); } #endif - irq = plat_gsi; + irq = gsi_to_irq(plat_gsi); return irq; } @@ -933,6 +980,8 @@ void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi) mp_irq.dstirq = pin; /* INTIN# */ save_mp_irq(&mp_irq); + + isa_irq_to_gsi[bus_irq] = gsi; } void __init mp_config_acpi_legacy_irqs(void) @@ -1086,7 +1135,7 @@ int mp_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity) set_io_apic_irq_attr(&irq_attr, ioapic, ioapic_pin, trigger == ACPI_EDGE_SENSITIVE ? 0 : 1, polarity == ACPI_ACTIVE_HIGH ? 0 : 1); - io_apic_set_pci_routing(dev, gsi, &irq_attr); + io_apic_set_pci_routing(dev, gsi_to_irq(gsi), &irq_attr); return gsi; } diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 9f3f6ca..594827c 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -1037,7 +1037,11 @@ static int pin_2_irq(int idx, int apic, int pin) */ if (ioapic_renumber_irq) gsi = ioapic_renumber_irq(apic, gsi); - irq = gsi; + + if (gsi >= NR_IRQS_LEGACY) + irq = gsi; + else + irq = gsi_end + 1 + gsi; } #ifdef CONFIG_X86_32 @@ -3852,7 +3856,7 @@ void __init probe_nr_irqs_gsi(void) { int nr; - nr = gsi_end + 1; + nr = gsi_end + 1 + NR_IRQS_LEGACY; if (nr > nr_irqs_gsi) nr_irqs_gsi = nr; -- cgit v0.10.2 From 7b20bd5fb902088579af4e70f7f802b93181a628 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 30 Mar 2010 01:07:16 -0700 Subject: x86, irq: Kill io_apic_renumber_irq Now that the generic irq layer is performing the exact same remapping as io_apic_renumber_irq we can kill this weird es7000 specific function. Signed-off-by: Eric W. Biederman LKML-Reference: <1269936436-7039-15-git-send-email-ebiederm@xmission.com> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h index 37b0f2b..9da192a 100644 --- a/arch/x86/include/asm/io_apic.h +++ b/arch/x86/include/asm/io_apic.h @@ -159,7 +159,6 @@ struct io_apic_irq_attr; extern int io_apic_set_pci_routing(struct device *dev, int irq, struct io_apic_irq_attr *irq_attr); void setup_IO_APIC_irq_extra(u32 gsi); -extern int (*ioapic_renumber_irq)(int ioapic, int irq); extern void ioapic_init_mappings(void); extern void ioapic_insert_resources(void); diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 325fbba..9a5ed58 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -1117,11 +1117,6 @@ int mp_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity) ioapic_pin = mp_find_ioapic_pin(ioapic, gsi); -#ifdef CONFIG_X86_32 - if (ioapic_renumber_irq) - gsi = ioapic_renumber_irq(ioapic, gsi); -#endif - if (ioapic_pin > MP_MAX_IOAPIC_PIN) { printk(KERN_ERR "Invalid reference to IOAPIC pin " "%d-%d\n", mp_ioapics[ioapic].apicid, diff --git a/arch/x86/kernel/apic/es7000_32.c b/arch/x86/kernel/apic/es7000_32.c index 03ba1b8..425e53a 100644 --- a/arch/x86/kernel/apic/es7000_32.c +++ b/arch/x86/kernel/apic/es7000_32.c @@ -131,24 +131,6 @@ int es7000_plat; static unsigned int base; -static int -es7000_rename_gsi(int ioapic, int gsi) -{ - if (es7000_plat == ES7000_ZORRO) - return gsi; - - if (!base) { - int i; - for (i = 0; i < nr_ioapics; i++) - base += nr_ioapic_registers[i]; - } - - if (!ioapic && (gsi < 16)) - gsi += base; - - return gsi; -} - static int __cpuinit wakeup_secondary_cpu_via_mip(int cpu, unsigned long eip) { unsigned long vect = 0, psaival = 0; @@ -190,7 +172,6 @@ static void setup_unisys(void) es7000_plat = ES7000_ZORRO; else es7000_plat = ES7000_CLASSIC; - ioapic_renumber_irq = es7000_rename_gsi; } /* diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 594827c..d174d88 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -1016,7 +1016,6 @@ static inline int irq_trigger(int idx) return MPBIOS_trigger(idx); } -int (*ioapic_renumber_irq)(int ioapic, int irq); static int pin_2_irq(int idx, int apic, int pin) { int irq; @@ -1032,11 +1031,6 @@ static int pin_2_irq(int idx, int apic, int pin) irq = mp_irqs[idx].srcbusirq; } else { u32 gsi = mp_gsi_routing[apic].gsi_base + pin; - /* - * For MPS mode, so far only needed by ES7000 platform - */ - if (ioapic_renumber_irq) - gsi = ioapic_renumber_irq(apic, gsi); if (gsi >= NR_IRQS_LEGACY) irq = gsi; -- cgit v0.10.2 From 5dfc589a8467470226feccdc50f1b32713318e7b Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 4 May 2010 16:14:46 -0700 Subject: ceph: unregister bdi before kill_anon_super releases device name Unregister and destroy the bdi in put_super, after mount is r/o, but before put_anon_super releases the device name. For symmetry, bdi_destroy in destroy_client (we bdi_init in create_client). Only set s_bdi if bdi_register succeeds, since we use it to decide whether to bdi_unregister. Signed-off-by: Sage Weil diff --git a/fs/ceph/super.c b/fs/ceph/super.c index f888cf4..110857b 100644 --- a/fs/ceph/super.c +++ b/fs/ceph/super.c @@ -47,10 +47,20 @@ const char *ceph_file_part(const char *s, int len) */ static void ceph_put_super(struct super_block *s) { - struct ceph_client *cl = ceph_client(s); + struct ceph_client *client = ceph_sb_to_client(s); dout("put_super\n"); - ceph_mdsc_close_sessions(&cl->mdsc); + ceph_mdsc_close_sessions(&client->mdsc); + + /* + * ensure we release the bdi before put_anon_super releases + * the device name. + */ + if (s->s_bdi == &client->backing_dev_info) { + bdi_unregister(&client->backing_dev_info); + s->s_bdi = NULL; + } + return; } @@ -636,6 +646,8 @@ static void ceph_destroy_client(struct ceph_client *client) destroy_workqueue(client->pg_inv_wq); destroy_workqueue(client->trunc_wq); + bdi_destroy(&client->backing_dev_info); + if (client->msgr) ceph_messenger_destroy(client->msgr); mempool_destroy(client->wb_pagevec_pool); @@ -876,14 +888,14 @@ static int ceph_register_bdi(struct super_block *sb, struct ceph_client *client) { int err; - sb->s_bdi = &client->backing_dev_info; - /* set ra_pages based on rsize mount option? */ if (client->mount_args->rsize >= PAGE_CACHE_SIZE) client->backing_dev_info.ra_pages = (client->mount_args->rsize + PAGE_CACHE_SIZE - 1) >> PAGE_SHIFT; err = bdi_register_dev(&client->backing_dev_info, sb->s_dev); + if (!err) + sb->s_bdi = &client->backing_dev_info; return err; } @@ -957,9 +969,6 @@ static void ceph_kill_sb(struct super_block *s) dout("kill_sb %p\n", s); ceph_mdsc_pre_umount(&client->mdsc); kill_anon_super(s); /* will call put_super after sb is r/o */ - if (s->s_bdi == &client->backing_dev_info) - bdi_unregister(&client->backing_dev_info); - bdi_destroy(&client->backing_dev_info); ceph_destroy_client(client); } -- cgit v0.10.2 From 762253741942d8ddbaca1c1ee62d7ed57544332b Mon Sep 17 00:00:00 2001 From: Harro Haan Date: Mon, 1 Mar 2010 17:54:55 +0100 Subject: ARM: 5966/1: at91_udc HW glitch Add some delay to avoid reading CSR TXCOUNT too early after updating it. For more info about this HW glitch see: http://lists.arm.linux.org.uk/lurker/message/20090325.150843.f515c02f.en.html http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20100129/10ba0f8b/attachment.el http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20100203/09cdb3b4/attachment.el http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20100203/08b5b249/attachment.el First applied: "Fix soft lockup in at91 udc driver" http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=5965 Signed-off-by: Anti Sullin Signed-off-by: Harro Haan Acked-by: Remy Bohmer Acked-by: Andrew Victor Signed-off-by: Russell King diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index 12ac9cd..b3bd22e 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -366,6 +366,13 @@ rescan: if (is_done) done(ep, req, 0); else if (ep->is_pingpong) { + /* + * One dummy read to delay the code because of a HW glitch: + * CSR returns bad RXCOUNT when read too soon after updating + * RX_DATA_BK flags. + */ + csr = __raw_readl(creg); + bufferspace -= count; buf += count; goto rescan; -- cgit v0.10.2 From 9890948d857c2120c234b0ca91a80416e8f747fb Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 4 May 2010 20:58:51 -0300 Subject: perf report: Make dso__calc_col_width agree with hist_entry__dso_snprintf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The first was always using the ->long_name, while the later used ->short_name if verbose was not set, resulting in the dso column to be much wider than needed most of the time. Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 2477270..23d5dfd 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -626,8 +626,10 @@ static void dso__calc_col_width(struct dso *self) if (!symbol_conf.col_width_list_str && !symbol_conf.field_sep && (!symbol_conf.dso_list || strlist__has_entry(symbol_conf.dso_list, self->name))) { - unsigned int slen = strlen(self->name); - if (slen > dsos__col_width) + u16 slen = self->short_name_len; + if (verbose) + slen = self->long_name_len; + if (dsos__col_width < slen) dsos__col_width = slen; } -- cgit v0.10.2 From db620b1c2fb172346dc54eb62bba9b4a117d173b Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Tue, 4 May 2010 22:20:16 -0500 Subject: perf/record: simplify TRACE_INFO tracepoint check Fix a couple of inefficiencies and redundancies related to have_tracepoints() and its use when checking whether to write TRACE_INFO. First, there's no need to use get_tracepoints_path() in have_tracepoints() - we really just want the part that checks whether any attributes correspondo to tracepoints. Second, we really don't care about raw_samples per se - tracepoints are always raw_samples. In any case, the have_tracepoints() check should be sufficient to decide whether or not to write TRACE_INFO. Cc: Frederic Weisbecker Cc: Ingo Molnar , Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Acked-by: Frederic Weisbecker LKML-Reference: <1273030770.6383.6.camel@tropicana> Signed-off-by: Tom Zanussi Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 0ff67d1..d3981ac 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -560,17 +560,8 @@ static int __cmd_record(int argc, const char **argv) return err; } - if (raw_samples && have_tracepoints(attrs, nr_counters)) { + if (have_tracepoints(attrs, nr_counters)) perf_header__set_feat(&session->header, HEADER_TRACE_INFO); - } else { - for (i = 0; i < nr_counters; i++) { - if (attrs[i].sample_type & PERF_SAMPLE_RAW && - attrs[i].type == PERF_TYPE_TRACEPOINT) { - perf_header__set_feat(&session->header, HEADER_TRACE_INFO); - break; - } - } - } atexit(atexit_header); diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c index 0a1fb9d..b157260 100644 --- a/tools/perf/util/trace-event-info.c +++ b/tools/perf/util/trace-event-info.c @@ -489,7 +489,13 @@ get_tracepoints_path(struct perf_event_attr *pattrs, int nb_events) bool have_tracepoints(struct perf_event_attr *pattrs, int nb_events) { - return get_tracepoints_path(pattrs, nb_events) ? true : false; + int i; + + for (i = 0; i < nb_events; i++) + if (pattrs[i].type == PERF_TYPE_TRACEPOINT) + return true; + + return false; } int read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events) -- cgit v0.10.2 From 9e32a3cb0661a6a30e0fd2b77ce85293805e6337 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 5 May 2010 11:20:05 -0300 Subject: perf list: Add explanation about raw hardware event descriptors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using explanation given by Ingo Molnar in the oprofile mailing list. Suggested-by: Nick Black Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Nick Black Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt index 8290b94..ad765e0 100644 --- a/tools/perf/Documentation/perf-list.txt +++ b/tools/perf/Documentation/perf-list.txt @@ -15,6 +15,24 @@ DESCRIPTION This command displays the symbolic event types which can be selected in the various perf commands with the -e option. +RAW HARDWARE EVENT DESCRIPTOR +----------------------------- +Even when an event is not available in a symbolic form within perf right now, +it can be encoded as , for instance, if the Intel docs +describe an event as: + + Event Umask Event Mask + Num. Value Mnemonic Description Comment + + A8H 01H LSD.UOPS Counts the number of micro-ops Use cmask=1 and + delivered by loop stream detector invert to count + cycles + +raw encoding of 0x1A8 can be used: + + perf stat -e r1a8 -a sleep 1 + perf record -e r1a8 ... + OPTIONS ------- None diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 600d327..bc8b7e6 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -936,7 +936,7 @@ void print_events(void) printf("\n"); printf(" %-42s [%s]\n", - "rNNN", event_type_descriptors[PERF_TYPE_RAW]); + "rNNN (NNN=)", event_type_descriptors[PERF_TYPE_RAW]); printf("\n"); printf(" %-42s [%s]\n", -- cgit v0.10.2 From 4778e0e8c64f683a71632dba1cff1f85f76f83c4 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 5 May 2010 11:23:27 -0300 Subject: perf tools: Fixup minor doc formatting issues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt index c9dcade..5164a65 100644 --- a/tools/perf/Documentation/perf-annotate.txt +++ b/tools/perf/Documentation/perf-annotate.txt @@ -1,5 +1,5 @@ perf-annotate(1) -============== +================ NAME ---- diff --git a/tools/perf/Documentation/perf-bench.txt b/tools/perf/Documentation/perf-bench.txt index 0181ddd..a3dbadb 100644 --- a/tools/perf/Documentation/perf-bench.txt +++ b/tools/perf/Documentation/perf-bench.txt @@ -1,5 +1,5 @@ perf-bench(1) -============ +============= NAME ---- diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt index 8974e20..20d97d8 100644 --- a/tools/perf/Documentation/perf-diff.txt +++ b/tools/perf/Documentation/perf-diff.txt @@ -1,5 +1,5 @@ perf-diff(1) -============== +============ NAME ---- diff --git a/tools/perf/Documentation/perf-kmem.txt b/tools/perf/Documentation/perf-kmem.txt index eac4d852e..a52fcde 100644 --- a/tools/perf/Documentation/perf-kmem.txt +++ b/tools/perf/Documentation/perf-kmem.txt @@ -1,5 +1,5 @@ perf-kmem(1) -============== +============ NAME ---- diff --git a/tools/perf/Documentation/perf-trace-python.txt b/tools/perf/Documentation/perf-trace-python.txt index 16a8650..864aac2 100644 --- a/tools/perf/Documentation/perf-trace-python.txt +++ b/tools/perf/Documentation/perf-trace-python.txt @@ -1,5 +1,5 @@ perf-trace-python(1) -================== +==================== NAME ---- diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt index 8879299..122ec9d 100644 --- a/tools/perf/Documentation/perf-trace.txt +++ b/tools/perf/Documentation/perf-trace.txt @@ -1,5 +1,5 @@ perf-trace(1) -============== +============= NAME ---- -- cgit v0.10.2 From 17dcd13a3793d434c030dcf9c52ad0d43493b2a0 Mon Sep 17 00:00:00 2001 From: Arnaud Patard Date: Thu, 22 Apr 2010 10:47:43 +0200 Subject: ARM: h1940: fix touchscreen support The touchscreen is using the adc device so it needs to be in the device list Signed-off-by: Arnaud Patard Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c index fbedd07..bd4ced5 100644 --- a/arch/arm/mach-s3c2410/mach-h1940.c +++ b/arch/arm/mach-s3c2410/mach-h1940.c @@ -271,7 +271,6 @@ static struct platform_device h1940_lcd_powerdev = { }; static struct platform_device *h1940_devices[] __initdata = { - &s3c_device_ts, &s3c_device_ohci, &s3c_device_lcd, &s3c_device_wdt, @@ -285,6 +284,8 @@ static struct platform_device *h1940_devices[] __initdata = { &s3c_device_timer[0], &h1940_backlight, &h1940_lcd_powerdev, + &s3c_device_adc, + &s3c_device_ts, }; static void __init h1940_map_io(void) -- cgit v0.10.2 From f44c67cdc3182dd59cae299488687c6280027410 Mon Sep 17 00:00:00 2001 From: Arnaud Patard Date: Thu, 22 Apr 2010 10:47:44 +0200 Subject: ARM: S3C24XX: fix s3c2410fb platdata passing Setting s3c2410fb_mach_info displays field with a struct marked as __initdata means it won't be available later for ioctls like FBIOPUT_VSCREENINFO and they will fail. Copying in s3c24xx_fb_set_platdata() is fixing this issue. Signed-off-by: Arnaud Patard Signed-off-by: Ben Dooks diff --git a/arch/arm/plat-s3c24xx/devs.c b/arch/arm/plat-s3c24xx/devs.c index 9265f09..429e453 100644 --- a/arch/arm/plat-s3c24xx/devs.c +++ b/arch/arm/plat-s3c24xx/devs.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -149,10 +150,14 @@ void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *pd) { struct s3c2410fb_mach_info *npd; - npd = kmalloc(sizeof(*npd), GFP_KERNEL); + npd = kmemdup(pd, sizeof(*npd), GFP_KERNEL); if (npd) { - memcpy(npd, pd, sizeof(*npd)); s3c_device_lcd.dev.platform_data = npd; + npd->displays = kmemdup(pd->displays, + sizeof(struct s3c2410fb_display) * npd->num_displays, + GFP_KERNEL); + if (!npd->displays) + printk(KERN_ERR "no memory for LCD display data\n"); } else { printk(KERN_ERR "no memory for LCD platform data\n"); } -- cgit v0.10.2 From 1f138f13890afc824443a9cfcebe9ecae7727666 Mon Sep 17 00:00:00 2001 From: Arnaud Patard Date: Thu, 22 Apr 2010 10:47:45 +0200 Subject: ARM: S3C24XX: s3c24xx_mci_set_platdata should be marked __init The s3c24xx_mci_set_platdata() is init time only, so should be marked as __init Signed-off-by: Arnaud Patard [ben-linux@fluff.org: update description] Signed-off-by: Ben Dooks diff --git a/arch/arm/plat-s3c24xx/devs.c b/arch/arm/plat-s3c24xx/devs.c index 429e453..b9565c1 100644 --- a/arch/arm/plat-s3c24xx/devs.c +++ b/arch/arm/plat-s3c24xx/devs.c @@ -376,7 +376,7 @@ struct platform_device s3c_device_sdi = { EXPORT_SYMBOL(s3c_device_sdi); -void s3c24xx_mci_set_platdata(struct s3c24xx_mci_pdata *pdata) +void __init s3c24xx_mci_set_platdata(struct s3c24xx_mci_pdata *pdata) { struct s3c24xx_mci_pdata *npd; -- cgit v0.10.2 From 2e26ca7150a4f2ab3e69471dfc65f131e7dd7a05 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Wed, 5 May 2010 10:52:31 -0400 Subject: tracing: Fix tracepoint.h DECLARE_TRACE() to allow more than one header When more than one header is included under CREATE_TRACE_POINTS the DECLARE_TRACE() macro is not defined back to its original meaning and the second include will fail to initialize the TRACE_EVENT() and DECLARE_TRACE() correctly. To fix this the tracepoint.h file moves the define of DECLARE_TRACE() out of the #ifdef _LINUX_TRACEPOINT_H protection (just like the define of the TRACE_EVENT()). This way the define_trace.h will undef the DECLARE_TRACE() at the end and allow new headers to start from scratch. This patch also requires fixing the include/events/napi.h It currently uses DECLARE_TRACE() and should be converted to a TRACE_EVENT() format. But I'll leave that change to the authors of that file. But since the napi.h file depends on using the CREATE_TRACE_POINTS and does not define its own DEFINE_TRACE() it must use the define_trace.h method instead. Cc: Neil Horman Cc: David S. Miller Cc: Mathieu Desnoyers Signed-off-by: Steven Rostedt diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h index 78b4bd3..1d85f9a 100644 --- a/include/linux/tracepoint.h +++ b/include/linux/tracepoint.h @@ -33,6 +33,65 @@ struct tracepoint { * Keep in sync with vmlinux.lds.h. */ +/* + * Connect a probe to a tracepoint. + * Internal API, should not be used directly. + */ +extern int tracepoint_probe_register(const char *name, void *probe); + +/* + * Disconnect a probe from a tracepoint. + * Internal API, should not be used directly. + */ +extern int tracepoint_probe_unregister(const char *name, void *probe); + +extern int tracepoint_probe_register_noupdate(const char *name, void *probe); +extern int tracepoint_probe_unregister_noupdate(const char *name, void *probe); +extern void tracepoint_probe_update_all(void); + +struct tracepoint_iter { + struct module *module; + struct tracepoint *tracepoint; +}; + +extern void tracepoint_iter_start(struct tracepoint_iter *iter); +extern void tracepoint_iter_next(struct tracepoint_iter *iter); +extern void tracepoint_iter_stop(struct tracepoint_iter *iter); +extern void tracepoint_iter_reset(struct tracepoint_iter *iter); +extern int tracepoint_get_iter_range(struct tracepoint **tracepoint, + struct tracepoint *begin, struct tracepoint *end); + +/* + * tracepoint_synchronize_unregister must be called between the last tracepoint + * probe unregistration and the end of module exit to make sure there is no + * caller executing a probe when it is freed. + */ +static inline void tracepoint_synchronize_unregister(void) +{ + synchronize_sched(); +} + +#define PARAMS(args...) args + +#ifdef CONFIG_TRACEPOINTS +extern void tracepoint_update_probe_range(struct tracepoint *begin, + struct tracepoint *end); +#else +static inline void tracepoint_update_probe_range(struct tracepoint *begin, + struct tracepoint *end) +{ } +#endif /* CONFIG_TRACEPOINTS */ + +#endif /* _LINUX_TRACEPOINT_H */ + +/* + * Note: we keep the TRACE_EVENT and DECLARE_TRACE outside the include + * file ifdef protection. + * This is due to the way trace events work. If a file includes two + * trace event headers under one "CREATE_TRACE_POINTS" the first include + * will override the TRACE_EVENT and break the second include. + */ + #ifndef DECLARE_TRACE #define TP_PROTO(args...) args @@ -96,9 +155,6 @@ struct tracepoint { #define EXPORT_TRACEPOINT_SYMBOL(name) \ EXPORT_SYMBOL(__tracepoint_##name) -extern void tracepoint_update_probe_range(struct tracepoint *begin, - struct tracepoint *end); - #else /* !CONFIG_TRACEPOINTS */ #define DECLARE_TRACE(name, proto, args) \ static inline void _do_trace_##name(struct tracepoint *tp, proto) \ @@ -119,61 +175,9 @@ extern void tracepoint_update_probe_range(struct tracepoint *begin, #define EXPORT_TRACEPOINT_SYMBOL_GPL(name) #define EXPORT_TRACEPOINT_SYMBOL(name) -static inline void tracepoint_update_probe_range(struct tracepoint *begin, - struct tracepoint *end) -{ } #endif /* CONFIG_TRACEPOINTS */ #endif /* DECLARE_TRACE */ -/* - * Connect a probe to a tracepoint. - * Internal API, should not be used directly. - */ -extern int tracepoint_probe_register(const char *name, void *probe); - -/* - * Disconnect a probe from a tracepoint. - * Internal API, should not be used directly. - */ -extern int tracepoint_probe_unregister(const char *name, void *probe); - -extern int tracepoint_probe_register_noupdate(const char *name, void *probe); -extern int tracepoint_probe_unregister_noupdate(const char *name, void *probe); -extern void tracepoint_probe_update_all(void); - -struct tracepoint_iter { - struct module *module; - struct tracepoint *tracepoint; -}; - -extern void tracepoint_iter_start(struct tracepoint_iter *iter); -extern void tracepoint_iter_next(struct tracepoint_iter *iter); -extern void tracepoint_iter_stop(struct tracepoint_iter *iter); -extern void tracepoint_iter_reset(struct tracepoint_iter *iter); -extern int tracepoint_get_iter_range(struct tracepoint **tracepoint, - struct tracepoint *begin, struct tracepoint *end); - -/* - * tracepoint_synchronize_unregister must be called between the last tracepoint - * probe unregistration and the end of module exit to make sure there is no - * caller executing a probe when it is freed. - */ -static inline void tracepoint_synchronize_unregister(void) -{ - synchronize_sched(); -} - -#define PARAMS(args...) args - -#endif /* _LINUX_TRACEPOINT_H */ - -/* - * Note: we keep the TRACE_EVENT outside the include file ifdef protection. - * This is due to the way trace events work. If a file includes two - * trace event headers under one "CREATE_TRACE_POINTS" the first include - * will override the TRACE_EVENT and break the second include. - */ - #ifndef TRACE_EVENT /* * For use with the TRACE_EVENT macro: diff --git a/include/trace/define_trace.h b/include/trace/define_trace.h index 5acfb1e..1dfab54 100644 --- a/include/trace/define_trace.h +++ b/include/trace/define_trace.h @@ -65,6 +65,10 @@ #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) +/* Make all open coded DECLARE_TRACE nops */ +#undef DECLARE_TRACE +#define DECLARE_TRACE(name, proto, args) + #ifdef CONFIG_EVENT_TRACING #include #endif @@ -75,6 +79,7 @@ #undef DEFINE_EVENT #undef DEFINE_EVENT_PRINT #undef TRACE_HEADER_MULTI_READ +#undef DECLARE_TRACE /* Only undef what we defined in this file */ #ifdef UNDEF_TRACE_INCLUDE_FILE diff --git a/include/trace/events/napi.h b/include/trace/events/napi.h index a8989c4..188deca 100644 --- a/include/trace/events/napi.h +++ b/include/trace/events/napi.h @@ -1,4 +1,7 @@ -#ifndef _TRACE_NAPI_H_ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM napi + +#if !defined(_TRACE_NAPI_H) || defined(TRACE_HEADER_MULTI_READ) #define _TRACE_NAPI_H_ #include @@ -8,4 +11,7 @@ DECLARE_TRACE(napi_poll, TP_PROTO(struct napi_struct *napi), TP_ARGS(napi)); -#endif +#endif /* _TRACE_NAPI_H_ */ + +/* This part must be outside protection */ +#include -- cgit v0.10.2 From 668eb65f092902eb7dd526af73d4a7f025a94612 Mon Sep 17 00:00:00 2001 From: Thiago Farina Date: Sun, 24 Jan 2010 11:03:50 -0500 Subject: tracing: Fix "integer as NULL pointer" warning. kernel/trace/trace_output.c:256:24: warning: Using plain integer as NULL pointer Signed-off-by: Thiago Farina LKML-Reference: <1264349038-1766-3-git-send-email-tfransosi@gmail.com> Signed-off-by: Steven Rostedt diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c index 8e46b33..2404c12 100644 --- a/kernel/trace/trace_output.c +++ b/kernel/trace/trace_output.c @@ -253,7 +253,7 @@ void *trace_seq_reserve(struct trace_seq *s, size_t len) void *ret; if (s->full) - return 0; + return NULL; if (len > ((PAGE_SIZE - 1) - s->len)) { s->full = 1; -- cgit v0.10.2 From bba0b5c2c27e6dadc93c476f8a4b49d108b66292 Mon Sep 17 00:00:00 2001 From: Joern Engel Date: Wed, 5 May 2010 22:32:52 +0200 Subject: logfs: fix compile failure When CONFIG_BLOCK is not enabled: fs/logfs/super.c:142: error: implicit declaration of function 'bdev_get_queue' fs/logfs/super.c:142: error: invalid type argument of '->' (have 'int') Found by Randy Dunlap Signed-off-by: Joern Engel diff --git a/fs/logfs/super.c b/fs/logfs/super.c index edd9948..2b26938 100644 --- a/fs/logfs/super.c +++ b/fs/logfs/super.c @@ -138,10 +138,14 @@ static int logfs_sb_set(struct super_block *sb, void *_super) sb->s_fs_info = super; sb->s_mtd = super->s_mtd; sb->s_bdev = super->s_bdev; +#ifdef CONFIG_BLOCK if (sb->s_bdev) sb->s_bdi = &bdev_get_queue(sb->s_bdev)->backing_dev_info; +#endif +#ifdef CONFIG_MTD if (sb->s_mtd) sb->s_bdi = sb->s_mtd->backing_dev_info; +#endif return 0; } -- cgit v0.10.2 From c0c79c31c9d5fcc19812c6c35f842baf50ee788a Mon Sep 17 00:00:00 2001 From: Joern Engel Date: Wed, 5 May 2010 22:33:36 +0200 Subject: logfs: fix sync Rather self-explanatory. Signed-off-by: Joern Engel diff --git a/fs/logfs/file.c b/fs/logfs/file.c index bf9b1cf..1639e92 100644 --- a/fs/logfs/file.c +++ b/fs/logfs/file.c @@ -224,8 +224,7 @@ int logfs_fsync(struct file *file, struct dentry *dentry, int datasync) struct super_block *sb = dentry->d_inode->i_sb; struct logfs_super *super = logfs_super(sb); - /* FIXME: write anchor */ - super->s_devops->sync(sb); + logfs_write_anchor(sb); return 0; } diff --git a/fs/logfs/inode.c b/fs/logfs/inode.c index af78b6e..755a92e 100644 --- a/fs/logfs/inode.c +++ b/fs/logfs/inode.c @@ -387,8 +387,7 @@ static void logfs_init_once(void *_li) static int logfs_sync_fs(struct super_block *sb, int wait) { - /* FIXME: write anchor */ - logfs_super(sb)->s_devops->sync(sb); + logfs_write_anchor(sb); return 0; } -- cgit v0.10.2 From 198b5682781b97251afd9025dbf559a77969abdd Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Sat, 24 Apr 2010 07:57:48 -0400 Subject: cifs: break negotiate protocol calls out of cifs_setup_session So that we can reasonably set up the secType based on both the NegotiateProtocol response and the parsed mount options. Signed-off-by: Jeff Layton Signed-off-by: Steve French diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 8e92142..6fa808e 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -138,7 +138,9 @@ extern void cifs_dfs_release_automount_timer(void); void cifs_proc_init(void); void cifs_proc_clean(void); -extern int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, +extern int cifs_negotiate_protocol(unsigned int xid, + struct cifsSesInfo *ses); +extern int cifs_setup_session(unsigned int xid, struct cifsSesInfo *ses, struct nls_table *nls_info); extern int CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses); diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 1372253..30742d8ee 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -172,7 +172,8 @@ cifs_reconnect_tcon(struct cifsTconInfo *tcon, int smb_command) * reconnect the same SMB session */ mutex_lock(&ses->session_mutex); - if (ses->need_reconnect) + rc = cifs_negotiate_protocol(0, ses); + if (rc == 0 && ses->need_reconnect) rc = cifs_setup_session(0, ses, nls_codepage); /* do we need to reconnect tcon? */ diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 9123c23..2208f06 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1651,6 +1651,14 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info) cifs_put_tcp_session(server); mutex_lock(&ses->session_mutex); + rc = cifs_negotiate_protocol(xid, ses); + if (rc) { + mutex_unlock(&ses->session_mutex); + /* problem -- put our ses reference */ + cifs_put_smb_ses(ses); + FreeXid(xid); + return ERR_PTR(rc); + } if (ses->need_reconnect) { cFYI(1, "Session needs reconnect"); rc = cifs_setup_session(xid, ses, @@ -1702,7 +1710,9 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info) ses->overrideSecFlg = volume_info->secFlg; mutex_lock(&ses->session_mutex); - rc = cifs_setup_session(xid, ses, volume_info->local_nls); + rc = cifs_negotiate_protocol(xid, ses); + if (!rc) + rc = cifs_setup_session(xid, ses, volume_info->local_nls); mutex_unlock(&ses->session_mutex); if (rc) goto get_ses_fail; @@ -2874,55 +2884,61 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) return rc; } -int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, - struct nls_table *nls_info) +int cifs_negotiate_protocol(unsigned int xid, struct cifsSesInfo *ses) { int rc = 0; - struct TCP_Server_Info *server = pSesInfo->server; - - /* what if server changes its buffer size after dropping the session? */ - if (server->maxBuf == 0) /* no need to send on reconnect */ { - rc = CIFSSMBNegotiate(xid, pSesInfo); - if (rc == -EAGAIN) { - /* retry only once on 1st time connection */ - rc = CIFSSMBNegotiate(xid, pSesInfo); - if (rc == -EAGAIN) - rc = -EHOSTDOWN; - } - if (rc == 0) { - spin_lock(&GlobalMid_Lock); - if (server->tcpStatus != CifsExiting) - server->tcpStatus = CifsGood; - else - rc = -EHOSTDOWN; - spin_unlock(&GlobalMid_Lock); + struct TCP_Server_Info *server = ses->server; - } + /* only send once per connect */ + if (server->maxBuf != 0) + return 0; + + rc = CIFSSMBNegotiate(xid, ses); + if (rc == -EAGAIN) { + /* retry only once on 1st time connection */ + rc = CIFSSMBNegotiate(xid, ses); + if (rc == -EAGAIN) + rc = -EHOSTDOWN; } + if (rc == 0) { + spin_lock(&GlobalMid_Lock); + if (server->tcpStatus != CifsExiting) + server->tcpStatus = CifsGood; + else + rc = -EHOSTDOWN; + spin_unlock(&GlobalMid_Lock); - if (rc) - goto ss_err_exit; + } + + return rc; +} + + +int cifs_setup_session(unsigned int xid, struct cifsSesInfo *ses, + struct nls_table *nls_info) +{ + int rc = 0; + struct TCP_Server_Info *server = ses->server; - pSesInfo->flags = 0; - pSesInfo->capabilities = server->capabilities; + ses->flags = 0; + ses->capabilities = server->capabilities; if (linuxExtEnabled == 0) - pSesInfo->capabilities &= (~CAP_UNIX); + ses->capabilities &= (~CAP_UNIX); cFYI(1, "Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d", server->secMode, server->capabilities, server->timeAdj); - rc = CIFS_SessSetup(xid, pSesInfo, nls_info); + rc = CIFS_SessSetup(xid, ses, nls_info); if (rc) { cERROR(1, "Send error in SessSetup = %d", rc); } else { cFYI(1, "CIFS Session Established successfully"); spin_lock(&GlobalMid_Lock); - pSesInfo->status = CifsGood; - pSesInfo->need_reconnect = false; + ses->status = CifsGood; + ses->need_reconnect = false; spin_unlock(&GlobalMid_Lock); } -ss_err_exit: return rc; } -- cgit v0.10.2 From 26efa0bac9dc3587ee8892c06642735bcded59e5 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Sat, 24 Apr 2010 07:57:49 -0400 Subject: cifs: have decode_negTokenInit set flags in server struct ...rather than the secType. This allows us to get rid of the MSKerberos securityEnum. The client just makes a decision at upcall time. Signed-off-by: Jeff Layton Signed-off-by: Steve French diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c index 6d555c0..cfd1ce3 100644 --- a/fs/cifs/asn1.c +++ b/fs/cifs/asn1.c @@ -492,17 +492,13 @@ compare_oid(unsigned long *oid1, unsigned int oid1len, int decode_negTokenInit(unsigned char *security_blob, int length, - enum securityEnum *secType) + struct TCP_Server_Info *server) { struct asn1_ctx ctx; unsigned char *end; unsigned char *sequence_end; unsigned long *oid = NULL; unsigned int cls, con, tag, oidlen, rc; - bool use_ntlmssp = false; - bool use_kerberos = false; - bool use_kerberosu2u = false; - bool use_mskerberos = false; /* cifs_dump_mem(" Received SecBlob ", security_blob, length); */ @@ -599,20 +595,17 @@ decode_negTokenInit(unsigned char *security_blob, int length, *(oid + 1), *(oid + 2), *(oid + 3)); if (compare_oid(oid, oidlen, MSKRB5_OID, - MSKRB5_OID_LEN) && - !use_mskerberos) - use_mskerberos = true; + MSKRB5_OID_LEN)) + server->sec_mskerberos = true; else if (compare_oid(oid, oidlen, KRB5U2U_OID, - KRB5U2U_OID_LEN) && - !use_kerberosu2u) - use_kerberosu2u = true; + KRB5U2U_OID_LEN)) + server->sec_kerberosu2u = true; else if (compare_oid(oid, oidlen, KRB5_OID, - KRB5_OID_LEN) && - !use_kerberos) - use_kerberos = true; + KRB5_OID_LEN)) + server->sec_kerberos = true; else if (compare_oid(oid, oidlen, NTLMSSP_OID, NTLMSSP_OID_LEN)) - use_ntlmssp = true; + server->sec_ntlmssp = true; kfree(oid); } @@ -669,12 +662,5 @@ decode_negTokenInit(unsigned char *security_blob, int length, cFYI(1, "Need to call asn1_octets_decode() function for %s", ctx.pointer); /* is this UTF-8 or ASCII? */ decode_negtoken_exit: - if (use_kerberos) - *secType = Kerberos; - else if (use_mskerberos) - *secType = MSKerberos; - else if (use_ntlmssp) - *secType = RawNTLMSSP; - return 1; } diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c index c53587b..379bd7d 100644 --- a/fs/cifs/cifs_spnego.c +++ b/fs/cifs/cifs_spnego.c @@ -133,9 +133,9 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo) dp = description + strlen(description); /* for now, only sec=krb5 and sec=mskrb5 are valid */ - if (server->secType == Kerberos) + if (server->sec_kerberos) sprintf(dp, ";sec=krb5"); - else if (server->secType == MSKerberos) + else if (server->sec_mskerberos) sprintf(dp, ";sec=mskrb5"); else goto out; diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index c412568..4a99487 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -87,7 +87,6 @@ enum securityEnum { RawNTLMSSP, /* NTLMSSP without SPNEGO, NTLMv2 hash */ /* NTLMSSP, */ /* can use rawNTLMSSP instead of NTLMSSP via SPNEGO */ Kerberos, /* Kerberos via SPNEGO */ - MSKerberos, /* MS Kerberos via SPNEGO */ }; enum protocolEnum { @@ -186,6 +185,11 @@ struct TCP_Server_Info { char ntlmv2_hash[16]; unsigned long lstrp; /* when we got last response from this server */ u16 dialect; /* dialect index that server chose */ + /* extended security flavors that server supports */ + bool sec_kerberos; /* supports plain Kerberos */ + bool sec_mskerberos; /* supports legacy MS Kerberos */ + bool sec_kerberosu2u; /* supports U2U Kerberos */ + bool sec_ntlmssp; /* supports NTLMSSP */ }; /* diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 6fa808e..2e07da9 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -85,7 +85,7 @@ extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *); extern unsigned int smbCalcSize(struct smb_hdr *ptr); extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr); extern int decode_negTokenInit(unsigned char *security_blob, int length, - enum securityEnum *secType); + struct TCP_Server_Info *server); extern int cifs_convert_address(char *src, void *dst); extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr); extern void header_assemble(struct smb_hdr *, char /* command */ , diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 30742d8ee..c65c341 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -597,13 +597,19 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) server->secType = RawNTLMSSP; } else { rc = decode_negTokenInit(pSMBr->u.extended_response. - SecurityBlob, - count - 16, - &server->secType); + SecurityBlob, count - 16, + server); if (rc == 1) rc = 0; else rc = -EINVAL; + + if (server->sec_kerberos || server->sec_mskerberos) + server->secType = Kerberos; + else if (server->sec_ntlmssp) + server->secType = RawNTLMSSP; + else + rc = -EOPNOTSUPP; } } else server->capabilities &= ~CAP_EXTENDED_SECURITY; diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 84b92df..7707389 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -751,7 +751,7 @@ ssetup_ntlmssp_authenticate: unicode_ssetup_strings(&bcc_ptr, ses, nls_cp); } else ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); - } else if (type == Kerberos || type == MSKerberos) { + } else if (type == Kerberos) { #ifdef CONFIG_CIFS_UPCALL struct cifs_spnego_msg *msg; spnego_key = cifs_get_spnego_key(ses); -- cgit v0.10.2 From 9bbb851c7079ff670ba3fe6c7ce93bb5daa9a694 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 30 Apr 2010 19:30:35 +0900 Subject: ARM: S3C24XX: Add initial s3c_gpio configuration code Add support for s3c_gpio_setcfg() and s3c_gpio_setpull() implementations to get ready for removal of the specific code being used by s3c24xx. Also rename the s3c_gpio_setcfg_s3c24xx_banka to s3c_gpio_setcfg_s3c24xx_a as seen in the header file to correct a build warning. Signed-off-by: Ben Dooks diff --git a/arch/arm/plat-s3c24xx/Kconfig b/arch/arm/plat-s3c24xx/Kconfig index 6e93ef8..a830fad 100644 --- a/arch/arm/plat-s3c24xx/Kconfig +++ b/arch/arm/plat-s3c24xx/Kconfig @@ -9,6 +9,7 @@ config PLAT_S3C24XX select NO_IOPORT select ARCH_REQUIRE_GPIOLIB select S3C_DEVICE_NAND + select S3C_GPIO_CFG_S3C24XX help Base platform code for any Samsung S3C24XX device diff --git a/arch/arm/plat-s3c24xx/gpiolib.c b/arch/arm/plat-s3c24xx/gpiolib.c index 4f0f11a..376b061 100644 --- a/arch/arm/plat-s3c24xx/gpiolib.c +++ b/arch/arm/plat-s3c24xx/gpiolib.c @@ -21,6 +21,8 @@ #include #include +#include +#include #include #include #include @@ -77,10 +79,19 @@ static int s3c24xx_gpiolib_bankg_toirq(struct gpio_chip *chip, unsigned offset) return IRQ_EINT8 + offset; } +static struct s3c_gpio_cfg s3c24xx_gpiocfg_banka = { + .set_config = s3c_gpio_setcfg_s3c24xx_a, +}; + +struct s3c_gpio_cfg s3c24xx_gpiocfg_default = { + .set_config = s3c_gpio_setcfg_s3c24xx, +}; + struct s3c_gpio_chip s3c24xx_gpios[] = { [0] = { .base = S3C2410_GPACON, .pm = __gpio_pm(&s3c_gpio_pm_1bit), + .config = &s3c24xx_gpiocfg_banka, .chip = { .base = S3C2410_GPA(0), .owner = THIS_MODULE, @@ -168,8 +179,12 @@ static __init int s3c24xx_gpiolib_init(void) struct s3c_gpio_chip *chip = s3c24xx_gpios; int gpn; - for (gpn = 0; gpn < ARRAY_SIZE(s3c24xx_gpios); gpn++, chip++) + for (gpn = 0; gpn < ARRAY_SIZE(s3c24xx_gpios); gpn++, chip++) { + if (!chip->config) + chip->config = &s3c24xx_gpiocfg_default; + s3c_gpiolib_add(chip); + } return 0; } diff --git a/arch/arm/plat-samsung/gpio-config.c b/arch/arm/plat-samsung/gpio-config.c index 44a84e8..c583282 100644 --- a/arch/arm/plat-samsung/gpio-config.c +++ b/arch/arm/plat-samsung/gpio-config.c @@ -61,8 +61,8 @@ int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull) EXPORT_SYMBOL(s3c_gpio_setpull); #ifdef CONFIG_S3C_GPIO_CFG_S3C24XX -int s3c_gpio_setcfg_s3c24xx_banka(struct s3c_gpio_chip *chip, - unsigned int off, unsigned int cfg) +int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip, + unsigned int off, unsigned int cfg) { void __iomem *reg = chip->base; unsigned int shift = off; diff --git a/arch/arm/plat-samsung/include/plat/gpio-core.h b/arch/arm/plat-samsung/include/plat/gpio-core.h index 49ff406..f0584f2 100644 --- a/arch/arm/plat-samsung/include/plat/gpio-core.h +++ b/arch/arm/plat-samsung/include/plat/gpio-core.h @@ -108,6 +108,9 @@ extern void samsung_gpiolib_add_4bit2_chips(struct s3c_gpio_chip *chip, extern void samsung_gpiolib_add_4bit(struct s3c_gpio_chip *chip); extern void samsung_gpiolib_add_4bit2(struct s3c_gpio_chip *chip); +/* exported for core SoC support to change */ +extern struct s3c_gpio_cfg s3c24xx_gpiocfg_default; + #ifdef CONFIG_S3C_GPIO_TRACK extern struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END]; -- cgit v0.10.2 From 1ec7269fd8b05044f2cb4059b679e053d57460f5 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 3 May 2010 14:39:45 +0900 Subject: ARM: S3C24XX: Add the gpio pull configuration for pull-up Add the necessary gpio configuration helper for the devices which have a single-bit pull-up resistor disabled. Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig index 5547318..9e5e96f 100644 --- a/arch/arm/mach-s3c2410/Kconfig +++ b/arch/arm/mach-s3c2410/Kconfig @@ -6,6 +6,7 @@ config CPU_S3C2410 bool depends on ARCH_S3C2410 select CPU_ARM920T + select S3C_GPIO_PULL_UP select S3C2410_CLOCK select S3C2410_GPIO select CPU_LLSERIAL_S3C2410 diff --git a/arch/arm/mach-s3c2410/s3c2410.c b/arch/arm/mach-s3c2410/s3c2410.c index 91ba42f..adc90a3 100644 --- a/arch/arm/mach-s3c2410/s3c2410.c +++ b/arch/arm/mach-s3c2410/s3c2410.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -40,6 +41,10 @@ #include #include +#include +#include +#include + /* Initial IO mappings */ static struct map_desc s3c2410_iodesc[] __initdata = { @@ -65,6 +70,9 @@ void __init s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no) void __init s3c2410_map_io(void) { + s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_1up; + s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_1up; + iotable_init(s3c2410_iodesc, ARRAY_SIZE(s3c2410_iodesc)); } diff --git a/arch/arm/mach-s3c2440/Kconfig b/arch/arm/mach-s3c2440/Kconfig index 7f46526..9d102b9 100644 --- a/arch/arm/mach-s3c2440/Kconfig +++ b/arch/arm/mach-s3c2440/Kconfig @@ -6,6 +6,7 @@ config CPU_S3C2440 bool depends on ARCH_S3C2410 select CPU_ARM920T + select S3C_GPIO_PULL_UP select S3C2410_CLOCK select S3C2410_PM if PM select S3C2410_GPIO diff --git a/arch/arm/mach-s3c2440/s3c2440.c b/arch/arm/mach-s3c2440/s3c2440.c index 2b68f7e..d50f3ae 100644 --- a/arch/arm/mach-s3c2440/s3c2440.c +++ b/arch/arm/mach-s3c2440/s3c2440.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -33,6 +34,10 @@ #include #include +#include +#include +#include + static struct sys_device s3c2440_sysdev = { .cls = &s3c2440_sysclass, }; @@ -41,6 +46,9 @@ int __init s3c2440_init(void) { printk("S3C2440: Initialising architecture\n"); + s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_1up; + s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_1up; + /* change irq for watchdog */ s3c_device_wdt.resource[1].start = IRQ_S3C2440_WDT; diff --git a/arch/arm/plat-samsung/gpio-config.c b/arch/arm/plat-samsung/gpio-config.c index c583282..8aca88d 100644 --- a/arch/arm/plat-samsung/gpio-config.c +++ b/arch/arm/plat-samsung/gpio-config.c @@ -164,3 +164,35 @@ s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip, return (__force s3c_gpio_pull_t)pup; } #endif + +#ifdef CONFIG_S3C_GPIO_PULL_UP +int s3c_gpio_setpull_1up(struct s3c_gpio_chip *chip, + unsigned int off, s3c_gpio_pull_t pull) +{ + void __iomem *reg = chip->base + 0x08; + u32 pup = __raw_readl(reg); + + pup = __raw_readl(reg); + + if (pup == S3C_GPIO_PULL_UP) + pup &= ~(1 << off); + else if (pup == S3C_GPIO_PULL_NONE) + pup |= (1 << off); + else + return -EINVAL; + + __raw_writel(pup, reg); + return 0; +} + +s3c_gpio_pull_t s3c_gpio_getpull_1up(struct s3c_gpio_chip *chip, + unsigned int off) +{ + void __iomem *reg = chip->base + 0x08; + u32 pup = __raw_readl(reg); + + pup &= (1 << off); + return pup ? S3C_GPIO_PULL_NONE : S3C_GPIO_PULL_UP; +} +#endif /* CONFIG_S3C_GPIO_PULL_UP */ + diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h b/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h index dda19da..885e9ac 100644 --- a/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h +++ b/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h @@ -146,6 +146,17 @@ extern s3c_gpio_pull_t s3c_gpio_getpull_updown(struct s3c_gpio_chip *chip, unsigned int off); /** + * s3c_gpio_getpull_1up() - Get configuration for choice of up or none + * @chip: The gpio chip that the GPIO pin belongs to + * @off: The offset to the pin to get the configuration of. + * + * This helper function reads the state of the pull-up resistor for the + * given GPIO in the same case as s3c_gpio_setpull_1up. +*/ +extern s3c_gpio_pull_t s3c_gpio_getpull_1up(struct s3c_gpio_chip *chip, + unsigned int off); + +/** * s3c_gpio_setpull_s3c2443() - Pull configuration for s3c2443. * @chip: The gpio chip that is being configured. * @off: The offset for the GPIO being configured. -- cgit v0.10.2 From 7ced5eab39809539e8fc7f3fb561bd3001d535e7 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 3 May 2010 17:19:49 +0900 Subject: ARM: S3C24XX: Add extended GPIO used on S3C2443 and beyond Add the GPIO banks that are used on the S3C2443 and above to the list of available GPIOS. Currently we do not have any limit on the SoC GPIO, so these are being registered whether the SoC has them or not. It is currently up to the user not to try and use them. Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h b/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h index 2edbb9c..f3182ff 100644 --- a/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h +++ b/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h @@ -34,6 +34,10 @@ #define S3C2410_GPIO_F_NR (32) #define S3C2410_GPIO_G_NR (32) #define S3C2410_GPIO_H_NR (32) +#define S3C2410_GPIO_J_NR (32) /* technically 16. */ +#define S3C2410_GPIO_K_NR (32) /* technically 16. */ +#define S3C2410_GPIO_L_NR (32) /* technically 15. */ +#define S3C2410_GPIO_M_NR (32) /* technically 2. */ #if CONFIG_S3C_GPIO_SPACE != 0 #error CONFIG_S3C_GPIO_SPACE cannot be zero at the moment @@ -53,6 +57,10 @@ enum s3c_gpio_number { S3C2410_GPIO_F_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_E), S3C2410_GPIO_G_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_F), S3C2410_GPIO_H_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_G), + S3C2410_GPIO_J_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_H), + S3C2410_GPIO_K_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_J), + S3C2410_GPIO_L_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_K), + S3C2410_GPIO_M_START = S3C2410_GPIO_NEXT(S3C2410_GPIO_L), }; #endif /* __ASSEMBLY__ */ @@ -67,6 +75,10 @@ enum s3c_gpio_number { #define S3C2410_GPF(_nr) (S3C2410_GPIO_F_START + (_nr)) #define S3C2410_GPG(_nr) (S3C2410_GPIO_G_START + (_nr)) #define S3C2410_GPH(_nr) (S3C2410_GPIO_H_START + (_nr)) +#define S3C2410_GPJ(_nr) (S3C2410_GPIO_J_START + (_nr)) +#define S3C2410_GPK(_nr) (S3C2410_GPIO_K_START + (_nr)) +#define S3C2410_GPL(_nr) (S3C2410_GPIO_L_START + (_nr)) +#define S3C2410_GPM(_nr) (S3C2410_GPIO_M_START + (_nr)) /* compatibility until drivers can be modified */ diff --git a/arch/arm/mach-s3c2410/include/mach/regs-gpio.h b/arch/arm/mach-s3c2410/include/mach/regs-gpio.h index fd672f3..821b966 100644 --- a/arch/arm/mach-s3c2410/include/mach/regs-gpio.h +++ b/arch/arm/mach-s3c2410/include/mach/regs-gpio.h @@ -639,6 +639,23 @@ * for the 2412/2413 from the 2410/2440/2442 */ +/* S3C2443 and above */ +#define S3C2440_GPJCON S3C2410_GPIOREG(0xD0) +#define S3C2440_GPJDAT S3C2410_GPIOREG(0xD4) +#define S3C2440_GPJUP S3C2410_GPIOREG(0xD8) + +#define S3C2443_GPKCON S3C2410_GPIOREG(0xE0) +#define S3C2443_GPKDAT S3C2410_GPIOREG(0xE4) +#define S3C2443_GPKUP S3C2410_GPIOREG(0xE8) + +#define S3C2443_GPLCON S3C2410_GPIOREG(0xF0) +#define S3C2443_GPLDAT S3C2410_GPIOREG(0xF4) +#define S3C2443_GPLUP S3C2410_GPIOREG(0xF8) + +#define S3C2443_GPMCON S3C2410_GPIOREG(0x100) +#define S3C2443_GPMDAT S3C2410_GPIOREG(0x104) +#define S3C2443_GPMUP S3C2410_GPIOREG(0x108) + /* miscellaneous control */ #define S3C2400_MISCCR S3C2410_GPIOREG(0x54) #define S3C2410_MISCCR S3C2410_GPIOREG(0x80) diff --git a/arch/arm/mach-s3c2410/include/mach/regs-gpioj.h b/arch/arm/mach-s3c2410/include/mach/regs-gpioj.h index 1202ca5..de463bc 100644 --- a/arch/arm/mach-s3c2410/include/mach/regs-gpioj.h +++ b/arch/arm/mach-s3c2410/include/mach/regs-gpioj.h @@ -24,10 +24,6 @@ #define S3C2440_GPIO_BANKJ (416) -#define S3C2440_GPJCON S3C2410_GPIOREG(0xd0) -#define S3C2440_GPJDAT S3C2410_GPIOREG(0xd4) -#define S3C2440_GPJUP S3C2410_GPIOREG(0xd8) - #define S3C2413_GPJCON S3C2410_GPIOREG(0x80) #define S3C2413_GPJDAT S3C2410_GPIOREG(0x84) #define S3C2413_GPJUP S3C2410_GPIOREG(0x88) diff --git a/arch/arm/plat-s3c24xx/gpiolib.c b/arch/arm/plat-s3c24xx/gpiolib.c index 376b061..e8c0e8a 100644 --- a/arch/arm/plat-s3c24xx/gpiolib.c +++ b/arch/arm/plat-s3c24xx/gpiolib.c @@ -1,6 +1,6 @@ /* linux/arch/arm/plat-s3c24xx/gpiolib.c * - * Copyright (c) 2008 Simtec Electronics + * Copyright (c) 2008-2010 Simtec Electronics * http://armlinux.simtec.co.uk/ * Ben Dooks * @@ -172,8 +172,47 @@ struct s3c_gpio_chip s3c24xx_gpios[] = { .ngpio = 11, }, }, + /* GPIOS for the S3C2443 and later devices. */ + { + .base = S3C2440_GPJCON, + .pm = __gpio_pm(&s3c_gpio_pm_2bit), + .chip = { + .base = S3C2410_GPJ(0), + .owner = THIS_MODULE, + .label = "GPIOJ", + .ngpio = 16, + }, + }, { + .base = S3C2443_GPKCON, + .pm = __gpio_pm(&s3c_gpio_pm_2bit), + .chip = { + .base = S3C2410_GPK(0), + .owner = THIS_MODULE, + .label = "GPIOK", + .ngpio = 16, + }, + }, { + .base = S3C2443_GPLCON, + .pm = __gpio_pm(&s3c_gpio_pm_2bit), + .chip = { + .base = S3C2410_GPL(0), + .owner = THIS_MODULE, + .label = "GPIOL", + .ngpio = 15, + }, + }, { + .base = S3C2443_GPMCON, + .pm = __gpio_pm(&s3c_gpio_pm_2bit), + .chip = { + .base = S3C2410_GPM(0), + .owner = THIS_MODULE, + .label = "GPIOM", + .ngpio = 2, + }, + }, }; + static __init int s3c24xx_gpiolib_init(void) { struct s3c_gpio_chip *chip = s3c24xx_gpios; -- cgit v0.10.2 From f4146a65fbdc5274a437f77ff2f3b4889c0edd0e Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 4 May 2010 11:23:05 +0900 Subject: ARM: H1940: Change h1940-bluetooth to use gpiolib API Change the h1940-bluetooth driver to use gpiolib to set the output state of GPH1. Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/h1940-bluetooth.c b/arch/arm/mach-s3c2410/h1940-bluetooth.c index a3f3c7b..6d06b7e 100644 --- a/arch/arm/mach-s3c2410/h1940-bluetooth.c +++ b/arch/arm/mach-s3c2410/h1940-bluetooth.c @@ -33,14 +33,15 @@ static void h1940bt_enable(int on) h1940_latch_control(0, H1940_LATCH_BLUETOOTH_POWER); /* Reset the chip */ mdelay(10); - s3c2410_gpio_setpin(S3C2410_GPH(1), 1); + + gpio_set_value(S3C2410_GPH(1), 1); mdelay(10); - s3c2410_gpio_setpin(S3C2410_GPH(1), 0); + gpio_set_value(S3C2410_GPH(1), 0); } else { - s3c2410_gpio_setpin(S3C2410_GPH(1), 1); + gpio_set_value(S3C2410_GPH(1), 1); mdelay(10); - s3c2410_gpio_setpin(S3C2410_GPH(1), 0); + gpio_set_value(S3C2410_GPH(1), 0); mdelay(10); h1940_latch_control(H1940_LATCH_BLUETOOTH_POWER, 0); } @@ -61,6 +62,12 @@ static int __devinit h1940bt_probe(struct platform_device *pdev) struct rfkill *rfk; int ret = 0; + ret = gpio_request(S3C2410_GPH(1), dev_name(&pdev->dev)); + if (ret) { + dev_err(&pdev->dev, "could not get GPH1\n");\ + return ret; + } + /* Configures BT serial port GPIOs */ s3c2410_gpio_cfgpin(S3C2410_GPH(0), S3C2410_GPH0_nCTS0); s3c2410_gpio_pullup(S3C2410_GPH(0), 1); @@ -100,6 +107,7 @@ static int h1940bt_remove(struct platform_device *pdev) struct rfkill *rfk = platform_get_drvdata(pdev); platform_set_drvdata(pdev, NULL); + gpio_free(S3C2410_GPH(1)); if (rfk) { rfkill_unregister(rfk); -- cgit v0.10.2 From afc84ad11b5c1247c2d0df06f10df69ea7206f6a Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 4 May 2010 11:30:42 +0900 Subject: ARM: JIVE: Update mach-jive to use gpiolib API Change mach-jive to use gpiolib for the GPIO lines that are directly manipulated by it. Note, we ignore any errors from gpio_request(), unlikely to see any. Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2412/mach-jive.c b/arch/arm/mach-s3c2412/mach-jive.c index 14f4798..d2bb7d2 100644 --- a/arch/arm/mach-s3c2412/mach-jive.c +++ b/arch/arm/mach-s3c2412/mach-jive.c @@ -357,8 +357,7 @@ static void jive_lcm_reset(unsigned int set) { printk(KERN_DEBUG "%s(%d)\n", __func__, set); - s3c2410_gpio_setpin(S3C2410_GPG(13), set); - s3c2410_gpio_cfgpin(S3C2410_GPG(13), S3C2410_GPIO_OUTPUT); + gpio_set_value(S3C2410_GPG(13), set); } #undef LCD_UPPER_MARGIN @@ -391,7 +390,7 @@ static struct ili9320_platdata jive_lcm_config = { static void jive_lcd_spi_chipselect(struct s3c2410_spigpio_info *spi, int cs) { - s3c2410_gpio_setpin(S3C2410_GPB(7), cs ? 0 : 1); + gpio_set_value(S3C2410_GPB(7), cs ? 0 : 1); } static struct s3c2410_spigpio_info jive_lcd_spi = { @@ -413,7 +412,7 @@ static struct platform_device jive_device_lcdspi = { static void jive_wm8750_chipselect(struct s3c2410_spigpio_info *spi, int cs) { - s3c2410_gpio_setpin(S3C2410_GPH(10), cs ? 0 : 1); + gpio_set_value(S3C2410_GPH(10), cs ? 0 : 1); } static struct s3c2410_spigpio_info jive_wm8750_spi = { @@ -636,11 +635,11 @@ static void __init jive_machine_init(void) /* initialise the spi */ - s3c2410_gpio_setpin(S3C2410_GPG(13), 0); - s3c2410_gpio_cfgpin(S3C2410_GPG(13), S3C2410_GPIO_OUTPUT); + gpio_request(S3C2410_GPG(13), "lcm reset"); + gpio_direction_output(S3C2410_GPG(13), 0); - s3c2410_gpio_setpin(S3C2410_GPB(7), 1); - s3c2410_gpio_cfgpin(S3C2410_GPB(7), S3C2410_GPIO_OUTPUT); + gpio_request(S3C2410_GPB(7), "jive spi"); + gpio_direction_output(S3C2410_GPB(7), 1); s3c2410_gpio_setpin(S3C2410_GPB(6), 0); s3c2410_gpio_cfgpin(S3C2410_GPB(6), S3C2410_GPIO_OUTPUT); @@ -650,8 +649,8 @@ static void __init jive_machine_init(void) /* initialise the WM8750 spi */ - s3c2410_gpio_setpin(S3C2410_GPH(10), 1); - s3c2410_gpio_cfgpin(S3C2410_GPH(10), S3C2410_GPIO_OUTPUT); + gpio_request(S3C2410_GPH(10), "jive wm8750 spi"); + gpio_direction_output(S3C2410_GPH(10), 1); /* Turn off suspend on both USB ports, and switch the * selectable USB port to USB device mode. */ -- cgit v0.10.2 From db61ac54c9bea389b98f88cb4a23f8dd1edde07f Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 4 May 2010 11:40:51 +0900 Subject: ARM: H1940: Change mach-h1940 to use gpiolib API Change mach-h1940 to use the gpiolib calls instead of s3c2410_gpio directly. Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c index fbedd07..5527f74 100644 --- a/arch/arm/mach-s3c2410/mach-h1940.c +++ b/arch/arm/mach-s3c2410/mach-h1940.c @@ -207,7 +207,7 @@ static int h1940_backlight_init(struct device *dev) { gpio_request(S3C2410_GPB(0), "Backlight"); - s3c2410_gpio_setpin(S3C2410_GPB(0), 0); + gpio_direction_output(S3C2410_GPB(0), 0); s3c2410_gpio_pullup(S3C2410_GPB(0), 0); s3c2410_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPB0_TOUT0); @@ -216,7 +216,7 @@ static int h1940_backlight_init(struct device *dev) static void h1940_backlight_exit(struct device *dev) { - s3c2410_gpio_cfgpin(S3C2410_GPB(0), 1/*S3C2410_GPB0_OUTP*/); + gpio_direction_output(S3C2410_GPB(0), 1); } static struct platform_pwm_backlight_data backlight_data = { @@ -245,18 +245,18 @@ static void h1940_lcd_power_set(struct plat_lcd_data *pd, if (!power) { /* set to 3ec */ - s3c2410_gpio_setpin(S3C2410_GPC(0), 0); + gpio_direction_output(S3C2410_GPC(0), 0); /* wait for 3ac */ do { - value = s3c2410_gpio_getpin(S3C2410_GPC(6)); + value = gpio_get_value(S3C2410_GPC(6)); } while (value); /* set to 38c */ - s3c2410_gpio_setpin(S3C2410_GPC(5), 0); + gpio_direction_output(S3C2410_GPC(5), 0); } else { /* Set to 3ac */ - s3c2410_gpio_setpin(S3C2410_GPC(5), 1); + gpio_direction_output(S3C2410_GPC(5), 1); /* Set to 3ad */ - s3c2410_gpio_setpin(S3C2410_GPC(0), 1); + gpio_direction_output(S3C2410_GPC(0), 1); } } @@ -332,6 +332,7 @@ static void __init h1940_init(void) gpio_request(S3C2410_GPC(5), "LCD power"); gpio_request(S3C2410_GPC(6), "LCD power"); + gpio_direction_input(S3C2410_GPC(6)); platform_add_devices(h1940_devices, ARRAY_SIZE(h1940_devices)); } diff --git a/arch/arm/mach-s3c2412/mach-smdk2413.c b/arch/arm/mach-s3c2412/mach-smdk2413.c index 0392065..faddb36 100644 --- a/arch/arm/mach-s3c2412/mach-smdk2413.c +++ b/arch/arm/mach-s3c2412/mach-smdk2413.c @@ -85,10 +85,10 @@ static void smdk2413_udc_pullup(enum s3c2410_udc_cmd_e cmd) switch (cmd) { case S3C2410_UDC_P_ENABLE : - s3c2410_gpio_setpin(S3C2410_GPF(2), 1); + gpio_set_value(S3C2410_GPF(2), 1); break; case S3C2410_UDC_P_DISABLE : - s3c2410_gpio_setpin(S3C2410_GPF(2), 0); + gpio_set_value(S3C2410_GPF(2), 0); break; case S3C2410_UDC_P_RESET : break; @@ -134,8 +134,8 @@ static void __init smdk2413_machine_init(void) { /* Turn off suspend on both USB ports, and switch the * selectable USB port to USB device mode. */ - s3c2410_gpio_setpin(S3C2410_GPF(2), 0); - s3c2410_gpio_cfgpin(S3C2410_GPF(2), S3C2410_GPIO_OUTPUT); + WARN_ON(gpio_request(S3C2410_GPF(2), "udc pull")); + gpio_direction_output(S3C2410_GPF(2), 0); s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST | S3C2410_MISCCR_USBSUSPND0 | -- cgit v0.10.2 From 2d2e0c89982c532f9da6891a733b7be43c7048ce Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 4 May 2010 12:32:16 +0900 Subject: ARM: QT2410: Update mach-qt2410 to use gpiolib API Change mach-qt2410.c to use gpiolib for the GPIO lines that are directly manipulated by it. Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/mach-qt2410.c b/arch/arm/mach-s3c2410/mach-qt2410.c index 92a4ec3..e9762fb 100644 --- a/arch/arm/mach-s3c2410/mach-qt2410.c +++ b/arch/arm/mach-s3c2410/mach-qt2410.c @@ -219,10 +219,10 @@ static void spi_gpio_cs(struct s3c2410_spigpio_info *spi, int cs) { switch (cs) { case BITBANG_CS_ACTIVE: - s3c2410_gpio_setpin(S3C2410_GPB(5), 0); + gpio_set_value(S3C2410_GPB(5), 0); break; case BITBANG_CS_INACTIVE: - s3c2410_gpio_setpin(S3C2410_GPB(5), 1); + gpio_set_value(S3C2410_GPB(5), 1); break; } } @@ -353,7 +353,8 @@ static void __init qt2410_machine_init(void) s3c24xx_udc_set_platdata(&qt2410_udc_cfg); s3c_i2c0_set_platdata(NULL); - s3c2410_gpio_cfgpin(S3C2410_GPB(5), S3C2410_GPIO_OUTPUT); + WARN_ON(gpio_request(S3C2410_GPB(5), "spi cs")); + gpio_direction_output(S3C2410_GPB(5), 1); platform_add_devices(qt2410_devices, ARRAY_SIZE(qt2410_devices)); s3c_pm_init(); -- cgit v0.10.2 From 96efa8dac85372fdddb1682949b468226126e333 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 4 May 2010 12:36:33 +0900 Subject: ARM: n30: Update mach-n30 to use gpiolib API Change mach-n30.c to use gpiolib for the GPIO lines that are directly manipulated by it. Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/mach-n30.c b/arch/arm/mach-s3c2410/mach-n30.c index 684710f..75a9fd3 100644 --- a/arch/arm/mach-s3c2410/mach-n30.c +++ b/arch/arm/mach-s3c2410/mach-n30.c @@ -86,10 +86,10 @@ static void n30_udc_pullup(enum s3c2410_udc_cmd_e cmd) { switch (cmd) { case S3C2410_UDC_P_ENABLE : - s3c2410_gpio_setpin(S3C2410_GPB(3), 1); + gpio_set_value(S3C2410_GPB(3), 1); break; case S3C2410_UDC_P_DISABLE : - s3c2410_gpio_setpin(S3C2410_GPB(3), 0); + gpio_set_value(S3C2410_GPB(3), 0); break; case S3C2410_UDC_P_RESET : break; @@ -536,6 +536,9 @@ static void __init n30_init(void) platform_add_devices(n35_devices, ARRAY_SIZE(n35_devices)); } + + WARN_ON(gpio_request(S3C2410_GPB(3), "udc pup")); + gpio_direction_output(S3C2410_GPB(3), 0); } MACHINE_START(N30, "Acer-N30") -- cgit v0.10.2 From 408c8b8ca46c16fa09a6795613db74a8d2de7980 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 4 May 2010 12:49:04 +0900 Subject: ARM: BAST: Update mach-bast to use gpiolib API Change mach-bast .c to use gpiolib for the GPIO lines that are directly manipulated by it. Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c index 02b1b622..d03cbe2 100644 --- a/arch/arm/mach-s3c2410/mach-bast.c +++ b/arch/arm/mach-s3c2410/mach-bast.c @@ -216,9 +216,7 @@ static struct s3c2410_uartcfg bast_uartcfgs[] __initdata = { static int bast_pm_suspend(struct sys_device *sd, pm_message_t state) { /* ensure that an nRESET is not generated on resume. */ - s3c2410_gpio_setpin(S3C2410_GPA(21), 1); - s3c2410_gpio_cfgpin(S3C2410_GPA(21), S3C2410_GPIO_OUTPUT); - + gpio_direction_output(S3C2410_GPA(21), 1); return 0; } @@ -658,6 +656,8 @@ static void __init bast_init(void) nor_simtec_init(); simtec_audio_add(NULL, true, &bast_audio); + WARN_ON(gpio_request(S3C2410_GPA(21), "bast nreset")); + s3c_cpufreq_setboard(&bast_cpufreq); } -- cgit v0.10.2 From 7614e1d9b9cad40ac9c90d934d2da64b36f354d1 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 4 May 2010 12:53:11 +0900 Subject: ARM: VR1000: Update mach-vr1000.c to use gpiolib API Change mach-vr1000.c to use gpiolib for gpio control. Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c index 9051f0d..d540d79 100644 --- a/arch/arm/mach-s3c2410/mach-vr1000.c +++ b/arch/arm/mach-s3c2410/mach-vr1000.c @@ -357,8 +357,7 @@ static struct clk *vr1000_clocks[] __initdata = { static void vr1000_power_off(void) { - s3c2410_gpio_cfgpin(S3C2410_GPB(9), S3C2410_GPIO_OUTPUT); - s3c2410_gpio_setpin(S3C2410_GPB(9), 1); + gpio_direction_output(S3C2410_GPB(9), 1); } static void __init vr1000_map_io(void) @@ -395,6 +394,8 @@ static void __init vr1000_init(void) nor_simtec_init(); simtec_audio_add(NULL, true, NULL); + + WARN_ON(gpio_request(S3C2410_GPB(9), "power off")); } MACHINE_START(VR1000, "Thorcom-VR1000") -- cgit v0.10.2 From 27da04049cabdf6a28288aaf083cfea64f7f9805 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 4 May 2010 13:20:12 +0900 Subject: ARM: S3C2410: Change s3c2410_gpio_pullupl(x, 1) to use s3c_gpio_cfgpull() Start moving code that is using the old s3c2410_gpio API to using the newer s3c_gpio variants by finding all the usages of s3c2410_gpio_pullup() which disable the pin's pull up and replacing them. sed 's/s3c2410_gpio_pullup\(.*\), 1/s3c_gpio_cfgpull\1, S3C_GPIO_PULL_NONE/g' Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/h1940-bluetooth.c b/arch/arm/mach-s3c2410/h1940-bluetooth.c index 6d06b7e..171a7c3 100644 --- a/arch/arm/mach-s3c2410/h1940-bluetooth.c +++ b/arch/arm/mach-s3c2410/h1940-bluetooth.c @@ -70,13 +70,13 @@ static int __devinit h1940bt_probe(struct platform_device *pdev) /* Configures BT serial port GPIOs */ s3c2410_gpio_cfgpin(S3C2410_GPH(0), S3C2410_GPH0_nCTS0); - s3c2410_gpio_pullup(S3C2410_GPH(0), 1); + s3c_gpio_cfgpull(S3C2410_GPH(0), S3C_GPIO_PULL_NONE); s3c2410_gpio_cfgpin(S3C2410_GPH(1), S3C2410_GPIO_OUTPUT); - s3c2410_gpio_pullup(S3C2410_GPH(1), 1); + s3c_gpio_cfgpull(S3C2410_GPH(1), S3C_GPIO_PULL_NONE); s3c2410_gpio_cfgpin(S3C2410_GPH(2), S3C2410_GPH2_TXD0); - s3c2410_gpio_pullup(S3C2410_GPH(2), 1); + s3c_gpio_cfgpull(S3C2410_GPH(2), S3C_GPIO_PULL_NONE); s3c2410_gpio_cfgpin(S3C2410_GPH(3), S3C2410_GPH3_RXD0); - s3c2410_gpio_pullup(S3C2410_GPH(3), 1); + s3c_gpio_cfgpull(S3C2410_GPH(3), S3C_GPIO_PULL_NONE); rfk = rfkill_alloc(DRV_NAME, &pdev->dev, RFKILL_TYPE_BLUETOOTH, -- cgit v0.10.2 From 82a4b6dcc72da33943b16338f607e7e148d177e4 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 4 May 2010 13:22:58 +0900 Subject: ARM: S3C24XX: Change s3c2410_gpio_pullupl(x, 1) to use s3c_gpio_cfgpull() Start moving code that is using the old s3c2410_gpio API to using the newer s3c_gpio variants by finding all the usages of s3c2410_gpio_pullup() which disable the pin's pull up and replacing them. sed 's/s3c2410_gpio_pullup\(.*\), 1/s3c_gpio_cfgpull\1, S3C_GPIO_PULL_NONE/g' Signed-off-by: Ben Dooks diff --git a/arch/arm/plat-s3c24xx/spi-bus0-gpe11_12_13.c b/arch/arm/plat-s3c24xx/spi-bus0-gpe11_12_13.c index da7a617..71256ad 100644 --- a/arch/arm/plat-s3c24xx/spi-bus0-gpe11_12_13.c +++ b/arch/arm/plat-s3c24xx/spi-bus0-gpe11_12_13.c @@ -29,8 +29,8 @@ void s3c24xx_spi_gpiocfg_bus0_gpe11_12_13(struct s3c2410_spi_info *spi, } else { s3c2410_gpio_cfgpin(S3C2410_GPE(13), S3C2410_GPIO_INPUT); s3c2410_gpio_cfgpin(S3C2410_GPE(11), S3C2410_GPIO_INPUT); - s3c2410_gpio_pullup(S3C2410_GPE(11), 1); - s3c2410_gpio_pullup(S3C2410_GPE(12), 1); - s3c2410_gpio_pullup(S3C2410_GPE(13), 1); + s3c_gpio_cfgpull(S3C2410_GPE(11), S3C_GPIO_PULL_NONE); + s3c_gpio_cfgpull(S3C2410_GPE(12), S3C_GPIO_PULL_NONE); + s3c_gpio_cfgpull(S3C2410_GPE(13), S3C_GPIO_PULL_NONE); } } diff --git a/arch/arm/plat-s3c24xx/spi-bus1-gpd8_9_10.c b/arch/arm/plat-s3c24xx/spi-bus1-gpd8_9_10.c index 89fcf53..31bda55 100644 --- a/arch/arm/plat-s3c24xx/spi-bus1-gpd8_9_10.c +++ b/arch/arm/plat-s3c24xx/spi-bus1-gpd8_9_10.c @@ -31,8 +31,8 @@ void s3c24xx_spi_gpiocfg_bus1_gpd8_9_10(struct s3c2410_spi_info *spi, } else { s3c2410_gpio_cfgpin(S3C2410_GPD(8), S3C2410_GPIO_INPUT); s3c2410_gpio_cfgpin(S3C2410_GPD(9), S3C2410_GPIO_INPUT); - s3c2410_gpio_pullup(S3C2410_GPD(10), 1); - s3c2410_gpio_pullup(S3C2410_GPD(9), 1); - s3c2410_gpio_pullup(S3C2410_GPD(8), 1); + s3c_gpio_cfgpull(S3C2410_GPD(10), S3C_GPIO_PULL_NONE); + s3c_gpio_cfgpull(S3C2410_GPD(9), S3C_GPIO_PULL_NONE); + s3c_gpio_cfgpull(S3C2410_GPD(8), S3C_GPIO_PULL_NONE); } } diff --git a/arch/arm/plat-s3c24xx/spi-bus1-gpg5_6_7.c b/arch/arm/plat-s3c24xx/spi-bus1-gpg5_6_7.c index 86b9edc..7910501 100644 --- a/arch/arm/plat-s3c24xx/spi-bus1-gpg5_6_7.c +++ b/arch/arm/plat-s3c24xx/spi-bus1-gpg5_6_7.c @@ -29,8 +29,8 @@ void s3c24xx_spi_gpiocfg_bus1_gpg5_6_7(struct s3c2410_spi_info *spi, } else { s3c2410_gpio_cfgpin(S3C2410_GPG(7), S3C2410_GPIO_INPUT); s3c2410_gpio_cfgpin(S3C2410_GPG(5), S3C2410_GPIO_INPUT); - s3c2410_gpio_pullup(S3C2410_GPG(5), 1); - s3c2410_gpio_pullup(S3C2410_GPG(6), 1); - s3c2410_gpio_pullup(S3C2410_GPG(7), 1); + s3c_gpio_cfgpull(S3C2410_GPG(5), S3C_GPIO_PULL_NONE); + s3c_gpio_cfgpull(S3C2410_GPG(6), S3C_GPIO_PULL_NONE); + s3c_gpio_cfgpull(S3C2410_GPG(7), S3C_GPIO_PULL_NONE); } } -- cgit v0.10.2 From 40b956f026a3303a67d2ab7fffa2331f72e1e019 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 4 May 2010 14:38:49 +0900 Subject: ARM: S3C24XX: Drop s3c2410 specific s3c2410_gpio_cfgpin() The s3c_gpio_cfgpin() call should be functionally equivalent, so replace the s3c2410_gpio_cfgpin() calls in the s3c24xx code with s3c_gpio_cfgpin to allow moving away from a fixed GPIO number to register address mapping Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/h1940-bluetooth.c b/arch/arm/mach-s3c2410/h1940-bluetooth.c index 171a7c3..8cdeb14 100644 --- a/arch/arm/mach-s3c2410/h1940-bluetooth.c +++ b/arch/arm/mach-s3c2410/h1940-bluetooth.c @@ -69,13 +69,13 @@ static int __devinit h1940bt_probe(struct platform_device *pdev) } /* Configures BT serial port GPIOs */ - s3c2410_gpio_cfgpin(S3C2410_GPH(0), S3C2410_GPH0_nCTS0); + s3c_gpio_cfgpin(S3C2410_GPH(0), S3C2410_GPH0_nCTS0); s3c_gpio_cfgpull(S3C2410_GPH(0), S3C_GPIO_PULL_NONE); - s3c2410_gpio_cfgpin(S3C2410_GPH(1), S3C2410_GPIO_OUTPUT); + s3c_gpio_cfgpin(S3C2410_GPH(1), S3C2410_GPIO_OUTPUT); s3c_gpio_cfgpull(S3C2410_GPH(1), S3C_GPIO_PULL_NONE); - s3c2410_gpio_cfgpin(S3C2410_GPH(2), S3C2410_GPH2_TXD0); + s3c_gpio_cfgpin(S3C2410_GPH(2), S3C2410_GPH2_TXD0); s3c_gpio_cfgpull(S3C2410_GPH(2), S3C_GPIO_PULL_NONE); - s3c2410_gpio_cfgpin(S3C2410_GPH(3), S3C2410_GPH3_RXD0); + s3c_gpio_cfgpin(S3C2410_GPH(3), S3C2410_GPH3_RXD0); s3c_gpio_cfgpull(S3C2410_GPH(3), S3C_GPIO_PULL_NONE); diff --git a/arch/arm/mach-s3c2410/mach-amlm5900.c b/arch/arm/mach-s3c2410/mach-amlm5900.c index 7047317..b42a760 100644 --- a/arch/arm/mach-s3c2410/mach-amlm5900.c +++ b/arch/arm/mach-s3c2410/mach-amlm5900.c @@ -56,6 +56,7 @@ #include #include #include +#include #ifdef CONFIG_MTD_PARTITIONS @@ -225,7 +226,7 @@ static void amlm5900_init_pm(void) } else { enable_irq_wake(IRQ_EINT9); /* configure the suspend/resume status pin */ - s3c2410_gpio_cfgpin(S3C2410_GPF(2), S3C2410_GPIO_OUTPUT); + s3c_gpio_cfgpin(S3C2410_GPF(2), S3C2410_GPIO_OUTPUT); s3c2410_gpio_pullup(S3C2410_GPF(2), 0); } } diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c index d03cbe2..b061ddc 100644 --- a/arch/arm/mach-s3c2410/mach-bast.c +++ b/arch/arm/mach-s3c2410/mach-bast.c @@ -61,6 +61,7 @@ #include #include #include +#include #include #include "usb-simtec.h" @@ -222,7 +223,7 @@ static int bast_pm_suspend(struct sys_device *sd, pm_message_t state) static int bast_pm_resume(struct sys_device *sd) { - s3c2410_gpio_cfgpin(S3C2410_GPA(21), S3C2410_GPA21_nRSTOUT); + s3c_gpio_cfgpin(S3C2410_GPA(21), S3C2410_GPA21_nRSTOUT); return 0; } diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c index 5527f74..e2f7e64 100644 --- a/arch/arm/mach-s3c2410/mach-h1940.c +++ b/arch/arm/mach-s3c2410/mach-h1940.c @@ -50,6 +50,7 @@ #include #include +#include #include #include #include @@ -209,7 +210,7 @@ static int h1940_backlight_init(struct device *dev) gpio_direction_output(S3C2410_GPB(0), 0); s3c2410_gpio_pullup(S3C2410_GPB(0), 0); - s3c2410_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPB0_TOUT0); + s3c_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPB0_TOUT0); return 0; } diff --git a/arch/arm/mach-s3c2410/mach-qt2410.c b/arch/arm/mach-s3c2410/mach-qt2410.c index e9762fb..d0e87b6 100644 --- a/arch/arm/mach-s3c2410/mach-qt2410.c +++ b/arch/arm/mach-s3c2410/mach-qt2410.c @@ -58,6 +58,7 @@ #include #include +#include #include #include #include @@ -347,7 +348,7 @@ static void __init qt2410_machine_init(void) } s3c24xx_fb_set_platdata(&qt2410_fb_info); - s3c2410_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPIO_OUTPUT); + s3c_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPIO_OUTPUT); s3c2410_gpio_setpin(S3C2410_GPB(0), 1); s3c24xx_udc_set_platdata(&qt2410_udc_cfg); diff --git a/arch/arm/mach-s3c2412/mach-jive.c b/arch/arm/mach-s3c2412/mach-jive.c index d2bb7d2..4316018 100644 --- a/arch/arm/mach-s3c2412/mach-jive.c +++ b/arch/arm/mach-s3c2412/mach-jive.c @@ -48,6 +48,7 @@ #include #include +#include #include #include #include @@ -530,7 +531,7 @@ static void jive_power_off(void) printk(KERN_INFO "powering system down...\n"); s3c2410_gpio_setpin(S3C2410_GPC(5), 1); - s3c2410_gpio_cfgpin(S3C2410_GPC(5), S3C2410_GPIO_OUTPUT); + s3c_gpio_cfgpin(S3C2410_GPC(5), S3C2410_GPIO_OUTPUT); } static void __init jive_machine_init(void) @@ -642,10 +643,10 @@ static void __init jive_machine_init(void) gpio_direction_output(S3C2410_GPB(7), 1); s3c2410_gpio_setpin(S3C2410_GPB(6), 0); - s3c2410_gpio_cfgpin(S3C2410_GPB(6), S3C2410_GPIO_OUTPUT); + s3c_gpio_cfgpin(S3C2410_GPB(6), S3C2410_GPIO_OUTPUT); s3c2410_gpio_setpin(S3C2410_GPG(8), 1); - s3c2410_gpio_cfgpin(S3C2410_GPG(8), S3C2410_GPIO_OUTPUT); + s3c_gpio_cfgpin(S3C2410_GPG(8), S3C2410_GPIO_OUTPUT); /* initialise the WM8750 spi */ diff --git a/arch/arm/mach-s3c2440/mach-mini2440.c b/arch/arm/mach-s3c2440/mach-mini2440.c index 571b176..362a2f9 100644 --- a/arch/arm/mach-s3c2440/mach-mini2440.c +++ b/arch/arm/mach-s3c2440/mach-mini2440.c @@ -53,6 +53,7 @@ #include #include +#include #include #include #include @@ -632,24 +633,24 @@ static void __init mini2440_init(void) mini2440_parse_features(&features, mini2440_features_str); /* turn LCD on */ - s3c2410_gpio_cfgpin(S3C2410_GPC(0), S3C2410_GPC0_LEND); + s3c_gpio_cfgpin(S3C2410_GPC(0), S3C2410_GPC0_LEND); /* Turn the backlight early on */ s3c2410_gpio_setpin(S3C2410_GPG(4), 1); - s3c2410_gpio_cfgpin(S3C2410_GPG(4), S3C2410_GPIO_OUTPUT); + s3c_gpio_cfgpin(S3C2410_GPG(4), S3C2410_GPIO_OUTPUT); /* remove pullup on optional PWM backlight -- unused on 3.5 and 7"s */ s3c2410_gpio_pullup(S3C2410_GPB(1), 0); s3c2410_gpio_setpin(S3C2410_GPB(1), 0); - s3c2410_gpio_cfgpin(S3C2410_GPB(1), S3C2410_GPIO_INPUT); + s3c_gpio_cfgpin(S3C2410_GPB(1), S3C2410_GPIO_INPUT); /* Make sure the D+ pullup pin is output */ - s3c2410_gpio_cfgpin(S3C2410_GPC(5), S3C2410_GPIO_OUTPUT); + s3c_gpio_cfgpin(S3C2410_GPC(5), S3C2410_GPIO_OUTPUT); /* mark the key as input, without pullups (there is one on the board) */ for (i = 0; i < ARRAY_SIZE(mini2440_buttons); i++) { s3c2410_gpio_pullup(mini2440_buttons[i].gpio, 0); - s3c2410_gpio_cfgpin(mini2440_buttons[i].gpio, + s3c_gpio_cfgpin(mini2440_buttons[i].gpio, S3C2410_GPIO_INPUT); } if (features.lcd_index != -1) { diff --git a/arch/arm/mach-s3c2440/mach-nexcoder.c b/arch/arm/mach-s3c2440/mach-nexcoder.c index 3420415..3ff62de 100644 --- a/arch/arm/mach-s3c2440/mach-nexcoder.c +++ b/arch/arm/mach-s3c2440/mach-nexcoder.c @@ -40,6 +40,7 @@ #include #include +#include #include #include #include @@ -122,15 +123,15 @@ static void __init nexcoder_sensorboard_init(void) { // Initialize SCCB bus s3c2410_gpio_setpin(S3C2410_GPE(14), 1); // IICSCL - s3c2410_gpio_cfgpin(S3C2410_GPE(14), S3C2410_GPIO_OUTPUT); + s3c_gpio_cfgpin(S3C2410_GPE(14), S3C2410_GPIO_OUTPUT); s3c2410_gpio_setpin(S3C2410_GPE(15), 1); // IICSDA - s3c2410_gpio_cfgpin(S3C2410_GPE(15), S3C2410_GPIO_OUTPUT); + s3c_gpio_cfgpin(S3C2410_GPE(15), S3C2410_GPIO_OUTPUT); // Power up the sensor board s3c2410_gpio_setpin(S3C2410_GPF(1), 1); - s3c2410_gpio_cfgpin(S3C2410_GPF(1), S3C2410_GPIO_OUTPUT); // CAM_GPIO7 => nLDO_PWRDN + s3c_gpio_cfgpin(S3C2410_GPF(1), S3C2410_GPIO_OUTPUT); // CAM_GPIO7 => nLDO_PWRDN s3c2410_gpio_setpin(S3C2410_GPF(2), 0); - s3c2410_gpio_cfgpin(S3C2410_GPF(2), S3C2410_GPIO_OUTPUT); // CAM_GPIO6 => CAM_PWRDN + s3c_gpio_cfgpin(S3C2410_GPF(2), S3C2410_GPIO_OUTPUT); // CAM_GPIO6 => CAM_PWRDN } static void __init nexcoder_map_io(void) diff --git a/arch/arm/mach-s3c2440/mach-osiris.c b/arch/arm/mach-s3c2440/mach-osiris.c index f35371d..319458d 100644 --- a/arch/arm/mach-s3c2440/mach-osiris.c +++ b/arch/arm/mach-s3c2440/mach-osiris.c @@ -49,6 +49,7 @@ #include #include +#include #include #include #include @@ -298,7 +299,7 @@ static int osiris_pm_suspend(struct sys_device *sd, pm_message_t state) /* ensure that an nRESET is not generated on resume. */ s3c2410_gpio_setpin(S3C2410_GPA(21), 1); - s3c2410_gpio_cfgpin(S3C2410_GPA(21), S3C2410_GPIO_OUTPUT); + s3c_gpio_cfgpin(S3C2410_GPA(21), S3C2410_GPIO_OUTPUT); return 0; } @@ -310,7 +311,7 @@ static int osiris_pm_resume(struct sys_device *sd) __raw_writeb(pm_osiris_ctrl0, OSIRIS_VA_CTRL0); - s3c2410_gpio_cfgpin(S3C2410_GPA(21), S3C2410_GPA21_nRSTOUT); + s3c_gpio_cfgpin(S3C2410_GPA(21), S3C2410_GPA21_nRSTOUT); return 0; } diff --git a/arch/arm/plat-s3c24xx/common-smdk.c b/arch/arm/plat-s3c24xx/common-smdk.c index 9e0e20a..7b44d0c 100644 --- a/arch/arm/plat-s3c24xx/common-smdk.c +++ b/arch/arm/plat-s3c24xx/common-smdk.c @@ -42,6 +42,7 @@ #include #include +#include #include #include @@ -185,10 +186,10 @@ void __init smdk_machine_init(void) { /* Configure the LEDs (even if we have no LED support)*/ - s3c2410_gpio_cfgpin(S3C2410_GPF(4), S3C2410_GPIO_OUTPUT); - s3c2410_gpio_cfgpin(S3C2410_GPF(5), S3C2410_GPIO_OUTPUT); - s3c2410_gpio_cfgpin(S3C2410_GPF(6), S3C2410_GPIO_OUTPUT); - s3c2410_gpio_cfgpin(S3C2410_GPF(7), S3C2410_GPIO_OUTPUT); + s3c_gpio_cfgpin(S3C2410_GPF(4), S3C2410_GPIO_OUTPUT); + s3c_gpio_cfgpin(S3C2410_GPF(5), S3C2410_GPIO_OUTPUT); + s3c_gpio_cfgpin(S3C2410_GPF(6), S3C2410_GPIO_OUTPUT); + s3c_gpio_cfgpin(S3C2410_GPF(7), S3C2410_GPIO_OUTPUT); s3c2410_gpio_setpin(S3C2410_GPF(4), 1); s3c2410_gpio_setpin(S3C2410_GPF(5), 1); diff --git a/arch/arm/plat-s3c24xx/pm.c b/arch/arm/plat-s3c24xx/pm.c index 3620dd2..37ea822 100644 --- a/arch/arm/plat-s3c24xx/pm.c +++ b/arch/arm/plat-s3c24xx/pm.c @@ -43,6 +43,7 @@ #include +#include #include #define PFX "s3c24xx-pm: " @@ -105,7 +106,7 @@ static void s3c_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs) } else { if (pinstate == S3C2410_GPIO_IRQ) { S3C_PMDBG("Disabling IRQ %d (pin %d)\n", irq, pin); - s3c2410_gpio_cfgpin(pin, S3C2410_GPIO_INPUT); + s3c_gpio_cfgpin(pin, S3C2410_GPIO_INPUT); } } } diff --git a/arch/arm/plat-s3c24xx/setup-i2c.c b/arch/arm/plat-s3c24xx/setup-i2c.c index 71a6acc..9e90a7c 100644 --- a/arch/arm/plat-s3c24xx/setup-i2c.c +++ b/arch/arm/plat-s3c24xx/setup-i2c.c @@ -15,12 +15,13 @@ struct platform_device; +#include #include #include #include void s3c_i2c0_cfg_gpio(struct platform_device *dev) { - s3c2410_gpio_cfgpin(S3C2410_GPE(15), S3C2410_GPE15_IICSDA); - s3c2410_gpio_cfgpin(S3C2410_GPE(14), S3C2410_GPE14_IICSCL); + s3c_gpio_cfgpin(S3C2410_GPE(15), S3C2410_GPE15_IICSDA); + s3c_gpio_cfgpin(S3C2410_GPE(14), S3C2410_GPE14_IICSCL); } diff --git a/arch/arm/plat-s3c24xx/spi-bus0-gpe11_12_13.c b/arch/arm/plat-s3c24xx/spi-bus0-gpe11_12_13.c index 71256ad..9793544 100644 --- a/arch/arm/plat-s3c24xx/spi-bus0-gpe11_12_13.c +++ b/arch/arm/plat-s3c24xx/spi-bus0-gpe11_12_13.c @@ -21,14 +21,14 @@ void s3c24xx_spi_gpiocfg_bus0_gpe11_12_13(struct s3c2410_spi_info *spi, int enable) { if (enable) { - s3c2410_gpio_cfgpin(S3C2410_GPE(13), S3C2410_GPE13_SPICLK0); - s3c2410_gpio_cfgpin(S3C2410_GPE(12), S3C2410_GPE12_SPIMOSI0); - s3c2410_gpio_cfgpin(S3C2410_GPE(11), S3C2410_GPE11_SPIMISO0); + s3c_gpio_cfgpin(S3C2410_GPE(13), S3C2410_GPE13_SPICLK0); + s3c_gpio_cfgpin(S3C2410_GPE(12), S3C2410_GPE12_SPIMOSI0); + s3c_gpio_cfgpin(S3C2410_GPE(11), S3C2410_GPE11_SPIMISO0); s3c2410_gpio_pullup(S3C2410_GPE(11), 0); s3c2410_gpio_pullup(S3C2410_GPE(13), 0); } else { - s3c2410_gpio_cfgpin(S3C2410_GPE(13), S3C2410_GPIO_INPUT); - s3c2410_gpio_cfgpin(S3C2410_GPE(11), S3C2410_GPIO_INPUT); + s3c_gpio_cfgpin(S3C2410_GPE(13), S3C2410_GPIO_INPUT); + s3c_gpio_cfgpin(S3C2410_GPE(11), S3C2410_GPIO_INPUT); s3c_gpio_cfgpull(S3C2410_GPE(11), S3C_GPIO_PULL_NONE); s3c_gpio_cfgpull(S3C2410_GPE(12), S3C_GPIO_PULL_NONE); s3c_gpio_cfgpull(S3C2410_GPE(13), S3C_GPIO_PULL_NONE); diff --git a/arch/arm/plat-s3c24xx/spi-bus1-gpd8_9_10.c b/arch/arm/plat-s3c24xx/spi-bus1-gpd8_9_10.c index 31bda55..db9e9e4 100644 --- a/arch/arm/plat-s3c24xx/spi-bus1-gpd8_9_10.c +++ b/arch/arm/plat-s3c24xx/spi-bus1-gpd8_9_10.c @@ -23,14 +23,14 @@ void s3c24xx_spi_gpiocfg_bus1_gpd8_9_10(struct s3c2410_spi_info *spi, printk(KERN_INFO "%s(%d)\n", __func__, enable); if (enable) { - s3c2410_gpio_cfgpin(S3C2410_GPD(10), S3C2440_GPD10_SPICLK1); - s3c2410_gpio_cfgpin(S3C2410_GPD(9), S3C2440_GPD9_SPIMOSI1); - s3c2410_gpio_cfgpin(S3C2410_GPD(8), S3C2440_GPD8_SPIMISO1); + s3c_gpio_cfgpin(S3C2410_GPD(10), S3C2440_GPD10_SPICLK1); + s3c_gpio_cfgpin(S3C2410_GPD(9), S3C2440_GPD9_SPIMOSI1); + s3c_gpio_cfgpin(S3C2410_GPD(8), S3C2440_GPD8_SPIMISO1); s3c2410_gpio_pullup(S3C2410_GPD(10), 0); s3c2410_gpio_pullup(S3C2410_GPD(9), 0); } else { - s3c2410_gpio_cfgpin(S3C2410_GPD(8), S3C2410_GPIO_INPUT); - s3c2410_gpio_cfgpin(S3C2410_GPD(9), S3C2410_GPIO_INPUT); + s3c_gpio_cfgpin(S3C2410_GPD(8), S3C2410_GPIO_INPUT); + s3c_gpio_cfgpin(S3C2410_GPD(9), S3C2410_GPIO_INPUT); s3c_gpio_cfgpull(S3C2410_GPD(10), S3C_GPIO_PULL_NONE); s3c_gpio_cfgpull(S3C2410_GPD(9), S3C_GPIO_PULL_NONE); s3c_gpio_cfgpull(S3C2410_GPD(8), S3C_GPIO_PULL_NONE); diff --git a/arch/arm/plat-s3c24xx/spi-bus1-gpg5_6_7.c b/arch/arm/plat-s3c24xx/spi-bus1-gpg5_6_7.c index 7910501..8ea663a 100644 --- a/arch/arm/plat-s3c24xx/spi-bus1-gpg5_6_7.c +++ b/arch/arm/plat-s3c24xx/spi-bus1-gpg5_6_7.c @@ -21,14 +21,14 @@ void s3c24xx_spi_gpiocfg_bus1_gpg5_6_7(struct s3c2410_spi_info *spi, int enable) { if (enable) { - s3c2410_gpio_cfgpin(S3C2410_GPG(7), S3C2410_GPG7_SPICLK1); - s3c2410_gpio_cfgpin(S3C2410_GPG(6), S3C2410_GPG6_SPIMOSI1); - s3c2410_gpio_cfgpin(S3C2410_GPG(5), S3C2410_GPG5_SPIMISO1); + s3c_gpio_cfgpin(S3C2410_GPG(7), S3C2410_GPG7_SPICLK1); + s3c_gpio_cfgpin(S3C2410_GPG(6), S3C2410_GPG6_SPIMOSI1); + s3c_gpio_cfgpin(S3C2410_GPG(5), S3C2410_GPG5_SPIMISO1); s3c2410_gpio_pullup(S3C2410_GPG(5), 0); s3c2410_gpio_pullup(S3C2410_GPG(6), 0); } else { - s3c2410_gpio_cfgpin(S3C2410_GPG(7), S3C2410_GPIO_INPUT); - s3c2410_gpio_cfgpin(S3C2410_GPG(5), S3C2410_GPIO_INPUT); + s3c_gpio_cfgpin(S3C2410_GPG(7), S3C2410_GPIO_INPUT); + s3c_gpio_cfgpin(S3C2410_GPG(5), S3C2410_GPIO_INPUT); s3c_gpio_cfgpull(S3C2410_GPG(5), S3C_GPIO_PULL_NONE); s3c_gpio_cfgpull(S3C2410_GPG(6), S3C_GPIO_PULL_NONE); s3c_gpio_cfgpull(S3C2410_GPG(7), S3C_GPIO_PULL_NONE); -- cgit v0.10.2 From eee2b94f01f7379940a656af8ef097749ce025b5 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 4 May 2010 15:01:44 +0900 Subject: ARM: S3C24XX: Remove s3c2410_gpio_setcfg() Remove the implementation of s3c2410_gpio_setcfg() as it should now be functionally equivalent to s3c_gpio_cfgpin(), and add a wrapper for those drivers that are still using this call. Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/include/mach/gpio-fns.h b/arch/arm/mach-s3c2410/include/mach/gpio-fns.h index 035a493..f50c2a5 100644 --- a/arch/arm/mach-s3c2410/include/mach/gpio-fns.h +++ b/arch/arm/mach-s3c2410/include/mach/gpio-fns.h @@ -10,14 +10,28 @@ * published by the Free Software Foundation. */ +#ifndef __MACH_GPIO_FNS_H +#define __MACH_GPIO_FNS_H __FILE__ + /* These functions are in the to-be-removed category and it is strongly * encouraged not to use these in new code. They will be marked deprecated * very soon. * * Most of the functionality can be either replaced by the gpiocfg calls * for the s3c platform or by the generic GPIOlib API. + * + * As of 2.6.35-rc, these will be removed, with the few drivers using them + * either replaced or given a wrapper until the calls can be removed. */ +#include + +static inline void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int cfg) +{ + /* 1:1 mapping between cfgpin and setcfg calls at the moment */ + s3c_gpio_cfgpin(pin, cfg); +} + /* external functions for GPIO support * * These allow various different clients to access the same GPIO @@ -25,17 +39,6 @@ * GPIO register, then it is safe to ioremap/__raw_{read|write} to it. */ -/* s3c2410_gpio_cfgpin - * - * set the configuration of the given pin to the value passed. - * - * eg: - * s3c2410_gpio_cfgpin(S3C2410_GPA(0), S3C2410_GPA0_ADDR0); - * s3c2410_gpio_cfgpin(S3C2410_GPE(8), S3C2410_GPE8_SDDAT1); -*/ - -extern void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function); - extern unsigned int s3c2410_gpio_getcfg(unsigned int pin); /* s3c2410_gpio_getirq @@ -73,6 +76,14 @@ extern int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on, /* s3c2410_gpio_pullup * + * This call should be replaced with s3c_gpio_setpull(). + * + * As a note, there is currently no distinction between pull-up and pull-down + * in the s3c24xx series devices with only an on/off configuration. + */ + +/* s3c2410_gpio_pullup + * * configure the pull-up control on the given pin * * to = 1 => disable the pull-up @@ -101,3 +112,5 @@ extern int s3c2410_gpio_getpull(unsigned int pin); extern void s3c2410_gpio_setpin(unsigned int pin, unsigned int to); extern unsigned int s3c2410_gpio_getpin(unsigned int pin); + +#endif /* __MACH_GPIO_FNS_H */ diff --git a/arch/arm/plat-s3c24xx/gpio.c b/arch/arm/plat-s3c24xx/gpio.c index 5467470..0b3b2cb 100644 --- a/arch/arm/plat-s3c24xx/gpio.c +++ b/arch/arm/plat-s3c24xx/gpio.c @@ -34,54 +34,6 @@ #include -void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function) -{ - void __iomem *base = S3C24XX_GPIO_BASE(pin); - unsigned long mask; - unsigned long con; - unsigned long flags; - - if (pin < S3C2410_GPIO_BANKB) { - mask = 1 << S3C2410_GPIO_OFFSET(pin); - } else { - mask = 3 << S3C2410_GPIO_OFFSET(pin)*2; - } - - switch (function) { - case S3C2410_GPIO_LEAVE: - mask = 0; - function = 0; - break; - - case S3C2410_GPIO_INPUT: - case S3C2410_GPIO_OUTPUT: - case S3C2410_GPIO_SFN2: - case S3C2410_GPIO_SFN3: - if (pin < S3C2410_GPIO_BANKB) { - function -= 1; - function &= 1; - function <<= S3C2410_GPIO_OFFSET(pin); - } else { - function &= 3; - function <<= S3C2410_GPIO_OFFSET(pin)*2; - } - } - - /* modify the specified register wwith IRQs off */ - - local_irq_save(flags); - - con = __raw_readl(base + 0x00); - con &= ~mask; - con |= function; - - __raw_writel(con, base + 0x00); - - local_irq_restore(flags); -} - -EXPORT_SYMBOL(s3c2410_gpio_cfgpin); - unsigned int s3c2410_gpio_getcfg(unsigned int pin) { void __iomem *base = S3C24XX_GPIO_BASE(pin); -- cgit v0.10.2 From e6528d5e8730b1f75acf035d7c11e06657963581 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 4 May 2010 15:07:43 +0900 Subject: ARM: S3C24XX: Remove s3c2410_gpio_getpull() Remove the unused s3c2410_gpio_getpull() Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/include/mach/gpio-fns.h b/arch/arm/mach-s3c2410/include/mach/gpio-fns.h index f50c2a5..f453c4f 100644 --- a/arch/arm/mach-s3c2410/include/mach/gpio-fns.h +++ b/arch/arm/mach-s3c2410/include/mach/gpio-fns.h @@ -97,18 +97,6 @@ extern int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on, extern void s3c2410_gpio_pullup(unsigned int pin, unsigned int to); -/* s3c2410_gpio_getpull - * - * Read the state of the pull-up on a given pin - * - * return: - * < 0 => error code - * 0 => enabled - * 1 => disabled -*/ - -extern int s3c2410_gpio_getpull(unsigned int pin); - extern void s3c2410_gpio_setpin(unsigned int pin, unsigned int to); extern unsigned int s3c2410_gpio_getpin(unsigned int pin); diff --git a/arch/arm/plat-s3c24xx/gpio.c b/arch/arm/plat-s3c24xx/gpio.c index 0b3b2cb..9b3d74c 100644 --- a/arch/arm/plat-s3c24xx/gpio.c +++ b/arch/arm/plat-s3c24xx/gpio.c @@ -20,7 +20,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - #include #include #include @@ -75,18 +74,6 @@ void s3c2410_gpio_pullup(unsigned int pin, unsigned int to) EXPORT_SYMBOL(s3c2410_gpio_pullup); -int s3c2410_gpio_getpull(unsigned int pin) -{ - void __iomem *base = S3C24XX_GPIO_BASE(pin); - unsigned long offs = S3C2410_GPIO_OFFSET(pin); - - if (pin < S3C2410_GPIO_BANKB) - return -EINVAL; - - return (__raw_readl(base + 0x08) & (1L << offs)) ? 1 : 0; -} - -EXPORT_SYMBOL(s3c2410_gpio_getpull); void s3c2410_gpio_setpin(unsigned int pin, unsigned int to) { -- cgit v0.10.2 From 5690a6267f0f0f15a01eeed143828726627c6ae6 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 4 May 2010 17:14:10 +0900 Subject: ARM: S3C24XX: Remove s3c2410_gpio_getirq() Remove s3c2410_gpio_getirq() as the only users is the pm code, and it can be replicated by using gpio_to_irq(). Signed-off-by: Ben Dooks diff --git a/arch/arm/plat-s3c24xx/gpio.c b/arch/arm/plat-s3c24xx/gpio.c index 9b3d74c..24c0047 100644 --- a/arch/arm/plat-s3c24xx/gpio.c +++ b/arch/arm/plat-s3c24xx/gpio.c @@ -120,22 +120,3 @@ unsigned int s3c2410_modify_misccr(unsigned int clear, unsigned int change) } EXPORT_SYMBOL(s3c2410_modify_misccr); - -int s3c2410_gpio_getirq(unsigned int pin) -{ - if (pin < S3C2410_GPF(0) || pin > S3C2410_GPG(15)) - return -EINVAL; /* not valid interrupts */ - - if (pin < S3C2410_GPG(0) && pin > S3C2410_GPF(7)) - return -EINVAL; /* not valid pin */ - - if (pin < S3C2410_GPF(4)) - return (pin - S3C2410_GPF(0)) + IRQ_EINT0; - - if (pin < S3C2410_GPG(0)) - return (pin - S3C2410_GPF(4)) + IRQ_EINT4; - - return (pin - S3C2410_GPG(0)) + IRQ_EINT8; -} - -EXPORT_SYMBOL(s3c2410_gpio_getirq); diff --git a/arch/arm/plat-s3c24xx/pm.c b/arch/arm/plat-s3c24xx/pm.c index 37ea822..691fecc 100644 --- a/arch/arm/plat-s3c24xx/pm.c +++ b/arch/arm/plat-s3c24xx/pm.c @@ -91,7 +91,7 @@ static void s3c_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs) { unsigned long irqstate; unsigned long pinstate; - int irq = s3c2410_gpio_getirq(pin); + int irq = gpio_to_irq(pin); if (irqoffs < 4) irqstate = s3c_irqwake_intmask & (1L< Date: Thu, 6 May 2010 00:38:16 +0000 Subject: [CIFS] Remove unused cifs_oplock_cachep CC: Jeff Layton Signed-off-by: Steve French diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 80a9356..09842d3 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -86,8 +86,6 @@ extern mempool_t *cifs_sm_req_poolp; extern mempool_t *cifs_req_poolp; extern mempool_t *cifs_mid_poolp; -extern struct kmem_cache *cifs_oplock_cachep; - static int cifs_read_super(struct super_block *sb, void *data, const char *devname, int silent) @@ -289,7 +287,6 @@ static int cifs_permission(struct inode *inode, int mask) static struct kmem_cache *cifs_inode_cachep; static struct kmem_cache *cifs_req_cachep; static struct kmem_cache *cifs_mid_cachep; -struct kmem_cache *cifs_oplock_cachep; static struct kmem_cache *cifs_sm_req_cachep; mempool_t *cifs_sm_req_poolp; mempool_t *cifs_req_poolp; @@ -939,15 +936,6 @@ cifs_init_mids(void) return -ENOMEM; } - cifs_oplock_cachep = kmem_cache_create("cifs_oplock_structs", - sizeof(struct oplock_q_entry), 0, - SLAB_HWCACHE_ALIGN, NULL); - if (cifs_oplock_cachep == NULL) { - mempool_destroy(cifs_mid_poolp); - kmem_cache_destroy(cifs_mid_cachep); - return -ENOMEM; - } - return 0; } @@ -956,7 +944,6 @@ cifs_destroy_mids(void) { mempool_destroy(cifs_mid_poolp); kmem_cache_destroy(cifs_mid_cachep); - kmem_cache_destroy(cifs_oplock_cachep); } static int __init diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 28f563c..82f78c4 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -35,7 +35,6 @@ #include "cifs_debug.h" extern mempool_t *cifs_mid_poolp; -extern struct kmem_cache *cifs_oplock_cachep; static struct mid_q_entry * AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server) -- cgit v0.10.2 From 97a339995fa6224487dc026e466f5bd1bbcaa3b2 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 6 May 2010 10:27:16 +0900 Subject: ARM: SAMSUNG: Add GPIO configuration read calls Add the necessary 1,2 and 4 bit configuration read calls for the new gpio code to allow removal of the old s3c24xx gpio code. Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c64xx/gpiolib.c b/arch/arm/mach-s3c64xx/gpiolib.c index 66e6794..60c929a 100644 --- a/arch/arm/mach-s3c64xx/gpiolib.c +++ b/arch/arm/mach-s3c64xx/gpiolib.c @@ -51,6 +51,7 @@ static struct s3c_gpio_cfg gpio_4bit_cfg_noint = { .set_config = s3c_gpio_setcfg_s3c64xx_4bit, + .get_config = s3c_gpio_getcfg_s3c64xx_4bit, .set_pull = s3c_gpio_setpull_updown, .get_pull = s3c_gpio_getpull_updown, }; @@ -58,12 +59,14 @@ static struct s3c_gpio_cfg gpio_4bit_cfg_noint = { static struct s3c_gpio_cfg gpio_4bit_cfg_eint0111 = { .cfg_eint = 7, .set_config = s3c_gpio_setcfg_s3c64xx_4bit, + .get_config = s3c_gpio_getcfg_s3c64xx_4bit, .set_pull = s3c_gpio_setpull_updown, .get_pull = s3c_gpio_getpull_updown, }; static struct s3c_gpio_cfg gpio_4bit_cfg_eint0011 = { .cfg_eint = 3, + .get_config = s3c_gpio_getcfg_s3c64xx_4bit, .set_config = s3c_gpio_setcfg_s3c64xx_4bit, .set_pull = s3c_gpio_setpull_updown, .get_pull = s3c_gpio_getpull_updown, @@ -171,6 +174,7 @@ static struct s3c_gpio_chip gpio_4bit2[] = { static struct s3c_gpio_cfg gpio_2bit_cfg_noint = { .set_config = s3c_gpio_setcfg_s3c24xx, + .get_config = s3c_gpio_getcfg_s3c24xx, .set_pull = s3c_gpio_setpull_updown, .get_pull = s3c_gpio_getpull_updown, }; @@ -178,6 +182,7 @@ static struct s3c_gpio_cfg gpio_2bit_cfg_noint = { static struct s3c_gpio_cfg gpio_2bit_cfg_eint10 = { .cfg_eint = 2, .set_config = s3c_gpio_setcfg_s3c24xx, + .get_config = s3c_gpio_getcfg_s3c24xx, .set_pull = s3c_gpio_setpull_updown, .get_pull = s3c_gpio_getpull_updown, }; @@ -185,6 +190,7 @@ static struct s3c_gpio_cfg gpio_2bit_cfg_eint10 = { static struct s3c_gpio_cfg gpio_2bit_cfg_eint11 = { .cfg_eint = 3, .set_config = s3c_gpio_setcfg_s3c24xx, + .get_config = s3c_gpio_getcfg_s3c24xx, .set_pull = s3c_gpio_setpull_updown, .get_pull = s3c_gpio_getpull_updown, }; diff --git a/arch/arm/mach-s5p6440/gpio.c b/arch/arm/mach-s5p6440/gpio.c index b0ea741..262dc75 100644 --- a/arch/arm/mach-s5p6440/gpio.c +++ b/arch/arm/mach-s5p6440/gpio.c @@ -161,12 +161,15 @@ static struct s3c_gpio_cfg s5p6440_gpio_cfgs[] = { }, { .cfg_eint = 0, .set_config = s3c_gpio_setcfg_s3c24xx, + .get_config = s3c_gpio_getcfg_s3c24xx, }, { .cfg_eint = 2, .set_config = s3c_gpio_setcfg_s3c24xx, + .get_config = s3c_gpio_getcfg_s3c24xx, }, { .cfg_eint = 3, .set_config = s3c_gpio_setcfg_s3c24xx, + .get_config = s3c_gpio_getcfg_s3c24xx, }, }; @@ -279,6 +282,8 @@ void __init s5p6440_gpiolib_set_cfg(struct s3c_gpio_cfg *chipcfg, int nr_chips) for (; nr_chips > 0; nr_chips--, chipcfg++) { if (!chipcfg->set_config) chipcfg->set_config = s3c_gpio_setcfg_s3c64xx_4bit; + if (!chipcfg->get_config) + chipcfg->get_config = s3c_gpio_getcfg_s3c64xx_4bit; if (!chipcfg->set_pull) chipcfg->set_pull = s3c_gpio_setpull_updown; if (!chipcfg->get_pull) diff --git a/arch/arm/plat-s3c24xx/gpiolib.c b/arch/arm/plat-s3c24xx/gpiolib.c index e8c0e8a..4c0896f 100644 --- a/arch/arm/plat-s3c24xx/gpiolib.c +++ b/arch/arm/plat-s3c24xx/gpiolib.c @@ -81,10 +81,12 @@ static int s3c24xx_gpiolib_bankg_toirq(struct gpio_chip *chip, unsigned offset) static struct s3c_gpio_cfg s3c24xx_gpiocfg_banka = { .set_config = s3c_gpio_setcfg_s3c24xx_a, + .get_config = s3c_gpio_getcfg_s3c24xx_a, }; struct s3c_gpio_cfg s3c24xx_gpiocfg_default = { .set_config = s3c_gpio_setcfg_s3c24xx, + .get_config = s3c_gpio_getcfg_s3c24xx, }; struct s3c_gpio_chip s3c24xx_gpios[] = { diff --git a/arch/arm/plat-samsung/gpio-config.c b/arch/arm/plat-samsung/gpio-config.c index 8aca88d..19ab89d 100644 --- a/arch/arm/plat-samsung/gpio-config.c +++ b/arch/arm/plat-samsung/gpio-config.c @@ -1,7 +1,7 @@ /* linux/arch/arm/plat-s3c/gpio-config.c * * Copyright 2008 Openmoko, Inc. - * Copyright 2008 Simtec Electronics + * Copyright 2008-2010 Simtec Electronics * Ben Dooks * http://armlinux.simtec.co.uk/ * @@ -87,6 +87,19 @@ int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip, return 0; } +unsigned s3c_gpio_getcfg_s3c24xx_a(struct s3c_gpio_chip *chip, + unsigned int off) +{ + u32 con; + + con = __raw_readl(chip->base); + con >>= off; + con &= 1; + con++; + + return S3C_GPIO_SFN(con); +} + int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip, unsigned int off, unsigned int cfg) { @@ -109,6 +122,19 @@ int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip, return 0; } + +unsigned int s3c_gpio_getcfg_s3c24xx(struct s3c_gpio_chip *chip, + unsigned int off) +{ + u32 con; + + con = __raw_readl(chip->base); + con >>= off * 2; + con &= 3; + + /* this conversion works for IN and OUT as well as special mode */ + return S3C_GPIO_SPECIAL(con); +} #endif #ifdef CONFIG_S3C_GPIO_CFG_S3C64XX @@ -134,6 +160,25 @@ int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip, return 0; } + +unsigned s3c_gpio_getcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip, + unsigned int off) +{ + void __iomem *reg = chip->base; + unsigned int shift = (off & 7) * 4; + u32 con; + + if (off < 8 && chip->chip.ngpio > 8) + reg -= 4; + + con = __raw_readl(reg); + con >>= shift; + con &= 0xf; + + /* this conversion works for IN and OUT as well as special mode */ + return S3C_GPIO_SPECIAL(con); +} + #endif /* CONFIG_S3C_GPIO_CFG_S3C64XX */ #ifdef CONFIG_S3C_GPIO_PULL_UPDOWN diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h b/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h index 885e9ac..a8868c4 100644 --- a/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h +++ b/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h @@ -53,6 +53,18 @@ extern int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip, unsigned int off, unsigned int cfg); /** + * s3c_gpio_getcfg_s3c24xx - S3C24XX style GPIO configuration read. + * @chip: The gpio chip that is being configured. + * @off: The offset for the GPIO being configured. + * + * The reverse of s3c_gpio_setcfg_s3c24xx(). Will return a value whicg + * could be directly passed back to s3c_gpio_setcfg_s3c24xx(), from the + * S3C_GPIO_SPECIAL() macro. + */ +unsigned int s3c_gpio_getcfg_s3c24xx(struct s3c_gpio_chip *chip, + unsigned int off); + +/** * s3c_gpio_setcfg_s3c24xx_a - S3C24XX style GPIO configuration (Bank A) * @chip: The gpio chip that is being configured. * @off: The offset for the GPIO being configured. @@ -65,6 +77,21 @@ extern int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip, extern int s3c_gpio_setcfg_s3c24xx_a(struct s3c_gpio_chip *chip, unsigned int off, unsigned int cfg); + +/** + * s3c_gpio_getcfg_s3c24xx_a - S3C24XX style GPIO configuration read (Bank A) + * @chip: The gpio chip that is being configured. + * @off: The offset for the GPIO being configured. + * + * The reverse of s3c_gpio_setcfg_s3c24xx_a() turning an GPIO into a usable + * GPIO configuration value. + * + * @sa s3c_gpio_getcfg_s3c24xx + * @sa s3c_gpio_getcfg_s3c64xx_4bit + */ +extern unsigned s3c_gpio_getcfg_s3c24xx_a(struct s3c_gpio_chip *chip, + unsigned int off); + /** * s3c_gpio_setcfg_s3c64xx_4bit - S3C64XX 4bit single register GPIO config. * @chip: The gpio chip that is being configured. @@ -85,6 +112,20 @@ extern int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip, unsigned int off, unsigned int cfg); +/** + * s3c_gpio_getcfg_s3c64xx_4bit - S3C64XX 4bit single register GPIO config read. + * @chip: The gpio chip that is being configured. + * @off: The offset for the GPIO being configured. + * + * The reverse of s3c_gpio_setcfg_s3c64xx_4bit(), turning a gpio configuration + * register setting into a value the software can use, such as could be passed + * to s3c_gpio_setcfg_s3c64xx_4bit(). + * + * @sa s3c_gpio_getcfg_s3c24xx + */ +extern unsigned s3c_gpio_getcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip, + unsigned int off); + /* Pull-{up,down} resistor controls. * * S3C2410,S3C2440,S3C24A0 = Pull-UP, -- cgit v0.10.2 From 9933847b29bb3d3447d19236375ccc84bfbcf3df Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 6 May 2010 10:50:42 +0900 Subject: ARM: S3C24XX: Remove s3c2410_gpio_getcfg(), implement s3c_gpio_getcfg() Add s3c_gpio_getcfg() and change anything using s3c2410_gpio_getcfg() to use this instead. Signed-off-by: Ben Dooks diff --git a/arch/arm/plat-s3c24xx/gpio.c b/arch/arm/plat-s3c24xx/gpio.c index 24c0047..c7c0cd7 100644 --- a/arch/arm/plat-s3c24xx/gpio.c +++ b/arch/arm/plat-s3c24xx/gpio.c @@ -33,25 +33,6 @@ #include -unsigned int s3c2410_gpio_getcfg(unsigned int pin) -{ - void __iomem *base = S3C24XX_GPIO_BASE(pin); - unsigned long val = __raw_readl(base); - - if (pin < S3C2410_GPIO_BANKB) { - val >>= S3C2410_GPIO_OFFSET(pin); - val &= 1; - val += 1; - } else { - val >>= S3C2410_GPIO_OFFSET(pin)*2; - val &= 3; - } - - return val | S3C2410_GPIO_INPUT; -} - -EXPORT_SYMBOL(s3c2410_gpio_getcfg); - void s3c2410_gpio_pullup(unsigned int pin, unsigned int to) { void __iomem *base = S3C24XX_GPIO_BASE(pin); diff --git a/arch/arm/plat-s3c24xx/pm.c b/arch/arm/plat-s3c24xx/pm.c index 691fecc..60627e6 100644 --- a/arch/arm/plat-s3c24xx/pm.c +++ b/arch/arm/plat-s3c24xx/pm.c @@ -98,11 +98,11 @@ static void s3c_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs) else irqstate = s3c_irqwake_eintmask & (1L<chip.base; + + local_irq_save(flags); + ret = s3c_gpio_do_getcfg(chip, offset); + local_irq_restore(flags); + } + + return ret; +} +EXPORT_SYMBOL(s3c_gpio_getcfg); + + int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull) { struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h b/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h index a8868c4..3e21c75 100644 --- a/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h +++ b/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h @@ -30,6 +30,12 @@ static inline int s3c_gpio_do_setcfg(struct s3c_gpio_chip *chip, return (chip->config->set_config)(chip, off, config); } +static inline unsigned s3c_gpio_do_getcfg(struct s3c_gpio_chip *chip, + unsigned int off) +{ + return (chip->config->get_config)(chip, off); +} + static inline int s3c_gpio_do_setpull(struct s3c_gpio_chip *chip, unsigned int off, s3c_gpio_pull_t pull) { diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg.h b/arch/arm/plat-samsung/include/plat/gpio-cfg.h index 29cd6a8..8d01e85 100644 --- a/arch/arm/plat-samsung/include/plat/gpio-cfg.h +++ b/arch/arm/plat-samsung/include/plat/gpio-cfg.h @@ -77,6 +77,17 @@ struct s3c_gpio_cfg { */ extern int s3c_gpio_cfgpin(unsigned int pin, unsigned int to); +/** + * s3c_gpio_getcfg - Read the current function for a GPIO pin + * @pin: The pin to read the configuration value for. + * + * Read the configuration state of the given @pin, returning a value that + * could be passed back to s3c_gpio_cfgpin(). + * + * @sa s3c_gpio_cfgpin + */ +extern unsigned s3c_gpio_getcfg(unsigned int pin); + /* Define values for the pull-{up,down} available for each gpio pin. * * These values control the state of the weak pull-{up,down} resistors -- cgit v0.10.2 From 64f508da584f983642eb8cf808fcca68f9efa44a Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 6 May 2010 10:59:55 +0900 Subject: ARM: mini2440: Move to using gpiolib API and s3c_gpio functions Move the mach-mini2440 to using the gpiolib API for GPIOS it directly uses, and s3c_gpio calls for configuration. Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2440/mach-mini2440.c b/arch/arm/mach-s3c2440/mach-mini2440.c index 362a2f9..a76bcda 100644 --- a/arch/arm/mach-s3c2440/mach-mini2440.c +++ b/arch/arm/mach-s3c2440/mach-mini2440.c @@ -103,10 +103,10 @@ static void mini2440_udc_pullup(enum s3c2410_udc_cmd_e cmd) switch (cmd) { case S3C2410_UDC_P_ENABLE : - s3c2410_gpio_setpin(S3C2410_GPC(5), 1); + gpio_set_value(S3C2410_GPC(5), 1); break; case S3C2410_UDC_P_DISABLE : - s3c2410_gpio_setpin(S3C2410_GPC(5), 0); + gpio_set_value(S3C2410_GPC(5), 0); break; case S3C2410_UDC_P_RESET : break; @@ -636,22 +636,22 @@ static void __init mini2440_init(void) s3c_gpio_cfgpin(S3C2410_GPC(0), S3C2410_GPC0_LEND); /* Turn the backlight early on */ - s3c2410_gpio_setpin(S3C2410_GPG(4), 1); - s3c_gpio_cfgpin(S3C2410_GPG(4), S3C2410_GPIO_OUTPUT); + WARN_ON(gpio_request(S3C2410_GPG(4), "backlight")); + gpio_direction_output(S3C2410_GPG(4), 1); /* remove pullup on optional PWM backlight -- unused on 3.5 and 7"s */ - s3c2410_gpio_pullup(S3C2410_GPB(1), 0); + s3c_gpio_setpull(S3C2410_GPB(1), S3C_GPIO_PULL_UP); s3c2410_gpio_setpin(S3C2410_GPB(1), 0); s3c_gpio_cfgpin(S3C2410_GPB(1), S3C2410_GPIO_INPUT); /* Make sure the D+ pullup pin is output */ - s3c_gpio_cfgpin(S3C2410_GPC(5), S3C2410_GPIO_OUTPUT); + WARN_ON(gpio_request(S3C2410_GPC(5), "udc pup")); + gpio_direction_output(S3C2410_GPC(5), 0); /* mark the key as input, without pullups (there is one on the board) */ for (i = 0; i < ARRAY_SIZE(mini2440_buttons); i++) { - s3c2410_gpio_pullup(mini2440_buttons[i].gpio, 0); - s3c_gpio_cfgpin(mini2440_buttons[i].gpio, - S3C2410_GPIO_INPUT); + s3c_gpio_setpull(mini2440_buttons[i].gpio, S3C_GPIO_PULL_UP); + s3c_gpio_cfgpin(mini2440_buttons[i].gpio, S3C2410_GPIO_INPUT); } if (features.lcd_index != -1) { int li; -- cgit v0.10.2 From fb3787470ee6fee5900026170c05261c8c090a06 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 6 May 2010 11:03:50 +0900 Subject: ARM: S3C2410: Remove the users of s3c2410_gpio_pullup() Remove the last s3c2410_gpio_pullup() users in arch/arm/mach-s3c2410 Note, since mach-h1940.c is setting output and a pull-up, the call has vbeen chanerd to S3C_GPIO_PULL_NONE instead of S3C_GPIO_PULL_UP. Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/mach-amlm5900.c b/arch/arm/mach-s3c2410/mach-amlm5900.c index b42a760..34fc05a 100644 --- a/arch/arm/mach-s3c2410/mach-amlm5900.c +++ b/arch/arm/mach-s3c2410/mach-amlm5900.c @@ -227,7 +227,7 @@ static void amlm5900_init_pm(void) enable_irq_wake(IRQ_EINT9); /* configure the suspend/resume status pin */ s3c_gpio_cfgpin(S3C2410_GPF(2), S3C2410_GPIO_OUTPUT); - s3c2410_gpio_pullup(S3C2410_GPF(2), 0); + s3c_gpio_setpull(S3C2410_GPF(2), S3C_GPIO_PULL_UP); } } static void __init amlm5900_init(void) diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c index e2f7e64..9531b4c 100644 --- a/arch/arm/mach-s3c2410/mach-h1940.c +++ b/arch/arm/mach-s3c2410/mach-h1940.c @@ -209,7 +209,7 @@ static int h1940_backlight_init(struct device *dev) gpio_request(S3C2410_GPB(0), "Backlight"); gpio_direction_output(S3C2410_GPB(0), 0); - s3c2410_gpio_pullup(S3C2410_GPB(0), 0); + s3c_gpio_setpull(S3C2410_GPB(0), S3C_GPIO_PULL_NONE); s3c_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPB0_TOUT0); return 0; -- cgit v0.10.2 From 31da46d9f11ccdb11d7f2f07421f5cccb64fbbd6 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 6 May 2010 11:21:05 +0900 Subject: ARM: S3C24XX: Wrapper s3c2410_gpio_setpin and s3c2410_gpio_pullup() Change s3c2410_gpio_setpin() and s3c2410_gpio_pullup() to use the new s3c_ gpio configuration calls until all their users are converted. Signed-off-by: Ben Dooks diff --git a/arch/arm/plat-s3c24xx/gpio.c b/arch/arm/plat-s3c24xx/gpio.c index c7c0cd7..45126d3 100644 --- a/arch/arm/plat-s3c24xx/gpio.c +++ b/arch/arm/plat-s3c24xx/gpio.c @@ -1,6 +1,6 @@ /* linux/arch/arm/plat-s3c24xx/gpio.c * - * Copyright (c) 2004-2005 Simtec Electronics + * Copyright (c) 2004-2010 Simtec Electronics * Ben Dooks * * S3C24XX GPIO support @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -33,44 +34,34 @@ #include +/* gpiolib wrappers until these are totally eliminated */ + void s3c2410_gpio_pullup(unsigned int pin, unsigned int to) { - void __iomem *base = S3C24XX_GPIO_BASE(pin); - unsigned long offs = S3C2410_GPIO_OFFSET(pin); - unsigned long flags; - unsigned long up; + int ret; - if (pin < S3C2410_GPIO_BANKB) - return; + WARN_ON(to); /* should be none of these left */ - local_irq_save(flags); - - up = __raw_readl(base + 0x08); - up &= ~(1L << offs); - up |= to << offs; - __raw_writel(up, base + 0x08); + if (!to) { + /* if pull is enabled, try first with up, and if that + * fails, try using down */ - local_irq_restore(flags); + ret = s3c_gpio_setpull(pin, S3C_GPIO_PULL_UP); + if (ret) + s3c_gpio_setpull(pin, S3C_GPIO_PULL_DOWN); + } else { + s3c_gpio_setpull(pin, S3C_GPIO_PULL_NONE); + } } - EXPORT_SYMBOL(s3c2410_gpio_pullup); - void s3c2410_gpio_setpin(unsigned int pin, unsigned int to) { - void __iomem *base = S3C24XX_GPIO_BASE(pin); - unsigned long offs = S3C2410_GPIO_OFFSET(pin); - unsigned long flags; - unsigned long dat; + /* do this via gpiolib until all users removed */ - local_irq_save(flags); - - dat = __raw_readl(base + 0x04); - dat &= ~(1 << offs); - dat |= to << offs; - __raw_writel(dat, base + 0x04); - - local_irq_restore(flags); + gpio_request(pin, "temporary"); + gpio_set_value(pin, to); + gpio_free(pin); } EXPORT_SYMBOL(s3c2410_gpio_setpin); -- cgit v0.10.2 From 9772b7586efb189ac2dcac1d6f7d09c6d879ac64 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 6 May 2010 11:23:35 +0900 Subject: ARM: S3C24XX: Remove S3C2410_GPJ numbering Remove the old S3C2410_GPJ as we will be moving to the new gpiolib based driver code and these numbers will become invalid. Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/include/mach/regs-gpioj.h b/arch/arm/mach-s3c2410/include/mach/regs-gpioj.h index de463bc..5025757 100644 --- a/arch/arm/mach-s3c2410/include/mach/regs-gpioj.h +++ b/arch/arm/mach-s3c2410/include/mach/regs-gpioj.h @@ -22,81 +22,62 @@ * pull up works like all other ports. */ -#define S3C2440_GPIO_BANKJ (416) - #define S3C2413_GPJCON S3C2410_GPIOREG(0x80) #define S3C2413_GPJDAT S3C2410_GPIOREG(0x84) #define S3C2413_GPJUP S3C2410_GPIOREG(0x88) #define S3C2413_GPJSLPCON S3C2410_GPIOREG(0x8C) -#define S3C2440_GPJ0 S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 0) #define S3C2440_GPJ0_INP (0x00 << 0) #define S3C2440_GPJ0_OUTP (0x01 << 0) #define S3C2440_GPJ0_CAMDATA0 (0x02 << 0) -#define S3C2440_GPJ1 S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 1) #define S3C2440_GPJ1_INP (0x00 << 2) #define S3C2440_GPJ1_OUTP (0x01 << 2) #define S3C2440_GPJ1_CAMDATA1 (0x02 << 2) -#define S3C2440_GPJ2 S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 2) #define S3C2440_GPJ2_INP (0x00 << 4) #define S3C2440_GPJ2_OUTP (0x01 << 4) #define S3C2440_GPJ2_CAMDATA2 (0x02 << 4) -#define S3C2440_GPJ3 S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 3) #define S3C2440_GPJ3_INP (0x00 << 6) #define S3C2440_GPJ3_OUTP (0x01 << 6) #define S3C2440_GPJ3_CAMDATA3 (0x02 << 6) -#define S3C2440_GPJ4 S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 4) #define S3C2440_GPJ4_INP (0x00 << 8) #define S3C2440_GPJ4_OUTP (0x01 << 8) #define S3C2440_GPJ4_CAMDATA4 (0x02 << 8) -#define S3C2440_GPJ5 S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 5) #define S3C2440_GPJ5_INP (0x00 << 10) #define S3C2440_GPJ5_OUTP (0x01 << 10) #define S3C2440_GPJ5_CAMDATA5 (0x02 << 10) -#define S3C2440_GPJ6 S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 6) #define S3C2440_GPJ6_INP (0x00 << 12) #define S3C2440_GPJ6_OUTP (0x01 << 12) #define S3C2440_GPJ6_CAMDATA6 (0x02 << 12) -#define S3C2440_GPJ7 S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 7) #define S3C2440_GPJ7_INP (0x00 << 14) #define S3C2440_GPJ7_OUTP (0x01 << 14) #define S3C2440_GPJ7_CAMDATA7 (0x02 << 14) -#define S3C2440_GPJ8 S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 8) #define S3C2440_GPJ8_INP (0x00 << 16) #define S3C2440_GPJ8_OUTP (0x01 << 16) #define S3C2440_GPJ8_CAMPCLK (0x02 << 16) -#define S3C2440_GPJ9 S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 9) #define S3C2440_GPJ9_INP (0x00 << 18) #define S3C2440_GPJ9_OUTP (0x01 << 18) #define S3C2440_GPJ9_CAMVSYNC (0x02 << 18) -#define S3C2440_GPJ10 S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 10) #define S3C2440_GPJ10_INP (0x00 << 20) #define S3C2440_GPJ10_OUTP (0x01 << 20) #define S3C2440_GPJ10_CAMHREF (0x02 << 20) -#define S3C2440_GPJ11 S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 11) #define S3C2440_GPJ11_INP (0x00 << 22) #define S3C2440_GPJ11_OUTP (0x01 << 22) #define S3C2440_GPJ11_CAMCLKOUT (0x02 << 22) -#define S3C2440_GPJ12 S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 12) #define S3C2440_GPJ12_INP (0x00 << 24) #define S3C2440_GPJ12_OUTP (0x01 << 24) #define S3C2440_GPJ12_CAMRESET (0x02 << 24) -#define S3C2443_GPJ13 S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 13) -#define S3C2443_GPJ14 S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 14) -#define S3C2443_GPJ15 S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 15) - #endif /* __ASM_ARCH_REGS_GPIOJ_H */ -- cgit v0.10.2 From 1d3ef014b5fe959a789c2df708713d58c9491c3b Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 6 May 2010 11:32:14 +0900 Subject: ARM: S3C24XX: Remove _INP macros in Remove the _INP definitions, they are all zero and also unused Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/include/mach/regs-gpioj.h b/arch/arm/mach-s3c2410/include/mach/regs-gpioj.h index 5025757..19575e0 100644 --- a/arch/arm/mach-s3c2410/include/mach/regs-gpioj.h +++ b/arch/arm/mach-s3c2410/include/mach/regs-gpioj.h @@ -27,55 +27,42 @@ #define S3C2413_GPJUP S3C2410_GPIOREG(0x88) #define S3C2413_GPJSLPCON S3C2410_GPIOREG(0x8C) -#define S3C2440_GPJ0_INP (0x00 << 0) #define S3C2440_GPJ0_OUTP (0x01 << 0) #define S3C2440_GPJ0_CAMDATA0 (0x02 << 0) -#define S3C2440_GPJ1_INP (0x00 << 2) #define S3C2440_GPJ1_OUTP (0x01 << 2) #define S3C2440_GPJ1_CAMDATA1 (0x02 << 2) -#define S3C2440_GPJ2_INP (0x00 << 4) #define S3C2440_GPJ2_OUTP (0x01 << 4) #define S3C2440_GPJ2_CAMDATA2 (0x02 << 4) -#define S3C2440_GPJ3_INP (0x00 << 6) #define S3C2440_GPJ3_OUTP (0x01 << 6) #define S3C2440_GPJ3_CAMDATA3 (0x02 << 6) -#define S3C2440_GPJ4_INP (0x00 << 8) #define S3C2440_GPJ4_OUTP (0x01 << 8) #define S3C2440_GPJ4_CAMDATA4 (0x02 << 8) -#define S3C2440_GPJ5_INP (0x00 << 10) #define S3C2440_GPJ5_OUTP (0x01 << 10) #define S3C2440_GPJ5_CAMDATA5 (0x02 << 10) -#define S3C2440_GPJ6_INP (0x00 << 12) #define S3C2440_GPJ6_OUTP (0x01 << 12) #define S3C2440_GPJ6_CAMDATA6 (0x02 << 12) -#define S3C2440_GPJ7_INP (0x00 << 14) #define S3C2440_GPJ7_OUTP (0x01 << 14) #define S3C2440_GPJ7_CAMDATA7 (0x02 << 14) -#define S3C2440_GPJ8_INP (0x00 << 16) #define S3C2440_GPJ8_OUTP (0x01 << 16) #define S3C2440_GPJ8_CAMPCLK (0x02 << 16) -#define S3C2440_GPJ9_INP (0x00 << 18) #define S3C2440_GPJ9_OUTP (0x01 << 18) #define S3C2440_GPJ9_CAMVSYNC (0x02 << 18) -#define S3C2440_GPJ10_INP (0x00 << 20) #define S3C2440_GPJ10_OUTP (0x01 << 20) #define S3C2440_GPJ10_CAMHREF (0x02 << 20) -#define S3C2440_GPJ11_INP (0x00 << 22) #define S3C2440_GPJ11_OUTP (0x01 << 22) #define S3C2440_GPJ11_CAMCLKOUT (0x02 << 22) -#define S3C2440_GPJ12_INP (0x00 << 24) #define S3C2440_GPJ12_OUTP (0x01 << 24) #define S3C2440_GPJ12_CAMRESET (0x02 << 24) -- cgit v0.10.2 From 5faf5011841dc2a4797093b845e49bc40b4b4666 Mon Sep 17 00:00:00 2001 From: Yauhen Kharuzhy Date: Wed, 19 Aug 2009 16:31:05 +0300 Subject: ARM: S3C: Add S3C2416 detection to uncompress code Add S3C2416 serial port setup to uncompress code. Signed-off-by: Yauhen Kharuzhy Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/include/mach/uncompress.h b/arch/arm/mach-s3c2410/include/mach/uncompress.h index 72f756c..8b283f8 100644 --- a/arch/arm/mach-s3c2410/include/mach/uncompress.h +++ b/arch/arm/mach-s3c2410/include/mach/uncompress.h @@ -40,7 +40,9 @@ static void arch_detect_cpu(void) cpuid &= S3C2410_GSTATUS1_IDMASK; if (is_arm926() || cpuid == S3C2410_GSTATUS1_2440 || - cpuid == S3C2410_GSTATUS1_2442) { + cpuid == S3C2410_GSTATUS1_2442 || + cpuid == S3C2410_GSTATUS1_2416 || + cpuid == S3C2410_GSTATUS1_2450) { fifo_mask = S3C2440_UFSTAT_TXMASK; fifo_max = 63 << S3C2440_UFSTAT_TXSHIFT; } else { -- cgit v0.10.2 From 4fcfce9f33cd2e173f83c20e93c8b0a9397bf0bc Mon Sep 17 00:00:00 2001 From: Yauhen Kharuzhy Date: Wed, 19 Aug 2009 16:31:06 +0300 Subject: serial: Use s3c2440 driver for S3C2416 SoC UARTs in the S3C2416 are almost same as in S3C2443 and can be handled by s3c2440 serial driver. Signed-off-by: Yauhen Kharuzhy Signed-off-by: Ben Dooks diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index f55c494..5f3f03d 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -518,12 +518,13 @@ config SERIAL_S3C2412 Serial port support for the Samsung S3C2412 and S3C2413 SoC config SERIAL_S3C2440 - tristate "Samsung S3C2440/S3C2442 Serial port support" - depends on SERIAL_SAMSUNG && (CPU_S3C2440 || CPU_S3C2442) + tristate "Samsung S3C2440/S3C2442/S3C2416 Serial port support" + depends on SERIAL_SAMSUNG && (CPU_S3C2440 || CPU_S3C2442 || CPU_S3C2416) default y if CPU_S3C2440 default y if CPU_S3C2442 + select SERIAL_SAMSUNG_UARTS_4 if CPU_S3C2416 help - Serial port support for the Samsung S3C2440 and S3C2442 SoC + Serial port support for the Samsung S3C2440, S3C2416 and S3C2442 SoC config SERIAL_S3C24A0 tristate "Samsung S3C24A0 Serial port support" -- cgit v0.10.2 From 7df9c43fbe470628a755dfd028e58fdd7ab9b44e Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 4 May 2010 22:30:47 +0000 Subject: net/gianfar: drop recycled skbs on MTU change The size for skbs which is added to the recycled list is using the current descriptor size which is current MTU. gfar_new_skb() is also using this size. So after changing or alteast increasing the MTU all recycled skbs should be dropped. Signed-off-by: Sebastian Andrzej Siewior Acked-by: Andy Fleming Signed-off-by: David S. Miller diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 4e97ca1..5d3763f 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -1649,6 +1649,7 @@ static void free_skb_resources(struct gfar_private *priv) sizeof(struct rxbd8) * priv->total_rx_ring_size, priv->tx_queue[0]->tx_bd_base, priv->tx_queue[0]->tx_bd_dma_base); + skb_queue_purge(&priv->rx_recycle); } void gfar_start(struct net_device *dev) @@ -2088,7 +2089,6 @@ static int gfar_close(struct net_device *dev) disable_napi(priv); - skb_queue_purge(&priv->rx_recycle); cancel_work_sync(&priv->reset_task); stop_gfar(dev); -- cgit v0.10.2 From 54ad023ba8108d0163acc931ed4b5e4a8a3a7327 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Wed, 5 May 2010 21:30:35 -0700 Subject: ceph: don't use writeback_control in writepages completion The ->writepages writeback_control is not still valid in the writepages completion. We were touching it solely to adjust pages_skipped when there was a writeback error (EIO, ENOSPC, EPERM due to bad osd credentials), causing an oops in the writeback code shortly thereafter. Updating pages_skipped on error isn't correct anyway, so let's just rip out this (clearly broken) code to pass the wbc to the completion. Signed-off-by: Sage Weil diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 4b42c2b..a9005d8 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -504,7 +504,6 @@ static void writepages_finish(struct ceph_osd_request *req, int i; struct ceph_snap_context *snapc = req->r_snapc; struct address_space *mapping = inode->i_mapping; - struct writeback_control *wbc = req->r_wbc; __s32 rc = -EIO; u64 bytes = 0; struct ceph_client *client = ceph_inode_to_client(inode); @@ -546,10 +545,6 @@ static void writepages_finish(struct ceph_osd_request *req, clear_bdi_congested(&client->backing_dev_info, BLK_RW_ASYNC); - if (i >= wrote) { - dout("inode %p skipping page %p\n", inode, page); - wbc->pages_skipped++; - } ceph_put_snap_context((void *)page->private); page->private = 0; ClearPagePrivate(page); @@ -799,7 +794,6 @@ get_more_pages: alloc_page_vec(client, req); req->r_callback = writepages_finish; req->r_inode = inode; - req->r_wbc = wbc; } /* note position of first page in pvec */ diff --git a/fs/ceph/osd_client.h b/fs/ceph/osd_client.h index b075991..c5191d6 100644 --- a/fs/ceph/osd_client.h +++ b/fs/ceph/osd_client.h @@ -66,7 +66,6 @@ struct ceph_osd_request { struct list_head r_unsafe_item; struct inode *r_inode; /* for use by callbacks */ - struct writeback_control *r_wbc; /* ditto */ char r_oid[40]; /* object name */ int r_oid_len; -- cgit v0.10.2 From d40a4de0be08f005814a4fddac748fe5353208ec Mon Sep 17 00:00:00 2001 From: Brian Haley Date: Mon, 3 May 2010 15:44:27 +0000 Subject: IPv6: fix IPV6_RECVERR handling of locally-generated errors I noticed when I added support for IPV6_DONTFRAG that if you set IPV6_RECVERR and tried to send a UDP packet larger than 64K to an IPv6 destination, you'd correctly get an EMSGSIZE, but reading from MSG_ERRQUEUE returned the incorrect address in the cmsg: struct msghdr: msg_name 0x7fff8f3c96d0 msg_namelen 28 struct sockaddr_in6: sin6_family 10 sin6_port 7639 sin6_flowinfo 0 sin6_addr ::ffff:38.32.0.0 sin6_scope_id 0 ((null)) It should have returned this in my case: struct msghdr: msg_name 0x7fffd866b510 msg_namelen 28 struct sockaddr_in6: sin6_family 10 sin6_port 7639 sin6_flowinfo 0 sin6_addr 2620:0:a09:e000:21f:29ff:fe57:f88b sin6_scope_id 0 ((null)) The problem is that ipv6_recv_error() assumes that if the error wasn't generated by ICMPv6, it's an IPv4 address sitting there, and proceeds to create a v4-mapped address from it. Change ipv6_icmp_error() and ipv6_local_error() to set skb->protocol to htons(ETH_P_IPV6) so that ipv6_recv_error() knows the address sitting right after the extended error is IPv6, else it will incorrectly map the first octet into an IPv4-mapped IPv6 address in the cmsg structure returned in a recvmsg() call to obtain the error. Signed-off-by: Brian Haley -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Signed-off-by: David S. Miller diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 622dc79..6157388 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c @@ -222,6 +222,8 @@ void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, if (!skb) return; + skb->protocol = htons(ETH_P_IPV6); + serr = SKB_EXT_ERR(skb); serr->ee.ee_errno = err; serr->ee.ee_origin = SO_EE_ORIGIN_ICMP6; @@ -255,6 +257,8 @@ void ipv6_local_error(struct sock *sk, int err, struct flowi *fl, u32 info) if (!skb) return; + skb->protocol = htons(ETH_P_IPV6); + skb_put(skb, sizeof(struct ipv6hdr)); skb_reset_network_header(skb); iph = ipv6_hdr(skb); @@ -319,7 +323,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) sin->sin6_flowinfo = 0; sin->sin6_port = serr->port; sin->sin6_scope_id = 0; - if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP6) { + if (skb->protocol == htons(ETH_P_IPV6)) { ipv6_addr_copy(&sin->sin6_addr, (struct in6_addr *)(nh + serr->addr_offset)); if (np->sndflow) @@ -341,7 +345,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) sin->sin6_family = AF_INET6; sin->sin6_flowinfo = 0; sin->sin6_scope_id = 0; - if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP6) { + if (skb->protocol == htons(ETH_P_IPV6)) { ipv6_addr_copy(&sin->sin6_addr, &ipv6_hdr(skb)->saddr); if (np->rxopt.all) datagram_recv_ctl(sk, msg, skb); -- cgit v0.10.2 From 9b7a37853a8cd69829eb1d9715a6c09aae01eeec Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 6 May 2010 15:09:45 +0900 Subject: sh: Make initrd detection more robust. Various boot loaders go to various extents to thwart the initrd detection logic (mostly on account of not being able to be bothered with adhering to the established boot ABI), so we make the detection logic a bit more robust. This makes it possible to work around the SDK7786's firmware's attempts to thwart compressed image booting. Victory is mine. Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 14735d5..9c7f781 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -188,6 +188,63 @@ static inline void __init reserve_crashkernel(void) {} #endif +static void __init check_for_initrd(void) +{ +#ifdef CONFIG_BLK_DEV_INITRD + unsigned long start, end; + + /* + * Check for the rare cases where boot loaders adhere to the boot + * ABI. + */ + if (!LOADER_TYPE || !INITRD_START || !INITRD_SIZE) + goto disable; + + start = INITRD_START + __MEMORY_START; + end = start + INITRD_SIZE; + + if (unlikely(end <= start)) + goto disable; + if (unlikely(start & ~PAGE_MASK)) { + pr_err("initrd must be page aligned\n"); + goto disable; + } + + if (unlikely(start < PAGE_OFFSET)) { + pr_err("initrd start < PAGE_OFFSET\n"); + goto disable; + } + + if (unlikely(end > lmb_end_of_DRAM())) { + pr_err("initrd extends beyond end of memory " + "(0x%08lx > 0x%08lx)\ndisabling initrd\n", + end, (unsigned long)lmb_end_of_DRAM()); + goto disable; + } + + /* + * If we got this far inspite of the boot loader's best efforts + * to the contrary, assume we actually have a valid initrd and + * fix up the root dev. + */ + ROOT_DEV = Root_RAM0; + + /* + * Address sanitization + */ + initrd_start = (unsigned long)__va(__pa(start)); + initrd_end = initrd_start + INITRD_SIZE; + + reserve_bootmem(__pa(initrd_start), INITRD_SIZE, BOOTMEM_DEFAULT); + + return; + +disable: + pr_info("initrd disabled\n"); + initrd_start = initrd_end = 0; +#endif +} + void __cpuinit calibrate_delay(void) { struct clk *clk = clk_get(NULL, "cpu_clk"); @@ -277,26 +334,7 @@ void __init setup_bootmem_allocator(unsigned long free_pfn) sparse_memory_present_with_active_regions(0); -#ifdef CONFIG_BLK_DEV_INITRD - ROOT_DEV = Root_RAM0; - - if (LOADER_TYPE && INITRD_START) { - unsigned long initrd_start_phys = INITRD_START + __MEMORY_START; - - if (initrd_start_phys + INITRD_SIZE <= PFN_PHYS(max_low_pfn)) { - reserve_bootmem(initrd_start_phys, INITRD_SIZE, - BOOTMEM_DEFAULT); - initrd_start = (unsigned long)__va(initrd_start_phys); - initrd_end = initrd_start + INITRD_SIZE; - } else { - printk("initrd extends beyond end of memory " - "(0x%08lx > 0x%08lx)\ndisabling initrd\n", - initrd_start_phys + INITRD_SIZE, - (unsigned long)PFN_PHYS(max_low_pfn)); - initrd_start = 0; - } - } -#endif + check_for_initrd(); reserve_crashkernel(); } -- cgit v0.10.2 From 4f47b4c9f0b711bf84adb8c27774ae80d346b628 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Wed, 5 May 2010 13:22:25 -0700 Subject: x86, acpi/irq: Define gsi_end when X86_IO_APIC is undefined My recent changes introducing a global gsi_end variable failed to take into account the case of using acpi on a system not built to support IO_APICs, causing the build to fail. Define gsi_end to 15 when CONFIG_X86_IO_APIC is not set to avoid compile errors. Signed-off-by: Eric W. Biederman Cc: Yinghai Lu LKML-Reference: Signed-off-by: Ingo Molnar diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h index 9da192a..63cb409 100644 --- a/arch/x86/include/asm/io_apic.h +++ b/arch/x86/include/asm/io_apic.h @@ -197,6 +197,7 @@ static const int timer_through_8259 = 0; static inline void ioapic_init_mappings(void) { } static inline void ioapic_insert_resources(void) { } static inline void probe_nr_irqs_gsi(void) { } +#define gsi_end (NR_IRQS_LEGACY - 1) static inline int mp_find_ioapic(u32 gsi) { return 0; } struct io_apic_irq_attr; -- cgit v0.10.2 From 6ec82562ffc6f297d0de36d65776cff8e5704867 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 6 May 2010 00:53:53 -0700 Subject: veth: Dont kfree_skb() after dev_forward_skb() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In case of congestion, netif_rx() frees the skb, so we must assume dev_forward_skb() also consume skb. Bug introduced by commit 445409602c092 (veth: move loopback logic to common location) We must change dev_forward_skb() to always consume skb, and veth to not double free it. Bug report : http://marc.info/?l=linux-netdev&m=127310770900442&w=3 Reported-by: Martín Ferrari Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller diff --git a/drivers/net/veth.c b/drivers/net/veth.c index f9f0730..5ec542d 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -187,7 +187,6 @@ tx_drop: return NETDEV_TX_OK; rx_drop: - kfree_skb(skb); rcv_stats->rx_dropped++; return NETDEV_TX_OK; } diff --git a/net/core/dev.c b/net/core/dev.c index f769098..264137f 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1451,7 +1451,7 @@ static inline void net_timestamp(struct sk_buff *skb) * * return values: * NET_RX_SUCCESS (no congestion) - * NET_RX_DROP (packet was dropped) + * NET_RX_DROP (packet was dropped, but freed) * * dev_forward_skb can be used for injecting an skb from the * start_xmit function of one device into the receive queue @@ -1465,12 +1465,11 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb) { skb_orphan(skb); - if (!(dev->flags & IFF_UP)) - return NET_RX_DROP; - - if (skb->len > (dev->mtu + dev->hard_header_len)) + if (!(dev->flags & IFF_UP) || + (skb->len > (dev->mtu + dev->hard_header_len))) { + kfree_skb(skb); return NET_RX_DROP; - + } skb_set_dev(skb, dev); skb->tstamp.tv64 = 0; skb->pkt_type = PACKET_HOST; -- cgit v0.10.2 From 50b5d6ad63821cea324a5a7a19854d4de1a0a819 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Thu, 6 May 2010 00:56:07 -0700 Subject: sctp: Fix a race between ICMP protocol unreachable and connect() ICMP protocol unreachable handling completely disregarded the fact that the user may have locked the socket. It proceeded to destroy the association, even though the user may have held the lock and had a ref on the association. This resulted in the following: Attempt to release alive inet socket f6afcc00 ========================= [ BUG: held lock freed! ] ------------------------- somenu/2672 is freeing memory f6afcc00-f6afcfff, with a lock still held there! (sk_lock-AF_INET){+.+.+.}, at: [] sctp_connect+0x13/0x4c 1 lock held by somenu/2672: #0: (sk_lock-AF_INET){+.+.+.}, at: [] sctp_connect+0x13/0x4c stack backtrace: Pid: 2672, comm: somenu Not tainted 2.6.32-telco #55 Call Trace: [] ? printk+0xf/0x11 [] debug_check_no_locks_freed+0xce/0xff [] kmem_cache_free+0x21/0x66 [] __sk_free+0x9d/0xab [] sk_free+0x1c/0x1e [] sctp_association_put+0x32/0x89 [] __sctp_connect+0x36d/0x3f4 [] ? sctp_connect+0x13/0x4c [] ? autoremove_wake_function+0x0/0x33 [] sctp_connect+0x31/0x4c [] inet_dgram_connect+0x4b/0x55 [] sys_connect+0x54/0x71 [] ? lock_release_non_nested+0x88/0x239 [] ? might_fault+0x42/0x7c [] ? might_fault+0x42/0x7c [] sys_socketcall+0x6d/0x178 [] ? trace_hardirqs_on_thunk+0xc/0x10 [] syscall_call+0x7/0xb This was because the sctp_wait_for_connect() would aqcure the socket lock and then proceed to release the last reference count on the association, thus cause the fully destruction path to finish freeing the socket. The simplest solution is to start a very short timer in case the socket is owned by user. When the timer expires, we can do some verification and be able to do the release properly. Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index 851c813..61d73e3 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h @@ -279,6 +279,7 @@ int sctp_do_sm(sctp_event_t event_type, sctp_subtype_t subtype, /* 2nd level prototypes */ void sctp_generate_t3_rtx_event(unsigned long peer); void sctp_generate_heartbeat_event(unsigned long peer); +void sctp_generate_proto_unreach_event(unsigned long peer); void sctp_ootb_pkt_free(struct sctp_packet *); diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 597f8e2..219043a 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -1010,6 +1010,9 @@ struct sctp_transport { /* Heartbeat timer is per destination. */ struct timer_list hb_timer; + /* Timer to handle ICMP proto unreachable envets */ + struct timer_list proto_unreach_timer; + /* Since we're using per-destination retransmission timers * (see above), we're also using per-destination "transmitted" * queues. This probably ought to be a private struct diff --git a/net/sctp/input.c b/net/sctp/input.c index 2a57018..ea21924 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -440,11 +440,25 @@ void sctp_icmp_proto_unreachable(struct sock *sk, { SCTP_DEBUG_PRINTK("%s\n", __func__); - sctp_do_sm(SCTP_EVENT_T_OTHER, - SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH), - asoc->state, asoc->ep, asoc, t, - GFP_ATOMIC); + if (sock_owned_by_user(sk)) { + if (timer_pending(&t->proto_unreach_timer)) + return; + else { + if (!mod_timer(&t->proto_unreach_timer, + jiffies + (HZ/20))) + sctp_association_hold(asoc); + } + + } else { + if (timer_pending(&t->proto_unreach_timer) && + del_timer(&t->proto_unreach_timer)) + sctp_association_put(asoc); + sctp_do_sm(SCTP_EVENT_T_OTHER, + SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH), + asoc->state, asoc->ep, asoc, t, + GFP_ATOMIC); + } } /* Common lookup code for icmp/icmpv6 error handler. */ diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index d5ae450..eb1f42f 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -397,6 +397,41 @@ out_unlock: sctp_transport_put(transport); } +/* Handle the timeout of the ICMP protocol unreachable timer. Trigger + * the correct state machine transition that will close the association. + */ +void sctp_generate_proto_unreach_event(unsigned long data) +{ + struct sctp_transport *transport = (struct sctp_transport *) data; + struct sctp_association *asoc = transport->asoc; + + sctp_bh_lock_sock(asoc->base.sk); + if (sock_owned_by_user(asoc->base.sk)) { + SCTP_DEBUG_PRINTK("%s:Sock is busy.\n", __func__); + + /* Try again later. */ + if (!mod_timer(&transport->proto_unreach_timer, + jiffies + (HZ/20))) + sctp_association_hold(asoc); + goto out_unlock; + } + + /* Is this structure just waiting around for us to actually + * get destroyed? + */ + if (asoc->base.dead) + goto out_unlock; + + sctp_do_sm(SCTP_EVENT_T_OTHER, + SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH), + asoc->state, asoc->ep, asoc, transport, GFP_ATOMIC); + +out_unlock: + sctp_bh_unlock_sock(asoc->base.sk); + sctp_association_put(asoc); +} + + /* Inject a SACK Timeout event into the state machine. */ static void sctp_generate_sack_event(unsigned long data) { diff --git a/net/sctp/transport.c b/net/sctp/transport.c index be4d63d..4a36803 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c @@ -108,6 +108,8 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, (unsigned long)peer); setup_timer(&peer->hb_timer, sctp_generate_heartbeat_event, (unsigned long)peer); + setup_timer(&peer->proto_unreach_timer, + sctp_generate_proto_unreach_event, (unsigned long)peer); /* Initialize the 64-bit random nonce sent with heartbeat. */ get_random_bytes(&peer->hb_nonce, sizeof(peer->hb_nonce)); -- cgit v0.10.2 From b0c4d952a158a6a2547672cf4fc9d55e415410de Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Thu, 6 May 2010 02:24:34 -0700 Subject: x86: Fix fake apicid to node mapping for numa emulation With NUMA emulation, it's possible for a single cpu to be bound to multiple nodes since more than one may have affinity if allocated on a physical node that is local to the cpu. APIC ids must therefore be mapped to the lowest node ids to maintain generic kernel use of functions such as cpu_to_node() that determine device affinity. For example, if a device has proximity to physical node 1, for instance, and a cpu happens to be mapped to a higher emulated node id 8, the proximity may not be correctly determined by comparison in generic code even though the cpu may be truly local and allocated on physical node 1. When this happens, the true topology of the machine isn't accurately represented in the emulated environment; although this isn't critical to the system's uptime, any generic code that is NUMA aware benefits from the physical topology being accurately represented. This can affect any system that maps multiple APIC ids to a single node and is booted with numa=fake=N where N is greater than the number of physical nodes. Signed-off-by: David Rientjes Cc: Yinghai Lu Cc: Suresh Siddha LKML-Reference: Signed-off-by: Ingo Molnar diff --git a/arch/x86/mm/srat_64.c b/arch/x86/mm/srat_64.c index 28c6876..38512d0 100644 --- a/arch/x86/mm/srat_64.c +++ b/arch/x86/mm/srat_64.c @@ -461,7 +461,8 @@ void __init acpi_fake_nodes(const struct bootnode *fake_nodes, int num_nodes) * node, it must now point to the fake node ID. */ for (j = 0; j < MAX_LOCAL_APIC; j++) - if (apicid_to_node[j] == nid) + if (apicid_to_node[j] == nid && + fake_apicid_to_node[j] == NUMA_NO_NODE) fake_apicid_to_node[j] = i; } for (i = 0; i < num_nodes; i++) -- cgit v0.10.2 From 80ea76bb2575c426154b8d61d324197ee3592baa Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 6 May 2010 03:15:59 -0700 Subject: phy: Fix initialization in micrel driver. Missing name string in ks8001_driver, so we crash on register. Reported-by: Ingo Molnar Tested-by: Ingo Molnar Signed-off-by: David S. Miller diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index 0cd80e4..e67691d 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -32,6 +32,7 @@ static int kszphy_config_init(struct phy_device *phydev) static struct phy_driver ks8001_driver = { .phy_id = PHY_ID_KS8001, + .name = "Micrel KS8001", .phy_id_mask = 0x00fffff0, .features = PHY_BASIC_FEATURES, .flags = PHY_POLL, -- cgit v0.10.2 From 3de668ee8d5b1e08da3200f926ff5a28aeb99bc2 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Mon, 3 May 2010 15:00:25 +0200 Subject: oprofile/x86: notify cpus only when daemon is running This patch moves the cpu notifier registration from nmi_init() to nmi_setup(). The corresponding unregistration function is now in nmi_shutdown(). Thus, the hotplug code is only active, if the oprofile daemon is running. Cc: Andi Kleen Signed-off-by: Robert Richter diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index 7de0572..2a08672 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -504,6 +504,7 @@ static int nmi_setup(void) goto fail; get_online_cpus(); + register_cpu_notifier(&oprofile_cpu_nb); on_each_cpu(nmi_cpu_setup, NULL, 1); nmi_enabled = 1; put_online_cpus(); @@ -519,6 +520,7 @@ static void nmi_shutdown(void) struct op_msrs *msrs; get_online_cpus(); + unregister_cpu_notifier(&oprofile_cpu_nb); on_each_cpu(nmi_cpu_shutdown, NULL, 1); nmi_enabled = 0; ctr_running = 0; @@ -739,12 +741,6 @@ int __init op_nmi_init(struct oprofile_operations *ops) return -ENODEV; } - get_online_cpus(); - register_cpu_notifier(&oprofile_cpu_nb); - nmi_enabled = 0; - ctr_running = 0; - put_online_cpus(); - /* default values, can be overwritten by model */ ops->create_files = nmi_create_files; ops->setup = nmi_setup; @@ -771,14 +767,8 @@ int __init op_nmi_init(struct oprofile_operations *ops) void op_nmi_exit(void) { - if (using_nmi) { + if (using_nmi) exit_sysfs(); - get_online_cpus(); - unregister_cpu_notifier(&oprofile_cpu_nb); - nmi_enabled = 0; - ctr_running = 0; - put_online_cpus(); - } if (model->exit) model->exit(); } -- cgit v0.10.2 From bae663bc635e2726c7c5228dbf0f2051e16d1c81 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Wed, 5 May 2010 17:47:17 +0200 Subject: oprofile/x86: make AMD IBS hotplug capable Current IBS code is not hotplug capable. An offline cpu might not be initialized or deinitialized properly. This patch fixes this by removing on_each_cpu() functions. The IBS init/deinit code is executed in the per-cpu functions model->setup_ctrs() and model->cpu_down() which are also called by hotplug notifiers. model->cpu_down() replaces model->exit() that became obsolete. Cc: Andi Kleen Signed-off-by: Robert Richter diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index 2a08672..b28d2f1 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -397,6 +397,8 @@ static void nmi_cpu_shutdown(void *dummy) apic_write(APIC_LVTPC, per_cpu(saved_lvtpc, cpu)); apic_write(APIC_LVTERR, v); nmi_cpu_restore_registers(msrs); + if (model->cpu_down) + model->cpu_down(); } static void nmi_cpu_up(void *dummy) @@ -769,6 +771,4 @@ void op_nmi_exit(void) { if (using_nmi) exit_sysfs(); - if (model->exit) - model->exit(); } diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c index 384c524..b67a6b5 100644 --- a/arch/x86/oprofile/op_model_amd.c +++ b/arch/x86/oprofile/op_model_amd.c @@ -374,6 +374,15 @@ static void op_amd_setup_ctrs(struct op_x86_model_spec const *model, val |= op_x86_get_ctrl(model, &counter_config[virt]); wrmsrl(msrs->controls[i].addr, val); } + + if (ibs_caps) + setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_NMI, 0); +} + +static void op_amd_cpu_shutdown(void) +{ + if (ibs_caps) + setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1); } static int op_amd_check_ctrs(struct pt_regs * const regs, @@ -436,28 +445,16 @@ static void op_amd_stop(struct op_msrs const * const msrs) op_amd_stop_ibs(); } -static u8 ibs_eilvt_off; - -static inline void apic_init_ibs_nmi_per_cpu(void *arg) -{ - ibs_eilvt_off = setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_NMI, 0); -} - -static inline void apic_clear_ibs_nmi_per_cpu(void *arg) -{ - setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1); -} - -static int init_ibs_nmi(void) +static int __init_ibs_nmi(void) { #define IBSCTL_LVTOFFSETVAL (1 << 8) #define IBSCTL 0x1cc struct pci_dev *cpu_cfg; int nodes; u32 value = 0; + u8 ibs_eilvt_off; - /* per CPU setup */ - on_each_cpu(apic_init_ibs_nmi_per_cpu, NULL, 1); + ibs_eilvt_off = setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1); nodes = 0; cpu_cfg = NULL; @@ -487,21 +484,15 @@ static int init_ibs_nmi(void) return 0; } -/* uninitialize the APIC for the IBS interrupts if needed */ -static void clear_ibs_nmi(void) -{ - on_each_cpu(apic_clear_ibs_nmi_per_cpu, NULL, 1); -} - /* initialize the APIC for the IBS interrupts if available */ -static void ibs_init(void) +static void init_ibs(void) { ibs_caps = get_ibs_caps(); if (!ibs_caps) return; - if (init_ibs_nmi()) { + if (__init_ibs_nmi()) { ibs_caps = 0; return; } @@ -510,14 +501,6 @@ static void ibs_init(void) (unsigned)ibs_caps); } -static void ibs_exit(void) -{ - if (!ibs_caps) - return; - - clear_ibs_nmi(); -} - static int (*create_arch_files)(struct super_block *sb, struct dentry *root); static int setup_ibs_files(struct super_block *sb, struct dentry *root) @@ -566,17 +549,12 @@ static int setup_ibs_files(struct super_block *sb, struct dentry *root) static int op_amd_init(struct oprofile_operations *ops) { - ibs_init(); + init_ibs(); create_arch_files = ops->create_files; ops->create_files = setup_ibs_files; return 0; } -static void op_amd_exit(void) -{ - ibs_exit(); -} - struct op_x86_model_spec op_amd_spec = { .num_counters = NUM_COUNTERS, .num_controls = NUM_COUNTERS, @@ -584,9 +562,9 @@ struct op_x86_model_spec op_amd_spec = { .reserved = MSR_AMD_EVENTSEL_RESERVED, .event_mask = OP_EVENT_MASK, .init = op_amd_init, - .exit = op_amd_exit, .fill_in_addresses = &op_amd_fill_in_addresses, .setup_ctrs = &op_amd_setup_ctrs, + .cpu_down = &op_amd_cpu_shutdown, .check_ctrs = &op_amd_check_ctrs, .start = &op_amd_start, .stop = &op_amd_stop, diff --git a/arch/x86/oprofile/op_x86_model.h b/arch/x86/oprofile/op_x86_model.h index 5514013..89017fa 100644 --- a/arch/x86/oprofile/op_x86_model.h +++ b/arch/x86/oprofile/op_x86_model.h @@ -40,10 +40,10 @@ struct op_x86_model_spec { u64 reserved; u16 event_mask; int (*init)(struct oprofile_operations *ops); - void (*exit)(void); int (*fill_in_addresses)(struct op_msrs * const msrs); void (*setup_ctrs)(struct op_x86_model_spec const *model, struct op_msrs const * const msrs); + void (*cpu_down)(void); int (*check_ctrs)(struct pt_regs * const regs, struct op_msrs const * const msrs); void (*start)(struct op_msrs const * const msrs); -- cgit v0.10.2 From 1142d810298e694754498dbb4983fcb6cb7fd884 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 6 May 2010 18:49:20 +0200 Subject: cpu_stop: implement stop_cpu[s]() Implement a simplistic per-cpu maximum priority cpu monopolization mechanism. A non-sleeping callback can be scheduled to run on one or multiple cpus with maximum priority monopolozing those cpus. This is primarily to replace and unify RT workqueue usage in stop_machine and scheduler migration_thread which currently is serving multiple purposes. Four functions are provided - stop_one_cpu(), stop_one_cpu_nowait(), stop_cpus() and try_stop_cpus(). This is to allow clean sharing of resources among stop_cpu and all the migration thread users. One stopper thread per cpu is created which is currently named "stopper/CPU". This will eventually replace the migration thread and take on its name. * This facility was originally named cpuhog and lived in separate files but Peter Zijlstra nacked the name and thus got renamed to cpu_stop and moved into stop_machine.c. * Better reporting of preemption leak as per Peter's suggestion. Signed-off-by: Tejun Heo Acked-by: Peter Zijlstra Cc: Oleg Nesterov Cc: Dimitri Sivanich diff --git a/include/linux/stop_machine.h b/include/linux/stop_machine.h index baba3a2..efcbd6c 100644 --- a/include/linux/stop_machine.h +++ b/include/linux/stop_machine.h @@ -1,15 +1,46 @@ #ifndef _LINUX_STOP_MACHINE #define _LINUX_STOP_MACHINE -/* "Bogolock": stop the entire machine, disable interrupts. This is a - very heavy lock, which is equivalent to grabbing every spinlock - (and more). So the "read" side to such a lock is anything which - disables preeempt. */ + #include #include +#include #include #if defined(CONFIG_STOP_MACHINE) && defined(CONFIG_SMP) +/* + * stop_cpu[s]() is simplistic per-cpu maximum priority cpu + * monopolization mechanism. The caller can specify a non-sleeping + * function to be executed on a single or multiple cpus preempting all + * other processes and monopolizing those cpus until it finishes. + * + * Resources for this mechanism are preallocated when a cpu is brought + * up and requests are guaranteed to be served as long as the target + * cpus are online. + */ + +typedef int (*cpu_stop_fn_t)(void *arg); + +struct cpu_stop_work { + struct list_head list; /* cpu_stopper->works */ + cpu_stop_fn_t fn; + void *arg; + struct cpu_stop_done *done; +}; + +int stop_one_cpu(unsigned int cpu, cpu_stop_fn_t fn, void *arg); +void stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg, + struct cpu_stop_work *work_buf); +int stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg); +int try_stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg); + +/* + * stop_machine "Bogolock": stop the entire machine, disable + * interrupts. This is a very heavy lock, which is equivalent to + * grabbing every spinlock (and more). So the "read" side to such a + * lock is anything which disables preeempt. + */ + /** * stop_machine: freeze the machine on all CPUs and run this function * @fn: the function to run diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c index 9bb9fb1..7e3f918 100644 --- a/kernel/stop_machine.c +++ b/kernel/stop_machine.c @@ -1,17 +1,379 @@ -/* Copyright 2008, 2005 Rusty Russell rusty@rustcorp.com.au IBM Corporation. - * GPL v2 and any later version. +/* + * kernel/stop_machine.c + * + * Copyright (C) 2008, 2005 IBM Corporation. + * Copyright (C) 2008, 2005 Rusty Russell rusty@rustcorp.com.au + * Copyright (C) 2010 SUSE Linux Products GmbH + * Copyright (C) 2010 Tejun Heo + * + * This file is released under the GPLv2 and any later version. */ +#include #include -#include +#include #include #include +#include #include #include -#include #include +#include #include -#include + +/* + * Structure to determine completion condition and record errors. May + * be shared by works on different cpus. + */ +struct cpu_stop_done { + atomic_t nr_todo; /* nr left to execute */ + bool executed; /* actually executed? */ + int ret; /* collected return value */ + struct completion completion; /* fired if nr_todo reaches 0 */ +}; + +/* the actual stopper, one per every possible cpu, enabled on online cpus */ +struct cpu_stopper { + spinlock_t lock; + struct list_head works; /* list of pending works */ + struct task_struct *thread; /* stopper thread */ + bool enabled; /* is this stopper enabled? */ +}; + +static DEFINE_PER_CPU(struct cpu_stopper, cpu_stopper); + +static void cpu_stop_init_done(struct cpu_stop_done *done, unsigned int nr_todo) +{ + memset(done, 0, sizeof(*done)); + atomic_set(&done->nr_todo, nr_todo); + init_completion(&done->completion); +} + +/* signal completion unless @done is NULL */ +static void cpu_stop_signal_done(struct cpu_stop_done *done, bool executed) +{ + if (done) { + if (executed) + done->executed = true; + if (atomic_dec_and_test(&done->nr_todo)) + complete(&done->completion); + } +} + +/* queue @work to @stopper. if offline, @work is completed immediately */ +static void cpu_stop_queue_work(struct cpu_stopper *stopper, + struct cpu_stop_work *work) +{ + unsigned long flags; + + spin_lock_irqsave(&stopper->lock, flags); + + if (stopper->enabled) { + list_add_tail(&work->list, &stopper->works); + wake_up_process(stopper->thread); + } else + cpu_stop_signal_done(work->done, false); + + spin_unlock_irqrestore(&stopper->lock, flags); +} + +/** + * stop_one_cpu - stop a cpu + * @cpu: cpu to stop + * @fn: function to execute + * @arg: argument to @fn + * + * Execute @fn(@arg) on @cpu. @fn is run in a process context with + * the highest priority preempting any task on the cpu and + * monopolizing it. This function returns after the execution is + * complete. + * + * This function doesn't guarantee @cpu stays online till @fn + * completes. If @cpu goes down in the middle, execution may happen + * partially or fully on different cpus. @fn should either be ready + * for that or the caller should ensure that @cpu stays online until + * this function completes. + * + * CONTEXT: + * Might sleep. + * + * RETURNS: + * -ENOENT if @fn(@arg) was not executed because @cpu was offline; + * otherwise, the return value of @fn. + */ +int stop_one_cpu(unsigned int cpu, cpu_stop_fn_t fn, void *arg) +{ + struct cpu_stop_done done; + struct cpu_stop_work work = { .fn = fn, .arg = arg, .done = &done }; + + cpu_stop_init_done(&done, 1); + cpu_stop_queue_work(&per_cpu(cpu_stopper, cpu), &work); + wait_for_completion(&done.completion); + return done.executed ? done.ret : -ENOENT; +} + +/** + * stop_one_cpu_nowait - stop a cpu but don't wait for completion + * @cpu: cpu to stop + * @fn: function to execute + * @arg: argument to @fn + * + * Similar to stop_one_cpu() but doesn't wait for completion. The + * caller is responsible for ensuring @work_buf is currently unused + * and will remain untouched until stopper starts executing @fn. + * + * CONTEXT: + * Don't care. + */ +void stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg, + struct cpu_stop_work *work_buf) +{ + *work_buf = (struct cpu_stop_work){ .fn = fn, .arg = arg, }; + cpu_stop_queue_work(&per_cpu(cpu_stopper, cpu), work_buf); +} + +/* static data for stop_cpus */ +static DEFINE_MUTEX(stop_cpus_mutex); +static DEFINE_PER_CPU(struct cpu_stop_work, stop_cpus_work); + +int __stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg) +{ + struct cpu_stop_work *work; + struct cpu_stop_done done; + unsigned int cpu; + + /* initialize works and done */ + for_each_cpu(cpu, cpumask) { + work = &per_cpu(stop_cpus_work, cpu); + work->fn = fn; + work->arg = arg; + work->done = &done; + } + cpu_stop_init_done(&done, cpumask_weight(cpumask)); + + /* + * Disable preemption while queueing to avoid getting + * preempted by a stopper which might wait for other stoppers + * to enter @fn which can lead to deadlock. + */ + preempt_disable(); + for_each_cpu(cpu, cpumask) + cpu_stop_queue_work(&per_cpu(cpu_stopper, cpu), + &per_cpu(stop_cpus_work, cpu)); + preempt_enable(); + + wait_for_completion(&done.completion); + return done.executed ? done.ret : -ENOENT; +} + +/** + * stop_cpus - stop multiple cpus + * @cpumask: cpus to stop + * @fn: function to execute + * @arg: argument to @fn + * + * Execute @fn(@arg) on online cpus in @cpumask. On each target cpu, + * @fn is run in a process context with the highest priority + * preempting any task on the cpu and monopolizing it. This function + * returns after all executions are complete. + * + * This function doesn't guarantee the cpus in @cpumask stay online + * till @fn completes. If some cpus go down in the middle, execution + * on the cpu may happen partially or fully on different cpus. @fn + * should either be ready for that or the caller should ensure that + * the cpus stay online until this function completes. + * + * All stop_cpus() calls are serialized making it safe for @fn to wait + * for all cpus to start executing it. + * + * CONTEXT: + * Might sleep. + * + * RETURNS: + * -ENOENT if @fn(@arg) was not executed at all because all cpus in + * @cpumask were offline; otherwise, 0 if all executions of @fn + * returned 0, any non zero return value if any returned non zero. + */ +int stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg) +{ + int ret; + + /* static works are used, process one request at a time */ + mutex_lock(&stop_cpus_mutex); + ret = __stop_cpus(cpumask, fn, arg); + mutex_unlock(&stop_cpus_mutex); + return ret; +} + +/** + * try_stop_cpus - try to stop multiple cpus + * @cpumask: cpus to stop + * @fn: function to execute + * @arg: argument to @fn + * + * Identical to stop_cpus() except that it fails with -EAGAIN if + * someone else is already using the facility. + * + * CONTEXT: + * Might sleep. + * + * RETURNS: + * -EAGAIN if someone else is already stopping cpus, -ENOENT if + * @fn(@arg) was not executed at all because all cpus in @cpumask were + * offline; otherwise, 0 if all executions of @fn returned 0, any non + * zero return value if any returned non zero. + */ +int try_stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg) +{ + int ret; + + /* static works are used, process one request at a time */ + if (!mutex_trylock(&stop_cpus_mutex)) + return -EAGAIN; + ret = __stop_cpus(cpumask, fn, arg); + mutex_unlock(&stop_cpus_mutex); + return ret; +} + +static int cpu_stopper_thread(void *data) +{ + struct cpu_stopper *stopper = data; + struct cpu_stop_work *work; + int ret; + +repeat: + set_current_state(TASK_INTERRUPTIBLE); /* mb paired w/ kthread_stop */ + + if (kthread_should_stop()) { + __set_current_state(TASK_RUNNING); + return 0; + } + + work = NULL; + spin_lock_irq(&stopper->lock); + if (!list_empty(&stopper->works)) { + work = list_first_entry(&stopper->works, + struct cpu_stop_work, list); + list_del_init(&work->list); + } + spin_unlock_irq(&stopper->lock); + + if (work) { + cpu_stop_fn_t fn = work->fn; + void *arg = work->arg; + struct cpu_stop_done *done = work->done; + char ksym_buf[KSYM_NAME_LEN]; + + __set_current_state(TASK_RUNNING); + + /* cpu stop callbacks are not allowed to sleep */ + preempt_disable(); + + ret = fn(arg); + if (ret) + done->ret = ret; + + /* restore preemption and check it's still balanced */ + preempt_enable(); + WARN_ONCE(preempt_count(), + "cpu_stop: %s(%p) leaked preempt count\n", + kallsyms_lookup((unsigned long)fn, NULL, NULL, NULL, + ksym_buf), arg); + + cpu_stop_signal_done(done, true); + } else + schedule(); + + goto repeat; +} + +/* manage stopper for a cpu, mostly lifted from sched migration thread mgmt */ +static int __cpuinit cpu_stop_cpu_callback(struct notifier_block *nfb, + unsigned long action, void *hcpu) +{ + struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 }; + unsigned int cpu = (unsigned long)hcpu; + struct cpu_stopper *stopper = &per_cpu(cpu_stopper, cpu); + struct cpu_stop_work *work; + struct task_struct *p; + + switch (action & ~CPU_TASKS_FROZEN) { + case CPU_UP_PREPARE: + BUG_ON(stopper->thread || stopper->enabled || + !list_empty(&stopper->works)); + p = kthread_create(cpu_stopper_thread, stopper, "stopper/%d", + cpu); + if (IS_ERR(p)) + return NOTIFY_BAD; + sched_setscheduler_nocheck(p, SCHED_FIFO, ¶m); + get_task_struct(p); + stopper->thread = p; + break; + + case CPU_ONLINE: + kthread_bind(stopper->thread, cpu); + /* strictly unnecessary, as first user will wake it */ + wake_up_process(stopper->thread); + /* mark enabled */ + spin_lock_irq(&stopper->lock); + stopper->enabled = true; + spin_unlock_irq(&stopper->lock); + break; + +#ifdef CONFIG_HOTPLUG_CPU + case CPU_UP_CANCELED: + case CPU_DEAD: + /* kill the stopper */ + kthread_stop(stopper->thread); + /* drain remaining works */ + spin_lock_irq(&stopper->lock); + list_for_each_entry(work, &stopper->works, list) + cpu_stop_signal_done(work->done, false); + stopper->enabled = false; + spin_unlock_irq(&stopper->lock); + /* release the stopper */ + put_task_struct(stopper->thread); + stopper->thread = NULL; + break; +#endif + } + + return NOTIFY_OK; +} + +/* + * Give it a higher priority so that cpu stopper is available to other + * cpu notifiers. It currently shares the same priority as sched + * migration_notifier. + */ +static struct notifier_block __cpuinitdata cpu_stop_cpu_notifier = { + .notifier_call = cpu_stop_cpu_callback, + .priority = 10, +}; + +static int __init cpu_stop_init(void) +{ + void *bcpu = (void *)(long)smp_processor_id(); + unsigned int cpu; + int err; + + for_each_possible_cpu(cpu) { + struct cpu_stopper *stopper = &per_cpu(cpu_stopper, cpu); + + spin_lock_init(&stopper->lock); + INIT_LIST_HEAD(&stopper->works); + } + + /* start one for the boot cpu */ + err = cpu_stop_cpu_callback(&cpu_stop_cpu_notifier, CPU_UP_PREPARE, + bcpu); + BUG_ON(err == NOTIFY_BAD); + cpu_stop_cpu_callback(&cpu_stop_cpu_notifier, CPU_ONLINE, bcpu); + register_cpu_notifier(&cpu_stop_cpu_notifier); + + return 0; +} +early_initcall(cpu_stop_init); /* This controls the threads on each CPU. */ enum stopmachine_state { -- cgit v0.10.2 From 3fc1f1e27a5b807791d72e5d992aa33b668a6626 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 6 May 2010 18:49:20 +0200 Subject: stop_machine: reimplement using cpu_stop Reimplement stop_machine using cpu_stop. As cpu stoppers are guaranteed to be available for all online cpus, stop_machine_create/destroy() are no longer necessary and removed. With resource management and synchronization handled by cpu_stop, the new implementation is much simpler. Asking the cpu_stop to execute the stop_cpu() state machine on all online cpus with cpu hotplug disabled is enough. stop_machine itself doesn't need to manage any global resources anymore, so all per-instance information is rolled into struct stop_machine_data and the mutex and all static data variables are removed. The previous implementation created and destroyed RT workqueues as necessary which made stop_machine() calls highly expensive on very large machines. According to Dimitri Sivanich, preventing the dynamic creation/destruction makes booting faster more than twice on very large machines. cpu_stop resources are preallocated for all online cpus and should have the same effect. Signed-off-by: Tejun Heo Acked-by: Rusty Russell Acked-by: Peter Zijlstra Cc: Oleg Nesterov Cc: Dimitri Sivanich diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index fba6dec..03d9656 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -390,7 +390,6 @@ static void __init time_init_wq(void) if (time_sync_wq) return; time_sync_wq = create_singlethread_workqueue("timesync"); - stop_machine_create(); } /* diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index 2ac4440..8943b8c 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c @@ -80,12 +80,6 @@ static void do_suspend(void) shutting_down = SHUTDOWN_SUSPEND; - err = stop_machine_create(); - if (err) { - printk(KERN_ERR "xen suspend: failed to setup stop_machine %d\n", err); - goto out; - } - #ifdef CONFIG_PREEMPT /* If the kernel is preemptible, we need to freeze all the processes to prevent them from being in the middle of a pagetable update @@ -93,7 +87,7 @@ static void do_suspend(void) err = freeze_processes(); if (err) { printk(KERN_ERR "xen suspend: freeze failed %d\n", err); - goto out_destroy_sm; + goto out; } #endif @@ -136,12 +130,8 @@ out_resume: out_thaw: #ifdef CONFIG_PREEMPT thaw_processes(); - -out_destroy_sm: -#endif - stop_machine_destroy(); - out: +#endif shutting_down = SHUTDOWN_INVALID; } #endif /* CONFIG_PM_SLEEP */ diff --git a/include/linux/stop_machine.h b/include/linux/stop_machine.h index efcbd6c..0e552e7 100644 --- a/include/linux/stop_machine.h +++ b/include/linux/stop_machine.h @@ -67,23 +67,6 @@ int stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus); */ int __stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus); -/** - * stop_machine_create: create all stop_machine threads - * - * Description: This causes all stop_machine threads to be created before - * stop_machine actually gets called. This can be used by subsystems that - * need a non failing stop_machine infrastructure. - */ -int stop_machine_create(void); - -/** - * stop_machine_destroy: destroy all stop_machine threads - * - * Description: This causes all stop_machine threads which were created with - * stop_machine_create to be destroyed again. - */ -void stop_machine_destroy(void); - #else static inline int stop_machine(int (*fn)(void *), void *data, @@ -96,8 +79,5 @@ static inline int stop_machine(int (*fn)(void *), void *data, return ret; } -static inline int stop_machine_create(void) { return 0; } -static inline void stop_machine_destroy(void) { } - #endif /* CONFIG_SMP */ #endif /* _LINUX_STOP_MACHINE */ diff --git a/kernel/cpu.c b/kernel/cpu.c index 914aedc..5457775 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -266,9 +266,6 @@ int __ref cpu_down(unsigned int cpu) { int err; - err = stop_machine_create(); - if (err) - return err; cpu_maps_update_begin(); if (cpu_hotplug_disabled) { @@ -280,7 +277,6 @@ int __ref cpu_down(unsigned int cpu) out: cpu_maps_update_done(); - stop_machine_destroy(); return err; } EXPORT_SYMBOL(cpu_down); @@ -361,9 +357,6 @@ int disable_nonboot_cpus(void) { int cpu, first_cpu, error; - error = stop_machine_create(); - if (error) - return error; cpu_maps_update_begin(); first_cpu = cpumask_first(cpu_online_mask); /* @@ -394,7 +387,6 @@ int disable_nonboot_cpus(void) printk(KERN_ERR "Non-boot CPUs are not disabled\n"); } cpu_maps_update_done(); - stop_machine_destroy(); return error; } diff --git a/kernel/module.c b/kernel/module.c index 1016b75..0838246 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -723,16 +723,8 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user, return -EFAULT; name[MODULE_NAME_LEN-1] = '\0'; - /* Create stop_machine threads since free_module relies on - * a non-failing stop_machine call. */ - ret = stop_machine_create(); - if (ret) - return ret; - - if (mutex_lock_interruptible(&module_mutex) != 0) { - ret = -EINTR; - goto out_stop; - } + if (mutex_lock_interruptible(&module_mutex) != 0) + return -EINTR; mod = find_module(name); if (!mod) { @@ -792,8 +784,6 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user, out: mutex_unlock(&module_mutex); -out_stop: - stop_machine_destroy(); return ret; } diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c index 7e3f918..884c7a1 100644 --- a/kernel/stop_machine.c +++ b/kernel/stop_machine.c @@ -388,174 +388,92 @@ enum stopmachine_state { /* Exit */ STOPMACHINE_EXIT, }; -static enum stopmachine_state state; struct stop_machine_data { - int (*fn)(void *); - void *data; - int fnret; + int (*fn)(void *); + void *data; + /* Like num_online_cpus(), but hotplug cpu uses us, so we need this. */ + unsigned int num_threads; + const struct cpumask *active_cpus; + + enum stopmachine_state state; + atomic_t thread_ack; }; -/* Like num_online_cpus(), but hotplug cpu uses us, so we need this. */ -static unsigned int num_threads; -static atomic_t thread_ack; -static DEFINE_MUTEX(lock); -/* setup_lock protects refcount, stop_machine_wq and stop_machine_work. */ -static DEFINE_MUTEX(setup_lock); -/* Users of stop_machine. */ -static int refcount; -static struct workqueue_struct *stop_machine_wq; -static struct stop_machine_data active, idle; -static const struct cpumask *active_cpus; -static void __percpu *stop_machine_work; - -static void set_state(enum stopmachine_state newstate) +static void set_state(struct stop_machine_data *smdata, + enum stopmachine_state newstate) { /* Reset ack counter. */ - atomic_set(&thread_ack, num_threads); + atomic_set(&smdata->thread_ack, smdata->num_threads); smp_wmb(); - state = newstate; + smdata->state = newstate; } /* Last one to ack a state moves to the next state. */ -static void ack_state(void) +static void ack_state(struct stop_machine_data *smdata) { - if (atomic_dec_and_test(&thread_ack)) - set_state(state + 1); + if (atomic_dec_and_test(&smdata->thread_ack)) + set_state(smdata, smdata->state + 1); } -/* This is the actual function which stops the CPU. It runs - * in the context of a dedicated stopmachine workqueue. */ -static void stop_cpu(struct work_struct *unused) +/* This is the cpu_stop function which stops the CPU. */ +static int stop_machine_cpu_stop(void *data) { + struct stop_machine_data *smdata = data; enum stopmachine_state curstate = STOPMACHINE_NONE; - struct stop_machine_data *smdata = &idle; - int cpu = smp_processor_id(); - int err; + int cpu = smp_processor_id(), err = 0; + bool is_active; + + if (!smdata->active_cpus) + is_active = cpu == cpumask_first(cpu_online_mask); + else + is_active = cpumask_test_cpu(cpu, smdata->active_cpus); - if (!active_cpus) { - if (cpu == cpumask_first(cpu_online_mask)) - smdata = &active; - } else { - if (cpumask_test_cpu(cpu, active_cpus)) - smdata = &active; - } /* Simple state machine */ do { /* Chill out and ensure we re-read stopmachine_state. */ cpu_relax(); - if (state != curstate) { - curstate = state; + if (smdata->state != curstate) { + curstate = smdata->state; switch (curstate) { case STOPMACHINE_DISABLE_IRQ: local_irq_disable(); hard_irq_disable(); break; case STOPMACHINE_RUN: - /* On multiple CPUs only a single error code - * is needed to tell that something failed. */ - err = smdata->fn(smdata->data); - if (err) - smdata->fnret = err; + if (is_active) + err = smdata->fn(smdata->data); break; default: break; } - ack_state(); + ack_state(smdata); } } while (curstate != STOPMACHINE_EXIT); local_irq_enable(); + return err; } -/* Callback for CPUs which aren't supposed to do anything. */ -static int chill(void *unused) -{ - return 0; -} - -int stop_machine_create(void) -{ - mutex_lock(&setup_lock); - if (refcount) - goto done; - stop_machine_wq = create_rt_workqueue("kstop"); - if (!stop_machine_wq) - goto err_out; - stop_machine_work = alloc_percpu(struct work_struct); - if (!stop_machine_work) - goto err_out; -done: - refcount++; - mutex_unlock(&setup_lock); - return 0; - -err_out: - if (stop_machine_wq) - destroy_workqueue(stop_machine_wq); - mutex_unlock(&setup_lock); - return -ENOMEM; -} -EXPORT_SYMBOL_GPL(stop_machine_create); - -void stop_machine_destroy(void) -{ - mutex_lock(&setup_lock); - refcount--; - if (refcount) - goto done; - destroy_workqueue(stop_machine_wq); - free_percpu(stop_machine_work); -done: - mutex_unlock(&setup_lock); -} -EXPORT_SYMBOL_GPL(stop_machine_destroy); - int __stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus) { - struct work_struct *sm_work; - int i, ret; - - /* Set up initial state. */ - mutex_lock(&lock); - num_threads = num_online_cpus(); - active_cpus = cpus; - active.fn = fn; - active.data = data; - active.fnret = 0; - idle.fn = chill; - idle.data = NULL; - - set_state(STOPMACHINE_PREPARE); - - /* Schedule the stop_cpu work on all cpus: hold this CPU so one - * doesn't hit this CPU until we're ready. */ - get_cpu(); - for_each_online_cpu(i) { - sm_work = per_cpu_ptr(stop_machine_work, i); - INIT_WORK(sm_work, stop_cpu); - queue_work_on(i, stop_machine_wq, sm_work); - } - /* This will release the thread on our CPU. */ - put_cpu(); - flush_workqueue(stop_machine_wq); - ret = active.fnret; - mutex_unlock(&lock); - return ret; + struct stop_machine_data smdata = { .fn = fn, .data = data, + .num_threads = num_online_cpus(), + .active_cpus = cpus }; + + /* Set the initial state and stop all online cpus. */ + set_state(&smdata, STOPMACHINE_PREPARE); + return stop_cpus(cpu_online_mask, stop_machine_cpu_stop, &smdata); } int stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus) { int ret; - ret = stop_machine_create(); - if (ret) - return ret; /* No CPUs can come up or down during this. */ get_online_cpus(); ret = __stop_machine(fn, data, cpus); put_online_cpus(); - stop_machine_destroy(); return ret; } EXPORT_SYMBOL_GPL(stop_machine); -- cgit v0.10.2 From 969c79215a35b06e5e3efe69b9412f858df7856c Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 6 May 2010 18:49:21 +0200 Subject: sched: replace migration_thread with cpu_stop Currently migration_thread is serving three purposes - migration pusher, context to execute active_load_balance() and forced context switcher for expedited RCU synchronize_sched. All three roles are hardcoded into migration_thread() and determining which job is scheduled is slightly messy. This patch kills migration_thread and replaces all three uses with cpu_stop. The three different roles of migration_thread() are splitted into three separate cpu_stop callbacks - migration_cpu_stop(), active_load_balance_cpu_stop() and synchronize_sched_expedited_cpu_stop() - and each use case now simply asks cpu_stop to execute the callback as necessary. synchronize_sched_expedited() was implemented with private preallocated resources and custom multi-cpu queueing and waiting logic, both of which are provided by cpu_stop. synchronize_sched_expedited_count is made atomic and all other shared resources along with the mutex are dropped. synchronize_sched_expedited() also implemented a check to detect cases where not all the callback got executed on their assigned cpus and fall back to synchronize_sched(). If called with cpu hotplug blocked, cpu_stop already guarantees that and the condition cannot happen; otherwise, stop_machine() would break. However, this patch preserves the paranoid check using a cpumask to record on which cpus the stopper ran so that it can serve as a bisection point if something actually goes wrong theree. Because the internal execution state is no longer visible, rcu_expedited_torture_stats() is removed. This patch also renames cpu_stop threads to from "stopper/%d" to "migration/%d". The names of these threads ultimately don't matter and there's no reason to make unnecessary userland visible changes. With this patch applied, stop_machine() and sched now share the same resources. stop_machine() is faster without wasting any resources and sched migration users are much cleaner. Signed-off-by: Tejun Heo Acked-by: Peter Zijlstra Cc: Ingo Molnar Cc: Dipankar Sarma Cc: Josh Triplett Cc: Paul E. McKenney Cc: Oleg Nesterov Cc: Dimitri Sivanich diff --git a/Documentation/RCU/torture.txt b/Documentation/RCU/torture.txt index 0e50bc2..5d90167 100644 --- a/Documentation/RCU/torture.txt +++ b/Documentation/RCU/torture.txt @@ -182,16 +182,6 @@ Similarly, sched_expedited RCU provides the following: sched_expedited-torture: Reader Pipe: 12660320201 95875 0 0 0 0 0 0 0 0 0 sched_expedited-torture: Reader Batch: 12660424885 0 0 0 0 0 0 0 0 0 0 sched_expedited-torture: Free-Block Circulation: 1090795 1090795 1090794 1090793 1090792 1090791 1090790 1090789 1090788 1090787 0 - state: -1 / 0:0 3:0 4:0 - -As before, the first four lines are similar to those for RCU. -The last line shows the task-migration state. The first number is --1 if synchronize_sched_expedited() is idle, -2 if in the process of -posting wakeups to the migration kthreads, and N when waiting on CPU N. -Each of the colon-separated fields following the "/" is a CPU:state pair. -Valid states are "0" for idle, "1" for waiting for quiescent state, -"2" for passed through quiescent state, and "3" when a race with a -CPU-hotplug event forces use of the synchronize_sched() primitive. USAGE diff --git a/include/linux/rcutiny.h b/include/linux/rcutiny.h index a519587..0006b2d 100644 --- a/include/linux/rcutiny.h +++ b/include/linux/rcutiny.h @@ -60,8 +60,6 @@ static inline long rcu_batches_completed_bh(void) return 0; } -extern int rcu_expedited_torture_stats(char *page); - static inline void rcu_force_quiescent_state(void) { } diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h index 42cc3a0..24e467e 100644 --- a/include/linux/rcutree.h +++ b/include/linux/rcutree.h @@ -35,7 +35,6 @@ struct notifier_block; extern void rcu_sched_qs(int cpu); extern void rcu_bh_qs(int cpu); extern int rcu_needs_cpu(int cpu); -extern int rcu_expedited_torture_stats(char *page); #ifdef CONFIG_TREE_PREEMPT_RCU diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c index 58df55b..2b676f3 100644 --- a/kernel/rcutorture.c +++ b/kernel/rcutorture.c @@ -669,7 +669,7 @@ static struct rcu_torture_ops sched_expedited_ops = { .sync = synchronize_sched_expedited, .cb_barrier = NULL, .fqs = rcu_sched_force_quiescent_state, - .stats = rcu_expedited_torture_stats, + .stats = NULL, .irq_capable = 1, .name = "sched_expedited" }; diff --git a/kernel/sched.c b/kernel/sched.c index 4956ed0..f1d577a 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -55,9 +55,9 @@ #include #include #include -#include #include #include +#include #include #include #include @@ -539,15 +539,13 @@ struct rq { int post_schedule; int active_balance; int push_cpu; + struct cpu_stop_work active_balance_work; /* cpu of this runqueue: */ int cpu; int online; unsigned long avg_load_per_task; - struct task_struct *migration_thread; - struct list_head migration_queue; - u64 rt_avg; u64 age_stamp; u64 idle_stamp; @@ -2037,21 +2035,18 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu) __set_task_cpu(p, new_cpu); } -struct migration_req { - struct list_head list; - +struct migration_arg { struct task_struct *task; int dest_cpu; - - struct completion done; }; +static int migration_cpu_stop(void *data); + /* * The task's runqueue lock must be held. * Returns true if you have to wait for migration thread. */ -static int -migrate_task(struct task_struct *p, int dest_cpu, struct migration_req *req) +static bool migrate_task(struct task_struct *p, int dest_cpu) { struct rq *rq = task_rq(p); @@ -2059,15 +2054,7 @@ migrate_task(struct task_struct *p, int dest_cpu, struct migration_req *req) * If the task is not on a runqueue (and not running), then * the next wake-up will properly place the task. */ - if (!p->se.on_rq && !task_running(rq, p)) - return 0; - - init_completion(&req->done); - req->task = p; - req->dest_cpu = dest_cpu; - list_add(&req->list, &rq->migration_queue); - - return 1; + return p->se.on_rq || task_running(rq, p); } /* @@ -3110,7 +3097,6 @@ static void update_cpu_load(struct rq *this_rq) void sched_exec(void) { struct task_struct *p = current; - struct migration_req req; unsigned long flags; struct rq *rq; int dest_cpu; @@ -3124,17 +3110,11 @@ void sched_exec(void) * select_task_rq() can race against ->cpus_allowed */ if (cpumask_test_cpu(dest_cpu, &p->cpus_allowed) && - likely(cpu_active(dest_cpu)) && - migrate_task(p, dest_cpu, &req)) { - /* Need to wait for migration thread (might exit: take ref). */ - struct task_struct *mt = rq->migration_thread; + likely(cpu_active(dest_cpu)) && migrate_task(p, dest_cpu)) { + struct migration_arg arg = { p, dest_cpu }; - get_task_struct(mt); task_rq_unlock(rq, &flags); - wake_up_process(mt); - put_task_struct(mt); - wait_for_completion(&req.done); - + stop_one_cpu(cpu_of(rq), migration_cpu_stop, &arg); return; } unlock: @@ -5290,17 +5270,15 @@ static inline void sched_init_granularity(void) /* * This is how migration works: * - * 1) we queue a struct migration_req structure in the source CPU's - * runqueue and wake up that CPU's migration thread. - * 2) we down() the locked semaphore => thread blocks. - * 3) migration thread wakes up (implicitly it forces the migrated - * thread off the CPU) - * 4) it gets the migration request and checks whether the migrated - * task is still in the wrong runqueue. - * 5) if it's in the wrong runqueue then the migration thread removes + * 1) we invoke migration_cpu_stop() on the target CPU using + * stop_one_cpu(). + * 2) stopper starts to run (implicitly forcing the migrated thread + * off the CPU) + * 3) it checks whether the migrated task is still in the wrong runqueue. + * 4) if it's in the wrong runqueue then the migration thread removes * it and puts it into the right queue. - * 6) migration thread up()s the semaphore. - * 7) we wake up and the migration is done. + * 5) stopper completes and stop_one_cpu() returns and the migration + * is done. */ /* @@ -5314,9 +5292,9 @@ static inline void sched_init_granularity(void) */ int set_cpus_allowed_ptr(struct task_struct *p, const struct cpumask *new_mask) { - struct migration_req req; unsigned long flags; struct rq *rq; + unsigned int dest_cpu; int ret = 0; /* @@ -5354,15 +5332,12 @@ again: if (cpumask_test_cpu(task_cpu(p), new_mask)) goto out; - if (migrate_task(p, cpumask_any_and(cpu_active_mask, new_mask), &req)) { + dest_cpu = cpumask_any_and(cpu_active_mask, new_mask); + if (migrate_task(p, dest_cpu)) { + struct migration_arg arg = { p, dest_cpu }; /* Need help from migration thread: drop lock and wait. */ - struct task_struct *mt = rq->migration_thread; - - get_task_struct(mt); task_rq_unlock(rq, &flags); - wake_up_process(mt); - put_task_struct(mt); - wait_for_completion(&req.done); + stop_one_cpu(cpu_of(rq), migration_cpu_stop, &arg); tlb_migrate_finish(p->mm); return 0; } @@ -5420,70 +5395,22 @@ fail: return ret; } -#define RCU_MIGRATION_IDLE 0 -#define RCU_MIGRATION_NEED_QS 1 -#define RCU_MIGRATION_GOT_QS 2 -#define RCU_MIGRATION_MUST_SYNC 3 - /* - * migration_thread - this is a highprio system thread that performs - * thread migration by bumping thread off CPU then 'pushing' onto - * another runqueue. + * migration_cpu_stop - this will be executed by a highprio stopper thread + * and performs thread migration by bumping thread off CPU then + * 'pushing' onto another runqueue. */ -static int migration_thread(void *data) +static int migration_cpu_stop(void *data) { - int badcpu; - int cpu = (long)data; - struct rq *rq; - - rq = cpu_rq(cpu); - BUG_ON(rq->migration_thread != current); - - set_current_state(TASK_INTERRUPTIBLE); - while (!kthread_should_stop()) { - struct migration_req *req; - struct list_head *head; - - raw_spin_lock_irq(&rq->lock); - - if (cpu_is_offline(cpu)) { - raw_spin_unlock_irq(&rq->lock); - break; - } - - if (rq->active_balance) { - active_load_balance(rq, cpu); - rq->active_balance = 0; - } - - head = &rq->migration_queue; - - if (list_empty(head)) { - raw_spin_unlock_irq(&rq->lock); - schedule(); - set_current_state(TASK_INTERRUPTIBLE); - continue; - } - req = list_entry(head->next, struct migration_req, list); - list_del_init(head->next); - - if (req->task != NULL) { - raw_spin_unlock(&rq->lock); - __migrate_task(req->task, cpu, req->dest_cpu); - } else if (likely(cpu == (badcpu = smp_processor_id()))) { - req->dest_cpu = RCU_MIGRATION_GOT_QS; - raw_spin_unlock(&rq->lock); - } else { - req->dest_cpu = RCU_MIGRATION_MUST_SYNC; - raw_spin_unlock(&rq->lock); - WARN_ONCE(1, "migration_thread() on CPU %d, expected %d\n", badcpu, cpu); - } - local_irq_enable(); - - complete(&req->done); - } - __set_current_state(TASK_RUNNING); + struct migration_arg *arg = data; + /* + * The original target cpu might have gone down and we might + * be on another cpu but it doesn't matter. + */ + local_irq_disable(); + __migrate_task(arg->task, raw_smp_processor_id(), arg->dest_cpu); + local_irq_enable(); return 0; } @@ -5850,35 +5777,20 @@ static void set_rq_offline(struct rq *rq) static int __cpuinit migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu) { - struct task_struct *p; int cpu = (long)hcpu; unsigned long flags; - struct rq *rq; + struct rq *rq = cpu_rq(cpu); switch (action) { case CPU_UP_PREPARE: case CPU_UP_PREPARE_FROZEN: - p = kthread_create(migration_thread, hcpu, "migration/%d", cpu); - if (IS_ERR(p)) - return NOTIFY_BAD; - kthread_bind(p, cpu); - /* Must be high prio: stop_machine expects to yield to it. */ - rq = task_rq_lock(p, &flags); - __setscheduler(rq, p, SCHED_FIFO, MAX_RT_PRIO-1); - task_rq_unlock(rq, &flags); - get_task_struct(p); - cpu_rq(cpu)->migration_thread = p; rq->calc_load_update = calc_load_update; break; case CPU_ONLINE: case CPU_ONLINE_FROZEN: - /* Strictly unnecessary, as first user will wake it. */ - wake_up_process(cpu_rq(cpu)->migration_thread); - /* Update our root-domain */ - rq = cpu_rq(cpu); raw_spin_lock_irqsave(&rq->lock, flags); if (rq->rd) { BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span)); @@ -5889,25 +5801,9 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu) break; #ifdef CONFIG_HOTPLUG_CPU - case CPU_UP_CANCELED: - case CPU_UP_CANCELED_FROZEN: - if (!cpu_rq(cpu)->migration_thread) - break; - /* Unbind it from offline cpu so it can run. Fall thru. */ - kthread_bind(cpu_rq(cpu)->migration_thread, - cpumask_any(cpu_online_mask)); - kthread_stop(cpu_rq(cpu)->migration_thread); - put_task_struct(cpu_rq(cpu)->migration_thread); - cpu_rq(cpu)->migration_thread = NULL; - break; - case CPU_DEAD: case CPU_DEAD_FROZEN: migrate_live_tasks(cpu); - rq = cpu_rq(cpu); - kthread_stop(rq->migration_thread); - put_task_struct(rq->migration_thread); - rq->migration_thread = NULL; /* Idle task back to normal (off runqueue, low prio) */ raw_spin_lock_irq(&rq->lock); deactivate_task(rq, rq->idle, 0); @@ -5918,29 +5814,11 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu) migrate_nr_uninterruptible(rq); BUG_ON(rq->nr_running != 0); calc_global_load_remove(rq); - /* - * No need to migrate the tasks: it was best-effort if - * they didn't take sched_hotcpu_mutex. Just wake up - * the requestors. - */ - raw_spin_lock_irq(&rq->lock); - while (!list_empty(&rq->migration_queue)) { - struct migration_req *req; - - req = list_entry(rq->migration_queue.next, - struct migration_req, list); - list_del_init(&req->list); - raw_spin_unlock_irq(&rq->lock); - complete(&req->done); - raw_spin_lock_irq(&rq->lock); - } - raw_spin_unlock_irq(&rq->lock); break; case CPU_DYING: case CPU_DYING_FROZEN: /* Update our root-domain */ - rq = cpu_rq(cpu); raw_spin_lock_irqsave(&rq->lock, flags); if (rq->rd) { BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span)); @@ -7757,10 +7635,8 @@ void __init sched_init(void) rq->push_cpu = 0; rq->cpu = i; rq->online = 0; - rq->migration_thread = NULL; rq->idle_stamp = 0; rq->avg_idle = 2*sysctl_sched_migration_cost; - INIT_LIST_HEAD(&rq->migration_queue); rq_attach_root(rq, &def_root_domain); #endif init_rq_hrtick(rq); @@ -9054,43 +8930,39 @@ struct cgroup_subsys cpuacct_subsys = { #ifndef CONFIG_SMP -int rcu_expedited_torture_stats(char *page) -{ - return 0; -} -EXPORT_SYMBOL_GPL(rcu_expedited_torture_stats); - void synchronize_sched_expedited(void) { + /* + * There must be a full memory barrier on each affected CPU + * between the time that try_stop_cpus() is called and the + * time that it returns. + * + * In the current initial implementation of cpu_stop, the + * above condition is already met when the control reaches + * this point and the following smp_mb() is not strictly + * necessary. Do smp_mb() anyway for documentation and + * robustness against future implementation changes. + */ + smp_mb(); } EXPORT_SYMBOL_GPL(synchronize_sched_expedited); #else /* #ifndef CONFIG_SMP */ -static DEFINE_PER_CPU(struct migration_req, rcu_migration_req); -static DEFINE_MUTEX(rcu_sched_expedited_mutex); - -#define RCU_EXPEDITED_STATE_POST -2 -#define RCU_EXPEDITED_STATE_IDLE -1 +static atomic_t synchronize_sched_expedited_count = ATOMIC_INIT(0); -static int rcu_expedited_state = RCU_EXPEDITED_STATE_IDLE; - -int rcu_expedited_torture_stats(char *page) +static int synchronize_sched_expedited_cpu_stop(void *data) { - int cnt = 0; - int cpu; + static DEFINE_SPINLOCK(done_mask_lock); + struct cpumask *done_mask = data; - cnt += sprintf(&page[cnt], "state: %d /", rcu_expedited_state); - for_each_online_cpu(cpu) { - cnt += sprintf(&page[cnt], " %d:%d", - cpu, per_cpu(rcu_migration_req, cpu).dest_cpu); + if (done_mask) { + spin_lock(&done_mask_lock); + cpumask_set_cpu(smp_processor_id(), done_mask); + spin_unlock(&done_mask_lock); } - cnt += sprintf(&page[cnt], "\n"); - return cnt; + return 0; } -EXPORT_SYMBOL_GPL(rcu_expedited_torture_stats); - -static long synchronize_sched_expedited_count; /* * Wait for an rcu-sched grace period to elapse, but use "big hammer" @@ -9104,60 +8976,55 @@ static long synchronize_sched_expedited_count; */ void synchronize_sched_expedited(void) { - int cpu; - unsigned long flags; - bool need_full_sync = 0; - struct rq *rq; - struct migration_req *req; - long snap; - int trycount = 0; + cpumask_var_t done_mask_var; + struct cpumask *done_mask = NULL; + int snap, trycount = 0; + + /* + * done_mask is used to check that all cpus actually have + * finished running the stopper, which is guaranteed by + * stop_cpus() if it's called with cpu hotplug blocked. Keep + * the paranoia for now but it's best effort if cpumask is off + * stack. + */ + if (zalloc_cpumask_var(&done_mask_var, GFP_ATOMIC)) + done_mask = done_mask_var; smp_mb(); /* ensure prior mod happens before capturing snap. */ - snap = ACCESS_ONCE(synchronize_sched_expedited_count) + 1; + snap = atomic_read(&synchronize_sched_expedited_count) + 1; get_online_cpus(); - while (!mutex_trylock(&rcu_sched_expedited_mutex)) { + while (try_stop_cpus(cpu_online_mask, + synchronize_sched_expedited_cpu_stop, + done_mask) == -EAGAIN) { put_online_cpus(); if (trycount++ < 10) udelay(trycount * num_online_cpus()); else { synchronize_sched(); - return; + goto free_out; } - if (ACCESS_ONCE(synchronize_sched_expedited_count) - snap > 0) { + if (atomic_read(&synchronize_sched_expedited_count) - snap > 0) { smp_mb(); /* ensure test happens before caller kfree */ - return; + goto free_out; } get_online_cpus(); } - rcu_expedited_state = RCU_EXPEDITED_STATE_POST; - for_each_online_cpu(cpu) { - rq = cpu_rq(cpu); - req = &per_cpu(rcu_migration_req, cpu); - init_completion(&req->done); - req->task = NULL; - req->dest_cpu = RCU_MIGRATION_NEED_QS; - raw_spin_lock_irqsave(&rq->lock, flags); - list_add(&req->list, &rq->migration_queue); - raw_spin_unlock_irqrestore(&rq->lock, flags); - wake_up_process(rq->migration_thread); - } - for_each_online_cpu(cpu) { - rcu_expedited_state = cpu; - req = &per_cpu(rcu_migration_req, cpu); - rq = cpu_rq(cpu); - wait_for_completion(&req->done); - raw_spin_lock_irqsave(&rq->lock, flags); - if (unlikely(req->dest_cpu == RCU_MIGRATION_MUST_SYNC)) - need_full_sync = 1; - req->dest_cpu = RCU_MIGRATION_IDLE; - raw_spin_unlock_irqrestore(&rq->lock, flags); - } - rcu_expedited_state = RCU_EXPEDITED_STATE_IDLE; - synchronize_sched_expedited_count++; - mutex_unlock(&rcu_sched_expedited_mutex); + atomic_inc(&synchronize_sched_expedited_count); + if (done_mask) + cpumask_xor(done_mask, done_mask, cpu_online_mask); put_online_cpus(); - if (need_full_sync) + + /* paranoia - this can't happen */ + if (done_mask && cpumask_weight(done_mask)) { + char buf[80]; + + cpulist_scnprintf(buf, sizeof(buf), done_mask); + WARN_ONCE(1, "synchronize_sched_expedited: cpu online and done masks disagree on %d cpus: %s\n", + cpumask_weight(done_mask), buf); synchronize_sched(); + } +free_out: + free_cpumask_var(done_mask_var); } EXPORT_SYMBOL_GPL(synchronize_sched_expedited); diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index cbd8b8a..217e4a9 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -2798,6 +2798,8 @@ static int need_active_balance(struct sched_domain *sd, int sd_idle, int idle) return unlikely(sd->nr_balance_failed > sd->cache_nice_tries+2); } +static int active_load_balance_cpu_stop(void *data); + /* * Check this_cpu to ensure it is balanced within domain. Attempt to move * tasks if there is an imbalance. @@ -2887,8 +2889,9 @@ redo: if (need_active_balance(sd, sd_idle, idle)) { raw_spin_lock_irqsave(&busiest->lock, flags); - /* don't kick the migration_thread, if the curr - * task on busiest cpu can't be moved to this_cpu + /* don't kick the active_load_balance_cpu_stop, + * if the curr task on busiest cpu can't be + * moved to this_cpu */ if (!cpumask_test_cpu(this_cpu, &busiest->curr->cpus_allowed)) { @@ -2898,14 +2901,22 @@ redo: goto out_one_pinned; } + /* + * ->active_balance synchronizes accesses to + * ->active_balance_work. Once set, it's cleared + * only after active load balance is finished. + */ if (!busiest->active_balance) { busiest->active_balance = 1; busiest->push_cpu = this_cpu; active_balance = 1; } raw_spin_unlock_irqrestore(&busiest->lock, flags); + if (active_balance) - wake_up_process(busiest->migration_thread); + stop_one_cpu_nowait(cpu_of(busiest), + active_load_balance_cpu_stop, busiest, + &busiest->active_balance_work); /* * We've kicked active balancing, reset the failure @@ -3012,24 +3023,29 @@ static void idle_balance(int this_cpu, struct rq *this_rq) } /* - * active_load_balance is run by migration threads. It pushes running tasks - * off the busiest CPU onto idle CPUs. It requires at least 1 task to be - * running on each physical CPU where possible, and avoids physical / - * logical imbalances. - * - * Called with busiest_rq locked. + * active_load_balance_cpu_stop is run by cpu stopper. It pushes + * running tasks off the busiest CPU onto idle CPUs. It requires at + * least 1 task to be running on each physical CPU where possible, and + * avoids physical / logical imbalances. */ -static void active_load_balance(struct rq *busiest_rq, int busiest_cpu) +static int active_load_balance_cpu_stop(void *data) { + struct rq *busiest_rq = data; + int busiest_cpu = cpu_of(busiest_rq); int target_cpu = busiest_rq->push_cpu; + struct rq *target_rq = cpu_rq(target_cpu); struct sched_domain *sd; - struct rq *target_rq; + + raw_spin_lock_irq(&busiest_rq->lock); + + /* make sure the requested cpu hasn't gone down in the meantime */ + if (unlikely(busiest_cpu != smp_processor_id() || + !busiest_rq->active_balance)) + goto out_unlock; /* Is there any task to move? */ if (busiest_rq->nr_running <= 1) - return; - - target_rq = cpu_rq(target_cpu); + goto out_unlock; /* * This condition is "impossible", if it occurs @@ -3058,6 +3074,10 @@ static void active_load_balance(struct rq *busiest_rq, int busiest_cpu) schedstat_inc(sd, alb_failed); } double_unlock_balance(busiest_rq, target_rq); +out_unlock: + busiest_rq->active_balance = 0; + raw_spin_unlock_irq(&busiest_rq->lock); + return 0; } #ifdef CONFIG_NO_HZ diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c index 884c7a1..5b20141 100644 --- a/kernel/stop_machine.c +++ b/kernel/stop_machine.c @@ -301,7 +301,7 @@ static int __cpuinit cpu_stop_cpu_callback(struct notifier_block *nfb, case CPU_UP_PREPARE: BUG_ON(stopper->thread || stopper->enabled || !list_empty(&stopper->works)); - p = kthread_create(cpu_stopper_thread, stopper, "stopper/%d", + p = kthread_create(cpu_stopper_thread, stopper, "migration/%d", cpu); if (IS_ERR(p)) return NOTIFY_BAD; -- cgit v0.10.2 From 94458d5ecb3da844823cc191e73e5c5ead98a464 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 6 May 2010 18:49:21 +0200 Subject: sched: kill paranoia check in synchronize_sched_expedited() The paranoid check which verifies that the cpu_stop callback is actually called on all online cpus is completely superflous. It's guaranteed by cpu_stop facility and if it didn't work as advertised other things would go horribly wrong and trying to recover using synchronize_sched() wouldn't be very meaningful. Kill the paranoid check. Removal of this feature is done as a separate step so that it can serve as a bisection point if something actually goes wrong. Signed-off-by: Tejun Heo Acked-by: Peter Zijlstra Cc: Ingo Molnar Cc: Dipankar Sarma Cc: Josh Triplett Cc: Paul E. McKenney Cc: Oleg Nesterov Cc: Dimitri Sivanich diff --git a/kernel/sched.c b/kernel/sched.c index f1d577a..e9c6d79 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -8953,14 +8953,6 @@ static atomic_t synchronize_sched_expedited_count = ATOMIC_INIT(0); static int synchronize_sched_expedited_cpu_stop(void *data) { - static DEFINE_SPINLOCK(done_mask_lock); - struct cpumask *done_mask = data; - - if (done_mask) { - spin_lock(&done_mask_lock); - cpumask_set_cpu(smp_processor_id(), done_mask); - spin_unlock(&done_mask_lock); - } return 0; } @@ -8976,55 +8968,29 @@ static int synchronize_sched_expedited_cpu_stop(void *data) */ void synchronize_sched_expedited(void) { - cpumask_var_t done_mask_var; - struct cpumask *done_mask = NULL; int snap, trycount = 0; - /* - * done_mask is used to check that all cpus actually have - * finished running the stopper, which is guaranteed by - * stop_cpus() if it's called with cpu hotplug blocked. Keep - * the paranoia for now but it's best effort if cpumask is off - * stack. - */ - if (zalloc_cpumask_var(&done_mask_var, GFP_ATOMIC)) - done_mask = done_mask_var; - smp_mb(); /* ensure prior mod happens before capturing snap. */ snap = atomic_read(&synchronize_sched_expedited_count) + 1; get_online_cpus(); while (try_stop_cpus(cpu_online_mask, synchronize_sched_expedited_cpu_stop, - done_mask) == -EAGAIN) { + NULL) == -EAGAIN) { put_online_cpus(); if (trycount++ < 10) udelay(trycount * num_online_cpus()); else { synchronize_sched(); - goto free_out; + return; } if (atomic_read(&synchronize_sched_expedited_count) - snap > 0) { smp_mb(); /* ensure test happens before caller kfree */ - goto free_out; + return; } get_online_cpus(); } atomic_inc(&synchronize_sched_expedited_count); - if (done_mask) - cpumask_xor(done_mask, done_mask, cpu_online_mask); put_online_cpus(); - - /* paranoia - this can't happen */ - if (done_mask && cpumask_weight(done_mask)) { - char buf[80]; - - cpulist_scnprintf(buf, sizeof(buf), done_mask); - WARN_ONCE(1, "synchronize_sched_expedited: cpu online and done masks disagree on %d cpus: %s\n", - cpumask_weight(done_mask), buf); - synchronize_sched(); - } -free_out: - free_cpumask_var(done_mask_var); } EXPORT_SYMBOL_GPL(synchronize_sched_expedited); -- cgit v0.10.2 From cc631fb732b8ccd6a0cc45557475ea09b0c21a68 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Thu, 6 May 2010 18:49:21 +0200 Subject: sched: correctly place paranioa memory barriers in synchronize_sched_expedited() The memory barriers must be in the SMP case, not in the !SMP case. Also add a barrier after the atomic_inc() in order to ensure that other CPUs see post-synchronize_sched_expedited() actions as following the expedited grace period. Signed-off-by: Paul E. McKenney Signed-off-by: Tejun Heo diff --git a/kernel/sched.c b/kernel/sched.c index e9c6d79..155a16d 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -8932,6 +8932,15 @@ struct cgroup_subsys cpuacct_subsys = { void synchronize_sched_expedited(void) { +} +EXPORT_SYMBOL_GPL(synchronize_sched_expedited); + +#else /* #ifndef CONFIG_SMP */ + +static atomic_t synchronize_sched_expedited_count = ATOMIC_INIT(0); + +static int synchronize_sched_expedited_cpu_stop(void *data) +{ /* * There must be a full memory barrier on each affected CPU * between the time that try_stop_cpus() is called and the @@ -8943,16 +8952,7 @@ void synchronize_sched_expedited(void) * necessary. Do smp_mb() anyway for documentation and * robustness against future implementation changes. */ - smp_mb(); -} -EXPORT_SYMBOL_GPL(synchronize_sched_expedited); - -#else /* #ifndef CONFIG_SMP */ - -static atomic_t synchronize_sched_expedited_count = ATOMIC_INIT(0); - -static int synchronize_sched_expedited_cpu_stop(void *data) -{ + smp_mb(); /* See above comment block. */ return 0; } @@ -8990,6 +8990,7 @@ void synchronize_sched_expedited(void) get_online_cpus(); } atomic_inc(&synchronize_sched_expedited_count); + smp_mb__after_atomic_inc(); /* ensure post-GP actions seen after GP. */ put_online_cpus(); } EXPORT_SYMBOL_GPL(synchronize_sched_expedited); -- cgit v0.10.2 From 6b07aaedc029d507501a931aabfd3d0a70f1828f Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Thu, 6 May 2010 10:40:47 +0100 Subject: ARM: 6099/1: nomadik-gpio: fix mask/unmask Mask/unmask should modify the interrupt mask register (RIMSC and FIMSC) not the wakeup mask registers (RWIMSC and FWIMSC). Acked-by: Alessandro Rubini Acked-by: Linus Walleij Signed-off-by: Rabin Vincent Signed-off-by: Russell King diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c index 092f380..38fc3b5 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c @@ -123,14 +123,14 @@ static void nmk_gpio_irq_mask(unsigned int irq) /* we must individually clear the two edges */ spin_lock_irqsave(&nmk_chip->lock, flags); if (nmk_chip->edge_rising & bitmask) { - reg = readl(nmk_chip->addr + NMK_GPIO_RWIMSC); + reg = readl(nmk_chip->addr + NMK_GPIO_RIMSC); reg &= ~bitmask; - writel(reg, nmk_chip->addr + NMK_GPIO_RWIMSC); + writel(reg, nmk_chip->addr + NMK_GPIO_RIMSC); } if (nmk_chip->edge_falling & bitmask) { - reg = readl(nmk_chip->addr + NMK_GPIO_FWIMSC); + reg = readl(nmk_chip->addr + NMK_GPIO_FIMSC); reg &= ~bitmask; - writel(reg, nmk_chip->addr + NMK_GPIO_FWIMSC); + writel(reg, nmk_chip->addr + NMK_GPIO_FIMSC); } spin_unlock_irqrestore(&nmk_chip->lock, flags); }; @@ -151,14 +151,14 @@ static void nmk_gpio_irq_unmask(unsigned int irq) /* we must individually set the two edges */ spin_lock_irqsave(&nmk_chip->lock, flags); if (nmk_chip->edge_rising & bitmask) { - reg = readl(nmk_chip->addr + NMK_GPIO_RWIMSC); + reg = readl(nmk_chip->addr + NMK_GPIO_RIMSC); reg |= bitmask; - writel(reg, nmk_chip->addr + NMK_GPIO_RWIMSC); + writel(reg, nmk_chip->addr + NMK_GPIO_RIMSC); } if (nmk_chip->edge_falling & bitmask) { - reg = readl(nmk_chip->addr + NMK_GPIO_FWIMSC); + reg = readl(nmk_chip->addr + NMK_GPIO_FIMSC); reg |= bitmask; - writel(reg, nmk_chip->addr + NMK_GPIO_FWIMSC); + writel(reg, nmk_chip->addr + NMK_GPIO_FIMSC); } spin_unlock_irqrestore(&nmk_chip->lock, flags); } -- cgit v0.10.2 From 040e5ecddaa72f1f982b83cb205509bc9ce7f91e Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Thu, 6 May 2010 10:42:42 +0100 Subject: ARM: 6100/1: nomadik-gpio: factor out helper to enable/disable irqs Remove some nearly-duplicated code to make the following patch simpler. Acked-by: Alessandro Rubini Acked-by: Linus Walleij Signed-off-by: Rabin Vincent Signed-off-by: Russell King diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c index 38fc3b5..a8ac545 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c @@ -107,40 +107,37 @@ static void nmk_gpio_irq_ack(unsigned int irq) writel(nmk_gpio_get_bitmask(gpio), nmk_chip->addr + NMK_GPIO_IC); } -static void nmk_gpio_irq_mask(unsigned int irq) +static void __nmk_gpio_irq_modify(struct nmk_gpio_chip *nmk_chip, + int gpio, bool enable) { - int gpio; - struct nmk_gpio_chip *nmk_chip; - unsigned long flags; - u32 bitmask, reg; - - gpio = NOMADIK_IRQ_TO_GPIO(irq); - nmk_chip = get_irq_chip_data(irq); - bitmask = nmk_gpio_get_bitmask(gpio); - if (!nmk_chip) - return; + u32 bitmask = nmk_gpio_get_bitmask(gpio); + u32 reg; - /* we must individually clear the two edges */ - spin_lock_irqsave(&nmk_chip->lock, flags); + /* we must individually set/clear the two edges */ if (nmk_chip->edge_rising & bitmask) { reg = readl(nmk_chip->addr + NMK_GPIO_RIMSC); - reg &= ~bitmask; + if (enable) + reg |= bitmask; + else + reg &= ~bitmask; writel(reg, nmk_chip->addr + NMK_GPIO_RIMSC); } if (nmk_chip->edge_falling & bitmask) { reg = readl(nmk_chip->addr + NMK_GPIO_FIMSC); - reg &= ~bitmask; + if (enable) + reg |= bitmask; + else + reg &= ~bitmask; writel(reg, nmk_chip->addr + NMK_GPIO_FIMSC); } - spin_unlock_irqrestore(&nmk_chip->lock, flags); -}; +} -static void nmk_gpio_irq_unmask(unsigned int irq) +static void nmk_gpio_irq_modify(unsigned int irq, bool enable) { int gpio; struct nmk_gpio_chip *nmk_chip; unsigned long flags; - u32 bitmask, reg; + u32 bitmask; gpio = NOMADIK_IRQ_TO_GPIO(irq); nmk_chip = get_irq_chip_data(irq); @@ -148,21 +145,21 @@ static void nmk_gpio_irq_unmask(unsigned int irq) if (!nmk_chip) return; - /* we must individually set the two edges */ spin_lock_irqsave(&nmk_chip->lock, flags); - if (nmk_chip->edge_rising & bitmask) { - reg = readl(nmk_chip->addr + NMK_GPIO_RIMSC); - reg |= bitmask; - writel(reg, nmk_chip->addr + NMK_GPIO_RIMSC); - } - if (nmk_chip->edge_falling & bitmask) { - reg = readl(nmk_chip->addr + NMK_GPIO_FIMSC); - reg |= bitmask; - writel(reg, nmk_chip->addr + NMK_GPIO_FIMSC); - } + __nmk_gpio_irq_modify(nmk_chip, gpio, enable); spin_unlock_irqrestore(&nmk_chip->lock, flags); } +static void nmk_gpio_irq_mask(unsigned int irq) +{ + nmk_gpio_irq_modify(irq, false); +}; + +static void nmk_gpio_irq_unmask(unsigned int irq) +{ + nmk_gpio_irq_modify(irq, true); +} + static int nmk_gpio_irq_set_type(unsigned int irq, unsigned int type) { int gpio; -- cgit v0.10.2 From 7a852d8060e1bb3a5e621caaebea86c43cf4a62d Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Thu, 6 May 2010 10:43:55 +0100 Subject: ARM: 6101/1: nomadik-gpio: don't enable in set_type On this peripheral, setting the trigger type enables the interrupt, and the current set_type() implementation unconditionally enables the interrupt, even if it is called when the interrupt is disabled. Fix set_type() to: - if the interrupt is disabled, defer the actual trigger setting to when it is unmasked - if the interrupt is enabled, change the type immediately by clearing the old type and then re-enabling with the new type. Acked-by: Alessandro Rubini Acked-by: Linus Walleij Signed-off-by: Rabin Vincent Signed-off-by: Russell King diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c index a8ac545..b877d76 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c @@ -162,6 +162,7 @@ static void nmk_gpio_irq_unmask(unsigned int irq) static int nmk_gpio_irq_set_type(unsigned int irq, unsigned int type) { + bool enabled = !(irq_to_desc(irq)->status & IRQ_DISABLED); int gpio; struct nmk_gpio_chip *nmk_chip; unsigned long flags; @@ -180,19 +181,21 @@ static int nmk_gpio_irq_set_type(unsigned int irq, unsigned int type) spin_lock_irqsave(&nmk_chip->lock, flags); + if (enabled) + __nmk_gpio_irq_modify(nmk_chip, gpio, false); + nmk_chip->edge_rising &= ~bitmask; if (type & IRQ_TYPE_EDGE_RISING) nmk_chip->edge_rising |= bitmask; - writel(nmk_chip->edge_rising, nmk_chip->addr + NMK_GPIO_RIMSC); nmk_chip->edge_falling &= ~bitmask; if (type & IRQ_TYPE_EDGE_FALLING) nmk_chip->edge_falling |= bitmask; - writel(nmk_chip->edge_falling, nmk_chip->addr + NMK_GPIO_FIMSC); - spin_unlock_irqrestore(&nmk_chip->lock, flags); + if (enabled) + __nmk_gpio_irq_modify(nmk_chip, gpio, true); - nmk_gpio_irq_unmask(irq); + spin_unlock_irqrestore(&nmk_chip->lock, flags); return 0; } -- cgit v0.10.2 From 2210d6453b4d888c122b2b1c236f50b0a2d30bfa Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Thu, 6 May 2010 10:45:18 +0100 Subject: ARM: 6102/1: nomadik-gpio: set a default trigger for interrupts Set a default trigger type for interrupts, otherwise if request_irq is called without specifiying a trigger type, the interrupt will not actually be enabled. Acked-by: Alessandro Rubini Acked-by: Linus Walleij Signed-off-by: Rabin Vincent Signed-off-by: Russell King diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c index b877d76..eac9c9a 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c @@ -245,6 +245,7 @@ static int nmk_gpio_init_irq(struct nmk_gpio_chip *nmk_chip) set_irq_handler(i, handle_edge_irq); set_irq_flags(i, IRQF_VALID); set_irq_chip_data(i, nmk_chip); + set_irq_type(i, IRQ_TYPE_EDGE_FALLING); } set_irq_chained_handler(nmk_chip->parent_irq, nmk_gpio_irq_handler); set_irq_data(nmk_chip->parent_irq, nmk_chip); -- cgit v0.10.2 From dc6048c7f97beaf8c5bb97ed772f43330d04727a Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Thu, 6 May 2010 10:47:25 +0100 Subject: ARM: 6103/1: nomadik: define clocks statically Add a table for clocks to be defined statically, so that new clocks can be added without having to call nmdk_clk_create() for each of them. Remove the now unused nmdk_clk_create() function. Acked-by: Alessandro Rubini Acked-by: Linus Walleij Signed-off-by: Rabin Vincent Signed-off-by: Russell King diff --git a/arch/arm/mach-nomadik/board-nhk8815.c b/arch/arm/mach-nomadik/board-nhk8815.c index ab3712c..841d459 100644 --- a/arch/arm/mach-nomadik/board-nhk8815.c +++ b/arch/arm/mach-nomadik/board-nhk8815.c @@ -32,7 +32,6 @@ #include #include #include -#include "clock.h" /* Initial value for SRC control register: all timers use MXTAL/8 source */ #define SRC_CR_INIT_MASK 0x00007fff @@ -202,11 +201,6 @@ static struct amba_device *amba_devs[] __initdata = { &uart1_device, }; -/* We have a fixed clock alone, by now */ -static struct clk nhk8815_clk_48 = { - .rate = 48*1000*1000, -}; - static struct resource nhk8815_eth_resources[] = { { .name = "smc91x-regs", @@ -276,10 +270,8 @@ static void __init nhk8815_platform_init(void) platform_add_devices(nhk8815_platform_devices, ARRAY_SIZE(nhk8815_platform_devices)); - for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { - nmdk_clk_create(&nhk8815_clk_48, amba_devs[i]->dev.init_name); + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) amba_device_register(amba_devs[i], &iomem_resource); - } } MACHINE_START(NOMADIK, "NHK8815") diff --git a/arch/arm/mach-nomadik/clock.c b/arch/arm/mach-nomadik/clock.c index 9f92502..7af7850 100644 --- a/arch/arm/mach-nomadik/clock.c +++ b/arch/arm/mach-nomadik/clock.c @@ -32,14 +32,26 @@ void clk_disable(struct clk *clk) } EXPORT_SYMBOL(clk_disable); -/* Create a clock structure with the given name */ -int nmdk_clk_create(struct clk *clk, const char *dev_id) -{ - struct clk_lookup *clkdev; +/* We have a fixed clock alone, for now */ +static struct clk clk_48 = { + .rate = 48 * 1000 * 1000, +}; + +#define CLK(_clk, dev) \ + { \ + .clk = _clk, \ + .dev_id = dev, \ + } + +static struct clk_lookup lookups[] = { + CLK(&clk_48, "uart0"), + CLK(&clk_48, "uart1"), +}; - clkdev = clkdev_alloc(clk, NULL, dev_id); - if (!clkdev) - return -ENOMEM; - clkdev_add(clkdev); +static int __init clk_init(void) +{ + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); return 0; } + +arch_initcall(clk_init); diff --git a/arch/arm/mach-nomadik/clock.h b/arch/arm/mach-nomadik/clock.h index 235faec..5563985 100644 --- a/arch/arm/mach-nomadik/clock.h +++ b/arch/arm/mach-nomadik/clock.h @@ -11,4 +11,3 @@ struct clk { unsigned long rate; }; -extern int nmdk_clk_create(struct clk *clk, const char *dev_id); -- cgit v0.10.2 From af7dc2281fd3cedc04cb51bcc0887cdaf65c3fcc Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Thu, 6 May 2010 11:14:17 +0100 Subject: ARM: 6104/1: nomadik-gpio: use clk API Add clocks with appropriate names in platforms that use it, and use the clk API in nomadik-gpio. Acked-by: Alessandro Rubini Acked-by: Linus Walleij Acked-by: Srinidhi Kasagar Signed-off-by: Rabin Vincent Signed-off-by: Russell King diff --git a/arch/arm/mach-nomadik/clock.c b/arch/arm/mach-nomadik/clock.c index 7af7850..60f5bee 100644 --- a/arch/arm/mach-nomadik/clock.c +++ b/arch/arm/mach-nomadik/clock.c @@ -37,6 +37,12 @@ static struct clk clk_48 = { .rate = 48 * 1000 * 1000, }; +/* + * Catch-all default clock to satisfy drivers using the clk API. We don't + * model the actual hardware clocks yet. + */ +static struct clk clk_default; + #define CLK(_clk, dev) \ { \ .clk = _clk, \ @@ -46,6 +52,10 @@ static struct clk clk_48 = { static struct clk_lookup lookups[] = { CLK(&clk_48, "uart0"), CLK(&clk_48, "uart1"), + CLK(&clk_default, "gpio.0"), + CLK(&clk_default, "gpio.1"), + CLK(&clk_default, "gpio.2"), + CLK(&clk_default, "gpio.3"), }; static int __init clk_init(void) diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c index c325dad..1b2c989 100644 --- a/arch/arm/mach-ux500/clock.c +++ b/arch/arm/mach-ux500/clock.c @@ -364,7 +364,8 @@ static DEFINE_PRCC_CLK(7, cfgreg_ed, 0, -1, NULL); static struct clk_lookup u8500_common_clks[] = { /* Peripheral Cluster #1 */ - CLK(gpio0, "gpioblock0", NULL), + CLK(gpio0, "gpio.0", NULL), + CLK(gpio0, "gpio.1", NULL), CLK(slimbus0, "slimbus0", NULL), CLK(i2c2, "nmk-i2c.2", NULL), CLK(sdi0, "sdi0", NULL), @@ -374,7 +375,10 @@ static struct clk_lookup u8500_common_clks[] = { CLK(uart0, "uart0", NULL), /* Peripheral Cluster #3 */ - CLK(gpio2, "gpioblock2", NULL), + CLK(gpio2, "gpio.2", NULL), + CLK(gpio2, "gpio.3", NULL), + CLK(gpio2, "gpio.4", NULL), + CLK(gpio2, "gpio.5", NULL), CLK(sdi5, "sdi5", NULL), CLK(uart2, "uart2", NULL), CLK(ske, "ske", NULL), @@ -383,7 +387,7 @@ static struct clk_lookup u8500_common_clks[] = { CLK(fsmc, "fsmc", NULL), /* Peripheral Cluster #5 */ - CLK(gpio3, "gpioblock3", NULL), + CLK(gpio3, "gpio.8", NULL), /* Peripheral Cluster #6 */ CLK(hash1, "hash1", NULL), @@ -418,7 +422,8 @@ static struct clk_lookup u8500_ed_clks[] = { CLK(msp1_ed, "msp1", NULL), /* Peripheral Cluster #2 */ - CLK(gpio1_ed, "gpioblock1", NULL), + CLK(gpio1_ed, "gpio.6", NULL), + CLK(gpio1_ed, "gpio.7", NULL), CLK(ssitx_ed, "ssitx", NULL), CLK(ssirx_ed, "ssirx", NULL), CLK(spi0_ed, "spi0", NULL), @@ -458,7 +463,8 @@ static struct clk_lookup u8500_v1_clks[] = { CLK(msp1_v1, "msp1", NULL), /* Peripheral Cluster #2 */ - CLK(gpio1_v1, "gpioblock1", NULL), + CLK(gpio1_v1, "gpio.6", NULL), + CLK(gpio1_v1, "gpio.7", NULL), CLK(ssitx_v1, "ssitx", NULL), CLK(ssirx_v1, "ssirx", NULL), CLK(spi0_v1, "spi0", NULL), diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c index eac9c9a..d28900c 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include #include #include @@ -35,6 +37,7 @@ struct nmk_gpio_chip { struct gpio_chip chip; void __iomem *addr; + struct clk *clk; unsigned int parent_irq; spinlock_t lock; /* Keep track of configured edges */ @@ -310,6 +313,7 @@ static int __init nmk_gpio_probe(struct platform_device *dev) struct nmk_gpio_chip *nmk_chip; struct gpio_chip *chip; struct resource *res; + struct clk *clk; int irq; int ret; @@ -334,15 +338,24 @@ static int __init nmk_gpio_probe(struct platform_device *dev) goto out; } + clk = clk_get(&dev->dev, NULL); + if (IS_ERR(clk)) { + ret = PTR_ERR(clk); + goto out_release; + } + + clk_enable(clk); + nmk_chip = kzalloc(sizeof(*nmk_chip), GFP_KERNEL); if (!nmk_chip) { ret = -ENOMEM; - goto out_release; + goto out_clk; } /* * The virt address in nmk_chip->addr is in the nomadik register space, * so we can simply convert the resource address, without remapping */ + nmk_chip->clk = clk; nmk_chip->addr = io_p2v(res->start); nmk_chip->chip = nmk_gpio_template; nmk_chip->parent_irq = irq; @@ -368,6 +381,9 @@ static int __init nmk_gpio_probe(struct platform_device *dev) out_free: kfree(nmk_chip); +out_clk: + clk_disable(clk); + clk_put(clk); out_release: release_mem_region(res->start, resource_size(res)); out: @@ -385,6 +401,8 @@ static int __exit nmk_gpio_remove(struct platform_device *dev) nmk_chip = platform_get_drvdata(dev); gpiochip_remove(&nmk_chip->chip); + clk_disable(nmk_chip->clk); + clk_put(nmk_chip->clk); kfree(nmk_chip); release_mem_region(res->start, resource_size(res)); return 0; -- cgit v0.10.2 From 28552c2eae472a0a52d1cdb02eb32766c7f690e1 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Thu, 25 Feb 2010 15:36:38 -0800 Subject: davinci: misc cleanups from sparse - Convert data/functions to static - include headers for missing declarations - pointer cleanups: struct foo *__iomem f --> struct foo __iomem *f; Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c index 976e11b..95cef1f 100644 --- a/arch/arm/mach-davinci/board-dm644x-evm.c +++ b/arch/arm/mach-davinci/board-dm644x-evm.c @@ -111,7 +111,7 @@ static struct platform_device davinci_evm_norflash_device = { * It may used instead of the (default) NOR chip to boot, using TI's * tools to install the secondary boot loader (UBL) and U-Boot. */ -struct mtd_partition davinci_evm_nandflash_partition[] = { +static struct mtd_partition davinci_evm_nandflash_partition[] = { /* Bootloader layout depends on whose u-boot is installed, but we * can hide all the details. * - block 0 for u-boot environment ... in mainline u-boot diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c index bd9ca07..1fadc68 100644 --- a/arch/arm/mach-davinci/board-neuros-osd2.c +++ b/arch/arm/mach-davinci/board-neuros-osd2.c @@ -60,7 +60,7 @@ #define NAND_BLOCK_SIZE SZ_128K -struct mtd_partition davinci_ntosd2_nandflash_partition[] = { +static struct mtd_partition davinci_ntosd2_nandflash_partition[] = { { /* UBL (a few copies) plus U-Boot */ .name = "bootloader", diff --git a/arch/arm/mach-davinci/board-sffsdr.c b/arch/arm/mach-davinci/board-sffsdr.c index 08d373b..a7cf810 100644 --- a/arch/arm/mach-davinci/board-sffsdr.c +++ b/arch/arm/mach-davinci/board-sffsdr.c @@ -48,7 +48,7 @@ #define DAVINCI_ASYNC_EMIF_CONTROL_BASE 0x01e00000 #define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE 0x02000000 -struct mtd_partition davinci_sffsdr_nandflash_partition[] = { +static struct mtd_partition davinci_sffsdr_nandflash_partition[] = { /* U-Boot Environment: Block 0 * UBL: Block 1 * U-Boot: Blocks 6-7 (256 kb) diff --git a/arch/arm/mach-davinci/cdce949.c b/arch/arm/mach-davinci/cdce949.c index aec3756..ba8b12b 100644 --- a/arch/arm/mach-davinci/cdce949.c +++ b/arch/arm/mach-davinci/cdce949.c @@ -19,6 +19,7 @@ #include #include +#include #include "clock.h" diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c index bf6218e..058c77f 100644 --- a/arch/arm/mach-davinci/clock.c +++ b/arch/arm/mach-davinci/clock.c @@ -22,6 +22,7 @@ #include +#include #include #include #include "clock.h" diff --git a/arch/arm/mach-davinci/devices.c b/arch/arm/mach-davinci/devices.c index 1479496..ef28080 100644 --- a/arch/arm/mach-davinci/devices.c +++ b/arch/arm/mach-davinci/devices.c @@ -23,6 +23,8 @@ #include #include +#include "clock.h" + #define DAVINCI_I2C_BASE 0x01C21000 #define DAVINCI_MMCSD0_BASE 0x01E10000 #define DM355_MMCSD0_BASE 0x01E11000 diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c index 3dc0a88..5efce70 100644 --- a/arch/arm/mach-davinci/dm355.c +++ b/arch/arm/mach-davinci/dm355.c @@ -798,7 +798,7 @@ static void __iomem *dm355_psc_bases[] = { * T1_BOT: Timer 1, bottom: (used by DSP in TI DSPLink code) * T1_TOP: Timer 1, top : */ -struct davinci_timer_info dm355_timer_info = { +static struct davinci_timer_info dm355_timer_info = { .timers = davinci_timer_instance, .clockevent_id = T0_BOT, .clocksource_id = T0_TOP, diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index 0d6ee58..871be5a 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -1010,7 +1010,7 @@ static void __iomem *dm365_psc_bases[] = { IO_ADDRESS(DAVINCI_PWR_SLEEP_CNTRL_BASE), }; -struct davinci_timer_info dm365_timer_info = { +static struct davinci_timer_info dm365_timer_info = { .timers = davinci_timer_instance, .clockevent_id = T0_BOT, .clocksource_id = T0_TOP, diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index 2f2ae8b..23cbe9d 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c @@ -277,7 +277,7 @@ static struct clk timer2_clk = { .usecount = 1, /* REVISIT: why cant' this be disabled? */ }; -struct clk_lookup dm644x_clks[] = { +static struct clk_lookup dm644x_clks[] = { CLK(NULL, "ref", &ref_clk), CLK(NULL, "pll1", &pll1_clk), CLK(NULL, "pll1_sysclk1", &pll1_sysclk1), @@ -687,7 +687,7 @@ static void __iomem *dm644x_psc_bases[] = { * T1_BOT: Timer 1, bottom: (used by DSP in TI DSPLink code) * T1_TOP: Timer 1, top : */ -struct davinci_timer_info dm644x_timer_info = { +static struct davinci_timer_info dm644x_timer_info = { .timers = davinci_timer_instance, .clockevent_id = T0_BOT, .clocksource_id = T0_TOP, diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index 893baf4..b67b997d 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -311,7 +311,7 @@ static struct clk vpif1_clk = { .flags = ALWAYS_ENABLED, }; -struct clk_lookup dm646x_clks[] = { +static struct clk_lookup dm646x_clks[] = { CLK(NULL, "ref", &ref_clk), CLK(NULL, "aux", &aux_clkin), CLK(NULL, "pll1", &pll1_clk), @@ -797,7 +797,7 @@ static void __iomem *dm646x_psc_bases[] = { * T1_BOT: Timer 1, bottom: (used by DSP in TI DSPLink code) * T1_TOP: Timer 1, top : */ -struct davinci_timer_info dm646x_timer_info = { +static struct davinci_timer_info dm646x_timer_info = { .timers = davinci_timer_instance, .clockevent_id = T0_BOT, .clocksource_id = T0_TOP, @@ -867,7 +867,7 @@ static struct davinci_soc_info davinci_soc_info_dm646x = { .sram_len = SZ_32K, }; -void __init dm646x_init_ide() +void __init dm646x_init_ide(void) { davinci_cfg_reg(DM646X_ATAEN); platform_device_register(&ide_dev); diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c index 744755b..3f77062 100644 --- a/arch/arm/mach-davinci/gpio.c +++ b/arch/arm/mach-davinci/gpio.c @@ -24,14 +24,14 @@ static DEFINE_SPINLOCK(gpio_lock); struct davinci_gpio { struct gpio_chip chip; - struct gpio_controller *__iomem regs; + struct gpio_controller __iomem *regs; int irq_base; }; static struct davinci_gpio chips[DIV_ROUND_UP(DAVINCI_N_GPIO, 32)]; /* create a non-inlined version */ -static struct gpio_controller __iomem * __init gpio2controller(unsigned gpio) +static struct gpio_controller __iomem __init *gpio2controller(unsigned gpio) { return __gpio_to_controller(gpio); } @@ -48,7 +48,7 @@ static int __init davinci_gpio_irq_setup(void); static int davinci_direction_in(struct gpio_chip *chip, unsigned offset) { struct davinci_gpio *d = container_of(chip, struct davinci_gpio, chip); - struct gpio_controller *__iomem g = d->regs; + struct gpio_controller __iomem *g = d->regs; u32 temp; spin_lock(&gpio_lock); @@ -70,7 +70,7 @@ static int davinci_direction_in(struct gpio_chip *chip, unsigned offset) static int davinci_gpio_get(struct gpio_chip *chip, unsigned offset) { struct davinci_gpio *d = container_of(chip, struct davinci_gpio, chip); - struct gpio_controller *__iomem g = d->regs; + struct gpio_controller __iomem *g = d->regs; return (1 << offset) & __raw_readl(&g->in_data); } @@ -79,7 +79,7 @@ static int davinci_direction_out(struct gpio_chip *chip, unsigned offset, int value) { struct davinci_gpio *d = container_of(chip, struct davinci_gpio, chip); - struct gpio_controller *__iomem g = d->regs; + struct gpio_controller __iomem *g = d->regs; u32 temp; u32 mask = 1 << offset; @@ -99,7 +99,7 @@ static void davinci_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { struct davinci_gpio *d = container_of(chip, struct davinci_gpio, chip); - struct gpio_controller *__iomem g = d->regs; + struct gpio_controller __iomem *g = d->regs; __raw_writel((1 << offset), value ? &g->set_data : &g->clr_data); } @@ -161,7 +161,7 @@ pure_initcall(davinci_gpio_setup); static void gpio_irq_disable(unsigned irq) { - struct gpio_controller *__iomem g = get_irq_chip_data(irq); + struct gpio_controller __iomem *g = get_irq_chip_data(irq); u32 mask = (u32) get_irq_data(irq); __raw_writel(mask, &g->clr_falling); @@ -170,7 +170,7 @@ static void gpio_irq_disable(unsigned irq) static void gpio_irq_enable(unsigned irq) { - struct gpio_controller *__iomem g = get_irq_chip_data(irq); + struct gpio_controller __iomem *g = get_irq_chip_data(irq); u32 mask = (u32) get_irq_data(irq); unsigned status = irq_desc[irq].status; @@ -186,7 +186,7 @@ static void gpio_irq_enable(unsigned irq) static int gpio_irq_type(unsigned irq, unsigned trigger) { - struct gpio_controller *__iomem g = get_irq_chip_data(irq); + struct gpio_controller __iomem *g = get_irq_chip_data(irq); u32 mask = (u32) get_irq_data(irq); if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) @@ -215,7 +215,7 @@ static struct irq_chip gpio_irqchip = { static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) { - struct gpio_controller *__iomem g = get_irq_chip_data(irq); + struct gpio_controller __iomem *g = get_irq_chip_data(irq); u32 mask = 0xffff; /* we only care about one bank */ @@ -276,7 +276,7 @@ static int gpio_to_irq_unbanked(struct gpio_chip *chip, unsigned offset) static int gpio_irq_type_unbanked(unsigned irq, unsigned trigger) { - struct gpio_controller *__iomem g = get_irq_chip_data(irq); + struct gpio_controller __iomem *g = get_irq_chip_data(irq); u32 mask = (u32) get_irq_data(irq); if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) @@ -305,7 +305,7 @@ static int __init davinci_gpio_irq_setup(void) u32 binten = 0; unsigned ngpio, bank_irq; struct davinci_soc_info *soc_info = &davinci_soc_info; - struct gpio_controller *__iomem g; + struct gpio_controller __iomem *g; ngpio = soc_info->gpio_num; diff --git a/arch/arm/mach-davinci/include/mach/gpio.h b/arch/arm/mach-davinci/include/mach/gpio.h index f3b8ef8..0099e6e 100644 --- a/arch/arm/mach-davinci/include/mach/gpio.h +++ b/arch/arm/mach-davinci/include/mach/gpio.h @@ -67,10 +67,10 @@ struct gpio_controller { * * These are NOT part of the cross-platform GPIO interface */ -static inline struct gpio_controller *__iomem +static inline struct gpio_controller __iomem * __gpio_to_controller(unsigned gpio) { - void *__iomem ptr; + void __iomem *ptr; void __iomem *base = davinci_soc_info.gpio_base; if (gpio < 32 * 1) @@ -102,7 +102,7 @@ static inline u32 __gpio_mask(unsigned gpio) static inline void gpio_set_value(unsigned gpio, int value) { if (__builtin_constant_p(value) && gpio < DAVINCI_N_GPIO) { - struct gpio_controller *__iomem g; + struct gpio_controller __iomem *g; u32 mask; g = __gpio_to_controller(gpio); @@ -128,7 +128,7 @@ static inline void gpio_set_value(unsigned gpio, int value) */ static inline int gpio_get_value(unsigned gpio) { - struct gpio_controller *__iomem g; + struct gpio_controller __iomem *g; if (!__builtin_constant_p(gpio) || gpio >= DAVINCI_N_GPIO) return __gpio_get_value(gpio); diff --git a/arch/arm/mach-davinci/mux.c b/arch/arm/mach-davinci/mux.c index f757e83..c942c89 100644 --- a/arch/arm/mach-davinci/mux.c +++ b/arch/arm/mach-davinci/mux.c @@ -21,6 +21,7 @@ #include #include +#include /* * Sets the DAVINCI MUX register based on the table -- cgit v0.10.2 From 21ce873d211a42e315558d6ae09a8bb04508a592 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Thu, 25 Feb 2010 16:49:56 -0800 Subject: davinci: sparse: gpio: void casting Cleanup usage of void pointers when using genirq. genirq API takes and returns void *, where this GPIO API is using those as __iomem pointers. Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c index 3f77062..5476ad1 100644 --- a/arch/arm/mach-davinci/gpio.c +++ b/arch/arm/mach-davinci/gpio.c @@ -36,6 +36,15 @@ static struct gpio_controller __iomem __init *gpio2controller(unsigned gpio) return __gpio_to_controller(gpio); } +static inline struct gpio_controller __iomem *irq2controller(int irq) +{ + struct gpio_controller __iomem *g; + + g = (__force struct gpio_controller __iomem *)get_irq_chip_data(irq); + + return g; +} + static int __init davinci_gpio_irq_setup(void); /*--------------------------------------------------------------------------*/ @@ -161,7 +170,7 @@ pure_initcall(davinci_gpio_setup); static void gpio_irq_disable(unsigned irq) { - struct gpio_controller __iomem *g = get_irq_chip_data(irq); + struct gpio_controller __iomem *g = irq2controller(irq); u32 mask = (u32) get_irq_data(irq); __raw_writel(mask, &g->clr_falling); @@ -170,7 +179,7 @@ static void gpio_irq_disable(unsigned irq) static void gpio_irq_enable(unsigned irq) { - struct gpio_controller __iomem *g = get_irq_chip_data(irq); + struct gpio_controller __iomem *g = irq2controller(irq); u32 mask = (u32) get_irq_data(irq); unsigned status = irq_desc[irq].status; @@ -186,7 +195,7 @@ static void gpio_irq_enable(unsigned irq) static int gpio_irq_type(unsigned irq, unsigned trigger) { - struct gpio_controller __iomem *g = get_irq_chip_data(irq); + struct gpio_controller __iomem *g = irq2controller(irq); u32 mask = (u32) get_irq_data(irq); if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) @@ -215,7 +224,7 @@ static struct irq_chip gpio_irqchip = { static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) { - struct gpio_controller __iomem *g = get_irq_chip_data(irq); + struct gpio_controller __iomem *g = irq2controller(irq); u32 mask = 0xffff; /* we only care about one bank */ @@ -276,7 +285,7 @@ static int gpio_to_irq_unbanked(struct gpio_chip *chip, unsigned offset) static int gpio_irq_type_unbanked(unsigned irq, unsigned trigger) { - struct gpio_controller __iomem *g = get_irq_chip_data(irq); + struct gpio_controller __iomem *g = irq2controller(irq); u32 mask = (u32) get_irq_data(irq); if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) @@ -362,7 +371,7 @@ static int __init davinci_gpio_irq_setup(void) for (gpio = 0; gpio < soc_info->gpio_unbanked; gpio++, irq++) { set_irq_chip(irq, &gpio_irqchip_unbanked); set_irq_data(irq, (void *) __gpio_mask(gpio)); - set_irq_chip_data(irq, g); + set_irq_chip_data(irq, (__force void *) g); irq_desc[irq].status |= IRQ_TYPE_EDGE_BOTH; } @@ -385,12 +394,12 @@ static int __init davinci_gpio_irq_setup(void) /* set up all irqs in this bank */ set_irq_chained_handler(bank_irq, gpio_irq_handler); - set_irq_chip_data(bank_irq, g); - set_irq_data(bank_irq, (void *)irq); + set_irq_chip_data(bank_irq, (__force void *) g); + set_irq_data(bank_irq, (void *) irq); for (i = 0; i < 16 && gpio < ngpio; i++, irq++, gpio++) { set_irq_chip(irq, &gpio_irqchip); - set_irq_chip_data(irq, g); + set_irq_chip_data(irq, (__force void *) g); set_irq_data(irq, (void *) __gpio_mask(gpio)); set_irq_handler(irq, handle_simple_irq); set_irq_flags(irq, IRQF_VALID); -- cgit v0.10.2 From 8ccfd3f074f75135971905d2413811729e19580e Mon Sep 17 00:00:00 2001 From: Vipin Bhandari Date: Wed, 10 Mar 2010 14:03:01 +0530 Subject: davinci: da830/omap-l137 evm: add support for GPIO based MMC/SD card detection The DA830/OMAP-L137 EVM has GPIO based card detection logic, but the current code does not use it. Add support for GPIO based card detection to avoid reading the card to see if a card is present or not. Signed-off-by: Vipin Bhandari Signed-off-by: Sekhar Nori Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c index dc19870..8e67037 100644 --- a/arch/arm/mach-davinci/board-da830-evm.c +++ b/arch/arm/mach-davinci/board-da830-evm.c @@ -229,14 +229,21 @@ static const short da830_evm_mmc_sd_pins[] = { }; #define DA830_MMCSD_WP_PIN GPIO_TO_PIN(2, 1) +#define DA830_MMCSD_CD_PIN GPIO_TO_PIN(2, 2) static int da830_evm_mmc_get_ro(int index) { return gpio_get_value(DA830_MMCSD_WP_PIN); } +static int da830_evm_mmc_get_cd(int index) +{ + return !gpio_get_value(DA830_MMCSD_CD_PIN); +} + static struct davinci_mmc_config da830_evm_mmc_config = { .get_ro = da830_evm_mmc_get_ro, + .get_cd = da830_evm_mmc_get_cd, .wires = 4, .max_freq = 50000000, .caps = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED, @@ -262,6 +269,14 @@ static inline void da830_evm_init_mmc(void) } gpio_direction_input(DA830_MMCSD_WP_PIN); + ret = gpio_request(DA830_MMCSD_CD_PIN, "MMC CD\n"); + if (ret) { + pr_warning("da830_evm_init: can not open GPIO %d\n", + DA830_MMCSD_CD_PIN); + return; + } + gpio_direction_input(DA830_MMCSD_CD_PIN); + ret = da8xx_register_mmcsd0(&da830_evm_mmc_config); if (ret) { pr_warning("da830_evm_init: mmc/sd registration failed: %d\n", -- cgit v0.10.2 From d154fed7234331dc29240deb04f92f382000e66b Mon Sep 17 00:00:00 2001 From: Vipin Bhandari Date: Wed, 10 Mar 2010 14:03:02 +0530 Subject: davinci: da830/omap-l137 evm: use 8-wire MMC/SD card support The merge for 2.6.34 brings in 8-bit support to the DaVinci MMC/SD driver. This patch updates the platform data for DA830/OMAP-L137 EVM to use 8-wire support available in the driver. Signed-off-by: Vipin Bhandari Signed-off-by: Sekhar Nori Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c index 8e67037..ea293b8 100644 --- a/arch/arm/mach-davinci/board-da830-evm.c +++ b/arch/arm/mach-davinci/board-da830-evm.c @@ -244,7 +244,7 @@ static int da830_evm_mmc_get_cd(int index) static struct davinci_mmc_config da830_evm_mmc_config = { .get_ro = da830_evm_mmc_get_ro, .get_cd = da830_evm_mmc_get_cd, - .wires = 4, + .wires = 8, .max_freq = 50000000, .caps = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED, .version = MMC_CTLR_VERSION_2, -- cgit v0.10.2 From a7e05065f562ae347db36b0ef644525cd1e89ecd Mon Sep 17 00:00:00 2001 From: Anuj Aggarwal Date: Mon, 8 Mar 2010 15:05:58 +0530 Subject: davinci: edma: clear interrupt status for interrupt enabled channels only Currently, the ISR in the EDMA driver clears the pending interrupt for all channels without regard to whether that channel has a registered callback or not. This causes problems for devices like DM355/DM365 where the multimedia accelerator uses EDMA by polling on the interrupt pending bits of some of the EDMA channels. Since these channels are actually allocated through the Linux EDMA driver (by an out-of-kernel module), the same shadow region is used by Linux and accelerator. There a race between the Linux ISR and the polling code running on the accelerator on the IPR (interrupt pending register). This patch fixes the issue by making the ISR clear the interrupts only for those channels which have interrupt enabled. The channels which are allocated for the purpose of being polled on by the accelerator will not have a callback function provided and so will not have IER (interrupt enable register) bits set. Tested on DM365 and OMAP-L137/L138 with audio and MMC/SD (as EDMA users). Signed-off-by: Anuj Aggarwal Signed-off-by: Sekhar Nori CC: Archith John Bency Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/dma.c b/arch/arm/mach-davinci/dma.c index 5313738..0bf290b 100644 --- a/arch/arm/mach-davinci/dma.c +++ b/arch/arm/mach-davinci/dma.c @@ -359,9 +359,11 @@ static irqreturn_t dma_irq_handler(int irq, void *data) while (1) { int j; - if (edma_shadow0_read_array(ctlr, SH_IPR, 0)) + if (edma_shadow0_read_array(ctlr, SH_IPR, 0) & + edma_shadow0_read_array(ctlr, SH_IER, 0)) j = 0; - else if (edma_shadow0_read_array(ctlr, SH_IPR, 1)) + else if (edma_shadow0_read_array(ctlr, SH_IPR, 1) & + edma_shadow0_read_array(ctlr, SH_IER, 1)) j = 1; else break; @@ -369,8 +371,9 @@ static irqreturn_t dma_irq_handler(int irq, void *data) edma_shadow0_read_array(ctlr, SH_IPR, j)); for (i = 0; i < 32; i++) { int k = (j << 5) + i; - if (edma_shadow0_read_array(ctlr, SH_IPR, j) & - (1 << i)) { + if ((edma_shadow0_read_array(ctlr, SH_IPR, j) & BIT(i)) + && (edma_shadow0_read_array(ctlr, + SH_IER, j) & BIT(i))) { /* Clear the corresponding IPR bits */ edma_shadow0_write_array(ctlr, SH_ICR, j, (1 << i)); -- cgit v0.10.2 From 8ecf6c54d44c535b2296319aa58567ea9a1db026 Mon Sep 17 00:00:00 2001 From: Miguel Aguilar Date: Thu, 5 Nov 2009 08:51:34 -0600 Subject: RTC: DaVinci RTC driver This driver features: * Alarm support. * Periodic interrupt by using a timer include into the RTC module. * The update interrupt is not supported by this RTC module. This driver was tested on a DM365 EVM by using the rtc-test application from the Documentation/rtc.txt. Signed-off-by: Miguel Aguilar Signed-off-by: Kevin Hilman Acked-by: Alessandro Zummo diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 6a13037..50ac047 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -620,6 +620,16 @@ config RTC_DRV_NUC900 comment "on-CPU RTC drivers" +config RTC_DRV_DAVINCI + tristate "TI DaVinci RTC" + depends on ARCH_DAVINCI_DM365 + help + If you say yes here you get support for the RTC on the + DaVinci platforms (DM365). + + This driver can also be built as a module. If so, the module + will be called rtc-davinci. + config RTC_DRV_OMAP tristate "TI OMAP1" depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 44ef194..245311a 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_RTC_DRV_BQ32K) += rtc-bq32k.o obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.o obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o +obj-$(CONFIG_RTC_DRV_DAVINCI) += rtc-davinci.o obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o obj-$(CONFIG_RTC_DRV_DS1286) += rtc-ds1286.o diff --git a/drivers/rtc/rtc-davinci.c b/drivers/rtc/rtc-davinci.c new file mode 100644 index 0000000..92a8f6c --- /dev/null +++ b/drivers/rtc/rtc-davinci.c @@ -0,0 +1,673 @@ +/* + * DaVinci Power Management and Real Time Clock Driver for TI platforms + * + * Copyright (C) 2009 Texas Instruments, Inc + * + * Author: Miguel Aguilar + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * The DaVinci RTC is a simple RTC with the following + * Sec: 0 - 59 : BCD count + * Min: 0 - 59 : BCD count + * Hour: 0 - 23 : BCD count + * Day: 0 - 0x7FFF(32767) : Binary count ( Over 89 years ) + */ + +/* PRTC interface registers */ +#define DAVINCI_PRTCIF_PID 0x00 +#define PRTCIF_CTLR 0x04 +#define PRTCIF_LDATA 0x08 +#define PRTCIF_UDATA 0x0C +#define PRTCIF_INTEN 0x10 +#define PRTCIF_INTFLG 0x14 + +/* PRTCIF_CTLR bit fields */ +#define PRTCIF_CTLR_BUSY BIT(31) +#define PRTCIF_CTLR_SIZE BIT(25) +#define PRTCIF_CTLR_DIR BIT(24) +#define PRTCIF_CTLR_BENU_MSB BIT(23) +#define PRTCIF_CTLR_BENU_3RD_BYTE BIT(22) +#define PRTCIF_CTLR_BENU_2ND_BYTE BIT(21) +#define PRTCIF_CTLR_BENU_LSB BIT(20) +#define PRTCIF_CTLR_BENU_MASK (0x00F00000) +#define PRTCIF_CTLR_BENL_MSB BIT(19) +#define PRTCIF_CTLR_BENL_3RD_BYTE BIT(18) +#define PRTCIF_CTLR_BENL_2ND_BYTE BIT(17) +#define PRTCIF_CTLR_BENL_LSB BIT(16) +#define PRTCIF_CTLR_BENL_MASK (0x000F0000) + +/* PRTCIF_INTEN bit fields */ +#define PRTCIF_INTEN_RTCSS BIT(1) +#define PRTCIF_INTEN_RTCIF BIT(0) +#define PRTCIF_INTEN_MASK (PRTCIF_INTEN_RTCSS \ + | PRTCIF_INTEN_RTCIF) + +/* PRTCIF_INTFLG bit fields */ +#define PRTCIF_INTFLG_RTCSS BIT(1) +#define PRTCIF_INTFLG_RTCIF BIT(0) +#define PRTCIF_INTFLG_MASK (PRTCIF_INTFLG_RTCSS \ + | PRTCIF_INTFLG_RTCIF) + +/* PRTC subsystem registers */ +#define PRTCSS_RTC_INTC_EXTENA1 (0x0C) +#define PRTCSS_RTC_CTRL (0x10) +#define PRTCSS_RTC_WDT (0x11) +#define PRTCSS_RTC_TMR0 (0x12) +#define PRTCSS_RTC_TMR1 (0x13) +#define PRTCSS_RTC_CCTRL (0x14) +#define PRTCSS_RTC_SEC (0x15) +#define PRTCSS_RTC_MIN (0x16) +#define PRTCSS_RTC_HOUR (0x17) +#define PRTCSS_RTC_DAY0 (0x18) +#define PRTCSS_RTC_DAY1 (0x19) +#define PRTCSS_RTC_AMIN (0x1A) +#define PRTCSS_RTC_AHOUR (0x1B) +#define PRTCSS_RTC_ADAY0 (0x1C) +#define PRTCSS_RTC_ADAY1 (0x1D) +#define PRTCSS_RTC_CLKC_CNT (0x20) + +/* PRTCSS_RTC_INTC_EXTENA1 */ +#define PRTCSS_RTC_INTC_EXTENA1_MASK (0x07) + +/* PRTCSS_RTC_CTRL bit fields */ +#define PRTCSS_RTC_CTRL_WDTBUS BIT(7) +#define PRTCSS_RTC_CTRL_WEN BIT(6) +#define PRTCSS_RTC_CTRL_WDRT BIT(5) +#define PRTCSS_RTC_CTRL_WDTFLG BIT(4) +#define PRTCSS_RTC_CTRL_TE BIT(3) +#define PRTCSS_RTC_CTRL_TIEN BIT(2) +#define PRTCSS_RTC_CTRL_TMRFLG BIT(1) +#define PRTCSS_RTC_CTRL_TMMD BIT(0) + +/* PRTCSS_RTC_CCTRL bit fields */ +#define PRTCSS_RTC_CCTRL_CALBUSY BIT(7) +#define PRTCSS_RTC_CCTRL_DAEN BIT(5) +#define PRTCSS_RTC_CCTRL_HAEN BIT(4) +#define PRTCSS_RTC_CCTRL_MAEN BIT(3) +#define PRTCSS_RTC_CCTRL_ALMFLG BIT(2) +#define PRTCSS_RTC_CCTRL_AIEN BIT(1) +#define PRTCSS_RTC_CCTRL_CAEN BIT(0) + +static DEFINE_SPINLOCK(davinci_rtc_lock); + +struct davinci_rtc { + struct rtc_device *rtc; + void __iomem *base; + resource_size_t pbase; + size_t base_size; + int irq; +}; + +static inline void rtcif_write(struct davinci_rtc *davinci_rtc, + u32 val, u32 addr) +{ + writel(val, davinci_rtc->base + addr); +} + +static inline u32 rtcif_read(struct davinci_rtc *davinci_rtc, u32 addr) +{ + return readl(davinci_rtc->base + addr); +} + +static inline void rtcif_wait(struct davinci_rtc *davinci_rtc) +{ + while (rtcif_read(davinci_rtc, PRTCIF_CTLR) & PRTCIF_CTLR_BUSY) + cpu_relax(); +} + +static inline void rtcss_write(struct davinci_rtc *davinci_rtc, + unsigned long val, u8 addr) +{ + rtcif_wait(davinci_rtc); + + rtcif_write(davinci_rtc, PRTCIF_CTLR_BENL_LSB | addr, PRTCIF_CTLR); + rtcif_write(davinci_rtc, val, PRTCIF_LDATA); + + rtcif_wait(davinci_rtc); +} + +static inline u8 rtcss_read(struct davinci_rtc *davinci_rtc, u8 addr) +{ + rtcif_wait(davinci_rtc); + + rtcif_write(davinci_rtc, PRTCIF_CTLR_DIR | PRTCIF_CTLR_BENL_LSB | addr, + PRTCIF_CTLR); + + rtcif_wait(davinci_rtc); + + return rtcif_read(davinci_rtc, PRTCIF_LDATA); +} + +static inline void davinci_rtcss_calendar_wait(struct davinci_rtc *davinci_rtc) +{ + while (rtcss_read(davinci_rtc, PRTCSS_RTC_CCTRL) & + PRTCSS_RTC_CCTRL_CALBUSY) + cpu_relax(); +} + +static irqreturn_t davinci_rtc_interrupt(int irq, void *class_dev) +{ + struct davinci_rtc *davinci_rtc = class_dev; + unsigned long events = 0; + u32 irq_flg; + u8 alm_irq, tmr_irq; + u8 rtc_ctrl, rtc_cctrl; + int ret = IRQ_NONE; + + irq_flg = rtcif_read(davinci_rtc, PRTCIF_INTFLG) & + PRTCIF_INTFLG_RTCSS; + + alm_irq = rtcss_read(davinci_rtc, PRTCSS_RTC_CCTRL) & + PRTCSS_RTC_CCTRL_ALMFLG; + + tmr_irq = rtcss_read(davinci_rtc, PRTCSS_RTC_CTRL) & + PRTCSS_RTC_CTRL_TMRFLG; + + if (irq_flg) { + if (alm_irq) { + events |= RTC_IRQF | RTC_AF; + rtc_cctrl = rtcss_read(davinci_rtc, PRTCSS_RTC_CCTRL); + rtc_cctrl |= PRTCSS_RTC_CCTRL_ALMFLG; + rtcss_write(davinci_rtc, rtc_cctrl, PRTCSS_RTC_CCTRL); + } else if (tmr_irq) { + events |= RTC_IRQF | RTC_PF; + rtc_ctrl = rtcss_read(davinci_rtc, PRTCSS_RTC_CTRL); + rtc_ctrl |= PRTCSS_RTC_CTRL_TMRFLG; + rtcss_write(davinci_rtc, rtc_ctrl, PRTCSS_RTC_CTRL); + } + + rtcif_write(davinci_rtc, PRTCIF_INTFLG_RTCSS, + PRTCIF_INTFLG); + rtc_update_irq(davinci_rtc->rtc, 1, events); + + ret = IRQ_HANDLED; + } + + return ret; +} + +static int +davinci_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) +{ + struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev); + u8 rtc_ctrl; + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&davinci_rtc_lock, flags); + + rtc_ctrl = rtcss_read(davinci_rtc, PRTCSS_RTC_CTRL); + + switch (cmd) { + case RTC_WIE_ON: + rtc_ctrl |= PRTCSS_RTC_CTRL_WEN | PRTCSS_RTC_CTRL_WDTFLG; + break; + case RTC_WIE_OFF: + rtc_ctrl &= ~PRTCSS_RTC_CTRL_WEN; + break; + case RTC_UIE_OFF: + case RTC_UIE_ON: + ret = -ENOTTY; + break; + default: + ret = -ENOIOCTLCMD; + } + + rtcss_write(davinci_rtc, rtc_ctrl, PRTCSS_RTC_CTRL); + + spin_unlock_irqrestore(&davinci_rtc_lock, flags); + + return ret; +} + +static int convertfromdays(u16 days, struct rtc_time *tm) +{ + int tmp_days, year, mon; + + for (year = 2000;; year++) { + tmp_days = rtc_year_days(1, 12, year); + if (days >= tmp_days) + days -= tmp_days; + else { + for (mon = 0;; mon++) { + tmp_days = rtc_month_days(mon, year); + if (days >= tmp_days) { + days -= tmp_days; + } else { + tm->tm_year = year - 1900; + tm->tm_mon = mon; + tm->tm_mday = days + 1; + break; + } + } + break; + } + } + return 0; +} + +static int convert2days(u16 *days, struct rtc_time *tm) +{ + int i; + *days = 0; + + /* epoch == 1900 */ + if (tm->tm_year < 100 || tm->tm_year > 199) + return -EINVAL; + + for (i = 2000; i < 1900 + tm->tm_year; i++) + *days += rtc_year_days(1, 12, i); + + *days += rtc_year_days(tm->tm_mday, tm->tm_mon, 1900 + tm->tm_year); + + return 0; +} + +static int davinci_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev); + u16 days = 0; + u8 day0, day1; + unsigned long flags; + + spin_lock_irqsave(&davinci_rtc_lock, flags); + + davinci_rtcss_calendar_wait(davinci_rtc); + tm->tm_sec = bcd2bin(rtcss_read(davinci_rtc, PRTCSS_RTC_SEC)); + + davinci_rtcss_calendar_wait(davinci_rtc); + tm->tm_min = bcd2bin(rtcss_read(davinci_rtc, PRTCSS_RTC_MIN)); + + davinci_rtcss_calendar_wait(davinci_rtc); + tm->tm_hour = bcd2bin(rtcss_read(davinci_rtc, PRTCSS_RTC_HOUR)); + + davinci_rtcss_calendar_wait(davinci_rtc); + day0 = rtcss_read(davinci_rtc, PRTCSS_RTC_DAY0); + + davinci_rtcss_calendar_wait(davinci_rtc); + day1 = rtcss_read(davinci_rtc, PRTCSS_RTC_DAY1); + + spin_unlock_irqrestore(&davinci_rtc_lock, flags); + + days |= day1; + days <<= 8; + days |= day0; + + if (convertfromdays(days, tm) < 0) + return -EINVAL; + + return 0; +} + +static int davinci_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev); + u16 days; + u8 rtc_cctrl; + unsigned long flags; + + if (convert2days(&days, tm) < 0) + return -EINVAL; + + spin_lock_irqsave(&davinci_rtc_lock, flags); + + davinci_rtcss_calendar_wait(davinci_rtc); + rtcss_write(davinci_rtc, bin2bcd(tm->tm_sec), PRTCSS_RTC_SEC); + + davinci_rtcss_calendar_wait(davinci_rtc); + rtcss_write(davinci_rtc, bin2bcd(tm->tm_min), PRTCSS_RTC_MIN); + + davinci_rtcss_calendar_wait(davinci_rtc); + rtcss_write(davinci_rtc, bin2bcd(tm->tm_hour), PRTCSS_RTC_HOUR); + + davinci_rtcss_calendar_wait(davinci_rtc); + rtcss_write(davinci_rtc, days & 0xFF, PRTCSS_RTC_DAY0); + + davinci_rtcss_calendar_wait(davinci_rtc); + rtcss_write(davinci_rtc, (days & 0xFF00) >> 8, PRTCSS_RTC_DAY1); + + rtc_cctrl = rtcss_read(davinci_rtc, PRTCSS_RTC_CCTRL); + rtc_cctrl |= PRTCSS_RTC_CCTRL_CAEN; + rtcss_write(davinci_rtc, rtc_cctrl, PRTCSS_RTC_CCTRL); + + spin_unlock_irqrestore(&davinci_rtc_lock, flags); + + return 0; +} + +static int davinci_rtc_alarm_irq_enable(struct device *dev, + unsigned int enabled) +{ + struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev); + unsigned long flags; + u8 rtc_cctrl = rtcss_read(davinci_rtc, PRTCSS_RTC_CCTRL); + + spin_lock_irqsave(&davinci_rtc_lock, flags); + + if (enabled) + rtc_cctrl |= PRTCSS_RTC_CCTRL_DAEN | + PRTCSS_RTC_CCTRL_HAEN | + PRTCSS_RTC_CCTRL_MAEN | + PRTCSS_RTC_CCTRL_ALMFLG | + PRTCSS_RTC_CCTRL_AIEN; + else + rtc_cctrl &= ~PRTCSS_RTC_CCTRL_AIEN; + + davinci_rtcss_calendar_wait(davinci_rtc); + rtcss_write(davinci_rtc, rtc_cctrl, PRTCSS_RTC_CCTRL); + + spin_unlock_irqrestore(&davinci_rtc_lock, flags); + + return 0; +} + +static int davinci_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) +{ + struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev); + u16 days = 0; + u8 day0, day1; + unsigned long flags; + + spin_lock_irqsave(&davinci_rtc_lock, flags); + + davinci_rtcss_calendar_wait(davinci_rtc); + alm->time.tm_min = bcd2bin(rtcss_read(davinci_rtc, PRTCSS_RTC_AMIN)); + + davinci_rtcss_calendar_wait(davinci_rtc); + alm->time.tm_hour = bcd2bin(rtcss_read(davinci_rtc, PRTCSS_RTC_AHOUR)); + + davinci_rtcss_calendar_wait(davinci_rtc); + day0 = rtcss_read(davinci_rtc, PRTCSS_RTC_ADAY0); + + davinci_rtcss_calendar_wait(davinci_rtc); + day1 = rtcss_read(davinci_rtc, PRTCSS_RTC_ADAY1); + + spin_unlock_irqrestore(&davinci_rtc_lock, flags); + days |= day1; + days <<= 8; + days |= day0; + + if (convertfromdays(days, &alm->time) < 0) + return -EINVAL; + + alm->pending = !!(rtcss_read(davinci_rtc, + PRTCSS_RTC_CCTRL) & + PRTCSS_RTC_CCTRL_AIEN); + alm->enabled = alm->pending && device_may_wakeup(dev); + + return 0; +} + +static int davinci_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) +{ + struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev); + unsigned long flags; + u16 days; + + if (alm->time.tm_mday <= 0 && alm->time.tm_mon < 0 + && alm->time.tm_year < 0) { + struct rtc_time tm; + unsigned long now, then; + + davinci_rtc_read_time(dev, &tm); + rtc_tm_to_time(&tm, &now); + + alm->time.tm_mday = tm.tm_mday; + alm->time.tm_mon = tm.tm_mon; + alm->time.tm_year = tm.tm_year; + rtc_tm_to_time(&alm->time, &then); + + if (then < now) { + rtc_time_to_tm(now + 24 * 60 * 60, &tm); + alm->time.tm_mday = tm.tm_mday; + alm->time.tm_mon = tm.tm_mon; + alm->time.tm_year = tm.tm_year; + } + } + + if (convert2days(&days, &alm->time) < 0) + return -EINVAL; + + spin_lock_irqsave(&davinci_rtc_lock, flags); + + davinci_rtcss_calendar_wait(davinci_rtc); + rtcss_write(davinci_rtc, bin2bcd(alm->time.tm_min), PRTCSS_RTC_AMIN); + + davinci_rtcss_calendar_wait(davinci_rtc); + rtcss_write(davinci_rtc, bin2bcd(alm->time.tm_hour), PRTCSS_RTC_AHOUR); + + davinci_rtcss_calendar_wait(davinci_rtc); + rtcss_write(davinci_rtc, days & 0xFF, PRTCSS_RTC_ADAY0); + + davinci_rtcss_calendar_wait(davinci_rtc); + rtcss_write(davinci_rtc, (days & 0xFF00) >> 8, PRTCSS_RTC_ADAY1); + + spin_unlock_irqrestore(&davinci_rtc_lock, flags); + + return 0; +} + +static int davinci_rtc_irq_set_state(struct device *dev, int enabled) +{ + struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev); + unsigned long flags; + u8 rtc_ctrl; + + spin_lock_irqsave(&davinci_rtc_lock, flags); + + rtc_ctrl = rtcss_read(davinci_rtc, PRTCSS_RTC_CTRL); + + if (enabled) { + while (rtcss_read(davinci_rtc, PRTCSS_RTC_CTRL) + & PRTCSS_RTC_CTRL_WDTBUS) + cpu_relax(); + + rtc_ctrl |= PRTCSS_RTC_CTRL_TE; + rtcss_write(davinci_rtc, rtc_ctrl, PRTCSS_RTC_CTRL); + + rtcss_write(davinci_rtc, 0x0, PRTCSS_RTC_CLKC_CNT); + + rtc_ctrl |= PRTCSS_RTC_CTRL_TIEN | + PRTCSS_RTC_CTRL_TMMD | + PRTCSS_RTC_CTRL_TMRFLG; + } else + rtc_ctrl &= ~PRTCSS_RTC_CTRL_TIEN; + + rtcss_write(davinci_rtc, rtc_ctrl, PRTCSS_RTC_CTRL); + + spin_unlock_irqrestore(&davinci_rtc_lock, flags); + + return 0; +} + +static int davinci_rtc_irq_set_freq(struct device *dev, int freq) +{ + struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev); + unsigned long flags; + u16 tmr_counter = (0x8000 >> (ffs(freq) - 1)); + + spin_lock_irqsave(&davinci_rtc_lock, flags); + + rtcss_write(davinci_rtc, tmr_counter & 0xFF, PRTCSS_RTC_TMR0); + rtcss_write(davinci_rtc, (tmr_counter & 0xFF00) >> 8, PRTCSS_RTC_TMR1); + + spin_unlock_irqrestore(&davinci_rtc_lock, flags); + + return 0; +} + +static struct rtc_class_ops davinci_rtc_ops = { + .ioctl = davinci_rtc_ioctl, + .read_time = davinci_rtc_read_time, + .set_time = davinci_rtc_set_time, + .alarm_irq_enable = davinci_rtc_alarm_irq_enable, + .read_alarm = davinci_rtc_read_alarm, + .set_alarm = davinci_rtc_set_alarm, + .irq_set_state = davinci_rtc_irq_set_state, + .irq_set_freq = davinci_rtc_irq_set_freq, +}; + +static int __init davinci_rtc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct davinci_rtc *davinci_rtc; + struct resource *res, *mem; + int ret = 0; + + davinci_rtc = kzalloc(sizeof(struct davinci_rtc), GFP_KERNEL); + if (!davinci_rtc) { + dev_dbg(dev, "could not allocate memory for private data\n"); + return -ENOMEM; + } + + davinci_rtc->irq = platform_get_irq(pdev, 0); + if (davinci_rtc->irq < 0) { + dev_err(dev, "no RTC irq\n"); + ret = davinci_rtc->irq; + goto fail1; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "no mem resource\n"); + ret = -EINVAL; + goto fail1; + } + + davinci_rtc->pbase = res->start; + davinci_rtc->base_size = resource_size(res); + + mem = request_mem_region(davinci_rtc->pbase, davinci_rtc->base_size, + pdev->name); + if (!mem) { + dev_err(dev, "RTC registers at %08x are not free\n", + davinci_rtc->pbase); + ret = -EBUSY; + goto fail1; + } + + davinci_rtc->base = ioremap(davinci_rtc->pbase, davinci_rtc->base_size); + if (!davinci_rtc->base) { + dev_err(dev, "unable to ioremap MEM resource\n"); + ret = -ENOMEM; + goto fail2; + } + + davinci_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, + &davinci_rtc_ops, THIS_MODULE); + if (IS_ERR(davinci_rtc->rtc)) { + dev_err(dev, "unable to register RTC device, err %ld\n", + PTR_ERR(davinci_rtc->rtc)); + goto fail3; + } + + rtcif_write(davinci_rtc, PRTCIF_INTFLG_RTCSS, PRTCIF_INTFLG); + rtcif_write(davinci_rtc, 0, PRTCIF_INTEN); + rtcss_write(davinci_rtc, 0, PRTCSS_RTC_INTC_EXTENA1); + + rtcss_write(davinci_rtc, 0, PRTCSS_RTC_CTRL); + rtcss_write(davinci_rtc, 0, PRTCSS_RTC_CCTRL); + + ret = request_irq(davinci_rtc->irq, davinci_rtc_interrupt, + IRQF_DISABLED, "davinci_rtc", davinci_rtc); + if (ret < 0) { + dev_err(dev, "unable to register davinci RTC interrupt\n"); + goto fail4; + } + + /* Enable interrupts */ + rtcif_write(davinci_rtc, PRTCIF_INTEN_RTCSS, PRTCIF_INTEN); + rtcss_write(davinci_rtc, PRTCSS_RTC_INTC_EXTENA1_MASK, + PRTCSS_RTC_INTC_EXTENA1); + + rtcss_write(davinci_rtc, PRTCSS_RTC_CCTRL_CAEN, PRTCSS_RTC_CCTRL); + + platform_set_drvdata(pdev, davinci_rtc); + + device_init_wakeup(&pdev->dev, 0); + + return 0; + +fail4: + rtc_device_unregister(davinci_rtc->rtc); +fail3: + iounmap(davinci_rtc->base); +fail2: + release_mem_region(davinci_rtc->pbase, davinci_rtc->base_size); +fail1: + kfree(davinci_rtc); + + return ret; +} + +static int __devexit davinci_rtc_remove(struct platform_device *pdev) +{ + struct davinci_rtc *davinci_rtc = platform_get_drvdata(pdev); + + device_init_wakeup(&pdev->dev, 0); + + rtcif_write(davinci_rtc, 0, PRTCIF_INTEN); + + free_irq(davinci_rtc->irq, davinci_rtc); + + rtc_device_unregister(davinci_rtc->rtc); + + iounmap(davinci_rtc->base); + release_mem_region(davinci_rtc->pbase, davinci_rtc->base_size); + + platform_set_drvdata(pdev, NULL); + + kfree(davinci_rtc); + + return 0; +} + +static struct platform_driver davinci_rtc_driver = { + .probe = davinci_rtc_probe, + .remove = __devexit_p(davinci_rtc_remove), + .driver = { + .name = "rtc_davinci", + .owner = THIS_MODULE, + }, +}; + +static int __init rtc_init(void) +{ + return platform_driver_probe(&davinci_rtc_driver, davinci_rtc_probe); +} +module_init(rtc_init); + +static void __exit rtc_exit(void) +{ + platform_driver_unregister(&davinci_rtc_driver); +} +module_exit(rtc_exit); + +MODULE_AUTHOR("Miguel Aguilar "); +MODULE_DESCRIPTION("Texas Instruments DaVinci PRTC Driver"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 9c0a342c45b2d98209ac473ea7a429ddd5c1b473 Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Sun, 7 Mar 2010 18:05:54 +0530 Subject: rtc: omap: let device wakeup capability be configured from chip init logic The rtc-omap driver currently hardcodes the RTC wakeup capability to be "not capable". While this seems to be true for existing OMAP1 boards which are not wired for this, the DA850/OMAP-L138 SoC, the RTC can always be wake up source from its "deep sleep" mode. This patch lets the wakeup capability to be set from platform data and does not override the setting from the driver. For DA850/OMAP-L138, this is done from arch/arm/mach-davinci/devices-da8xx.c:da8xx_register_rtc() Note that this patch does not change the behavior on any existing OMAP1 board since the platform device registration sets the wakeup capability to 0 by default. Signed-off-by: Sekhar Nori Signed-off-by: Kevin Hilman diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index 64d9727..73377b0 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -34,7 +34,8 @@ * Board-specific wiring options include using split power mode with * RTC_OFF_NOFF used as the reset signal (so the RTC won't be reset), * and wiring RTC_WAKE_INT (so the RTC alarm can wake the system from - * low power modes). See the BOARD-SPECIFIC CUSTOMIZATION comment. + * low power modes) for OMAP1 boards (OMAP-L138 has this built into + * the SoC). See the BOARD-SPECIFIC CUSTOMIZATION comment. */ #define OMAP_RTC_BASE 0xfffb4800 @@ -401,16 +402,17 @@ static int __init omap_rtc_probe(struct platform_device *pdev) /* BOARD-SPECIFIC CUSTOMIZATION CAN GO HERE: * - * - Boards wired so that RTC_WAKE_INT does something, and muxed - * right (W13_1610_RTC_WAKE_INT is the default after chip reset), - * should initialize the device wakeup flag appropriately. + * - Device wake-up capability setting should come through chip + * init logic. OMAP1 boards should initialize the "wakeup capable" + * flag in the platform device if the board is wired right for + * being woken up by RTC alarm. For OMAP-L138, this capability + * is built into the SoC by the "Deep Sleep" capability. * * - Boards wired so RTC_ON_nOFF is used as the reset signal, * rather than nPWRON_RESET, should forcibly enable split * power mode. (Some chip errata report that RTC_CTRL_SPLIT * is write-only, and always reads as zero...) */ - device_init_wakeup(&pdev->dev, 0); if (new_ctrl & (u8) OMAP_RTC_CTRL_SPLIT) pr_info("%s: split power mode\n", pdev->name); -- cgit v0.10.2 From b722049d7e60356fe04bcac6065a7c8b1c64c06f Mon Sep 17 00:00:00 2001 From: Cyril Chemparathy Date: Thu, 25 Mar 2010 17:43:44 -0400 Subject: Davinci: allow SOCs based on other ARM CPUs Preliminary modification prior to adding support for TNETV107X based on ARM1176. This change allows for CPUs other than ARM926T to be used for Davinci derivative SoCs. Existing devices (DA8x and DMx) operate unchanged. Signed-off-by: Cyril Chemparathy Signed-off-by: Kevin Hilman diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 92622eb..1151d1a 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -776,7 +776,6 @@ config ARCH_NOMADIK config ARCH_DAVINCI bool "TI DaVinci" - select CPU_ARM926T select GENERIC_TIME select GENERIC_CLOCKEVENTS select GENERIC_GPIO diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index 0ebe185..0316e20 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig @@ -7,6 +7,7 @@ config CP_INTC bool config ARCH_DAVINCI_DMx + select CPU_ARM926T bool menu "TI DaVinci Implementations" @@ -41,6 +42,7 @@ config ARCH_DAVINCI_DA850 select ARCH_HAS_CPUFREQ config ARCH_DAVINCI_DA8XX + select CPU_ARM926T bool config ARCH_DAVINCI_DM365 -- cgit v0.10.2 From 8ca2e597fc8f3337cef1f8febab482fe8c52b004 Mon Sep 17 00:00:00 2001 From: Cyril Chemparathy Date: Thu, 25 Mar 2010 17:43:45 -0400 Subject: Davinci: enable timer clock before use timer_init() programs timer64 hardware. The module should ideally be brought out of reset before this happens. Signed-off-by: Cyril Chemparathy Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/time.c b/arch/arm/mach-davinci/time.c index 9e0b106..b21f763 100644 --- a/arch/arm/mach-davinci/time.c +++ b/arch/arm/mach-davinci/time.c @@ -361,13 +361,13 @@ static void __init davinci_timer_init(void) } } - /* init timer hw */ - timer_init(); - timer_clk = clk_get(NULL, "timer0"); BUG_ON(IS_ERR(timer_clk)); clk_enable(timer_clk); + /* init timer hw */ + timer_init(); + davinci_clock_tick_rate = clk_get_rate(timer_clk); /* setup clocksource */ -- cgit v0.10.2 From 449ef7f6a9c732657938b222f8804d3e34a3603e Mon Sep 17 00:00:00 2001 From: Cyril Chemparathy Date: Thu, 25 Mar 2010 17:43:46 -0400 Subject: Davinci: cpintc host map configuration Host map configuration instructs the interrupt controller to route interrupt channels to FIQ or IRQ lines. Currently, DA8xx family of devices leave these registers at their reset-default values. TNETV107X however does not have sane reset defaults, and therefore this architecture needs to reconfigure the host-map such that channels 0 and 1 go to FIQ, and the remaining channels raise IRQs. This patch adds an optional host map argument to cp_intc_init() for this. Signed-off-by: Cyril Chemparathy Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c index ea293b8..db5ac0f 100644 --- a/arch/arm/mach-davinci/board-da830-evm.c +++ b/arch/arm/mach-davinci/board-da830-evm.c @@ -569,7 +569,7 @@ static __init void da830_evm_irq_init(void) struct davinci_soc_info *soc_info = &davinci_soc_info; cp_intc_init((void __iomem *)DA8XX_CP_INTC_VIRT, DA830_N_CP_INTC_IRQ, - soc_info->intc_irq_prios); + soc_info->intc_irq_prios, NULL); } static void __init da830_evm_map_io(void) diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c index 411284d..ef691ae 100644 --- a/arch/arm/mach-davinci/board-da850-evm.c +++ b/arch/arm/mach-davinci/board-da850-evm.c @@ -741,7 +741,7 @@ static __init void da850_evm_irq_init(void) struct davinci_soc_info *soc_info = &davinci_soc_info; cp_intc_init((void __iomem *)DA8XX_CP_INTC_VIRT, DA850_N_CP_INTC_IRQ, - soc_info->intc_irq_prios); + soc_info->intc_irq_prios, NULL); } static void __init da850_evm_map_io(void) diff --git a/arch/arm/mach-davinci/cp_intc.c b/arch/arm/mach-davinci/cp_intc.c index 37311d1..2a8d26e 100644 --- a/arch/arm/mach-davinci/cp_intc.c +++ b/arch/arm/mach-davinci/cp_intc.c @@ -101,7 +101,7 @@ static struct irq_chip cp_intc_irq_chip = { }; void __init cp_intc_init(void __iomem *base, unsigned short num_irq, - u8 *irq_prio) + u8 *irq_prio, u32 *host_map) { unsigned num_reg = BITS_TO_LONGS(num_irq); int i; @@ -157,6 +157,10 @@ void __init cp_intc_init(void __iomem *base, unsigned short num_irq, cp_intc_write(0x0f0f0f0f, CP_INTC_CHAN_MAP(i)); } + if (host_map) + for (i = 0; host_map[i] != -1; i++) + cp_intc_write(host_map[i], CP_INTC_HOST_MAP(i)); + /* Set up genirq dispatching for cp_intc */ for (i = 0; i < num_irq; i++) { set_irq_chip(i, &cp_intc_irq_chip); diff --git a/arch/arm/mach-davinci/include/mach/cp_intc.h b/arch/arm/mach-davinci/include/mach/cp_intc.h index c4d27ee..121b114 100644 --- a/arch/arm/mach-davinci/include/mach/cp_intc.h +++ b/arch/arm/mach-davinci/include/mach/cp_intc.h @@ -52,6 +52,6 @@ #define CP_INTC_VECTOR_ADDR(n) (0x2000 + (n << 2)) void __init cp_intc_init(void __iomem *base, unsigned short num_irq, - u8 *irq_prio); + u8 *irq_prio, u32 *host_map); #endif /* __ASM_HARDWARE_CP_INTC_H */ -- cgit v0.10.2 From 52958be3ad6e2b72a5943718f339ed4e11685739 Mon Sep 17 00:00:00 2001 From: Cyril Chemparathy Date: Thu, 25 Mar 2010 17:43:47 -0400 Subject: Davinci: support LPSC SwRstDisable state The current clock control code always gates the clock (PSC state Disable = 2) on clk_disable(). Some on-chip peripherals (e.g. LCD controller on TNETV107X) need to be put into SwRstDisable = 0 on clock disable, to maintain hardware sanity. This patch extends the davinci_psc_config() arguments to pass in the desired module state instead of a boolean enable/disable. Further, clk_disable() now checks for the PSC_SWRSTDISABLE clk flag before selecting the target state. Signed-off-by: Cyril Chemparathy Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c index 058c77f..5de60ae 100644 --- a/arch/arm/mach-davinci/clock.c +++ b/arch/arm/mach-davinci/clock.c @@ -43,7 +43,8 @@ static void __clk_enable(struct clk *clk) if (clk->parent) __clk_enable(clk->parent); if (clk->usecount++ == 0 && (clk->flags & CLK_PSC)) - davinci_psc_config(psc_domain(clk), clk->gpsc, clk->lpsc, 1); + davinci_psc_config(psc_domain(clk), clk->gpsc, clk->lpsc, + PSC_STATE_ENABLE); } static void __clk_disable(struct clk *clk) @@ -52,7 +53,9 @@ static void __clk_disable(struct clk *clk) return; if (--clk->usecount == 0 && !(clk->flags & CLK_PLL) && (clk->flags & CLK_PSC)) - davinci_psc_config(psc_domain(clk), clk->gpsc, clk->lpsc, 0); + davinci_psc_config(psc_domain(clk), clk->gpsc, clk->lpsc, + (clk->flags & PSC_SWRSTDISABLE) ? + PSC_STATE_SWRSTDISABLE : PSC_STATE_DISABLE); if (clk->parent) __clk_disable(clk->parent); } @@ -234,7 +237,10 @@ static int __init clk_disable_unused(void) continue; pr_info("Clocks: disable unused %s\n", ck->name); - davinci_psc_config(psc_domain(ck), ck->gpsc, ck->lpsc, 0); + + davinci_psc_config(psc_domain(ck), ck->gpsc, ck->lpsc, + (ck->flags & PSC_SWRSTDISABLE) ? + PSC_STATE_SWRSTDISABLE : PSC_STATE_DISABLE); } spin_unlock_irq(&clockfw_lock); diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h index aa0a611..53a0f7b 100644 --- a/arch/arm/mach-davinci/clock.h +++ b/arch/arm/mach-davinci/clock.h @@ -101,10 +101,11 @@ struct clk { /* Clock flags: SoC-specific flags start at BIT(16) */ #define ALWAYS_ENABLED BIT(1) -#define CLK_PSC BIT(2) -#define PSC_DSP BIT(3) /* PSC uses DSP domain, not ARM */ +#define CLK_PSC BIT(2) +#define PSC_DSP BIT(3) /* PSC uses DSP domain, not ARM */ #define CLK_PLL BIT(4) /* PLL-derived clock */ -#define PRE_PLL BIT(5) /* source is before PLL mult/div */ +#define PRE_PLL BIT(5) /* source is before PLL mult/div */ +#define PSC_SWRSTDISABLE BIT(6) /* Disable state is SwRstDisable */ #define CLK(dev, con, ck) \ { \ diff --git a/arch/arm/mach-davinci/include/mach/psc.h b/arch/arm/mach-davinci/include/mach/psc.h index 651f6d8..7dd2962 100644 --- a/arch/arm/mach-davinci/include/mach/psc.h +++ b/arch/arm/mach-davinci/include/mach/psc.h @@ -189,13 +189,19 @@ #define MDSTAT 0x800 #define MDCTL 0xA00 +/* PSC module states */ +#define PSC_STATE_SWRSTDISABLE 0 +#define PSC_STATE_SYNCRST 1 +#define PSC_STATE_DISABLE 2 +#define PSC_STATE_ENABLE 3 + #define MDSTAT_STATE_MASK 0x1f #ifndef __ASSEMBLER__ extern int davinci_psc_is_clk_active(unsigned int ctlr, unsigned int id); extern void davinci_psc_config(unsigned int domain, unsigned int ctlr, - unsigned int id, char enable); + unsigned int id, u32 next_state); #endif diff --git a/arch/arm/mach-davinci/psc.c b/arch/arm/mach-davinci/psc.c index adf6b5c..d7cb438 100644 --- a/arch/arm/mach-davinci/psc.c +++ b/arch/arm/mach-davinci/psc.c @@ -47,12 +47,11 @@ int __init davinci_psc_is_clk_active(unsigned int ctlr, unsigned int id) /* Enable or disable a PSC domain */ void davinci_psc_config(unsigned int domain, unsigned int ctlr, - unsigned int id, char enable) + unsigned int id, u32 next_state) { u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl; void __iomem *psc_base; struct davinci_soc_info *soc_info = &davinci_soc_info; - u32 next_state = enable ? 0x3 : 0x2; /* 0x3 enables, 0x2 disables */ if (!soc_info->psc_bases || (ctlr >= soc_info->psc_bases_num)) { pr_warning("PSC: Bad psc data: 0x%x[%d]\n", -- cgit v0.10.2 From 3821d10a538ac9d750987badd404c8f860ffa774 Mon Sep 17 00:00:00 2001 From: Cyril Chemparathy Date: Thu, 25 Mar 2010 17:43:48 -0400 Subject: Davinci: promote da8xx_pinmux_setup() Rename da8xx_pinmux_setup() to davinci_cfg_reg_list() and promote it for use in other SOCs that may need the ability to configure multiple pins in one shot. Signed-off-by: Cyril Chemparathy Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c index db5ac0f..9257056 100644 --- a/arch/arm/mach-davinci/board-da830-evm.c +++ b/arch/arm/mach-davinci/board-da830-evm.c @@ -157,7 +157,7 @@ static __init void da830_evm_usb_init(void) __func__, ret); } - ret = da8xx_pinmux_setup(da830_evm_usb11_pins); + ret = davinci_cfg_reg_list(da830_evm_usb11_pins); if (ret) { pr_warning("%s: USB 1.1 PinMux setup failed: %d\n", __func__, ret); @@ -254,7 +254,7 @@ static inline void da830_evm_init_mmc(void) { int ret; - ret = da8xx_pinmux_setup(da830_evm_mmc_sd_pins); + ret = davinci_cfg_reg_list(da830_evm_mmc_sd_pins); if (ret) { pr_warning("da830_evm_init: mmc/sd mux setup failed: %d\n", ret); @@ -407,7 +407,7 @@ static inline void da830_evm_init_nand(int mux_mode) return; } - ret = da8xx_pinmux_setup(da830_evm_emif25_pins); + ret = davinci_cfg_reg_list(da830_evm_emif25_pins); if (ret) pr_warning("da830_evm_init: emif25 mux setup failed: %d\n", ret); @@ -427,7 +427,7 @@ static inline void da830_evm_init_lcdc(int mux_mode) { int ret; - ret = da8xx_pinmux_setup(da830_lcdcntl_pins); + ret = davinci_cfg_reg_list(da830_lcdcntl_pins); if (ret) pr_warning("da830_evm_init: lcdcntl mux setup failed: %d\n", ret); @@ -507,7 +507,7 @@ static __init void da830_evm_init(void) pr_warning("da830_evm_init: edma registration failed: %d\n", ret); - ret = da8xx_pinmux_setup(da830_i2c0_pins); + ret = davinci_cfg_reg_list(da830_i2c0_pins); if (ret) pr_warning("da830_evm_init: i2c0 mux setup failed: %d\n", ret); @@ -523,7 +523,7 @@ static __init void da830_evm_init(void) soc_info->emac_pdata->mdio_max_freq = DA830_EVM_MDIO_FREQUENCY; soc_info->emac_pdata->rmii_en = 1; - ret = da8xx_pinmux_setup(da830_cpgmac_pins); + ret = davinci_cfg_reg_list(da830_cpgmac_pins); if (ret) pr_warning("da830_evm_init: cpgmac mux setup failed: %d\n", ret); @@ -542,7 +542,7 @@ static __init void da830_evm_init(void) i2c_register_board_info(1, da830_evm_i2c_devices, ARRAY_SIZE(da830_evm_i2c_devices)); - ret = da8xx_pinmux_setup(da830_evm_mcasp1_pins); + ret = davinci_cfg_reg_list(da830_evm_mcasp1_pins); if (ret) pr_warning("da830_evm_init: mcasp1 mux setup failed: %d\n", ret); diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c index ef691ae..6c137e0 100644 --- a/arch/arm/mach-davinci/board-da850-evm.c +++ b/arch/arm/mach-davinci/board-da850-evm.c @@ -206,12 +206,12 @@ static __init void da850_evm_setup_nor_nand(void) int ret = 0; if (ui_card_detected & !HAS_MMC) { - ret = da8xx_pinmux_setup(da850_nand_pins); + ret = davinci_cfg_reg_list(da850_nand_pins); if (ret) pr_warning("da850_evm_init: nand mux setup failed: " "%d\n", ret); - ret = da8xx_pinmux_setup(da850_nor_pins); + ret = davinci_cfg_reg_list(da850_nor_pins); if (ret) pr_warning("da850_evm_init: nor mux setup failed: %d\n", ret); @@ -568,12 +568,12 @@ static int __init da850_evm_config_emac(void) if (rmii_en) { val |= BIT(8); - ret = da8xx_pinmux_setup(da850_rmii_pins); + ret = davinci_cfg_reg_list(da850_rmii_pins); pr_info("EMAC: RMII PHY configured, MII PHY will not be" " functional\n"); } else { val &= ~BIT(8); - ret = da8xx_pinmux_setup(da850_cpgmac_pins); + ret = davinci_cfg_reg_list(da850_cpgmac_pins); pr_info("EMAC: MII PHY configured, RMII PHY will not be" " functional\n"); } @@ -626,7 +626,7 @@ static __init void da850_evm_init(void) pr_warning("da850_evm_init: edma registration failed: %d\n", ret); - ret = da8xx_pinmux_setup(da850_i2c0_pins); + ret = davinci_cfg_reg_list(da850_i2c0_pins); if (ret) pr_warning("da850_evm_init: i2c0 mux setup failed: %d\n", ret); @@ -643,7 +643,7 @@ static __init void da850_evm_init(void) ret); if (HAS_MMC) { - ret = da8xx_pinmux_setup(da850_mmcsd0_pins); + ret = davinci_cfg_reg_list(da850_mmcsd0_pins); if (ret) pr_warning("da850_evm_init: mmcsd0 mux setup failed:" " %d\n", ret); @@ -679,20 +679,20 @@ static __init void da850_evm_init(void) __raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30); __raw_writel(0, IO_ADDRESS(DA8XX_UART0_BASE) + 0x30); - ret = da8xx_pinmux_setup(da850_mcasp_pins); + ret = davinci_cfg_reg_list(da850_mcasp_pins); if (ret) pr_warning("da850_evm_init: mcasp mux setup failed: %d\n", ret); da8xx_register_mcasp(0, &da850_evm_snd_data); - ret = da8xx_pinmux_setup(da850_lcdcntl_pins); + ret = davinci_cfg_reg_list(da850_lcdcntl_pins); if (ret) pr_warning("da850_evm_init: lcdcntl mux setup failed: %d\n", ret); /* Handle board specific muxing for LCD here */ - ret = da8xx_pinmux_setup(da850_evm_lcdc_pins); + ret = davinci_cfg_reg_list(da850_evm_lcdc_pins); if (ret) pr_warning("da850_evm_init: evm specific lcd mux setup " "failed: %d\n", ret); diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h index 03acfd3..33471c9 100644 --- a/arch/arm/mach-davinci/include/mach/da8xx.h +++ b/arch/arm/mach-davinci/include/mach/da8xx.h @@ -146,10 +146,4 @@ extern const short da850_mmcsd0_pins[]; extern const short da850_nand_pins[]; extern const short da850_nor_pins[]; -#ifdef CONFIG_DAVINCI_MUX -int da8xx_pinmux_setup(const short pins[]); -#else -static inline int da8xx_pinmux_setup(const short pins[]) { return 0; } -#endif - #endif /* __ASM_ARCH_DAVINCI_DA8XX_H */ diff --git a/arch/arm/mach-davinci/include/mach/mux.h b/arch/arm/mach-davinci/include/mach/mux.h index 2a68c1d..48888db 100644 --- a/arch/arm/mach-davinci/include/mach/mux.h +++ b/arch/arm/mach-davinci/include/mach/mux.h @@ -907,9 +907,14 @@ enum davinci_da850_index { #ifdef CONFIG_DAVINCI_MUX /* setup pin muxing */ extern int davinci_cfg_reg(unsigned long reg_cfg); +extern int davinci_cfg_reg_list(const short pins[]); #else /* boot loader does it all (no warnings from CONFIG_DAVINCI_MUX_WARNINGS) */ static inline int davinci_cfg_reg(unsigned long reg_cfg) { return 0; } +static inline int davinci_cfg_reg_list(const short pins[]) +{ + return 0; +} #endif #endif /* __INC_MACH_MUX_H */ diff --git a/arch/arm/mach-davinci/mux.c b/arch/arm/mach-davinci/mux.c index c942c89..e9d530a 100644 --- a/arch/arm/mach-davinci/mux.c +++ b/arch/arm/mach-davinci/mux.c @@ -21,7 +21,6 @@ #include #include -#include /* * Sets the DAVINCI MUX register based on the table @@ -92,7 +91,7 @@ int __init_or_module davinci_cfg_reg(const unsigned long index) } EXPORT_SYMBOL(davinci_cfg_reg); -int da8xx_pinmux_setup(const short pins[]) +int __init_or_module davinci_cfg_reg_list(const short pins[]) { int i, error = -EINVAL; -- cgit v0.10.2 From 0e23f71d60bdb4c202402c5f5c709deacc5d0f17 Mon Sep 17 00:00:00 2001 From: Cyril Chemparathy Date: Thu, 25 Mar 2010 17:43:49 -0400 Subject: Davinci: tnetv107x pin list Added list of muxed pins on the tnetv107x SOC. Signed-off-by: Cyril Chemparathy Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/include/mach/mux.h b/arch/arm/mach-davinci/include/mach/mux.h index 48888db..8638903 100644 --- a/arch/arm/mach-davinci/include/mach/mux.h +++ b/arch/arm/mach-davinci/include/mach/mux.h @@ -904,6 +904,275 @@ enum davinci_da850_index { DA850_RTC_ALARM, }; +enum davinci_tnetv107x_index { + TNETV107X_ASR_A00, + TNETV107X_GPIO32, + TNETV107X_ASR_A01, + TNETV107X_GPIO33, + TNETV107X_ASR_A02, + TNETV107X_GPIO34, + TNETV107X_ASR_A03, + TNETV107X_GPIO35, + TNETV107X_ASR_A04, + TNETV107X_GPIO36, + TNETV107X_ASR_A05, + TNETV107X_GPIO37, + TNETV107X_ASR_A06, + TNETV107X_GPIO38, + TNETV107X_ASR_A07, + TNETV107X_GPIO39, + TNETV107X_ASR_A08, + TNETV107X_GPIO40, + TNETV107X_ASR_A09, + TNETV107X_GPIO41, + TNETV107X_ASR_A10, + TNETV107X_GPIO42, + TNETV107X_ASR_A11, + TNETV107X_BOOT_STRP_0, + TNETV107X_ASR_A12, + TNETV107X_BOOT_STRP_1, + TNETV107X_ASR_A13, + TNETV107X_GPIO43, + TNETV107X_ASR_A14, + TNETV107X_GPIO44, + TNETV107X_ASR_A15, + TNETV107X_GPIO45, + TNETV107X_ASR_A16, + TNETV107X_GPIO46, + TNETV107X_ASR_A17, + TNETV107X_GPIO47, + TNETV107X_ASR_A18, + TNETV107X_GPIO48, + TNETV107X_SDIO1_DATA3_0, + TNETV107X_ASR_A19, + TNETV107X_GPIO49, + TNETV107X_SDIO1_DATA2_0, + TNETV107X_ASR_A20, + TNETV107X_GPIO50, + TNETV107X_SDIO1_DATA1_0, + TNETV107X_ASR_A21, + TNETV107X_GPIO51, + TNETV107X_SDIO1_DATA0_0, + TNETV107X_ASR_A22, + TNETV107X_GPIO52, + TNETV107X_SDIO1_CMD_0, + TNETV107X_ASR_A23, + TNETV107X_GPIO53, + TNETV107X_SDIO1_CLK_0, + TNETV107X_ASR_BA_1, + TNETV107X_GPIO54, + TNETV107X_SYS_PLL_CLK, + TNETV107X_ASR_CS0, + TNETV107X_ASR_CS1, + TNETV107X_ASR_CS2, + TNETV107X_TDM_PLL_CLK, + TNETV107X_ASR_CS3, + TNETV107X_ETH_PHY_CLK, + TNETV107X_ASR_D00, + TNETV107X_GPIO55, + TNETV107X_ASR_D01, + TNETV107X_GPIO56, + TNETV107X_ASR_D02, + TNETV107X_GPIO57, + TNETV107X_ASR_D03, + TNETV107X_GPIO58, + TNETV107X_ASR_D04, + TNETV107X_GPIO59_0, + TNETV107X_ASR_D05, + TNETV107X_GPIO60_0, + TNETV107X_ASR_D06, + TNETV107X_GPIO61_0, + TNETV107X_ASR_D07, + TNETV107X_GPIO62_0, + TNETV107X_ASR_D08, + TNETV107X_GPIO63_0, + TNETV107X_ASR_D09, + TNETV107X_GPIO64_0, + TNETV107X_ASR_D10, + TNETV107X_SDIO1_DATA3_1, + TNETV107X_ASR_D11, + TNETV107X_SDIO1_DATA2_1, + TNETV107X_ASR_D12, + TNETV107X_SDIO1_DATA1_1, + TNETV107X_ASR_D13, + TNETV107X_SDIO1_DATA0_1, + TNETV107X_ASR_D14, + TNETV107X_SDIO1_CMD_1, + TNETV107X_ASR_D15, + TNETV107X_SDIO1_CLK_1, + TNETV107X_ASR_OE, + TNETV107X_BOOT_STRP_2, + TNETV107X_ASR_RNW, + TNETV107X_GPIO29_0, + TNETV107X_ASR_WAIT, + TNETV107X_GPIO30_0, + TNETV107X_ASR_WE, + TNETV107X_BOOT_STRP_3, + TNETV107X_ASR_WE_DQM0, + TNETV107X_GPIO31, + TNETV107X_LCD_PD17_0, + TNETV107X_ASR_WE_DQM1, + TNETV107X_ASR_BA0_0, + TNETV107X_VLYNQ_CLK, + TNETV107X_GPIO14, + TNETV107X_LCD_PD19_0, + TNETV107X_VLYNQ_RXD0, + TNETV107X_GPIO15, + TNETV107X_LCD_PD20_0, + TNETV107X_VLYNQ_RXD1, + TNETV107X_GPIO16, + TNETV107X_LCD_PD21_0, + TNETV107X_VLYNQ_TXD0, + TNETV107X_GPIO17, + TNETV107X_LCD_PD22_0, + TNETV107X_VLYNQ_TXD1, + TNETV107X_GPIO18, + TNETV107X_LCD_PD23_0, + TNETV107X_SDIO0_CLK, + TNETV107X_GPIO19, + TNETV107X_SDIO0_CMD, + TNETV107X_GPIO20, + TNETV107X_SDIO0_DATA0, + TNETV107X_GPIO21, + TNETV107X_SDIO0_DATA1, + TNETV107X_GPIO22, + TNETV107X_SDIO0_DATA2, + TNETV107X_GPIO23, + TNETV107X_SDIO0_DATA3, + TNETV107X_GPIO24, + TNETV107X_EMU0, + TNETV107X_EMU1, + TNETV107X_RTCK, + TNETV107X_TRST_N, + TNETV107X_TCK, + TNETV107X_TDI, + TNETV107X_TDO, + TNETV107X_TMS, + TNETV107X_TDM1_CLK, + TNETV107X_TDM1_RX, + TNETV107X_TDM1_TX, + TNETV107X_TDM1_FS, + TNETV107X_KEYPAD_R0, + TNETV107X_KEYPAD_R1, + TNETV107X_KEYPAD_R2, + TNETV107X_KEYPAD_R3, + TNETV107X_KEYPAD_R4, + TNETV107X_KEYPAD_R5, + TNETV107X_KEYPAD_R6, + TNETV107X_GPIO12, + TNETV107X_KEYPAD_R7, + TNETV107X_GPIO10, + TNETV107X_KEYPAD_C0, + TNETV107X_KEYPAD_C1, + TNETV107X_KEYPAD_C2, + TNETV107X_KEYPAD_C3, + TNETV107X_KEYPAD_C4, + TNETV107X_KEYPAD_C5, + TNETV107X_KEYPAD_C6, + TNETV107X_GPIO13, + TNETV107X_TEST_CLK_IN, + TNETV107X_KEYPAD_C7, + TNETV107X_GPIO11, + TNETV107X_SSP0_0, + TNETV107X_SCC_DCLK, + TNETV107X_LCD_PD20_1, + TNETV107X_SSP0_1, + TNETV107X_SCC_CS_N, + TNETV107X_LCD_PD21_1, + TNETV107X_SSP0_2, + TNETV107X_SCC_D, + TNETV107X_LCD_PD22_1, + TNETV107X_SSP0_3, + TNETV107X_SCC_RESETN, + TNETV107X_LCD_PD23_1, + TNETV107X_SSP1_0, + TNETV107X_GPIO25, + TNETV107X_UART2_CTS, + TNETV107X_SSP1_1, + TNETV107X_GPIO26, + TNETV107X_UART2_RD, + TNETV107X_SSP1_2, + TNETV107X_GPIO27, + TNETV107X_UART2_RTS, + TNETV107X_SSP1_3, + TNETV107X_GPIO28, + TNETV107X_UART2_TD, + TNETV107X_UART0_CTS, + TNETV107X_UART0_RD, + TNETV107X_UART0_RTS, + TNETV107X_UART0_TD, + TNETV107X_UART1_RD, + TNETV107X_UART1_TD, + TNETV107X_LCD_AC_NCS, + TNETV107X_LCD_HSYNC_RNW, + TNETV107X_LCD_VSYNC_A0, + TNETV107X_LCD_MCLK, + TNETV107X_LCD_PD16_0, + TNETV107X_LCD_PCLK_E, + TNETV107X_LCD_PD00, + TNETV107X_LCD_PD01, + TNETV107X_LCD_PD02, + TNETV107X_LCD_PD03, + TNETV107X_LCD_PD04, + TNETV107X_LCD_PD05, + TNETV107X_LCD_PD06, + TNETV107X_LCD_PD07, + TNETV107X_LCD_PD08, + TNETV107X_GPIO59_1, + TNETV107X_LCD_PD09, + TNETV107X_GPIO60_1, + TNETV107X_LCD_PD10, + TNETV107X_ASR_BA0_1, + TNETV107X_GPIO61_1, + TNETV107X_LCD_PD11, + TNETV107X_GPIO62_1, + TNETV107X_LCD_PD12, + TNETV107X_GPIO63_1, + TNETV107X_LCD_PD13, + TNETV107X_GPIO64_1, + TNETV107X_LCD_PD14, + TNETV107X_GPIO29_1, + TNETV107X_LCD_PD15, + TNETV107X_GPIO30_1, + TNETV107X_EINT0, + TNETV107X_GPIO08, + TNETV107X_EINT1, + TNETV107X_GPIO09, + TNETV107X_GPIO00, + TNETV107X_LCD_PD20_2, + TNETV107X_TDM_CLK_IN_2, + TNETV107X_GPIO01, + TNETV107X_LCD_PD21_2, + TNETV107X_24M_CLK_OUT_1, + TNETV107X_GPIO02, + TNETV107X_LCD_PD22_2, + TNETV107X_GPIO03, + TNETV107X_LCD_PD23_2, + TNETV107X_GPIO04, + TNETV107X_LCD_PD16_1, + TNETV107X_USB0_RXERR, + TNETV107X_GPIO05, + TNETV107X_LCD_PD17_1, + TNETV107X_TDM_CLK_IN_1, + TNETV107X_GPIO06, + TNETV107X_LCD_PD18, + TNETV107X_24M_CLK_OUT_2, + TNETV107X_GPIO07, + TNETV107X_LCD_PD19_1, + TNETV107X_USB1_RXERR, + TNETV107X_ETH_PLL_CLK, + TNETV107X_MDIO, + TNETV107X_MDC, + TNETV107X_AIC_MUTE_STAT_N, + TNETV107X_TDM0_CLK, + TNETV107X_AIC_HNS_EN_N, + TNETV107X_TDM0_FS, + TNETV107X_AIC_HDS_EN_STAT_N, + TNETV107X_TDM0_TX, + TNETV107X_AIC_HNF_EN_STAT_N, + TNETV107X_TDM0_RX, +}; + #ifdef CONFIG_DAVINCI_MUX /* setup pin muxing */ extern int davinci_cfg_reg(unsigned long reg_cfg); -- cgit v0.10.2 From 7520f4eded66091b59c9aa3054c6fc8843a6c9a6 Mon Sep 17 00:00:00 2001 From: Cyril Chemparathy Date: Thu, 25 Mar 2010 17:43:50 -0400 Subject: Davinci: tnetv107x LPSC modules Added definitions for LPSC modules in the tnetv107x SOC Signed-off-by: Cyril Chemparathy Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/include/mach/psc.h b/arch/arm/mach-davinci/include/mach/psc.h index 7dd2962..983da6e 100644 --- a/arch/arm/mach-davinci/include/mach/psc.h +++ b/arch/arm/mach-davinci/include/mach/psc.h @@ -180,6 +180,53 @@ #define DA8XX_LPSC1_CR_P3_SS 26 #define DA8XX_LPSC1_L3_CBA_RAM 31 +/* TNETV107X LPSC Assignments */ +#define TNETV107X_LPSC_ARM 0 +#define TNETV107X_LPSC_GEM 1 +#define TNETV107X_LPSC_DDR2_PHY 2 +#define TNETV107X_LPSC_TPCC 3 +#define TNETV107X_LPSC_TPTC0 4 +#define TNETV107X_LPSC_TPTC1 5 +#define TNETV107X_LPSC_RAM 6 +#define TNETV107X_LPSC_MBX_LITE 7 +#define TNETV107X_LPSC_LCD 8 +#define TNETV107X_LPSC_ETHSS 9 +#define TNETV107X_LPSC_AEMIF 10 +#define TNETV107X_LPSC_CHIP_CFG 11 +#define TNETV107X_LPSC_TSC 12 +#define TNETV107X_LPSC_ROM 13 +#define TNETV107X_LPSC_UART2 14 +#define TNETV107X_LPSC_PKTSEC 15 +#define TNETV107X_LPSC_SECCTL 16 +#define TNETV107X_LPSC_KEYMGR 17 +#define TNETV107X_LPSC_KEYPAD 18 +#define TNETV107X_LPSC_GPIO 19 +#define TNETV107X_LPSC_MDIO 20 +#define TNETV107X_LPSC_SDIO0 21 +#define TNETV107X_LPSC_UART0 22 +#define TNETV107X_LPSC_UART1 23 +#define TNETV107X_LPSC_TIMER0 24 +#define TNETV107X_LPSC_TIMER1 25 +#define TNETV107X_LPSC_WDT_ARM 26 +#define TNETV107X_LPSC_WDT_DSP 27 +#define TNETV107X_LPSC_SSP 28 +#define TNETV107X_LPSC_TDM0 29 +#define TNETV107X_LPSC_VLYNQ 30 +#define TNETV107X_LPSC_MCDMA 31 +#define TNETV107X_LPSC_USB0 32 +#define TNETV107X_LPSC_TDM1 33 +#define TNETV107X_LPSC_DEBUGSS 34 +#define TNETV107X_LPSC_ETHSS_RGMII 35 +#define TNETV107X_LPSC_SYSTEM 36 +#define TNETV107X_LPSC_IMCOP 37 +#define TNETV107X_LPSC_SPARE 38 +#define TNETV107X_LPSC_SDIO1 39 +#define TNETV107X_LPSC_USB1 40 +#define TNETV107X_LPSC_USBSS 41 +#define TNETV107X_LPSC_DDR2_EMIF1_VRST 42 +#define TNETV107X_LPSC_DDR2_EMIF2_VCTL_RST 43 +#define TNETV107X_LPSC_MAX 44 + /* PSC register offsets */ #define EPCPR 0x070 #define PTCMD 0x120 -- cgit v0.10.2 From 6cc20cd8ed876ce21b558006f18d4c86f2efbdfd Mon Sep 17 00:00:00 2001 From: Cyril Chemparathy Date: Thu, 25 Mar 2010 17:43:51 -0400 Subject: Davinci: tnetv107x IRQ definitions IRQ numbers as defined for tnetv107x cp_intc. Signed-off-by: Cyril Chemparathy Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/include/mach/irqs.h b/arch/arm/mach-davinci/include/mach/irqs.h index 354af71..ec76c77 100644 --- a/arch/arm/mach-davinci/include/mach/irqs.h +++ b/arch/arm/mach-davinci/include/mach/irqs.h @@ -401,6 +401,103 @@ #define DA850_N_CP_INTC_IRQ 101 + +/* TNETV107X specific interrupts */ +#define IRQ_TNETV107X_TDM1_TXDMA 0 +#define IRQ_TNETV107X_EXT_INT_0 1 +#define IRQ_TNETV107X_EXT_INT_1 2 +#define IRQ_TNETV107X_GPIO_INT12 3 +#define IRQ_TNETV107X_GPIO_INT13 4 +#define IRQ_TNETV107X_TIMER_0_TINT12 5 +#define IRQ_TNETV107X_TIMER_1_TINT12 6 +#define IRQ_TNETV107X_UART0 7 +#define IRQ_TNETV107X_TDM1_RXDMA 8 +#define IRQ_TNETV107X_MCDMA_INT0 9 +#define IRQ_TNETV107X_MCDMA_INT1 10 +#define IRQ_TNETV107X_TPCC 11 +#define IRQ_TNETV107X_TPCC_INT0 12 +#define IRQ_TNETV107X_TPCC_INT1 13 +#define IRQ_TNETV107X_TPCC_INT2 14 +#define IRQ_TNETV107X_TPCC_INT3 15 +#define IRQ_TNETV107X_TPTC0 16 +#define IRQ_TNETV107X_TPTC1 17 +#define IRQ_TNETV107X_TIMER_0_TINT34 18 +#define IRQ_TNETV107X_ETHSS 19 +#define IRQ_TNETV107X_TIMER_1_TINT34 20 +#define IRQ_TNETV107X_DSP2ARM_INT0 21 +#define IRQ_TNETV107X_DSP2ARM_INT1 22 +#define IRQ_TNETV107X_ARM_NPMUIRQ 23 +#define IRQ_TNETV107X_USB1 24 +#define IRQ_TNETV107X_VLYNQ 25 +#define IRQ_TNETV107X_UART0_DMATX 26 +#define IRQ_TNETV107X_UART0_DMARX 27 +#define IRQ_TNETV107X_TDM1_TXMCSP 28 +#define IRQ_TNETV107X_SSP 29 +#define IRQ_TNETV107X_MCDMA_INT2 30 +#define IRQ_TNETV107X_MCDMA_INT3 31 +#define IRQ_TNETV107X_TDM_CODECIF_EOT 32 +#define IRQ_TNETV107X_IMCOP_SQR_ARM 33 +#define IRQ_TNETV107X_USB0 34 +#define IRQ_TNETV107X_USB_CDMA 35 +#define IRQ_TNETV107X_LCD 36 +#define IRQ_TNETV107X_KEYPAD 37 +#define IRQ_TNETV107X_KEYPAD_FREE 38 +#define IRQ_TNETV107X_RNG 39 +#define IRQ_TNETV107X_PKA 40 +#define IRQ_TNETV107X_TDM0_TXDMA 41 +#define IRQ_TNETV107X_TDM0_RXDMA 42 +#define IRQ_TNETV107X_TDM0_TXMCSP 43 +#define IRQ_TNETV107X_TDM0_RXMCSP 44 +#define IRQ_TNETV107X_TDM1_RXMCSP 45 +#define IRQ_TNETV107X_SDIO1 46 +#define IRQ_TNETV107X_SDIO0 47 +#define IRQ_TNETV107X_TSC 48 +#define IRQ_TNETV107X_TS 49 +#define IRQ_TNETV107X_UART1 50 +#define IRQ_TNETV107X_MBX_LITE 51 +#define IRQ_TNETV107X_GPIO_INT00 52 +#define IRQ_TNETV107X_GPIO_INT01 53 +#define IRQ_TNETV107X_GPIO_INT02 54 +#define IRQ_TNETV107X_GPIO_INT03 55 +#define IRQ_TNETV107X_UART2 56 +#define IRQ_TNETV107X_UART2_DMATX 57 +#define IRQ_TNETV107X_UART2_DMARX 58 +#define IRQ_TNETV107X_IMCOP_IMX 59 +#define IRQ_TNETV107X_IMCOP_VLCD 60 +#define IRQ_TNETV107X_AES 61 +#define IRQ_TNETV107X_DES 62 +#define IRQ_TNETV107X_SHAMD5 63 +#define IRQ_TNETV107X_TPCC_ERR 68 +#define IRQ_TNETV107X_TPCC_PROT 69 +#define IRQ_TNETV107X_TPTC0_ERR 70 +#define IRQ_TNETV107X_TPTC1_ERR 71 +#define IRQ_TNETV107X_UART0_ERR 72 +#define IRQ_TNETV107X_UART1_ERR 73 +#define IRQ_TNETV107X_AEMIF_ERR 74 +#define IRQ_TNETV107X_DDR_ERR 75 +#define IRQ_TNETV107X_WDTARM_INT0 76 +#define IRQ_TNETV107X_MCDMA_ERR 77 +#define IRQ_TNETV107X_GPIO_ERR 78 +#define IRQ_TNETV107X_MPU_ADDR 79 +#define IRQ_TNETV107X_MPU_PROT 80 +#define IRQ_TNETV107X_IOPU_ADDR 81 +#define IRQ_TNETV107X_IOPU_PROT 82 +#define IRQ_TNETV107X_KEYPAD_ADDR_ERR 83 +#define IRQ_TNETV107X_WDT0_ADDR_ERR 84 +#define IRQ_TNETV107X_WDT1_ADDR_ERR 85 +#define IRQ_TNETV107X_CLKCTL_ADDR_ERR 86 +#define IRQ_TNETV107X_PLL_UNLOCK 87 +#define IRQ_TNETV107X_WDTDSP_INT0 88 +#define IRQ_TNETV107X_SEC_CTRL_VIOLATION 89 +#define IRQ_TNETV107X_KEY_MNG_VIOLATION 90 +#define IRQ_TNETV107X_PBIST_CPU 91 +#define IRQ_TNETV107X_WDTARM 92 +#define IRQ_TNETV107X_PSC 93 +#define IRQ_TNETV107X_MMC0 94 +#define IRQ_TNETV107X_MMC1 95 + +#define TNETV107X_N_CP_INTC_IRQ 96 + /* da850 currently has the most gpio pins (144) */ #define DAVINCI_N_GPIO 144 /* da850 currently has the most irqs so use DA850_N_CP_INTC_IRQ */ -- cgit v0.10.2 From ef03592a1a8112309f1fca1c11fbaef8ab541ef2 Mon Sep 17 00:00:00 2001 From: Cyril Chemparathy Date: Thu, 25 Mar 2010 17:43:53 -0400 Subject: Davinci: tnetv107x cpu types Added tnetv107x cpu type definitions and cpu identification macros. Signed-off-by: Cyril Chemparathy Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/include/mach/cputype.h b/arch/arm/mach-davinci/include/mach/cputype.h index 189b1ff..cea6b89 100644 --- a/arch/arm/mach-davinci/include/mach/cputype.h +++ b/arch/arm/mach-davinci/include/mach/cputype.h @@ -33,6 +33,7 @@ struct davinci_id { #define DAVINCI_CPU_ID_DM365 0x03650000 #define DAVINCI_CPU_ID_DA830 0x08300000 #define DAVINCI_CPU_ID_DA850 0x08500000 +#define DAVINCI_CPU_ID_TNETV107X 0x0b8a0000 #define IS_DAVINCI_CPU(type, id) \ static inline int is_davinci_ ##type(void) \ @@ -46,6 +47,7 @@ IS_DAVINCI_CPU(dm355, DAVINCI_CPU_ID_DM355) IS_DAVINCI_CPU(dm365, DAVINCI_CPU_ID_DM365) IS_DAVINCI_CPU(da830, DAVINCI_CPU_ID_DA830) IS_DAVINCI_CPU(da850, DAVINCI_CPU_ID_DA850) +IS_DAVINCI_CPU(tnetv107x, DAVINCI_CPU_ID_TNETV107X) #ifdef CONFIG_ARCH_DAVINCI_DM644x #define cpu_is_davinci_dm644x() is_davinci_dm644x() @@ -83,4 +85,10 @@ IS_DAVINCI_CPU(da850, DAVINCI_CPU_ID_DA850) #define cpu_is_davinci_da850() 0 #endif +#ifdef CONFIG_ARCH_DAVINCI_TNETV107X +#define cpu_is_davinci_tnetv107x() is_davinci_tnetv107x() +#else +#define cpu_is_davinci_tnetv107x() 0 +#endif + #endif -- cgit v0.10.2 From 7034217467abe91b5bc63fc2993bb8eec1cf3c9f Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 16 Apr 2010 21:29:11 +0400 Subject: DaVinci: move AEMIF #define's to the proper headers Currently each DaVinci board file #define's its own version of the EMIFA base addresses (all named DAVINCI_ASYNC_EMIF_*_BASE), which leads to duplication. Move these #define's to the SoC specific headers, changing their prefixes from 'DAVINCI' to the 'DM355', 'DM644X', and 'DM646X' since all these base addresses are SoC specific... And while at it, rename DM646X_ASYNC_EMIF_DATA_CE0_BASE to DM646X_ASYNC_EMIF_CS2_SPACE_BASE in order to match the DM646x datasheet. Signed-off-by: Sergei Shtylyov Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/board-dm355-evm.c b/arch/arm/mach-davinci/board-dm355-evm.c index aa48e3f..a0ad7d9 100644 --- a/arch/arm/mach-davinci/board-dm355-evm.c +++ b/arch/arm/mach-davinci/board-dm355-evm.c @@ -33,9 +33,6 @@ #include #include -#define DAVINCI_ASYNC_EMIF_CONTROL_BASE 0x01e10000 -#define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE 0x02000000 - /* NOTE: this is geared for the standard config, with a socketed * 2 GByte Micron NAND (MT29F16G08FAA) using 128KB sectors. If you * swap chips, maybe with a different block size, partitioning may @@ -86,12 +83,12 @@ static struct davinci_nand_pdata davinci_nand_data = { static struct resource davinci_nand_resources[] = { { - .start = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE, - .end = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE + SZ_32M - 1, + .start = DM355_ASYNC_EMIF_DATA_CE0_BASE, + .end = DM355_ASYNC_EMIF_DATA_CE0_BASE + SZ_32M - 1, .flags = IORESOURCE_MEM, }, { - .start = DAVINCI_ASYNC_EMIF_CONTROL_BASE, - .end = DAVINCI_ASYNC_EMIF_CONTROL_BASE + SZ_4K - 1, + .start = DM355_ASYNC_EMIF_CONTROL_BASE, + .end = DM355_ASYNC_EMIF_CONTROL_BASE + SZ_4K - 1, .flags = IORESOURCE_MEM, }, }; diff --git a/arch/arm/mach-davinci/board-dm355-leopard.c b/arch/arm/mach-davinci/board-dm355-leopard.c index 21f32eb..c3d5a70 100644 --- a/arch/arm/mach-davinci/board-dm355-leopard.c +++ b/arch/arm/mach-davinci/board-dm355-leopard.c @@ -30,9 +30,6 @@ #include #include -#define DAVINCI_ASYNC_EMIF_CONTROL_BASE 0x01e10000 -#define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE 0x02000000 - /* NOTE: this is geared for the standard config, with a socketed * 2 GByte Micron NAND (MT29F16G08FAA) using 128KB sectors. If you * swap chips, maybe with a different block size, partitioning may @@ -82,12 +79,12 @@ static struct davinci_nand_pdata davinci_nand_data = { static struct resource davinci_nand_resources[] = { { - .start = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE, - .end = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE + SZ_32M - 1, + .start = DM355_ASYNC_EMIF_DATA_CE0_BASE, + .end = DM355_ASYNC_EMIF_DATA_CE0_BASE + SZ_32M - 1, .flags = IORESOURCE_MEM, }, { - .start = DAVINCI_ASYNC_EMIF_CONTROL_BASE, - .end = DAVINCI_ASYNC_EMIF_CONTROL_BASE + SZ_4K - 1, + .start = DM355_ASYNC_EMIF_CONTROL_BASE, + .end = DM355_ASYNC_EMIF_CONTROL_BASE + SZ_4K - 1, .flags = IORESOURCE_MEM, }, }; diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c index df4ab21..b98b35c 100644 --- a/arch/arm/mach-davinci/board-dm365-evm.c +++ b/arch/arm/mach-davinci/board-dm365-evm.c @@ -54,11 +54,6 @@ static inline int have_tvp7002(void) return 0; } - -#define DM365_ASYNC_EMIF_CONTROL_BASE 0x01d10000 -#define DM365_ASYNC_EMIF_DATA_CE0_BASE 0x02000000 -#define DM365_ASYNC_EMIF_DATA_CE1_BASE 0x04000000 - #define DM365_EVM_PHY_MASK (0x2) #define DM365_EVM_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c index 95cef1f..d028bab 100644 --- a/arch/arm/mach-davinci/board-dm644x-evm.c +++ b/arch/arm/mach-davinci/board-dm644x-evm.c @@ -43,12 +43,6 @@ #define DAVINCI_CFC_ATA_BASE 0x01C66000 -#define DAVINCI_ASYNC_EMIF_CONTROL_BASE 0x01e00000 -#define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE 0x02000000 -#define DAVINCI_ASYNC_EMIF_DATA_CE1_BASE 0x04000000 -#define DAVINCI_ASYNC_EMIF_DATA_CE2_BASE 0x06000000 -#define DAVINCI_ASYNC_EMIF_DATA_CE3_BASE 0x08000000 - #define LXT971_PHY_ID (0x001378e2) #define LXT971_PHY_MASK (0xfffffff0) @@ -92,8 +86,8 @@ static struct physmap_flash_data davinci_evm_norflash_data = { /* NOTE: CFI probe will correctly detect flash part as 32M, but EMIF * limits addresses to 16M, so using addresses past 16M will wrap */ static struct resource davinci_evm_norflash_resource = { - .start = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE, - .end = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE + SZ_16M - 1, + .start = DM644X_ASYNC_EMIF_DATA_CE0_BASE, + .end = DM644X_ASYNC_EMIF_DATA_CE0_BASE + SZ_16M - 1, .flags = IORESOURCE_MEM, }; @@ -154,12 +148,12 @@ static struct davinci_nand_pdata davinci_evm_nandflash_data = { static struct resource davinci_evm_nandflash_resource[] = { { - .start = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE, - .end = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE + SZ_16M - 1, + .start = DM644X_ASYNC_EMIF_DATA_CE0_BASE, + .end = DM644X_ASYNC_EMIF_DATA_CE0_BASE + SZ_16M - 1, .flags = IORESOURCE_MEM, }, { - .start = DAVINCI_ASYNC_EMIF_CONTROL_BASE, - .end = DAVINCI_ASYNC_EMIF_CONTROL_BASE + SZ_4K - 1, + .start = DM644X_ASYNC_EMIF_CONTROL_BASE, + .end = DM644X_ASYNC_EMIF_CONTROL_BASE + SZ_4K - 1, .flags = IORESOURCE_MEM, }, }; diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c index 5ba3cb2..b22e22c 100644 --- a/arch/arm/mach-davinci/board-dm646x-evm.c +++ b/arch/arm/mach-davinci/board-dm646x-evm.c @@ -80,17 +80,14 @@ static struct davinci_nand_pdata davinci_nand_data = { .options = 0, }; -#define DAVINCI_ASYNC_EMIF_CONTROL_BASE 0x20008000 -#define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE 0x42000000 - static struct resource davinci_nand_resources[] = { { - .start = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE, - .end = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE + SZ_32M - 1, + .start = DM646X_ASYNC_EMIF_CS2_SPACE_BASE, + .end = DM646X_ASYNC_EMIF_CS2_SPACE_BASE + SZ_32M - 1, .flags = IORESOURCE_MEM, }, { - .start = DAVINCI_ASYNC_EMIF_CONTROL_BASE, - .end = DAVINCI_ASYNC_EMIF_CONTROL_BASE + SZ_4K - 1, + .start = DM646X_ASYNC_EMIF_CONTROL_BASE, + .end = DM646X_ASYNC_EMIF_CONTROL_BASE + SZ_4K - 1, .flags = IORESOURCE_MEM, }, }; diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c index 1fadc68..5afe37e 100644 --- a/arch/arm/mach-davinci/board-neuros-osd2.c +++ b/arch/arm/mach-davinci/board-neuros-osd2.c @@ -43,9 +43,6 @@ #define DAVINCI_CFC_ATA_BASE 0x01C66000 -#define DAVINCI_ASYNC_EMIF_CONTROL_BASE 0x01e00000 -#define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE 0x02000000 - #define LXT971_PHY_ID 0x001378e2 #define LXT971_PHY_MASK 0xfffffff0 @@ -98,12 +95,12 @@ static struct davinci_nand_pdata davinci_ntosd2_nandflash_data = { static struct resource davinci_ntosd2_nandflash_resource[] = { { - .start = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE, - .end = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE + SZ_16M - 1, + .start = DM644X_ASYNC_EMIF_DATA_CE0_BASE, + .end = DM644X_ASYNC_EMIF_DATA_CE0_BASE + SZ_16M - 1, .flags = IORESOURCE_MEM, }, { - .start = DAVINCI_ASYNC_EMIF_CONTROL_BASE, - .end = DAVINCI_ASYNC_EMIF_CONTROL_BASE + SZ_4K - 1, + .start = DM644X_ASYNC_EMIF_CONTROL_BASE, + .end = DM644X_ASYNC_EMIF_CONTROL_BASE + SZ_4K - 1, .flags = IORESOURCE_MEM, }, }; diff --git a/arch/arm/mach-davinci/board-sffsdr.c b/arch/arm/mach-davinci/board-sffsdr.c index a7cf810..1ed0662 100644 --- a/arch/arm/mach-davinci/board-sffsdr.c +++ b/arch/arm/mach-davinci/board-sffsdr.c @@ -45,9 +45,6 @@ #define SFFSDR_PHY_MASK (0x2) #define SFFSDR_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ -#define DAVINCI_ASYNC_EMIF_CONTROL_BASE 0x01e00000 -#define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE 0x02000000 - static struct mtd_partition davinci_sffsdr_nandflash_partition[] = { /* U-Boot Environment: Block 0 * UBL: Block 1 @@ -76,12 +73,12 @@ static struct flash_platform_data davinci_sffsdr_nandflash_data = { static struct resource davinci_sffsdr_nandflash_resource[] = { { - .start = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE, - .end = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE + SZ_16M - 1, + .start = DM644X_ASYNC_EMIF_DATA_CE0_BASE, + .end = DM644X_ASYNC_EMIF_DATA_CE0_BASE + SZ_16M - 1, .flags = IORESOURCE_MEM, }, { - .start = DAVINCI_ASYNC_EMIF_CONTROL_BASE, - .end = DAVINCI_ASYNC_EMIF_CONTROL_BASE + SZ_4K - 1, + .start = DM644X_ASYNC_EMIF_CONTROL_BASE, + .end = DM644X_ASYNC_EMIF_CONTROL_BASE + SZ_4K - 1, .flags = IORESOURCE_MEM, }, }; diff --git a/arch/arm/mach-davinci/include/mach/dm355.h b/arch/arm/mach-davinci/include/mach/dm355.h index 85536d8..36dff4a 100644 --- a/arch/arm/mach-davinci/include/mach/dm355.h +++ b/arch/arm/mach-davinci/include/mach/dm355.h @@ -15,6 +15,9 @@ #include #include +#define DM355_ASYNC_EMIF_CONTROL_BASE 0x01E10000 +#define DM355_ASYNC_EMIF_DATA_CE0_BASE 0x02000000 + #define ASP1_TX_EVT_EN 1 #define ASP1_RX_EVT_EN 2 diff --git a/arch/arm/mach-davinci/include/mach/dm365.h b/arch/arm/mach-davinci/include/mach/dm365.h index 3a37b5a..ea5df3b 100644 --- a/arch/arm/mach-davinci/include/mach/dm365.h +++ b/arch/arm/mach-davinci/include/mach/dm365.h @@ -36,6 +36,10 @@ #define DAVINCI_DMA_VC_TX 2 #define DAVINCI_DMA_VC_RX 3 +#define DM365_ASYNC_EMIF_CONTROL_BASE 0x01D10000 +#define DM365_ASYNC_EMIF_DATA_CE0_BASE 0x02000000 +#define DM365_ASYNC_EMIF_DATA_CE1_BASE 0x04000000 + void __init dm365_init(void); void __init dm365_init_asp(struct snd_platform_data *pdata); void __init dm365_init_vc(struct snd_platform_data *pdata); diff --git a/arch/arm/mach-davinci/include/mach/dm644x.h b/arch/arm/mach-davinci/include/mach/dm644x.h index 1a8b09c..6fca568 100644 --- a/arch/arm/mach-davinci/include/mach/dm644x.h +++ b/arch/arm/mach-davinci/include/mach/dm644x.h @@ -34,6 +34,12 @@ #define DM644X_EMAC_MDIO_OFFSET (0x4000) #define DM644X_EMAC_CNTRL_RAM_SIZE (0x2000) +#define DM644X_ASYNC_EMIF_CONTROL_BASE 0x01E00000 +#define DM644X_ASYNC_EMIF_DATA_CE0_BASE 0x02000000 +#define DM644X_ASYNC_EMIF_DATA_CE1_BASE 0x04000000 +#define DM644X_ASYNC_EMIF_DATA_CE2_BASE 0x06000000 +#define DM644X_ASYNC_EMIF_DATA_CE3_BASE 0x08000000 + void __init dm644x_init(void); void __init dm644x_init_asp(struct snd_platform_data *pdata); void dm644x_set_vpfe_config(struct vpfe_config *cfg); diff --git a/arch/arm/mach-davinci/include/mach/dm646x.h b/arch/arm/mach-davinci/include/mach/dm646x.h index 846da98..4d62db7 100644 --- a/arch/arm/mach-davinci/include/mach/dm646x.h +++ b/arch/arm/mach-davinci/include/mach/dm646x.h @@ -27,6 +27,9 @@ #define DM646X_ATA_REG_BASE (0x01C66000) +#define DM646X_ASYNC_EMIF_CONTROL_BASE 0x20008000 +#define DM646X_ASYNC_EMIF_CS2_SPACE_BASE 0x42000000 + void __init dm646x_init(void); void __init dm646x_init_ide(void); void __init dm646x_init_mcasp0(struct snd_platform_data *pdata); -- cgit v0.10.2 From 002cb2d2f1dde524b2aef6e43922984f6d1c8adc Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 16 Apr 2010 21:29:20 +0400 Subject: DA830 EVM: use DA8XX_AEMIF_*_BASE #define's The board file #define's its own version of EMIFA base addresses, while there are DA8XX_AEMIF_*_BASE macros #define'd in . Start using them instead. Signed-off-by: Sergei Shtylyov Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c index 9257056..8f079d2 100644 --- a/arch/arm/mach-davinci/board-da830-evm.c +++ b/arch/arm/mach-davinci/board-da830-evm.c @@ -33,9 +33,6 @@ #define DA830_EVM_PHY_MASK 0x0 #define DA830_EVM_MDIO_FREQUENCY 2200000 /* PHY bus frequency */ -#define DA830_EMIF25_ASYNC_DATA_CE3_BASE 0x62000000 -#define DA830_EMIF25_CONTROL_BASE 0x68000000 - /* * USB1 VBUS is controlled by GPIO1[15], over-current is reported on GPIO2[4]. */ @@ -375,13 +372,13 @@ static struct davinci_nand_pdata da830_evm_nand_pdata = { static struct resource da830_evm_nand_resources[] = { [0] = { /* First memory resource is NAND I/O window */ - .start = DA830_EMIF25_ASYNC_DATA_CE3_BASE, - .end = DA830_EMIF25_ASYNC_DATA_CE3_BASE + PAGE_SIZE - 1, + .start = DA8XX_AEMIF_CS3_BASE, + .end = DA8XX_AEMIF_CS3_BASE + PAGE_SIZE - 1, .flags = IORESOURCE_MEM, }, [1] = { /* Second memory resource is AEMIF control registers */ - .start = DA830_EMIF25_CONTROL_BASE, - .end = DA830_EMIF25_CONTROL_BASE + SZ_32K - 1, + .start = DA8XX_AEMIF_CTL_BASE, + .end = DA8XX_AEMIF_CTL_BASE + SZ_32K - 1, .flags = IORESOURCE_MEM, }, }; -- cgit v0.10.2 From ce100669d2ee202acac94d39f1a585c6b066cecc Mon Sep 17 00:00:00 2001 From: Thomas Koeller Date: Thu, 8 Apr 2010 17:01:56 +0200 Subject: davinci: DM365: Allow use of GPIO64_57 Extended the MUX configuration to allow use of GPIO terminals 64..57. Signed-off-by: Thomas Koeller Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index 871be5a..1ee3fc8 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -576,6 +576,7 @@ MUX_CFG(DM365, SPI4_SDENA1, 4, 16, 3, 2, false) MUX_CFG(DM365, GPIO20, 3, 21, 3, 0, false) MUX_CFG(DM365, GPIO33, 4, 12, 3, 0, false) MUX_CFG(DM365, GPIO40, 4, 26, 3, 0, false) +MUX_CFG(DM365, GPIO64_57, 2, 6, 1, 0, false) MUX_CFG(DM365, VOUT_FIELD, 1, 18, 3, 1, false) MUX_CFG(DM365, VOUT_FIELD_G81, 1, 18, 3, 0, false) diff --git a/arch/arm/mach-davinci/include/mach/mux.h b/arch/arm/mach-davinci/include/mach/mux.h index 8638903..923debe 100644 --- a/arch/arm/mach-davinci/include/mach/mux.h +++ b/arch/arm/mach-davinci/include/mach/mux.h @@ -291,6 +291,7 @@ enum davinci_dm365_index { DM365_GPIO20, DM365_GPIO33, DM365_GPIO40, + DM365_GPIO64_57, /* Video */ DM365_VOUT_FIELD, -- cgit v0.10.2 From d6961e6889a26de427aa6e0df823c789cf4a848f Mon Sep 17 00:00:00 2001 From: Cyril Chemparathy Date: Wed, 14 Apr 2010 14:44:49 -0400 Subject: Davinci: configurable pll divider mask This patch allows socs to override the divider ratio mask by setting an optional field (div_ratio_mask) in the pll_data structure. Signed-off-by: Cyril Chemparathy Tested-by: Sandeep Paulraj Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c index 5de60ae..868cb76 100644 --- a/arch/arm/mach-davinci/clock.c +++ b/arch/arm/mach-davinci/clock.c @@ -279,7 +279,7 @@ static unsigned long clk_sysclk_recalc(struct clk *clk) v = __raw_readl(pll->base + clk->div_reg); if (v & PLLDIV_EN) { - plldiv = (v & PLLDIV_RATIO_MASK) + 1; + plldiv = (v & pll->div_ratio_mask) + 1; if (plldiv) rate /= plldiv; } @@ -319,7 +319,7 @@ static unsigned long clk_pllclk_recalc(struct clk *clk) if (pll->flags & PLL_HAS_PREDIV) { prediv = __raw_readl(pll->base + PREDIV); if (prediv & PLLDIV_EN) - prediv = (prediv & PLLDIV_RATIO_MASK) + 1; + prediv = (prediv & pll->div_ratio_mask) + 1; else prediv = 1; } @@ -331,7 +331,7 @@ static unsigned long clk_pllclk_recalc(struct clk *clk) if (pll->flags & PLL_HAS_POSTDIV) { postdiv = __raw_readl(pll->base + POSTDIV); if (postdiv & PLLDIV_EN) - postdiv = (postdiv & PLLDIV_RATIO_MASK) + 1; + postdiv = (postdiv & pll->div_ratio_mask) + 1; else postdiv = 1; } @@ -458,6 +458,9 @@ int __init davinci_clk_init(struct clk_lookup *clocks) clk->recalc = clk_leafclk_recalc; } + if (clk->pll_data && !clk->pll_data->div_ratio_mask) + clk->pll_data->div_ratio_mask = PLLDIV_RATIO_MASK; + if (clk->recalc) clk->rate = clk->recalc(clk); diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h index 53a0f7b..ce26015 100644 --- a/arch/arm/mach-davinci/clock.h +++ b/arch/arm/mach-davinci/clock.h @@ -76,6 +76,7 @@ struct pll_data { u32 num; u32 flags; u32 input_rate; + u32 div_ratio_mask; }; #define PLL_HAS_PREDIV 0x01 #define PLL_HAS_POSTDIV 0x02 -- cgit v0.10.2 From 280faffb4e059b3f453e297af7060d9c277c0ca9 Mon Sep 17 00:00:00 2001 From: Thomas Koeller Date: Wed, 21 Apr 2010 15:33:32 +0200 Subject: davinci: mach/common.h: add missing includes linux/compiler.h is required for __iomem linux/types.h is required u32 Signed-off-by: Thomas Koeller Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/include/mach/common.h b/arch/arm/mach-davinci/include/mach/common.h index 50a955f..d88104e 100644 --- a/arch/arm/mach-davinci/include/mach/common.h +++ b/arch/arm/mach-davinci/include/mach/common.h @@ -12,6 +12,9 @@ #ifndef __ARCH_ARM_MACH_DAVINCI_COMMON_H #define __ARCH_ARM_MACH_DAVINCI_COMMON_H +#include +#include + struct sys_timer; extern struct sys_timer davinci_timer; -- cgit v0.10.2 From 7a9978a1e2225507025a8b90b4289d506a416bd9 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 21 Apr 2010 18:11:33 +0400 Subject: DaVinci: move IDE platform device to its proper place The IDE platform device is registered in three different places (2 board files for DM644x and in dm646x.c for DM646x) while both the IDE base address and the IDE IRQ are the same for both SoCs -- therefore, the proper place for the IDE platform seems to be in devices.c. Merge the IDE platform data and registration code and create davinci_init_ide() in place of dm646x_init_ide()... Signed-off-by: Sergei Shtylyov Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c index d028bab..73c0b04 100644 --- a/arch/arm/mach-davinci/board-dm644x-evm.c +++ b/arch/arm/mach-davinci/board-dm644x-evm.c @@ -41,8 +41,6 @@ #define DM644X_EVM_PHY_MASK (0x2) #define DM644X_EVM_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ -#define DAVINCI_CFC_ATA_BASE 0x01C66000 - #define LXT971_PHY_ID (0x001378e2) #define LXT971_PHY_MASK (0xfffffff0) @@ -252,32 +250,6 @@ static struct platform_device rtc_dev = { .id = -1, }; -static struct resource ide_resources[] = { - { - .start = DAVINCI_CFC_ATA_BASE, - .end = DAVINCI_CFC_ATA_BASE + 0x7ff, - .flags = IORESOURCE_MEM, - }, - { - .start = IRQ_IDE, - .end = IRQ_IDE, - .flags = IORESOURCE_IRQ, - }, -}; - -static u64 ide_dma_mask = DMA_BIT_MASK(32); - -static struct platform_device ide_dev = { - .name = "palm_bk3710", - .id = -1, - .resource = ide_resources, - .num_resources = ARRAY_SIZE(ide_resources), - .dev = { - .dma_mask = &ide_dma_mask, - .coherent_dma_mask = DMA_BIT_MASK(32), - }, -}; - static struct snd_platform_data dm644x_evm_snd_data; /*----------------------------------------------------------------------*/ @@ -698,10 +670,7 @@ static __init void davinci_evm_init(void) pr_warning("WARNING: both IDE and Flash are " "enabled, but they share AEMIF pins.\n" "\tDisable IDE for NAND/NOR support.\n"); - davinci_cfg_reg(DM644X_HPIEN_DISABLE); - davinci_cfg_reg(DM644X_ATAEN); - davinci_cfg_reg(DM644X_HDIREN); - platform_device_register(&ide_dev); + davinci_init_ide(); } else if (HAS_NAND || HAS_NOR) { davinci_cfg_reg(DM644X_HPIEN_DISABLE); davinci_cfg_reg(DM644X_ATAEN_DISABLE); diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c index b22e22c..e2ac06f 100644 --- a/arch/arm/mach-davinci/board-dm646x-evm.c +++ b/arch/arm/mach-davinci/board-dm646x-evm.c @@ -733,7 +733,7 @@ static __init void evm_init(void) platform_device_register(&davinci_nand_device); if (HAS_ATA) - dm646x_init_ide(); + davinci_init_ide(); soc_info->emac_pdata->phy_mask = DM646X_EVM_PHY_MASK; soc_info->emac_pdata->mdio_max_freq = DM646X_EVM_MDIO_FREQUENCY; diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c index 5afe37e..875770c 100644 --- a/arch/arm/mach-davinci/board-neuros-osd2.c +++ b/arch/arm/mach-davinci/board-neuros-osd2.c @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -41,8 +42,6 @@ #define NEUROS_OSD2_PHY_MASK 0x2 #define NEUROS_OSD2_MDIO_FREQUENCY 2200000 /* PHY bus frequency */ -#define DAVINCI_CFC_ATA_BASE 0x01C66000 - #define LXT971_PHY_ID 0x001378e2 #define LXT971_PHY_MASK 0xfffffff0 @@ -127,32 +126,6 @@ static struct platform_device davinci_fb_device = { .num_resources = 0, }; -static struct resource ide_resources[] = { - { - .start = DAVINCI_CFC_ATA_BASE, - .end = DAVINCI_CFC_ATA_BASE + 0x7ff, - .flags = IORESOURCE_MEM, - }, - { - .start = IRQ_IDE, - .end = IRQ_IDE, - .flags = IORESOURCE_IRQ, - }, -}; - -static u64 ide_dma_mask = DMA_BIT_MASK(32); - -static struct platform_device ide_dev = { - .name = "palm_bk3710", - .id = -1, - .resource = ide_resources, - .num_resources = ARRAY_SIZE(ide_resources), - .dev = { - .dma_mask = &ide_dma_mask, - .coherent_dma_mask = DMA_BIT_MASK(32), - }, -}; - static struct snd_platform_data dm644x_ntosd2_snd_data; static struct gpio_led ntosd2_leds[] = { @@ -256,10 +229,7 @@ static __init void davinci_ntosd2_init(void) pr_warning("WARNING: both IDE and Flash are " "enabled, but they share AEMIF pins.\n" "\tDisable IDE for NAND/NOR support.\n"); - davinci_cfg_reg(DM644X_HPIEN_DISABLE); - davinci_cfg_reg(DM644X_ATAEN); - davinci_cfg_reg(DM644X_HDIREN); - platform_device_register(&ide_dev); + davinci_init_ide(); } else if (HAS_NAND) { davinci_cfg_reg(DM644X_HPIEN_DISABLE); davinci_cfg_reg(DM644X_ATAEN_DISABLE); diff --git a/arch/arm/mach-davinci/devices.c b/arch/arm/mach-davinci/devices.c index ef28080..d9c82ee 100644 --- a/arch/arm/mach-davinci/devices.c +++ b/arch/arm/mach-davinci/devices.c @@ -26,6 +26,7 @@ #include "clock.h" #define DAVINCI_I2C_BASE 0x01C21000 +#define DAVINCI_ATA_BASE 0x01C66000 #define DAVINCI_MMCSD0_BASE 0x01E10000 #define DM355_MMCSD0_BASE 0x01E11000 #define DM355_MMCSD1_BASE 0x01E00000 @@ -60,6 +61,49 @@ void __init davinci_init_i2c(struct davinci_i2c_platform_data *pdata) (void) platform_device_register(&davinci_i2c_device); } +static struct resource ide_resources[] = { + { + .start = DAVINCI_ATA_BASE, + .end = DAVINCI_ATA_BASE + 0x7ff, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_IDE, + .end = IRQ_IDE, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 ide_dma_mask = DMA_BIT_MASK(32); + +static struct platform_device ide_device = { + .name = "palm_bk3710", + .id = -1, + .resource = ide_resources, + .num_resources = ARRAY_SIZE(ide_resources), + .dev = { + .dma_mask = &ide_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, +}; + +void __init davinci_init_ide(void) +{ + if (cpu_is_davinci_dm644x()) { + davinci_cfg_reg(DM644X_HPIEN_DISABLE); + davinci_cfg_reg(DM644X_ATAEN); + davinci_cfg_reg(DM644X_HDIREN); + } else if (cpu_is_davinci_dm646x()) { + /* IRQ_DM646X_IDE is the same as IRQ_IDE */ + davinci_cfg_reg(DM646X_ATAEN); + } else { + WARN_ON(1); + return; + } + + platform_device_register(&ide_device); +} + #if defined(CONFIG_MMC_DAVINCI) || defined(CONFIG_MMC_DAVINCI_MODULE) static u64 mmcsd0_dma_mask = DMA_BIT_MASK(32); diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index b67b997d..a0b3739 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -596,32 +596,6 @@ static struct platform_device dm646x_edma_device = { .resource = edma_resources, }; -static struct resource ide_resources[] = { - { - .start = DM646X_ATA_REG_BASE, - .end = DM646X_ATA_REG_BASE + 0x7ff, - .flags = IORESOURCE_MEM, - }, - { - .start = IRQ_DM646X_IDE, - .end = IRQ_DM646X_IDE, - .flags = IORESOURCE_IRQ, - }, -}; - -static u64 ide_dma_mask = DMA_BIT_MASK(32); - -static struct platform_device ide_dev = { - .name = "palm_bk3710", - .id = -1, - .resource = ide_resources, - .num_resources = ARRAY_SIZE(ide_resources), - .dev = { - .dma_mask = &ide_dma_mask, - .coherent_dma_mask = DMA_BIT_MASK(32), - }, -}; - static struct resource dm646x_mcasp0_resources[] = { { .name = "mcasp0", @@ -867,12 +841,6 @@ static struct davinci_soc_info davinci_soc_info_dm646x = { .sram_len = SZ_32K, }; -void __init dm646x_init_ide(void) -{ - davinci_cfg_reg(DM646X_ATAEN); - platform_device_register(&ide_dev); -} - void __init dm646x_init_mcasp0(struct snd_platform_data *pdata) { dm646x_mcasp0_device.dev.platform_data = pdata; diff --git a/arch/arm/mach-davinci/include/mach/common.h b/arch/arm/mach-davinci/include/mach/common.h index d88104e..884dc72 100644 --- a/arch/arm/mach-davinci/include/mach/common.h +++ b/arch/arm/mach-davinci/include/mach/common.h @@ -70,6 +70,7 @@ struct davinci_soc_info { extern struct davinci_soc_info davinci_soc_info; extern void davinci_common_init(struct davinci_soc_info *soc_info); +extern void davinci_init_ide(void); /* standard place to map on-chip SRAMs; they *may* support DMA */ #define SRAM_VIRT 0xfffe0000 diff --git a/arch/arm/mach-davinci/include/mach/dm646x.h b/arch/arm/mach-davinci/include/mach/dm646x.h index 4d62db7..add6f79 100644 --- a/arch/arm/mach-davinci/include/mach/dm646x.h +++ b/arch/arm/mach-davinci/include/mach/dm646x.h @@ -25,13 +25,10 @@ #define DM646X_EMAC_MDIO_OFFSET (0x4000) #define DM646X_EMAC_CNTRL_RAM_SIZE (0x2000) -#define DM646X_ATA_REG_BASE (0x01C66000) - #define DM646X_ASYNC_EMIF_CONTROL_BASE 0x20008000 #define DM646X_ASYNC_EMIF_CS2_SPACE_BASE 0x42000000 void __init dm646x_init(void); -void __init dm646x_init_ide(void); void __init dm646x_init_mcasp0(struct snd_platform_data *pdata); void __init dm646x_init_mcasp1(struct snd_platform_data *pdata); void __init dm646x_board_setup_refclk(struct clk *clk); -- cgit v0.10.2 From ba4a984e838dfb1c46135ff8cadeea5f8ca5fd0a Mon Sep 17 00:00:00 2001 From: Cyril Chemparathy Date: Sat, 1 May 2010 18:37:51 -0400 Subject: Davinci: gpio - minor cleanup macroized repeated container_of()s to improve readability. unified direction in/out functions. Signed-off-by: Cyril Chemparathy Tested-by: Sandeep Paulraj Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c index 5476ad1..93f7c68 100644 --- a/arch/arm/mach-davinci/gpio.c +++ b/arch/arm/mach-davinci/gpio.c @@ -28,6 +28,9 @@ struct davinci_gpio { int irq_base; }; +#define chip2controller(chip) \ + container_of(chip, struct davinci_gpio, chip) + static struct davinci_gpio chips[DIV_ROUND_UP(DAVINCI_N_GPIO, 32)]; /* create a non-inlined version */ @@ -54,21 +57,39 @@ static int __init davinci_gpio_irq_setup(void); * needed, and enable the GPIO clock. */ -static int davinci_direction_in(struct gpio_chip *chip, unsigned offset) +static inline int __davinci_direction(struct gpio_chip *chip, + unsigned offset, bool out, int value) { - struct davinci_gpio *d = container_of(chip, struct davinci_gpio, chip); + struct davinci_gpio *d = chip2controller(chip); struct gpio_controller __iomem *g = d->regs; u32 temp; + u32 mask = 1 << offset; spin_lock(&gpio_lock); temp = __raw_readl(&g->dir); - temp |= (1 << offset); + if (out) { + temp &= ~mask; + __raw_writel(mask, value ? &g->set_data : &g->clr_data); + } else { + temp |= mask; + } __raw_writel(temp, &g->dir); spin_unlock(&gpio_lock); return 0; } +static int davinci_direction_in(struct gpio_chip *chip, unsigned offset) +{ + return __davinci_direction(chip, offset, false, 0); +} + +static int +davinci_direction_out(struct gpio_chip *chip, unsigned offset, int value) +{ + return __davinci_direction(chip, offset, true, value); +} + /* * Read the pin's value (works even if it's set up as output); * returns zero/nonzero. @@ -78,36 +99,19 @@ static int davinci_direction_in(struct gpio_chip *chip, unsigned offset) */ static int davinci_gpio_get(struct gpio_chip *chip, unsigned offset) { - struct davinci_gpio *d = container_of(chip, struct davinci_gpio, chip); + struct davinci_gpio *d = chip2controller(chip); struct gpio_controller __iomem *g = d->regs; return (1 << offset) & __raw_readl(&g->in_data); } -static int -davinci_direction_out(struct gpio_chip *chip, unsigned offset, int value) -{ - struct davinci_gpio *d = container_of(chip, struct davinci_gpio, chip); - struct gpio_controller __iomem *g = d->regs; - u32 temp; - u32 mask = 1 << offset; - - spin_lock(&gpio_lock); - temp = __raw_readl(&g->dir); - temp &= ~mask; - __raw_writel(mask, value ? &g->set_data : &g->clr_data); - __raw_writel(temp, &g->dir); - spin_unlock(&gpio_lock); - return 0; -} - /* * Assuming the pin is muxed as a gpio output, set its output value. */ static void davinci_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - struct davinci_gpio *d = container_of(chip, struct davinci_gpio, chip); + struct davinci_gpio *d = chip2controller(chip); struct gpio_controller __iomem *g = d->regs; __raw_writel((1 << offset), value ? &g->set_data : &g->clr_data); @@ -262,7 +266,7 @@ gpio_irq_handler(unsigned irq, struct irq_desc *desc) static int gpio_to_irq_banked(struct gpio_chip *chip, unsigned offset) { - struct davinci_gpio *d = container_of(chip, struct davinci_gpio, chip); + struct davinci_gpio *d = chip2controller(chip); if (d->irq_base >= 0) return d->irq_base + offset; -- cgit v0.10.2 From 99e9e52de635728d7c89a0fdf79b307f3082cf3a Mon Sep 17 00:00:00 2001 From: Cyril Chemparathy Date: Sat, 1 May 2010 18:37:52 -0400 Subject: Davinci: gpio - structs and functions renamed Renamed gpio types to something more sensible: struct gpio_controller --> struct davinci_gpio_regs struct davinci_gpio --> struct davinci_gpio_controller gpio2controller() --> gpio2regs() irq2controller() --> irq2regs() This change also moves davinci_gpio_controller definition to gpio.h. Eventually, the gpio registers structure will be moved to gpio.c and no longer a common cross-soc definition. Signed-off-by: Cyril Chemparathy Tested-by: Sandeep Paulraj Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c index 93f7c68..c77683c 100644 --- a/arch/arm/mach-davinci/gpio.c +++ b/arch/arm/mach-davinci/gpio.c @@ -22,28 +22,22 @@ static DEFINE_SPINLOCK(gpio_lock); -struct davinci_gpio { - struct gpio_chip chip; - struct gpio_controller __iomem *regs; - int irq_base; -}; - #define chip2controller(chip) \ - container_of(chip, struct davinci_gpio, chip) + container_of(chip, struct davinci_gpio_controller, chip) -static struct davinci_gpio chips[DIV_ROUND_UP(DAVINCI_N_GPIO, 32)]; +static struct davinci_gpio_controller chips[DIV_ROUND_UP(DAVINCI_N_GPIO, 32)]; /* create a non-inlined version */ -static struct gpio_controller __iomem __init *gpio2controller(unsigned gpio) +static struct davinci_gpio_regs __iomem __init *gpio2regs(unsigned gpio) { return __gpio_to_controller(gpio); } -static inline struct gpio_controller __iomem *irq2controller(int irq) +static inline struct davinci_gpio_regs __iomem *irq2regs(int irq) { - struct gpio_controller __iomem *g; + struct davinci_gpio_regs __iomem *g; - g = (__force struct gpio_controller __iomem *)get_irq_chip_data(irq); + g = (__force struct davinci_gpio_regs __iomem *)get_irq_chip_data(irq); return g; } @@ -60,8 +54,8 @@ static int __init davinci_gpio_irq_setup(void); static inline int __davinci_direction(struct gpio_chip *chip, unsigned offset, bool out, int value) { - struct davinci_gpio *d = chip2controller(chip); - struct gpio_controller __iomem *g = d->regs; + struct davinci_gpio_controller *d = chip2controller(chip); + struct davinci_gpio_regs __iomem *g = d->regs; u32 temp; u32 mask = 1 << offset; @@ -99,8 +93,8 @@ davinci_direction_out(struct gpio_chip *chip, unsigned offset, int value) */ static int davinci_gpio_get(struct gpio_chip *chip, unsigned offset) { - struct davinci_gpio *d = chip2controller(chip); - struct gpio_controller __iomem *g = d->regs; + struct davinci_gpio_controller *d = chip2controller(chip); + struct davinci_gpio_regs __iomem *g = d->regs; return (1 << offset) & __raw_readl(&g->in_data); } @@ -111,8 +105,8 @@ static int davinci_gpio_get(struct gpio_chip *chip, unsigned offset) static void davinci_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - struct davinci_gpio *d = chip2controller(chip); - struct gpio_controller __iomem *g = d->regs; + struct davinci_gpio_controller *d = chip2controller(chip); + struct davinci_gpio_regs __iomem *g = d->regs; __raw_writel((1 << offset), value ? &g->set_data : &g->clr_data); } @@ -150,7 +144,7 @@ static int __init davinci_gpio_setup(void) if (chips[i].chip.ngpio > 32) chips[i].chip.ngpio = 32; - chips[i].regs = gpio2controller(base); + chips[i].regs = gpio2regs(base); gpiochip_add(&chips[i].chip); } @@ -174,7 +168,7 @@ pure_initcall(davinci_gpio_setup); static void gpio_irq_disable(unsigned irq) { - struct gpio_controller __iomem *g = irq2controller(irq); + struct davinci_gpio_regs __iomem *g = irq2regs(irq); u32 mask = (u32) get_irq_data(irq); __raw_writel(mask, &g->clr_falling); @@ -183,7 +177,7 @@ static void gpio_irq_disable(unsigned irq) static void gpio_irq_enable(unsigned irq) { - struct gpio_controller __iomem *g = irq2controller(irq); + struct davinci_gpio_regs __iomem *g = irq2regs(irq); u32 mask = (u32) get_irq_data(irq); unsigned status = irq_desc[irq].status; @@ -199,7 +193,7 @@ static void gpio_irq_enable(unsigned irq) static int gpio_irq_type(unsigned irq, unsigned trigger) { - struct gpio_controller __iomem *g = irq2controller(irq); + struct davinci_gpio_regs __iomem *g = irq2regs(irq); u32 mask = (u32) get_irq_data(irq); if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) @@ -228,7 +222,7 @@ static struct irq_chip gpio_irqchip = { static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) { - struct gpio_controller __iomem *g = irq2controller(irq); + struct davinci_gpio_regs __iomem *g = irq2regs(irq); u32 mask = 0xffff; /* we only care about one bank */ @@ -266,7 +260,7 @@ gpio_irq_handler(unsigned irq, struct irq_desc *desc) static int gpio_to_irq_banked(struct gpio_chip *chip, unsigned offset) { - struct davinci_gpio *d = chip2controller(chip); + struct davinci_gpio_controller *d = chip2controller(chip); if (d->irq_base >= 0) return d->irq_base + offset; @@ -289,7 +283,7 @@ static int gpio_to_irq_unbanked(struct gpio_chip *chip, unsigned offset) static int gpio_irq_type_unbanked(unsigned irq, unsigned trigger) { - struct gpio_controller __iomem *g = irq2controller(irq); + struct davinci_gpio_regs __iomem *g = irq2regs(irq); u32 mask = (u32) get_irq_data(irq); if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) @@ -318,7 +312,7 @@ static int __init davinci_gpio_irq_setup(void) u32 binten = 0; unsigned ngpio, bank_irq; struct davinci_soc_info *soc_info = &davinci_soc_info; - struct gpio_controller __iomem *g; + struct davinci_gpio_regs __iomem *g; ngpio = soc_info->gpio_num; @@ -367,7 +361,7 @@ static int __init davinci_gpio_irq_setup(void) gpio_irqchip_unbanked.set_type = gpio_irq_type_unbanked; /* default trigger: both edges */ - g = gpio2controller(0); + g = gpio2regs(0); __raw_writel(~0, &g->set_falling); __raw_writel(~0, &g->set_rising); @@ -392,7 +386,7 @@ static int __init davinci_gpio_irq_setup(void) unsigned i; /* disabled by default, enabled only as needed */ - g = gpio2controller(gpio); + g = gpio2regs(gpio); __raw_writel(~0, &g->clr_falling); __raw_writel(~0, &g->clr_rising); diff --git a/arch/arm/mach-davinci/include/mach/gpio.h b/arch/arm/mach-davinci/include/mach/gpio.h index 0099e6e..bdab001 100644 --- a/arch/arm/mach-davinci/include/mach/gpio.h +++ b/arch/arm/mach-davinci/include/mach/gpio.h @@ -45,7 +45,7 @@ /* Convert GPIO signal to GPIO pin number */ #define GPIO_TO_PIN(bank, gpio) (16 * (bank) + (gpio)) -struct gpio_controller { +struct davinci_gpio_regs { u32 dir; u32 out_data; u32 set_data; @@ -58,6 +58,12 @@ struct gpio_controller { u32 intstat; }; +struct davinci_gpio_controller { + struct davinci_gpio_regs __iomem *regs; + struct gpio_chip chip; + int irq_base; +}; + /* The __gpio_to_controller() and __gpio_mask() functions inline to constants * with constant parameters; or in outlined code they execute at runtime. * @@ -67,7 +73,7 @@ struct gpio_controller { * * These are NOT part of the cross-platform GPIO interface */ -static inline struct gpio_controller __iomem * +static inline struct davinci_gpio_regs __iomem * __gpio_to_controller(unsigned gpio) { void __iomem *ptr; @@ -102,7 +108,7 @@ static inline u32 __gpio_mask(unsigned gpio) static inline void gpio_set_value(unsigned gpio, int value) { if (__builtin_constant_p(value) && gpio < DAVINCI_N_GPIO) { - struct gpio_controller __iomem *g; + struct davinci_gpio_regs __iomem *g; u32 mask; g = __gpio_to_controller(gpio); @@ -128,7 +134,7 @@ static inline void gpio_set_value(unsigned gpio, int value) */ static inline int gpio_get_value(unsigned gpio) { - struct gpio_controller __iomem *g; + struct davinci_gpio_regs __iomem *g; if (!__builtin_constant_p(gpio) || gpio >= DAVINCI_N_GPIO) return __gpio_get_value(gpio); -- cgit v0.10.2 From c12f415a9144a76dc99df34f56ce3022207ad1d0 Mon Sep 17 00:00:00 2001 From: Cyril Chemparathy Date: Sat, 1 May 2010 18:37:53 -0400 Subject: Davinci: gpio - register layout invariant inlines This patch renders the inlined gpio accessors in gpio.h independent of the underlying controller's register layout. This is done by including three new fields in davinci_gpio_controller to hold the addresses of the set, clear, and in data registers. Other changes: 1. davinci_gpio_regs structure definition moved to gpio.c. This structure is no longer common across all davinci socs (davinci_gpio_controller is). 2. controller base address calculation code (gpio2controller()) moved to gpio.c as this was no longer necessary for the inline implementation. 3. modified inline range checks to use davinci_soc_info.gpio_num instead of DAVINCI_N_GPIO. Signed-off-by: Cyril Chemparathy Tested-by: Sandeep Paulraj Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c index c77683c..d241b4f 100644 --- a/arch/arm/mach-davinci/gpio.c +++ b/arch/arm/mach-davinci/gpio.c @@ -20,6 +20,19 @@ #include +struct davinci_gpio_regs { + u32 dir; + u32 out_data; + u32 set_data; + u32 clr_data; + u32 in_data; + u32 set_rising; + u32 clr_rising; + u32 set_falling; + u32 clr_falling; + u32 intstat; +}; + static DEFINE_SPINLOCK(gpio_lock); #define chip2controller(chip) \ @@ -27,10 +40,24 @@ static DEFINE_SPINLOCK(gpio_lock); static struct davinci_gpio_controller chips[DIV_ROUND_UP(DAVINCI_N_GPIO, 32)]; -/* create a non-inlined version */ static struct davinci_gpio_regs __iomem __init *gpio2regs(unsigned gpio) { - return __gpio_to_controller(gpio); + void __iomem *ptr; + void __iomem *base = davinci_soc_info.gpio_base; + + if (gpio < 32 * 1) + ptr = base + 0x10; + else if (gpio < 32 * 2) + ptr = base + 0x38; + else if (gpio < 32 * 3) + ptr = base + 0x60; + else if (gpio < 32 * 4) + ptr = base + 0x88; + else if (gpio < 32 * 5) + ptr = base + 0xb0; + else + ptr = NULL; + return ptr; } static inline struct davinci_gpio_regs __iomem *irq2regs(int irq) @@ -116,6 +143,7 @@ static int __init davinci_gpio_setup(void) int i, base; unsigned ngpio; struct davinci_soc_info *soc_info = &davinci_soc_info; + struct davinci_gpio_regs *regs; /* * The gpio banks conceptually expose a segmented bitmap, @@ -144,11 +172,18 @@ static int __init davinci_gpio_setup(void) if (chips[i].chip.ngpio > 32) chips[i].chip.ngpio = 32; - chips[i].regs = gpio2regs(base); + regs = gpio2regs(base); + chips[i].regs = regs; + chips[i].set_data = ®s->set_data; + chips[i].clr_data = ®s->clr_data; + chips[i].in_data = ®s->in_data; gpiochip_add(&chips[i].chip); } + soc_info->gpio_ctlrs = chips; + soc_info->gpio_ctlrs_num = DIV_ROUND_UP(ngpio, 32); + davinci_gpio_irq_setup(); return 0; } diff --git a/arch/arm/mach-davinci/include/mach/common.h b/arch/arm/mach-davinci/include/mach/common.h index 884dc72..1d72883 100644 --- a/arch/arm/mach-davinci/include/mach/common.h +++ b/arch/arm/mach-davinci/include/mach/common.h @@ -37,6 +37,8 @@ struct davinci_timer_info { unsigned int clocksource_id; }; +struct davinci_gpio_controller; + /* SoC specific init support */ struct davinci_soc_info { struct map_desc *io_desc; @@ -61,6 +63,8 @@ struct davinci_soc_info { unsigned gpio_num; unsigned gpio_irq; unsigned gpio_unbanked; + struct davinci_gpio_controller *gpio_ctlrs; + int gpio_ctlrs_num; struct platform_device *serial_dev; struct emac_platform_data *emac_pdata; dma_addr_t sram_dma; diff --git a/arch/arm/mach-davinci/include/mach/gpio.h b/arch/arm/mach-davinci/include/mach/gpio.h index bdab001..82591d0 100644 --- a/arch/arm/mach-davinci/include/mach/gpio.h +++ b/arch/arm/mach-davinci/include/mach/gpio.h @@ -45,23 +45,13 @@ /* Convert GPIO signal to GPIO pin number */ #define GPIO_TO_PIN(bank, gpio) (16 * (bank) + (gpio)) -struct davinci_gpio_regs { - u32 dir; - u32 out_data; - u32 set_data; - u32 clr_data; - u32 in_data; - u32 set_rising; - u32 clr_rising; - u32 set_falling; - u32 clr_falling; - u32 intstat; -}; - struct davinci_gpio_controller { - struct davinci_gpio_regs __iomem *regs; struct gpio_chip chip; int irq_base; + void __iomem *regs; + void __iomem *set_data; + void __iomem *clr_data; + void __iomem *in_data; }; /* The __gpio_to_controller() and __gpio_mask() functions inline to constants @@ -73,25 +63,16 @@ struct davinci_gpio_controller { * * These are NOT part of the cross-platform GPIO interface */ -static inline struct davinci_gpio_regs __iomem * +static inline struct davinci_gpio_controller * __gpio_to_controller(unsigned gpio) { - void __iomem *ptr; - void __iomem *base = davinci_soc_info.gpio_base; - - if (gpio < 32 * 1) - ptr = base + 0x10; - else if (gpio < 32 * 2) - ptr = base + 0x38; - else if (gpio < 32 * 3) - ptr = base + 0x60; - else if (gpio < 32 * 4) - ptr = base + 0x88; - else if (gpio < 32 * 5) - ptr = base + 0xb0; - else - ptr = NULL; - return ptr; + struct davinci_gpio_controller *ctlrs = davinci_soc_info.gpio_ctlrs; + int index = gpio / 32; + + if (!ctlrs || index >= davinci_soc_info.gpio_ctlrs_num) + return NULL; + + return ctlrs + index; } static inline u32 __gpio_mask(unsigned gpio) @@ -107,16 +88,16 @@ static inline u32 __gpio_mask(unsigned gpio) */ static inline void gpio_set_value(unsigned gpio, int value) { - if (__builtin_constant_p(value) && gpio < DAVINCI_N_GPIO) { - struct davinci_gpio_regs __iomem *g; - u32 mask; + if (__builtin_constant_p(value) && gpio < davinci_soc_info.gpio_num) { + struct davinci_gpio_controller *ctlr; + u32 mask; - g = __gpio_to_controller(gpio); + ctlr = __gpio_to_controller(gpio); mask = __gpio_mask(gpio); if (value) - __raw_writel(mask, &g->set_data); + __raw_writel(mask, ctlr->set_data); else - __raw_writel(mask, &g->clr_data); + __raw_writel(mask, ctlr->clr_data); return; } @@ -134,18 +115,18 @@ static inline void gpio_set_value(unsigned gpio, int value) */ static inline int gpio_get_value(unsigned gpio) { - struct davinci_gpio_regs __iomem *g; + struct davinci_gpio_controller *ctlr; - if (!__builtin_constant_p(gpio) || gpio >= DAVINCI_N_GPIO) + if (!__builtin_constant_p(gpio) || gpio >= davinci_soc_info.gpio_num) return __gpio_get_value(gpio); - g = __gpio_to_controller(gpio); - return __gpio_mask(gpio) & __raw_readl(&g->in_data); + ctlr = __gpio_to_controller(gpio); + return __gpio_mask(gpio) & __raw_readl(ctlr->in_data); } static inline int gpio_cansleep(unsigned gpio) { - if (__builtin_constant_p(gpio) && gpio < DAVINCI_N_GPIO) + if (__builtin_constant_p(gpio) && gpio < davinci_soc_info.gpio_num) return 0; else return __gpio_cansleep(gpio); -- cgit v0.10.2 From 686b634a07451fc4fe3b712fe211bfa861a53241 Mon Sep 17 00:00:00 2001 From: Cyril Chemparathy Date: Sat, 1 May 2010 18:37:54 -0400 Subject: Davinci: gpio - controller type support This patch allows for gpio controllers that deviate from those found on traditional davinci socs. davinci_soc_info has an added field to indicate the soc-specific gpio controller type. The gpio initialization code then bails out if necessary. More elements (tnetv107x) to be added later into enum davinci_gpio_type. Signed-off-by: Cyril Chemparathy Tested-by: Sandeep Paulraj Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c index 122e61a..68e5233 100644 --- a/arch/arm/mach-davinci/da830.c +++ b/arch/arm/mach-davinci/da830.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "clock.h" #include "mux.h" @@ -1199,6 +1200,7 @@ static struct davinci_soc_info davinci_soc_info_da830 = { .intc_irq_prios = da830_default_priorities, .intc_irq_num = DA830_N_CP_INTC_IRQ, .timer_info = &da830_timer_info, + .gpio_type = GPIO_TYPE_DAVINCI, .gpio_base = IO_ADDRESS(DA8XX_GPIO_BASE), .gpio_num = 128, .gpio_irq = IRQ_DA8XX_GPIO0, diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c index d0fd756..8aefcff 100644 --- a/arch/arm/mach-davinci/da850.c +++ b/arch/arm/mach-davinci/da850.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "clock.h" #include "mux.h" @@ -1084,6 +1085,7 @@ static struct davinci_soc_info davinci_soc_info_da850 = { .intc_irq_prios = da850_default_priorities, .intc_irq_num = DA850_N_CP_INTC_IRQ, .timer_info = &da850_timer_info, + .gpio_type = GPIO_TYPE_DAVINCI, .gpio_base = IO_ADDRESS(DA8XX_GPIO_BASE), .gpio_num = 144, .gpio_irq = IRQ_DA8XX_GPIO0, diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c index 5efce70..f9a54ff 100644 --- a/arch/arm/mach-davinci/dm355.c +++ b/arch/arm/mach-davinci/dm355.c @@ -859,6 +859,7 @@ static struct davinci_soc_info davinci_soc_info_dm355 = { .intc_irq_prios = dm355_default_priorities, .intc_irq_num = DAVINCI_N_AINTC_IRQ, .timer_info = &dm355_timer_info, + .gpio_type = GPIO_TYPE_DAVINCI, .gpio_base = IO_ADDRESS(DAVINCI_GPIO_BASE), .gpio_num = 104, .gpio_irq = IRQ_DM355_GPIOBNK0, diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index 1ee3fc8..0566675 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -1064,6 +1064,7 @@ static struct davinci_soc_info davinci_soc_info_dm365 = { .intc_irq_prios = dm365_default_priorities, .intc_irq_num = DAVINCI_N_AINTC_IRQ, .timer_info = &dm365_timer_info, + .gpio_type = GPIO_TYPE_DAVINCI, .gpio_base = IO_ADDRESS(DAVINCI_GPIO_BASE), .gpio_num = 104, .gpio_irq = IRQ_DM365_GPIO0, diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index 23cbe9d..4af349e 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c @@ -748,6 +748,7 @@ static struct davinci_soc_info davinci_soc_info_dm644x = { .intc_irq_prios = dm644x_default_priorities, .intc_irq_num = DAVINCI_N_AINTC_IRQ, .timer_info = &dm644x_timer_info, + .gpio_type = GPIO_TYPE_DAVINCI, .gpio_base = IO_ADDRESS(DAVINCI_GPIO_BASE), .gpio_num = 71, .gpio_irq = IRQ_GPIOBNK0, diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index a0b3739..bdb1ace 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -832,6 +832,7 @@ static struct davinci_soc_info davinci_soc_info_dm646x = { .intc_irq_prios = dm646x_default_priorities, .intc_irq_num = DAVINCI_N_AINTC_IRQ, .timer_info = &dm646x_timer_info, + .gpio_type = GPIO_TYPE_DAVINCI, .gpio_base = IO_ADDRESS(DAVINCI_GPIO_BASE), .gpio_num = 43, /* Only 33 usable */ .gpio_irq = IRQ_DM646X_GPIOBNK0, diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c index d241b4f..e422cd3 100644 --- a/arch/arm/mach-davinci/gpio.c +++ b/arch/arm/mach-davinci/gpio.c @@ -145,6 +145,9 @@ static int __init davinci_gpio_setup(void) struct davinci_soc_info *soc_info = &davinci_soc_info; struct davinci_gpio_regs *regs; + if (soc_info->gpio_type != GPIO_TYPE_DAVINCI) + return 0; + /* * The gpio banks conceptually expose a segmented bitmap, * and "ngpio" is one more than the largest zero-based diff --git a/arch/arm/mach-davinci/include/mach/common.h b/arch/arm/mach-davinci/include/mach/common.h index 1d72883..8ffef5b 100644 --- a/arch/arm/mach-davinci/include/mach/common.h +++ b/arch/arm/mach-davinci/include/mach/common.h @@ -59,6 +59,7 @@ struct davinci_soc_info { u8 *intc_irq_prios; unsigned long intc_irq_num; struct davinci_timer_info *timer_info; + int gpio_type; void __iomem *gpio_base; unsigned gpio_num; unsigned gpio_irq; diff --git a/arch/arm/mach-davinci/include/mach/gpio.h b/arch/arm/mach-davinci/include/mach/gpio.h index 82591d0..9a71a26 100644 --- a/arch/arm/mach-davinci/include/mach/gpio.h +++ b/arch/arm/mach-davinci/include/mach/gpio.h @@ -21,6 +21,10 @@ #define DAVINCI_GPIO_BASE 0x01C67000 +enum davinci_gpio_type { + GPIO_TYPE_DAVINCI = 0, +}; + /* * basic gpio routines * -- cgit v0.10.2 From b27b6d03f245e5eaf6473da58a2612077fb7cfe7 Mon Sep 17 00:00:00 2001 From: Cyril Chemparathy Date: Sat, 1 May 2010 18:37:55 -0400 Subject: Davinci: gpio - fine grained locking This patch eliminates the global gpio_lock, and implements a per-controller lock instead. This also switches to irqsave/irqrestore locks in case gpios are manipulated in isr. Signed-off-by: Cyril Chemparathy Tested-by: Sandeep Paulraj Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c index e422cd3..b62d5e2 100644 --- a/arch/arm/mach-davinci/gpio.c +++ b/arch/arm/mach-davinci/gpio.c @@ -33,8 +33,6 @@ struct davinci_gpio_regs { u32 intstat; }; -static DEFINE_SPINLOCK(gpio_lock); - #define chip2controller(chip) \ container_of(chip, struct davinci_gpio_controller, chip) @@ -83,10 +81,11 @@ static inline int __davinci_direction(struct gpio_chip *chip, { struct davinci_gpio_controller *d = chip2controller(chip); struct davinci_gpio_regs __iomem *g = d->regs; + unsigned long flags; u32 temp; u32 mask = 1 << offset; - spin_lock(&gpio_lock); + spin_lock_irqsave(&d->lock, flags); temp = __raw_readl(&g->dir); if (out) { temp &= ~mask; @@ -95,7 +94,7 @@ static inline int __davinci_direction(struct gpio_chip *chip, temp |= mask; } __raw_writel(temp, &g->dir); - spin_unlock(&gpio_lock); + spin_unlock_irqrestore(&d->lock, flags); return 0; } @@ -175,6 +174,8 @@ static int __init davinci_gpio_setup(void) if (chips[i].chip.ngpio > 32) chips[i].chip.ngpio = 32; + spin_lock_init(&chips[i].lock); + regs = gpio2regs(base); chips[i].regs = regs; chips[i].set_data = ®s->set_data; diff --git a/arch/arm/mach-davinci/include/mach/gpio.h b/arch/arm/mach-davinci/include/mach/gpio.h index 9a71a26..504cc18 100644 --- a/arch/arm/mach-davinci/include/mach/gpio.h +++ b/arch/arm/mach-davinci/include/mach/gpio.h @@ -14,6 +14,8 @@ #define __DAVINCI_GPIO_H #include +#include + #include #include @@ -52,6 +54,7 @@ enum davinci_gpio_type { struct davinci_gpio_controller { struct gpio_chip chip; int irq_base; + spinlock_t lock; void __iomem *regs; void __iomem *set_data; void __iomem *clr_data; -- cgit v0.10.2 From 5b3a05ca911688c53680f2b020a1512b9da29c89 Mon Sep 17 00:00:00 2001 From: Cyril Chemparathy Date: Sat, 1 May 2010 18:38:27 -0400 Subject: Davinci: eliminate pinmux offset verbosity Pinmux registers are sequential, and do not need to be enumerated out as they currently are. This reduces code volume and keeps things simple. If some future SoC comes up with a discontiguous register map, PINMUX() can then be expanded with local token pasting. Signed-off-by: Cyril Chemparathy Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c index f9a54ff..f91e9a1 100644 --- a/arch/arm/mach-davinci/dm355.c +++ b/arch/arm/mach-davinci/dm355.c @@ -450,11 +450,6 @@ void __init dm355_init_spi0(unsigned chipselect_mask, /*----------------------------------------------------------------------*/ -#define PINMUX0 0x00 -#define PINMUX1 0x04 -#define PINMUX2 0x08 -#define PINMUX3 0x0c -#define PINMUX4 0x10 #define INTMUX 0x18 #define EVTMUX 0x1c diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index 0566675..f2b1d93 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -467,11 +467,6 @@ static struct clk_lookup dm365_clks[] = { /*----------------------------------------------------------------------*/ -#define PINMUX0 0x00 -#define PINMUX1 0x04 -#define PINMUX2 0x08 -#define PINMUX3 0x0c -#define PINMUX4 0x10 #define INTMUX 0x18 #define EVTMUX 0x1c diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index 4af349e..85c88ec 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c @@ -350,9 +350,6 @@ static struct platform_device dm644x_emac_device = { .resource = dm644x_emac_resources, }; -#define PINMUX0 0x00 -#define PINMUX1 0x04 - /* * Device specific mux setup * diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index bdb1ace..a8189c9 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -401,9 +401,6 @@ static struct platform_device dm646x_emac_device = { .resource = dm646x_emac_resources, }; -#define PINMUX0 0x00 -#define PINMUX1 0x04 - /* * Device specific mux setup * diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c index b62d5e2..2efb446 100644 --- a/arch/arm/mach-davinci/gpio.c +++ b/arch/arm/mach-davinci/gpio.c @@ -71,11 +71,7 @@ static int __init davinci_gpio_irq_setup(void); /*--------------------------------------------------------------------------*/ -/* - * board setup code *MUST* set PINMUX0 and PINMUX1 as - * needed, and enable the GPIO clock. - */ - +/* board setup code *MUST* setup pinmux and enable the GPIO clock. */ static inline int __davinci_direction(struct gpio_chip *chip, unsigned offset, bool out, int value) { diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h index 33471c9..dbb4ebe 100644 --- a/arch/arm/mach-davinci/include/mach/da8xx.h +++ b/arch/arm/mach-davinci/include/mach/da8xx.h @@ -64,27 +64,6 @@ extern void __iomem *da8xx_syscfg1_base; #define DA8XX_DDR2_CTL_BASE 0xb0000000 #define DA8XX_ARM_RAM_BASE 0xffff0000 -#define PINMUX0 0x00 -#define PINMUX1 0x04 -#define PINMUX2 0x08 -#define PINMUX3 0x0c -#define PINMUX4 0x10 -#define PINMUX5 0x14 -#define PINMUX6 0x18 -#define PINMUX7 0x1c -#define PINMUX8 0x20 -#define PINMUX9 0x24 -#define PINMUX10 0x28 -#define PINMUX11 0x2c -#define PINMUX12 0x30 -#define PINMUX13 0x34 -#define PINMUX14 0x38 -#define PINMUX15 0x3c -#define PINMUX16 0x40 -#define PINMUX17 0x44 -#define PINMUX18 0x48 -#define PINMUX19 0x4c - void __init da830_init(void); void __init da850_init(void); diff --git a/arch/arm/mach-davinci/include/mach/mux.h b/arch/arm/mach-davinci/include/mach/mux.h index 923debe..743dbd2 100644 --- a/arch/arm/mach-davinci/include/mach/mux.h +++ b/arch/arm/mach-davinci/include/mach/mux.h @@ -1174,6 +1174,8 @@ enum davinci_tnetv107x_index { TNETV107X_TDM0_RX, }; +#define PINMUX(x) (4 * (x)) + #ifdef CONFIG_DAVINCI_MUX /* setup pin muxing */ extern int davinci_cfg_reg(unsigned long reg_cfg); diff --git a/arch/arm/mach-davinci/mux.h b/arch/arm/mach-davinci/mux.h index adc8694..5aad1e7 100644 --- a/arch/arm/mach-davinci/mux.h +++ b/arch/arm/mach-davinci/mux.h @@ -20,7 +20,7 @@ .name = #desc, \ .debug = dbg, \ .mux_reg_name = "PINMUX"#muxreg, \ - .mux_reg = PINMUX##muxreg, \ + .mux_reg = PINMUX(muxreg), \ .mask_offset = mode_offset, \ .mask = mode_mask, \ .mode = mux_mode, \ -- cgit v0.10.2 From c78a5bc2e77e8fc5be29cda5b28c9b9afd0f4b6d Mon Sep 17 00:00:00 2001 From: Cyril Chemparathy Date: Sat, 1 May 2010 18:38:28 -0400 Subject: Davinci: watchdog reset separation across socs The earlier watchdog reset mechanism had a couple of limitations. First, it embedded a reference to "davinci_wdt_device" inside common code. This forced all derived platforms (da8xx and tnetv107x) to define such a device. This also would have caused problems in including multiple socs in a single build due to symbol redefinition. With this patch, davinci_watchdog_reset() now takes the platform device as an argument. The davinci_soc_info struct has been extended to include a reset function and a watchdog platform_device. arch_reset() then uses these elements to reset the system in a SoC specific fashion. Signed-off-by: Cyril Chemparathy Tested-by: Sandeep Paulraj Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h index ce26015..01e3648 100644 --- a/arch/arm/mach-davinci/clock.h +++ b/arch/arm/mach-davinci/clock.h @@ -120,6 +120,7 @@ int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv, unsigned int mult, unsigned int postdiv); extern struct platform_device davinci_wdt_device; +extern void davinci_watchdog_reset(struct platform_device *); #endif diff --git a/arch/arm/mach-davinci/common.c b/arch/arm/mach-davinci/common.c index 94f27cb..f8221c5 100644 --- a/arch/arm/mach-davinci/common.c +++ b/arch/arm/mach-davinci/common.c @@ -77,6 +77,9 @@ void __init davinci_common_init(struct davinci_soc_info *soc_info) local_flush_tlb_all(); flush_cache_all(); + if (!davinci_soc_info.reset) + davinci_soc_info.reset = davinci_watchdog_reset; + /* * We want to check CPU revision early for cpu_is_xxxx() macros. * IO space mapping must be initialized before we can do that. diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c index 68e5233..83879f8 100644 --- a/arch/arm/mach-davinci/da830.c +++ b/arch/arm/mach-davinci/da830.c @@ -1206,6 +1206,7 @@ static struct davinci_soc_info davinci_soc_info_da830 = { .gpio_irq = IRQ_DA8XX_GPIO0, .serial_dev = &da8xx_serial_device, .emac_pdata = &da8xx_emac_pdata, + .reset_device = &da8xx_wdt_device, }; void __init da830_init(void) diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c index 8aefcff..2b6dd59 100644 --- a/arch/arm/mach-davinci/da850.c +++ b/arch/arm/mach-davinci/da850.c @@ -1093,6 +1093,7 @@ static struct davinci_soc_info davinci_soc_info_da850 = { .emac_pdata = &da8xx_emac_pdata, .sram_dma = DA8XX_ARM_RAM_BASE, .sram_len = SZ_8K, + .reset_device = &da8xx_wdt_device, }; void __init da850_init(void) diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c index 0a96791..67a6fbc 100644 --- a/arch/arm/mach-davinci/devices-da8xx.c +++ b/arch/arm/mach-davinci/devices-da8xx.c @@ -326,7 +326,7 @@ static struct resource da8xx_watchdog_resources[] = { }, }; -struct platform_device davinci_wdt_device = { +struct platform_device da8xx_wdt_device = { .name = "watchdog", .id = -1, .num_resources = ARRAY_SIZE(da8xx_watchdog_resources), @@ -335,7 +335,7 @@ struct platform_device davinci_wdt_device = { int __init da8xx_register_watchdog(void) { - return platform_device_register(&davinci_wdt_device); + return platform_device_register(&da8xx_wdt_device); } static struct resource da8xx_emac_resources[] = { diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c index f91e9a1..0c62a68 100644 --- a/arch/arm/mach-davinci/dm355.c +++ b/arch/arm/mach-davinci/dm355.c @@ -861,6 +861,7 @@ static struct davinci_soc_info davinci_soc_info_dm355 = { .serial_dev = &dm355_serial_device, .sram_dma = 0x00010000, .sram_len = SZ_32K, + .reset_device = &davinci_wdt_device, }; void __init dm355_init_asp1(u32 evt_enable, struct snd_platform_data *pdata) diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index f2b1d93..ed76450 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -1068,6 +1068,7 @@ static struct davinci_soc_info davinci_soc_info_dm365 = { .emac_pdata = &dm365_emac_pdata, .sram_dma = 0x00010000, .sram_len = SZ_32K, + .reset_device = &davinci_wdt_device, }; void __init dm365_init_asp(struct snd_platform_data *pdata) diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index 85c88ec..7f36c22 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c @@ -753,6 +753,7 @@ static struct davinci_soc_info davinci_soc_info_dm644x = { .emac_pdata = &dm644x_emac_pdata, .sram_dma = 0x00008000, .sram_len = SZ_16K, + .reset_device = &davinci_wdt_device, }; void __init dm644x_init_asp(struct snd_platform_data *pdata) diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index a8189c9..8dd0afe 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -837,6 +837,7 @@ static struct davinci_soc_info davinci_soc_info_dm646x = { .emac_pdata = &dm646x_emac_pdata, .sram_dma = 0x10010000, .sram_len = SZ_32K, + .reset_device = &davinci_wdt_device, }; void __init dm646x_init_mcasp0(struct snd_platform_data *pdata) diff --git a/arch/arm/mach-davinci/include/mach/common.h b/arch/arm/mach-davinci/include/mach/common.h index 8ffef5b..a58bd88 100644 --- a/arch/arm/mach-davinci/include/mach/common.h +++ b/arch/arm/mach-davinci/include/mach/common.h @@ -70,6 +70,8 @@ struct davinci_soc_info { struct emac_platform_data *emac_pdata; dma_addr_t sram_dma; unsigned sram_len; + struct platform_device *reset_device; + void (*reset)(struct platform_device *); }; extern struct davinci_soc_info davinci_soc_info; diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h index dbb4ebe..1b31a9a 100644 --- a/arch/arm/mach-davinci/include/mach/da8xx.h +++ b/arch/arm/mach-davinci/include/mach/da8xx.h @@ -87,6 +87,8 @@ extern struct emac_platform_data da8xx_emac_pdata; extern struct da8xx_lcdc_platform_data sharp_lcd035q3dg01_pdata; extern struct da8xx_lcdc_platform_data sharp_lk043t1dg01_pdata; +extern struct platform_device da8xx_wdt_device; + extern const short da830_emif25_pins[]; extern const short da830_spi0_pins[]; extern const short da830_spi1_pins[]; diff --git a/arch/arm/mach-davinci/include/mach/system.h b/arch/arm/mach-davinci/include/mach/system.h index 5a7d758..e65629c 100644 --- a/arch/arm/mach-davinci/include/mach/system.h +++ b/arch/arm/mach-davinci/include/mach/system.h @@ -11,7 +11,7 @@ #ifndef __ASM_ARCH_SYSTEM_H #define __ASM_ARCH_SYSTEM_H -extern void davinci_watchdog_reset(void); +#include static inline void arch_idle(void) { @@ -20,7 +20,8 @@ static inline void arch_idle(void) static inline void arch_reset(char mode, const char *cmd) { - davinci_watchdog_reset(); + if (davinci_soc_info.reset) + davinci_soc_info.reset(davinci_soc_info.reset_device); } #endif /* __ASM_ARCH_SYSTEM_H */ diff --git a/arch/arm/mach-davinci/time.c b/arch/arm/mach-davinci/time.c index b21f763..e5c598a 100644 --- a/arch/arm/mach-davinci/time.c +++ b/arch/arm/mach-davinci/time.c @@ -399,13 +399,16 @@ struct sys_timer davinci_timer = { /* reset board using watchdog timer */ -void davinci_watchdog_reset(void) +void davinci_watchdog_reset(struct platform_device *pdev) { u32 tgcr, wdtcr; - struct platform_device *pdev = &davinci_wdt_device; - void __iomem *base = IO_ADDRESS(pdev->resource[0].start); + void __iomem *base; struct clk *wd_clk; + base = ioremap(pdev->resource[0].start, SZ_4K); + if (WARN_ON(!base)) + return; + wd_clk = clk_get(&pdev->dev, NULL); if (WARN_ON(IS_ERR(wd_clk))) return; -- cgit v0.10.2 From da0122ca8b7804b9cd8fa7eff466bafba27f09a3 Mon Sep 17 00:00:00 2001 From: Cyril Chemparathy Date: Sun, 2 May 2010 14:28:12 -0400 Subject: Davinci: serial - remove unnecessary define The uart pdata array is already terminated by a zero flag field. This patch reuses this terminator and eliminates DAVINCI_MAX_NR_UARTS definition. This way, future platforms can have different number of uarts initialized via davinci_serial_init(). Signed-off-by: Cyril Chemparathy Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/include/mach/serial.h b/arch/arm/mach-davinci/include/mach/serial.h index a584697..f6c4f34 100644 --- a/arch/arm/mach-davinci/include/mach/serial.h +++ b/arch/arm/mach-davinci/include/mach/serial.h @@ -13,7 +13,6 @@ #include -#define DAVINCI_MAX_NR_UARTS 3 #define DAVINCI_UART0_BASE (IO_PHYS + 0x20000) #define DAVINCI_UART1_BASE (IO_PHYS + 0x20400) #define DAVINCI_UART2_BASE (IO_PHYS + 0x20800) diff --git a/arch/arm/mach-davinci/serial.c b/arch/arm/mach-davinci/serial.c index 7ce5ba0..709e1a9 100644 --- a/arch/arm/mach-davinci/serial.c +++ b/arch/arm/mach-davinci/serial.c @@ -77,7 +77,7 @@ int __init davinci_serial_init(struct davinci_uart_config *info) * Make sure the serial ports are muxed on at this point. * You have to mux them off in device drivers later on if not needed. */ - for (i = 0; i < DAVINCI_MAX_NR_UARTS; i++, p++) { + for (i = 0; p->flags; i++, p++) { if (!(info->enabled_uarts & (1 << i))) continue; -- cgit v0.10.2 From 9ee1acefa86083c6acf4112983b88a0057eb7785 Mon Sep 17 00:00:00 2001 From: Cyril Chemparathy Date: Sun, 2 May 2010 14:28:13 -0400 Subject: Davinci: serial - use ioremap() This patch implements davinci serial cleanups towards having this code reusable on tnetv107x. The change reuses the platform data membase field to hold the remapped space. By disabling the UPF_IOREMAP flag in the platform data, we prevent the 8250 driver from repeating the ioremap. Signed-off-by: Cyril Chemparathy Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/serial.c b/arch/arm/mach-davinci/serial.c index 709e1a9..81af42c 100644 --- a/arch/arm/mach-davinci/serial.c +++ b/arch/arm/mach-davinci/serial.c @@ -35,14 +35,20 @@ static inline unsigned int serial_read_reg(struct plat_serial8250_port *up, int offset) { offset <<= up->regshift; - return (unsigned int)__raw_readl(IO_ADDRESS(up->mapbase) + offset); + + WARN_ONCE(!up->membase, "unmapped read: uart[%d]\n", offset); + + return (unsigned int)__raw_readl(up->membase + offset); } static inline void serial_write_reg(struct plat_serial8250_port *p, int offset, int value) { offset <<= p->regshift; - __raw_writel(value, IO_ADDRESS(p->mapbase) + offset); + + WARN_ONCE(!p->membase, "unmapped write: uart[%d]\n", offset); + + __raw_writel(value, p->membase + offset); } static void __init davinci_serial_reset(struct plat_serial8250_port *p) @@ -83,14 +89,26 @@ int __init davinci_serial_init(struct davinci_uart_config *info) sprintf(name, "uart%d", i); uart_clk = clk_get(dev, name); - if (IS_ERR(uart_clk)) + if (IS_ERR(uart_clk)) { printk(KERN_ERR "%s:%d: failed to get UART%d clock\n", __func__, __LINE__, i); - else { - clk_enable(uart_clk); - p->uartclk = clk_get_rate(uart_clk); - davinci_serial_reset(p); + continue; } + + clk_enable(uart_clk); + p->uartclk = clk_get_rate(uart_clk); + + if (!p->membase && p->mapbase) { + p->membase = ioremap(p->mapbase, SZ_4K); + + if (p->membase) + p->flags &= ~UPF_IOREMAP; + else + pr_err("uart regs ioremap failed\n"); + } + + if (p->membase) + davinci_serial_reset(p); } return platform_device_register(soc_info->serial_dev); -- cgit v0.10.2 From e2800007f3b9aab51c1fe866034db576d3a9fd83 Mon Sep 17 00:00:00 2001 From: Cyril Chemparathy Date: Sun, 2 May 2010 14:28:14 -0400 Subject: Davinci: serial - conditional reset via pwremu With this patch, AR7 type uart ports are not reset via pwremu registers. This allows davinci_serial_init() reuse on tnetv107x soc. Signed-off-by: Cyril Chemparathy Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/serial.c b/arch/arm/mach-davinci/serial.c index 81af42c..1875740 100644 --- a/arch/arm/mach-davinci/serial.c +++ b/arch/arm/mach-davinci/serial.c @@ -107,7 +107,7 @@ int __init davinci_serial_init(struct davinci_uart_config *info) pr_err("uart regs ioremap failed\n"); } - if (p->membase) + if (p->membase && p->type != PORT_AR7) davinci_serial_reset(p); } -- cgit v0.10.2 From 3f68b98a75381f785f4e13085296c52c75ea29ac Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Tue, 4 May 2010 14:11:35 +0530 Subject: davinci: edma: use a more intuitive name for edma_info 'edma_info' structure inside the edma driver represents a single instance of edma channel controller. Call it 'edma_cc' instead. This also avoids readers confusing it with an instance of edma_soc_info structre which carries the platform data for a single channel controller instance. Signed-off-by: Sekhar Nori Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/dma.c b/arch/arm/mach-davinci/dma.c index 0bf290b..b705089 100644 --- a/arch/arm/mach-davinci/dma.c +++ b/arch/arm/mach-davinci/dma.c @@ -243,7 +243,7 @@ struct edma { } intr_data[EDMA_MAX_DMACH]; }; -static struct edma *edma_info[EDMA_MAX_CC]; +static struct edma *edma_cc[EDMA_MAX_CC]; static int arch_num_cc; /* dummy param set used to (re)initialize parameter RAM slots */ @@ -261,7 +261,7 @@ static void map_dmach_queue(unsigned ctlr, unsigned ch_no, /* default to low priority queue */ if (queue_no == EVENTQ_DEFAULT) - queue_no = edma_info[ctlr]->default_queue; + queue_no = edma_cc[ctlr]->default_queue; queue_no &= 7; edma_modify_array(ctlr, EDMA_DMAQNUM, (ch_no >> 3), @@ -315,8 +315,8 @@ setup_dma_interrupt(unsigned lch, (1 << (lch & 0x1f))); } - edma_info[ctlr]->intr_data[lch].callback = callback; - edma_info[ctlr]->intr_data[lch].data = data; + edma_cc[ctlr]->intr_data[lch].callback = callback; + edma_cc[ctlr]->intr_data[lch].data = data; if (callback) { edma_shadow0_write_array(ctlr, SH_ICR, lch >> 5, @@ -328,11 +328,10 @@ setup_dma_interrupt(unsigned lch, static int irq2ctlr(int irq) { - if (irq >= edma_info[0]->irq_res_start && - irq <= edma_info[0]->irq_res_end) + if (irq >= edma_cc[0]->irq_res_start && irq <= edma_cc[0]->irq_res_end) return 0; - else if (irq >= edma_info[1]->irq_res_start && - irq <= edma_info[1]->irq_res_end) + else if (irq >= edma_cc[1]->irq_res_start && + irq <= edma_cc[1]->irq_res_end) return 1; return -1; @@ -377,10 +376,10 @@ static irqreturn_t dma_irq_handler(int irq, void *data) /* Clear the corresponding IPR bits */ edma_shadow0_write_array(ctlr, SH_ICR, j, (1 << i)); - if (edma_info[ctlr]->intr_data[k].callback) { - edma_info[ctlr]->intr_data[k].callback( + if (edma_cc[ctlr]->intr_data[k].callback) { + edma_cc[ctlr]->intr_data[k].callback( k, DMA_COMPLETE, - edma_info[ctlr]->intr_data[k]. + edma_cc[ctlr]->intr_data[k]. data); } } @@ -433,12 +432,12 @@ static irqreturn_t dma_ccerr_handler(int irq, void *data) /* Clear any SER */ edma_shadow0_write_array(ctlr, SH_SECR, j, (1 << i)); - if (edma_info[ctlr]->intr_data[k]. + if (edma_cc[ctlr]->intr_data[k]. callback) { - edma_info[ctlr]->intr_data[k]. + edma_cc[ctlr]->intr_data[k]. callback(k, DMA_CC_ERROR, - edma_info[ctlr]->intr_data + edma_cc[ctlr]->intr_data [k].data); } } @@ -514,9 +513,9 @@ static int reserve_contiguous_slots(int ctlr, unsigned int id, int stop_slot = start_slot; DECLARE_BITMAP(tmp_inuse, EDMA_MAX_PARAMENTRY); - for (i = start_slot; i < edma_info[ctlr]->num_slots; ++i) { + for (i = start_slot; i < edma_cc[ctlr]->num_slots; ++i) { j = EDMA_CHAN_SLOT(i); - if (!test_and_set_bit(j, edma_info[ctlr]->edma_inuse)) { + if (!test_and_set_bit(j, edma_cc[ctlr]->edma_inuse)) { /* Record our current beginning slot */ if (count == num_slots) stop_slot = i; @@ -543,12 +542,12 @@ static int reserve_contiguous_slots(int ctlr, unsigned int id, * of contiguous parameter RAM slots but do not find the exact number * requested as we may reach the total number of parameter RAM slots */ - if (i == edma_info[ctlr]->num_slots) + if (i == edma_cc[ctlr]->num_slots) stop_slot = i; for (j = start_slot; j < stop_slot; j++) if (test_bit(j, tmp_inuse)) - clear_bit(j, edma_info[ctlr]->edma_inuse); + clear_bit(j, edma_cc[ctlr]->edma_inuse); if (count) return -EBUSY; @@ -570,7 +569,7 @@ static int prepare_unused_channel_list(struct device *dev, void *data) (int)pdev->resource[i].start >= 0) { ctlr = EDMA_CTLR(pdev->resource[i].start); clear_bit(EDMA_CHAN_SLOT(pdev->resource[i].start), - edma_info[ctlr]->edma_unused); + edma_cc[ctlr]->edma_unused); } } @@ -644,14 +643,13 @@ int edma_alloc_channel(int channel, for (i = 0; i < arch_num_cc; i++) { channel = 0; for (;;) { - channel = find_next_bit(edma_info[i]-> - edma_unused, - edma_info[i]->num_channels, + channel = find_next_bit(edma_cc[i]->edma_unused, + edma_cc[i]->num_channels, channel); - if (channel == edma_info[i]->num_channels) + if (channel == edma_cc[i]->num_channels) break; if (!test_and_set_bit(channel, - edma_info[i]->edma_inuse)) { + edma_cc[i]->edma_inuse)) { done = 1; ctlr = i; break; @@ -663,9 +661,9 @@ int edma_alloc_channel(int channel, } if (!done) return -ENOMEM; - } else if (channel >= edma_info[ctlr]->num_channels) { + } else if (channel >= edma_cc[ctlr]->num_channels) { return -EINVAL; - } else if (test_and_set_bit(channel, edma_info[ctlr]->edma_inuse)) { + } else if (test_and_set_bit(channel, edma_cc[ctlr]->edma_inuse)) { return -EBUSY; } @@ -706,7 +704,7 @@ void edma_free_channel(unsigned channel) ctlr = EDMA_CTLR(channel); channel = EDMA_CHAN_SLOT(channel); - if (channel >= edma_info[ctlr]->num_channels) + if (channel >= edma_cc[ctlr]->num_channels) return; setup_dma_interrupt(channel, NULL, NULL); @@ -714,7 +712,7 @@ void edma_free_channel(unsigned channel) memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(channel), &dummy_paramset, PARM_SIZE); - clear_bit(channel, edma_info[ctlr]->edma_inuse); + clear_bit(channel, edma_cc[ctlr]->edma_inuse); } EXPORT_SYMBOL(edma_free_channel); @@ -738,20 +736,19 @@ int edma_alloc_slot(unsigned ctlr, int slot) slot = EDMA_CHAN_SLOT(slot); if (slot < 0) { - slot = edma_info[ctlr]->num_channels; + slot = edma_cc[ctlr]->num_channels; for (;;) { - slot = find_next_zero_bit(edma_info[ctlr]->edma_inuse, - edma_info[ctlr]->num_slots, slot); - if (slot == edma_info[ctlr]->num_slots) + slot = find_next_zero_bit(edma_cc[ctlr]->edma_inuse, + edma_cc[ctlr]->num_slots, slot); + if (slot == edma_cc[ctlr]->num_slots) return -ENOMEM; - if (!test_and_set_bit(slot, - edma_info[ctlr]->edma_inuse)) + if (!test_and_set_bit(slot, edma_cc[ctlr]->edma_inuse)) break; } - } else if (slot < edma_info[ctlr]->num_channels || - slot >= edma_info[ctlr]->num_slots) { + } else if (slot < edma_cc[ctlr]->num_channels || + slot >= edma_cc[ctlr]->num_slots) { return -EINVAL; - } else if (test_and_set_bit(slot, edma_info[ctlr]->edma_inuse)) { + } else if (test_and_set_bit(slot, edma_cc[ctlr]->edma_inuse)) { return -EBUSY; } @@ -777,13 +774,13 @@ void edma_free_slot(unsigned slot) ctlr = EDMA_CTLR(slot); slot = EDMA_CHAN_SLOT(slot); - if (slot < edma_info[ctlr]->num_channels || - slot >= edma_info[ctlr]->num_slots) + if (slot < edma_cc[ctlr]->num_channels || + slot >= edma_cc[ctlr]->num_slots) return; memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(slot), &dummy_paramset, PARM_SIZE); - clear_bit(slot, edma_info[ctlr]->edma_inuse); + clear_bit(slot, edma_cc[ctlr]->edma_inuse); } EXPORT_SYMBOL(edma_free_slot); @@ -821,8 +818,8 @@ int edma_alloc_cont_slots(unsigned ctlr, unsigned int id, int slot, int count) * of slots */ if ((id != EDMA_CONT_PARAMS_ANY) && - (slot < edma_info[ctlr]->num_channels || - slot >= edma_info[ctlr]->num_slots)) + (slot < edma_cc[ctlr]->num_channels || + slot >= edma_cc[ctlr]->num_slots)) return -EINVAL; /* @@ -831,13 +828,13 @@ int edma_alloc_cont_slots(unsigned ctlr, unsigned int id, int slot, int count) * channels */ if (count < 1 || count > - (edma_info[ctlr]->num_slots - edma_info[ctlr]->num_channels)) + (edma_cc[ctlr]->num_slots - edma_cc[ctlr]->num_channels)) return -EINVAL; switch (id) { case EDMA_CONT_PARAMS_ANY: return reserve_contiguous_slots(ctlr, id, count, - edma_info[ctlr]->num_channels); + edma_cc[ctlr]->num_channels); case EDMA_CONT_PARAMS_FIXED_EXACT: case EDMA_CONT_PARAMS_FIXED_NOT_EXACT: return reserve_contiguous_slots(ctlr, id, count, slot); @@ -869,8 +866,8 @@ int edma_free_cont_slots(unsigned slot, int count) ctlr = EDMA_CTLR(slot); slot = EDMA_CHAN_SLOT(slot); - if (slot < edma_info[ctlr]->num_channels || - slot >= edma_info[ctlr]->num_slots || + if (slot < edma_cc[ctlr]->num_channels || + slot >= edma_cc[ctlr]->num_slots || count < 1) return -EINVAL; @@ -880,7 +877,7 @@ int edma_free_cont_slots(unsigned slot, int count) memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(slot_to_free), &dummy_paramset, PARM_SIZE); - clear_bit(slot_to_free, edma_info[ctlr]->edma_inuse); + clear_bit(slot_to_free, edma_cc[ctlr]->edma_inuse); } return 0; @@ -910,7 +907,7 @@ void edma_set_src(unsigned slot, dma_addr_t src_port, ctlr = EDMA_CTLR(slot); slot = EDMA_CHAN_SLOT(slot); - if (slot < edma_info[ctlr]->num_slots) { + if (slot < edma_cc[ctlr]->num_slots) { unsigned int i = edma_parm_read(ctlr, PARM_OPT, slot); if (mode) { @@ -948,7 +945,7 @@ void edma_set_dest(unsigned slot, dma_addr_t dest_port, ctlr = EDMA_CTLR(slot); slot = EDMA_CHAN_SLOT(slot); - if (slot < edma_info[ctlr]->num_slots) { + if (slot < edma_cc[ctlr]->num_slots) { unsigned int i = edma_parm_read(ctlr, PARM_OPT, slot); if (mode) { @@ -1008,7 +1005,7 @@ void edma_set_src_index(unsigned slot, s16 src_bidx, s16 src_cidx) ctlr = EDMA_CTLR(slot); slot = EDMA_CHAN_SLOT(slot); - if (slot < edma_info[ctlr]->num_slots) { + if (slot < edma_cc[ctlr]->num_slots) { edma_parm_modify(ctlr, PARM_SRC_DST_BIDX, slot, 0xffff0000, src_bidx); edma_parm_modify(ctlr, PARM_SRC_DST_CIDX, slot, @@ -1034,7 +1031,7 @@ void edma_set_dest_index(unsigned slot, s16 dest_bidx, s16 dest_cidx) ctlr = EDMA_CTLR(slot); slot = EDMA_CHAN_SLOT(slot); - if (slot < edma_info[ctlr]->num_slots) { + if (slot < edma_cc[ctlr]->num_slots) { edma_parm_modify(ctlr, PARM_SRC_DST_BIDX, slot, 0x0000ffff, dest_bidx << 16); edma_parm_modify(ctlr, PARM_SRC_DST_CIDX, slot, @@ -1081,7 +1078,7 @@ void edma_set_transfer_params(unsigned slot, ctlr = EDMA_CTLR(slot); slot = EDMA_CHAN_SLOT(slot); - if (slot < edma_info[ctlr]->num_slots) { + if (slot < edma_cc[ctlr]->num_slots) { edma_parm_modify(ctlr, PARM_LINK_BCNTRLD, slot, 0x0000ffff, bcnt_rld << 16); if (sync_mode == ASYNC) @@ -1111,9 +1108,9 @@ void edma_link(unsigned from, unsigned to) ctlr_to = EDMA_CTLR(to); to = EDMA_CHAN_SLOT(to); - if (from >= edma_info[ctlr_from]->num_slots) + if (from >= edma_cc[ctlr_from]->num_slots) return; - if (to >= edma_info[ctlr_to]->num_slots) + if (to >= edma_cc[ctlr_to]->num_slots) return; edma_parm_modify(ctlr_from, PARM_LINK_BCNTRLD, from, 0xffff0000, PARM_OFFSET(to)); @@ -1134,7 +1131,7 @@ void edma_unlink(unsigned from) ctlr = EDMA_CTLR(from); from = EDMA_CHAN_SLOT(from); - if (from >= edma_info[ctlr]->num_slots) + if (from >= edma_cc[ctlr]->num_slots) return; edma_parm_or(ctlr, PARM_LINK_BCNTRLD, from, 0xffff); } @@ -1161,7 +1158,7 @@ void edma_write_slot(unsigned slot, const struct edmacc_param *param) ctlr = EDMA_CTLR(slot); slot = EDMA_CHAN_SLOT(slot); - if (slot >= edma_info[ctlr]->num_slots) + if (slot >= edma_cc[ctlr]->num_slots) return; memcpy_toio(edmacc_regs_base[ctlr] + PARM_OFFSET(slot), param, PARM_SIZE); @@ -1183,7 +1180,7 @@ void edma_read_slot(unsigned slot, struct edmacc_param *param) ctlr = EDMA_CTLR(slot); slot = EDMA_CHAN_SLOT(slot); - if (slot >= edma_info[ctlr]->num_slots) + if (slot >= edma_cc[ctlr]->num_slots) return; memcpy_fromio(param, edmacc_regs_base[ctlr] + PARM_OFFSET(slot), PARM_SIZE); @@ -1208,7 +1205,7 @@ void edma_pause(unsigned channel) ctlr = EDMA_CTLR(channel); channel = EDMA_CHAN_SLOT(channel); - if (channel < edma_info[ctlr]->num_channels) { + if (channel < edma_cc[ctlr]->num_channels) { unsigned int mask = (1 << (channel & 0x1f)); edma_shadow0_write_array(ctlr, SH_EECR, channel >> 5, mask); @@ -1229,7 +1226,7 @@ void edma_resume(unsigned channel) ctlr = EDMA_CTLR(channel); channel = EDMA_CHAN_SLOT(channel); - if (channel < edma_info[ctlr]->num_channels) { + if (channel < edma_cc[ctlr]->num_channels) { unsigned int mask = (1 << (channel & 0x1f)); edma_shadow0_write_array(ctlr, SH_EESR, channel >> 5, mask); @@ -1255,12 +1252,12 @@ int edma_start(unsigned channel) ctlr = EDMA_CTLR(channel); channel = EDMA_CHAN_SLOT(channel); - if (channel < edma_info[ctlr]->num_channels) { + if (channel < edma_cc[ctlr]->num_channels) { int j = channel >> 5; unsigned int mask = (1 << (channel & 0x1f)); /* EDMA channels without event association */ - if (test_bit(channel, edma_info[ctlr]->edma_unused)) { + if (test_bit(channel, edma_cc[ctlr]->edma_unused)) { pr_debug("EDMA: ESR%d %08x\n", j, edma_shadow0_read_array(ctlr, SH_ESR, j)); edma_shadow0_write_array(ctlr, SH_ESR, j, mask); @@ -1301,7 +1298,7 @@ void edma_stop(unsigned channel) ctlr = EDMA_CTLR(channel); channel = EDMA_CHAN_SLOT(channel); - if (channel < edma_info[ctlr]->num_channels) { + if (channel < edma_cc[ctlr]->num_channels) { int j = channel >> 5; unsigned int mask = (1 << (channel & 0x1f)); @@ -1340,7 +1337,7 @@ void edma_clean_channel(unsigned channel) ctlr = EDMA_CTLR(channel); channel = EDMA_CHAN_SLOT(channel); - if (channel < edma_info[ctlr]->num_channels) { + if (channel < edma_cc[ctlr]->num_channels) { int j = (channel >> 5); unsigned int mask = 1 << (channel & 0x1f); @@ -1368,7 +1365,7 @@ void edma_clear_event(unsigned channel) ctlr = EDMA_CTLR(channel); channel = EDMA_CHAN_SLOT(channel); - if (channel >= edma_info[ctlr]->num_channels) + if (channel >= edma_cc[ctlr]->num_channels) return; if (channel < 32) edma_write(ctlr, EDMA_ECR, 1 << channel); @@ -1423,38 +1420,37 @@ static int __init edma_probe(struct platform_device *pdev) goto fail1; } - edma_info[j] = kmalloc(sizeof(struct edma), GFP_KERNEL); - if (!edma_info[j]) { + edma_cc[j] = kmalloc(sizeof(struct edma), GFP_KERNEL); + if (!edma_cc[j]) { status = -ENOMEM; goto fail1; } - memset(edma_info[j], 0, sizeof(struct edma)); + memset(edma_cc[j], 0, sizeof(struct edma)); - edma_info[j]->num_channels = min_t(unsigned, info[j].n_channel, + edma_cc[j]->num_channels = min_t(unsigned, info[j].n_channel, EDMA_MAX_DMACH); - edma_info[j]->num_slots = min_t(unsigned, info[j].n_slot, + edma_cc[j]->num_slots = min_t(unsigned, info[j].n_slot, EDMA_MAX_PARAMENTRY); - edma_info[j]->num_cc = min_t(unsigned, info[j].n_cc, - EDMA_MAX_CC); + edma_cc[j]->num_cc = min_t(unsigned, info[j].n_cc, EDMA_MAX_CC); - edma_info[j]->default_queue = info[j].default_queue; - if (!edma_info[j]->default_queue) - edma_info[j]->default_queue = EVENTQ_1; + edma_cc[j]->default_queue = info[j].default_queue; + if (!edma_cc[j]->default_queue) + edma_cc[j]->default_queue = EVENTQ_1; dev_dbg(&pdev->dev, "DMA REG BASE ADDR=%p\n", edmacc_regs_base[j]); - for (i = 0; i < edma_info[j]->num_slots; i++) + for (i = 0; i < edma_cc[j]->num_slots; i++) memcpy_toio(edmacc_regs_base[j] + PARM_OFFSET(i), &dummy_paramset, PARM_SIZE); /* Mark all channels as unused */ - memset(edma_info[j]->edma_unused, 0xff, - sizeof(edma_info[j]->edma_unused)); + memset(edma_cc[j]->edma_unused, 0xff, + sizeof(edma_cc[j]->edma_unused)); sprintf(irq_name, "edma%d", j); irq[j] = platform_get_irq_byname(pdev, irq_name); - edma_info[j]->irq_res_start = irq[j]; + edma_cc[j]->irq_res_start = irq[j]; status = request_irq(irq[j], dma_irq_handler, 0, "edma", &pdev->dev); if (status < 0) { @@ -1465,7 +1461,7 @@ static int __init edma_probe(struct platform_device *pdev) sprintf(irq_name, "edma%d_err", j); err_irq[j] = platform_get_irq_byname(pdev, irq_name); - edma_info[j]->irq_res_end = err_irq[j]; + edma_cc[j]->irq_res_end = err_irq[j]; status = request_irq(err_irq[j], dma_ccerr_handler, 0, "edma_error", &pdev->dev); if (status < 0) { @@ -1478,7 +1474,7 @@ static int __init edma_probe(struct platform_device *pdev) * specified. This way, long transfers on the low priority queue * started by the codec engine will not cause audio defects. */ - for (i = 0; i < edma_info[j]->num_channels; i++) + for (i = 0; i < edma_cc[j]->num_channels; i++) map_dmach_queue(j, i, EVENTQ_1); queue_tc_mapping = info[j].queue_tc_mapping; @@ -1541,7 +1537,7 @@ fail1: release_mem_region(r[i]->start, len[i]); if (edmacc_regs_base[i]) iounmap(edmacc_regs_base[i]); - kfree(edma_info[i]); + kfree(edma_cc[i]); } return status; } -- cgit v0.10.2 From 243bc65447a74fbc674fc7fab6f212cce62e0152 Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Tue, 4 May 2010 14:11:36 +0530 Subject: davinci: edma: fix coding style issue related to usage of braces In the edma driver, there are couple of instances where braces are used for a single statement 'if' construct. There are other instances where 'else' part of the if-else construct does not use braces even if the 'if' part is a multi-line statement. This patch fixes both. Signed-off-by: Sekhar Nori Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/dma.c b/arch/arm/mach-davinci/dma.c index b705089..cc5fcda 100644 --- a/arch/arm/mach-davinci/dma.c +++ b/arch/arm/mach-davinci/dma.c @@ -310,10 +310,9 @@ setup_dma_interrupt(unsigned lch, ctlr = EDMA_CTLR(lch); lch = EDMA_CHAN_SLOT(lch); - if (!callback) { + if (!callback) edma_shadow0_write_array(ctlr, SH_IECR, lch >> 5, (1 << (lch & 0x1f))); - } edma_cc[ctlr]->intr_data[lch].callback = callback; edma_cc[ctlr]->intr_data[lch].data = data; @@ -376,12 +375,11 @@ static irqreturn_t dma_irq_handler(int irq, void *data) /* Clear the corresponding IPR bits */ edma_shadow0_write_array(ctlr, SH_ICR, j, (1 << i)); - if (edma_cc[ctlr]->intr_data[k].callback) { + if (edma_cc[ctlr]->intr_data[k].callback) edma_cc[ctlr]->intr_data[k].callback( k, DMA_COMPLETE, edma_cc[ctlr]->intr_data[k]. data); - } } } cnt++; @@ -473,9 +471,8 @@ static irqreturn_t dma_ccerr_handler(int irq, void *data) if ((edma_read_array(ctlr, EDMA_EMR, 0) == 0) && (edma_read_array(ctlr, EDMA_EMR, 1) == 0) && (edma_read(ctlr, EDMA_QEMR) == 0) - && (edma_read(ctlr, EDMA_CCERR) == 0)) { + && (edma_read(ctlr, EDMA_CCERR) == 0)) break; - } cnt++; if (cnt > 10) break; @@ -531,8 +528,9 @@ static int reserve_contiguous_slots(int ctlr, unsigned int id, if (id == EDMA_CONT_PARAMS_FIXED_EXACT) { stop_slot = i; break; - } else + } else { count = num_slots; + } } } @@ -1402,8 +1400,9 @@ static int __init edma_probe(struct platform_device *pdev) break; else return -ENODEV; - } else + } else { found = 1; + } len[j] = resource_size(r[j]); -- cgit v0.10.2 From d9f599e1e6d019968b35d2dc63074b9e8964fa69 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 20 Mar 2010 17:39:11 +0300 Subject: perf: Fix check at end of event search The original code doesn't work because "call" is never NULL there. Signed-off-by: Dan Carpenter LKML-Reference: <20100320143911.GF5331@bicker> Signed-off-by: Steven Rostedt diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c index 88c0b6d..58092d8 100644 --- a/kernel/trace/trace_events_filter.c +++ b/kernel/trace/trace_events_filter.c @@ -1398,7 +1398,7 @@ int ftrace_profile_set_filter(struct perf_event *event, int event_id, } err = -EINVAL; - if (!call) + if (&call->list == &ftrace_events) goto out_unlock; err = -EEXIST; -- cgit v0.10.2 From ff3c25fa1b7f0a3c7b112c25af6d259cb8c59bc1 Mon Sep 17 00:00:00 2001 From: Pinkava J Date: Thu, 6 May 2010 15:18:06 +0200 Subject: ARM: n30: Enable Acer n35 if Acer n30 is selected All code already present for Acer n35 is useless unless MACH_N35 is defined. Signed-off-by: Jiri Pinkava [ben-linux@fluff.org: minor edit of subject] Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig index 5547318..2b5a33f 100644 --- a/arch/arm/mach-s3c2410/Kconfig +++ b/arch/arm/mach-s3c2410/Kconfig @@ -95,12 +95,19 @@ config PM_H1940 config MACH_N30 bool "Acer N30 family" select CPU_S3C2410 + select MACH_N35 select S3C_DEV_USB_HOST select S3C_DEV_NAND help Say Y here if you want suppt for the Acer N30, Acer N35, Navman PiN570, Yakumo AlphaX or Airis NC05 PDAs. +config MACH_N35 + bool + help + Internal node in order to enable support for Acer N35 if Acer N30 is + selected. + config ARCH_BAST bool "Simtec Electronics BAST (EB2410ITX)" select CPU_S3C2410 -- cgit v0.10.2 From be7c4cf632f47d798ad6a27da15de0195ddf6f30 Mon Sep 17 00:00:00 2001 From: Pinkava J Date: Thu, 6 May 2010 15:19:19 +0200 Subject: ARM: n30: fix: suspended wrong USB port on Acer n35 There is bug in USB setup code for Acer n35 (it is related directly to s3c2410, see doc). We want suspend host port (is not connected) but device port should be active. Signed-off-by: Jiri Pinkava Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/mach-n30.c b/arch/arm/mach-s3c2410/mach-n30.c index 684710f..1b635fd 100644 --- a/arch/arm/mach-s3c2410/mach-n30.c +++ b/arch/arm/mach-s3c2410/mach-n30.c @@ -532,7 +532,7 @@ static void __init n30_init(void) s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST | S3C2410_MISCCR_USBSUSPND0 | S3C2410_MISCCR_USBSUSPND1, - S3C2410_MISCCR_USBSUSPND1); + S3C2410_MISCCR_USBSUSPND0); platform_add_devices(n35_devices, ARRAY_SIZE(n35_devices)); } -- cgit v0.10.2 From 8ecad34918174580b069f7d4dcef3f46a099e8f7 Mon Sep 17 00:00:00 2001 From: Pinkava J Date: Thu, 6 May 2010 15:20:36 +0200 Subject: ARM: n30: Add RTC platform device for Acer n30 / Acer n35 Signed-off-by: Jiri Pinkava Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/mach-n30.c b/arch/arm/mach-s3c2410/mach-n30.c index 1b635fd..ce1172e 100644 --- a/arch/arm/mach-s3c2410/mach-n30.c +++ b/arch/arm/mach-s3c2410/mach-n30.c @@ -323,6 +323,7 @@ static struct platform_device *n30_devices[] __initdata = { &s3c_device_i2c0, &s3c_device_iis, &s3c_device_ohci, + &s3c_device_rtc, &s3c_device_usbgadget, &n30_button_device, &n30_blue_led, @@ -334,6 +335,7 @@ static struct platform_device *n35_devices[] __initdata = { &s3c_device_wdt, &s3c_device_i2c0, &s3c_device_iis, + &s3c_device_rtc, &s3c_device_usbgadget, &n35_button_device, }; -- cgit v0.10.2 From 319887ee800f889e4c81d73f0ee4bcf532f9c34d Mon Sep 17 00:00:00 2001 From: Pinkava J Date: Thu, 6 May 2010 15:21:16 +0200 Subject: ARM: n35: Add support for LEDs on Acer n35 Signed-off-by: Jiri Pinkava Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/mach-n30.c b/arch/arm/mach-s3c2410/mach-n30.c index ce1172e..b83eabd 100644 --- a/arch/arm/mach-s3c2410/mach-n30.c +++ b/arch/arm/mach-s3c2410/mach-n30.c @@ -264,6 +264,14 @@ static struct s3c24xx_led_platdata n30_blue_led_pdata = { .def_trigger = "", }; +/* This is the blue LED on the device. Originaly used to indicate GPS activity + * by flashing. */ +static struct s3c24xx_led_platdata n35_blue_led_pdata = { + .name = "blue_led", + .gpio = S3C2410_GPD(8), + .def_trigger = "", +}; + /* This LED is driven by the battery microcontroller, and is blinking * red, blinking green or solid green when the battery is low, * charging or full respectively. By driving GPD9 low, it's possible @@ -275,6 +283,13 @@ static struct s3c24xx_led_platdata n30_warning_led_pdata = { .def_trigger = "", }; +static struct s3c24xx_led_platdata n35_warning_led_pdata = { + .name = "warning_led", + .flags = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE, + .gpio = S3C2410_GPD(9), + .def_trigger = "", +}; + static struct platform_device n30_blue_led = { .name = "s3c24xx_led", .id = 1, @@ -283,6 +298,14 @@ static struct platform_device n30_blue_led = { }, }; +static struct platform_device n35_blue_led = { + .name = "s3c24xx_led", + .id = 1, + .dev = { + .platform_data = &n35_blue_led_pdata, + }, +}; + static struct platform_device n30_warning_led = { .name = "s3c24xx_led", .id = 2, @@ -291,6 +314,14 @@ static struct platform_device n30_warning_led = { }, }; +static struct platform_device n35_warning_led = { + .name = "s3c24xx_led", + .id = 2, + .dev = { + .platform_data = &n35_warning_led_pdata, + }, +}; + static struct s3c2410fb_display n30_display __initdata = { .type = S3C2410_LCDCON1_TFT, .width = 240, @@ -338,6 +369,8 @@ static struct platform_device *n35_devices[] __initdata = { &s3c_device_rtc, &s3c_device_usbgadget, &n35_button_device, + &n35_blue_led, + &n35_warning_led, }; static struct s3c2410_platform_i2c __initdata n30_i2ccfg = { -- cgit v0.10.2 From aeb1b7e49f97e96e8b63c76c22f6fe6186a46ff3 Mon Sep 17 00:00:00 2001 From: Pinkava J Date: Thu, 6 May 2010 15:21:50 +0200 Subject: ARM: n35: Enable wake-up by Power button on Acer n35 Signed-off-by: Jiri Pinkava Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/mach-n30.c b/arch/arm/mach-s3c2410/mach-n30.c index b83eabd..d63b48f 100644 --- a/arch/arm/mach-s3c2410/mach-n30.c +++ b/arch/arm/mach-s3c2410/mach-n30.c @@ -172,8 +172,10 @@ static struct gpio_keys_button n35_buttons[] = { { .gpio = S3C2410_GPF(0), .code = KEY_POWER, + .type = EV_PWR, .desc = "Power", .active_low = 0, + .wakeup = 1, }, { .gpio = S3C2410_GPG(9), -- cgit v0.10.2 From 50cdba782c3de35bf6d454096213c986146f46a5 Mon Sep 17 00:00:00 2001 From: Pinkava J Date: Thu, 6 May 2010 15:22:28 +0200 Subject: ARM: n30: Add support for MMC card reader on Acer n30 / Acer n35 Signed-off-by: Jiri Pinkava Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/mach-n30.c b/arch/arm/mach-s3c2410/mach-n30.c index d63b48f..81973aa 100644 --- a/arch/arm/mach-s3c2410/mach-n30.c +++ b/arch/arm/mach-s3c2410/mach-n30.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -46,6 +47,7 @@ #include #include #include +#include #include #include @@ -350,6 +352,12 @@ static struct s3c2410fb_mach_info n30_fb_info __initdata = { .lpcsel = 0x06, }; +static struct s3c24xx_mci_pdata n30_mci_cfg __initdata = { + .gpio_detect = S3C2410_GPF(1), + .gpio_wprotect = S3C2410_GPG(10), + .ocr_avail = MMC_VDD_32_33, +}; + static struct platform_device *n30_devices[] __initdata = { &s3c_device_lcd, &s3c_device_wdt, @@ -358,6 +366,7 @@ static struct platform_device *n30_devices[] __initdata = { &s3c_device_ohci, &s3c_device_rtc, &s3c_device_usbgadget, + &s3c_device_sdi, &n30_button_device, &n30_blue_led, &n30_warning_led, @@ -370,6 +379,7 @@ static struct platform_device *n35_devices[] __initdata = { &s3c_device_iis, &s3c_device_rtc, &s3c_device_usbgadget, + &s3c_device_sdi, &n35_button_device, &n35_blue_led, &n35_warning_led, @@ -538,6 +548,7 @@ static void __init n30_init(void) { s3c24xx_fb_set_platdata(&n30_fb_info); s3c24xx_udc_set_platdata(&n30_udc_cfg); + s3c24xx_mci_set_platdata(&n30_mci_cfg); s3c_i2c0_set_platdata(&n30_i2ccfg); /* Turn off suspend on both USB ports, and switch the -- cgit v0.10.2 From 271d323237a1ab96b74c69fa48a8612963245266 Mon Sep 17 00:00:00 2001 From: Pinkava J Date: Thu, 6 May 2010 15:23:24 +0200 Subject: ARM: n30: Add support for power on/off on Acer n30 / Acer n35 MMC card reader Signed-off-by: Jiri Pinkava Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/mach-n30.c b/arch/arm/mach-s3c2410/mach-n30.c index 81973aa..f25275e 100644 --- a/arch/arm/mach-s3c2410/mach-n30.c +++ b/arch/arm/mach-s3c2410/mach-n30.c @@ -352,10 +352,25 @@ static struct s3c2410fb_mach_info n30_fb_info __initdata = { .lpcsel = 0x06, }; +static void n30_sdi_set_power(unsigned char power_mode, unsigned short vdd) +{ + switch (power_mode) { + case MMC_POWER_ON: + case MMC_POWER_UP: + s3c2410_gpio_setpin(S3C2410_GPG(4), 1); + break; + case MMC_POWER_OFF: + default: + s3c2410_gpio_setpin(S3C2410_GPG(4), 0); + break; + } +} + static struct s3c24xx_mci_pdata n30_mci_cfg __initdata = { .gpio_detect = S3C2410_GPF(1), .gpio_wprotect = S3C2410_GPG(10), .ocr_avail = MMC_VDD_32_33, + .set_power = n30_sdi_set_power, }; static struct platform_device *n30_devices[] __initdata = { -- cgit v0.10.2 From 8a19ebb0938752af8da142c4731f310bb8f9d130 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 7 May 2010 09:59:11 +0900 Subject: ARM: n30: Fixup gpiolib calls for mmc power Move to using gpio_request() and gpio_set_value() for the MMC power control calls. Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/mach-n30.c b/arch/arm/mach-s3c2410/mach-n30.c index f25275e..dfa09ea 100644 --- a/arch/arm/mach-s3c2410/mach-n30.c +++ b/arch/arm/mach-s3c2410/mach-n30.c @@ -88,10 +88,10 @@ static void n30_udc_pullup(enum s3c2410_udc_cmd_e cmd) { switch (cmd) { case S3C2410_UDC_P_ENABLE : - s3c2410_gpio_setpin(S3C2410_GPB(3), 1); + gpio_set_value(S3C2410_GPB(3), 1); break; case S3C2410_UDC_P_DISABLE : - s3c2410_gpio_setpin(S3C2410_GPB(3), 0); + gpio_set_value(S3C2410_GPB(3), 0); break; case S3C2410_UDC_P_RESET : break; @@ -357,11 +357,11 @@ static void n30_sdi_set_power(unsigned char power_mode, unsigned short vdd) switch (power_mode) { case MMC_POWER_ON: case MMC_POWER_UP: - s3c2410_gpio_setpin(S3C2410_GPG(4), 1); + gpio_set_value(S3C2410_GPG(4), 1); break; case MMC_POWER_OFF: default: - s3c2410_gpio_setpin(S3C2410_GPG(4), 0); + gpio_set_value(S3C2410_GPG(4), 0); break; } } @@ -561,6 +561,8 @@ static void __init n30_init_irq(void) static void __init n30_init(void) { + WARN_ON(gpio_request(S3C2410_GPG(4), "mmc power")); + s3c24xx_fb_set_platdata(&n30_fb_info); s3c24xx_udc_set_platdata(&n30_udc_cfg); s3c24xx_mci_set_platdata(&n30_mci_cfg); -- cgit v0.10.2 From 0c3767b161a91eab5b23d602d374b9c070c067a9 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 7 May 2010 10:01:28 +0900 Subject: ARM: n30: Just call s3c24xx_init_irq() directly from machine definition The n30_init_irq() call is simply a call to s3c24xx_init_irq, so just remove it and update the machine definitions to call the IRQ initialision call directly. Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/mach-n30.c b/arch/arm/mach-s3c2410/mach-n30.c index dfa09ea..9e2565a 100644 --- a/arch/arm/mach-s3c2410/mach-n30.c +++ b/arch/arm/mach-s3c2410/mach-n30.c @@ -552,11 +552,6 @@ static void __init n30_map_io(void) s3c24xx_init_uarts(n30_uartcfgs, ARRAY_SIZE(n30_uartcfgs)); } -static void __init n30_init_irq(void) -{ - s3c24xx_init_irq(); -} - /* GPB3 is the line that controls the pull-up for the USB D+ line */ static void __init n30_init(void) @@ -612,7 +607,7 @@ MACHINE_START(N30, "Acer-N30") .boot_params = S3C2410_SDRAM_PA + 0x100, .timer = &s3c24xx_timer, .init_machine = n30_init, - .init_irq = n30_init_irq, + .init_irq = s3c24xx_init_irq, .map_io = n30_map_io, MACHINE_END @@ -624,6 +619,6 @@ MACHINE_START(N35, "Acer-N35") .boot_params = S3C2410_SDRAM_PA + 0x100, .timer = &s3c24xx_timer, .init_machine = n30_init, - .init_irq = n30_init_irq, + .init_irq = s3c24xx_init_irq, .map_io = n30_map_io, MACHINE_END -- cgit v0.10.2 From a2a47c6c3d1a7c01da4464b3b7be93b924f874c1 Mon Sep 17 00:00:00 2001 From: Ky Srinivasan Date: Thu, 6 May 2010 12:08:41 -0700 Subject: x86: Detect running on a Microsoft HyperV system This patch integrates HyperV detection within the framework currently used by VmWare. With this patch, we can avoid having to replicate the HyperV detection code in each of the Microsoft HyperV drivers. Reworked and tweaked by Greg K-H to build properly. Signed-off-by: K. Y. Srinivasan LKML-Reference: <20100506190841.GA1605@kroah.com> Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: Vadim Rozenfeld Cc: Avi Kivity Cc: Gleb Natapov Cc: Frederic Weisbecker Cc: Alexey Dobriyan Cc: "K.Prasad" Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Paul Mackerras Cc: Alan Cox Cc: Haiyang Zhang Cc: Hank Janssen Signed-off-by: Greg Kroah-Hartman Signed-off-by: H. Peter Anvin diff --git a/arch/x86/include/asm/hyperv.h b/arch/x86/include/asm/hyperv.h index e153a2b..4604047 100644 --- a/arch/x86/include/asm/hyperv.h +++ b/arch/x86/include/asm/hyperv.h @@ -14,6 +14,9 @@ #define HYPERV_CPUID_ENLIGHTMENT_INFO 0x40000004 #define HYPERV_CPUID_IMPLEMENT_LIMITS 0x40000005 +#define HYPERV_HYPERVISOR_PRESENT_BIT 0x80000000 +#define HYPERV_CPUID_MIN 0x40000005 + /* * Feature identification. EAX indicates which features are available * to the partition based upon the current partition privileges. @@ -129,6 +132,9 @@ /* MSR used to provide vcpu index */ #define HV_X64_MSR_VP_INDEX 0x40000002 +/* MSR used to read the per-partition time reference counter */ +#define HV_X64_MSR_TIME_REF_COUNT 0x40000020 + /* Define the virtual APIC registers */ #define HV_X64_MSR_EOI 0x40000070 #define HV_X64_MSR_ICR 0x40000071 diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h new file mode 100644 index 0000000..6cd8101 --- /dev/null +++ b/arch/x86/include/asm/mshyperv.h @@ -0,0 +1,7 @@ +#ifndef ASM_X86__MSHYPER_H +#define ASM_X86__MSHYPER_H + +int ms_hyperv_platform(void); +void __cpuinit ms_hyperv_set_feature_bits(struct cpuinfo_x86 *c); + +#endif diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index b753ea5..597c041 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -114,6 +114,8 @@ struct cpuinfo_x86 { u16 cpu_index; #endif unsigned int x86_hyper_vendor; + /* The layout of this field is hypervisor specific */ + unsigned int x86_hyper_features; } __attribute__((__aligned__(SMP_CACHE_BYTES))); #define X86_VENDOR_INTEL 0 @@ -129,6 +131,7 @@ struct cpuinfo_x86 { #define X86_HYPER_VENDOR_NONE 0 #define X86_HYPER_VENDOR_VMWARE 1 +#define X86_HYPER_VENDOR_MSFT 2 /* * capabilities of CPUs diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index c202b62..3a785da 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile @@ -14,7 +14,7 @@ CFLAGS_common.o := $(nostackp) obj-y := intel_cacheinfo.o addon_cpuid_features.o obj-y += proc.o capflags.o powerflags.o common.o -obj-y += vmware.o hypervisor.o sched.o +obj-y += vmware.o hypervisor.o sched.o mshyperv.o obj-$(CONFIG_X86_32) += bugs.o cmpxchg.o obj-$(CONFIG_X86_64) += bugs_64.o diff --git a/arch/x86/kernel/cpu/hypervisor.c b/arch/x86/kernel/cpu/hypervisor.c index 08be922..de3f4e0 100644 --- a/arch/x86/kernel/cpu/hypervisor.c +++ b/arch/x86/kernel/cpu/hypervisor.c @@ -23,6 +23,7 @@ #include #include +#include #include static inline void __cpuinit @@ -30,6 +31,8 @@ detect_hypervisor_vendor(struct cpuinfo_x86 *c) { if (vmware_platform()) c->x86_hyper_vendor = X86_HYPER_VENDOR_VMWARE; + else if (ms_hyperv_platform()) + c->x86_hyper_vendor = X86_HYPER_VENDOR_MSFT; else c->x86_hyper_vendor = X86_HYPER_VENDOR_NONE; } @@ -37,10 +40,11 @@ detect_hypervisor_vendor(struct cpuinfo_x86 *c) static inline void __cpuinit hypervisor_set_feature_bits(struct cpuinfo_x86 *c) { - if (boot_cpu_data.x86_hyper_vendor == X86_HYPER_VENDOR_VMWARE) { + if (boot_cpu_data.x86_hyper_vendor == X86_HYPER_VENDOR_VMWARE) vmware_set_feature_bits(c); - return; - } + else if (boot_cpu_data.x86_hyper_vendor == X86_HYPER_VENDOR_MSFT) + ms_hyperv_set_feature_bits(c); + return; } void __cpuinit init_hypervisor(struct cpuinfo_x86 *c) diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c new file mode 100644 index 0000000..2443b61 --- /dev/null +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -0,0 +1,67 @@ +/* + * HyperV Detection code. + * + * Copyright (C) 2010, Novell, Inc. + * Author : K. Y. Srinivasan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include +#include +#include + + +int ms_hyperv_platform(void) +{ + u32 eax, ebx, ecx, edx; + char hyp_signature[13]; + + cpuid(1, &eax, &ebx, &ecx, &edx); + if (!(ecx & HYPERV_HYPERVISOR_PRESENT_BIT)) + return 0; + + cpuid(HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS, &eax, &ebx, &ecx, &edx); + *(u32 *)(hyp_signature + 0) = ebx; + *(u32 *)(hyp_signature + 4) = ecx; + *(u32 *)(hyp_signature + 8) = edx; + + if ((eax < HYPERV_CPUID_MIN) || (memcmp("Microsoft Hv", hyp_signature, 12))) + return 0; + return 1; +} + +void __cpuinit ms_hyperv_set_feature_bits(struct cpuinfo_x86 *c) +{ + u32 eax, ebx, ecx, edx; + + c->x86_hyper_features = 0; + /* + * Extract the features, recommendations etc. + * The first 9 bits will be used to track hypervisor features. + * The next 6 bits will be used to track the hypervisor + * recommendations. + */ + cpuid(HYPERV_CPUID_FEATURES, &eax, &ebx, &ecx, &edx); + c->x86_hyper_features |= (eax & 0x1ff); + + cpuid(HYPERV_CPUID_ENLIGHTMENT_INFO, &eax, &ebx, &ecx, &edx); + c->x86_hyper_features |= ((eax & 0x3f) << 9); + printk(KERN_INFO "Detected HyperV with features: %x\n", + c->x86_hyper_features); +} -- cgit v0.10.2 From ccc2d97cb7c798e785c9f198de243e2b59f7073b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Thu, 6 May 2010 03:44:34 +0000 Subject: ipv4: udp: fix short packet and bad checksum logging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 2783ef23 moved the initialisation of saddr and daddr after pskb_may_pull() to avoid a potential data corruption. Unfortunately also placing it after the short packet and bad checksum error paths, where these variables are used for logging. The result is bogus output like [92238.389505] UDP: short packet: From 2.0.0.0:65535 23715/178 to 0.0.0.0:65535 Moving the saddr and daddr initialisation above the error paths, while still keeping it after the pskb_may_pull() to keep the fix from commit 2783ef23. Signed-off-by: Bjørn Mork Cc: stable@kernel.org Acked-by: Eric Dumazet Signed-off-by: David S. Miller diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 8fef859..c36522a 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1527,6 +1527,9 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, uh = udp_hdr(skb); ulen = ntohs(uh->len); + saddr = ip_hdr(skb)->saddr; + daddr = ip_hdr(skb)->daddr; + if (ulen > skb->len) goto short_packet; @@ -1540,9 +1543,6 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, if (udp4_csum_init(skb, uh, proto)) goto csum_error; - saddr = ip_hdr(skb)->saddr; - daddr = ip_hdr(skb)->daddr; - if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST)) return __udp4_lib_mcast_deliver(net, skb, uh, saddr, daddr, udptable); -- cgit v0.10.2 From fc390cde362309f6892bb719194f242c466a978b Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Thu, 6 May 2010 11:42:52 -0700 Subject: rcu: need barrier() in UP synchronize_sched_expedited() If synchronize_sched_expedited() is ever to be called from within kernel/sched.c in a !SMP PREEMPT kernel, the !SMP implementation needs a barrier(). Signed-off-by: Paul E. McKenney Signed-off-by: Tejun Heo diff --git a/kernel/sched.c b/kernel/sched.c index 155a16d..fbaf312 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -8932,6 +8932,7 @@ struct cgroup_subsys cpuacct_subsys = { void synchronize_sched_expedited(void) { + barrier(); } EXPORT_SYMBOL_GPL(synchronize_sched_expedited); -- cgit v0.10.2 From a5ec39507129a086d8838228ac1ca0a2eab38f91 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 7 May 2010 14:54:55 +0900 Subject: sh: convert kexec crash kernel management to LMB. This migrates the crash kernel handling off of bootmem and over to LMB. Signed-off-by: Paul Mundt diff --git a/arch/sh/include/asm/kexec.h b/arch/sh/include/asm/kexec.h index 765a5e1..ad6ef8a 100644 --- a/arch/sh/include/asm/kexec.h +++ b/arch/sh/include/asm/kexec.h @@ -26,6 +26,10 @@ /* The native architecture */ #define KEXEC_ARCH KEXEC_ARCH_SH +#ifdef CONFIG_KEXEC +/* arch/sh/kernel/machine_kexec.c */ +void reserve_crashkernel(void); + static inline void crash_setup_regs(struct pt_regs *newregs, struct pt_regs *oldregs) { @@ -59,4 +63,8 @@ static inline void crash_setup_regs(struct pt_regs *newregs, newregs->pc = (unsigned long)current_text_addr(); } } +#else +static inline void reserve_crashkernel(void) { } +#endif /* CONFIG_KEXEC */ + #endif /* __ASM_SH_KEXEC_H */ diff --git a/arch/sh/kernel/machine_kexec.c b/arch/sh/kernel/machine_kexec.c index 7672141..f0f049c 100644 --- a/arch/sh/kernel/machine_kexec.c +++ b/arch/sh/kernel/machine_kexec.c @@ -8,7 +8,6 @@ * This source code is licensed under the GNU General Public License, * Version 2. See the file COPYING for more details. */ - #include #include #include @@ -16,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -148,3 +148,52 @@ void arch_crash_save_vmcoreinfo(void) VMCOREINFO_LENGTH(node_data, MAX_NUMNODES); #endif } + +void __init reserve_crashkernel(void) +{ + unsigned long long crash_size, crash_base; + int ret; + + /* this is necessary because of lmb_phys_mem_size() */ + lmb_analyze(); + + ret = parse_crashkernel(boot_command_line, lmb_phys_mem_size(), + &crash_size, &crash_base); + if (ret == 0 && crash_size > 0) { + crashk_res.start = crash_base; + crashk_res.end = crash_base + crash_size - 1; + } + + if (crashk_res.end == crashk_res.start) + goto disable; + + crash_size = PAGE_ALIGN(crashk_res.end - crashk_res.start + 1); + if (!crashk_res.start) { + crashk_res.start = lmb_alloc(crash_size, PAGE_SIZE); + if (!crashk_res.start) { + pr_err("crashkernel allocation failed\n"); + goto disable; + } + } else { + ret = lmb_reserve(crashk_res.start, crash_size); + if (unlikely(ret < 0)) { + pr_err("crashkernel reservation failed - " + "memory is in use\n"); + goto disable; + } + } + + pr_info("Reserving %ldMB of memory at %ldMB " + "for crashkernel (System RAM: %ldMB)\n", + (unsigned long)(crash_size >> 20), + (unsigned long)(crashk_res.start >> 20), + (unsigned long)(lmb_phys_mem_size() >> 20)); + + crashk_res.end = crashk_res.start + crash_size - 1; + insert_resource(&iomem_resource, &crashk_res); + + return; + +disable: + crashk_res.start = crashk_res.end = 0; +} diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 9c7f781..d67a8a3 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -145,49 +145,6 @@ static void __init register_bootmem_low_pages(void) free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(pages)); } -#ifdef CONFIG_KEXEC -static void __init reserve_crashkernel(void) -{ - unsigned long long free_mem; - unsigned long long crash_size, crash_base; - void *vp; - int ret; - - free_mem = ((unsigned long long)max_low_pfn - min_low_pfn) << PAGE_SHIFT; - - ret = parse_crashkernel(boot_command_line, free_mem, - &crash_size, &crash_base); - if (ret == 0 && crash_size) { - if (crash_base <= 0) { - vp = alloc_bootmem_nopanic(crash_size); - if (!vp) { - printk(KERN_INFO "crashkernel allocation " - "failed\n"); - return; - } - crash_base = __pa(vp); - } else if (reserve_bootmem(crash_base, crash_size, - BOOTMEM_EXCLUSIVE) < 0) { - printk(KERN_INFO "crashkernel reservation failed - " - "memory is in use\n"); - return; - } - - printk(KERN_INFO "Reserving %ldMB of memory at %ldMB " - "for crashkernel (System RAM: %ldMB)\n", - (unsigned long)(crash_size >> 20), - (unsigned long)(crash_base >> 20), - (unsigned long)(free_mem >> 20)); - crashk_res.start = crash_base; - crashk_res.end = crash_base + crash_size - 1; - insert_resource(&iomem_resource, &crashk_res); - } -} -#else -static inline void __init reserve_crashkernel(void) -{} -#endif - static void __init check_for_initrd(void) { #ifdef CONFIG_BLK_DEV_INITRD -- cgit v0.10.2 From 36fa06d6b5ef1874d012c04b23d5b8982b1f8dea Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 7 May 2010 15:10:07 +0900 Subject: sh: convert initrd reservation to LMB. This switches over from bootmem -> LMB for the initrd area reservation. Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index d67a8a3..0800172 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -192,7 +192,7 @@ static void __init check_for_initrd(void) initrd_start = (unsigned long)__va(__pa(start)); initrd_end = initrd_start + INITRD_SIZE; - reserve_bootmem(__pa(initrd_start), INITRD_SIZE, BOOTMEM_DEFAULT); + lmb_reserve(__pa(initrd_start), INITRD_SIZE); return; -- cgit v0.10.2 From 080e71e13d99d850875c0335c364766162eae7c6 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 7 May 2010 15:10:42 +0900 Subject: sh: bump up extra LMB reservations in bootmem init. This bumps up the extra LMB reservations in ordering so that they're accounted for prior to iterating over the region list. This ensures that reservations are visible both within the LMB and bootmem context. Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 0800172..e3f0da7 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -276,6 +276,12 @@ void __init setup_bootmem_allocator(unsigned long free_pfn) } /* + * Handle additional early reservations + */ + check_for_initrd(); + reserve_crashkernel(); + + /* * Add all physical memory to the bootmem map and mark each * area as present. */ @@ -290,10 +296,6 @@ void __init setup_bootmem_allocator(unsigned long free_pfn) node_set_online(0); sparse_memory_present_with_active_regions(0); - - check_for_initrd(); - - reserve_crashkernel(); } #ifndef CONFIG_NEED_MULTIPLE_NODES -- cgit v0.10.2 From d523e1ae6addd4f18a609da39f23719eaecfedf0 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 7 May 2010 16:39:09 +0900 Subject: sh: flag kdump as broken on SMP for now. There's still quite a bit of shootdown logic that needs to be hacked up to support SMP for kdump properly, so just add in a BROKEN_ON_SMP dependency for now. Signed-off-by: Paul Mundt diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index c2325bd..38611bc 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -633,7 +633,7 @@ config KEXEC config CRASH_DUMP bool "kernel crash dumps (EXPERIMENTAL)" - depends on SUPERH32 && EXPERIMENTAL + depends on SUPERH32 && EXPERIMENTAL && BROKEN_ON_SMP help Generate crash dump after being started by kexec. This should be normally only set in special crash dump kernels -- cgit v0.10.2 From aa424bbb8cf5f7f3c6a70065bcb28a6e6af7897d Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 7 May 2010 17:14:00 +0900 Subject: sh: Ensure that X2 TLB settings are reflected in vmcore. This rolls in the X2TLB config settings for vmcore. Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/machine_kexec.c b/arch/sh/kernel/machine_kexec.c index 7672141..0e90c7f 100644 --- a/arch/sh/kernel/machine_kexec.c +++ b/arch/sh/kernel/machine_kexec.c @@ -147,4 +147,7 @@ void arch_crash_save_vmcoreinfo(void) VMCOREINFO_SYMBOL(node_data); VMCOREINFO_LENGTH(node_data, MAX_NUMNODES); #endif +#ifdef CONFIG_X2TLB + VMCOREINFO_CONFIG(X2TLB); +#endif } -- cgit v0.10.2 From 4d26f44657915f082806abfe3624aeded4c121fa Mon Sep 17 00:00:00 2001 From: Wu Fengguang Date: Fri, 7 May 2010 08:47:54 +0800 Subject: ALSA: hda - fix DG45ID SPDIF output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts part of commit 52dc438606d1e, in order to fix a regression: broken SPDIF output on Intel DG45FC motherboard (IDT 92HD73E1X5 codec). --- DG45FC-IDT-codec-2.6.32 (SPDIF OK) +++ DG45FC-IDT-codec-2.6.33 (SPDIF broken) Node 0x22 [Pin Complex] wcaps 0x400301: Stereo Digital Pincap 0x00000010: OUT - Pin Default 0x40f000f0: [N/A] Other at Ext N/A - Conn = Unknown, Color = Unknown - DefAssociation = 0xf, Sequence = 0x0 - Pin-ctls: 0x00: + Pin Default 0x014510a0: [Jack] SPDIF Out at Ext Rear + Conn = Optical, Color = Black + DefAssociation = 0xa, Sequence = 0x0 + Pin-ctls: 0x40: OUT Connection: 3 0x25* 0x20 0x21 Node 0x23 [Pin Complex] wcaps 0x400301: Stereo Digital Pincap 0x00000010: OUT - Pin Default 0x01451140: [Jack] SPDIF Out at Ext Rear + Pin Default 0x074510b0: [Jack] SPDIF Out at Ext Rear Panel Conn = Optical, Color = Black - DefAssociation = 0x4, Sequence = 0x0 - Misc = NO_PRESENCE - Pin-ctls: 0x40: OUT + DefAssociation = 0xb, Sequence = 0x0 + Pin-ctls: 0x00: Connection: 3 0x26* 0x20 0x21 Cc: Cc: Alexey Fisher Tested-by: David Härdeman Signed-off-by: Wu Fengguang Signed-off-by: Takashi Iwai diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 7fb7d01..12825aa0 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -1544,11 +1544,9 @@ static unsigned int alienware_m17x_pin_configs[13] = { 0x904601b0, }; -static unsigned int intel_dg45id_pin_configs[14] = { +static unsigned int intel_dg45id_pin_configs[13] = { 0x02214230, 0x02A19240, 0x01013214, 0x01014210, - 0x01A19250, 0x01011212, 0x01016211, 0x40f000f0, - 0x40f000f0, 0x40f000f0, 0x40f000f0, 0x014510A0, - 0x074510B0, 0x40f000f0 + 0x01A19250, 0x01011212, 0x01016211 }; static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = { -- cgit v0.10.2 From 7aed3b34fb0a98e89d0e999f5833ceebdb3876b9 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 7 May 2010 17:58:55 +0900 Subject: sh: shuffle the elfcorehdr handling over to the crash dump code. The elfcorehdr parsing was just tossed in setup.c, but nothing outside of the crash dump code/vmcore bits require it, so we just move it out of the way, as per ppc. Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/crash_dump.c b/arch/sh/kernel/crash_dump.c index 95d2162..37c97d4 100644 --- a/arch/sh/kernel/crash_dump.c +++ b/arch/sh/kernel/crash_dump.c @@ -4,7 +4,6 @@ * Created by: Hariprasad Nellitheertha (hari@in.ibm.com) * Copyright (C) IBM Corporation, 2004. All rights reserved */ - #include #include #include @@ -13,6 +12,25 @@ /* Stores the physical address of elf header of crash image. */ unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX; +/* + * Note: elfcorehdr_addr is not just limited to vmcore. It is also used by + * is_kdump_kernel() to determine if we are booting after a panic. Hence + * ifdef it under CONFIG_CRASH_DUMP and not CONFIG_PROC_VMCORE. + * + * elfcorehdr= specifies the location of elf core header + * stored by the crashed kernel. + */ +static int __init parse_elfcorehdr(char *arg) +{ + if (!arg) + return -EINVAL; + + elfcorehdr_addr = memparse(arg, &arg); + + return 0; +} +early_param("elfcorehdr", parse_elfcorehdr); + /** * copy_oldmem_page - copy one page from "oldmem" * @pfn: page frame number to be copied diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 9c7f781..4f1585f 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -380,25 +380,6 @@ static void __init setup_memory(void) extern void __init setup_memory(void); #endif -/* - * Note: elfcorehdr_addr is not just limited to vmcore. It is also used by - * is_kdump_kernel() to determine if we are booting after a panic. Hence - * ifdef it under CONFIG_CRASH_DUMP and not CONFIG_PROC_VMCORE. - */ -#ifdef CONFIG_CRASH_DUMP -/* elfcorehdr= specifies the location of elf core header - * stored by the crashed kernel. - */ -static int __init parse_elfcorehdr(char *arg) -{ - if (!arg) - return -EINVAL; - elfcorehdr_addr = memparse(arg, &arg); - return 0; -} -early_param("elfcorehdr", parse_elfcorehdr); -#endif - void __init __attribute__ ((weak)) plat_early_device_setup(void) { } -- cgit v0.10.2 From 4726f2a617ebd868a4fdeb5679613b897e5f1676 Mon Sep 17 00:00:00 2001 From: Yong Zhang Date: Tue, 4 May 2010 14:16:48 +0800 Subject: lockdep: Reduce stack_trace usage When calling check_prevs_add(), if all validations passed add_lock_to_list() will add new lock to dependency tree and alloc stack_trace for each list_entry. But at this time, we are always on the same stack, so stack_trace for each list_entry has the same value. This is redundant and eats up lots of memory which could lead to warning on low MAX_STACK_TRACE_ENTRIES. Use one copy of stack_trace instead. V2: As suggested by Peter Zijlstra, move save_trace() from check_prevs_add() to check_prev_add(). Add tracking for trylock dependence which is also redundant. Signed-off-by: Yong Zhang Cc: David S. Miller Signed-off-by: Peter Zijlstra LKML-Reference: <20100504065711.GC10784@windriver.com> Signed-off-by: Ingo Molnar diff --git a/kernel/lockdep.c b/kernel/lockdep.c index 9cf7985..5108080 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c @@ -805,7 +805,8 @@ static struct lock_list *alloc_list_entry(void) * Add a new dependency to the head of the list: */ static int add_lock_to_list(struct lock_class *class, struct lock_class *this, - struct list_head *head, unsigned long ip, int distance) + struct list_head *head, unsigned long ip, + int distance, struct stack_trace *trace) { struct lock_list *entry; /* @@ -816,11 +817,9 @@ static int add_lock_to_list(struct lock_class *class, struct lock_class *this, if (!entry) return 0; - if (!save_trace(&entry->trace)) - return 0; - entry->class = this; entry->distance = distance; + entry->trace = *trace; /* * Since we never remove from the dependency list, the list can * be walked lockless by other CPUs, it's only allocation @@ -1622,12 +1621,20 @@ check_deadlock(struct task_struct *curr, struct held_lock *next, */ static int check_prev_add(struct task_struct *curr, struct held_lock *prev, - struct held_lock *next, int distance) + struct held_lock *next, int distance, int trylock_loop) { struct lock_list *entry; int ret; struct lock_list this; struct lock_list *uninitialized_var(target_entry); + /* + * Static variable, serialized by the graph_lock(). + * + * We use this static variable to save the stack trace in case + * we call into this function multiple times due to encountering + * trylocks in the held lock stack. + */ + static struct stack_trace trace; /* * Prove that the new -> dependency would not @@ -1675,20 +1682,23 @@ check_prev_add(struct task_struct *curr, struct held_lock *prev, } } + if (!trylock_loop && !save_trace(&trace)) + return 0; + /* * Ok, all validations passed, add the new lock * to the previous lock's dependency list: */ ret = add_lock_to_list(hlock_class(prev), hlock_class(next), &hlock_class(prev)->locks_after, - next->acquire_ip, distance); + next->acquire_ip, distance, &trace); if (!ret) return 0; ret = add_lock_to_list(hlock_class(next), hlock_class(prev), &hlock_class(next)->locks_before, - next->acquire_ip, distance); + next->acquire_ip, distance, &trace); if (!ret) return 0; @@ -1718,6 +1728,7 @@ static int check_prevs_add(struct task_struct *curr, struct held_lock *next) { int depth = curr->lockdep_depth; + int trylock_loop = 0; struct held_lock *hlock; /* @@ -1743,7 +1754,8 @@ check_prevs_add(struct task_struct *curr, struct held_lock *next) * added: */ if (hlock->read != 2) { - if (!check_prev_add(curr, hlock, next, distance)) + if (!check_prev_add(curr, hlock, next, + distance, trylock_loop)) return 0; /* * Stop after the first non-trylock entry, @@ -1766,6 +1778,7 @@ check_prevs_add(struct task_struct *curr, struct held_lock *next) if (curr->held_locks[depth].irq_context != curr->held_locks[depth-1].irq_context) break; + trylock_loop = 1; } return 1; out_bug: -- cgit v0.10.2 From 27a9da6538ee18046d7bff8e36a9f783542c54c3 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 4 May 2010 20:36:56 +0200 Subject: sched: Remove rq argument to the tracepoints struct rq isn't visible outside of sched.o so its near useless to expose the pointer, also there are no users of it, so remove it. Acked-by: Steven Rostedt Signed-off-by: Peter Zijlstra LKML-Reference: <1272997616.1642.207.camel@laptop> Signed-off-by: Ingo Molnar diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h index cfceb0b..4f733ec 100644 --- a/include/trace/events/sched.h +++ b/include/trace/events/sched.h @@ -51,15 +51,12 @@ TRACE_EVENT(sched_kthread_stop_ret, /* * Tracepoint for waiting on task to unschedule: - * - * (NOTE: the 'rq' argument is not used by generic trace events, - * but used by the latency tracer plugin. ) */ TRACE_EVENT(sched_wait_task, - TP_PROTO(struct rq *rq, struct task_struct *p), + TP_PROTO(struct task_struct *p), - TP_ARGS(rq, p), + TP_ARGS(p), TP_STRUCT__entry( __array( char, comm, TASK_COMM_LEN ) @@ -79,15 +76,12 @@ TRACE_EVENT(sched_wait_task, /* * Tracepoint for waking up a task: - * - * (NOTE: the 'rq' argument is not used by generic trace events, - * but used by the latency tracer plugin. ) */ DECLARE_EVENT_CLASS(sched_wakeup_template, - TP_PROTO(struct rq *rq, struct task_struct *p, int success), + TP_PROTO(struct task_struct *p, int success), - TP_ARGS(rq, p, success), + TP_ARGS(p, success), TP_STRUCT__entry( __array( char, comm, TASK_COMM_LEN ) @@ -111,31 +105,25 @@ DECLARE_EVENT_CLASS(sched_wakeup_template, ); DEFINE_EVENT(sched_wakeup_template, sched_wakeup, - TP_PROTO(struct rq *rq, struct task_struct *p, int success), - TP_ARGS(rq, p, success)); + TP_PROTO(struct task_struct *p, int success), + TP_ARGS(p, success)); /* * Tracepoint for waking up a new task: - * - * (NOTE: the 'rq' argument is not used by generic trace events, - * but used by the latency tracer plugin. ) */ DEFINE_EVENT(sched_wakeup_template, sched_wakeup_new, - TP_PROTO(struct rq *rq, struct task_struct *p, int success), - TP_ARGS(rq, p, success)); + TP_PROTO(struct task_struct *p, int success), + TP_ARGS(p, success)); /* * Tracepoint for task switches, performed by the scheduler: - * - * (NOTE: the 'rq' argument is not used by generic trace events, - * but used by the latency tracer plugin. ) */ TRACE_EVENT(sched_switch, - TP_PROTO(struct rq *rq, struct task_struct *prev, + TP_PROTO(struct task_struct *prev, struct task_struct *next), - TP_ARGS(rq, prev, next), + TP_ARGS(prev, next), TP_STRUCT__entry( __array( char, prev_comm, TASK_COMM_LEN ) diff --git a/kernel/sched.c b/kernel/sched.c index 4956ed0..11ac0eb 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -2168,7 +2168,7 @@ unsigned long wait_task_inactive(struct task_struct *p, long match_state) * just go back and repeat. */ rq = task_rq_lock(p, &flags); - trace_sched_wait_task(rq, p); + trace_sched_wait_task(p); running = task_running(rq, p); on_rq = p->se.on_rq; ncsw = 0; @@ -2439,7 +2439,7 @@ out_activate: success = 1; out_running: - trace_sched_wakeup(rq, p, success); + trace_sched_wakeup(p, success); check_preempt_curr(rq, p, wake_flags); p->state = TASK_RUNNING; @@ -2613,7 +2613,7 @@ void wake_up_new_task(struct task_struct *p, unsigned long clone_flags) rq = task_rq_lock(p, &flags); activate_task(rq, p, 0); - trace_sched_wakeup_new(rq, p, 1); + trace_sched_wakeup_new(p, 1); check_preempt_curr(rq, p, WF_FORK); #ifdef CONFIG_SMP if (p->sched_class->task_woken) @@ -2833,7 +2833,7 @@ context_switch(struct rq *rq, struct task_struct *prev, struct mm_struct *mm, *oldmm; prepare_task_switch(rq, prev, next); - trace_sched_switch(rq, prev, next); + trace_sched_switch(prev, next); mm = next->mm; oldmm = prev->active_mm; /* diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 2404b59..aa3a92b 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -3212,8 +3212,7 @@ free: } static void -ftrace_graph_probe_sched_switch(struct rq *__rq, struct task_struct *prev, - struct task_struct *next) +ftrace_graph_probe_sched_switch(struct task_struct *prev, struct task_struct *next) { unsigned long long timestamp; int index; diff --git a/kernel/trace/trace_sched_switch.c b/kernel/trace/trace_sched_switch.c index 5fca0f5..a55fccf 100644 --- a/kernel/trace/trace_sched_switch.c +++ b/kernel/trace/trace_sched_switch.c @@ -50,8 +50,7 @@ tracing_sched_switch_trace(struct trace_array *tr, } static void -probe_sched_switch(struct rq *__rq, struct task_struct *prev, - struct task_struct *next) +probe_sched_switch(struct task_struct *prev, struct task_struct *next) { struct trace_array_cpu *data; unsigned long flags; @@ -109,7 +108,7 @@ tracing_sched_wakeup_trace(struct trace_array *tr, } static void -probe_sched_wakeup(struct rq *__rq, struct task_struct *wakee, int success) +probe_sched_wakeup(struct task_struct *wakee, int success) { struct trace_array_cpu *data; unsigned long flags; diff --git a/kernel/trace/trace_sched_wakeup.c b/kernel/trace/trace_sched_wakeup.c index 0271742..8052446 100644 --- a/kernel/trace/trace_sched_wakeup.c +++ b/kernel/trace/trace_sched_wakeup.c @@ -107,8 +107,7 @@ static void probe_wakeup_migrate_task(struct task_struct *task, int cpu) } static void notrace -probe_wakeup_sched_switch(struct rq *rq, struct task_struct *prev, - struct task_struct *next) +probe_wakeup_sched_switch(struct task_struct *prev, struct task_struct *next) { struct trace_array_cpu *data; cycle_t T0, T1, delta; @@ -200,7 +199,7 @@ static void wakeup_reset(struct trace_array *tr) } static void -probe_wakeup(struct rq *rq, struct task_struct *p, int success) +probe_wakeup(struct task_struct *p, int success) { struct trace_array_cpu *data; int cpu = smp_processor_id(); -- cgit v0.10.2 From 4fd38e4595e2f6c9d27732c042a0e16b2753049c Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 6 May 2010 17:31:38 +0200 Subject: perf: Fix exit() vs PERF_FORMAT_GROUP Both Stephane and Corey reported that PERF_FORMAT_GROUP didn't work as expected if the task the counters were attached to quit before the read() call. The cause is that we unconditionally destroy the grouping when we remove counters from their context. Fix this by only doing this when we free the counter itself. Reported-by: Corey Ashford Reported-by: Stephane Eranian Signed-off-by: Peter Zijlstra LKML-Reference: <1273160566.5605.404.camel@twins> Signed-off-by: Ingo Molnar diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index c8e3754..bf8f3c0 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -522,6 +522,7 @@ struct pmu { * enum perf_event_active_state - the states of a event */ enum perf_event_active_state { + PERF_EVENT_STATE_FREE = -3, PERF_EVENT_STATE_ERROR = -2, PERF_EVENT_STATE_OFF = -1, PERF_EVENT_STATE_INACTIVE = 0, diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 3d1552d..f13c3db 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -341,6 +341,9 @@ list_del_event(struct perf_event *event, struct perf_event_context *ctx) if (event->state > PERF_EVENT_STATE_OFF) event->state = PERF_EVENT_STATE_OFF; + if (event->state > PERF_EVENT_STATE_FREE) + return; + /* * If this was a group event with sibling events then * upgrade the siblings to singleton events by adding them @@ -1856,6 +1859,8 @@ int perf_event_release_kernel(struct perf_event *event) { struct perf_event_context *ctx = event->ctx; + event->state = PERF_EVENT_STATE_FREE; + WARN_ON_ONCE(ctx->parent_ctx); mutex_lock(&ctx->mutex); perf_event_remove_from_context(event); -- cgit v0.10.2 From a0507c84bf47dfd204299774f45fd16da33f0619 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 6 May 2010 15:42:53 +0200 Subject: perf: Annotate perf_event_read_group() vs perf_event_release_kernel() Stephane reported a lockdep warning while using PERF_FORMAT_GROUP. The issue is that perf_event_read_group() takes faults while holding the ctx->mutex, while perf_event_release_kernel() can be called from munmap(). Which makes for an AB-BA deadlock. Except we can never establish the deadlock because we'll only ever call perf_event_release_kernel() after all file descriptors are dead so there is no concurrency possible. Reported-by: Stephane Eranian Cc: Paul Mackerras Signed-off-by: Peter Zijlstra LKML-Reference: Signed-off-by: Ingo Molnar diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 49d8be5..34659d4 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -1867,7 +1867,19 @@ int perf_event_release_kernel(struct perf_event *event) event->state = PERF_EVENT_STATE_FREE; WARN_ON_ONCE(ctx->parent_ctx); - mutex_lock(&ctx->mutex); + /* + * There are two ways this annotation is useful: + * + * 1) there is a lock recursion from perf_event_exit_task + * see the comment there. + * + * 2) there is a lock-inversion with mmap_sem through + * perf_event_read_group(), which takes faults while + * holding ctx->mutex, however this is called after + * the last filedesc died, so there is no possibility + * to trigger the AB-BA case. + */ + mutex_lock_nested(&ctx->mutex, SINGLE_DEPTH_NESTING); perf_event_remove_from_context(event); mutex_unlock(&ctx->mutex); @@ -5305,7 +5317,7 @@ void perf_event_exit_task(struct task_struct *child) * * But since its the parent context it won't be the same instance. */ - mutex_lock_nested(&child_ctx->mutex, SINGLE_DEPTH_NESTING); + mutex_lock(&child_ctx->mutex); again: list_for_each_entry_safe(child_event, tmp, &child_ctx->pinned_groups, -- cgit v0.10.2 From 4261e0e0efd9e04b6c69e0773c3cf4d6f337c416 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 13 Apr 2010 22:23:10 +0200 Subject: perf, x86: Move perfctr init code to x86_setup_perfctr() Split __hw_perf_event_init() to configure pmu events other than perfctrs. Perfctr code is moved to a separate function x86_setup_perfctr(). This and the following patches refactor the code. Split in multiple patches for better review. Signed-off-by: Robert Richter Signed-off-by: Peter Zijlstra LKML-Reference: <1271190201-25705-2-git-send-email-robert.richter@amd.com> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 7de7061..801441a 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -426,6 +426,8 @@ set_ext_hw_attr(struct hw_perf_event *hwc, struct perf_event_attr *attr) return 0; } +static int x86_setup_perfctr(struct perf_event *event); + static int x86_pmu_hw_config(struct perf_event *event) { /* @@ -453,9 +455,6 @@ static int x86_pmu_hw_config(struct perf_event *event) */ static int __hw_perf_event_init(struct perf_event *event) { - struct perf_event_attr *attr = &event->attr; - struct hw_perf_event *hwc = &event->hw; - u64 config; int err; if (!x86_pmu_initialized()) @@ -482,15 +481,24 @@ static int __hw_perf_event_init(struct perf_event *event) event->destroy = hw_perf_event_destroy; - hwc->idx = -1; - hwc->last_cpu = -1; - hwc->last_tag = ~0ULL; + event->hw.idx = -1; + event->hw.last_cpu = -1; + event->hw.last_tag = ~0ULL; /* Processor specifics */ err = x86_pmu.hw_config(event); if (err) return err; + return x86_setup_perfctr(event); +} + +static int x86_setup_perfctr(struct perf_event *event) +{ + struct perf_event_attr *attr = &event->attr; + struct hw_perf_event *hwc = &event->hw; + u64 config; + if (!hwc->sample_period) { hwc->sample_period = x86_pmu.max_period; hwc->last_period = hwc->sample_period; -- cgit v0.10.2 From c1726f343b3bfc2ee037e191907c632a31903021 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 13 Apr 2010 22:23:11 +0200 Subject: perf, x86: Move x86_setup_perfctr() Move x86_setup_perfctr(), no other changes made. Signed-off-by: Robert Richter Signed-off-by: Peter Zijlstra LKML-Reference: <1271190201-25705-3-git-send-email-robert.richter@amd.com> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 801441a..3d3bceb 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -426,7 +426,65 @@ set_ext_hw_attr(struct hw_perf_event *hwc, struct perf_event_attr *attr) return 0; } -static int x86_setup_perfctr(struct perf_event *event); +static int x86_setup_perfctr(struct perf_event *event) +{ + struct perf_event_attr *attr = &event->attr; + struct hw_perf_event *hwc = &event->hw; + u64 config; + + if (!hwc->sample_period) { + hwc->sample_period = x86_pmu.max_period; + hwc->last_period = hwc->sample_period; + atomic64_set(&hwc->period_left, hwc->sample_period); + } else { + /* + * If we have a PMU initialized but no APIC + * interrupts, we cannot sample hardware + * events (user-space has to fall back and + * sample via a hrtimer based software event): + */ + if (!x86_pmu.apic) + return -EOPNOTSUPP; + } + + if (attr->type == PERF_TYPE_RAW) + return 0; + + if (attr->type == PERF_TYPE_HW_CACHE) + return set_ext_hw_attr(hwc, attr); + + if (attr->config >= x86_pmu.max_events) + return -EINVAL; + + /* + * The generic map: + */ + config = x86_pmu.event_map(attr->config); + + if (config == 0) + return -ENOENT; + + if (config == -1LL) + return -EINVAL; + + /* + * Branch tracing: + */ + if ((attr->config == PERF_COUNT_HW_BRANCH_INSTRUCTIONS) && + (hwc->sample_period == 1)) { + /* BTS is not supported by this architecture. */ + if (!x86_pmu.bts) + return -EOPNOTSUPP; + + /* BTS is currently only allowed for user-mode. */ + if (!attr->exclude_kernel) + return -EOPNOTSUPP; + } + + hwc->config |= config; + + return 0; +} static int x86_pmu_hw_config(struct perf_event *event) { @@ -493,66 +551,6 @@ static int __hw_perf_event_init(struct perf_event *event) return x86_setup_perfctr(event); } -static int x86_setup_perfctr(struct perf_event *event) -{ - struct perf_event_attr *attr = &event->attr; - struct hw_perf_event *hwc = &event->hw; - u64 config; - - if (!hwc->sample_period) { - hwc->sample_period = x86_pmu.max_period; - hwc->last_period = hwc->sample_period; - atomic64_set(&hwc->period_left, hwc->sample_period); - } else { - /* - * If we have a PMU initialized but no APIC - * interrupts, we cannot sample hardware - * events (user-space has to fall back and - * sample via a hrtimer based software event): - */ - if (!x86_pmu.apic) - return -EOPNOTSUPP; - } - - if (attr->type == PERF_TYPE_RAW) - return 0; - - if (attr->type == PERF_TYPE_HW_CACHE) - return set_ext_hw_attr(hwc, attr); - - if (attr->config >= x86_pmu.max_events) - return -EINVAL; - - /* - * The generic map: - */ - config = x86_pmu.event_map(attr->config); - - if (config == 0) - return -ENOENT; - - if (config == -1LL) - return -EINVAL; - - /* - * Branch tracing: - */ - if ((attr->config == PERF_COUNT_HW_BRANCH_INSTRUCTIONS) && - (hwc->sample_period == 1)) { - /* BTS is not supported by this architecture. */ - if (!x86_pmu.bts) - return -EOPNOTSUPP; - - /* BTS is currently only allowed for user-mode. */ - if (!attr->exclude_kernel) - return -EOPNOTSUPP; - } - - hwc->config |= config; - - return 0; -} - static void x86_pmu_disable_all(void) { struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); -- cgit v0.10.2 From 9d0fcba67e47ff398a6fa86476d4884d472dc98a Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 13 Apr 2010 22:23:12 +0200 Subject: perf, x86: Call x86_setup_perfctr() from .hw_config() The perfctr setup calls are in the corresponding .hw_config() functions now. This makes it possible to introduce config functions for other pmu events that are not perfctr specific. Also, all of a sudden the code looks much nicer. Signed-off-by: Robert Richter Signed-off-by: Peter Zijlstra LKML-Reference: <1271190201-25705-4-git-send-email-robert.richter@amd.com> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 3d3bceb..c2c1e10 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -505,7 +505,7 @@ static int x86_pmu_hw_config(struct perf_event *event) if (event->attr.type == PERF_TYPE_RAW) event->hw.config |= event->attr.config & X86_RAW_EVENT_MASK; - return 0; + return x86_setup_perfctr(event); } /* @@ -543,12 +543,7 @@ static int __hw_perf_event_init(struct perf_event *event) event->hw.last_cpu = -1; event->hw.last_tag = ~0ULL; - /* Processor specifics */ - err = x86_pmu.hw_config(event); - if (err) - return err; - - return x86_setup_perfctr(event); + return x86_pmu.hw_config(event); } static void x86_pmu_disable_all(void) diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index 15367cc..9e00205 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c @@ -455,7 +455,7 @@ static int p4_hw_config(struct perf_event *event) (p4_config_pack_escr(P4_ESCR_MASK_HT) | p4_config_pack_cccr(P4_CCCR_MASK_HT)); - return 0; + return x86_setup_perfctr(event); } static inline void p4_pmu_clear_cccr_ovf(struct hw_perf_event *hwc) -- cgit v0.10.2 From 31fa58af57c41d2912debf62d47d5811062411f1 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 13 Apr 2010 22:23:14 +0200 Subject: perf, x86: Pass enable bit mask to __x86_pmu_enable_event() To reuse this function for events with different enable bit masks, this mask is part of the function's argument list now. The function will be used later to control ibs events too. Signed-off-by: Robert Richter Signed-off-by: Peter Zijlstra LKML-Reference: <1271190201-25705-6-git-send-email-robert.richter@amd.com> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index c2c1e10..4e218d7 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -844,10 +844,10 @@ void hw_perf_enable(void) x86_pmu.enable_all(added); } -static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc) +static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc, + u64 enable_mask) { - wrmsrl(hwc->config_base + hwc->idx, - hwc->config | ARCH_PERFMON_EVENTSEL_ENABLE); + wrmsrl(hwc->config_base + hwc->idx, hwc->config | enable_mask); } static inline void x86_pmu_disable_event(struct perf_event *event) @@ -919,7 +919,8 @@ static void x86_pmu_enable_event(struct perf_event *event) { struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); if (cpuc->enabled) - __x86_pmu_enable_event(&event->hw); + __x86_pmu_enable_event(&event->hw, + ARCH_PERFMON_EVENTSEL_ENABLE); } /* diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index a099df9..a4b56ac 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -513,7 +513,8 @@ static void intel_pmu_nhm_enable_all(int added) if (!event) continue; - __x86_pmu_enable_event(&event->hw); + __x86_pmu_enable_event(&event->hw, + ARCH_PERFMON_EVENTSEL_ENABLE); } } intel_pmu_enable_all(added); @@ -617,7 +618,7 @@ static void intel_pmu_enable_event(struct perf_event *event) if (unlikely(event->attr.precise)) intel_pmu_pebs_enable(event); - __x86_pmu_enable_event(hwc); + __x86_pmu_enable_event(hwc, ARCH_PERFMON_EVENTSEL_ENABLE); } /* -- cgit v0.10.2 From a1f2b70a942b8d858a0ab02567da3999b60a99b2 Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Tue, 13 Apr 2010 22:23:15 +0200 Subject: perf, x86: Use weight instead of cmask in for_each_event_constraint() There may exist constraints with a cmask set to zero. In this case for_each_event_constraint() will not work properly. Now weight is used instead of the cmask for loop exit detection. Weight is always a value other than zero since the default contains the HWEIGHT from the counter mask and in other cases a value of zero does not fit too. This is in preparation of ibs event constraints that wont have a cmask. Signed-off-by: Robert Richter Signed-off-by: Peter Zijlstra LKML-Reference: <1271190201-25705-7-git-send-email-robert.richter@amd.com> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 4e218d7..4a3f1f2 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -170,7 +170,7 @@ struct cpu_hw_events { EVENT_CONSTRAINT(0, 0, 0) #define for_each_event_constraint(e, c) \ - for ((e) = (c); (e)->cmask; (e)++) + for ((e) = (c); (e)->weight; (e)++) union perf_capabilities { struct { -- cgit v0.10.2 From 1e9a6d8d44cb6dcd2799b36ceb23007e6a423bfe Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 4 May 2010 16:30:21 +0200 Subject: perf, x86: Remove PEBS SAMPLE_RAW support Its broken, we really should get PERF_SAMPLE_REGS sorted. Signed-off-by: Peter Zijlstra LKML-Reference: Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c index ec8b2e1..080b9b0 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -459,7 +459,6 @@ static void intel_pmu_drain_pebs_core(struct pt_regs *iregs) struct perf_event *event = cpuc->events[0]; /* PMC0 only */ struct pebs_record_core *at, *top; struct perf_sample_data data; - struct perf_raw_record raw; struct pt_regs regs; int n; @@ -499,12 +498,6 @@ static void intel_pmu_drain_pebs_core(struct pt_regs *iregs) perf_sample_data_init(&data, 0); data.period = event->hw.last_period; - if (event->attr.sample_type & PERF_SAMPLE_RAW) { - raw.size = x86_pmu.pebs_record_size; - raw.data = at; - data.raw = &raw; - } - /* * We use the interrupt regs as a base because the PEBS record * does not contain a full regs set, specifically it seems to @@ -536,7 +529,6 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs) struct pebs_record_nhm *at, *top; struct perf_sample_data data; struct perf_event *event = NULL; - struct perf_raw_record raw; struct pt_regs regs; u64 status = 0; int bit, n; @@ -585,12 +577,6 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs) perf_sample_data_init(&data, 0); data.period = event->hw.last_period; - if (event->attr.sample_type & PERF_SAMPLE_RAW) { - raw.size = x86_pmu.pebs_record_size; - raw.data = at; - data.raw = &raw; - } - /* * See the comment in intel_pmu_drain_pebs_core() */ -- cgit v0.10.2 From 2b0b5c6fe9b383f3cf35a0a6371c9d577bd523ff Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 8 Apr 2010 23:03:20 +0200 Subject: perf, x86: Consolidate some code repetition Remove some duplicated logic. Signed-off-by: Peter Zijlstra LKML-Reference: Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c index 080b9b0..35056f7 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -452,14 +452,54 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs) static int intel_pmu_save_and_restart(struct perf_event *event); +static void __intel_pmu_pebs_event(struct perf_event *event, + struct pt_regs *iregs, void *__pebs) +{ + /* + * We cast to pebs_record_core since that is a subset of + * both formats and we don't use the other fields in this + * routine. + */ + struct pebs_record_core *pebs = __pebs; + struct perf_sample_data data; + struct pt_regs regs; + + if (!intel_pmu_save_and_restart(event)) + return; + + perf_sample_data_init(&data, 0); + data.period = event->hw.last_period; + + /* + * We use the interrupt regs as a base because the PEBS record + * does not contain a full regs set, specifically it seems to + * lack segment descriptors, which get used by things like + * user_mode(). + * + * In the simple case fix up only the IP and BP,SP regs, for + * PERF_SAMPLE_IP and PERF_SAMPLE_CALLCHAIN to function properly. + * A possible PERF_SAMPLE_REGS will have to transfer all regs. + */ + regs = *iregs; + regs.ip = pebs->ip; + regs.bp = pebs->bp; + regs.sp = pebs->sp; + + if (intel_pmu_pebs_fixup_ip(regs)) + regs.flags |= PERF_EFLAGS_EXACT; + else + regs.flags &= ~PERF_EFLAGS_EXACT; + + if (perf_event_overflow(event, 1, &data, ®s)) + x86_pmu_stop(event); +} + static void intel_pmu_drain_pebs_core(struct pt_regs *iregs) { struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); struct debug_store *ds = cpuc->ds; struct perf_event *event = cpuc->events[0]; /* PMC0 only */ struct pebs_record_core *at, *top; - struct perf_sample_data data; - struct pt_regs regs; int n; if (!ds || !x86_pmu.pebs) @@ -485,9 +525,6 @@ static void intel_pmu_drain_pebs_core(struct pt_regs *iregs) if (n <= 0) return; - if (!intel_pmu_save_and_restart(event)) - return; - /* * Should not happen, we program the threshold at 1 and do not * set a reset value. @@ -495,31 +532,7 @@ static void intel_pmu_drain_pebs_core(struct pt_regs *iregs) WARN_ON_ONCE(n > 1); at += n - 1; - perf_sample_data_init(&data, 0); - data.period = event->hw.last_period; - - /* - * We use the interrupt regs as a base because the PEBS record - * does not contain a full regs set, specifically it seems to - * lack segment descriptors, which get used by things like - * user_mode(). - * - * In the simple case fix up only the IP and BP,SP regs, for - * PERF_SAMPLE_IP and PERF_SAMPLE_CALLCHAIN to function properly. - * A possible PERF_SAMPLE_REGS will have to transfer all regs. - */ - regs = *iregs; - regs.ip = at->ip; - regs.bp = at->bp; - regs.sp = at->sp; - - if (intel_pmu_pebs_fixup_ip(®s)) - regs.flags |= PERF_EFLAGS_EXACT; - else - regs.flags &= ~PERF_EFLAGS_EXACT; - - if (perf_event_overflow(event, 1, &data, ®s)) - x86_pmu_stop(event); + __intel_pmu_pebs_event(event, iregs, at); } static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs) @@ -527,9 +540,7 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs) struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); struct debug_store *ds = cpuc->ds; struct pebs_record_nhm *at, *top; - struct perf_sample_data data; struct perf_event *event = NULL; - struct pt_regs regs; u64 status = 0; int bit, n; @@ -571,27 +582,7 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs) if (!event || bit >= MAX_PEBS_EVENTS) continue; - if (!intel_pmu_save_and_restart(event)) - continue; - - perf_sample_data_init(&data, 0); - data.period = event->hw.last_period; - - /* - * See the comment in intel_pmu_drain_pebs_core() - */ - regs = *iregs; - regs.ip = at->ip; - regs.bp = at->bp; - regs.sp = at->sp; - - if (intel_pmu_pebs_fixup_ip(®s)) - regs.flags |= PERF_EFLAGS_EXACT; - else - regs.flags &= ~PERF_EFLAGS_EXACT; - - if (perf_event_overflow(event, 1, &data, ®s)) - x86_pmu_stop(event); + __intel_pmu_pebs_event(event, iregs, at); } } -- cgit v0.10.2 From ab608344bcbde4f55ec4cd911b686b0ce3eae076 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 8 Apr 2010 23:03:20 +0200 Subject: perf, x86: Improve the PEBS ABI Rename perf_event_attr::precise to perf_event_attr::precise_ip and widen it to 2 bits. This new field describes the required precision of the PERF_SAMPLE_IP field: 0 - SAMPLE_IP can have arbitrary skid 1 - SAMPLE_IP must have constant skid 2 - SAMPLE_IP requested to have 0 skid 3 - SAMPLE_IP must have 0 skid And modify the Intel PEBS code accordingly. The PEBS implementation now supports up to precise_ip == 2, where we perform the IP fixup. Also s/PERF_RECORD_MISC_EXACT/&_IP/ to clarify its meaning, this bit should be set for each PERF_SAMPLE_IP field known to match the actual instruction triggering the event. This new scheme allows for a PEBS mode that uses the buffer for more than a single event. Signed-off-by: Peter Zijlstra Cc: Paul Mackerras Cc: Stephane Eranian LKML-Reference: Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 4a3f1f2..27fa9ee 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -488,6 +488,21 @@ static int x86_setup_perfctr(struct perf_event *event) static int x86_pmu_hw_config(struct perf_event *event) { + if (event->attr.precise_ip) { + int precise = 0; + + /* Support for constant skid */ + if (x86_pmu.pebs) + precise++; + + /* Support for IP fixup */ + if (x86_pmu.lbr_nr) + precise++; + + if (event->attr.precise_ip > precise) + return -EOPNOTSUPP; + } + /* * Generate PMC IRQs: * (keep 'enabled' bit clear for now) @@ -1780,7 +1795,7 @@ unsigned long perf_misc_flags(struct pt_regs *regs) } if (regs->flags & PERF_EFLAGS_EXACT) - misc |= PERF_RECORD_MISC_EXACT; + misc |= PERF_RECORD_MISC_EXACT_IP; return misc; } diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index a4b56ac..fdbc652 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -563,7 +563,7 @@ static void intel_pmu_disable_event(struct perf_event *event) x86_pmu_disable_event(event); - if (unlikely(event->attr.precise)) + if (unlikely(event->attr.precise_ip)) intel_pmu_pebs_disable(event); } @@ -615,7 +615,7 @@ static void intel_pmu_enable_event(struct perf_event *event) return; } - if (unlikely(event->attr.precise)) + if (unlikely(event->attr.precise_ip)) intel_pmu_pebs_enable(event); __x86_pmu_enable_event(hwc, ARCH_PERFMON_EVENTSEL_ENABLE); diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c index 35056f7..18018d1 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -307,7 +307,7 @@ intel_pebs_constraints(struct perf_event *event) { struct event_constraint *c; - if (!event->attr.precise) + if (!event->attr.precise_ip) return NULL; if (x86_pmu.pebs_constraints) { @@ -330,7 +330,7 @@ static void intel_pmu_pebs_enable(struct perf_event *event) cpuc->pebs_enabled |= 1ULL << hwc->idx; WARN_ON_ONCE(cpuc->enabled); - if (x86_pmu.intel_cap.pebs_trap) + if (x86_pmu.intel_cap.pebs_trap && event->attr.precise_ip > 1) intel_pmu_lbr_enable(event); } @@ -345,7 +345,7 @@ static void intel_pmu_pebs_disable(struct perf_event *event) hwc->config |= ARCH_PERFMON_EVENTSEL_INT; - if (x86_pmu.intel_cap.pebs_trap) + if (x86_pmu.intel_cap.pebs_trap && event->attr.precise_ip > 1) intel_pmu_lbr_disable(event); } @@ -485,7 +485,7 @@ static void __intel_pmu_pebs_event(struct perf_event *event, regs.bp = pebs->bp; regs.sp = pebs->sp; - if (intel_pmu_pebs_fixup_ip(regs)) + if (event->attr.precise_ip > 1 && intel_pmu_pebs_fixup_ip(®s)) regs.flags |= PERF_EFLAGS_EXACT; else regs.flags &= ~PERF_EFLAGS_EXACT; @@ -518,7 +518,7 @@ static void intel_pmu_drain_pebs_core(struct pt_regs *iregs) WARN_ON_ONCE(!event); - if (!event->attr.precise) + if (!event->attr.precise_ip) return; n = top - at; @@ -570,7 +570,7 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs) WARN_ON_ONCE(!event); - if (!event->attr.precise) + if (!event->attr.precise_ip) continue; if (__test_and_set_bit(bit, (unsigned long *)&status)) diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 6be4a0f..23cd005 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -203,9 +203,19 @@ struct perf_event_attr { enable_on_exec : 1, /* next exec enables */ task : 1, /* trace fork/exit */ watermark : 1, /* wakeup_watermark */ - precise : 1, /* OoO invariant counter */ - - __reserved_1 : 48; + /* + * precise_ip: + * + * 0 - SAMPLE_IP can have arbitrary skid + * 1 - SAMPLE_IP must have constant skid + * 2 - SAMPLE_IP requested to have 0 skid + * 3 - SAMPLE_IP must have 0 skid + * + * See also PERF_RECORD_MISC_EXACT_IP + */ + precise_ip : 2, /* skid constraint */ + + __reserved_1 : 47; union { __u32 wakeup_events; /* wakeup every n events */ @@ -296,7 +306,12 @@ struct perf_event_mmap_page { #define PERF_RECORD_MISC_GUEST_KERNEL (4 << 0) #define PERF_RECORD_MISC_GUEST_USER (5 << 0) -#define PERF_RECORD_MISC_EXACT (1 << 14) +/* + * Indicates that the content of PERF_SAMPLE_IP points to + * the actual instruction that triggered the event. See also + * perf_event_attr::precise_ip. + */ +#define PERF_RECORD_MISC_EXACT_IP (1 << 14) /* * Reserve the last bit to indicate some extended misc field */ diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 3de3977..ed9b5b6 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -1021,7 +1021,7 @@ static void event__process_sample(const event_t *self, return; } - if (self->header.misc & PERF_RECORD_MISC_EXACT) + if (self->header.misc & PERF_RECORD_MISC_EXACT_IP) exact_samples++; if (event__preprocess_sample(self, session, &al, symbol_filter) < 0 || diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index bc8b7e6..ae7f591 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -654,10 +654,6 @@ parse_raw_event(const char **strp, struct perf_event_attr *attr) return EVT_FAILED; n = hex2u64(str + 1, &config); if (n > 0) { - if (str[n+1] == 'p') { - attr->precise = 1; - n++; - } *strp = str + n + 1; attr->type = PERF_TYPE_RAW; attr->config = config; @@ -692,19 +688,29 @@ static enum event_result parse_event_modifier(const char **strp, struct perf_event_attr *attr) { const char *str = *strp; - int eu = 1, ek = 1, eh = 1; + int exclude = 0; + int eu = 0, ek = 0, eh = 0, precise = 0; if (*str++ != ':') return 0; while (*str) { - if (*str == 'u') + if (*str == 'u') { + if (!exclude) + exclude = eu = ek = eh = 1; eu = 0; - else if (*str == 'k') + } else if (*str == 'k') { + if (!exclude) + exclude = eu = ek = eh = 1; ek = 0; - else if (*str == 'h') + } else if (*str == 'h') { + if (!exclude) + exclude = eu = ek = eh = 1; eh = 0; - else + } else if (*str == 'p') { + precise++; + } else break; + ++str; } if (str >= *strp + 2) { @@ -712,6 +718,7 @@ parse_event_modifier(const char **strp, struct perf_event_attr *attr) attr->exclude_user = eu; attr->exclude_kernel = ek; attr->exclude_hv = eh; + attr->precise_ip = precise; return 1; } return 0; -- cgit v0.10.2 From 6bde9b6ce0127e2a56228a2071536d422be31336 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Fri, 23 Apr 2010 13:56:00 +0800 Subject: perf: Add group scheduling transactional APIs Add group scheduling transactional APIs to struct pmu. These APIs will be implemented in arch code, based on Peter's idea as below. > the idea behind hw_perf_group_sched_in() is to not perform > schedulability tests on each event in the group, but to add the group > as a whole and then perform one test. > > Of course, when that test fails, you'll have to roll-back the whole > group again. > > So start_txn (or a better name) would simply toggle a flag in the pmu > implementation that will make pmu::enable() not perform the > schedulablilty test. > > Then commit_txn() will perform the schedulability test (so note the > method has to have a !void return value. > > This will allow us to use the regular > kernel/perf_event.c::group_sched_in() and all the rollback code. > Currently each hw_perf_group_sched_in() implementation duplicates all > the rolllback code (with various bugs). ->start_txn: Start group events scheduling transaction, set a flag to make pmu::enable() not perform the schedulability test, it will be performed at commit time. ->commit_txn: Commit group events scheduling transaction, perform the group schedulability as a whole ->cancel_txn: Stop group events scheduling transaction, clear the flag so pmu::enable() will perform the schedulability test. Reviewed-by: Stephane Eranian Reviewed-by: Frederic Weisbecker Signed-off-by: Lin Ming Cc: David Miller Cc: Paul Mackerras Signed-off-by: Peter Zijlstra LKML-Reference: <1272002160.5707.60.camel@minggr.sh.intel.com> Signed-off-by: Ingo Molnar diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 23cd005..4924c96 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -547,6 +547,8 @@ struct hw_perf_event { struct perf_event; +#define PERF_EVENT_TXN_STARTED 1 + /** * struct pmu - generic performance monitoring unit */ @@ -557,6 +559,16 @@ struct pmu { void (*stop) (struct perf_event *event); void (*read) (struct perf_event *event); void (*unthrottle) (struct perf_event *event); + + /* + * group events scheduling is treated as a transaction, + * add group events as a whole and perform one schedulability test. + * If test fails, roll back the whole group + */ + + void (*start_txn) (const struct pmu *pmu); + void (*cancel_txn) (const struct pmu *pmu); + int (*commit_txn) (const struct pmu *pmu); }; /** @@ -823,9 +835,6 @@ extern void perf_disable(void); extern void perf_enable(void); extern int perf_event_task_disable(void); extern int perf_event_task_enable(void); -extern int hw_perf_group_sched_in(struct perf_event *group_leader, - struct perf_cpu_context *cpuctx, - struct perf_event_context *ctx); extern void perf_event_update_userpage(struct perf_event *event); extern int perf_event_release_kernel(struct perf_event *event); extern struct perf_event * diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 34659d4..bb06382 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -83,14 +83,6 @@ extern __weak const struct pmu *hw_perf_event_init(struct perf_event *event) void __weak hw_perf_disable(void) { barrier(); } void __weak hw_perf_enable(void) { barrier(); } -int __weak -hw_perf_group_sched_in(struct perf_event *group_leader, - struct perf_cpu_context *cpuctx, - struct perf_event_context *ctx) -{ - return 0; -} - void __weak perf_event_print_debug(void) { } static DEFINE_PER_CPU(int, perf_disable_count); @@ -644,15 +636,20 @@ group_sched_in(struct perf_event *group_event, struct perf_cpu_context *cpuctx, struct perf_event_context *ctx) { - struct perf_event *event, *partial_group; + struct perf_event *event, *partial_group = NULL; + const struct pmu *pmu = group_event->pmu; + bool txn = false; int ret; if (group_event->state == PERF_EVENT_STATE_OFF) return 0; - ret = hw_perf_group_sched_in(group_event, cpuctx, ctx); - if (ret) - return ret < 0 ? ret : 0; + /* Check if group transaction availabe */ + if (pmu->start_txn) + txn = true; + + if (txn) + pmu->start_txn(pmu); if (event_sched_in(group_event, cpuctx, ctx)) return -EAGAIN; @@ -667,9 +664,19 @@ group_sched_in(struct perf_event *group_event, } } - return 0; + if (txn) { + ret = pmu->commit_txn(pmu); + if (!ret) { + pmu->cancel_txn(pmu); + + return 0; + } + } group_error: + if (txn) + pmu->cancel_txn(pmu); + /* * Groups can be scheduled in as one unit only, so undo any * partial group before returning: -- cgit v0.10.2 From 4d1c52b02d977d884abb21d0bbaba6b5d6bc8374 Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Fri, 23 Apr 2010 13:56:12 +0800 Subject: perf, x86: implement group scheduling transactional APIs Convert to the transactional PMU API and remove the duplication of group_sched_in(). Reviewed-by: Stephane Eranian Signed-off-by: Lin Ming Signed-off-by: Peter Zijlstra Cc: David Miller Cc: Paul Mackerras LKML-Reference: <1272002172.5707.61.camel@minggr.sh.intel.com> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 27fa9ee..fd4db0d 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -110,6 +110,8 @@ struct cpu_hw_events { u64 tags[X86_PMC_IDX_MAX]; struct perf_event *event_list[X86_PMC_IDX_MAX]; /* in enabled order */ + unsigned int group_flag; + /* * Intel DebugStore bits */ @@ -961,6 +963,14 @@ static int x86_pmu_enable(struct perf_event *event) if (n < 0) return n; + /* + * If group events scheduling transaction was started, + * skip the schedulability test here, it will be peformed + * at commit time(->commit_txn) as a whole + */ + if (cpuc->group_flag & PERF_EVENT_TXN_STARTED) + goto out; + ret = x86_pmu.schedule_events(cpuc, n, assign); if (ret) return ret; @@ -970,6 +980,7 @@ static int x86_pmu_enable(struct perf_event *event) */ memcpy(cpuc->assign, assign, n*sizeof(int)); +out: cpuc->n_events = n; cpuc->n_added += n - n0; @@ -1227,119 +1238,6 @@ x86_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event) return &unconstrained; } -static int x86_event_sched_in(struct perf_event *event, - struct perf_cpu_context *cpuctx) -{ - int ret = 0; - - event->state = PERF_EVENT_STATE_ACTIVE; - event->oncpu = smp_processor_id(); - event->tstamp_running += event->ctx->time - event->tstamp_stopped; - - if (!is_x86_event(event)) - ret = event->pmu->enable(event); - - if (!ret && !is_software_event(event)) - cpuctx->active_oncpu++; - - if (!ret && event->attr.exclusive) - cpuctx->exclusive = 1; - - return ret; -} - -static void x86_event_sched_out(struct perf_event *event, - struct perf_cpu_context *cpuctx) -{ - event->state = PERF_EVENT_STATE_INACTIVE; - event->oncpu = -1; - - if (!is_x86_event(event)) - event->pmu->disable(event); - - event->tstamp_running -= event->ctx->time - event->tstamp_stopped; - - if (!is_software_event(event)) - cpuctx->active_oncpu--; - - if (event->attr.exclusive || !cpuctx->active_oncpu) - cpuctx->exclusive = 0; -} - -/* - * Called to enable a whole group of events. - * Returns 1 if the group was enabled, or -EAGAIN if it could not be. - * Assumes the caller has disabled interrupts and has - * frozen the PMU with hw_perf_save_disable. - * - * called with PMU disabled. If successful and return value 1, - * then guaranteed to call perf_enable() and hw_perf_enable() - */ -int hw_perf_group_sched_in(struct perf_event *leader, - struct perf_cpu_context *cpuctx, - struct perf_event_context *ctx) -{ - struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); - struct perf_event *sub; - int assign[X86_PMC_IDX_MAX]; - int n0, n1, ret; - - if (!x86_pmu_initialized()) - return 0; - - /* n0 = total number of events */ - n0 = collect_events(cpuc, leader, true); - if (n0 < 0) - return n0; - - ret = x86_pmu.schedule_events(cpuc, n0, assign); - if (ret) - return ret; - - ret = x86_event_sched_in(leader, cpuctx); - if (ret) - return ret; - - n1 = 1; - list_for_each_entry(sub, &leader->sibling_list, group_entry) { - if (sub->state > PERF_EVENT_STATE_OFF) { - ret = x86_event_sched_in(sub, cpuctx); - if (ret) - goto undo; - ++n1; - } - } - /* - * copy new assignment, now we know it is possible - * will be used by hw_perf_enable() - */ - memcpy(cpuc->assign, assign, n0*sizeof(int)); - - cpuc->n_events = n0; - cpuc->n_added += n1; - ctx->nr_active += n1; - - /* - * 1 means successful and events are active - * This is not quite true because we defer - * actual activation until hw_perf_enable() but - * this way we* ensure caller won't try to enable - * individual events - */ - return 1; -undo: - x86_event_sched_out(leader, cpuctx); - n0 = 1; - list_for_each_entry(sub, &leader->sibling_list, group_entry) { - if (sub->state == PERF_EVENT_STATE_ACTIVE) { - x86_event_sched_out(sub, cpuctx); - if (++n0 == n1) - break; - } - } - return ret; -} - #include "perf_event_amd.c" #include "perf_event_p6.c" #include "perf_event_p4.c" @@ -1471,6 +1369,59 @@ static inline void x86_pmu_read(struct perf_event *event) x86_perf_event_update(event); } +/* + * Start group events scheduling transaction + * Set the flag to make pmu::enable() not perform the + * schedulability test, it will be performed at commit time + */ +static void x86_pmu_start_txn(const struct pmu *pmu) +{ + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + + cpuc->group_flag |= PERF_EVENT_TXN_STARTED; +} + +/* + * Stop group events scheduling transaction + * Clear the flag and pmu::enable() will perform the + * schedulability test. + */ +static void x86_pmu_cancel_txn(const struct pmu *pmu) +{ + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + + cpuc->group_flag &= ~PERF_EVENT_TXN_STARTED; +} + +/* + * Commit group events scheduling transaction + * Perform the group schedulability test as a whole + * Return 0 if success + */ +static int x86_pmu_commit_txn(const struct pmu *pmu) +{ + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + int assign[X86_PMC_IDX_MAX]; + int n, ret; + + n = cpuc->n_events; + + if (!x86_pmu_initialized()) + return -EAGAIN; + + ret = x86_pmu.schedule_events(cpuc, n, assign); + if (ret) + return ret; + + /* + * copy new assignment, now we know it is possible + * will be used by hw_perf_enable() + */ + memcpy(cpuc->assign, assign, n*sizeof(int)); + + return 0; +} + static const struct pmu pmu = { .enable = x86_pmu_enable, .disable = x86_pmu_disable, @@ -1478,6 +1429,9 @@ static const struct pmu pmu = { .stop = x86_pmu_stop, .read = x86_pmu_read, .unthrottle = x86_pmu_unthrottle, + .start_txn = x86_pmu_start_txn, + .cancel_txn = x86_pmu_cancel_txn, + .commit_txn = x86_pmu_commit_txn, }; /* -- cgit v0.10.2 From 58e323cf5e4ed621a6e88263aca40c3d9c3d9bfd Mon Sep 17 00:00:00 2001 From: Joern Engel Date: Fri, 7 May 2010 14:15:04 +0200 Subject: logfs: remove unused variable Signed-off-by: Joern Engel diff --git a/fs/logfs/file.c b/fs/logfs/file.c index 1639e92..0de5240 100644 --- a/fs/logfs/file.c +++ b/fs/logfs/file.c @@ -222,7 +222,6 @@ int logfs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, int logfs_fsync(struct file *file, struct dentry *dentry, int datasync) { struct super_block *sb = dentry->d_inode->i_sb; - struct logfs_super *super = logfs_super(sb); logfs_write_anchor(sb); return 0; -- cgit v0.10.2 From ccf31c10f125ab5233c8517f91d4b3bd0bd60936 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 7 May 2010 10:59:06 +0200 Subject: logfs: handle errors from get_mtd_device() The get_mtd_device() function returns error pointers on failure and if we don't handle it, it leads to a crash. Signed-off-by: Dan Carpenter Signed-off-by: Joern Engel diff --git a/fs/logfs/dev_mtd.c b/fs/logfs/dev_mtd.c index cafb6ef..b02a402 100644 --- a/fs/logfs/dev_mtd.c +++ b/fs/logfs/dev_mtd.c @@ -250,5 +250,7 @@ int logfs_get_sb_mtd(struct file_system_type *type, int flags, const struct logfs_device_ops *devops = &mtd_devops; mtd = get_mtd_device(NULL, mtdnr); + if (IS_ERR(mtd)) + return PTR_ERR(mtd); return logfs_get_sb_device(type, flags, mtd, NULL, devops, mnt); } -- cgit v0.10.2 From 1cf4a0632c24ea61162ed819bde358bc94c55510 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 7 May 2010 14:07:05 -0300 Subject: perf list: Improve the raw hw event descriptor documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It was x86 specific and imcomplete at that, improve the situation by making it clear where the example provided applies and by adding the URLs for the Intel and AMD manuals where this is discussed in depth. Acked-by: Robert Richter Cc: Cyrill Gorcunov Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Tom Zanussi Cc: Robert Richter Reported-by: Robert Richter Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt index ad765e0..43e3dd2 100644 --- a/tools/perf/Documentation/perf-list.txt +++ b/tools/perf/Documentation/perf-list.txt @@ -18,8 +18,16 @@ various perf commands with the -e option. RAW HARDWARE EVENT DESCRIPTOR ----------------------------- Even when an event is not available in a symbolic form within perf right now, -it can be encoded as , for instance, if the Intel docs -describe an event as: +it can be encoded in a per processor specific way. + +For instance For x86 CPUs NNN represents the raw register encoding with the +layout of IA32_PERFEVTSELx MSRs (see [Intel® 64 and IA-32 Architectures Software Developer's Manual Volume 3B: System Programming Guide] Figure 30-1 Layout +of IA32_PERFEVTSELx MSRs) or AMD's PerfEvtSeln (see [AMD64 Architecture Programmer’s Manual Volume 2: System Programming], Page 344, +Figure 13-7 Performance Event-Select Register (PerfEvtSeln)). + +Example: + +If the Intel docs for a QM720 Core i7 describe an event as: Event Umask Event Mask Num. Value Mnemonic Description Comment @@ -33,6 +41,9 @@ raw encoding of 0x1A8 can be used: perf stat -e r1a8 -a sleep 1 perf record -e r1a8 ... +You should refer to the processor specific documentation for getting these +details. Some of them are referenced in the SEE ALSO section below. + OPTIONS ------- None @@ -40,4 +51,6 @@ None SEE ALSO -------- linkperf:perf-stat[1], linkperf:perf-top[1], -linkperf:perf-record[1] +linkperf:perf-record[1], +http://www.intel.com/Assets/PDF/manual/253669.pdf[Intel® 64 and IA-32 Architectures Software Developer's Manual Volume 3B: System Programming Guide], +http://support.amd.com/us/Processor_TechDocs/24593.pdf[AMD64 Architecture Programmer’s Manual Volume 2: System Programming] diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index bc8b7e6..7b24b5d 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -936,7 +936,8 @@ void print_events(void) printf("\n"); printf(" %-42s [%s]\n", - "rNNN (NNN=)", event_type_descriptors[PERF_TYPE_RAW]); + "rNNN (see 'perf list --help' on how to encode it)", + event_type_descriptors[PERF_TYPE_RAW]); printf("\n"); printf(" %-42s [%s]\n", -- cgit v0.10.2 From 6f485b41875dbf5160c1990322469c1f65f77b28 Mon Sep 17 00:00:00 2001 From: Joern Engel Date: Fri, 7 May 2010 19:38:40 +0200 Subject: logfs: handle powerfail on NAND flash The write buffer may not have been written and may no longer be written due to an interrupted write in the affected page. Signed-off-by: Joern Engel diff --git a/fs/logfs/dev_bdev.c b/fs/logfs/dev_bdev.c index 243c000..9bd2ce2 100644 --- a/fs/logfs/dev_bdev.c +++ b/fs/logfs/dev_bdev.c @@ -303,6 +303,11 @@ static void bdev_put_device(struct super_block *sb) close_bdev_exclusive(logfs_super(sb)->s_bdev, FMODE_READ|FMODE_WRITE); } +static int bdev_can_write_buf(struct super_block *sb, u64 ofs) +{ + return 0; +} + static const struct logfs_device_ops bd_devops = { .find_first_sb = bdev_find_first_sb, .find_last_sb = bdev_find_last_sb, @@ -310,6 +315,7 @@ static const struct logfs_device_ops bd_devops = { .readpage = bdev_readpage, .writeseg = bdev_writeseg, .erase = bdev_erase, + .can_write_buf = bdev_can_write_buf, .sync = bdev_sync, .put_device = bdev_put_device, }; diff --git a/fs/logfs/dev_mtd.c b/fs/logfs/dev_mtd.c index b02a402..a85d47d 100644 --- a/fs/logfs/dev_mtd.c +++ b/fs/logfs/dev_mtd.c @@ -9,6 +9,7 @@ #include #include #include +#include #define PAGE_OFS(ofs) ((ofs) & (PAGE_SIZE-1)) @@ -126,7 +127,8 @@ static int mtd_readpage(void *_sb, struct page *page) err = mtd_read(sb, page->index << PAGE_SHIFT, PAGE_SIZE, page_address(page)); - if (err == -EUCLEAN) { + if (err == -EUCLEAN || err == -EBADMSG) { + /* -EBADMSG happens regularly on power failures */ err = 0; /* FIXME: force GC this segment */ } @@ -233,12 +235,32 @@ static void mtd_put_device(struct super_block *sb) put_mtd_device(logfs_super(sb)->s_mtd); } +static int mtd_can_write_buf(struct super_block *sb, u64 ofs) +{ + struct logfs_super *super = logfs_super(sb); + void *buf; + int err; + + buf = kmalloc(super->s_writesize, GFP_KERNEL); + if (!buf) + return -ENOMEM; + err = mtd_read(sb, ofs, super->s_writesize, buf); + if (err) + goto out; + if (memchr_inv(buf, 0xff, super->s_writesize)) + err = -EIO; + kfree(buf); +out: + return err; +} + static const struct logfs_device_ops mtd_devops = { .find_first_sb = mtd_find_first_sb, .find_last_sb = mtd_find_last_sb, .readpage = mtd_readpage, .writeseg = mtd_writeseg, .erase = mtd_erase, + .can_write_buf = mtd_can_write_buf, .sync = mtd_sync, .put_device = mtd_put_device, }; diff --git a/fs/logfs/gc.c b/fs/logfs/gc.c index 76c242f..caa4419 100644 --- a/fs/logfs/gc.c +++ b/fs/logfs/gc.c @@ -122,7 +122,7 @@ static void logfs_cleanse_block(struct super_block *sb, u64 ofs, u64 ino, logfs_safe_iput(inode, cookie); } -static u32 logfs_gc_segment(struct super_block *sb, u32 segno, u8 dist) +static u32 logfs_gc_segment(struct super_block *sb, u32 segno) { struct logfs_super *super = logfs_super(sb); struct logfs_segment_header sh; @@ -401,7 +401,7 @@ static int __logfs_gc_once(struct super_block *sb, struct gc_candidate *cand) segno, (u64)segno << super->s_segshift, dist, no_free_segments(sb), valid, super->s_free_bytes); - cleaned = logfs_gc_segment(sb, segno, dist); + cleaned = logfs_gc_segment(sb, segno); log_gc("GC segment #%02x complete - now %x valid\n", segno, valid - cleaned); BUG_ON(cleaned != valid); @@ -632,38 +632,31 @@ static int check_area(struct super_block *sb, int i) { struct logfs_super *super = logfs_super(sb); struct logfs_area *area = super->s_area[i]; - struct logfs_object_header oh; + gc_level_t gc_level; + u32 cleaned, valid, ec; u32 segno = area->a_segno; - u32 ofs = area->a_used_bytes; - __be32 crc; - int err; + u64 ofs = dev_ofs(sb, area->a_segno, area->a_written_bytes); if (!area->a_is_open) return 0; - for (ofs = area->a_used_bytes; - ofs <= super->s_segsize - sizeof(oh); - ofs += (u32)be16_to_cpu(oh.len) + sizeof(oh)) { - err = wbuf_read(sb, dev_ofs(sb, segno, ofs), sizeof(oh), &oh); - if (err) - return err; - - if (!memchr_inv(&oh, 0xff, sizeof(oh))) - break; + if (super->s_devops->can_write_buf(sb, ofs) == 0) + return 0; - crc = logfs_crc32(&oh, sizeof(oh) - 4, 4); - if (crc != oh.crc) { - printk(KERN_INFO "interrupted header at %llx\n", - dev_ofs(sb, segno, ofs)); - return 0; - } - } - if (ofs != area->a_used_bytes) { - printk(KERN_INFO "%x bytes unaccounted data found at %llx\n", - ofs - area->a_used_bytes, - dev_ofs(sb, segno, area->a_used_bytes)); - area->a_used_bytes = ofs; - } + printk(KERN_INFO"LogFS: Possibly incomplete write at %llx\n", ofs); + /* + * The device cannot write back the write buffer. Most likely the + * wbuf was already written out and the system crashed at some point + * before the journal commit happened. In that case we wouldn't have + * to do anything. But if the crash happened before the wbuf was + * written out correctly, we must GC this segment. So assume the + * worst and always do the GC run. + */ + area->a_is_open = 0; + valid = logfs_valid_bytes(sb, segno, &ec, &gc_level); + cleaned = logfs_gc_segment(sb, segno); + if (cleaned != valid) + return -EIO; return 0; } diff --git a/fs/logfs/logfs.h b/fs/logfs/logfs.h index 26a9458..93b55f3 100644 --- a/fs/logfs/logfs.h +++ b/fs/logfs/logfs.h @@ -144,6 +144,7 @@ struct logfs_area_ops { * @erase: erase one segment * @read: read from the device * @erase: erase part of the device + * @can_write_buf: decide whether wbuf can be written to ofs */ struct logfs_device_ops { struct page *(*find_first_sb)(struct super_block *sb, u64 *ofs); @@ -153,6 +154,7 @@ struct logfs_device_ops { void (*writeseg)(struct super_block *sb, u64 ofs, size_t len); int (*erase)(struct super_block *sb, loff_t ofs, size_t len, int ensure_write); + int (*can_write_buf)(struct super_block *sb, u64 ofs); void (*sync)(struct super_block *sb); void (*put_device)(struct super_block *sb); }; -- cgit v0.10.2 From 160b82420ab41f1e67fbf2e56dc587837ef39ce0 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Thu, 29 Apr 2010 17:53:33 +0200 Subject: ar9170: wait for asynchronous firmware loading This patch fixes a regression introduced by the following patch: "ar9170: load firmware asynchronously" When we kick off a firmware loading request and then unbind, or disconnect the usb device right away, we get into trouble: > ------------[ cut here ]------------ > WARNING: at lib/kref.c:44 kref_get+0x1c/0x20() > Hardware name: 18666GU > Modules linked in: ar9170usb [...] > Pid: 6588, comm: firmware/ar9170 Not tainted 2.6.34-rc5-wl #43 > Call Trace: > [] ? warn_slowpath_common+0x6e/0xb0 > [] ? kref_get+0x1c/0x20 > [] ? warn_slowpath_null+0x13/0x20 > [] ? kref_get+0x1c/0x20 > [] ? kobject_get+0xf/0x20 > [] ? get_device+0x10/0x20 > [] ? device_add+0x60/0x530 > [] ? kobject_init+0x25/0xa0 > [] ? _request_firmware+0x139/0x3e0 > [] ? request_firmware_work_func+0x20/0x70 > [] ? request_firmware_work_func+0x0/0x70 > [] ? kthread+0x74/0x80 > [] ? kthread+0x0/0x80 > [] ? kernel_thread_helper+0x6/0x10 >---[ end trace 2d50bd818f64a1b7 ]--- - followed by a random Oops - Avoid that by waiting for the firmware loading to finish (whether successfully or not) before the unbind in ar9170_usb_disconnect. Reported-by: Johannes Berg Bug-fixed-by: Johannes Berg Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index 6b1cb70..24dc555 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c @@ -726,12 +726,16 @@ static void ar9170_usb_firmware_failed(struct ar9170_usb *aru) { struct device *parent = aru->udev->dev.parent; + complete(&aru->firmware_loading_complete); + /* unbind anything failed */ if (parent) down(&parent->sem); device_release_driver(&aru->udev->dev); if (parent) up(&parent->sem); + + usb_put_dev(aru->udev); } static void ar9170_usb_firmware_finish(const struct firmware *fw, void *context) @@ -760,6 +764,8 @@ static void ar9170_usb_firmware_finish(const struct firmware *fw, void *context) if (err) goto err_unrx; + complete(&aru->firmware_loading_complete); + usb_put_dev(aru->udev); return; err_unrx: @@ -857,6 +863,7 @@ static int ar9170_usb_probe(struct usb_interface *intf, init_usb_anchor(&aru->tx_pending); init_usb_anchor(&aru->tx_submitted); init_completion(&aru->cmd_wait); + init_completion(&aru->firmware_loading_complete); spin_lock_init(&aru->tx_urb_lock); aru->tx_pending_urbs = 0; @@ -876,6 +883,7 @@ static int ar9170_usb_probe(struct usb_interface *intf, if (err) goto err_freehw; + usb_get_dev(aru->udev); return request_firmware_nowait(THIS_MODULE, 1, "ar9170.fw", &aru->udev->dev, GFP_KERNEL, aru, ar9170_usb_firmware_step2); @@ -895,6 +903,9 @@ static void ar9170_usb_disconnect(struct usb_interface *intf) return; aru->common.state = AR9170_IDLE; + + wait_for_completion(&aru->firmware_loading_complete); + ar9170_unregister(&aru->common); ar9170_usb_cancel_urbs(aru); diff --git a/drivers/net/wireless/ath/ar9170/usb.h b/drivers/net/wireless/ath/ar9170/usb.h index a2ce3b1..919b060 100644 --- a/drivers/net/wireless/ath/ar9170/usb.h +++ b/drivers/net/wireless/ath/ar9170/usb.h @@ -71,6 +71,7 @@ struct ar9170_usb { unsigned int tx_pending_urbs; struct completion cmd_wait; + struct completion firmware_loading_complete; int readlen; u8 *readbuf; -- cgit v0.10.2 From 79733a865c7fd778ce45e3503962b3a875b0a153 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Tue, 4 May 2010 16:04:49 -0700 Subject: mac80211: remove association work when processing deauth request In https://bugzilla.kernel.org/show_bug.cgi?id=15794 a user encountered the following: [18967.469098] wlan0: authenticated [18967.472527] wlan0: associate with 00:1c:10:b8:e3:ea (try 1) [18967.472585] wlan0: deauthenticating from 00:1c:10:b8:e3:ea by local choice (reason=3) [18967.672057] wlan0: associate with 00:1c:10:b8:e3:ea (try 2) [18967.872357] wlan0: associate with 00:1c:10:b8:e3:ea (try 3) [18968.072960] wlan0: association with 00:1c:10:b8:e3:ea timed out [18968.076890] ------------[ cut here ]------------ [18968.076898] WARNING: at net/wireless/mlme.c:341 cfg80211_send_assoc_timeout+0xa8/0x140() [18968.076900] Hardware name: GX628 [18968.076924] Pid: 1408, comm: phy0 Not tainted 2.6.34-rc4-00082-g250541f-dirty #3 [18968.076926] Call Trace: [18968.076931] [] ? warn_slowpath_common+0x6e/0xb0 [18968.076934] [] ? cfg80211_send_assoc_timeout+0xa8/0x140 [18968.076937] [] ? mod_timer+0x10b/0x180 [18968.076940] [] ? ieee80211_assoc_done+0xbc/0xc0 [18968.076943] [] ? ieee80211_work_work+0x553/0x11c0 [18968.076945] [] ? finish_task_switch+0x41/0xb0 [18968.076948] [] ? ieee80211_work_work+0x0/0x11c0 [18968.076951] [] ? worker_thread+0x13b/0x210 [18968.076954] [] ? autoremove_wake_function+0x0/0x30 [18968.076956] [] ? worker_thread+0x0/0x210 [18968.076959] [] ? kthread+0x8e/0xa0 [18968.076962] [] ? kernel_thread_helper+0x4/0x10 [18968.076964] [] ? kthread+0x0/0xa0 [18968.076966] [] ? kernel_thread_helper+0x0/0x10 [18968.076968] ---[ end trace 8aa6265f4b1adfe0 ]--- As explained by Johannes Berg : We authenticate successfully, and then userspace requests association. Then we start that process, but the AP doesn't respond. While we're still waiting for an AP response, userspace asks for a deauth. We do the deauth, but don't abort the association work. Then once the association work times out we tell cfg80211, but it no longer wants to know since for all it is concerned we accepted the deauth that also kills the association attempt. Fix this by, upon receipt of deauth request, removing the association work and continuing to send the deauth. Unfortunately the user reporting the issue is not able to reproduce this problem anymore and cannot verify this fix. This seems like a well understood issue though and I thus present the patch. Bug-identified-by: Johannes Berg Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 8a96503..6ccd48e 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2029,7 +2029,8 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, continue; if (wk->type != IEEE80211_WORK_DIRECT_PROBE && - wk->type != IEEE80211_WORK_AUTH) + wk->type != IEEE80211_WORK_AUTH && + wk->type != IEEE80211_WORK_ASSOC) continue; if (memcmp(req->bss->bssid, wk->filter_ta, ETH_ALEN)) -- cgit v0.10.2 From 1252fa3154fae1f9624ea40cbbf0ea5e21319013 Mon Sep 17 00:00:00 2001 From: Daniel Walker Date: Fri, 7 May 2010 12:09:52 -0700 Subject: Revert "arm: msm: add oprofile pmu support" This reverts commit ee3c454b8da04815c1884ed85fe89d2d131c0e51. As request by Russell King. Signed-off-by: Daniel Walker diff --git a/arch/arm/kernel/pmu.c b/arch/arm/kernel/pmu.c index 4f0eb4c..a124312 100644 --- a/arch/arm/kernel/pmu.c +++ b/arch/arm/kernel/pmu.c @@ -44,8 +44,6 @@ static const int irqs[] = { IRQ_IOP33X_CORE_PMU, #elif defined(CONFIG_ARCH_PXA) IRQ_PMU, -#elif defined(CONFIG_ARCH_MSM_ARM11) - INT_ARM11_PMU, #endif }; -- cgit v0.10.2 From fde4e2f73208b8f34f123791e39c0cb6bc74b32a Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 7 May 2010 10:41:10 -0400 Subject: HID: fix suspend crash by moving initializations earlier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Although the usbhid driver allocates its usbhid structure in the probe routine, several critical fields in that structure don't get initialized until usbhid_start(). However if report descriptor parsing fails then usbhid_start() is never called. This leads to problems during system suspend -- the system will freeze. This patch (as1378) fixes the bug by moving the initialization statements up into usbhid_probe(). Signed-off-by: Alan Stern Reported-by: Bruno Prémont Tested-By: Bruno Prémont Signed-off-by: Jiri Kosina diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 56d06cd..7b85b69 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -999,13 +999,6 @@ static int usbhid_start(struct hid_device *hid) } } - init_waitqueue_head(&usbhid->wait); - INIT_WORK(&usbhid->reset_work, hid_reset); - INIT_WORK(&usbhid->restart_work, __usbhid_restart_queues); - setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid); - - spin_lock_init(&usbhid->lock); - usbhid->urbctrl = usb_alloc_urb(0, GFP_KERNEL); if (!usbhid->urbctrl) { ret = -ENOMEM; @@ -1179,6 +1172,12 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id * usbhid->intf = intf; usbhid->ifnum = interface->desc.bInterfaceNumber; + init_waitqueue_head(&usbhid->wait); + INIT_WORK(&usbhid->reset_work, hid_reset); + INIT_WORK(&usbhid->restart_work, __usbhid_restart_queues); + setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid); + spin_lock_init(&usbhid->lock); + ret = hid_add_device(hid); if (ret) { if (ret != -ENODEV) -- cgit v0.10.2 From 2b107d93635616db0c3f893c8cc2e6d5cd8d77b2 Mon Sep 17 00:00:00 2001 From: Jacob Pan Date: Fri, 7 May 2010 14:59:45 -0700 Subject: x86: Avoid check hlt for newer cpus Check hlt instruction was targeted for some older CPUs. It is an expensive operation in that it takes 4 ticks to break out the check. We can avoid such check completely for newer x86 cpus (family >= 5). [ hpa: corrected family > 5 to family >= 5 ] Signed-off-by: Jacob Pan LKML-Reference: <1273269585-14346-1-git-send-email-jacob.jun.pan@linux.intel.com> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index 01a2652..c39576c 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -86,7 +86,7 @@ static void __init check_fpu(void) static void __init check_hlt(void) { - if (paravirt_enabled()) + if (boot_cpu_data.x86 >= 5 || paravirt_enabled()) return; printk(KERN_INFO "Checking 'hlt' instruction... "); -- cgit v0.10.2 From 9fa02317429449e8176c9bb6da3ac00eb14d52d3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 7 May 2010 16:55:41 -0700 Subject: x86, HyperV: fix up the license to mshyperv.c This should have been GPLv2 only, we cut and pasted from the wrong file originally, sorry. Also removed some unneeded boilerplate license code, we all know where to find the GPLv2, and that there's no warranty as that is implicit from the license. Cc: Ky Srinivasan Cc: Hank Janssen Signed-off-by: Greg Kroah-Hartman LKML-Reference: <20100507235541.GA15448@kroah.com> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index 2443b61..a58d8e6 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -6,18 +6,7 @@ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * the Free Software Foundation; version 2 of the License. * */ -- cgit v0.10.2 From e08cae4181af9483b04ecfac48f01c8e5a5f27bf Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 7 May 2010 16:57:28 -0700 Subject: x86: Clean up the hypervisor layer Clean up the hypervisor layer and the hypervisor drivers, using an ops structure instead of an enumeration with if statements. The identity of the hypervisor, if needed, can be tested by testing the pointer value in x86_hyper. The MS-HyperV private state is moved into a normal global variable (it's per-system state, not per-CPU state). Being a normal bss variable, it will be left at all zero on non-HyperV platforms, and so can generally be tested for HyperV-specific features without additional qualification. Signed-off-by: H. Peter Anvin Acked-by: Greg KH Cc: Hank Janssen Cc: Alok Kataria Cc: Ky Srinivasan LKML-Reference: <4BE49778.6060800@zytor.com> diff --git a/arch/x86/include/asm/hyperv.h b/arch/x86/include/asm/hyperv.h index 4604047..5df477a 100644 --- a/arch/x86/include/asm/hyperv.h +++ b/arch/x86/include/asm/hyperv.h @@ -1,5 +1,5 @@ -#ifndef _ASM_X86_KVM_HYPERV_H -#define _ASM_X86_KVM_HYPERV_H +#ifndef _ASM_X86_HYPERV_H +#define _ASM_X86_HYPERV_H #include @@ -16,6 +16,7 @@ #define HYPERV_HYPERVISOR_PRESENT_BIT 0x80000000 #define HYPERV_CPUID_MIN 0x40000005 +#define HYPERV_CPUID_MAX 0x4000ffff /* * Feature identification. EAX indicates which features are available diff --git a/arch/x86/include/asm/hypervisor.h b/arch/x86/include/asm/hypervisor.h index b78c094..70abda7 100644 --- a/arch/x86/include/asm/hypervisor.h +++ b/arch/x86/include/asm/hypervisor.h @@ -17,10 +17,33 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * */ -#ifndef ASM_X86__HYPERVISOR_H -#define ASM_X86__HYPERVISOR_H +#ifndef _ASM_X86_HYPERVISOR_H +#define _ASM_X86_HYPERVISOR_H extern void init_hypervisor(struct cpuinfo_x86 *c); extern void init_hypervisor_platform(void); +/* + * x86 hypervisor information + */ +struct hypervisor_x86 { + /* Hypervisor name */ + const char *name; + + /* Detection routine */ + bool (*detect)(void); + + /* Adjust CPU feature bits (run once per CPU) */ + void (*set_cpu_features)(struct cpuinfo_x86 *); + + /* Platform setup (run once per boot) */ + void (*init_platform)(void); +}; + +extern const struct hypervisor_x86 *x86_hyper; + +/* Recognized hypervisors */ +extern const struct hypervisor_x86 x86_hyper_vmware; +extern const struct hypervisor_x86 x86_hyper_ms_hyperv; + #endif diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h index 6cd8101..79ce568 100644 --- a/arch/x86/include/asm/mshyperv.h +++ b/arch/x86/include/asm/mshyperv.h @@ -1,7 +1,14 @@ -#ifndef ASM_X86__MSHYPER_H -#define ASM_X86__MSHYPER_H +#ifndef _ASM_X86_MSHYPER_H +#define _ASM_X86_MSHYPER_H -int ms_hyperv_platform(void); -void __cpuinit ms_hyperv_set_feature_bits(struct cpuinfo_x86 *c); +#include +#include + +struct ms_hyperv_info { + u32 features; + u32 hints; +}; + +extern struct ms_hyperv_info ms_hyperv; #endif diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 597c041..e4f1dfb 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -113,9 +113,6 @@ struct cpuinfo_x86 { /* Index into per_cpu list: */ u16 cpu_index; #endif - unsigned int x86_hyper_vendor; - /* The layout of this field is hypervisor specific */ - unsigned int x86_hyper_features; } __attribute__((__aligned__(SMP_CACHE_BYTES))); #define X86_VENDOR_INTEL 0 @@ -129,10 +126,6 @@ struct cpuinfo_x86 { #define X86_VENDOR_UNKNOWN 0xff -#define X86_HYPER_VENDOR_NONE 0 -#define X86_HYPER_VENDOR_VMWARE 1 -#define X86_HYPER_VENDOR_MSFT 2 - /* * capabilities of CPUs */ diff --git a/arch/x86/include/asm/vmware.h b/arch/x86/include/asm/vmware.h deleted file mode 100644 index e49ed6d..0000000 --- a/arch/x86/include/asm/vmware.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2008, VMware, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ -#ifndef ASM_X86__VMWARE_H -#define ASM_X86__VMWARE_H - -extern void vmware_platform_setup(void); -extern int vmware_platform(void); -extern void vmware_set_feature_bits(struct cpuinfo_x86 *c); - -#endif diff --git a/arch/x86/kernel/cpu/hypervisor.c b/arch/x86/kernel/cpu/hypervisor.c index de3f4e0..8738175 100644 --- a/arch/x86/kernel/cpu/hypervisor.c +++ b/arch/x86/kernel/cpu/hypervisor.c @@ -22,40 +22,52 @@ */ #include -#include -#include #include -static inline void __cpuinit -detect_hypervisor_vendor(struct cpuinfo_x86 *c) +/* + * Hypervisor detect order. This is specified explicitly here because + * some hypervisors might implement compatibility modes for other + * hypervisors and therefore need to be detected in specific sequence. + */ +static const __initconst struct hypervisor_x86 * const hypervisors[] = { - if (vmware_platform()) - c->x86_hyper_vendor = X86_HYPER_VENDOR_VMWARE; - else if (ms_hyperv_platform()) - c->x86_hyper_vendor = X86_HYPER_VENDOR_MSFT; - else - c->x86_hyper_vendor = X86_HYPER_VENDOR_NONE; -} + &x86_hyper_vmware, + &x86_hyper_ms_hyperv, +}; -static inline void __cpuinit -hypervisor_set_feature_bits(struct cpuinfo_x86 *c) +const struct hypervisor_x86 *x86_hyper; + +static inline void __init +detect_hypervisor_vendor(void) { - if (boot_cpu_data.x86_hyper_vendor == X86_HYPER_VENDOR_VMWARE) - vmware_set_feature_bits(c); - else if (boot_cpu_data.x86_hyper_vendor == X86_HYPER_VENDOR_MSFT) - ms_hyperv_set_feature_bits(c); - return; + const struct hypervisor_x86 *h, * const *p; + + for (p = hypervisors; p < hypervisors + ARRAY_SIZE(hypervisors); p++) { + h = *p; + if (h->detect()) { + x86_hyper = h; + printk(KERN_INFO "Hypervisor detected: %s\n", h->name); + break; + } + } } void __cpuinit init_hypervisor(struct cpuinfo_x86 *c) { - detect_hypervisor_vendor(c); - hypervisor_set_feature_bits(c); + if (x86_hyper && x86_hyper->set_cpu_features) + x86_hyper->set_cpu_features(c); } void __init init_hypervisor_platform(void) { + + detect_hypervisor_vendor(); + + if (!x86_hyper) + return; + init_hypervisor(&boot_cpu_data); - if (boot_cpu_data.x86_hyper_vendor == X86_HYPER_VENDOR_VMWARE) - vmware_platform_setup(); + + if (x86_hyper->init_platform) + x86_hyper->init_platform(); } diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index a58d8e6..5969c3e 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -12,45 +12,42 @@ #include #include +#include #include #include +struct ms_hyperv_info ms_hyperv; -int ms_hyperv_platform(void) +static bool __init ms_hyperv_platform(void) { - u32 eax, ebx, ecx, edx; - char hyp_signature[13]; + u32 eax; + u32 hyp_signature[3]; - cpuid(1, &eax, &ebx, &ecx, &edx); - if (!(ecx & HYPERV_HYPERVISOR_PRESENT_BIT)) - return 0; + if (!boot_cpu_has(X86_FEATURE_HYPERVISOR)) + return false; - cpuid(HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS, &eax, &ebx, &ecx, &edx); - *(u32 *)(hyp_signature + 0) = ebx; - *(u32 *)(hyp_signature + 4) = ecx; - *(u32 *)(hyp_signature + 8) = edx; + cpuid(HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS, + &eax, &hyp_signature[0], &hyp_signature[1], &hyp_signature[2]); - if ((eax < HYPERV_CPUID_MIN) || (memcmp("Microsoft Hv", hyp_signature, 12))) - return 0; - return 1; + return eax >= HYPERV_CPUID_MIN && + eax <= HYPERV_CPUID_MAX && + !memcmp("Microsoft Hv", hyp_signature, 12); } -void __cpuinit ms_hyperv_set_feature_bits(struct cpuinfo_x86 *c) +static void __init ms_hyperv_init_platform(void) { - u32 eax, ebx, ecx, edx; - - c->x86_hyper_features = 0; /* - * Extract the features, recommendations etc. - * The first 9 bits will be used to track hypervisor features. - * The next 6 bits will be used to track the hypervisor - * recommendations. + * Extract the features and hints */ - cpuid(HYPERV_CPUID_FEATURES, &eax, &ebx, &ecx, &edx); - c->x86_hyper_features |= (eax & 0x1ff); + ms_hyperv.features = cpuid_eax(HYPERV_CPUID_FEATURES); + ms_hyperv.hints = cpuid_eax(HYPERV_CPUID_ENLIGHTMENT_INFO); - cpuid(HYPERV_CPUID_ENLIGHTMENT_INFO, &eax, &ebx, &ecx, &edx); - c->x86_hyper_features |= ((eax & 0x3f) << 9); - printk(KERN_INFO "Detected HyperV with features: %x\n", - c->x86_hyper_features); + printk(KERN_INFO "HyperV: features 0x%x, hints 0x%x\n", + ms_hyperv.features, ms_hyperv.hints); } + +const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = { + .name = "Microsoft HyperV", + .detect = ms_hyperv_platform, + .init_platform = ms_hyperv_init_platform, +}; diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c index 1cbed97..46a5b5d 100644 --- a/arch/x86/kernel/cpu/vmware.c +++ b/arch/x86/kernel/cpu/vmware.c @@ -23,8 +23,8 @@ #include #include -#include #include +#include #define CPUID_VMWARE_INFO_LEAF 0x40000000 #define VMWARE_HYPERVISOR_MAGIC 0x564D5868 @@ -64,7 +64,7 @@ static unsigned long vmware_get_tsc_khz(void) return tsc_hz; } -void __init vmware_platform_setup(void) +static void __init vmware_platform_setup(void) { uint32_t eax, ebx, ecx, edx; @@ -82,24 +82,21 @@ void __init vmware_platform_setup(void) * serial key should be enough, as this will always have a VMware * specific string when running under VMware hypervisor. */ -int vmware_platform(void) +static bool __init vmware_platform(void) { if (cpu_has_hypervisor) { - unsigned int eax, ebx, ecx, edx; - char hyper_vendor_id[13]; - - cpuid(CPUID_VMWARE_INFO_LEAF, &eax, &ebx, &ecx, &edx); - memcpy(hyper_vendor_id + 0, &ebx, 4); - memcpy(hyper_vendor_id + 4, &ecx, 4); - memcpy(hyper_vendor_id + 8, &edx, 4); - hyper_vendor_id[12] = '\0'; - if (!strcmp(hyper_vendor_id, "VMwareVMware")) - return 1; + unsigned int eax; + unsigned int hyper_vendor_id[3]; + + cpuid(CPUID_VMWARE_INFO_LEAF, &eax, &hyper_vendor_id[0], + &hyper_vendor_id[1], &hyper_vendor_id[2]); + if (!memcmp(hyper_vendor_id, "VMwareVMware", 12)) + return true; } else if (dmi_available && dmi_name_in_serial("VMware") && __vmware_platform()) - return 1; + return true; - return 0; + return false; } /* @@ -114,8 +111,15 @@ int vmware_platform(void) * so that the kernel could just trust the hypervisor with providing a * reliable virtual TSC that is suitable for timekeeping. */ -void __cpuinit vmware_set_feature_bits(struct cpuinfo_x86 *c) +static void __cpuinit vmware_set_cpu_features(struct cpuinfo_x86 *c) { set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); set_cpu_cap(c, X86_FEATURE_TSC_RELIABLE); } + +const __refconst struct hypervisor_x86 x86_hyper_vmware = { + .name = "VMware", + .detect = vmware_platform, + .set_cpu_features = vmware_set_cpu_features, + .init_platform = vmware_platform_setup, +}; -- cgit v0.10.2 From b1a9ceb2e003aab7b96e30d990c1092453a0ea44 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Thu, 6 May 2010 15:14:09 +0100 Subject: ARM: 6105/1: Fix the __arm_ioremap_caller() definition in nommu.c Commit 31aa8fd6 introduced the __arm_ioremap_caller() function but the nommu.c version did not have the _caller suffix. Signed-off-by: Catalin Marinas Signed-off-by: Russell King diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c index 9bfeb6b..f8791ee 100644 --- a/arch/arm/mm/nommu.c +++ b/arch/arm/mm/nommu.c @@ -87,8 +87,8 @@ void __iomem *__arm_ioremap(unsigned long phys_addr, size_t size, } EXPORT_SYMBOL(__arm_ioremap); -void __iomem *__arm_ioremap(unsigned long phys_addr, size_t size, - unsigned int mtype, void *caller) +void __iomem *__arm_ioremap_caller(unsigned long phys_addr, size_t size, + unsigned int mtype, void *caller) { return __arm_ioremap(phys_addr, size, mtype); } -- cgit v0.10.2 From b5a07faadeb4e0cfd6dcee359e501d4755cab875 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Thu, 6 May 2010 15:15:28 +0100 Subject: ARM: 6106/1: Implement copy_to_user_page() for noMMU Commit 7959722 introduced calls to copy_(to|from)_user_page() from access_process_vm() in mm/nommu.c. The copy_to_user_page() was not implemented on noMMU ARM. Signed-off-by: Catalin Marinas Signed-off-by: Russell King diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c index f8791ee..33b3273 100644 --- a/arch/arm/mm/nommu.c +++ b/arch/arm/mm/nommu.c @@ -65,6 +65,15 @@ void flush_dcache_page(struct page *page) } EXPORT_SYMBOL(flush_dcache_page); +void copy_to_user_page(struct vm_area_struct *vma, struct page *page, + unsigned long uaddr, void *dst, const void *src, + unsigned long len) +{ + memcpy(dst, src, len); + if (vma->vm_flags & VM_EXEC) + __cpuc_coherent_user_range(uaddr, uaddr + len); +} + void __iomem *__arm_ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size, unsigned int mtype) { -- cgit v0.10.2 From f4d6477f7f073b99220386d62f5bf54bec3482cc Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Fri, 7 May 2010 16:26:24 +0100 Subject: ARM: 6111/1: Implement read/write for ownership in the ARMv6 DMA cache ops The Snoop Control Unit on the ARM11MPCore hardware does not detect the cache operations and the dma_cache_maint*() functions may leave stale cache entries on other CPUs. The solution implemented in this patch performs a Read or Write For Ownership in the ARMv6 DMA cache maintenance functions. These LDR/STR instructions change the cache line state to shared or exclusive so that the cache maintenance operation has the desired effect. Tested-by: George G. Davis Signed-off-by: Catalin Marinas Signed-off-by: Russell King diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S index 9d89c67..e46ecd8 100644 --- a/arch/arm/mm/cache-v6.S +++ b/arch/arm/mm/cache-v6.S @@ -211,6 +211,9 @@ v6_dma_inv_range: mcrne p15, 0, r1, c7, c15, 1 @ clean & invalidate unified line #endif 1: +#ifdef CONFIG_SMP + str r0, [r0] @ write for ownership +#endif #ifdef HARVARD_CACHE mcr p15, 0, r0, c7, c6, 1 @ invalidate D line #else @@ -231,6 +234,9 @@ v6_dma_inv_range: v6_dma_clean_range: bic r0, r0, #D_CACHE_LINE_SIZE - 1 1: +#ifdef CONFIG_SMP + ldr r2, [r0] @ read for ownership +#endif #ifdef HARVARD_CACHE mcr p15, 0, r0, c7, c10, 1 @ clean D line #else @@ -251,6 +257,10 @@ v6_dma_clean_range: ENTRY(v6_dma_flush_range) bic r0, r0, #D_CACHE_LINE_SIZE - 1 1: +#ifdef CONFIG_SMP + ldr r2, [r0] @ read for ownership + str r2, [r0] @ write for ownership +#endif #ifdef HARVARD_CACHE mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D line #else @@ -273,7 +283,9 @@ ENTRY(v6_dma_map_area) add r1, r1, r0 teq r2, #DMA_FROM_DEVICE beq v6_dma_inv_range - b v6_dma_clean_range + teq r2, #DMA_TO_DEVICE + beq v6_dma_clean_range + b v6_dma_flush_range ENDPROC(v6_dma_map_area) /* @@ -283,9 +295,6 @@ ENDPROC(v6_dma_map_area) * - dir - DMA direction */ ENTRY(v6_dma_unmap_area) - add r1, r1, r0 - teq r2, #DMA_TO_DEVICE - bne v6_dma_inv_range mov pc, lr ENDPROC(v6_dma_unmap_area) -- cgit v0.10.2 From b8349b569aae661dea9d59d7d2ee587ccea3336c Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Fri, 7 May 2010 18:03:05 +0100 Subject: ARM: 6112/1: Use the Inner Shareable I-cache and BTB ops on ARMv7 SMP The standard I-cache Invalidate All (ICIALLU) and Branch Predication Invalidate All (BPIALL) operations are not automatically broadcast to the other CPUs in an ARMv7 MP system. The patch adds the Inner Shareable variants, ICIALLUIS and BPIALLIS, if ARMv7 and SMP. Signed-off-by: Catalin Marinas Signed-off-by: Russell King diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index 0d08d41..4656a24 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -371,6 +371,10 @@ static inline void __flush_icache_all(void) #ifdef CONFIG_ARM_ERRATA_411920 extern void v6_icache_inval_all(void); v6_icache_inval_all(); +#elif defined(CONFIG_SMP) && __LINUX_ARM_ARCH__ >= 7 + asm("mcr p15, 0, %0, c7, c1, 0 @ invalidate I-cache inner shareable\n" + : + : "r" (0)); #else asm("mcr p15, 0, %0, c7, c5, 0 @ invalidate I-cache\n" : diff --git a/arch/arm/include/asm/tlbflush.h b/arch/arm/include/asm/tlbflush.h index e085e2c..bd863d8 100644 --- a/arch/arm/include/asm/tlbflush.h +++ b/arch/arm/include/asm/tlbflush.h @@ -46,6 +46,9 @@ #define TLB_V7_UIS_FULL (1 << 20) #define TLB_V7_UIS_ASID (1 << 21) +/* Inner Shareable BTB operation (ARMv7 MP extensions) */ +#define TLB_V7_IS_BTB (1 << 22) + #define TLB_L2CLEAN_FR (1 << 29) /* Feroceon */ #define TLB_DCLEAN (1 << 30) #define TLB_WB (1 << 31) @@ -183,7 +186,7 @@ #endif #ifdef CONFIG_SMP -#define v7wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_BTB | \ +#define v7wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_V7_IS_BTB | \ TLB_V7_UIS_FULL | TLB_V7_UIS_PAGE | TLB_V7_UIS_ASID) #else #define v7wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_BTB | \ @@ -339,6 +342,12 @@ static inline void local_flush_tlb_all(void) dsb(); isb(); } + if (tlb_flag(TLB_V7_IS_BTB)) { + /* flush the branch target cache */ + asm("mcr p15, 0, %0, c7, c1, 6" : : "r" (zero) : "cc"); + dsb(); + isb(); + } } static inline void local_flush_tlb_mm(struct mm_struct *mm) @@ -376,6 +385,12 @@ static inline void local_flush_tlb_mm(struct mm_struct *mm) asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc"); dsb(); } + if (tlb_flag(TLB_V7_IS_BTB)) { + /* flush the branch target cache */ + asm("mcr p15, 0, %0, c7, c1, 6" : : "r" (zero) : "cc"); + dsb(); + isb(); + } } static inline void @@ -416,6 +431,12 @@ local_flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr) asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc"); dsb(); } + if (tlb_flag(TLB_V7_IS_BTB)) { + /* flush the branch target cache */ + asm("mcr p15, 0, %0, c7, c1, 6" : : "r" (zero) : "cc"); + dsb(); + isb(); + } } static inline void local_flush_tlb_kernel_page(unsigned long kaddr) @@ -454,6 +475,12 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr) dsb(); isb(); } + if (tlb_flag(TLB_V7_IS_BTB)) { + /* flush the branch target cache */ + asm("mcr p15, 0, %0, c7, c1, 6" : : "r" (zero) : "cc"); + dsb(); + isb(); + } } /* diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S index bcd64f2..06a90dc 100644 --- a/arch/arm/mm/cache-v7.S +++ b/arch/arm/mm/cache-v7.S @@ -167,7 +167,11 @@ ENTRY(v7_coherent_user_range) cmp r0, r1 blo 1b mov r0, #0 +#ifdef CONFIG_SMP + mcr p15, 0, r0, c7, c1, 6 @ invalidate BTB Inner Shareable +#else mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB +#endif dsb isb mov pc, lr diff --git a/arch/arm/mm/tlb-v7.S b/arch/arm/mm/tlb-v7.S index 0cb1848..f3f288a 100644 --- a/arch/arm/mm/tlb-v7.S +++ b/arch/arm/mm/tlb-v7.S @@ -50,7 +50,11 @@ ENTRY(v7wbi_flush_user_tlb_range) cmp r0, r1 blo 1b mov ip, #0 +#ifdef CONFIG_SMP + mcr p15, 0, ip, c7, c1, 6 @ flush BTAC/BTB Inner Shareable +#else mcr p15, 0, ip, c7, c5, 6 @ flush BTAC/BTB +#endif dsb mov pc, lr ENDPROC(v7wbi_flush_user_tlb_range) @@ -79,7 +83,11 @@ ENTRY(v7wbi_flush_kern_tlb_range) cmp r0, r1 blo 1b mov r2, #0 +#ifdef CONFIG_SMP + mcr p15, 0, r2, c7, c1, 6 @ flush BTAC/BTB Inner Shareable +#else mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB +#endif dsb isb mov pc, lr -- cgit v0.10.2 From e814d826dc1821dbce3aa1ddb7f2f739f420ffd8 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Fri, 7 May 2010 10:52:32 +0100 Subject: ARM: 6110/1: Fix Thumb-2 kernel builds when UACCESS_WITH_MEMCPY is enabled The patch adds the ENDPROC declarations for the __copy_to_user_std and __clear_user_std functions. Without these, the compiler generates BXL to ARM when compiling the kernel in Thumb-2 mode. Reported-by: Kyungmin Park Tested-by: Kyungmin Park Signed-off-by: Catalin Marinas Acked-by: Nicolas Pitre Signed-off-by: Russell King diff --git a/arch/arm/lib/clear_user.S b/arch/arm/lib/clear_user.S index 5e3f996..14a0d98 100644 --- a/arch/arm/lib/clear_user.S +++ b/arch/arm/lib/clear_user.S @@ -45,6 +45,7 @@ USER( strnebt r2, [r0]) mov r0, #0 ldmfd sp!, {r1, pc} ENDPROC(__clear_user) +ENDPROC(__clear_user_std) .pushsection .fixup,"ax" .align 0 diff --git a/arch/arm/lib/copy_to_user.S b/arch/arm/lib/copy_to_user.S index 027b69b..d066df6 100644 --- a/arch/arm/lib/copy_to_user.S +++ b/arch/arm/lib/copy_to_user.S @@ -93,6 +93,7 @@ WEAK(__copy_to_user) #include "copy_template.S" ENDPROC(__copy_to_user) +ENDPROC(__copy_to_user_std) .pushsection .fixup,"ax" .align 0 -- cgit v0.10.2 From 6e85158cf5a2385264316870256fb6ad681156a0 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Sat, 8 May 2010 20:58:00 +1000 Subject: perf_event: Make software events work again Commit 6bde9b6ce0127e2a56228a2071536d422be31336 ("perf: Add group scheduling transactional APIs") added code to allow a group to be scheduled in a single transaction. However, it introduced a bug in handling events whose pmu does not implement transactions -- at the end of scheduling in the events in the group, in the non-transactional case the code now falls through to the group_error label, and proceeds to unschedule all the events in the group and return failure. This fixes it by returning 0 (success) in the non-transactional case. Signed-off-by: Paul Mackerras Cc: Peter Zijlstra Cc: Lin Ming Cc: Frederic Weisbecker Cc: eranian@gmail.com LKML-Reference: <20100508105800.GB10650@brick.ozlabs.ibm.com> Signed-off-by: Ingo Molnar diff --git a/kernel/perf_event.c b/kernel/perf_event.c index bb06382..180151f 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -664,13 +664,13 @@ group_sched_in(struct perf_event *group_event, } } - if (txn) { - ret = pmu->commit_txn(pmu); - if (!ret) { - pmu->cancel_txn(pmu); + if (!txn) + return 0; - return 0; - } + ret = pmu->commit_txn(pmu); + if (!ret) { + pmu->cancel_txn(pmu); + return 0; } group_error: -- cgit v0.10.2 From de902d967feb96f2dfddfbe9dbd69dc22fd5ebcb Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sat, 8 May 2010 15:39:52 +0400 Subject: x86, perf: P4 PMU -- configure predefined events If an event is not RAW we should not exit p4_hw_config early but call x86_setup_perfctr as well. Signed-off-by: Cyrill Gorcunov Cc: Peter Zijlstra Cc: Frederic Weisbecker Cc: Lin Ming Cc: Robert Richter Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index 9e00205..b1f532d 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c @@ -439,21 +439,20 @@ static int p4_hw_config(struct perf_event *event) if (p4_ht_active() && p4_ht_thread(cpu)) event->hw.config = p4_set_ht_bit(event->hw.config); - if (event->attr.type != PERF_TYPE_RAW) - return 0; - - /* - * We don't control raw events so it's up to the caller - * to pass sane values (and we don't count the thread number - * on HT machine but allow HT-compatible specifics to be - * passed on) - * - * XXX: HT wide things should check perf_paranoid_cpu() && - * CAP_SYS_ADMIN - */ - event->hw.config |= event->attr.config & - (p4_config_pack_escr(P4_ESCR_MASK_HT) | - p4_config_pack_cccr(P4_CCCR_MASK_HT)); + if (event->attr.type == PERF_TYPE_RAW) { + /* + * We don't control raw events so it's up to the caller + * to pass sane values (and we don't count the thread number + * on HT machine but allow HT-compatible specifics to be + * passed on) + * + * XXX: HT wide things should check perf_paranoid_cpu() && + * CAP_SYS_ADMIN + */ + event->hw.config |= event->attr.config & + (p4_config_pack_escr(P4_ESCR_MASK_HT) | + p4_config_pack_cccr(P4_CCCR_MASK_HT)); + } return x86_setup_perfctr(event); } -- cgit v0.10.2 From 137351e0feeb9f25d99488ee1afc1c79f5499a9a Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sat, 8 May 2010 15:25:52 +0400 Subject: x86, perf: P4 PMU -- protect sensible procedures from preemption Steven reported: | | I'm getting: | | Pid: 3477, comm: perf Not tainted 2.6.34-rc6 #2727 | Call Trace: | [] debug_smp_processor_id+0xd5/0xf0 | [] p4_hw_config+0x2b/0x15c | [] ? trace_hardirqs_on_caller+0x12b/0x14f | [] hw_perf_event_init+0x468/0x7be | [] ? debug_mutex_init+0x31/0x3c | [] T.850+0x273/0x42e | [] sys_perf_event_open+0x23e/0x3f1 | [] ? sysret_check+0x2e/0x69 | [] system_call_fastpath+0x16/0x1b | | When running perf record in latest tip/perf/core | Due to the fact that p4 counters are shared between HT threads we synthetically divide the whole set of counters into two non-intersected subsets. And while we're "borrowing" counters from these subsets we should not be preempted (well, strictly speaking in p4_hw_config we just pre-set reference to the subset which allow to save some cycles in schedule routine if it happens on the same cpu). So use get_cpu/put_cpu pair. Also p4_pmu_schedule_events should use smp_processor_id rather than raw_ version. This allow us to catch up preemption issue (if there will ever be). Reported-by: Steven Rostedt Tested-by: Steven Rostedt Signed-off-by: Cyrill Gorcunov Cc: Steven Rostedt Cc: Peter Zijlstra Cc: Frederic Weisbecker Cc: Lin Ming LKML-Reference: <20100508112716.963478928@openvz.org> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index b1f532d..ca40180 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c @@ -421,7 +421,8 @@ static u64 p4_pmu_event_map(int hw_event) static int p4_hw_config(struct perf_event *event) { - int cpu = raw_smp_processor_id(); + int cpu = get_cpu(); + int rc = 0; u32 escr, cccr; /* @@ -454,7 +455,10 @@ static int p4_hw_config(struct perf_event *event) p4_config_pack_cccr(P4_CCCR_MASK_HT)); } - return x86_setup_perfctr(event); + rc = x86_setup_perfctr(event); + put_cpu(); + + return rc; } static inline void p4_pmu_clear_cccr_ovf(struct hw_perf_event *hwc) -- cgit v0.10.2 From 3f51b7119d052827dbb0e40c966acdf2bdc6f47f Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sat, 8 May 2010 15:25:53 +0400 Subject: x86, perf: P4 PMU -- Get rid of redundant check for array index The caller already has done such a check. And it was wrong anyway, it had to be '>=' rather than '>' Signed-off-by: Cyrill Gorcunov Cc: Peter Zijlstra Cc: Frederic Weisbecker Cc: Lin Ming LKML-Reference: <20100508112717.130386882@openvz.org> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index ca40180..b8c2d37 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c @@ -406,11 +406,6 @@ static u64 p4_pmu_event_map(int hw_event) unsigned int esel; u64 config; - if (hw_event > ARRAY_SIZE(p4_general_events)) { - printk_once(KERN_ERR "P4 PMU: Bad index: %i\n", hw_event); - return 0; - } - config = p4_general_events[hw_event]; bind = p4_config_get_bind(config); esel = P4_OPCODE_ESEL(bind->opcode); -- cgit v0.10.2 From c7993165ef0c1d636ca05f4787739f8414584e6d Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sat, 8 May 2010 15:25:54 +0400 Subject: x86, perf: P4 PMU -- check for proper event index in RAW events RAW events are special and we should be ready for user passing in insane event index values. Signed-off-by: Cyrill Gorcunov Cc: Peter Zijlstra Cc: Frederic Weisbecker Cc: Lin Ming LKML-Reference: <20100508112717.315897547@openvz.org> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index b8c2d37..a603930 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c @@ -418,6 +418,7 @@ static int p4_hw_config(struct perf_event *event) { int cpu = get_cpu(); int rc = 0; + unsigned int evnt; u32 escr, cccr; /* @@ -436,6 +437,14 @@ static int p4_hw_config(struct perf_event *event) event->hw.config = p4_set_ht_bit(event->hw.config); if (event->attr.type == PERF_TYPE_RAW) { + + /* user data may have out-of-bound event index */ + evnt = p4_config_unpack_event(event->attr.config); + if (evnt >= ARRAY_SIZE(p4_event_bind_map)) { + rc = -EINVAL; + goto out; + } + /* * We don't control raw events so it's up to the caller * to pass sane values (and we don't count the thread number @@ -451,8 +460,8 @@ static int p4_hw_config(struct perf_event *event) } rc = x86_setup_perfctr(event); +out: put_cpu(); - return rc; } -- cgit v0.10.2 From bbf1bb3eee86f2eef2baa14e600be454d09109ee Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sat, 8 May 2010 16:20:53 +0200 Subject: cpu_stop: add dummy implementation for UP When !CONFIG_SMP, cpu_stop functions weren't defined at all which could lead to build failures if UP code uses cpu_stop facility. Add dummy cpu_stop implementation for UP. The waiting variants execute the work function directly with preempt disabled and stop_one_cpu_nowait() schedules a workqueue work. Makefile and ifdefs around stop_machine implementation are updated to accomodate CONFIG_SMP && !CONFIG_STOP_MACHINE case. Signed-off-by: Tejun Heo Reported-by: Ingo Molnar diff --git a/include/linux/stop_machine.h b/include/linux/stop_machine.h index 0e552e7..6b524a0 100644 --- a/include/linux/stop_machine.h +++ b/include/linux/stop_machine.h @@ -6,8 +6,6 @@ #include #include -#if defined(CONFIG_STOP_MACHINE) && defined(CONFIG_SMP) - /* * stop_cpu[s]() is simplistic per-cpu maximum priority cpu * monopolization mechanism. The caller can specify a non-sleeping @@ -18,9 +16,10 @@ * up and requests are guaranteed to be served as long as the target * cpus are online. */ - typedef int (*cpu_stop_fn_t)(void *arg); +#ifdef CONFIG_SMP + struct cpu_stop_work { struct list_head list; /* cpu_stopper->works */ cpu_stop_fn_t fn; @@ -34,12 +33,70 @@ void stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg, int stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg); int try_stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg); +#else /* CONFIG_SMP */ + +#include + +struct cpu_stop_work { + struct work_struct work; + cpu_stop_fn_t fn; + void *arg; +}; + +static inline int stop_one_cpu(unsigned int cpu, cpu_stop_fn_t fn, void *arg) +{ + int ret = -ENOENT; + preempt_disable(); + if (cpu == smp_processor_id()) + ret = fn(arg); + preempt_enable(); + return ret; +} + +static void stop_one_cpu_nowait_workfn(struct work_struct *work) +{ + struct cpu_stop_work *stwork = + container_of(work, struct cpu_stop_work, work); + preempt_disable(); + stwork->fn(stwork->arg); + preempt_enable(); +} + +static inline void stop_one_cpu_nowait(unsigned int cpu, + cpu_stop_fn_t fn, void *arg, + struct cpu_stop_work *work_buf) +{ + if (cpu == smp_processor_id()) { + INIT_WORK(&work_buf->work, stop_one_cpu_nowait_workfn); + work_buf->fn = fn; + work_buf->arg = arg; + schedule_work(&work_buf->work); + } +} + +static inline int stop_cpus(const struct cpumask *cpumask, + cpu_stop_fn_t fn, void *arg) +{ + if (cpumask_test_cpu(raw_smp_processor_id(), cpumask)) + return stop_one_cpu(raw_smp_processor_id(), fn, arg); + return -ENOENT; +} + +static inline int try_stop_cpus(const struct cpumask *cpumask, + cpu_stop_fn_t fn, void *arg) +{ + return stop_cpus(cpumask, fn, arg); +} + +#endif /* CONFIG_SMP */ + /* * stop_machine "Bogolock": stop the entire machine, disable * interrupts. This is a very heavy lock, which is equivalent to * grabbing every spinlock (and more). So the "read" side to such a * lock is anything which disables preeempt. */ +#if defined(CONFIG_STOP_MACHINE) && defined(CONFIG_SMP) /** * stop_machine: freeze the machine on all CPUs and run this function @@ -67,7 +124,7 @@ int stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus); */ int __stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus); -#else +#else /* CONFIG_STOP_MACHINE && CONFIG_SMP */ static inline int stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus) @@ -79,5 +136,5 @@ static inline int stop_machine(int (*fn)(void *), void *data, return ret; } -#endif /* CONFIG_SMP */ -#endif /* _LINUX_STOP_MACHINE */ +#endif /* CONFIG_STOP_MACHINE && CONFIG_SMP */ +#endif /* _LINUX_STOP_MACHINE */ diff --git a/kernel/Makefile b/kernel/Makefile index a987aa1..149e18e 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -68,7 +68,7 @@ obj-$(CONFIG_USER_NS) += user_namespace.o obj-$(CONFIG_PID_NS) += pid_namespace.o obj-$(CONFIG_IKCONFIG) += configs.o obj-$(CONFIG_RESOURCE_COUNTERS) += res_counter.o -obj-$(CONFIG_STOP_MACHINE) += stop_machine.o +obj-$(CONFIG_SMP) += stop_machine.o obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o obj-$(CONFIG_AUDIT) += audit.o auditfilter.o audit_watch.o obj-$(CONFIG_AUDITSYSCALL) += auditsc.o diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c index 5b20141..ef51d1f 100644 --- a/kernel/stop_machine.c +++ b/kernel/stop_machine.c @@ -375,6 +375,8 @@ static int __init cpu_stop_init(void) } early_initcall(cpu_stop_init); +#ifdef CONFIG_STOP_MACHINE + /* This controls the threads on each CPU. */ enum stopmachine_state { /* Dummy starting state for thread. */ @@ -477,3 +479,5 @@ int stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus) return ret; } EXPORT_SYMBOL_GPL(stop_machine); + +#endif /* CONFIG_STOP_MACHINE */ -- cgit v0.10.2 From c0614829c16ab9d31f1b7d40516decfbf3d32102 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Tue, 27 Apr 2010 18:33:12 -0400 Subject: kprobes: Move enable/disable_kprobe() out from debugfs code Move enable/disable_kprobe() API out from debugfs related code, because these interfaces are not related to debugfs interface. This fixes a compiler warning. Signed-off-by: Masami Hiramatsu Acked-by: Ananth N Mavinakayanahalli Acked-by: Tony Luck Cc: systemtap Cc: DLE LKML-Reference: <20100427223312.2322.60512.stgit@localhost6.localdomain6> Signed-off-by: Ingo Molnar diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 0ed46f3..282035f 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -1588,6 +1588,72 @@ static void __kprobes kill_kprobe(struct kprobe *p) arch_remove_kprobe(p); } +/* Disable one kprobe */ +int __kprobes disable_kprobe(struct kprobe *kp) +{ + int ret = 0; + struct kprobe *p; + + mutex_lock(&kprobe_mutex); + + /* Check whether specified probe is valid. */ + p = __get_valid_kprobe(kp); + if (unlikely(p == NULL)) { + ret = -EINVAL; + goto out; + } + + /* If the probe is already disabled (or gone), just return */ + if (kprobe_disabled(kp)) + goto out; + + kp->flags |= KPROBE_FLAG_DISABLED; + if (p != kp) + /* When kp != p, p is always enabled. */ + try_to_disable_aggr_kprobe(p); + + if (!kprobes_all_disarmed && kprobe_disabled(p)) + disarm_kprobe(p); +out: + mutex_unlock(&kprobe_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(disable_kprobe); + +/* Enable one kprobe */ +int __kprobes enable_kprobe(struct kprobe *kp) +{ + int ret = 0; + struct kprobe *p; + + mutex_lock(&kprobe_mutex); + + /* Check whether specified probe is valid. */ + p = __get_valid_kprobe(kp); + if (unlikely(p == NULL)) { + ret = -EINVAL; + goto out; + } + + if (kprobe_gone(kp)) { + /* This kprobe has gone, we couldn't enable it. */ + ret = -EINVAL; + goto out; + } + + if (p != kp) + kp->flags &= ~KPROBE_FLAG_DISABLED; + + if (!kprobes_all_disarmed && kprobe_disabled(p)) { + p->flags &= ~KPROBE_FLAG_DISABLED; + arm_kprobe(p); + } +out: + mutex_unlock(&kprobe_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(enable_kprobe); + void __kprobes dump_kprobe(struct kprobe *kp) { printk(KERN_WARNING "Dumping kprobe:\n"); @@ -1805,72 +1871,6 @@ static const struct file_operations debugfs_kprobes_operations = { .release = seq_release, }; -/* Disable one kprobe */ -int __kprobes disable_kprobe(struct kprobe *kp) -{ - int ret = 0; - struct kprobe *p; - - mutex_lock(&kprobe_mutex); - - /* Check whether specified probe is valid. */ - p = __get_valid_kprobe(kp); - if (unlikely(p == NULL)) { - ret = -EINVAL; - goto out; - } - - /* If the probe is already disabled (or gone), just return */ - if (kprobe_disabled(kp)) - goto out; - - kp->flags |= KPROBE_FLAG_DISABLED; - if (p != kp) - /* When kp != p, p is always enabled. */ - try_to_disable_aggr_kprobe(p); - - if (!kprobes_all_disarmed && kprobe_disabled(p)) - disarm_kprobe(p); -out: - mutex_unlock(&kprobe_mutex); - return ret; -} -EXPORT_SYMBOL_GPL(disable_kprobe); - -/* Enable one kprobe */ -int __kprobes enable_kprobe(struct kprobe *kp) -{ - int ret = 0; - struct kprobe *p; - - mutex_lock(&kprobe_mutex); - - /* Check whether specified probe is valid. */ - p = __get_valid_kprobe(kp); - if (unlikely(p == NULL)) { - ret = -EINVAL; - goto out; - } - - if (kprobe_gone(kp)) { - /* This kprobe has gone, we couldn't enable it. */ - ret = -EINVAL; - goto out; - } - - if (p != kp) - kp->flags &= ~KPROBE_FLAG_DISABLED; - - if (!kprobes_all_disarmed && kprobe_disabled(p)) { - p->flags &= ~KPROBE_FLAG_DISABLED; - arm_kprobe(p); - } -out: - mutex_unlock(&kprobe_mutex); - return ret; -} -EXPORT_SYMBOL_GPL(enable_kprobe); - static void __kprobes arm_all_kprobes(void) { struct hlist_head *head; -- cgit v0.10.2 From e157eb8341e7885ff2d9f1620155e3da6e0c8f56 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Sat, 8 May 2010 18:33:03 +0300 Subject: perf report: Document '--call-graph' better for usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch improves 'perf report -h' output for the '--call-graph' command line option by enumerating the different output types. Signed-off-by: Pekka Enberg Cc: Arnaldo Carvalho de Melo Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra LKML-Reference: <1273332783-4268-1-git-send-email-penberg@cs.helsinki.fi> Signed-off-by: Ingo Molnar diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 0152b54..196473b 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -457,7 +457,7 @@ static const struct option options[] = { OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other, "Only display entries with parent-match"), OPT_CALLBACK_DEFAULT('g', "call-graph", NULL, "output_type,min_percent", - "Display callchains using output_type and min percent threshold. " + "Display callchains using output_type (graph, flat, fractal, or none) and min percent threshold. " "Default: fractal,0.5", &parse_callchain_opt, callchain_default_opt), OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]", "only consider symbols in these dsos"), -- cgit v0.10.2 From 96f6e775b58687d85ee33004d414419b5ec34106 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Sun, 9 May 2010 01:10:34 -0700 Subject: x86, hypervisor: Export the x86_hyper* symbols Export x86_hyper and the related specific structures, allowing for hypervisor identification by modules. Signed-off-by: H. Peter Anvin Cc: Greg KH Cc: Hank Janssen Cc: Alok Kataria Cc: Ky Srinivasan Cc: Dmitry Torokhov LKML-Reference: <4BE49778.6060800@zytor.com> diff --git a/arch/x86/kernel/cpu/hypervisor.c b/arch/x86/kernel/cpu/hypervisor.c index 8738175..4afb5a2 100644 --- a/arch/x86/kernel/cpu/hypervisor.c +++ b/arch/x86/kernel/cpu/hypervisor.c @@ -36,6 +36,7 @@ static const __initconst struct hypervisor_x86 * const hypervisors[] = }; const struct hypervisor_x86 *x86_hyper; +EXPORT_SYMBOL(x86_hyper); static inline void __init detect_hypervisor_vendor(void) diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index 5969c3e..0f13717 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -51,3 +51,4 @@ const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = { .detect = ms_hyperv_platform, .init_platform = ms_hyperv_init_platform, }; +EXPORT_SYMBOL(x86_hyper_ms_hyperv); diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c index 265b432..b9d1ff5 100644 --- a/arch/x86/kernel/cpu/vmware.c +++ b/arch/x86/kernel/cpu/vmware.c @@ -99,7 +99,6 @@ static bool __init vmware_platform(void) return false; } -EXPORT_SYMBOL(vmware_platform); /* * VMware hypervisor takes care of exporting a reliable TSC to the guest. @@ -125,3 +124,4 @@ const __refconst struct hypervisor_x86 x86_hyper_vmware = { .set_cpu_features = vmware_set_cpu_features, .init_platform = vmware_platform_setup, }; +EXPORT_SYMBOL(x86_hyper_vmware); -- cgit v0.10.2 From a10a569806e43b9be5fce60b21f836b50b1010e4 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Sun, 9 May 2010 01:13:42 -0700 Subject: Modify the VMware balloon driver for the new x86_hyper API Modify the VMware balloon driver to match the new x86_hyper API. Signed-off-by: H. Peter Anvin Cc: Greg KH Cc: Hank Janssen Cc: Alok Kataria Cc: Ky Srinivasan Cc: Dmitry Torokhov LKML-Reference: <4BE49778.6060800@zytor.com> diff --git a/drivers/misc/vmware_balloon.c b/drivers/misc/vmware_balloon.c index e7161c4..db9cd02 100644 --- a/drivers/misc/vmware_balloon.c +++ b/drivers/misc/vmware_balloon.c @@ -41,7 +41,7 @@ #include #include #include -#include +#include MODULE_AUTHOR("VMware, Inc."); MODULE_DESCRIPTION("VMware Memory Control (Balloon) Driver"); @@ -767,7 +767,7 @@ static int __init vmballoon_init(void) * Check if we are running on VMware's hypervisor and bail out * if we are not. */ - if (!vmware_platform()) + if (x86_hyper != &x86_hyper_vmware) return -ENODEV; vmballoon_wq = create_freezeable_workqueue("vmmemctl"); -- cgit v0.10.2 From 984028075794c00cbf4fb1e94bb6233e8be08875 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Sun, 2 May 2010 22:05:29 +0200 Subject: perf: Introduce a new "round of buffers read" pseudo event In order to provide a more rubust and deterministic reordering algorithm, we need to know when we reach a point where we just did a pass through over every counter buffers to read every thing they had. This patch introduces a new PERF_RECORD_FINISHED_ROUND pseudo event that only consist in an event header and doesn't need to contain anything. Signed-off-by: Frederic Weisbecker Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Tom Zanussi Cc: Masami Hiramatsu diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index d3981ac..6b77b28 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -494,6 +494,29 @@ static void event__synthesize_guest_os(struct machine *machine, void *data) " relocation symbol.\n", machine->pid); } +static struct perf_event_header finished_round_event = { + .size = sizeof(struct perf_event_header), + .type = PERF_RECORD_FINISHED_ROUND, +}; + +static void mmap_read_all(void) +{ + int i, counter, thread; + + for (i = 0; i < nr_cpu; i++) { + for (counter = 0; counter < nr_counters; counter++) { + for (thread = 0; thread < thread_num; thread++) { + if (mmap_array[i][counter][thread].base) + mmap_read(&mmap_array[i][counter][thread]); + } + + } + } + + if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO)) + write_output(&finished_round_event, sizeof(finished_round_event)); +} + static int __cmd_record(int argc, const char **argv) { int i, counter; @@ -726,16 +749,7 @@ static int __cmd_record(int argc, const char **argv) int hits = samples; int thread; - for (i = 0; i < nr_cpu; i++) { - for (counter = 0; counter < nr_counters; counter++) { - for (thread = 0; - thread < thread_num; thread++) { - if (mmap_array[i][counter][thread].base) - mmap_read(&mmap_array[i][counter][thread]); - } - - } - } + mmap_read_all(); if (hits == samples) { if (done) diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index b364da5..6cc1b1d 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -84,11 +84,12 @@ struct build_id_event { char filename[]; }; -enum perf_header_event_type { /* above any possible kernel type */ +enum perf_user_event_type { /* above any possible kernel type */ PERF_RECORD_HEADER_ATTR = 64, PERF_RECORD_HEADER_EVENT_TYPE = 65, PERF_RECORD_HEADER_TRACING_DATA = 66, PERF_RECORD_HEADER_BUILD_ID = 67, + PERF_RECORD_FINISHED_ROUND = 68, PERF_RECORD_HEADER_MAX }; -- cgit v0.10.2 From d6b17bebd79dae2e3577f2ea27a832af4991a5e6 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Mon, 3 May 2010 15:14:33 +0200 Subject: perf: Provide a new deterministic events reordering algorithm The current events reordering algorithm is based on a heuristic that gets broken once we deal with a very fast flow of events. Indeed the time period based flushing is not suitable anymore in the following case, assuming we have a flush period of two seconds. CPU 0 | CPU 1 | cnt1 timestamps | cnt1 timestamps | 0 | 0 1 | 1 2 | 2 3 | 3 [...] | [...] 4 seconds later If we spend too much time to read the buffers (case of a lot of events to record in each buffers or when we have a lot of CPU buffers to read), in the next pass the CPU 0 buffer could contain a slice of several seconds of events. We'll read them all and notice we've reached the period to flush. In the above example we flush the first half of the CPU 0 buffer, then we read the CPU 1 buffer where we have events that were on the flush slice and then the reordering fails. It's simple to reproduce with: perf lock record perf bench sched messaging To solve this, we use a new solution that doesn't rely on an heuristical time slice period anymore but on a deterministic basis based on how perf record does its job. perf record saves the buffers through passes. A pass is a tour on every buffers from every CPUs. This is made in order: for each CPU we read the buffers of every counters. So the more buffers we visit, the later will be the timstamps of their events. When perf record finishes a pass it records a PERF_RECORD_FINISHED_ROUND pseudo event. We record the max timestamp t found in the pass n. Assuming these timestamps are monotonic across cpus, we know that if a buffer still has events with timestamps below t, they will be all available and then read in the pass n + 1. Hence when we start to read the pass n + 2, we can safely flush every events with timestamps below t. ============ PASS n ================= CPU 0 | CPU 1 | cnt1 timestamps | cnt2 timestamps 1 | 2 2 | 3 - | 4 <--- max recorded ============ PASS n + 1 ============== CPU 0 | CPU 1 | cnt1 timestamps | cnt2 timestamps 3 | 5 4 | 6 5 | 7 <---- max recorded Flush every events below timestamp 4 ============ PASS n + 2 ============== CPU 0 | CPU 1 | cnt1 timestamps | cnt2 timestamps 6 | 8 7 | 9 - | 10 Flush every events below timestamp 7 etc... It also works on perf.data versions that don't have PERF_RECORD_FINISHED_ROUND pseudo events. The difference is that the events will be only flushed in the end of the perf.data processing. It will then consume more memory and scale less with large perf.data files. Signed-off-by: Frederic Weisbecker Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Tom Zanussi Cc: Masami Hiramatsu diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 5d353e7..9401909 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -98,7 +98,6 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc self->unknown_events = 0; self->machines = RB_ROOT; self->repipe = repipe; - self->ordered_samples.flush_limit = ULLONG_MAX; INIT_LIST_HEAD(&self->ordered_samples.samples_head); if (mode == O_RDONLY) { @@ -194,6 +193,18 @@ static int process_event_stub(event_t *event __used, return 0; } +static int process_finished_round_stub(event_t *event __used, + struct perf_session *session __used, + struct perf_event_ops *ops __used) +{ + dump_printf(": unhandled!\n"); + return 0; +} + +static int process_finished_round(event_t *event, + struct perf_session *session, + struct perf_event_ops *ops); + static void perf_event_ops__fill_defaults(struct perf_event_ops *handler) { if (handler->sample == NULL) @@ -222,6 +233,12 @@ static void perf_event_ops__fill_defaults(struct perf_event_ops *handler) handler->tracing_data = process_event_stub; if (handler->build_id == NULL) handler->build_id = process_event_stub; + if (handler->finished_round == NULL) { + if (handler->ordered_samples) + handler->finished_round = process_finished_round; + else + handler->finished_round = process_finished_round_stub; + } } static const char *event__name[] = { @@ -359,16 +376,14 @@ struct sample_queue { struct list_head list; }; -#define FLUSH_PERIOD (2 * NSEC_PER_SEC) - static void flush_sample_queue(struct perf_session *s, struct perf_event_ops *ops) { struct list_head *head = &s->ordered_samples.samples_head; - u64 limit = s->ordered_samples.flush_limit; + u64 limit = s->ordered_samples.next_flush; struct sample_queue *tmp, *iter; - if (!ops->ordered_samples) + if (!ops->ordered_samples || !limit) return; list_for_each_entry_safe(iter, tmp, head, list) { @@ -387,6 +402,55 @@ static void flush_sample_queue(struct perf_session *s, } } +/* + * When perf record finishes a pass on every buffers, it records this pseudo + * event. + * We record the max timestamp t found in the pass n. + * Assuming these timestamps are monotonic across cpus, we know that if + * a buffer still has events with timestamps below t, they will be all + * available and then read in the pass n + 1. + * Hence when we start to read the pass n + 2, we can safely flush every + * events with timestamps below t. + * + * ============ PASS n ================= + * CPU 0 | CPU 1 + * | + * cnt1 timestamps | cnt2 timestamps + * 1 | 2 + * 2 | 3 + * - | 4 <--- max recorded + * + * ============ PASS n + 1 ============== + * CPU 0 | CPU 1 + * | + * cnt1 timestamps | cnt2 timestamps + * 3 | 5 + * 4 | 6 + * 5 | 7 <---- max recorded + * + * Flush every events below timestamp 4 + * + * ============ PASS n + 2 ============== + * CPU 0 | CPU 1 + * | + * cnt1 timestamps | cnt2 timestamps + * 6 | 8 + * 7 | 9 + * - | 10 + * + * Flush every events below timestamp 7 + * etc... + */ +static int process_finished_round(event_t *event __used, + struct perf_session *session, + struct perf_event_ops *ops) +{ + flush_sample_queue(session, ops); + session->ordered_samples.next_flush = session->ordered_samples.max_timestamp; + + return 0; +} + static void __queue_sample_end(struct sample_queue *new, struct list_head *head) { struct sample_queue *iter; @@ -455,16 +519,11 @@ static void __queue_sample_event(struct sample_queue *new, } static int queue_sample_event(event_t *event, struct sample_data *data, - struct perf_session *s, - struct perf_event_ops *ops) + struct perf_session *s) { u64 timestamp = data->time; struct sample_queue *new; - u64 flush_limit; - - if (s->ordered_samples.flush_limit == ULLONG_MAX) - s->ordered_samples.flush_limit = timestamp + FLUSH_PERIOD; if (timestamp < s->ordered_samples.last_flush) { printf("Warning: Timestamp below last timeslice flush\n"); @@ -488,23 +547,8 @@ static int queue_sample_event(event_t *event, struct sample_data *data, __queue_sample_event(new, s); s->ordered_samples.last_inserted = new; - /* - * We want to have a slice of events covering 2 * FLUSH_PERIOD - * If FLUSH_PERIOD is big enough, it ensures every events that occured - * in the first half of the timeslice have all been buffered and there - * are none remaining (we need that because of the weakly ordered - * event recording we have). Then once we reach the 2 * FLUSH_PERIOD - * timeslice, we flush the first half to be gentle with the memory - * (the second half can still get new events in the middle, so wait - * another period to flush it) - */ - flush_limit = s->ordered_samples.flush_limit; - - if (new->timestamp > flush_limit && - new->timestamp - flush_limit > FLUSH_PERIOD) { - s->ordered_samples.flush_limit += FLUSH_PERIOD; - flush_sample_queue(s, ops); - } + if (new->timestamp > s->ordered_samples.max_timestamp) + s->ordered_samples.max_timestamp = new->timestamp; return 0; } @@ -520,7 +564,7 @@ static int perf_session__process_sample(event_t *event, struct perf_session *s, bzero(&data, sizeof(struct sample_data)); event__parse_sample(event, s->sample_type, &data); - queue_sample_event(event, &data, s, ops); + queue_sample_event(event, &data, s); return 0; } @@ -572,6 +616,8 @@ static int perf_session__process_event(struct perf_session *self, return ops->tracing_data(event, self); case PERF_RECORD_HEADER_BUILD_ID: return ops->build_id(event, self); + case PERF_RECORD_FINISHED_ROUND: + return ops->finished_round(event, self, ops); default: self->unknown_events++; return -1; @@ -786,7 +832,7 @@ more: done: err = 0; /* do the final flush for ordered samples */ - self->ordered_samples.flush_limit = ULLONG_MAX; + self->ordered_samples.next_flush = ULLONG_MAX; flush_sample_queue(self, ops); out_err: ui_progress__delete(progress); diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index f2b2c6a..568fd08 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -14,7 +14,8 @@ struct thread; struct ordered_samples { u64 last_flush; - u64 flush_limit; + u64 next_flush; + u64 max_timestamp; struct list_head samples_head; struct sample_queue *last_inserted; }; @@ -41,23 +42,28 @@ struct perf_session { char filename[0]; }; +struct perf_event_ops; + typedef int (*event_op)(event_t *self, struct perf_session *session); +typedef int (*event_op2)(event_t *self, struct perf_session *session, + struct perf_event_ops *ops); struct perf_event_ops { - event_op sample, - mmap, - comm, - fork, - exit, - lost, - read, - throttle, - unthrottle, - attr, - event_type, - tracing_data, - build_id; - bool ordered_samples; + event_op sample, + mmap, + comm, + fork, + exit, + lost, + read, + throttle, + unthrottle, + attr, + event_type, + tracing_data, + build_id; + event_op2 finished_round; + bool ordered_samples; }; struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe); -- cgit v0.10.2 From 26242d859c9be9eea61f7f19514e9d272ae8ce26 Mon Sep 17 00:00:00 2001 From: Hitoshi Mitake Date: Mon, 3 May 2010 14:12:00 +0900 Subject: perf lock: Add "info" subcommand for dumping misc information This adds the "info" subcommand to perf lock which can be used to dump metadata like threads or addresses of lock instances. "map" was removed because info should do the work for it. This will be useful not only for debugging but also for ordinary analyzing. v2: adding example of usage % sudo ./perf lock info -t | Thread ID: comm | 0: swapper | 1: init | 18: migration/5 | 29: events/2 | 32: events/5 | 33: events/6 ... % sudo ./perf lock info -m | Address of instance: name of class | 0xffff8800b95adae0: &(&sighand->siglock)->rlock | 0xffff8800bbb41ae0: &(&sighand->siglock)->rlock | 0xffff8800bf165ae0: &(&sighand->siglock)->rlock | 0xffff8800b9576a98: &p->cred_guard_mutex | 0xffff8800bb890a08: &(&p->alloc_lock)->rlock | 0xffff8800b9522a08: &(&p->alloc_lock)->rlock | 0xffff8800bb8aaa08: &(&p->alloc_lock)->rlock | 0xffff8800bba72a08: &(&p->alloc_lock)->rlock | 0xffff8800bf18ea08: &(&p->alloc_lock)->rlock | 0xffff8800b8a0d8a0: &(&ip->i_lock)->mr_lock | 0xffff88009bf818a0: &(&ip->i_lock)->mr_lock | 0xffff88004c66b8a0: &(&ip->i_lock)->mr_lock | 0xffff8800bb6478a0: &(shost->host_lock)->rlock v3: fixed some problems Frederic pointed out * better rbtree tracking in dump_threads() * removed printf() and used pr_info() and pr_debug() Signed-off-by: Hitoshi Mitake Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo Cc: Jens Axboe Cc: Jason Baron Cc: Xiao Guangrong LKML-Reference: <1272863520-16179-1-git-send-email-mitake@dcl.info.waseda.ac.jp> Signed-off-by: Frederic Weisbecker diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index 6605000..c4eb854 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c @@ -720,15 +720,15 @@ static void print_result(void) char cut_name[20]; int bad, total; - printf("%20s ", "Name"); - printf("%10s ", "acquired"); - printf("%10s ", "contended"); + pr_info("%20s ", "Name"); + pr_info("%10s ", "acquired"); + pr_info("%10s ", "contended"); - printf("%15s ", "total wait (ns)"); - printf("%15s ", "max wait (ns)"); - printf("%15s ", "min wait (ns)"); + pr_info("%15s ", "total wait (ns)"); + pr_info("%15s ", "max wait (ns)"); + pr_info("%15s ", "min wait (ns)"); - printf("\n\n"); + pr_info("\n\n"); bad = total = 0; while ((st = pop_from_result())) { @@ -741,7 +741,7 @@ static void print_result(void) if (strlen(st->name) < 16) { /* output raw name */ - printf("%20s ", st->name); + pr_info("%20s ", st->name); } else { strncpy(cut_name, st->name, 16); cut_name[16] = '.'; @@ -749,17 +749,17 @@ static void print_result(void) cut_name[18] = '.'; cut_name[19] = '\0'; /* cut off name for saving output style */ - printf("%20s ", cut_name); + pr_info("%20s ", cut_name); } - printf("%10u ", st->nr_acquired); - printf("%10u ", st->nr_contended); + pr_info("%10u ", st->nr_acquired); + pr_info("%10u ", st->nr_contended); - printf("%15llu ", st->wait_time_total); - printf("%15llu ", st->wait_time_max); - printf("%15llu ", st->wait_time_min == ULLONG_MAX ? + pr_info("%15llu ", st->wait_time_total); + pr_info("%15llu ", st->wait_time_max); + pr_info("%15llu ", st->wait_time_min == ULLONG_MAX ? 0 : st->wait_time_min); - printf("\n"); + pr_info("\n"); } { @@ -768,28 +768,59 @@ static void print_result(void) const char *name[4] = { "acquire", "acquired", "contended", "release" }; - printf("\n=== output for debug===\n\n"); - printf("bad:%d, total:%d\n", bad, total); - printf("bad rate:%f\n", (double)(bad / total)); + pr_debug("\n=== output for debug===\n\n"); + pr_debug("bad:%d, total:%d\n", bad, total); + pr_debug("bad rate:%f\n", (double)(bad / total)); - printf("histogram of events caused bad sequence\n"); + pr_debug("histogram of events caused bad sequence\n"); for (i = 0; i < 4; i++) - printf(" %10s: %d\n", name[i], bad_hist[i]); + pr_debug(" %10s: %d\n", name[i], bad_hist[i]); } } +static int info_threads; +static int info_map; + +static void dump_threads(void) +{ + struct thread_stat *st; + struct rb_node *node; + struct thread *t; + + pr_info("%10s: comm\n", "Thread ID"); + + node = rb_first(&thread_stats); + while (node) { + st = container_of(node, struct thread_stat, rb); + t = perf_session__findnew(session, st->tid); + pr_info("%10d: %s\n", st->tid, t->comm); + node = rb_next(node); + }; +} + static void dump_map(void) { unsigned int i; struct lock_stat *st; + pr_info("Address of instance: name of class\n"); for (i = 0; i < LOCKHASH_SIZE; i++) { list_for_each_entry(st, &lockhash_table[i], hash_entry) { - printf("%p: %s\n", st->addr, st->name); + pr_info(" %p: %s\n", st->addr, st->name); } } } +static void dump_info(void) +{ + if (info_threads) + dump_threads(); + else if (info_map) + dump_map(); + else + die("Unknown type of information\n"); +} + static int process_sample_event(event_t *self, struct perf_session *s) { struct sample_data data; @@ -858,6 +889,19 @@ static const struct option report_options[] = { OPT_END() }; +static const char * const info_usage[] = { + "perf lock info []", + NULL +}; + +static const struct option info_options[] = { + OPT_BOOLEAN('t', "threads", &info_threads, + "dump thread list in perf.data"), + OPT_BOOLEAN('m', "map", &info_map, + "map of lock instances (name:address table)"), + OPT_END() +}; + static const char * const lock_usage[] = { "perf lock [] {record|trace|report}", NULL @@ -929,12 +973,18 @@ int cmd_lock(int argc, const char **argv, const char *prefix __used) } else if (!strcmp(argv[0], "trace")) { /* Aliased to 'perf trace' */ return cmd_trace(argc, argv, prefix); - } else if (!strcmp(argv[0], "map")) { + } else if (!strcmp(argv[0], "info")) { + if (argc) { + argc = parse_options(argc, argv, + info_options, info_usage, 0); + if (argc) + usage_with_options(info_usage, info_options); + } /* recycling report_lock_ops */ trace_handler = &report_lock_ops; setup_pager(); read_events(); - dump_map(); + dump_info(); } else { usage_with_options(lock_usage, lock_options); } -- cgit v0.10.2 From 10350ec362b48f79f3df8447c25813790075e27c Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 5 May 2010 23:47:28 +0200 Subject: perf: Cleanup perf lock broken states Use enum to get a human view of bad_hist indexes and put bad histogram output in its own function. Signed-off-by: Frederic Weisbecker Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Hitoshi Mitake diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index c4eb854..1e93179 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c @@ -387,7 +387,15 @@ static struct lock_seq_stat *get_seq(struct thread_stat *ts, void *addr) return seq; } -static int bad_hist[4]; +enum broken_state { + BROKEN_ACQUIRE, + BROKEN_ACQUIRED, + BROKEN_CONTENDED, + BROKEN_RELEASE, + BROKEN_MAX, +}; + +static int bad_hist[BROKEN_MAX]; static void report_lock_acquire_event(struct trace_acquire_event *acquire_event, @@ -437,7 +445,7 @@ report_lock_acquire_event(struct trace_acquire_event *acquire_event, broken: /* broken lock sequence, discard it */ ls->discard = 1; - bad_hist[0]++; + bad_hist[BROKEN_ACQUIRE]++; list_del(&seq->list); free(seq); goto end; @@ -481,7 +489,6 @@ report_lock_acquired_event(struct trace_acquired_event *acquired_event, case SEQ_STATE_CONTENDED: contended_term = timestamp - seq->prev_event_time; ls->wait_time_total += contended_term; - if (contended_term < ls->wait_time_min) ls->wait_time_min = contended_term; else if (ls->wait_time_max < contended_term) @@ -492,7 +499,7 @@ report_lock_acquired_event(struct trace_acquired_event *acquired_event, case SEQ_STATE_READ_ACQUIRED: /* broken lock sequence, discard it */ ls->discard = 1; - bad_hist[1]++; + bad_hist[BROKEN_ACQUIRED]++; list_del(&seq->list); free(seq); goto end; @@ -540,7 +547,7 @@ report_lock_contended_event(struct trace_contended_event *contended_event, case SEQ_STATE_CONTENDED: /* broken lock sequence, discard it */ ls->discard = 1; - bad_hist[2]++; + bad_hist[BROKEN_CONTENDED]++; list_del(&seq->list); free(seq); goto end; @@ -594,7 +601,7 @@ report_lock_release_event(struct trace_release_event *release_event, case SEQ_STATE_RELEASED: /* broken lock sequence, discard it */ ls->discard = 1; - bad_hist[3]++; + bad_hist[BROKEN_RELEASE]++; goto free_seq; break; default: @@ -713,6 +720,21 @@ process_raw_event(void *data, int cpu, u64 timestamp, struct thread *thread) process_lock_release_event(data, event, cpu, timestamp, thread); } +static void print_bad_events(int bad, int total) +{ + /* Output for debug, this have to be removed */ + int i; + const char *name[4] = + { "acquire", "acquired", "contended", "release" }; + + pr_info("\n=== output for debug===\n\n"); + pr_info("bad:%d, total:%d\n", bad, total); + pr_info("bad rate:%f\n", (double)(bad / total)); + pr_info("histogram of events caused bad sequence\n"); + for (i = 0; i < BROKEN_MAX; i++) + pr_info(" %10s: %d\n", name[i], bad_hist[i]); +} + /* TODO: various way to print, coloring, nano or milli sec */ static void print_result(void) { @@ -762,20 +784,7 @@ static void print_result(void) pr_info("\n"); } - { - /* Output for debug, this have to be removed */ - int i; - const char *name[4] = - { "acquire", "acquired", "contended", "release" }; - - pr_debug("\n=== output for debug===\n\n"); - pr_debug("bad:%d, total:%d\n", bad, total); - pr_debug("bad rate:%f\n", (double)(bad / total)); - - pr_debug("histogram of events caused bad sequence\n"); - for (i = 0; i < 4; i++) - pr_debug(" %10s: %d\n", name[i], bad_hist[i]); - } + print_bad_events(bad, total); } static int info_threads; -- cgit v0.10.2 From 84c7a21791eb2e962a27e19bab5b77d5d9e13a34 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 5 May 2010 23:57:25 +0200 Subject: perf: Humanize lock flags in perf lock Use an enum instead of plain constants for lock flags. Signed-off-by: Frederic Weisbecker Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Hitoshi Mitake diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index 1e93179..3b304ed 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c @@ -397,6 +397,11 @@ enum broken_state { static int bad_hist[BROKEN_MAX]; +enum acquire_flags { + TRY_LOCK = 1, + READ_LOCK = 2, +}; + static void report_lock_acquire_event(struct trace_acquire_event *acquire_event, struct event *__event __used, @@ -421,9 +426,9 @@ report_lock_acquire_event(struct trace_acquire_event *acquire_event, if (!acquire_event->flag) { seq->state = SEQ_STATE_ACQUIRING; } else { - if (acquire_event->flag & 1) + if (acquire_event->flag & TRY_LOCK) ls->nr_trylock++; - if (acquire_event->flag & 2) + if (acquire_event->flag & READ_LOCK) ls->nr_readlock++; seq->state = SEQ_STATE_READ_ACQUIRED; seq->read_count = 1; @@ -431,7 +436,7 @@ report_lock_acquire_event(struct trace_acquire_event *acquire_event, } break; case SEQ_STATE_READ_ACQUIRED: - if (acquire_event->flag & 2) { + if (acquire_event->flag & READ_LOCK) { seq->read_count++; ls->nr_acquired++; goto end; -- cgit v0.10.2 From 5efe08cf685f33f562566dc68b6077b6f6a4f706 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Thu, 6 May 2010 04:55:22 +0200 Subject: perf: Fix perf lock bad rate Fix the cast made to get the bad rate. It is made in the result instead of the operands. We need the operands to be cast in double, otherwise the result will always be zero. Signed-off-by: Frederic Weisbecker Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Hitoshi Mitake diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index 3b304ed..d7dde9c 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c @@ -733,8 +733,8 @@ static void print_bad_events(int bad, int total) { "acquire", "acquired", "contended", "release" }; pr_info("\n=== output for debug===\n\n"); - pr_info("bad:%d, total:%d\n", bad, total); - pr_info("bad rate:%f\n", (double)(bad / total)); + pr_info("bad: %d, total: %d\n", bad, total); + pr_info("bad rate: %f %%\n", (double)bad / (double)total * 100); pr_info("histogram of events caused bad sequence\n"); for (i = 0; i < BROKEN_MAX; i++) pr_info(" %10s: %d\n", name[i], bad_hist[i]); -- cgit v0.10.2 From 90c0e5fc7b73d2575c7367e1da70ff9521718e5e Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Fri, 7 May 2010 02:33:42 +0200 Subject: perf lock: Always check min AND max wait time When a lock is acquired after beeing contended, we update the wait time statistics for the given lock. But if the min wait time is updated, we don't check the max wait time. This is wrong because the first time we update the wait time, we want to update both min and max wait time. Before: Name acquired contended total wait (ns) max wait (ns) min wait (ns) key 8 1 21656 0 21656 After: Name acquired contended total wait (ns) max wait (ns) min wait (ns) key 8 1 21656 21656 21656 Signed-off-by: Frederic Weisbecker Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Hitoshi Mitake diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index d7dde9c..e549f45 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c @@ -496,7 +496,7 @@ report_lock_acquired_event(struct trace_acquired_event *acquired_event, ls->wait_time_total += contended_term; if (contended_term < ls->wait_time_min) ls->wait_time_min = contended_term; - else if (ls->wait_time_max < contended_term) + if (ls->wait_time_max < contended_term) ls->wait_time_max = contended_term; break; case SEQ_STATE_RELEASED: -- cgit v0.10.2 From 883a2a3189dae9d2912c417e47152f51cb922a3f Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Sat, 8 May 2010 06:16:11 +0200 Subject: tracing: Drop lock_acquired waittime field Drop the waittime field from the lock_acquired event, we can calculate it by substracting the lock_acquired event timestamp with the matching lock_acquire one. It is not needed and takes useless space in the traces. Signed-off-by: Frederic Weisbecker Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras Cc: Hitoshi Mitake Cc: Steven Rostedt diff --git a/include/trace/events/lock.h b/include/trace/events/lock.h index 5c1dcfc..17ca287 100644 --- a/include/trace/events/lock.h +++ b/include/trace/events/lock.h @@ -78,24 +78,21 @@ TRACE_EVENT(lock_contended, ); TRACE_EVENT(lock_acquired, - TP_PROTO(struct lockdep_map *lock, unsigned long ip, s64 waittime), + TP_PROTO(struct lockdep_map *lock, unsigned long ip), - TP_ARGS(lock, ip, waittime), + TP_ARGS(lock, ip), TP_STRUCT__entry( __string(name, lock->name) - __field(s64, wait_nsec) __field(void *, lockdep_addr) ), TP_fast_assign( __assign_str(name, lock->name); - __entry->wait_nsec = waittime; __entry->lockdep_addr = lock; ), - TP_printk("%p %s (%llu ns)", __entry->lockdep_addr, - __get_str(name), - __entry->wait_nsec) + TP_printk("%p %s", __entry->lockdep_addr, + __get_str(name)) ); #endif diff --git a/kernel/lockdep.c b/kernel/lockdep.c index 2594e1c..31e22e7 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c @@ -3380,7 +3380,7 @@ found_it: hlock->holdtime_stamp = now; } - trace_lock_acquired(lock, ip, waittime); + trace_lock_acquired(lock, ip); stats = get_lock_stats(hlock_class(hlock)); if (waittime) { -- cgit v0.10.2 From 93135439459920c4d856f4ab8f068c030085c8df Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Sat, 8 May 2010 06:24:25 +0200 Subject: tracing: Drop the nested field from lock_release event Drop the nested field as we don't use it. Every nested state can be computed from a state machine on post processing already. Signed-off-by: Frederic Weisbecker Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Hitoshi Mitake Cc: Steven Rostedt diff --git a/include/trace/events/lock.h b/include/trace/events/lock.h index 17ca287..fde4c38 100644 --- a/include/trace/events/lock.h +++ b/include/trace/events/lock.h @@ -37,9 +37,9 @@ TRACE_EVENT(lock_acquire, TRACE_EVENT(lock_release, - TP_PROTO(struct lockdep_map *lock, int nested, unsigned long ip), + TP_PROTO(struct lockdep_map *lock, unsigned long ip), - TP_ARGS(lock, nested, ip), + TP_ARGS(lock, ip), TP_STRUCT__entry( __string(name, lock->name) diff --git a/kernel/lockdep.c b/kernel/lockdep.c index 31e22e7..e9c759f 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c @@ -3227,7 +3227,7 @@ void lock_release(struct lockdep_map *lock, int nested, raw_local_irq_save(flags); check_flags(flags); current->lockdep_recursion = 1; - trace_lock_release(lock, nested, ip); + trace_lock_release(lock, ip); __lock_release(lock, nested, ip); current->lockdep_recursion = 0; raw_local_irq_restore(flags); -- cgit v0.10.2 From 2c193c736803ceb547daec725e5c5d992d039f20 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Sat, 8 May 2010 06:36:02 +0200 Subject: tracing: Factorize lock events in a lock class lock_acquired, lock_contended and lock_release now share the same prototype and format. Let's factorize them into a lock event class. Signed-off-by: Frederic Weisbecker Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Hitoshi Mitake Cc: Steven Rostedt diff --git a/include/trace/events/lock.h b/include/trace/events/lock.h index fde4c38..2821b86 100644 --- a/include/trace/events/lock.h +++ b/include/trace/events/lock.h @@ -35,15 +35,15 @@ TRACE_EVENT(lock_acquire, __get_str(name)) ); -TRACE_EVENT(lock_release, +DECLARE_EVENT_CLASS(lock, TP_PROTO(struct lockdep_map *lock, unsigned long ip), TP_ARGS(lock, ip), TP_STRUCT__entry( - __string(name, lock->name) - __field(void *, lockdep_addr) + __string( name, lock->name ) + __field( void *, lockdep_addr ) ), TP_fast_assign( @@ -51,48 +51,30 @@ TRACE_EVENT(lock_release, __entry->lockdep_addr = lock; ), - TP_printk("%p %s", - __entry->lockdep_addr, __get_str(name)) + TP_printk("%p %s", __entry->lockdep_addr, __get_str(name)) ); -#ifdef CONFIG_LOCK_STAT - -TRACE_EVENT(lock_contended, +DEFINE_EVENT(lock, lock_release, TP_PROTO(struct lockdep_map *lock, unsigned long ip), - TP_ARGS(lock, ip), - - TP_STRUCT__entry( - __string(name, lock->name) - __field(void *, lockdep_addr) - ), + TP_ARGS(lock, ip) +); - TP_fast_assign( - __assign_str(name, lock->name); - __entry->lockdep_addr = lock; - ), +#ifdef CONFIG_LOCK_STAT - TP_printk("%p %s", - __entry->lockdep_addr, __get_str(name)) -); +DEFINE_EVENT(lock, lock_contended, -TRACE_EVENT(lock_acquired, TP_PROTO(struct lockdep_map *lock, unsigned long ip), - TP_ARGS(lock, ip), + TP_ARGS(lock, ip) +); - TP_STRUCT__entry( - __string(name, lock->name) - __field(void *, lockdep_addr) - ), +DEFINE_EVENT(lock, lock_acquired, - TP_fast_assign( - __assign_str(name, lock->name); - __entry->lockdep_addr = lock; - ), - TP_printk("%p %s", __entry->lockdep_addr, - __get_str(name)) + TP_PROTO(struct lockdep_map *lock, unsigned long ip), + + TP_ARGS(lock, ip) ); #endif -- cgit v0.10.2 From 794e43b56c18b95fc9776c914a2659e7d558a352 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Wed, 5 May 2010 00:27:40 -0500 Subject: perf/live-mode: Handle payload-less events Some events, such as the PERF_RECORD_FINISHED_ROUND event consist of only an event header and no data. In this case, a 0-length payload will be read, and the 0 return value will be wrongly interpreted as an 'unexpected end of event stream'. This patch allows for proper handling of data-less events by skipping 0-length reads. Signed-off-by: Tom Zanussi Cc: Arnaldo Carvalho de Melo Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Masami Hiramatsu LKML-Reference: <1273038527.6383.51.camel@tropicana> Signed-off-by: Frederic Weisbecker diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 9401909..00ab298 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -696,15 +696,18 @@ more: p = &event; p += sizeof(struct perf_event_header); - err = do_read(self->fd, p, size - sizeof(struct perf_event_header)); - if (err <= 0) { - if (err == 0) { - pr_err("unexpected end of event stream\n"); - goto done; - } + if (size - sizeof(struct perf_event_header)) { + err = do_read(self->fd, p, + size - sizeof(struct perf_event_header)); + if (err <= 0) { + if (err == 0) { + pr_err("unexpected end of event stream\n"); + goto done; + } - pr_err("failed to read event data\n"); - goto out_err; + pr_err("failed to read event data\n"); + goto out_err; + } } if (size == 0 || -- cgit v0.10.2 From 139633c6a43781cd44798165b0472a34bf53a1e8 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 9 May 2010 11:47:13 -0300 Subject: perf callchain: Move validate_callchain to callchain lib MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 196473b..1cae877 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -123,19 +123,6 @@ static int perf_session__add_hist_entry(struct perf_session *self, return 0; } -static int validate_chain(struct ip_callchain *chain, event_t *event) -{ - unsigned int chain_size; - - chain_size = event->header.size; - chain_size -= (unsigned long)&event->ip.__more_data - (unsigned long)event; - - if (chain->nr*sizeof(u64) > chain_size) - return -1; - - return 0; -} - static int add_event_total(struct perf_session *session, struct sample_data *data, struct perf_event_attr *attr) @@ -171,7 +158,7 @@ static int process_sample_event(event_t *event, struct perf_session *session) dump_printf("... chain: nr:%Lu\n", data.callchain->nr); - if (validate_chain(data.callchain, event) < 0) { + if (!ip_callchain__valid(data.callchain, event)) { pr_debug("call-chain problem with event, " "skipping it.\n"); return 0; diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index db628af..ac14861 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -17,6 +17,13 @@ #include "callchain.h" +bool ip_callchain__valid(struct ip_callchain *chain, event_t *event) +{ + unsigned int chain_size = event->header.size; + chain_size -= (unsigned long)&event->ip.__more_data - (unsigned long)event; + return chain->nr * sizeof(u64) <= chain_size; +} + #define chain_for_each_child(child, parent) \ list_for_each_entry(child, &parent->children, brothers) diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index 8a7e8bb..0f4da09 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h @@ -4,6 +4,7 @@ #include "../perf.h" #include #include +#include "event.h" #include "util.h" #include "symbol.h" @@ -58,4 +59,6 @@ static inline u64 cumul_hits(struct callchain_node *node) int register_callchain_param(struct callchain_param *param); int append_chain(struct callchain_node *root, struct ip_callchain *chain, struct map_symbol *syms); + +bool ip_callchain__valid(struct ip_callchain *chain, event_t *event); #endif /* __PERF_CALLCHAIN_H */ -- cgit v0.10.2 From 39d1e1b1e26dc84d40bf2792287d0d61e44b57df Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 9 May 2010 12:01:05 -0300 Subject: perf report: Fix leak of resolved callchains array on error path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 1cae877..3a70c58 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -83,7 +83,7 @@ static int perf_session__add_hist_entry(struct perf_session *self, struct map_symbol *syms = NULL; struct symbol *parent = NULL; bool hit; - int err; + int err = -ENOMEM; struct hist_entry *he; struct event_stat_id *stats; struct perf_event_attr *attr; @@ -101,26 +101,24 @@ static int perf_session__add_hist_entry(struct perf_session *self, else stats = get_stats(self, data->id, 0, 0); if (stats == NULL) - return -ENOMEM; + goto out_free_syms; he = __perf_session__add_hist_entry(&stats->hists, al, parent, data->period, &hit); if (he == NULL) - return -ENOMEM; + goto out_free_syms; if (hit) __perf_session__add_count(he, al, data->period); + err = 0; if (symbol_conf.use_callchain) { if (!hit) callchain_init(he->callchain); err = append_chain(he->callchain, data->callchain, syms); - free(syms); - - if (err) - return err; } - - return 0; +out_free_syms: + free(syms); + return err; } static int add_event_total(struct perf_session *session, -- cgit v0.10.2 From 28e2a106d16046ca792722795f809e3f80a5af80 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 9 May 2010 13:02:23 -0300 Subject: perf hist: Simplify the insertion of new hist_entry instances MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit And with that fix at least one bug: The first hit for an entry, the one that calls malloc to create a new instance in __perf_session__add_hist_entry, wasn't adding the count to the per cpumode (PERF_RECORD_MISC_USER, etc) total variable. Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index ee154b5..c7ac45a 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -72,8 +72,6 @@ static int annotate__hist_hit(struct hist_entry *he, u64 ip) struct sym_priv *priv; struct sym_hist *h; - he->count++; - if (!sym || !he->ms.map) return 0; @@ -99,9 +97,8 @@ static int annotate__hist_hit(struct hist_entry *he, u64 ip) } static int perf_session__add_hist_entry(struct perf_session *self, - struct addr_location *al, u64 count) + struct addr_location *al) { - bool hit; struct hist_entry *he; if (sym_hist_filter != NULL && @@ -115,7 +112,7 @@ static int perf_session__add_hist_entry(struct perf_session *self, return 0; } - he = __perf_session__add_hist_entry(&self->hists, al, NULL, count, &hit); + he = __perf_session__add_hist_entry(&self->hists, al, NULL, 1); if (he == NULL) return -ENOMEM; @@ -135,7 +132,7 @@ static int process_sample_event(event_t *event, struct perf_session *session) return -1; } - if (!al.filtered && perf_session__add_hist_entry(session, &al, 1)) { + if (!al.filtered && perf_session__add_hist_entry(session, &al)) { pr_warning("problem incrementing symbol count, " "skipping event\n"); return -1; diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 4cce68f..613a5c4 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -25,17 +25,9 @@ static bool show_displacement; static int perf_session__add_hist_entry(struct perf_session *self, struct addr_location *al, u64 count) { - bool hit; - struct hist_entry *he = __perf_session__add_hist_entry(&self->hists, - al, NULL, - count, &hit); - if (he == NULL) - return -ENOMEM; - - if (hit) - __perf_session__add_count(he, al, count); - - return 0; + if (__perf_session__add_hist_entry(&self->hists, al, NULL, count) != NULL) + return 0; + return -ENOMEM; } static int diff__process_sample_event(event_t *event, struct perf_session *session) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 3a70c58..5e2f47f 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -82,7 +82,6 @@ static int perf_session__add_hist_entry(struct perf_session *self, { struct map_symbol *syms = NULL; struct symbol *parent = NULL; - bool hit; int err = -ENOMEM; struct hist_entry *he; struct event_stat_id *stats; @@ -103,19 +102,12 @@ static int perf_session__add_hist_entry(struct perf_session *self, if (stats == NULL) goto out_free_syms; he = __perf_session__add_hist_entry(&stats->hists, al, parent, - data->period, &hit); + data->period); if (he == NULL) goto out_free_syms; - - if (hit) - __perf_session__add_count(he, al, data->period); - err = 0; - if (symbol_conf.use_callchain) { - if (!hit) - callchain_init(he->callchain); + if (symbol_conf.use_callchain) err = append_chain(he->callchain, data->callchain, syms); - } out_free_syms: free(syms); return err; diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index ad6b22d..e0c8a72 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -8,13 +8,10 @@ struct callchain_param callchain_param = { .min_percent = 0.5 }; -void __perf_session__add_count(struct hist_entry *he, - struct addr_location *al, - u64 count) +static void perf_session__add_cpumode_count(struct hist_entry *he, + unsigned int cpumode, u64 count) { - he->count += count; - - switch (al->cpumode) { + switch (cpumode) { case PERF_RECORD_MISC_KERNEL: he->count_sys += count; break; @@ -36,10 +33,24 @@ void __perf_session__add_count(struct hist_entry *he, * histogram, sorted on item, collects counts */ +static struct hist_entry *hist_entry__new(struct hist_entry *template) +{ + size_t callchain_size = symbol_conf.use_callchain ? sizeof(struct callchain_node) : 0; + struct hist_entry *self = malloc(sizeof(*self) + callchain_size); + + if (self != NULL) { + *self = *template; + if (symbol_conf.use_callchain) + callchain_init(self->callchain); + } + + return self; +} + struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists, struct addr_location *al, struct symbol *sym_parent, - u64 count, bool *hit) + u64 count) { struct rb_node **p = &hists->rb_node; struct rb_node *parent = NULL; @@ -64,8 +75,8 @@ struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists, cmp = hist_entry__cmp(&entry, he); if (!cmp) { - *hit = true; - return he; + he->count += count; + goto out; } if (cmp < 0) @@ -74,14 +85,13 @@ struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists, p = &(*p)->rb_right; } - he = malloc(sizeof(*he) + (symbol_conf.use_callchain ? - sizeof(struct callchain_node) : 0)); + he = hist_entry__new(&entry); if (!he) return NULL; - *he = entry; rb_link_node(&he->rb_node, parent, p); rb_insert_color(&he->rb_node, hists); - *hit = false; +out: + perf_session__add_cpumode_count(he, al->cpumode, count); return he; } diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 9df1c34..b49013a 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -12,13 +12,10 @@ struct addr_location; struct symbol; struct rb_root; -void __perf_session__add_count(struct hist_entry *he, - struct addr_location *al, - u64 count); struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists, struct addr_location *al, struct symbol *parent, - u64 count, bool *hit); + u64 count); extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *); extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *); int hist_entry__fprintf(struct hist_entry *self, -- cgit v0.10.2 From b1f724c3055fa75a31d272222213647547a2d3d4 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Sun, 9 May 2010 08:22:08 -0700 Subject: sched: Add a comment to get_cpu_idle_time_us() The exported function get_cpu_idle_time_us() has no comment describing it; add a kerneldoc comment Signed-off-by: Arjan van de Ven Signed-off-by: Andrew Morton Reviewed-by: Rik van Riel Acked-by: Peter Zijlstra Cc: davej@redhat.com LKML-Reference: <20100509082208.7cb721f0@infradead.org> Signed-off-by: Ingo Molnar diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index f25735a..358822e 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -179,6 +179,20 @@ static ktime_t tick_nohz_start_idle(struct tick_sched *ts) return now; } +/** + * get_cpu_idle_time_us - get the total idle time of a cpu + * @cpu: CPU number to query + * @last_update_time: variable to store update time in + * + * Return the cummulative idle time (since boot) for a given + * CPU, in microseconds. The idle time returned includes + * the iowait time (unlike what "top" and co report). + * + * This time is measured via accounting rather than sampling, + * and is as accurate as ktime_get() is. + * + * This function returns -1 if NOHZ is not enabled. + */ u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time) { struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); -- cgit v0.10.2 From 595aac488b546c7185be7e29c8ae165a588b2a9f Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Sun, 9 May 2010 08:22:45 -0700 Subject: sched: Introduce a function to update the idle statistics Currently, two places update the idle statistics (and more to come later in this series). This patch creates a helper function for updating these statistics. Signed-off-by: Arjan van de Ven Signed-off-by: Andrew Morton Reviewed-by: Rik van Riel Acked-by: Peter Zijlstra Cc: davej@redhat.com LKML-Reference: <20100509082245.163e67ed@infradead.org> Signed-off-by: Ingo Molnar diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 358822e..59d8762 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -150,14 +150,25 @@ static void tick_nohz_update_jiffies(ktime_t now) touch_softlockup_watchdog(); } -static void tick_nohz_stop_idle(int cpu, ktime_t now) +/* + * Updates the per cpu time idle statistics counters + */ +static void update_ts_time_stats(struct tick_sched *ts, ktime_t now) { - struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); ktime_t delta; - delta = ktime_sub(now, ts->idle_entrytime); ts->idle_lastupdate = now; - ts->idle_sleeptime = ktime_add(ts->idle_sleeptime, delta); + if (ts->idle_active) { + delta = ktime_sub(now, ts->idle_entrytime); + ts->idle_sleeptime = ktime_add(ts->idle_sleeptime, delta); + } +} + +static void tick_nohz_stop_idle(int cpu, ktime_t now) +{ + struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); + + update_ts_time_stats(ts, now); ts->idle_active = 0; sched_clock_idle_wakeup_event(0); @@ -165,14 +176,12 @@ static void tick_nohz_stop_idle(int cpu, ktime_t now) static ktime_t tick_nohz_start_idle(struct tick_sched *ts) { - ktime_t now, delta; + ktime_t now; now = ktime_get(); - if (ts->idle_active) { - delta = ktime_sub(now, ts->idle_entrytime); - ts->idle_lastupdate = now; - ts->idle_sleeptime = ktime_add(ts->idle_sleeptime, delta); - } + + update_ts_time_stats(ts, now); + ts->idle_entrytime = now; ts->idle_active = 1; sched_clock_idle_sleep_event(); -- cgit v0.10.2 From 8c7b09f43f4bf570654bcc458ce96819a932303c Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Sun, 9 May 2010 08:23:23 -0700 Subject: sched: Update the idle statistics in get_cpu_idle_time_us() Right now, get_cpu_idle_time_us() only reports the idle statistics upto the point the CPU entered last idle; not what is valid right now. This patch adds an update of the idle statistics to get_cpu_idle_time_us(), so that calling this function always returns statistics that are accurate at the point of the call. This includes resetting the start of the idle time for accounting purposes to avoid double accounting. Signed-off-by: Arjan van de Ven Signed-off-by: Andrew Morton Reviewed-by: Rik van Riel Acked-by: Peter Zijlstra Cc: davej@redhat.com LKML-Reference: <20100509082323.2d2f1945@infradead.org> Signed-off-by: Ingo Molnar diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 59d8762..f15d18d 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -161,6 +161,7 @@ static void update_ts_time_stats(struct tick_sched *ts, ktime_t now) if (ts->idle_active) { delta = ktime_sub(now, ts->idle_entrytime); ts->idle_sleeptime = ktime_add(ts->idle_sleeptime, delta); + ts->idle_entrytime = now; } } @@ -205,14 +206,18 @@ static ktime_t tick_nohz_start_idle(struct tick_sched *ts) u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time) { struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); + ktime_t now; if (!tick_nohz_enabled) return -1; + now = ktime_get(); + update_ts_time_stats(ts, now); + if (ts->idle_active) *last_update_time = ktime_to_us(ts->idle_lastupdate); else - *last_update_time = ktime_to_us(ktime_get()); + *last_update_time = ktime_to_us(now); return ktime_to_us(ts->idle_sleeptime); } -- cgit v0.10.2 From 8d63bf949e330588b80d30ca8f0a27a45297a9e9 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Sun, 9 May 2010 08:24:03 -0700 Subject: sched: Fold updating of the last_update_time_info into update_ts_time_stats() This patch folds the updating of the last_update_time into the update_ts_time_stats() function, and updates the callers. This allows for further cleanups that are done in the next patch. Signed-off-by: Arjan van de Ven Signed-off-by: Andrew Morton Reviewed-by: Rik van Riel Acked-by: Peter Zijlstra Cc: davej@redhat.com LKML-Reference: <20100509082403.60072967@infradead.org> Signed-off-by: Ingo Molnar diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index f15d18d..e86e1c6 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -153,7 +153,8 @@ static void tick_nohz_update_jiffies(ktime_t now) /* * Updates the per cpu time idle statistics counters */ -static void update_ts_time_stats(struct tick_sched *ts, ktime_t now) +static void +update_ts_time_stats(struct tick_sched *ts, ktime_t now, u64 *last_update_time) { ktime_t delta; @@ -163,13 +164,19 @@ static void update_ts_time_stats(struct tick_sched *ts, ktime_t now) ts->idle_sleeptime = ktime_add(ts->idle_sleeptime, delta); ts->idle_entrytime = now; } + + if (ts->idle_active && last_update_time) + *last_update_time = ktime_to_us(ts->idle_lastupdate); + else + *last_update_time = ktime_to_us(now); + } static void tick_nohz_stop_idle(int cpu, ktime_t now) { struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); - update_ts_time_stats(ts, now); + update_ts_time_stats(ts, now, NULL); ts->idle_active = 0; sched_clock_idle_wakeup_event(0); @@ -181,7 +188,7 @@ static ktime_t tick_nohz_start_idle(struct tick_sched *ts) now = ktime_get(); - update_ts_time_stats(ts, now); + update_ts_time_stats(ts, now, NULL); ts->idle_entrytime = now; ts->idle_active = 1; @@ -206,18 +213,11 @@ static ktime_t tick_nohz_start_idle(struct tick_sched *ts) u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time) { struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); - ktime_t now; if (!tick_nohz_enabled) return -1; - now = ktime_get(); - update_ts_time_stats(ts, now); - - if (ts->idle_active) - *last_update_time = ktime_to_us(ts->idle_lastupdate); - else - *last_update_time = ktime_to_us(now); + update_ts_time_stats(ts, ktime_get(), last_update_time); return ktime_to_us(ts->idle_sleeptime); } -- cgit v0.10.2 From e0e37c200f1357db0dd986edb359c41c57d24f6e Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Sun, 9 May 2010 08:24:39 -0700 Subject: sched: Eliminate the ts->idle_lastupdate field Now that the only user of ts->idle_lastupdate is update_ts_time_stats(), the entire field can be eliminated. In update_ts_time_stats(), idle_lastupdate is first set to "now", and a few lines later, the only user is an if() statement that assigns a variable either to "now" or to ts->idle_lastupdate, which has the value of "now" at that point. Signed-off-by: Arjan van de Ven Signed-off-by: Andrew Morton Reviewed-by: Rik van Riel Acked-by: Peter Zijlstra Cc: davej@redhat.com LKML-Reference: <20100509082439.2fab0b4f@infradead.org> Signed-off-by: Ingo Molnar diff --git a/include/linux/tick.h b/include/linux/tick.h index d2ae79e..0343eed 100644 --- a/include/linux/tick.h +++ b/include/linux/tick.h @@ -60,7 +60,6 @@ struct tick_sched { ktime_t idle_waketime; ktime_t idle_exittime; ktime_t idle_sleeptime; - ktime_t idle_lastupdate; ktime_t sleep_length; unsigned long last_jiffies; unsigned long next_jiffies; diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index e86e1c6..50953f4 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -158,16 +158,13 @@ update_ts_time_stats(struct tick_sched *ts, ktime_t now, u64 *last_update_time) { ktime_t delta; - ts->idle_lastupdate = now; if (ts->idle_active) { delta = ktime_sub(now, ts->idle_entrytime); ts->idle_sleeptime = ktime_add(ts->idle_sleeptime, delta); ts->idle_entrytime = now; } - if (ts->idle_active && last_update_time) - *last_update_time = ktime_to_us(ts->idle_lastupdate); - else + if (last_update_time) *last_update_time = ktime_to_us(now); } -- cgit v0.10.2 From 0224cf4c5ee0d7faec83956b8e21f7d89e3df3bd Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Sun, 9 May 2010 08:25:23 -0700 Subject: sched: Intoduce get_cpu_iowait_time_us() For the ondemand cpufreq governor, it is desired that the iowait time is microaccounted in a similar way as idle time is. This patch introduces the infrastructure to account and expose this information via the get_cpu_iowait_time_us() function. [akpm@linux-foundation.org: fix CONFIG_NO_HZ=n build] Signed-off-by: Arjan van de Ven Signed-off-by: Andrew Morton Reviewed-by: Rik van Riel Acked-by: Peter Zijlstra Cc: davej@redhat.com LKML-Reference: <20100509082523.284feab6@infradead.org> Signed-off-by: Ingo Molnar diff --git a/include/linux/tick.h b/include/linux/tick.h index 0343eed..b232ccc 100644 --- a/include/linux/tick.h +++ b/include/linux/tick.h @@ -42,6 +42,7 @@ enum tick_nohz_mode { * @idle_waketime: Time when the idle was interrupted * @idle_exittime: Time when the idle state was left * @idle_sleeptime: Sum of the time slept in idle with sched tick stopped + * @iowait_sleeptime: Sum of the time slept in idle with sched tick stopped, with IO outstanding * @sleep_length: Duration of the current idle sleep * @do_timer_lst: CPU was the last one doing do_timer before going idle */ @@ -60,6 +61,7 @@ struct tick_sched { ktime_t idle_waketime; ktime_t idle_exittime; ktime_t idle_sleeptime; + ktime_t iowait_sleeptime; ktime_t sleep_length; unsigned long last_jiffies; unsigned long next_jiffies; @@ -123,6 +125,7 @@ extern void tick_nohz_stop_sched_tick(int inidle); extern void tick_nohz_restart_sched_tick(void); extern ktime_t tick_nohz_get_sleep_length(void); extern u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time); +extern u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time); # else static inline void tick_nohz_stop_sched_tick(int inidle) { } static inline void tick_nohz_restart_sched_tick(void) { } @@ -133,6 +136,7 @@ static inline ktime_t tick_nohz_get_sleep_length(void) return len; } static inline u64 get_cpu_idle_time_us(int cpu, u64 *unused) { return -1; } +static inline u64 get_cpu_iowait_time_us(int cpu, u64 *unused) { return -1; } # endif /* !NO_HZ */ #endif diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 50953f4..1d7b9bc 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -161,6 +161,8 @@ update_ts_time_stats(struct tick_sched *ts, ktime_t now, u64 *last_update_time) if (ts->idle_active) { delta = ktime_sub(now, ts->idle_entrytime); ts->idle_sleeptime = ktime_add(ts->idle_sleeptime, delta); + if (nr_iowait_cpu() > 0) + ts->iowait_sleeptime = ktime_add(ts->iowait_sleeptime, delta); ts->idle_entrytime = now; } @@ -220,6 +222,32 @@ u64 get_cpu_idle_time_us(int cpu, u64 *last_update_time) } EXPORT_SYMBOL_GPL(get_cpu_idle_time_us); +/* + * get_cpu_iowait_time_us - get the total iowait time of a cpu + * @cpu: CPU number to query + * @last_update_time: variable to store update time in + * + * Return the cummulative iowait time (since boot) for a given + * CPU, in microseconds. + * + * This time is measured via accounting rather than sampling, + * and is as accurate as ktime_get() is. + * + * This function returns -1 if NOHZ is not enabled. + */ +u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time) +{ + struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); + + if (!tick_nohz_enabled) + return -1; + + update_ts_time_stats(ts, ktime_get(), last_update_time); + + return ktime_to_us(ts->iowait_sleeptime); +} +EXPORT_SYMBOL_GPL(get_cpu_iowait_time_us); + /** * tick_nohz_stop_sched_tick - stop the idle tick from the idle task * diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c index 1a4a7dd..ab8f5e3 100644 --- a/kernel/time/timer_list.c +++ b/kernel/time/timer_list.c @@ -176,6 +176,7 @@ static void print_cpu(struct seq_file *m, int cpu, u64 now) P_ns(idle_waketime); P_ns(idle_exittime); P_ns(idle_sleeptime); + P_ns(iowait_sleeptime); P(last_jiffies); P(next_jiffies); P_ns(idle_expires); -- cgit v0.10.2 From 6b8fcd9029f217a9ecce822db645e19111c11080 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Sun, 9 May 2010 08:26:06 -0700 Subject: ondemand: Solve a big performance issue by counting IOWAIT time as busy The ondemand cpufreq governor uses CPU busy time (e.g. not-idle time) as a measure for scaling the CPU frequency up or down. If the CPU is busy, the CPU frequency scales up, if it's idle, the CPU frequency scales down. Effectively, it uses the CPU busy time as proxy variable for the more nebulous "how critical is performance right now" question. This algorithm falls flat on its face in the light of workloads where you're alternatingly disk and CPU bound, such as the ever popular "git grep", but also things like startup of programs and maildir using email clients... much to the chagarin of Andrew Morton. This patch changes the ondemand algorithm to count iowait time as busy, not idle, time. As shown in the breakdown cases above, iowait is performance critical often, and by counting iowait, the proxy variable becomes a more accurate representation of the "how critical is performance" question. The problem and fix are both verified with the "perf timechar" tool. Signed-off-by: Arjan van de Ven Signed-off-by: Andrew Morton Signed-off-by: Dave Jones Reviewed-by: Rik van Riel Acked-by: Peter Zijlstra LKML-Reference: <20100509082606.3d9f00d0@infradead.org> Signed-off-by: Ingo Molnar diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index bd444dc..ed472f8 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -73,6 +73,7 @@ enum {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE}; struct cpu_dbs_info_s { cputime64_t prev_cpu_idle; + cputime64_t prev_cpu_iowait; cputime64_t prev_cpu_wall; cputime64_t prev_cpu_nice; struct cpufreq_policy *cur_policy; @@ -148,6 +149,16 @@ static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall) return idle_time; } +static inline cputime64_t get_cpu_iowait_time(unsigned int cpu, cputime64_t *wall) +{ + u64 iowait_time = get_cpu_iowait_time_us(cpu, wall); + + if (iowait_time == -1ULL) + return 0; + + return iowait_time; +} + /* * Find right freq to be set now with powersave_bias on. * Returns the freq_hi to be used right now and will set freq_hi_jiffies, @@ -470,14 +481,15 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) for_each_cpu(j, policy->cpus) { struct cpu_dbs_info_s *j_dbs_info; - cputime64_t cur_wall_time, cur_idle_time; - unsigned int idle_time, wall_time; + cputime64_t cur_wall_time, cur_idle_time, cur_iowait_time; + unsigned int idle_time, wall_time, iowait_time; unsigned int load, load_freq; int freq_avg; j_dbs_info = &per_cpu(od_cpu_dbs_info, j); cur_idle_time = get_cpu_idle_time(j, &cur_wall_time); + cur_iowait_time = get_cpu_iowait_time(j, &cur_wall_time); wall_time = (unsigned int) cputime64_sub(cur_wall_time, j_dbs_info->prev_cpu_wall); @@ -487,6 +499,10 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) j_dbs_info->prev_cpu_idle); j_dbs_info->prev_cpu_idle = cur_idle_time; + iowait_time = (unsigned int) cputime64_sub(cur_iowait_time, + j_dbs_info->prev_cpu_iowait); + j_dbs_info->prev_cpu_iowait = cur_iowait_time; + if (dbs_tuners_ins.ignore_nice) { cputime64_t cur_nice; unsigned long cur_nice_jiffies; @@ -504,6 +520,16 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) idle_time += jiffies_to_usecs(cur_nice_jiffies); } + /* + * For the purpose of ondemand, waiting for disk IO is an + * indication that you're performance critical, and not that + * the system is actually idle. So subtract the iowait time + * from the cpu idle time. + */ + + if (idle_time >= iowait_time) + idle_time -= iowait_time; + if (unlikely(!wall_time || wall_time < idle_time)) continue; -- cgit v0.10.2 From 19379b11819efc1fc3b602e64f7e7531050aaddb Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Sun, 9 May 2010 08:26:51 -0700 Subject: ondemand: Make the iowait-is-busy time a sysfs tunable Pavel Machek pointed out that not all CPUs have an efficient idle at high frequency. Specifically, older Intel and various AMD cpus would get a higher powerusage when copying files from USB. Mike Chan pointed out that the same is true for various ARM chips as well. Thomas Renninger suggested to make this a sysfs tunable with a reasonable default. This patch adds a sysfs tunable for the new behavior, and uses a very simple function to determine a reasonable default, depending on the CPU vendor/type. Signed-off-by: Arjan van de Ven Acked-by: Rik van Riel Acked-by: Pavel Machek Acked-by: Peter Zijlstra Cc: davej@redhat.com LKML-Reference: <20100509082651.46914d04@infradead.org> [ minor tidyup ] Signed-off-by: Ingo Molnar diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index ed472f8..8e9dbdc 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -109,6 +109,7 @@ static struct dbs_tuners { unsigned int down_differential; unsigned int ignore_nice; unsigned int powersave_bias; + unsigned int io_is_busy; } dbs_tuners_ins = { .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, .down_differential = DEF_FREQUENCY_DOWN_DIFFERENTIAL, @@ -260,6 +261,7 @@ static ssize_t show_##file_name \ return sprintf(buf, "%u\n", dbs_tuners_ins.object); \ } show_one(sampling_rate, sampling_rate); +show_one(io_is_busy, io_is_busy); show_one(up_threshold, up_threshold); show_one(ignore_nice_load, ignore_nice); show_one(powersave_bias, powersave_bias); @@ -310,6 +312,23 @@ static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b, return count; } +static ssize_t store_io_is_busy(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + + mutex_lock(&dbs_mutex); + dbs_tuners_ins.io_is_busy = !!input; + mutex_unlock(&dbs_mutex); + + return count; +} + static ssize_t store_up_threshold(struct kobject *a, struct attribute *b, const char *buf, size_t count) { @@ -392,6 +411,7 @@ static struct global_attr _name = \ __ATTR(_name, 0644, show_##_name, store_##_name) define_one_rw(sampling_rate); +define_one_rw(io_is_busy); define_one_rw(up_threshold); define_one_rw(ignore_nice_load); define_one_rw(powersave_bias); @@ -403,6 +423,7 @@ static struct attribute *dbs_attributes[] = { &up_threshold.attr, &ignore_nice_load.attr, &powersave_bias.attr, + &io_is_busy.attr, NULL }; @@ -527,7 +548,7 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) * from the cpu idle time. */ - if (idle_time >= iowait_time) + if (dbs_tuners_ins.io_is_busy && idle_time >= iowait_time) idle_time -= iowait_time; if (unlikely(!wall_time || wall_time < idle_time)) @@ -643,6 +664,29 @@ static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info) cancel_delayed_work_sync(&dbs_info->work); } +/* + * Not all CPUs want IO time to be accounted as busy; this dependson how + * efficient idling at a higher frequency/voltage is. + * Pavel Machek says this is not so for various generations of AMD and old + * Intel systems. + * Mike Chan (androidlcom) calis this is also not true for ARM. + * Because of this, whitelist specific known (series) of CPUs by default, and + * leave all others up to the user. + */ +static int should_io_be_busy(void) +{ +#if defined(CONFIG_X86) + /* + * For Intel, Core 2 (model 15) andl later have an efficient idle. + */ + if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && + boot_cpu_data.x86 == 6 && + boot_cpu_data.x86_model >= 15) + return 1; +#endif + return 0; +} + static int cpufreq_governor_dbs(struct cpufreq_policy *policy, unsigned int event) { @@ -705,6 +749,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, dbs_tuners_ins.sampling_rate = max(min_sampling_rate, latency * LATENCY_MULTIPLIER); + dbs_tuners_ins.io_is_busy = should_io_be_busy(); } mutex_unlock(&dbs_mutex); -- cgit v0.10.2 From 76ba7e846fcc89d9d4b25b89e303c9058de96d60 Mon Sep 17 00:00:00 2001 From: Hitoshi Mitake Date: Sat, 8 May 2010 17:10:29 +0900 Subject: perf lock: Drop "-a" option from cmd_record() default arguments set This patch drops "-a" from the default arguments passed to perf record by perf lock. If a user wants to do a system wide record of lock events, perf lock record -a ... is enough for this purpose. This can reduce the size of the perf.data file. % sudo ./perf lock record whoami root [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.439 MB perf.data (~19170 samples) ] % sudo ./perf lock record -a whoami # with -a option root [ perf record: Woken up 0 times to write data ] [ perf record: Captured and wrote 48.962 MB perf.data (~2139197 samples) ] Signed-off-by: Hitoshi Mitake Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo Cc: Jens Axboe Cc: Jason Baron Cc: Xiao Guangrong LKML-Reference: Message-Id: <1273306229-5216-1-git-send-email-mitake@dcl.info.waseda.ac.jp> Signed-off-by: Frederic Weisbecker diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index e549f45..e18dfdc 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c @@ -930,7 +930,6 @@ static const struct option lock_options[] = { static const char *record_args[] = { "record", - "-a", "-R", "-f", "-m", "1024", -- cgit v0.10.2 From 3ceb0d4438876a65606c258e5d69e03e57460dd6 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 9 May 2010 16:07:01 -0300 Subject: perf symbols: Consider unresolved DSOs in the dso__col_widt calculation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit By using BITS_PER_LONG / 4, that is the number of chars that will be used in such cases as the DSO "name". Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 23d5dfd..46563e1 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -676,6 +676,13 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session, dso__calc_col_width(al->map->dso); al->sym = map__find_symbol(al->map, al->addr, filter); + } else { + const unsigned int unresolved_col_width = BITS_PER_LONG / 4; + + if (dsos__col_width < unresolved_col_width && + !symbol_conf.col_width_list_str && !symbol_conf.field_sep && + !symbol_conf.dso_list) + dsos__col_width = unresolved_col_width; } if (symbol_conf.sym_list && al->sym && -- cgit v0.10.2 From 4cc4945844fe2cf493f1783b6ce938ba1617d5c2 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 9 May 2010 21:14:07 -0300 Subject: perf symbols: Check if a struct machine instance was found MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Which can happen when processing old files that had no fake kernel MMAP, events. That shouldn't result in perf_session__create_kernel_maps not being called, this will be fixed in a followup patch, for now do these checks to avoid segfaulting. Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 46563e1..dfc8bf6 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -493,8 +493,10 @@ int event__process_mmap(event_t *self, struct perf_session *session) return 0; } - thread = perf_session__findnew(session, self->mmap.pid); machine = perf_session__find_host_machine(session); + if (machine == NULL) + goto out_problem; + thread = perf_session__findnew(session, self->mmap.pid); map = map__new(&machine->user_dsos, self->mmap.start, self->mmap.len, self->mmap.pgoff, self->mmap.pid, self->mmap.filename, @@ -552,6 +554,10 @@ void thread__find_addr_map(struct thread *self, if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) { al->level = 'k'; machine = perf_session__find_host_machine(session); + if (machine == NULL) { + al->map = NULL; + return; + } mg = &machine->kmaps; } else if (cpumode == PERF_RECORD_MISC_USER && perf_host) { al->level = '.'; @@ -559,7 +565,7 @@ void thread__find_addr_map(struct thread *self, } else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) { al->level = 'g'; machine = perf_session__find_machine(session, pid); - if (!machine) { + if (machine == NULL) { al->map = NULL; return; } -- cgit v0.10.2 From 1f626bc36847ac8dd192f055aed0f9678a781313 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 9 May 2010 19:57:08 -0300 Subject: perf session: Embed the host machine data on perf_session MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have just one host on a given session, and that is the most common setup right now, so embed a ->host_machine struct machine instance directly in the perf_session class, check if we're looking for it before going to the rb_tree. This also fixes a problem found when we try to process old perf.data files where we didn't have MMAP events for the kernel and modules and thus don't create the kernel maps, do it in event__preprocess_sample if it wasn't already. Reported-by: Ingo Molnar Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Tom Zanussi Cc: Zhang, Yanmin LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index dfc8bf6..d2ea9dd 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -656,6 +656,16 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session, goto out_filtered; dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); + /* + * Have we already created the kernel maps for the host machine? + * + * This should have happened earlier, when we processed the kernel MMAP + * events, but for older perf.data files there was no such thing, so do + * it now. + */ + if (cpumode == PERF_RECORD_MISC_KERNEL && + session->host_machine.vmlinux_maps[MAP__FUNCTION] == NULL) + machine__create_kernel_maps(&session->host_machine); thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION, self->ip.pid, self->ip.ip, al); diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 44a4df6..e672f2f 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -579,30 +579,6 @@ struct machine *machines__find(struct rb_root *self, pid_t pid) return default_machine; } -/* - * FIXME: Why repeatedly search for this? - */ -struct machine *machines__find_host(struct rb_root *self) -{ - struct rb_node **p = &self->rb_node; - struct rb_node *parent = NULL; - struct machine *machine; - pid_t pid = HOST_KERNEL_ID; - - while (*p != NULL) { - parent = *p; - machine = rb_entry(parent, struct machine, rb_node); - if (pid < machine->pid) - p = &(*p)->rb_left; - else if (pid > machine->pid) - p = &(*p)->rb_right; - else - return machine; - } - - return NULL; -} - struct machine *machines__findnew(struct rb_root *self, pid_t pid) { char path[PATH_MAX]; diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 5d353e7..71bc608 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -100,6 +100,7 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc self->repipe = repipe; self->ordered_samples.flush_limit = ULLONG_MAX; INIT_LIST_HEAD(&self->ordered_samples.samples_head); + machine__init(&self->host_machine, "", HOST_KERNEL_ID); if (mode == O_RDONLY) { if (perf_session__open(self, force) < 0) @@ -870,3 +871,10 @@ int perf_session__set_kallsyms_ref_reloc_sym(struct map **maps, return 0; } + +size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp) +{ + return __dsos__fprintf(&self->host_machine.kernel_dsos, fp) + + __dsos__fprintf(&self->host_machine.user_dsos, fp) + + machines__fprintf_dsos(&self->machines, fp); +} diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index f2b2c6a..eb9f179 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -25,6 +25,7 @@ struct perf_session { unsigned long mmap_window; struct rb_root threads; struct thread *last_match; + struct machine host_machine; struct rb_root machines; struct events_stats events_stats; struct rb_root stats_by_id; @@ -107,18 +108,22 @@ int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, static inline struct machine *perf_session__find_host_machine(struct perf_session *self) { - return machines__find_host(&self->machines); + return &self->host_machine; } static inline struct machine *perf_session__find_machine(struct perf_session *self, pid_t pid) { + if (pid == HOST_KERNEL_ID) + return &self->host_machine; return machines__find(&self->machines, pid); } static inline struct machine *perf_session__findnew_machine(struct perf_session *self, pid_t pid) { + if (pid == HOST_KERNEL_ID) + return &self->host_machine; return machines__findnew(&self->machines, pid); } @@ -126,14 +131,11 @@ static inline void perf_session__process_machines(struct perf_session *self, machine__process_t process) { + process(&self->host_machine, self); return machines__process(&self->machines, process, self); } -static inline -size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp) -{ - return machines__fprintf_dsos(&self->machines, fp); -} +size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp); static inline size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, FILE *fp, diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 4c0146a..994efdb 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1889,7 +1889,7 @@ struct dso *__dsos__findnew(struct list_head *head, const char *name) return dso; } -static size_t __dsos__fprintf(struct list_head *head, FILE *fp) +size_t __dsos__fprintf(struct list_head *head, FILE *fp) { struct dso *pos; size_t ret = 0; diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index a517c17..edff866 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -167,6 +167,8 @@ int machine__load_kallsyms(struct machine *self, const char *filename, int machine__load_vmlinux_path(struct machine *self, enum map_type type, symbol_filter_t filter); +size_t __dsos__fprintf(struct list_head *head, FILE *fp); + size_t machines__fprintf_dsos(struct rb_root *self, FILE *fp); size_t machines__fprintf_dsos_buildid(struct rb_root *self, FILE *fp, bool with_hits); -- cgit v0.10.2 From 232a5c948da5e23dff27e48180abf4a4238f7602 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 9 May 2010 20:28:10 -0300 Subject: perf report: Allow limiting the number of entries to print in callchains MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Works by adding a third parameter to the '-g' argument, after the graph type and minimum percentage, for example: [root@doppio linux-2.6-tip]# perf report -g fractal,0.5,2 Will show only the first two symbols where at least 0.5% of the samples took place. All the other symbols that don't fall outside these constraints will be put together in the last entry, prefixed with "[...]" and the total percentage for them. Suggested-by: Arjan van de Ven Acked-by: Arjan van de Ven Cc: Arjan van de Ven Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 5e2f47f..642a6d8 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -343,7 +343,7 @@ static int parse_callchain_opt(const struct option *opt __used, const char *arg, int unset) { - char *tok; + char *tok, *tok2; char *endptr; /* @@ -388,10 +388,13 @@ parse_callchain_opt(const struct option *opt __used, const char *arg, if (!tok) goto setup; + tok2 = strtok(NULL, ","); callchain_param.min_percent = strtod(tok, &endptr); if (tok == endptr) return -1; + if (tok2) + callchain_param.print_limit = strtod(tok2, &endptr); setup: if (register_callchain_param(&callchain_param) < 0) { fprintf(stderr, "Can't register callchain params\n"); diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index 0f4da09..1cba1f5 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h @@ -34,6 +34,7 @@ typedef void (*sort_chain_func_t)(struct rb_root *, struct callchain_node *, struct callchain_param { enum chain_mode mode; + u32 print_limit; double min_percent; sort_chain_func_t sort; }; diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index e0c8a72..0f154a5 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -333,6 +333,7 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct callchain_node *self, u64 remaining; size_t ret = 0; int i; + uint entries_printed = 0; if (callchain_param.mode == CHAIN_GRAPH_REL) new_total = self->children_hit; @@ -379,6 +380,8 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct callchain_node *self, new_depth_mask | (1 << depth), left_margin); node = next; + if (++entries_printed == callchain_param.print_limit) + break; } if (callchain_param.mode == CHAIN_GRAPH_REL && @@ -404,6 +407,7 @@ static size_t callchain__fprintf_graph(FILE *fp, struct callchain_node *self, bool printed = false; int i = 0; int ret = 0; + u32 entries_printed = 0; list_for_each_entry(chain, &self->val, list) { if (!i++ && sort__first_dimension == SORT_SYM) @@ -424,6 +428,9 @@ static size_t callchain__fprintf_graph(FILE *fp, struct callchain_node *self, ret += fprintf(fp, " %s\n", chain->ms.sym->name); else ret += fprintf(fp, " %p\n", (void *)(long)chain->ip); + + if (++entries_printed == callchain_param.print_limit) + break; } ret += __callchain__fprintf_graph(fp, self, total_samples, 1, 1, left_margin); @@ -462,6 +469,7 @@ static size_t hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self, struct rb_node *rb_node; struct callchain_node *chain; size_t ret = 0; + u32 entries_printed = 0; rb_node = rb_first(&self->sorted_chain); while (rb_node) { @@ -484,6 +492,8 @@ static size_t hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self, break; } ret += fprintf(fp, "\n"); + if (++entries_printed == callchain_param.print_limit) + break; rb_node = rb_next(rb_node); } -- cgit v0.10.2 From 7cfdee9f6791fe9ec288e75ee746790ebf3b6c3b Mon Sep 17 00:00:00 2001 From: Yauhen Kharuzhy Date: Wed, 19 Aug 2009 16:31:03 +0300 Subject: ARM: S3C2416: Add S3C2416-specific registers definitions Add macros for S3C2416 SoC support. Signed-off-by: Yauhen Kharuzhy [ben-linux@fluff.org: removed files that need changing] [ben-linux@fluff.org: Fix S3C2416_GPH0_TXD0 definition] Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/include/mach/dma.h b/arch/arm/mach-s3c2410/include/mach/dma.h index 08ac5f9..cf68136 100644 --- a/arch/arm/mach-s3c2410/include/mach/dma.h +++ b/arch/arm/mach-s3c2410/include/mach/dma.h @@ -54,7 +54,7 @@ enum dma_ch { #define DMACH_LOW_LEVEL (1<<28) /* use this to specifiy hardware ch no */ /* we have 4 dma channels */ -#ifndef CONFIG_CPU_S3C2443 +#if !defined(CONFIG_CPU_S3C2443) && !defined(CONFIG_CPU_S3C2416) #define S3C_DMA_CHANNELS (4) #else #define S3C_DMA_CHANNELS (6) diff --git a/arch/arm/mach-s3c2410/include/mach/irqs.h b/arch/arm/mach-s3c2410/include/mach/irqs.h index 6c12c63..c1b8ec0 100644 --- a/arch/arm/mach-s3c2410/include/mach/irqs.h +++ b/arch/arm/mach-s3c2410/include/mach/irqs.h @@ -115,6 +115,26 @@ #define IRQ_S3C2412_SDI S3C2410_IRQSUB(13) #define IRQ_S3C2412_CF S3C2410_IRQSUB(14) + +#define IRQ_S3C2416_EINT8t15 S3C2410_IRQ(5) +#define IRQ_S3C2416_DMA S3C2410_IRQ(17) +#define IRQ_S3C2416_UART3 S3C2410_IRQ(18) +#define IRQ_S3C2416_SDI1 S3C2410_IRQ(20) +#define IRQ_S3C2416_SDI0 S3C2410_IRQ(21) + +#define IRQ_S3C2416_LCD2 S3C2410_IRQSUB(15) +#define IRQ_S3C2416_LCD3 S3C2410_IRQSUB(16) +#define IRQ_S3C2416_LCD4 S3C2410_IRQSUB(17) +#define IRQ_S3C2416_DMA0 S3C2410_IRQSUB(18) +#define IRQ_S3C2416_DMA1 S3C2410_IRQSUB(19) +#define IRQ_S3C2416_DMA2 S3C2410_IRQSUB(20) +#define IRQ_S3C2416_DMA3 S3C2410_IRQSUB(21) +#define IRQ_S3C2416_DMA4 S3C2410_IRQSUB(22) +#define IRQ_S3C2416_DMA5 S3C2410_IRQSUB(23) +#define IRQ_S32416_WDT S3C2410_IRQSUB(27) +#define IRQ_S32416_AC97 S3C2410_IRQSUB(28) + + /* extra irqs for s3c2440 */ #define IRQ_S3C2440_CAM_C S3C2410_IRQSUB(11) /* S3C2443 too */ @@ -152,7 +172,7 @@ #define IRQ_S3C2443_WDT S3C2410_IRQSUB(27) #define IRQ_S3C2443_AC97 S3C2410_IRQSUB(28) -#ifdef CONFIG_CPU_S3C2443 +#if defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2416) #define NR_IRQS (IRQ_S3C2443_AC97+1) #else #define NR_IRQS (IRQ_S3C2440_AC97+1) diff --git a/arch/arm/mach-s3c2410/include/mach/regs-dsc.h b/arch/arm/mach-s3c2410/include/mach/regs-dsc.h index 3c3853c..98fd4a0 100644 --- a/arch/arm/mach-s3c2410/include/mach/regs-dsc.h +++ b/arch/arm/mach-s3c2410/include/mach/regs-dsc.h @@ -19,6 +19,42 @@ #define S3C2412_DSC1 S3C2410_GPIOREG(0xe0) #endif +#if defined(CONFIG_CPU_S3C2416) +#define S3C2416_DSC0 S3C2410_GPIOREG(0xc0) +#define S3C2416_DSC1 S3C2410_GPIOREG(0xc4) +#define S3C2416_DSC2 S3C2410_GPIOREG(0xc8) +#define S3C2416_DSC3 S3C2410_GPIOREG(0x110) + +#define S3C2416_SELECT_DSC0 (0 << 30) +#define S3C2416_SELECT_DSC1 (1 << 30) +#define S3C2416_SELECT_DSC2 (2 << 30) +#define S3C2416_SELECT_DSC3 (3 << 30) + +#define S3C2416_DSC_GETSHIFT(x) (x & 30) + +#define S3C2416_DSC0_CF (S3C2416_SELECT_DSC0 | 28) +#define S3C2416_DSC0_CF_5mA (0 << 28) +#define S3C2416_DSC0_CF_10mA (1 << 28) +#define S3C2416_DSC0_CF_15mA (2 << 28) +#define S3C2416_DSC0_CF_21mA (3 << 28) +#define S3C2416_DSC0_CF_MASK (3 << 28) + +#define S3C2416_DSC0_nRBE (S3C2416_SELECT_DSC0 | 26) +#define S3C2416_DSC0_nRBE_5mA (0 << 26) +#define S3C2416_DSC0_nRBE_10mA (1 << 26) +#define S3C2416_DSC0_nRBE_15mA (2 << 26) +#define S3C2416_DSC0_nRBE_21mA (3 << 26) +#define S3C2416_DSC0_nRBE_MASK (3 << 26) + +#define S3C2416_DSC0_nROE (S3C2416_SELECT_DSC0 | 24) +#define S3C2416_DSC0_nROE_5mA (0 << 24) +#define S3C2416_DSC0_nROE_10mA (1 << 24) +#define S3C2416_DSC0_nROE_15mA (2 << 24) +#define S3C2416_DSC0_nROE_21mA (3 << 24) +#define S3C2416_DSC0_nROE_MASK (3 << 24) + +#endif + #if defined(CONFIG_CPU_S3C244X) #define S3C2440_DSC0 S3C2410_GPIOREG(0xc4) diff --git a/arch/arm/mach-s3c2410/include/mach/regs-gpio.h b/arch/arm/mach-s3c2410/include/mach/regs-gpio.h index 821b966..a638423 100644 --- a/arch/arm/mach-s3c2410/include/mach/regs-gpio.h +++ b/arch/arm/mach-s3c2410/include/mach/regs-gpio.h @@ -610,29 +610,50 @@ #define S3C2410_GPHUP S3C2410_GPIOREG(0x78) #define S3C2410_GPH0_nCTS0 (0x02 << 0) +#define S3C2416_GPH0_TXD0 (0x02 << 0) #define S3C2410_GPH1_nRTS0 (0x02 << 2) +#define S3C2416_GPH1_RXD0 (0x02 << 2) #define S3C2410_GPH2_TXD0 (0x02 << 4) +#define S3C2416_GPH2_TXD1 (0x02 << 4) #define S3C2410_GPH3_RXD0 (0x02 << 6) +#define S3C2416_GPH3_RXD1 (0x02 << 6) #define S3C2410_GPH4_TXD1 (0x02 << 8) +#define S3C2416_GPH4_TXD2 (0x02 << 8) #define S3C2410_GPH5_RXD1 (0x02 << 10) +#define S3C2416_GPH5_RXD2 (0x02 << 10) #define S3C2410_GPH6_TXD2 (0x02 << 12) +#define S3C2416_GPH6_TXD3 (0x02 << 12) #define S3C2410_GPH6_nRTS1 (0x03 << 12) +#define S3C2416_GPH6_nRTS2 (0x03 << 12) #define S3C2410_GPH7_RXD2 (0x02 << 14) +#define S3C2416_GPH7_RXD3 (0x02 << 14) #define S3C2410_GPH7_nCTS1 (0x03 << 14) +#define S3C2416_GPH7_nCTS2 (0x03 << 14) #define S3C2410_GPH8_UCLK (0x02 << 16) +#define S3C2416_GPH8_nCTS0 (0x02 << 16) #define S3C2410_GPH9_CLKOUT0 (0x02 << 18) #define S3C2442_GPH9_nSPICS0 (0x03 << 18) +#define S3C2416_GPH9_nRTS0 (0x02 << 18) #define S3C2410_GPH10_CLKOUT1 (0x02 << 20) +#define S3C2416_GPH10_nCTS1 (0x02 << 20) + +#define S3C2416_GPH11_nRTS1 (0x02 << 22) + +#define S3C2416_GPH12_EXTUARTCLK (0x02 << 24) + +#define S3C2416_GPH13_CLKOUT0 (0x02 << 26) + +#define S3C2416_GPH14_CLKOUT1 (0x02 << 28) /* The S3C2412 and S3C2413 move the GPJ register set to after * GPH, which means all registers after 0x80 are now offset by 0x10 @@ -703,6 +724,7 @@ #define S3C2412_MISCCR_CLK1_CLKsrc (0<<8) #define S3C2410_MISCCR_USBSUSPND0 (1<<12) +#define S3C2416_MISCCR_SEL_SUSPND (1<<12) #define S3C2410_MISCCR_USBSUSPND1 (1<<13) #define S3C2410_MISCCR_nRSTCON (1<<16) @@ -712,6 +734,9 @@ #define S3C2410_MISCCR_nEN_SCLKE (1<<19) /* not 2412 */ #define S3C2410_MISCCR_SDSLEEP (7<<17) +#define S3C2416_MISCCR_FLT_I2C (1<<24) +#define S3C2416_MISCCR_HSSPI_EN2 (1<<31) + /* external interrupt control... */ /* S3C2410_EXTINT0 -> irq sense control for EINT0..EINT7 * S3C2410_EXTINT1 -> irq sense control for EINT8..EINT15 @@ -779,8 +804,11 @@ #define S3C2410_GSTATUS1_IDMASK (0xffff0000) #define S3C2410_GSTATUS1_2410 (0x32410000) #define S3C2410_GSTATUS1_2412 (0x32412001) +#define S3C2410_GSTATUS1_2416 (0x32416003) #define S3C2410_GSTATUS1_2440 (0x32440000) #define S3C2410_GSTATUS1_2442 (0x32440aaa) +/* some 2416 CPUs report this value also */ +#define S3C2410_GSTATUS1_2450 (0x32450003) #define S3C2410_GSTATUS2_WTRESET (1<<2) #define S3C2410_GSTATUS2_OFFRESET (1<<1) diff --git a/arch/arm/mach-s3c2410/include/mach/regs-irq.h b/arch/arm/mach-s3c2410/include/mach/regs-irq.h index de86ee8..0f07ba3 100644 --- a/arch/arm/mach-s3c2410/include/mach/regs-irq.h +++ b/arch/arm/mach-s3c2410/include/mach/regs-irq.h @@ -27,6 +27,16 @@ #define S3C2410_SUBSRCPND S3C2410_IRQREG(0x018) #define S3C2410_INTSUBMSK S3C2410_IRQREG(0x01C) +#define S3C2416_PRIORITY_MODE1 S3C2410_IRQREG(0x030) +#define S3C2416_PRIORITY_UPDATE1 S3C2410_IRQREG(0x034) +#define S3C2416_SRCPND2 S3C2410_IRQREG(0x040) +#define S3C2416_INTMOD2 S3C2410_IRQREG(0x044) +#define S3C2416_INTMSK2 S3C2410_IRQREG(0x048) +#define S3C2416_INTPND2 S3C2410_IRQREG(0x050) +#define S3C2416_INTOFFSET2 S3C2410_IRQREG(0x054) +#define S3C2416_PRIORITY_MODE2 S3C2410_IRQREG(0x070) +#define S3C2416_PRIORITY_UPDATE2 S3C2410_IRQREG(0x074) + /* mask: 0=enable, 1=disable * 1 bit EINT, 4=EINT4, 23=EINT23 * EINT0,1,2,3 are not handled here. diff --git a/arch/arm/mach-s3c2410/include/mach/regs-s3c2416-mem.h b/arch/arm/mach-s3c2410/include/mach/regs-s3c2416-mem.h new file mode 100644 index 0000000..2f31b74 --- /dev/null +++ b/arch/arm/mach-s3c2410/include/mach/regs-s3c2416-mem.h @@ -0,0 +1,30 @@ +/* arch/arm/mach-s3c2410/include/mach/regs-s3c2416-mem.h + * + * Copyright (c) 2009 Yauhen Kharuzhy , + * as part of OpenInkpot project + * Copyright (c) 2009 Promwad Innovation Company + * Yauhen Kharuzhy + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * S3C2416 memory register definitions +*/ + +#ifndef __ASM_ARM_REGS_S3C2416_MEM +#define __ASM_ARM_REGS_S3C2416_MEM + +#ifndef S3C2416_MEMREG +#define S3C2416_MEMREG(x) (S3C24XX_VA_MEMCTRL + (x)) +#endif + +#define S3C2416_BANKCFG S3C2416_MEMREG(0x00) +#define S3C2416_BANKCON1 S3C2416_MEMREG(0x04) +#define S3C2416_BANKCON2 S3C2416_MEMREG(0x08) +#define S3C2416_BANKCON3 S3C2416_MEMREG(0x0C) + +#define S3C2416_REFRESH S3C2416_MEMREG(0x10) +#define S3C2416_TIMEOUT S3C2416_MEMREG(0x14) + +#endif /* __ASM_ARM_REGS_S3C2416_MEM */ diff --git a/arch/arm/mach-s3c2410/include/mach/regs-s3c2416.h b/arch/arm/mach-s3c2410/include/mach/regs-s3c2416.h new file mode 100644 index 0000000..e443167 --- /dev/null +++ b/arch/arm/mach-s3c2410/include/mach/regs-s3c2416.h @@ -0,0 +1,24 @@ +/* arch/arm/mach-s3c2410/include/mach/regs-s3c2416.h + * + * Copyright (c) 2009 Yauhen Kharuzhy , + * as part of OpenInkpot project + * Copyright (c) 2009 Promwad Innovation Company + * Yauhen Kharuzhy + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * S3C2416 specific register definitions +*/ + +#ifndef __ASM_ARCH_REGS_S3C2416_H +#define __ASM_ARCH_REGS_S3C2416_H "s3c2416" + +#define S3C2416_SWRST (S3C24XX_VA_CLKPWR + 0x44) +#define S3C2416_SWRST_RESET (0x533C2416) + +/* see regs-power.h for the other registers in the power block. */ + +#endif /* __ASM_ARCH_REGS_S3C2416_H */ + -- cgit v0.10.2 From e561aacc70716ff59b9359ba8f010609ee757241 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 28 Apr 2010 18:10:02 +0900 Subject: ARM: SAMSUNG: Move S3C6400 PLL code to for re-use The S3C6400 EPLL code matches the S3C2416 and compatible SoCs, so move it from mach-s3c64xx into for easy reuse. Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c64xx/include/mach/pll.h b/arch/arm/mach-s3c64xx/include/mach/pll.h index 90bbd72..5ef0bb6 100644 --- a/arch/arm/mach-s3c64xx/include/mach/pll.h +++ b/arch/arm/mach-s3c64xx/include/mach/pll.h @@ -20,6 +20,7 @@ #define S3C6400_PLL_SDIV_SHIFT (0) #include +#include static inline unsigned long s3c6400_get_pll(unsigned long baseclk, u32 pllcon) @@ -37,38 +38,8 @@ static inline unsigned long s3c6400_get_pll(unsigned long baseclk, return (unsigned long)fvco; } -#define S3C6400_EPLL_MDIV_MASK ((1 << (23-16)) - 1) -#define S3C6400_EPLL_PDIV_MASK ((1 << (13-8)) - 1) -#define S3C6400_EPLL_SDIV_MASK ((1 << (2-0)) - 1) -#define S3C6400_EPLL_MDIV_SHIFT (16) -#define S3C6400_EPLL_PDIV_SHIFT (8) -#define S3C6400_EPLL_SDIV_SHIFT (0) -#define S3C6400_EPLL_KDIV_MASK (0xffff) - static inline unsigned long s3c6400_get_epll(unsigned long baseclk) { - unsigned long result; - u32 epll0 = __raw_readl(S3C_EPLL_CON0); - u32 epll1 = __raw_readl(S3C_EPLL_CON1); - u32 mdiv, pdiv, sdiv, kdiv; - u64 tmp; - - mdiv = (epll0 >> S3C6400_EPLL_MDIV_SHIFT) & S3C6400_EPLL_MDIV_MASK; - pdiv = (epll0 >> S3C6400_EPLL_PDIV_SHIFT) & S3C6400_EPLL_PDIV_MASK; - sdiv = (epll0 >> S3C6400_EPLL_SDIV_SHIFT) & S3C6400_EPLL_SDIV_MASK; - kdiv = epll1 & S3C6400_EPLL_KDIV_MASK; - - /* We need to multiple baseclk by mdiv (the integer part) and kdiv - * which is in 2^16ths, so shift mdiv up (does not overflow) and - * add kdiv before multiplying. The use of tmp is to avoid any - * overflows before shifting bac down into result when multipling - * by the mdiv and kdiv pair. - */ - - tmp = baseclk; - tmp *= (mdiv << 16) + kdiv; - do_div(tmp, (pdiv << sdiv)); - result = tmp >> 16; - - return result; + return s3c_get_pll6553x(baseclk, __raw_readl(S3C_EPLL_CON0), + __raw_readl(S3C_EPLL_CON1)); } diff --git a/arch/arm/plat-samsung/include/plat/pll6553x.h b/arch/arm/plat-samsung/include/plat/pll6553x.h new file mode 100644 index 0000000..b8b7e1d --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/pll6553x.h @@ -0,0 +1,51 @@ +/* arch/arm/plat-samsung/include/plat/pll6553x.h + * partially from arch/arm/mach-s3c64xx/include/mach/pll.h + * + * Copyright 2008 Openmoko, Inc. + * Copyright 2008 Simtec Electronics + * Ben Dooks + * http://armlinux.simtec.co.uk/ + * + * Samsung PLL6553x PLL code + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +/* S3C6400 and compatible (S3C2416, etc.) EPLL code */ + +#define PLL6553X_MDIV_MASK ((1 << (23-16)) - 1) +#define PLL6553X_PDIV_MASK ((1 << (13-8)) - 1) +#define PLL6553X_SDIV_MASK ((1 << (2-0)) - 1) +#define PLL6553X_MDIV_SHIFT (16) +#define PLL6553X_PDIV_SHIFT (8) +#define PLL6553X_SDIV_SHIFT (0) +#define PLL6553X_KDIV_MASK (0xffff) + +static inline unsigned long s3c_get_pll6553x(unsigned long baseclk, + u32 pll0, u32 pll1) +{ + unsigned long result; + u32 mdiv, pdiv, sdiv, kdiv; + u64 tmp; + + mdiv = (pll0 >> PLL6553X_MDIV_SHIFT) & PLL6553X_MDIV_MASK; + pdiv = (pll0 >> PLL6553X_PDIV_SHIFT) & PLL6553X_PDIV_MASK; + sdiv = (pll0 >> PLL6553X_SDIV_SHIFT) & PLL6553X_SDIV_MASK; + kdiv = pll1 & PLL6553X_KDIV_MASK; + + /* We need to multiple baseclk by mdiv (the integer part) and kdiv + * which is in 2^16ths, so shift mdiv up (does not overflow) and + * add kdiv before multiplying. The use of tmp is to avoid any + * overflows before shifting bac down into result when multipling + * by the mdiv and kdiv pair. + */ + + tmp = baseclk; + tmp *= (mdiv << 16) + kdiv; + do_div(tmp, (pdiv << sdiv)); + result = tmp >> 16; + + return result; +} -- cgit v0.10.2 From 4e04691bc600b53f6aab63404e58fae3bdf8e310 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 28 Apr 2010 12:58:13 +0900 Subject: ARM: SAMSUNG: Add s3c_disable_clocks() and tidy init+disable usage Add s3c_disable_clocks() and change the clock registration code to use the s3c_register_clocks() followed by s3c_disable_clocks() instead of the loops it was using. Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2443/clock.c b/arch/arm/mach-s3c2443/clock.c index 62cd4ea..76d8d66 100644 --- a/arch/arm/mach-s3c2443/clock.c +++ b/arch/arm/mach-s3c2443/clock.c @@ -492,7 +492,7 @@ static struct clk clk_prediv = { /* standard clock definitions */ -static struct clk init_clocks_disable[] = { +static struct clk init_clocks_off[] = { { .name = "nand", .id = -1, @@ -761,9 +761,7 @@ void __init_or_cpufreq s3c2443_setup_clocks(void) void __init s3c2443_init_clocks(int xtal) { - struct clk *clkp; unsigned long epllcon = __raw_readl(S3C2443_EPLLCON); - int ret; int ptr; /* s3c2443 parents h and p clocks from prediv */ @@ -774,15 +772,7 @@ void __init s3c2443_init_clocks(int xtal) s3c2443_setup_clocks(); s3c2443_clk_initparents(); - for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) { - clkp = clks[ptr]; - - ret = s3c24xx_register_clock(clkp); - if (ret < 0) { - printk(KERN_ERR "Failed to register clock %s (%d)\n", - clkp->name, ret); - } - } + s3c24xx_register_clocks(clks, ARRAY_SIZE(clks)); for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) s3c_register_clksrc(clksrcs[ptr], 1); @@ -819,17 +809,8 @@ void __init s3c2443_init_clocks(int xtal) /* install (and disable) the clocks we do not need immediately */ - clkp = init_clocks_disable; - for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) { - - ret = s3c24xx_register_clock(clkp); - if (ret < 0) { - printk(KERN_ERR "Failed to register clock %s (%d)\n", - clkp->name, ret); - } - - (clkp->enable)(clkp, 0); - } + s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); + s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); s3c_pwmclk_init(); } diff --git a/arch/arm/plat-s3c24xx/s3c2410-clock.c b/arch/arm/plat-s3c24xx/s3c2410-clock.c index b61bdb7..9ecc5d9 100644 --- a/arch/arm/plat-s3c24xx/s3c2410-clock.c +++ b/arch/arm/plat-s3c24xx/s3c2410-clock.c @@ -87,7 +87,7 @@ static int s3c2410_upll_enable(struct clk *clk, int enable) /* standard clock definitions */ -static struct clk init_clocks_disable[] = { +static struct clk init_clocks_off[] = { { .name = "nand", .id = -1, @@ -249,17 +249,8 @@ int __init s3c2410_baseclk_add(void) /* install (and disable) the clocks we do not need immediately */ - clkp = init_clocks_disable; - for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) { - - ret = s3c24xx_register_clock(clkp); - if (ret < 0) { - printk(KERN_ERR "Failed to register clock %s (%d)\n", - clkp->name, ret); - } - - s3c2410_clkcon_enable(clkp, 0); - } + s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); + s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); /* show the clock-slow value */ diff --git a/arch/arm/plat-samsung/clock.c b/arch/arm/plat-samsung/clock.c index 1b25c9d..8bf79f3 100644 --- a/arch/arm/plat-samsung/clock.c +++ b/arch/arm/plat-samsung/clock.c @@ -376,6 +376,21 @@ void __init s3c_register_clocks(struct clk *clkp, int nr_clks) } } +/** + * s3c_disable_clocks() - disable an array of clocks + * @clkp: Pointer to the first clock in the array. + * @nr_clks: Number of clocks to register. + * + * for internal use only at initialisation time. disable the clocks in the + * @clkp array. + */ + +void __init s3c_disable_clocks(struct clk *clkp, int nr_clks) +{ + for (; nr_clks > 0; nr_clks--, clkp++) + (clkp->enable)(clkp, 0); +} + /* initalise all the clocks */ int __init s3c24xx_register_baseclocks(unsigned long xtal) diff --git a/arch/arm/plat-samsung/include/plat/clock.h b/arch/arm/plat-samsung/include/plat/clock.h index 60b6269..12caf48 100644 --- a/arch/arm/plat-samsung/include/plat/clock.h +++ b/arch/arm/plat-samsung/include/plat/clock.h @@ -91,6 +91,7 @@ extern int s3c24xx_register_clock(struct clk *clk); extern int s3c24xx_register_clocks(struct clk **clk, int nr_clks); extern void s3c_register_clocks(struct clk *clk, int nr_clks); +extern void s3c_disable_clocks(struct clk *clkp, int nr_clks); extern int s3c24xx_register_baseclocks(unsigned long xtal); -- cgit v0.10.2 From f1290a49c5496521360a3e40d8bc766aceee65e5 Mon Sep 17 00:00:00 2001 From: Yauhen Kharuzhy Date: Wed, 28 Apr 2010 18:09:01 +0900 Subject: ARM: S3C2416: Add arch support Add arch/arm/mach-s3c2416 for support of the Samsung S3C2416 SoC. This patch adds support of the S3C2416 SoC, clocks, timers, and initial IRQ support (without support of secondary set of registers). Signed-off-by: Yauhen Kharuzhy [ben-linux@fluff.org: removed files to be reworked, fixed conflicts] [ben-linux@fluff.org: use s3c2443 reset instead of specific reset code] Signed-off-by: Ben Dooks diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 92622eb..6785c33 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -647,7 +647,7 @@ config ARCH_SA1100 Support for StrongARM 11x0 based boards. config ARCH_S3C2410 - bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442, S3C2443" + bool "Samsung S3C2410, S3C2412, S3C2413, S3C2416, S3C2440, S3C2442, S3C2443" select GENERIC_GPIO select ARCH_HAS_CPUFREQ select HAVE_CLK @@ -892,6 +892,7 @@ if ARCH_S3C2410 source "arch/arm/mach-s3c2400/Kconfig" source "arch/arm/mach-s3c2410/Kconfig" source "arch/arm/mach-s3c2412/Kconfig" +source "arch/arm/mach-s3c2416/Kconfig" source "arch/arm/mach-s3c2440/Kconfig" source "arch/arm/mach-s3c2443/Kconfig" endif diff --git a/arch/arm/Makefile b/arch/arm/Makefile index ed820e7..1594739 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -160,7 +160,7 @@ machine-$(CONFIG_ARCH_PNX4008) := pnx4008 machine-$(CONFIG_ARCH_PXA) := pxa machine-$(CONFIG_ARCH_REALVIEW) := realview machine-$(CONFIG_ARCH_RPC) := rpc -machine-$(CONFIG_ARCH_S3C2410) := s3c2410 s3c2400 s3c2412 s3c2440 s3c2443 +machine-$(CONFIG_ARCH_S3C2410) := s3c2410 s3c2400 s3c2412 s3c2416 s3c2440 s3c2443 machine-$(CONFIG_ARCH_S3C24A0) := s3c24a0 machine-$(CONFIG_ARCH_S3C64XX) := s3c64xx machine-$(CONFIG_ARCH_S5P6440) := s5p6440 diff --git a/arch/arm/mach-s3c2412/Kconfig b/arch/arm/mach-s3c2412/Kconfig index 9a8c065..cef6a65 100644 --- a/arch/arm/mach-s3c2412/Kconfig +++ b/arch/arm/mach-s3c2412/Kconfig @@ -16,7 +16,8 @@ config CPU_S3C2412 config CPU_S3C2412_ONLY bool depends on ARCH_S3C2410 && !CPU_S3C2400 && !CPU_S3C2410 && \ - !CPU_S3C2440 && !CPU_S3C2442 && !CPU_S3C2443 && CPU_S3C2412 + !CPU_2416 && !CPU_S3C2440 && !CPU_S3C2442 && \ + !CPU_S3C2443 && CPU_S3C2412 default y if CPU_S3C2412 config S3C2412_DMA diff --git a/arch/arm/mach-s3c2416/Kconfig b/arch/arm/mach-s3c2416/Kconfig new file mode 100644 index 0000000..cc320f6 --- /dev/null +++ b/arch/arm/mach-s3c2416/Kconfig @@ -0,0 +1,25 @@ +# arch/arm/mach-s3c2416/Kconfig +# +# Copyright 2009 Yauhen Kharuzhy +# +# Licensed under GPLv2 + +config CPU_S3C2416 + bool + depends on ARCH_S3C2410 + select CPU_ARM926T + select S3C2416_DMA if S3C2410_DMA + select CPU_LLSERIAL_S3C2440 + help + Support for the S3C2416 SoC from the S3C24XX line + +config S3C2416_DMA + bool + depends on CPU_S3C2416 + help + Internal config node for S3C2416 DMA support + +menu "S3C2416 Machines" + + +endmenu diff --git a/arch/arm/mach-s3c2416/Makefile b/arch/arm/mach-s3c2416/Makefile new file mode 100644 index 0000000..34bb70d --- /dev/null +++ b/arch/arm/mach-s3c2416/Makefile @@ -0,0 +1,18 @@ +# arch/arm/mach-s3c2416/Makefile +# +# Copyright 2009 Yauhen Kharuzhy +# +# Licensed under GPLv2 + +obj-y := +obj-m := +obj-n := +obj- := + +obj-$(CONFIG_CPU_S3C2416) += s3c2416.o +obj-$(CONFIG_CPU_S3C2416) += irq.o + +#obj-$(CONFIG_S3C2416_DMA) += dma.o + +# Machine support + diff --git a/arch/arm/mach-s3c2416/irq.c b/arch/arm/mach-s3c2416/irq.c new file mode 100644 index 0000000..89f521d --- /dev/null +++ b/arch/arm/mach-s3c2416/irq.c @@ -0,0 +1,254 @@ +/* linux/arch/arm/mach-s3c2416/irq.c + * + * Copyright (c) 2009 Yauhen Kharuzhy , + * as part of OpenInkpot project + * Copyright (c) 2009 Promwad Innovation Company + * Yauhen Kharuzhy + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include + +#include +#include +#include + +#define INTMSK(start, end) ((1 << ((end) + 1 - (start))) - 1) + +static inline void s3c2416_irq_demux(unsigned int irq, unsigned int len) +{ + unsigned int subsrc, submsk; + unsigned int end; + + /* read the current pending interrupts, and the mask + * for what it is available */ + + subsrc = __raw_readl(S3C2410_SUBSRCPND); + submsk = __raw_readl(S3C2410_INTSUBMSK); + + subsrc &= ~submsk; + subsrc >>= (irq - S3C2410_IRQSUB(0)); + subsrc &= (1 << len)-1; + + end = len + irq; + + for (; irq < end && subsrc; irq++) { + if (subsrc & 1) + generic_handle_irq(irq); + + subsrc >>= 1; + } +} + +/* WDT/AC97 sub interrupts */ + +static void s3c2416_irq_demux_wdtac97(unsigned int irq, struct irq_desc *desc) +{ + s3c2416_irq_demux(IRQ_S3C2443_WDT, 4); +} + +#define INTMSK_WDTAC97 (1UL << (IRQ_WDT - IRQ_EINT0)) +#define SUBMSK_WDTAC97 INTMSK(IRQ_S3C2443_WDT, IRQ_S3C2443_AC97) + +static void s3c2416_irq_wdtac97_mask(unsigned int irqno) +{ + s3c_irqsub_mask(irqno, INTMSK_WDTAC97, SUBMSK_WDTAC97); +} + +static void s3c2416_irq_wdtac97_unmask(unsigned int irqno) +{ + s3c_irqsub_unmask(irqno, INTMSK_WDTAC97); +} + +static void s3c2416_irq_wdtac97_ack(unsigned int irqno) +{ + s3c_irqsub_maskack(irqno, INTMSK_WDTAC97, SUBMSK_WDTAC97); +} + +static struct irq_chip s3c2416_irq_wdtac97 = { + .mask = s3c2416_irq_wdtac97_mask, + .unmask = s3c2416_irq_wdtac97_unmask, + .ack = s3c2416_irq_wdtac97_ack, +}; + + +/* LCD sub interrupts */ + +static void s3c2416_irq_demux_lcd(unsigned int irq, struct irq_desc *desc) +{ + s3c2416_irq_demux(IRQ_S3C2443_LCD1, 4); +} + +#define INTMSK_LCD (1UL << (IRQ_LCD - IRQ_EINT0)) +#define SUBMSK_LCD INTMSK(IRQ_S3C2443_LCD1, IRQ_S3C2443_LCD4) + +static void s3c2416_irq_lcd_mask(unsigned int irqno) +{ + s3c_irqsub_mask(irqno, INTMSK_LCD, SUBMSK_LCD); +} + +static void s3c2416_irq_lcd_unmask(unsigned int irqno) +{ + s3c_irqsub_unmask(irqno, INTMSK_LCD); +} + +static void s3c2416_irq_lcd_ack(unsigned int irqno) +{ + s3c_irqsub_maskack(irqno, INTMSK_LCD, SUBMSK_LCD); +} + +static struct irq_chip s3c2416_irq_lcd = { + .mask = s3c2416_irq_lcd_mask, + .unmask = s3c2416_irq_lcd_unmask, + .ack = s3c2416_irq_lcd_ack, +}; + + +/* DMA sub interrupts */ + +static void s3c2416_irq_demux_dma(unsigned int irq, struct irq_desc *desc) +{ + s3c2416_irq_demux(IRQ_S3C2443_DMA0, 6); +} + +#define INTMSK_DMA (1UL << (IRQ_S3C2443_DMA - IRQ_EINT0)) +#define SUBMSK_DMA INTMSK(IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5) + + +static void s3c2416_irq_dma_mask(unsigned int irqno) +{ + s3c_irqsub_mask(irqno, INTMSK_DMA, SUBMSK_DMA); +} + +static void s3c2416_irq_dma_unmask(unsigned int irqno) +{ + s3c_irqsub_unmask(irqno, INTMSK_DMA); +} + +static void s3c2416_irq_dma_ack(unsigned int irqno) +{ + s3c_irqsub_maskack(irqno, INTMSK_DMA, SUBMSK_DMA); +} + +static struct irq_chip s3c2416_irq_dma = { + .mask = s3c2416_irq_dma_mask, + .unmask = s3c2416_irq_dma_unmask, + .ack = s3c2416_irq_dma_ack, +}; + + +/* UART3 sub interrupts */ + +static void s3c2416_irq_demux_uart3(unsigned int irq, struct irq_desc *desc) +{ + s3c2416_irq_demux(IRQ_S3C2443_UART3, 3); +} + +#define INTMSK_UART3 (1UL << (IRQ_S3C2443_UART3 - IRQ_EINT0)) +#define SUBMSK_UART3 (0xf << (IRQ_S3C2443_RX3 - S3C2410_IRQSUB(0))) + + +static void s3c2416_irq_uart3_mask(unsigned int irqno) +{ + s3c_irqsub_mask(irqno, INTMSK_UART3, SUBMSK_UART3); +} + +static void s3c2416_irq_uart3_unmask(unsigned int irqno) +{ + s3c_irqsub_unmask(irqno, INTMSK_UART3); +} + +static void s3c2416_irq_uart3_ack(unsigned int irqno) +{ + s3c_irqsub_maskack(irqno, INTMSK_UART3, SUBMSK_UART3); +} + +static struct irq_chip s3c2416_irq_uart3 = { + .mask = s3c2416_irq_uart3_mask, + .unmask = s3c2416_irq_uart3_unmask, + .ack = s3c2416_irq_uart3_ack, +}; + + +/* IRQ initialisation code */ + +static int __init s3c2416_add_sub(unsigned int base, + void (*demux)(unsigned int, + struct irq_desc *), + struct irq_chip *chip, + unsigned int start, unsigned int end) +{ + unsigned int irqno; + + set_irq_chip(base, &s3c_irq_level_chip); + set_irq_handler(base, handle_level_irq); + set_irq_chained_handler(base, demux); + + for (irqno = start; irqno <= end; irqno++) { + set_irq_chip(irqno, chip); + set_irq_handler(irqno, handle_level_irq); + set_irq_flags(irqno, IRQF_VALID); + } + + return 0; +} + +static int __init s3c2416_irq_add(struct sys_device *sysdev) +{ + printk(KERN_INFO "S3C2416: IRQ Support\n"); + + s3c2416_add_sub(IRQ_LCD, s3c2416_irq_demux_lcd, &s3c2416_irq_lcd, + IRQ_S3C2443_LCD2, IRQ_S3C2443_LCD4); + + s3c2416_add_sub(IRQ_S3C2443_DMA, s3c2416_irq_demux_dma, + &s3c2416_irq_dma, IRQ_S3C2443_DMA0, IRQ_S3C2443_DMA5); + + s3c2416_add_sub(IRQ_S3C2443_UART3, s3c2416_irq_demux_uart3, + &s3c2416_irq_uart3, + IRQ_S3C2443_RX3, IRQ_S3C2443_ERR3); + + s3c2416_add_sub(IRQ_WDT, s3c2416_irq_demux_wdtac97, + &s3c2416_irq_wdtac97, + IRQ_S3C2443_WDT, IRQ_S3C2443_AC97); + + return 0; +} + +static struct sysdev_driver s3c2416_irq_driver = { + .add = s3c2416_irq_add, +}; + +static int __init s3c2416_irq_init(void) +{ + return sysdev_driver_register(&s3c2416_sysclass, &s3c2416_irq_driver); +} + +arch_initcall(s3c2416_irq_init); + diff --git a/arch/arm/mach-s3c2416/s3c2416.c b/arch/arm/mach-s3c2416/s3c2416.c new file mode 100644 index 0000000..6165dc7 --- /dev/null +++ b/arch/arm/mach-s3c2416/s3c2416.c @@ -0,0 +1,115 @@ +/* linux/arch/arm/mach-s3c2416/s3c2416.c + * + * Copyright (c) 2009 Yauhen Kharuzhy , + * as part of OpenInkpot project + * Copyright (c) 2009 Promwad Innovation Company + * Yauhen Kharuzhy + * + * Samsung S3C2416 Mobile CPU support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +static struct map_desc s3c2416_iodesc[] __initdata = { + IODESC_ENT(WATCHDOG), + IODESC_ENT(CLKPWR), + IODESC_ENT(TIMER), +}; + +struct sysdev_class s3c2416_sysclass = { + .name = "s3c2416-core", +}; + +static struct sys_device s3c2416_sysdev = { + .cls = &s3c2416_sysclass, +}; + +static void s3c2416_hard_reset(void) +{ + __raw_writel(S3C2443_SWRST_RESET, S3C2443_SWRST); +} + +int __init s3c2416_init(void) +{ + printk(KERN_INFO "S3C2416: Initializing architecture\n"); + + s3c24xx_reset_hook = s3c2416_hard_reset; + /* s3c24xx_idle = s3c2416_idle; */ + + /* change WDT IRQ number */ + s3c_device_wdt.resource[1].start = IRQ_S3C2443_WDT; + s3c_device_wdt.resource[1].end = IRQ_S3C2443_WDT; + + return sysdev_register(&s3c2416_sysdev); +} + +void __init s3c2416_init_uarts(struct s3c2410_uartcfg *cfg, int no) +{ + s3c24xx_init_uartdevs("s3c2440-uart", s3c2410_uart_resources, cfg, no); + + s3c_device_nand.name = "s3c2416-nand"; +} + +/* s3c2416_map_io + * + * register the standard cpu IO areas, and any passed in from the + * machine specific initialisation. + */ + +void __init s3c2416_map_io(void) +{ + iotable_init(s3c2416_iodesc, ARRAY_SIZE(s3c2416_iodesc)); +} + +/* need to register class before we actually register the device, and + * we also need to ensure that it has been initialised before any of the + * drivers even try to use it (even if not on an s3c2416 based system) + * as a driver which may support both 2443 and 2440 may try and use it. +*/ + +static int __init s3c2416_core_init(void) +{ + return sysdev_class_register(&s3c2416_sysclass); +} + +core_initcall(s3c2416_core_init); diff --git a/arch/arm/plat-s3c24xx/cpu.c b/arch/arm/plat-s3c24xx/cpu.c index 9ca64df..494f4f3 100644 --- a/arch/arm/plat-s3c24xx/cpu.c +++ b/arch/arm/plat-s3c24xx/cpu.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #include @@ -57,6 +58,7 @@ static const char name_s3c2400[] = "S3C2400"; static const char name_s3c2410[] = "S3C2410"; static const char name_s3c2412[] = "S3C2412"; +static const char name_s3c2416[] = "S3C2416"; static const char name_s3c2440[] = "S3C2440"; static const char name_s3c2442[] = "S3C2442"; static const char name_s3c2442b[] = "S3C2442B"; @@ -137,6 +139,15 @@ static struct cpu_table cpu_ids[] __initdata = { .init = s3c2412_init, .name = name_s3c2412, }, + { /* a strange version of the s3c2416 */ + .idcode = 0x32450003, + .idmask = 0xffffffff, + .map_io = s3c2416_map_io, + .init_clocks = s3c2416_init_clocks, + .init_uarts = s3c2416_init_uarts, + .init = s3c2416_init, + .name = name_s3c2416, + }, { .idcode = 0x32443001, .idmask = 0xffffffff, @@ -172,6 +183,8 @@ static unsigned long s3c24xx_read_idcode_v5(void) { #if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413) return __raw_readl(S3C2412_GSTATUS1); +#elif defined(CONFIG_CPU_S3C2416) + return __raw_readl(S3C24XX_GSTATUS1); #else return 1UL; /* don't look like an 2400 */ #endif diff --git a/arch/arm/plat-s3c24xx/include/plat/s3c2416.h b/arch/arm/plat-s3c24xx/include/plat/s3c2416.h new file mode 100644 index 0000000..dc3c090 --- /dev/null +++ b/arch/arm/plat-s3c24xx/include/plat/s3c2416.h @@ -0,0 +1,31 @@ +/* linux/include/asm-arm/plat-s3c24xx/s3c2443.h + * + * Copyright (c) 2009 Yauhen Kharuzhy + * + * Header file for s3c2416 cpu support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifdef CONFIG_CPU_S3C2416 + +struct s3c2410_uartcfg; + +extern int s3c2416_init(void); + +extern void s3c2416_map_io(void); + +extern void s3c2416_init_uarts(struct s3c2410_uartcfg *cfg, int no); + +extern void s3c2416_init_clocks(int xtal); + +extern int s3c2416_baseclk_add(void); + +#else +#define s3c2416_init_clocks NULL +#define s3c2416_init_uarts NULL +#define s3c2416_map_io NULL +#define s3c2416_init NULL +#endif diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h index d316b4a..5dbeb79 100644 --- a/arch/arm/plat-samsung/include/plat/cpu.h +++ b/arch/arm/plat-samsung/include/plat/cpu.h @@ -73,6 +73,7 @@ extern struct sys_timer s3c24xx_timer; extern struct sysdev_class s3c2410_sysclass; extern struct sysdev_class s3c2410a_sysclass; extern struct sysdev_class s3c2412_sysclass; +extern struct sysdev_class s3c2416_sysclass; extern struct sysdev_class s3c2440_sysclass; extern struct sysdev_class s3c2442_sysclass; extern struct sysdev_class s3c2443_sysclass; -- cgit v0.10.2 From d24131470f3def698683144cf1e81ee0f4f9c0b8 Mon Sep 17 00:00:00 2001 From: Yauhen Kharuzhy Date: Wed, 19 Aug 2009 16:31:07 +0300 Subject: ARM: S3C2416: Add initial support of SMDK2416 Add support of SMDK2416 development board. Signed-off-by: Yauhen Kharuzhy Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2416/Kconfig b/arch/arm/mach-s3c2416/Kconfig index cc320f6..528f273 100644 --- a/arch/arm/mach-s3c2416/Kconfig +++ b/arch/arm/mach-s3c2416/Kconfig @@ -21,5 +21,11 @@ config S3C2416_DMA menu "S3C2416 Machines" +config MACH_SMDK2416 + bool "SMDK2416" + select CPU_S3C2416 + select S3C_DEV_HSMMC + help + Say Y here if you are using an SMDK2416 endmenu diff --git a/arch/arm/mach-s3c2416/Makefile b/arch/arm/mach-s3c2416/Makefile index 34bb70d..9183e81 100644 --- a/arch/arm/mach-s3c2416/Makefile +++ b/arch/arm/mach-s3c2416/Makefile @@ -16,3 +16,4 @@ obj-$(CONFIG_CPU_S3C2416) += irq.o # Machine support +obj-$(CONFIG_MACH_SMDK2416) += mach-smdk2416.o diff --git a/arch/arm/mach-s3c2416/mach-smdk2416.c b/arch/arm/mach-s3c2416/mach-smdk2416.c new file mode 100644 index 0000000..8c9aed6 --- /dev/null +++ b/arch/arm/mach-s3c2416/mach-smdk2416.c @@ -0,0 +1,144 @@ +/* linux/arch/arm/mach-s3c2416/mach-hanlin_v3c.c + * + * Copyright (c) 2009 Yauhen Kharuzhy , + * as part of OpenInkpot project + * Copyright (c) 2009 Promwad Innovation Company + * Yauhen Kharuzhy + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +static struct map_desc smdk2416_iodesc[] __initdata = { + /* ISA IO Space map (memory space selected by A24) */ + + { + .virtual = (u32)S3C24XX_VA_ISA_WORD, + .pfn = __phys_to_pfn(S3C2410_CS2), + .length = 0x10000, + .type = MT_DEVICE, + }, { + .virtual = (u32)S3C24XX_VA_ISA_WORD + 0x10000, + .pfn = __phys_to_pfn(S3C2410_CS2 + (1<<24)), + .length = SZ_4M, + .type = MT_DEVICE, + }, { + .virtual = (u32)S3C24XX_VA_ISA_BYTE, + .pfn = __phys_to_pfn(S3C2410_CS2), + .length = 0x10000, + .type = MT_DEVICE, + }, { + .virtual = (u32)S3C24XX_VA_ISA_BYTE + 0x10000, + .pfn = __phys_to_pfn(S3C2410_CS2 + (1<<24)), + .length = SZ_4M, + .type = MT_DEVICE, + } +}; + +#define UCON (S3C2410_UCON_DEFAULT | \ + S3C2440_UCON_PCLK | \ + S3C2443_UCON_RXERR_IRQEN) + +#define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE) + +#define UFCON (S3C2410_UFCON_RXTRIG8 | \ + S3C2410_UFCON_FIFOMODE | \ + S3C2440_UFCON_TXTRIG16) + +static struct s3c2410_uartcfg smdk2416_uartcfgs[] __initdata = { + [0] = { + .hwport = 0, + .flags = 0, + .ucon = UCON, + .ulcon = ULCON, + .ufcon = UFCON, + }, + [1] = { + .hwport = 1, + .flags = 0, + .ucon = UCON, + .ulcon = ULCON, + .ufcon = UFCON, + }, + /* IR port */ + [2] = { + .hwport = 2, + .flags = 0, + .ucon = UCON, + .ulcon = ULCON | 0x50, + .ufcon = UFCON, + } +}; + +static struct platform_device *smdk2416_devices[] __initdata = { + &s3c_device_wdt, + &s3c_device_i2c0, + &s3c_device_hsmmc0, +}; + +static void __init smdk2416_map_io(void) +{ + + s3c24xx_init_io(smdk2416_iodesc, ARRAY_SIZE(smdk2416_iodesc)); + s3c24xx_init_clocks(12000000); + s3c24xx_init_uarts(smdk2416_uartcfgs, ARRAY_SIZE(smdk2416_uartcfgs)); + +} + +static void __init smdk2416_machine_init(void) +{ + s3c_i2c0_set_platdata(NULL); + + platform_add_devices(smdk2416_devices, ARRAY_SIZE(smdk2416_devices)); + smdk_machine_init(); +} + +MACHINE_START(SMDK2416, "SMDK2416") + /* Maintainer: Yauhen Kharuzhy */ + .phys_io = S3C2410_PA_UART, + .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, + .boot_params = S3C2410_SDRAM_PA + 0x100, + + .init_irq = s3c24xx_init_irq, + .map_io = smdk2416_map_io, + .init_machine = smdk2416_machine_init, + .timer = &s3c24xx_timer, +MACHINE_END -- cgit v0.10.2 From d11a7d7100123d178821f82ecc11ba2d9d6e97c8 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 28 Apr 2010 18:00:07 +0900 Subject: ARM: S3C24XX: Identify S3C2416 if S3C2412/S3C2413 built in Extend the ARMv5 ID code to deal with S3C2416 being built with S3C2412/S3C2413 enabled, as these have their ID registers in a different place. Signed-off-by: Ben Dooks diff --git a/arch/arm/plat-s3c24xx/cpu.c b/arch/arm/plat-s3c24xx/cpu.c index 494f4f3..32db856 100644 --- a/arch/arm/plat-s3c24xx/cpu.c +++ b/arch/arm/plat-s3c24xx/cpu.c @@ -181,10 +181,18 @@ static struct map_desc s3c_iodesc[] __initdata = { static unsigned long s3c24xx_read_idcode_v5(void) { +#if defined(CONFIG_CPU_S3C2416) + /* s3c2416 is v5, with S3C24XX_GSTATUS1 instead of S3C2412_GSTATUS1 */ + + u32 gs = __raw_readl(S3C24XX_GSTATUS1); + + /* test for s3c2416 or similar device */ + if ((gs >> 16) == 0x3245) + return gs; +#endif + #if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413) return __raw_readl(S3C2412_GSTATUS1); -#elif defined(CONFIG_CPU_S3C2416) - return __raw_readl(S3C24XX_GSTATUS1); #else return 1UL; /* don't look like an 2400 */ #endif -- cgit v0.10.2 From af337f3e633a198034a99450416257ddf2307497 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 28 Apr 2010 18:03:57 +0900 Subject: ARM: S3C2443: Move parts of the clock code to common clock file To share code with some of the newer parts such as the S3C2416, move parts of arch/arm/mach-s3c2443/clock.c to a common file called arch/arm/plat-s3c24xx/s3c2443-clock.c. Update the build configuration to deal with this new file. Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2443/Kconfig b/arch/arm/mach-s3c2443/Kconfig index 698140a..4fef723 100644 --- a/arch/arm/mach-s3c2443/Kconfig +++ b/arch/arm/mach-s3c2443/Kconfig @@ -8,6 +8,7 @@ config CPU_S3C2443 select S3C2443_DMA if S3C2410_DMA select CPU_LLSERIAL_S3C2440 select SAMSUNG_CLKSRC + select S3C2443_CLOCK help Support for the S3C2443 SoC from the S3C24XX line diff --git a/arch/arm/mach-s3c2443/clock.c b/arch/arm/mach-s3c2443/clock.c index 76d8d66..83b1aa6 100644 --- a/arch/arm/mach-s3c2443/clock.c +++ b/arch/arm/mach-s3c2443/clock.c @@ -21,6 +21,7 @@ */ #include + #include #include #include @@ -54,111 +55,13 @@ * set the correct muxing at initialisation */ -static int s3c2443_gate(void __iomem *reg, struct clk *clk, int enable) -{ - u32 ctrlbit = clk->ctrlbit; - u32 con = __raw_readl(reg); - - if (enable) - con |= ctrlbit; - else - con &= ~ctrlbit; - - __raw_writel(con, reg); - return 0; -} - -static int s3c2443_clkcon_enable_h(struct clk *clk, int enable) -{ - return s3c2443_gate(S3C2443_HCLKCON, clk, enable); -} - -static int s3c2443_clkcon_enable_p(struct clk *clk, int enable) -{ - return s3c2443_gate(S3C2443_PCLKCON, clk, enable); -} - -static int s3c2443_clkcon_enable_s(struct clk *clk, int enable) -{ - return s3c2443_gate(S3C2443_SCLKCON, clk, enable); -} - /* clock selections */ -/* mpllref is a direct descendant of clk_xtal by default, but it is not - * elided as the EPLL can be either sourced by the XTAL or EXTCLK and as - * such directly equating the two source clocks is impossible. - */ -static struct clk clk_mpllref = { - .name = "mpllref", - .parent = &clk_xtal, - .id = -1, -}; - static struct clk clk_i2s_ext = { .name = "i2s-ext", .id = -1, }; -static struct clk *clk_epllref_sources[] = { - [0] = &clk_mpllref, - [1] = &clk_mpllref, - [2] = &clk_xtal, - [3] = &clk_ext, -}; - -static struct clksrc_clk clk_epllref = { - .clk = { - .name = "epllref", - .id = -1, - }, - .sources = &(struct clksrc_sources) { - .sources = clk_epllref_sources, - .nr_sources = ARRAY_SIZE(clk_epllref_sources), - }, - .reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 7 }, -}; - -static unsigned long s3c2443_getrate_mdivclk(struct clk *clk) -{ - unsigned long parent_rate = clk_get_rate(clk->parent); - unsigned long div = __raw_readl(S3C2443_CLKDIV0); - - div &= S3C2443_CLKDIV0_EXTDIV_MASK; - div >>= (S3C2443_CLKDIV0_EXTDIV_SHIFT-1); /* x2 */ - - return parent_rate / (div + 1); -} - -static struct clk clk_mdivclk = { - .name = "mdivclk", - .parent = &clk_mpllref, - .id = -1, - .ops = &(struct clk_ops) { - .get_rate = s3c2443_getrate_mdivclk, - }, -}; - -static struct clk *clk_msysclk_sources[] = { - [0] = &clk_mpllref, - [1] = &clk_mpll, - [2] = &clk_mdivclk, - [3] = &clk_mpllref, -}; - -static struct clksrc_clk clk_msysclk = { - .clk = { - .name = "msysclk", - .parent = &clk_xtal, - .id = -1, - }, - .sources = &(struct clksrc_sources) { - .sources = clk_msysclk_sources, - .nr_sources = ARRAY_SIZE(clk_msysclk_sources), - }, - .reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 3 }, -}; - /* armdiv * * this clock is sourced from msysclk and can have a number of @@ -266,44 +169,6 @@ static struct clksrc_clk clk_arm = { .reg_src = { .reg = S3C2443_CLKDIV0, .size = 1, .shift = 13 }, }; -/* esysclk - * - * this is sourced from either the EPLL or the EPLLref clock -*/ - -static struct clk *clk_sysclk_sources[] = { - [0] = &clk_epllref.clk, - [1] = &clk_epll, -}; - -static struct clksrc_clk clk_esysclk = { - .clk = { - .name = "esysclk", - .parent = &clk_epll, - .id = -1, - }, - .sources = &(struct clksrc_sources) { - .sources = clk_sysclk_sources, - .nr_sources = ARRAY_SIZE(clk_sysclk_sources), - }, - .reg_src = { .reg = S3C2443_CLKSRC, .size = 1, .shift = 6 }, -}; - -/* uartclk - * - * UART baud-rate clock sourced from esysclk via a divisor -*/ - -static struct clksrc_clk clk_uart = { - .clk = { - .name = "uartclk", - .id = -1, - .parent = &clk_esysclk.clk, - }, - .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 8 }, -}; - - /* hsspi * * high-speed spi clock, sourced from esysclk @@ -320,21 +185,6 @@ static struct clksrc_clk clk_hsspi = { .reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 4 }, }; -/* usbhost - * - * usb host bus-clock, usually 48MHz to provide USB bus clock timing -*/ - -static struct clksrc_clk clk_usb_bus_host = { - .clk = { - .name = "usb-bus-host-parent", - .id = -1, - .parent = &clk_esysclk.clk, - .ctrlbit = S3C2443_SCLKCON_USBHOST, - .enable = s3c2443_clkcon_enable_s, - }, - .reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 4 }, -}; /* clk_hsmcc_div * @@ -433,89 +283,16 @@ static struct clksrc_clk clk_i2s = { .reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 14 }, }; -/* cam-if - * - * camera interface bus-clock, divided down from esysclk -*/ - -static struct clksrc_clk clk_cam = { - .clk = { - .name = "camif-upll", /* same as 2440 name */ - .id = -1, - .parent = &clk_esysclk.clk, - .ctrlbit = S3C2443_SCLKCON_CAMCLK, - .enable = s3c2443_clkcon_enable_s, - }, - .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 26 }, -}; - -/* display-if - * - * display interface clock, divided from esysclk -*/ - -static struct clksrc_clk clk_display = { - .clk = { - .name = "display-if", - .id = -1, - .parent = &clk_esysclk.clk, - .ctrlbit = S3C2443_SCLKCON_DISPCLK, - .enable = s3c2443_clkcon_enable_s, - }, - .reg_div = { .reg = S3C2443_CLKDIV1, .size = 8, .shift = 16 }, -}; - -/* prediv - * - * this divides the msysclk down to pass to h/p/etc. - */ - -static unsigned long s3c2443_prediv_getrate(struct clk *clk) -{ - unsigned long rate = clk_get_rate(clk->parent); - unsigned long clkdiv0 = __raw_readl(S3C2443_CLKDIV0); - - clkdiv0 &= S3C2443_CLKDIV0_PREDIV_MASK; - clkdiv0 >>= S3C2443_CLKDIV0_PREDIV_SHIFT; - - return rate / (clkdiv0 + 1); -} - -static struct clk clk_prediv = { - .name = "prediv", - .id = -1, - .parent = &clk_msysclk.clk, - .ops = &(struct clk_ops) { - .get_rate = s3c2443_prediv_getrate, - }, -}; - /* standard clock definitions */ static struct clk init_clocks_off[] = { { - .name = "nand", - .id = -1, - .parent = &clk_h, - }, { .name = "sdi", .id = -1, .parent = &clk_p, .enable = s3c2443_clkcon_enable_p, .ctrlbit = S3C2443_PCLKCON_SDI, }, { - .name = "adc", - .id = -1, - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_ADC, - }, { - .name = "i2c", - .id = -1, - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_IIC, - }, { .name = "iis", .id = -1, .parent = &clk_p, @@ -537,179 +314,12 @@ static struct clk init_clocks_off[] = { }; static struct clk init_clocks[] = { - { - .name = "dma", - .id = 0, - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_DMA0, - }, { - .name = "dma", - .id = 1, - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_DMA1, - }, { - .name = "dma", - .id = 2, - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_DMA2, - }, { - .name = "dma", - .id = 3, - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_DMA3, - }, { - .name = "dma", - .id = 4, - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_DMA4, - }, { - .name = "dma", - .id = 5, - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_DMA5, - }, { - .name = "lcd", - .id = -1, - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_LCDC, - }, { - .name = "gpio", - .id = -1, - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_GPIO, - }, { - .name = "usb-host", - .id = -1, - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_USBH, - }, { - .name = "usb-device", - .id = -1, - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_USBD, - }, { - .name = "hsmmc", - .id = -1, - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_HSMMC, - }, { - .name = "cfc", - .id = -1, - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_CFC, - }, { - .name = "ssmc", - .id = -1, - .parent = &clk_h, - .enable = s3c2443_clkcon_enable_h, - .ctrlbit = S3C2443_HCLKCON_SSMC, - }, { - .name = "timers", - .id = -1, - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_PWMT, - }, { - .name = "uart", - .id = 0, - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_UART0, - }, { - .name = "uart", - .id = 1, - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_UART1, - }, { - .name = "uart", - .id = 2, - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_UART2, - }, { - .name = "uart", - .id = 3, - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_UART3, - }, { - .name = "rtc", - .id = -1, - .parent = &clk_p, - .enable = s3c2443_clkcon_enable_p, - .ctrlbit = S3C2443_PCLKCON_RTC, - }, { - .name = "watchdog", - .id = -1, - .parent = &clk_p, - .ctrlbit = S3C2443_PCLKCON_WDT, - }, { - .name = "usb-bus-host", - .id = -1, - .parent = &clk_usb_bus_host.clk, - }, { - .name = "ac97", - .id = -1, - .parent = &clk_p, - .ctrlbit = S3C2443_PCLKCON_AC97, - } }; -/* clocks to add where we need to check their parentage */ - -static struct clksrc_clk __initdata *init_list[] = { - &clk_epllref, /* should be first */ - &clk_esysclk, - &clk_msysclk, - &clk_arm, - &clk_i2s_eplldiv, - &clk_i2s, - &clk_cam, - &clk_uart, - &clk_display, - &clk_hsmmc_div, - &clk_usb_bus_host, -}; - -static void __init s3c2443_clk_initparents(void) -{ - int ptr; - - for (ptr = 0; ptr < ARRAY_SIZE(init_list); ptr++) - s3c_set_clksrc(init_list[ptr], true); -} - -static inline unsigned long s3c2443_get_hdiv(unsigned long clkcon0) -{ - clkcon0 &= S3C2443_CLKDIV0_HCLKDIV_MASK; - - return clkcon0 + 1; -} - /* clocks to add straight away */ static struct clksrc_clk *clksrcs[] __initdata = { - &clk_usb_bus_host, - &clk_epllref, - &clk_esysclk, - &clk_msysclk, &clk_arm, - &clk_uart, - &clk_display, - &clk_cam, &clk_i2s_eplldiv, &clk_i2s, &clk_hsspi, @@ -717,46 +327,13 @@ static struct clksrc_clk *clksrcs[] __initdata = { }; static struct clk *clks[] __initdata = { - &clk_ext, - &clk_epll, - &clk_usb_bus, - &clk_mpllref, &clk_hsmmc, &clk_armdiv, - &clk_prediv, }; void __init_or_cpufreq s3c2443_setup_clocks(void) { - unsigned long mpllcon = __raw_readl(S3C2443_MPLLCON); - unsigned long clkdiv0 = __raw_readl(S3C2443_CLKDIV0); - struct clk *xtal_clk; - unsigned long xtal; - unsigned long pll; - unsigned long fclk; - unsigned long hclk; - unsigned long pclk; - - xtal_clk = clk_get(NULL, "xtal"); - xtal = clk_get_rate(xtal_clk); - clk_put(xtal_clk); - - pll = s3c2443_get_mpll(mpllcon, xtal); - clk_msysclk.clk.rate = pll; - - fclk = pll / s3c2443_fclk_div(clkdiv0); - hclk = s3c2443_prediv_getrate(&clk_prediv); - hclk /= s3c2443_get_hdiv(clkdiv0); - pclk = hclk / ((clkdiv0 & S3C2443_CLKDIV0_HALF_PCLK) ? 2 : 1); - - s3c24xx_setup_clocks(fclk, hclk, pclk); - - printk("S3C2443: mpll %s %ld.%03ld MHz, cpu %ld.%03ld MHz, mem %ld.%03ld MHz, pclk %ld.%03ld MHz\n", - (mpllcon & S3C2443_PLLCON_OFF) ? "off":"on", - print_mhz(pll), print_mhz(fclk), - print_mhz(hclk), print_mhz(pclk)); - - s3c24xx_setup_clocks(fclk, hclk, pclk); + s3c2443_common_setup_clocks(s3c2443_get_mpll, s3c2443_fclk_div); } void __init s3c2443_init_clocks(int xtal) @@ -764,35 +341,18 @@ void __init s3c2443_init_clocks(int xtal) unsigned long epllcon = __raw_readl(S3C2443_EPLLCON); int ptr; - /* s3c2443 parents h and p clocks from prediv */ - clk_h.parent = &clk_prediv; - clk_p.parent = &clk_prediv; + clk_epll.rate = s3c2443_get_epll(epllcon, xtal); + clk_epll.parent = &clk_epllref.clk; + + s3c2443_common_init_clocks(xtal, s3c2443_get_mpll, s3c2443_fclk_div); - s3c24xx_register_baseclocks(xtal); s3c2443_setup_clocks(); - s3c2443_clk_initparents(); s3c24xx_register_clocks(clks, ARRAY_SIZE(clks)); for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) s3c_register_clksrc(clksrcs[ptr], 1); - clk_epll.rate = s3c2443_get_epll(epllcon, xtal); - clk_epll.parent = &clk_epllref.clk; - clk_usb_bus.parent = &clk_usb_bus_host.clk; - - /* ensure usb bus clock is within correct rate of 48MHz */ - - if (clk_get_rate(&clk_usb_bus_host.clk) != (48 * 1000 * 1000)) { - printk(KERN_INFO "Warning: USB host bus not at 48MHz\n"); - clk_set_rate(&clk_usb_bus_host.clk, 48*1000*1000); - } - - printk("S3C2443: epll %s %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n", - (epllcon & S3C2443_PLLCON_OFF) ? "off":"on", - print_mhz(clk_get_rate(&clk_epll)), - print_mhz(clk_get_rate(&clk_usb_bus))); - /* register clocks from clock array */ s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks)); diff --git a/arch/arm/plat-s3c24xx/Kconfig b/arch/arm/plat-s3c24xx/Kconfig index a830fad..3ce8f01 100644 --- a/arch/arm/plat-s3c24xx/Kconfig +++ b/arch/arm/plat-s3c24xx/Kconfig @@ -45,6 +45,12 @@ config S3C2410_CLOCK Clock code for the S3C2410, and similar processors which is currently includes the S3C2410, S3C2440, S3C2442. +config S3C2443_CLOCK + bool + help + Clock code for the S3C2443 and similar processors, which includes + the S3C2416 and S3C2450. + config S3C24XX_DCLK bool help diff --git a/arch/arm/plat-s3c24xx/Makefile b/arch/arm/plat-s3c24xx/Makefile index c2237c4..44aea88 100644 --- a/arch/arm/plat-s3c24xx/Makefile +++ b/arch/arm/plat-s3c24xx/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_PM) += pm.o obj-$(CONFIG_PM) += irq-pm.o obj-$(CONFIG_PM) += sleep.o obj-$(CONFIG_S3C2410_CLOCK) += s3c2410-clock.o +obj-$(CONFIG_S3C2443_CLOCK) += s3c2443-clock.o obj-$(CONFIG_S3C2410_DMA) += dma.o obj-$(CONFIG_S3C2410_IOTIMING) += s3c2410-iotiming.o obj-$(CONFIG_S3C2412_IOTIMING) += s3c2412-iotiming.o diff --git a/arch/arm/plat-s3c24xx/include/plat/s3c2443.h b/arch/arm/plat-s3c24xx/include/plat/s3c2443.h index 815b107..a19715f 100644 --- a/arch/arm/plat-s3c24xx/include/plat/s3c2443.h +++ b/arch/arm/plat-s3c24xx/include/plat/s3c2443.h @@ -30,3 +30,22 @@ extern int s3c2443_baseclk_add(void); #define s3c2443_map_io NULL #define s3c2443_init NULL #endif + +/* common code used by s3c2443 and others. + * note, not to be used outside of arch/arm/mach-s3c* */ + +struct clk; /* some files don't need clk.h otherwise */ + +typedef unsigned int (*pll_fn)(unsigned int reg, unsigned int base); +typedef unsigned int (*fdiv_fn)(unsigned long clkcon0); + +extern void s3c2443_common_setup_clocks(pll_fn get_mpll, fdiv_fn fdiv); +extern void s3c2443_common_init_clocks(int xtal, pll_fn get_mpll, fdiv_fn fdiv); + +extern int s3c2443_clkcon_enable_h(struct clk *clk, int enable); +extern int s3c2443_clkcon_enable_p(struct clk *clk, int enable); +extern int s3c2443_clkcon_enable_s(struct clk *clk, int enable); + +extern struct clksrc_clk clk_epllref; +extern struct clksrc_clk clk_esysclk; +extern struct clksrc_clk clk_msysclk; diff --git a/arch/arm/plat-s3c24xx/s3c2443-clock.c b/arch/arm/plat-s3c24xx/s3c2443-clock.c new file mode 100644 index 0000000..461f070 --- /dev/null +++ b/arch/arm/plat-s3c24xx/s3c2443-clock.c @@ -0,0 +1,472 @@ +/* linux/arch/arm/plat-s3c24xx/s3c2443-clock.c + * + * Copyright (c) 2007, 2010 Simtec Electronics + * Ben Dooks + * + * S3C2443 Clock control suport - common code + */ + +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + + +static int s3c2443_gate(void __iomem *reg, struct clk *clk, int enable) +{ + u32 ctrlbit = clk->ctrlbit; + u32 con = __raw_readl(reg); + + if (enable) + con |= ctrlbit; + else + con &= ~ctrlbit; + + __raw_writel(con, reg); + return 0; +} + +int s3c2443_clkcon_enable_h(struct clk *clk, int enable) +{ + return s3c2443_gate(S3C2443_HCLKCON, clk, enable); +} + +int s3c2443_clkcon_enable_p(struct clk *clk, int enable) +{ + return s3c2443_gate(S3C2443_PCLKCON, clk, enable); +} + +int s3c2443_clkcon_enable_s(struct clk *clk, int enable) +{ + return s3c2443_gate(S3C2443_SCLKCON, clk, enable); +} + +/* mpllref is a direct descendant of clk_xtal by default, but it is not + * elided as the EPLL can be either sourced by the XTAL or EXTCLK and as + * such directly equating the two source clocks is impossible. + */ +struct clk clk_mpllref = { + .name = "mpllref", + .parent = &clk_xtal, + .id = -1, +}; + +static struct clk *clk_epllref_sources[] = { + [0] = &clk_mpllref, + [1] = &clk_mpllref, + [2] = &clk_xtal, + [3] = &clk_ext, +}; + +struct clksrc_clk clk_epllref = { + .clk = { + .name = "epllref", + .id = -1, + }, + .sources = &(struct clksrc_sources) { + .sources = clk_epllref_sources, + .nr_sources = ARRAY_SIZE(clk_epllref_sources), + }, + .reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 7 }, +}; + +/* esysclk + * + * this is sourced from either the EPLL or the EPLLref clock +*/ + +static struct clk *clk_sysclk_sources[] = { + [0] = &clk_epllref.clk, + [1] = &clk_epll, +}; + +struct clksrc_clk clk_esysclk = { + .clk = { + .name = "esysclk", + .parent = &clk_epll, + .id = -1, + }, + .sources = &(struct clksrc_sources) { + .sources = clk_sysclk_sources, + .nr_sources = ARRAY_SIZE(clk_sysclk_sources), + }, + .reg_src = { .reg = S3C2443_CLKSRC, .size = 1, .shift = 6 }, +}; + +static unsigned long s3c2443_getrate_mdivclk(struct clk *clk) +{ + unsigned long parent_rate = clk_get_rate(clk->parent); + unsigned long div = __raw_readl(S3C2443_CLKDIV0); + + div &= S3C2443_CLKDIV0_EXTDIV_MASK; + div >>= (S3C2443_CLKDIV0_EXTDIV_SHIFT-1); /* x2 */ + + return parent_rate / (div + 1); +} + +static struct clk clk_mdivclk = { + .name = "mdivclk", + .parent = &clk_mpllref, + .id = -1, + .ops = &(struct clk_ops) { + .get_rate = s3c2443_getrate_mdivclk, + }, +}; + +static struct clk *clk_msysclk_sources[] = { + [0] = &clk_mpllref, + [1] = &clk_mpll, + [2] = &clk_mdivclk, + [3] = &clk_mpllref, +}; + +struct clksrc_clk clk_msysclk = { + .clk = { + .name = "msysclk", + .parent = &clk_xtal, + .id = -1, + }, + .sources = &(struct clksrc_sources) { + .sources = clk_msysclk_sources, + .nr_sources = ARRAY_SIZE(clk_msysclk_sources), + }, + .reg_src = { .reg = S3C2443_CLKSRC, .size = 2, .shift = 3 }, +}; + +/* prediv + * + * this divides the msysclk down to pass to h/p/etc. + */ + +static unsigned long s3c2443_prediv_getrate(struct clk *clk) +{ + unsigned long rate = clk_get_rate(clk->parent); + unsigned long clkdiv0 = __raw_readl(S3C2443_CLKDIV0); + + clkdiv0 &= S3C2443_CLKDIV0_PREDIV_MASK; + clkdiv0 >>= S3C2443_CLKDIV0_PREDIV_SHIFT; + + return rate / (clkdiv0 + 1); +} + +static struct clk clk_prediv = { + .name = "prediv", + .id = -1, + .parent = &clk_msysclk.clk, + .ops = &(struct clk_ops) { + .get_rate = s3c2443_prediv_getrate, + }, +}; + +/* usbhost + * + * usb host bus-clock, usually 48MHz to provide USB bus clock timing +*/ + +static struct clksrc_clk clk_usb_bus_host = { + .clk = { + .name = "usb-bus-host-parent", + .id = -1, + .parent = &clk_esysclk.clk, + .ctrlbit = S3C2443_SCLKCON_USBHOST, + .enable = s3c2443_clkcon_enable_s, + }, + .reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 4 }, +}; + +/* common clksrc clocks */ + +static struct clksrc_clk clksrc_clks[] = { + { + /* ART baud-rate clock sourced from esysclk via a divisor */ + .clk = { + .name = "uartclk", + .id = -1, + .parent = &clk_esysclk.clk, + }, + .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 8 }, + }, { + /* camera interface bus-clock, divided down from esysclk */ + .clk = { + .name = "camif-upll", /* same as 2440 name */ + .id = -1, + .parent = &clk_esysclk.clk, + .ctrlbit = S3C2443_SCLKCON_CAMCLK, + .enable = s3c2443_clkcon_enable_s, + }, + .reg_div = { .reg = S3C2443_CLKDIV1, .size = 4, .shift = 26 }, + }, { + .clk = { + .name = "display-if", + .id = -1, + .parent = &clk_esysclk.clk, + .ctrlbit = S3C2443_SCLKCON_DISPCLK, + .enable = s3c2443_clkcon_enable_s, + }, + .reg_div = { .reg = S3C2443_CLKDIV1, .size = 8, .shift = 16 }, + }, +}; + + +static struct clk init_clocks_off[] = { + { + .name = "adc", + .id = -1, + .parent = &clk_p, + .enable = s3c2443_clkcon_enable_p, + .ctrlbit = S3C2443_PCLKCON_ADC, + }, { + .name = "i2c", + .id = -1, + .parent = &clk_p, + .enable = s3c2443_clkcon_enable_p, + .ctrlbit = S3C2443_PCLKCON_IIC, + } +}; + +static struct clk init_clocks[] = { + { + .name = "dma", + .id = 0, + .parent = &clk_h, + .enable = s3c2443_clkcon_enable_h, + .ctrlbit = S3C2443_HCLKCON_DMA0, + }, { + .name = "dma", + .id = 1, + .parent = &clk_h, + .enable = s3c2443_clkcon_enable_h, + .ctrlbit = S3C2443_HCLKCON_DMA1, + }, { + .name = "dma", + .id = 2, + .parent = &clk_h, + .enable = s3c2443_clkcon_enable_h, + .ctrlbit = S3C2443_HCLKCON_DMA2, + }, { + .name = "dma", + .id = 3, + .parent = &clk_h, + .enable = s3c2443_clkcon_enable_h, + .ctrlbit = S3C2443_HCLKCON_DMA3, + }, { + .name = "dma", + .id = 4, + .parent = &clk_h, + .enable = s3c2443_clkcon_enable_h, + .ctrlbit = S3C2443_HCLKCON_DMA4, + }, { + .name = "dma", + .id = 5, + .parent = &clk_h, + .enable = s3c2443_clkcon_enable_h, + .ctrlbit = S3C2443_HCLKCON_DMA5, + }, { + .name = "hsmmc", + .id = 0, + .parent = &clk_h, + .enable = s3c2443_clkcon_enable_h, + .ctrlbit = S3C2443_HCLKCON_HSMMC, + }, { + .name = "gpio", + .id = -1, + .parent = &clk_p, + .enable = s3c2443_clkcon_enable_p, + .ctrlbit = S3C2443_PCLKCON_GPIO, + }, { + .name = "usb-host", + .id = -1, + .parent = &clk_h, + .enable = s3c2443_clkcon_enable_h, + .ctrlbit = S3C2443_HCLKCON_USBH, + }, { + .name = "usb-device", + .id = -1, + .parent = &clk_h, + .enable = s3c2443_clkcon_enable_h, + .ctrlbit = S3C2443_HCLKCON_USBD, + }, { + .name = "lcd", + .id = -1, + .parent = &clk_h, + .enable = s3c2443_clkcon_enable_h, + .ctrlbit = S3C2443_HCLKCON_LCDC, + + }, { + .name = "timers", + .id = -1, + .parent = &clk_p, + .enable = s3c2443_clkcon_enable_p, + .ctrlbit = S3C2443_PCLKCON_PWMT, + }, { + .name = "cfc", + .id = -1, + .parent = &clk_h, + .enable = s3c2443_clkcon_enable_h, + .ctrlbit = S3C2443_HCLKCON_CFC, + }, { + .name = "ssmc", + .id = -1, + .parent = &clk_h, + .enable = s3c2443_clkcon_enable_h, + .ctrlbit = S3C2443_HCLKCON_SSMC, + }, { + .name = "uart", + .id = 0, + .parent = &clk_p, + .enable = s3c2443_clkcon_enable_p, + .ctrlbit = S3C2443_PCLKCON_UART0, + }, { + .name = "uart", + .id = 1, + .parent = &clk_p, + .enable = s3c2443_clkcon_enable_p, + .ctrlbit = S3C2443_PCLKCON_UART1, + }, { + .name = "uart", + .id = 2, + .parent = &clk_p, + .enable = s3c2443_clkcon_enable_p, + .ctrlbit = S3C2443_PCLKCON_UART2, + }, { + .name = "uart", + .id = 3, + .parent = &clk_p, + .enable = s3c2443_clkcon_enable_p, + .ctrlbit = S3C2443_PCLKCON_UART3, + }, { + .name = "rtc", + .id = -1, + .parent = &clk_p, + .enable = s3c2443_clkcon_enable_p, + .ctrlbit = S3C2443_PCLKCON_RTC, + }, { + .name = "watchdog", + .id = -1, + .parent = &clk_p, + .ctrlbit = S3C2443_PCLKCON_WDT, + }, { + .name = "ac97", + .id = -1, + .parent = &clk_p, + .ctrlbit = S3C2443_PCLKCON_AC97, + }, { + .name = "nand", + .id = -1, + .parent = &clk_h, + }, { + .name = "usb-bus-host", + .id = -1, + .parent = &clk_usb_bus_host.clk, + } +}; + +static inline unsigned long s3c2443_get_hdiv(unsigned long clkcon0) +{ + clkcon0 &= S3C2443_CLKDIV0_HCLKDIV_MASK; + + return clkcon0 + 1; +} + +/* EPLLCON compatible enough to get on/off information */ + +void __init_or_cpufreq s3c2443_common_setup_clocks(pll_fn get_mpll, + fdiv_fn get_fdiv) +{ + unsigned long epllcon = __raw_readl(S3C2443_EPLLCON); + unsigned long mpllcon = __raw_readl(S3C2443_MPLLCON); + unsigned long clkdiv0 = __raw_readl(S3C2443_CLKDIV0); + struct clk *xtal_clk; + unsigned long xtal; + unsigned long pll; + unsigned long fclk; + unsigned long hclk; + unsigned long pclk; + int ptr; + + xtal_clk = clk_get(NULL, "xtal"); + xtal = clk_get_rate(xtal_clk); + clk_put(xtal_clk); + + pll = get_mpll(mpllcon, xtal); + clk_msysclk.clk.rate = pll; + + fclk = pll / get_fdiv(clkdiv0); + hclk = s3c2443_prediv_getrate(&clk_prediv); + hclk /= s3c2443_get_hdiv(clkdiv0); + pclk = hclk / ((clkdiv0 & S3C2443_CLKDIV0_HALF_PCLK) ? 2 : 1); + + s3c24xx_setup_clocks(fclk, hclk, pclk); + + printk("CPU: MPLL %s %ld.%03ld MHz, cpu %ld.%03ld MHz, mem %ld.%03ld MHz, pclk %ld.%03ld MHz\n", + (mpllcon & S3C2443_PLLCON_OFF) ? "off":"on", + print_mhz(pll), print_mhz(fclk), + print_mhz(hclk), print_mhz(pclk)); + + for (ptr = 0; ptr < ARRAY_SIZE(clksrc_clks); ptr++) + s3c_set_clksrc(&clksrc_clks[ptr], true); + + /* ensure usb bus clock is within correct rate of 48MHz */ + + if (clk_get_rate(&clk_usb_bus_host.clk) != (48 * 1000 * 1000)) { + printk(KERN_INFO "Warning: USB host bus not at 48MHz\n"); + clk_set_rate(&clk_usb_bus_host.clk, 48*1000*1000); + } + + printk("CPU: EPLL %s %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n", + (epllcon & S3C2443_PLLCON_OFF) ? "off":"on", + print_mhz(clk_get_rate(&clk_epll)), + print_mhz(clk_get_rate(&clk_usb_bus))); +} + +static struct clk *clks[] __initdata = { + &clk_prediv, + &clk_mpllref, + &clk_mdivclk, + &clk_ext, + &clk_epll, + &clk_usb_bus, +}; + +static struct clksrc_clk *clksrcs[] __initdata = { + &clk_usb_bus_host, + &clk_epllref, + &clk_esysclk, + &clk_msysclk, +}; + +void __init s3c2443_common_init_clocks(int xtal, pll_fn get_mpll, + fdiv_fn get_fdiv) +{ + int ptr; + + /* s3c2443 parents h and p clocks from prediv */ + clk_h.parent = &clk_prediv; + clk_p.parent = &clk_prediv; + + clk_usb_bus.parent = &clk_usb_bus_host.clk; + clk_epll.parent = &clk_epllref.clk; + + s3c24xx_register_baseclocks(xtal); + s3c24xx_register_clocks(clks, ARRAY_SIZE(clks)); + + for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) + s3c_register_clksrc(clksrcs[ptr], 1); + + s3c_register_clksrc(clksrc_clks, ARRAY_SIZE(clksrc_clks)); + s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks)); + + /* See s3c2443/etc notes on disabling clocks at init time */ + s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); + s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off)); + + s3c2443_common_setup_clocks(get_mpll, get_fdiv); +} -- cgit v0.10.2 From 8d6f8658305db969981f64a22296b487ef2f1148 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 30 Apr 2010 11:12:58 +0900 Subject: ARM: S3C2416: Add basic clock support Add basic clock support for the PLLs, HSMMC channels and PWM clocks. This is enough to get a basic system up and running. Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/include/mach/regs-clock.h b/arch/arm/mach-s3c2410/include/mach/regs-clock.h index 9a0d169..3415b60 100644 --- a/arch/arm/mach-s3c2410/include/mach/regs-clock.h +++ b/arch/arm/mach-s3c2410/include/mach/regs-clock.h @@ -161,4 +161,6 @@ #endif /* CONFIG_CPU_S3C2412 | CONFIG_CPU_S3C2413 */ +#define S3C2416_CLKDIV2 S3C2410_CLKREG(0x28) + #endif /* __ASM_ARM_REGS_CLOCK */ diff --git a/arch/arm/mach-s3c2416/Kconfig b/arch/arm/mach-s3c2416/Kconfig index 528f273..677f963 100644 --- a/arch/arm/mach-s3c2416/Kconfig +++ b/arch/arm/mach-s3c2416/Kconfig @@ -10,6 +10,8 @@ config CPU_S3C2416 select CPU_ARM926T select S3C2416_DMA if S3C2410_DMA select CPU_LLSERIAL_S3C2440 + select SAMSUNG_CLKSRC + select S3C2443_CLOCK help Support for the S3C2416 SoC from the S3C24XX line diff --git a/arch/arm/mach-s3c2416/Makefile b/arch/arm/mach-s3c2416/Makefile index 9183e81..6c12c7b 100644 --- a/arch/arm/mach-s3c2416/Makefile +++ b/arch/arm/mach-s3c2416/Makefile @@ -9,7 +9,7 @@ obj-m := obj-n := obj- := -obj-$(CONFIG_CPU_S3C2416) += s3c2416.o +obj-$(CONFIG_CPU_S3C2416) += s3c2416.o clock.o obj-$(CONFIG_CPU_S3C2416) += irq.o #obj-$(CONFIG_S3C2416_DMA) += dma.o diff --git a/arch/arm/mach-s3c2416/clock.c b/arch/arm/mach-s3c2416/clock.c new file mode 100644 index 0000000..7ccf5a2 --- /dev/null +++ b/arch/arm/mach-s3c2416/clock.c @@ -0,0 +1,135 @@ +/* linux/arch/arm/mach-s3c2416/clock.c + * + * Copyright (c) 2010 Simtec Electronics + * Copyright (c) 2010 Ben Dooks + * + * S3C2416 Clock control support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include + +static unsigned int armdiv[8] = { + [0] = 1, + [1] = 2, + [2] = 3, + [3] = 4, + [5] = 6, + [7] = 8, +}; + +/* ID to hardware numbering, 0 is HSMMC1, 1 is HSMMC0 */ +static struct clksrc_clk hsmmc_div[] = { + [0] = { + .clk = { + .name = "hsmmc-div", + .id = 1, + .parent = &clk_esysclk.clk, + }, + .reg_div = { .reg = S3C2416_CLKDIV2, .size = 2, .shift = 6 }, + }, + [1] = { + .clk = { + .name = "hsmmc-div", + .id = 0, + .parent = &clk_esysclk.clk, + }, + .reg_div = { .reg = S3C2443_CLKDIV1, .size = 2, .shift = 6 }, + }, +}; + +static struct clksrc_clk hsmmc_mux[] = { + [0] = { + .clk = { + .id = 1, + .name = "hsmmc-if", + .ctrlbit = (1 << 6), + .enable = s3c2443_clkcon_enable_s, + }, + .sources = &(struct clksrc_sources) { + .nr_sources = 2, + .sources = (struct clk *[]) { + [0] = &hsmmc_div[0].clk, + [1] = NULL, /* to fix */ + }, + }, + .reg_src = { .reg = S3C2443_CLKSRC, .size = 1, .shift = 16 }, + }, + [1] = { + .clk = { + .id = 0, + .name = "hsmmc-if", + .ctrlbit = (1 << 12), + .enable = s3c2443_clkcon_enable_s, + }, + .sources = &(struct clksrc_sources) { + .nr_sources = 2, + .sources = (struct clk *[]) { + [0] = &hsmmc_div[1].clk, + [1] = NULL, /* to fix */ + }, + }, + .reg_src = { .reg = S3C2443_CLKSRC, .size = 1, .shift = 17 }, + }, +}; + + +static inline unsigned int s3c2416_fclk_div(unsigned long clkcon0) +{ + clkcon0 &= 7 << S3C2443_CLKDIV0_ARMDIV_SHIFT; + + return armdiv[clkcon0 >> S3C2443_CLKDIV0_ARMDIV_SHIFT]; +} + +void __init_or_cpufreq s3c2416_setup_clocks(void) +{ + s3c2443_common_setup_clocks(s3c2416_get_pll, s3c2416_fclk_div); +} + + +static struct clksrc_clk *clksrcs[] __initdata = { + &hsmmc_div[0], + &hsmmc_div[1], + &hsmmc_mux[0], + &hsmmc_mux[1], +}; + +void __init s3c2416_init_clocks(int xtal) +{ + u32 epllcon = __raw_readl(S3C2443_EPLLCON); + u32 epllcon1 = __raw_readl(S3C2443_EPLLCON+4); + int ptr; + + /* s3c2416 EPLL compatible with s3c64xx */ + clk_epll.rate = s3c_get_pll6553x(xtal, epllcon, epllcon1); + + clk_epll.parent = &clk_epllref.clk; + + s3c2443_common_init_clocks(xtal, s3c2416_get_pll, s3c2416_fclk_div); + + for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) + s3c_register_clksrc(clksrcs[ptr], 1); + + s3c_pwmclk_init(); + +} diff --git a/arch/arm/plat-s3c24xx/include/plat/pll.h b/arch/arm/plat-s3c24xx/include/plat/pll.h index 7ea8bff..005729a 100644 --- a/arch/arm/plat-s3c24xx/include/plat/pll.h +++ b/arch/arm/plat-s3c24xx/include/plat/pll.h @@ -35,3 +35,28 @@ s3c24xx_get_pll(unsigned int pllval, unsigned int baseclk) return (unsigned int)fvco; } + +#define S3C2416_PLL_M_SHIFT (14) +#define S3C2416_PLL_P_SHIFT (5) +#define S3C2416_PLL_S_MASK (7) +#define S3C2416_PLL_M_MASK ((1 << 10) - 1) +#define S3C2416_PLL_P_MASK (63) + +static inline unsigned int +s3c2416_get_pll(unsigned int pllval, unsigned int baseclk) +{ + unsigned int m, p, s; + uint64_t fvco; + + m = pllval >> S3C2416_PLL_M_SHIFT; + p = pllval >> S3C2416_PLL_P_SHIFT; + + s = pllval & S3C2416_PLL_S_MASK; + m &= S3C2416_PLL_M_MASK; + p &= S3C2416_PLL_P_MASK; + + fvco = (uint64_t)baseclk * m; + do_div(fvco, (p << s)); + + return (unsigned int)fvco; +} -- cgit v0.10.2 From c140c98ac161ad270a768126431e36a22f86f6b3 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 29 Apr 2010 18:59:43 +0900 Subject: ARM: S3C2416: Add support for second HSMMC channel Add support for the second HSMMC channel on the S3C2416. Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/include/mach/irqs.h b/arch/arm/mach-s3c2410/include/mach/irqs.h index c1b8ec0..877c15e 100644 --- a/arch/arm/mach-s3c2410/include/mach/irqs.h +++ b/arch/arm/mach-s3c2410/include/mach/irqs.h @@ -150,7 +150,10 @@ #define IRQ_S3C2443_HSMMC S3C2410_IRQ(20) /* IRQ_SDI */ #define IRQ_S3C2443_NAND S3C2410_IRQ(24) /* reserved */ +#define IRQ_S3C2416_HSMMC0 S3C2410_IRQ(21) /* S3C2416/S3C2450 */ + #define IRQ_HSMMC0 IRQ_S3C2443_HSMMC +#define IRQ_HSMMC1 IRQ_S3C2416_HSMMC0 #define IRQ_S3C2443_LCD1 S3C2410_IRQSUB(14) #define IRQ_S3C2443_LCD2 S3C2410_IRQSUB(15) diff --git a/arch/arm/mach-s3c2410/include/mach/map.h b/arch/arm/mach-s3c2410/include/mach/map.h index b049e61..f07d680 100644 --- a/arch/arm/mach-s3c2410/include/mach/map.h +++ b/arch/arm/mach-s3c2410/include/mach/map.h @@ -63,9 +63,9 @@ #define S3C2440_PA_AC97 (0x5B000000) #define S3C2440_SZ_AC97 SZ_1M -/* S3C2443 High-speed SD/MMC */ +/* S3C2443/S3C2416 High-speed SD/MMC */ #define S3C2443_PA_HSMMC (0x4A800000) -#define S3C2443_SZ_HSMMC (256) +#define S3C2416_PA_HSMMC0 (0x4AC00000) /* S3C2412 memory and IO controls */ #define S3C2412_PA_SSMC (0x4F000000) @@ -110,6 +110,7 @@ #define S3C_PA_UART S3C24XX_PA_UART #define S3C_PA_USBHOST S3C2410_PA_USBHOST #define S3C_PA_HSMMC0 S3C2443_PA_HSMMC +#define S3C_PA_HSMMC1 S3C2416_PA_HSMMC0 #define S3C_PA_NAND S3C24XX_PA_NAND #endif /* __ASM_ARCH_MAP_H */ diff --git a/arch/arm/mach-s3c2416/Kconfig b/arch/arm/mach-s3c2416/Kconfig index 677f963..a1308d4 100644 --- a/arch/arm/mach-s3c2416/Kconfig +++ b/arch/arm/mach-s3c2416/Kconfig @@ -27,6 +27,7 @@ config MACH_SMDK2416 bool "SMDK2416" select CPU_S3C2416 select S3C_DEV_HSMMC + select S3C_DEV_HSMMC1 help Say Y here if you are using an SMDK2416 diff --git a/arch/arm/mach-s3c2416/mach-smdk2416.c b/arch/arm/mach-s3c2416/mach-smdk2416.c index 8c9aed6..a51973c 100644 --- a/arch/arm/mach-s3c2416/mach-smdk2416.c +++ b/arch/arm/mach-s3c2416/mach-smdk2416.c @@ -112,6 +112,7 @@ static struct platform_device *smdk2416_devices[] __initdata = { &s3c_device_wdt, &s3c_device_i2c0, &s3c_device_hsmmc0, + &s3c_device_hsmmc1, }; static void __init smdk2416_map_io(void) -- cgit v0.10.2 From a6e1ec7f69950864ff8d992da6d929b1444f7cb3 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 30 Apr 2010 10:59:42 +0900 Subject: ARM: S3C2416: Add support for OHCI on SMDK2416 Add device definition and ensure that the host port is powered up at start time. Full power control can be added at a later date. Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2416/mach-smdk2416.c b/arch/arm/mach-s3c2416/mach-smdk2416.c index a51973c..99d24c4 100644 --- a/arch/arm/mach-s3c2416/mach-smdk2416.c +++ b/arch/arm/mach-s3c2416/mach-smdk2416.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -110,6 +111,7 @@ static struct s3c2410_uartcfg smdk2416_uartcfgs[] __initdata = { static struct platform_device *smdk2416_devices[] __initdata = { &s3c_device_wdt, + &s3c_device_ohci, &s3c_device_i2c0, &s3c_device_hsmmc0, &s3c_device_hsmmc1, @@ -128,6 +130,9 @@ static void __init smdk2416_machine_init(void) { s3c_i2c0_set_platdata(NULL); + gpio_request(S3C2410_GPB(4), "USBHost Power"); + gpio_direction_output(S3C2410_GPB(4), 1); + platform_add_devices(smdk2416_devices, ARRAY_SIZE(smdk2416_devices)); smdk_machine_init(); } -- cgit v0.10.2 From e12ef7f02ed56af4f84a5743fa268901c52729bf Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 3 May 2010 16:44:35 +0900 Subject: ARM: S3C2416: Use s3c2440 style i2c controller The s3c2416 i2c controllers are compatible with the s3c2440 style i2c block, so change the device name appropriately. Signed-off-by: Ben Dooks y diff --git a/arch/arm/mach-s3c2416/s3c2416.c b/arch/arm/mach-s3c2416/s3c2416.c index 6165dc7..ad5a63a 100644 --- a/arch/arm/mach-s3c2416/s3c2416.c +++ b/arch/arm/mach-s3c2416/s3c2416.c @@ -50,6 +50,8 @@ #include #include +#include + static struct map_desc s3c2416_iodesc[] __initdata = { IODESC_ENT(WATCHDOG), IODESC_ENT(CLKPWR), @@ -80,6 +82,10 @@ int __init s3c2416_init(void) s3c_device_wdt.resource[1].start = IRQ_S3C2443_WDT; s3c_device_wdt.resource[1].end = IRQ_S3C2443_WDT; + /* the i2c devices are directly compatible with s3c2440 */ + s3c_i2c0_setname("s3c2440-i2c"); + s3c_i2c1_setname("s3c2440-i2c"); + return sysdev_register(&s3c2416_sysdev); } -- cgit v0.10.2 From eb90de4a2d2880f0037d2b2ba85a3e857a898b40 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 30 Apr 2010 19:48:02 +0900 Subject: ARM: S3C2413: Update GPIO pull-up support Ensure the right get/set pull code is selected and assigned to the GPIO core. Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2416/Kconfig b/arch/arm/mach-s3c2416/Kconfig index a1308d4..6d077b2 100644 --- a/arch/arm/mach-s3c2416/Kconfig +++ b/arch/arm/mach-s3c2416/Kconfig @@ -10,6 +10,7 @@ config CPU_S3C2416 select CPU_ARM926T select S3C2416_DMA if S3C2410_DMA select CPU_LLSERIAL_S3C2440 + select S3C_GPIO_PULL_UPDOWN select SAMSUNG_CLKSRC select S3C2443_CLOCK help diff --git a/arch/arm/mach-s3c2416/s3c2416.c b/arch/arm/mach-s3c2416/s3c2416.c index ad5a63a..3bff057 100644 --- a/arch/arm/mach-s3c2416/s3c2416.c +++ b/arch/arm/mach-s3c2416/s3c2416.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -46,6 +47,9 @@ #include #include +#include +#include +#include #include #include #include @@ -104,6 +108,9 @@ void __init s3c2416_init_uarts(struct s3c2410_uartcfg *cfg, int no) void __init s3c2416_map_io(void) { + s3c24xx_gpiocfg_default.set_pull = s3c_gpio_setpull_updown; + s3c24xx_gpiocfg_default.get_pull = s3c_gpio_getpull_updown; + iotable_init(s3c2416_iodesc, ARRAY_SIZE(s3c2416_iodesc)); } -- cgit v0.10.2 From 63b1f51b2405573d47bf5b9ab6e7cd5c697d3dcc Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 30 Apr 2010 16:32:26 +0900 Subject: ARM: SAMSUNG: Update S3C2416 entry with S3C2450 These devices are so similar that they share the same SoC ID code, so note this. Signed-off-by: Ben Dooks diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 6785c33..3f8718f 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -647,7 +647,7 @@ config ARCH_SA1100 Support for StrongARM 11x0 based boards. config ARCH_S3C2410 - bool "Samsung S3C2410, S3C2412, S3C2413, S3C2416, S3C2440, S3C2442, S3C2443" + bool "Samsung S3C2410, S3C2412, S3C2413, S3C2416, S3C2440, S3C2442, S3C2443, S3C2450" select GENERIC_GPIO select ARCH_HAS_CPUFREQ select HAVE_CLK @@ -656,6 +656,10 @@ config ARCH_S3C2410 BAST (), the IPAQ 1940 or the Samsung SMDK2410 development board (and derivatives). + Note, the S3C2416 and the S3C2450 are so close that they even share + the same SoC ID code. This means that there is no seperate machine + directory (no arch/arm/mach-s3c2450) as the S3C2416 was first. + config ARCH_S3C64XX bool "Samsung S3C64XX" select PLAT_SAMSUNG diff --git a/arch/arm/mach-s3c2416/Kconfig b/arch/arm/mach-s3c2416/Kconfig index 6d077b2..29103a6 100644 --- a/arch/arm/mach-s3c2416/Kconfig +++ b/arch/arm/mach-s3c2416/Kconfig @@ -4,6 +4,9 @@ # # Licensed under GPLv2 +# note, this also supports the S3C2450 which is so similar it has the same +# ID code as the S3C2416. + config CPU_S3C2416 bool depends on ARCH_S3C2410 diff --git a/arch/arm/plat-s3c24xx/cpu.c b/arch/arm/plat-s3c24xx/cpu.c index 32db856..76d0858 100644 --- a/arch/arm/plat-s3c24xx/cpu.c +++ b/arch/arm/plat-s3c24xx/cpu.c @@ -58,7 +58,7 @@ static const char name_s3c2400[] = "S3C2400"; static const char name_s3c2410[] = "S3C2410"; static const char name_s3c2412[] = "S3C2412"; -static const char name_s3c2416[] = "S3C2416"; +static const char name_s3c2416[] = "S3C2416/S3C2450"; static const char name_s3c2440[] = "S3C2440"; static const char name_s3c2442[] = "S3C2442"; static const char name_s3c2442b[] = "S3C2442B"; -- cgit v0.10.2 From 3998d095354d2a3062bdaa821ef07a1e1c82873c Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Sun, 9 May 2010 22:46:54 -0700 Subject: x86, hypervisor: add missing EXPORT_SYMBOL() needs to be included; fixes modular builds of the VMware balloon driver, and any future modular drivers which depends on the hypervisor. Reported-by: Ingo Molnar Signed-off-by: H. Peter Anvin Cc: Greg KH Cc: Hank Janssen Cc: Alok Kataria Cc: Ky Srinivasan Cc: Dmitry Torokhov LKML-Reference: <4BE49778.6060800@zytor.com> diff --git a/arch/x86/kernel/cpu/hypervisor.c b/arch/x86/kernel/cpu/hypervisor.c index 4afb5a2..dd531cc 100644 --- a/arch/x86/kernel/cpu/hypervisor.c +++ b/arch/x86/kernel/cpu/hypervisor.c @@ -21,6 +21,7 @@ * */ +#include #include #include diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index 0f13717..16f41bb 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -11,6 +11,7 @@ */ #include +#include #include #include #include -- cgit v0.10.2 From 19d8f84f86af867abee174be8bf1e4941a59143d Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 10 May 2010 15:39:05 +0900 Subject: sh: enable LMB region setup via machvec. This plugs in a memory init callback in the machvec to permit boards to wire up various bits of memory directly in to LMB. A generic machvec implementation is provided that simply wraps around the normal Kconfig-derived memory start/size. Signed-off-by: Paul Mundt diff --git a/arch/sh/include/asm/io_generic.h b/arch/sh/include/asm/io_generic.h index 1e5d375..491df93 100644 --- a/arch/sh/include/asm/io_generic.h +++ b/arch/sh/include/asm/io_generic.h @@ -38,5 +38,6 @@ void IO_CONCAT(__IO_PREFIX,iounmap)(void *addr); void __iomem *IO_CONCAT(__IO_PREFIX,ioport_map)(unsigned long addr, unsigned int size); void IO_CONCAT(__IO_PREFIX,ioport_unmap)(void __iomem *addr); +void IO_CONCAT(__IO_PREFIX,mem_init)(void); #undef __IO_PREFIX diff --git a/arch/sh/include/asm/machvec.h b/arch/sh/include/asm/machvec.h index 9c30955..bc0218c 100644 --- a/arch/sh/include/asm/machvec.h +++ b/arch/sh/include/asm/machvec.h @@ -49,6 +49,8 @@ struct sh_machine_vector { int (*mv_clk_init)(void); int (*mv_mode_pins)(void); + + void (*mv_mem_init)(void); }; extern struct sh_machine_vector sh_mv; diff --git a/arch/sh/include/asm/mmzone.h b/arch/sh/include/asm/mmzone.h index 7f5363b..94f04b2 100644 --- a/arch/sh/include/asm/mmzone.h +++ b/arch/sh/include/asm/mmzone.h @@ -42,7 +42,6 @@ setup_bootmem_node(int nid, unsigned long start, unsigned long end) void __init plat_mem_setup(void); /* arch/sh/kernel/setup.c */ -void __init setup_bootmem_allocator(unsigned long start_pfn); void __init __add_active_range(unsigned int nid, unsigned long start_pfn, unsigned long end_pfn); diff --git a/arch/sh/kernel/machvec.c b/arch/sh/kernel/machvec.c index 1652340..85cfaf9 100644 --- a/arch/sh/kernel/machvec.c +++ b/arch/sh/kernel/machvec.c @@ -131,6 +131,7 @@ void __init sh_mv_setup(void) mv_set(ioport_unmap); mv_set(irq_demux); mv_set(mode_pins); + mv_set(mem_init); if (!sh_mv.mv_nr_irqs) sh_mv.mv_nr_irqs = NR_IRQS; diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index e3f0da7..2c9ab28 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -4,7 +4,7 @@ * This file handles the architecture-dependent parts of initialization * * Copyright (C) 1999 Niibe Yutaka - * Copyright (C) 2002 - 2007 Paul Mundt + * Copyright (C) 2002 - 2010 Paul Mundt */ #include #include @@ -41,6 +41,7 @@ #include #include #include +#include /* * Initialize loops_per_jiffy as 10000000 (1000MIPS). @@ -247,7 +248,7 @@ void __init __add_active_range(unsigned int nid, unsigned long start_pfn, add_active_range(nid, start_pfn, end_pfn); } -void __init setup_bootmem_allocator(unsigned long free_pfn) +void __init do_init_bootmem(void) { unsigned long bootmap_size; unsigned long bootmap_pages, bootmem_paddr; @@ -298,12 +299,9 @@ void __init setup_bootmem_allocator(unsigned long free_pfn) sparse_memory_present_with_active_regions(0); } -#ifndef CONFIG_NEED_MULTIPLE_NODES static void __init setup_memory(void) { unsigned long start_pfn; - u64 base = min_low_pfn << PAGE_SHIFT; - u64 size = (max_low_pfn << PAGE_SHIFT) - base; /* * Partially used pages are not usable - thus @@ -311,8 +309,6 @@ static void __init setup_memory(void) */ start_pfn = PFN_UP(__pa(_end)); - lmb_add(base, size); - /* * Reserve the kernel text and * Reserve the bootmem bitmap. We do this in two steps (first step @@ -333,11 +329,9 @@ static void __init setup_memory(void) lmb_analyze(); lmb_dump_all(); - setup_bootmem_allocator(start_pfn); + do_init_bootmem(); + plat_mem_setup(); } -#else -extern void __init setup_memory(void); -#endif /* * Note: elfcorehdr_addr is not just limited to vmcore. It is also used by @@ -358,7 +352,11 @@ static int __init parse_elfcorehdr(char *arg) early_param("elfcorehdr", parse_elfcorehdr); #endif -void __init __attribute__ ((weak)) plat_early_device_setup(void) +void __init __weak plat_early_device_setup(void) +{ +} + +void __init __weak plat_mem_setup(void) { } @@ -426,7 +424,10 @@ void __init setup_arch(char **cmdline_p) /* Let earlyprintk output early console messages */ early_platform_driver_probe("earlyprintk", 1, 1); + lmb_init(); + sh_mv_setup(); + sh_mv.mv_mem_init(); /* * Find the highest page frame number we have available @@ -442,7 +443,6 @@ void __init setup_arch(char **cmdline_p) nodes_clear(node_online_map); pmb_init(); - lmb_init(); setup_memory(); sparse_init(); diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c index c505de6..9c5400b 100644 --- a/arch/sh/mm/init.c +++ b/arch/sh/mm/init.c @@ -2,7 +2,7 @@ * linux/arch/sh/mm/init.c * * Copyright (C) 1999 Niibe Yutaka - * Copyright (C) 2002 - 2007 Paul Mundt + * Copyright (C) 2002 - 2010 Paul Mundt * * Based on linux/arch/i386/mm/init.c: * Copyright (C) 1995 Linus Torvalds @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -27,6 +28,11 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); pgd_t swapper_pg_dir[PTRS_PER_PGD]; +void __init generic_mem_init(void) +{ + lmb_add(__MEMORY_START, __MEMORY_SIZE); +} + #ifdef CONFIG_MMU static pte_t *__get_pte_phys(unsigned long addr) { -- cgit v0.10.2 From af507ae8a0512a83728b17d8f8c5fa1561669f50 Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Mon, 10 May 2010 11:24:27 +0800 Subject: sched: Remove a stale comment This comment should have been removed together with uids_mutex when removing user sched. Signed-off-by: Li Zefan Cc: Peter Zijlstra Cc: Dhaval Giani LKML-Reference: <4BE77C6B.5010402@cn.fujitsu.com> Signed-off-by: Ingo Molnar diff --git a/kernel/user.c b/kernel/user.c index 8e1c8c0..7e72614 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -136,7 +136,6 @@ struct user_struct *alloc_uid(struct user_namespace *ns, uid_t uid) struct hlist_head *hashent = uidhashentry(ns, uid); struct user_struct *up, *new; - /* Make uid_hash_find() + uid_hash_insert() atomic. */ spin_lock_irq(&uidhash_lock); up = uid_hash_find(uid, hashent); spin_unlock_irq(&uidhash_lock); -- cgit v0.10.2 From 0217f1499cf880d93c64579b2943e9382d8c2c21 Mon Sep 17 00:00:00 2001 From: Andrej Gelenberg Date: Sun, 9 May 2010 22:10:41 +0200 Subject: ALSA: hda - add support for Lenovo ThinkPad X100e in conexant codec Ideapad quirks working for my ThinkPad X100e (microphone is not tested). Signed-off-by: Andrej Gelenberg Signed-off-by: Takashi Iwai diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 56e5207..d8213e2 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -2846,6 +2846,7 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = { SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5), SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5), + SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x3a0d, "ideapad", CXT5066_IDEAPAD), {} }; -- cgit v0.10.2 From 5e2ff328c0668794ff408a4632f5b8a62827571f Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 10 May 2010 20:17:25 +0900 Subject: sh: rework memory limits to work with LMB. This reworks the memory limit handling to tie in through the available LMB infrastructure. This requires a bit of reordering as we need to have all of the LMB reservations taken care of prior to establishing the limits. While we're at it, the crash kernel reservation semantics are reworked so that we allocate from the bottom up and reduce the risk of having to disable the memory limit due to a clash with the crash kernel reservation. Signed-off-by: Paul Mundt diff --git a/arch/sh/include/asm/page.h b/arch/sh/include/asm/page.h index 0152c04..fb703d1 100644 --- a/arch/sh/include/asm/page.h +++ b/arch/sh/include/asm/page.h @@ -49,7 +49,7 @@ extern unsigned long shm_align_mask; extern unsigned long max_low_pfn, min_low_pfn; -extern unsigned long memory_start, memory_end; +extern unsigned long memory_start, memory_end, memory_limit; static inline unsigned long pages_do_alias(unsigned long addr1, unsigned long addr2) diff --git a/arch/sh/kernel/machine_kexec.c b/arch/sh/kernel/machine_kexec.c index f0f049c..7f68fc0 100644 --- a/arch/sh/kernel/machine_kexec.c +++ b/arch/sh/kernel/machine_kexec.c @@ -169,7 +169,8 @@ void __init reserve_crashkernel(void) crash_size = PAGE_ALIGN(crashk_res.end - crashk_res.start + 1); if (!crashk_res.start) { - crashk_res.start = lmb_alloc(crash_size, PAGE_SIZE); + unsigned long max = lmb_end_of_DRAM() - memory_limit; + crashk_res.start = __lmb_alloc_base(crash_size, PAGE_SIZE, max); if (!crashk_res.start) { pr_err("crashkernel allocation failed\n"); goto disable; @@ -183,15 +184,22 @@ void __init reserve_crashkernel(void) } } - pr_info("Reserving %ldMB of memory at %ldMB " + crashk_res.end = crashk_res.start + crash_size - 1; + + /* + * Crash kernel trumps memory limit + */ + if ((lmb_end_of_DRAM() - memory_limit) <= crashk_res.end) { + memory_limit = 0; + pr_info("Disabled memory limit for crashkernel\n"); + } + + pr_info("Reserving %ldMB of memory at 0x%08lx " "for crashkernel (System RAM: %ldMB)\n", (unsigned long)(crash_size >> 20), - (unsigned long)(crashk_res.start >> 20), + (unsigned long)(crashk_res.start), (unsigned long)(lmb_phys_mem_size() >> 20)); - crashk_res.end = crashk_res.start + crash_size - 1; - insert_resource(&iomem_resource, &crashk_res); - return; disable: diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 2c9ab28..f6a2db1 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -95,6 +95,7 @@ unsigned long memory_start; EXPORT_SYMBOL(memory_start); unsigned long memory_end = 0; EXPORT_SYMBOL(memory_end); +unsigned long memory_limit = 0; static struct resource mem_resources[MAX_NUMNODES]; @@ -102,21 +103,12 @@ int l1i_cache_shape, l1d_cache_shape, l2_cache_shape; static int __init early_parse_mem(char *p) { - unsigned long size; + if (!p) + return 1; - memory_start = (unsigned long)__va(__MEMORY_START); - size = memparse(p, &p); - - if (size > __MEMORY_SIZE) { - printk(KERN_ERR - "Using mem= to increase the size of kernel memory " - "is not allowed.\n" - " Recompile the kernel with the correct value for " - "CONFIG_MEMORY_SIZE.\n"); - return 0; - } + memory_limit = PAGE_ALIGN(memparse(p, &p)); - memory_end = memory_start + size; + pr_notice("Memory limited to %ldMB\n", memory_limit >> 20); return 0; } @@ -252,7 +244,7 @@ void __init do_init_bootmem(void) { unsigned long bootmap_size; unsigned long bootmap_pages, bootmem_paddr; - u64 total_pages = (lmb_end_of_DRAM() - __MEMORY_START) >> PAGE_SHIFT; + u64 total_pages = lmb_phys_mem_size() >> PAGE_SHIFT; int i; bootmap_pages = bootmem_bootmap_pages(total_pages); @@ -277,12 +269,6 @@ void __init do_init_bootmem(void) } /* - * Handle additional early reservations - */ - check_for_initrd(); - reserve_crashkernel(); - - /* * Add all physical memory to the bootmem map and mark each * area as present. */ @@ -299,7 +285,7 @@ void __init do_init_bootmem(void) sparse_memory_present_with_active_regions(0); } -static void __init setup_memory(void) +static void __init early_reserve_mem(void) { unsigned long start_pfn; @@ -326,11 +312,11 @@ static void __init setup_memory(void) if (CONFIG_ZERO_PAGE_OFFSET != 0) lmb_reserve(__MEMORY_START, CONFIG_ZERO_PAGE_OFFSET); - lmb_analyze(); - lmb_dump_all(); - - do_init_bootmem(); - plat_mem_setup(); + /* + * Handle additional early reservations + */ + check_for_initrd(); + reserve_crashkernel(); } /* @@ -397,10 +383,6 @@ void __init setup_arch(char **cmdline_p) bss_resource.start = virt_to_phys(__bss_start); bss_resource.end = virt_to_phys(_ebss)-1; - memory_start = (unsigned long)__va(__MEMORY_START); - if (!memory_end) - memory_end = memory_start + __MEMORY_SIZE; - #ifdef CONFIG_CMDLINE_OVERWRITE strlcpy(command_line, CONFIG_CMDLINE, sizeof(command_line)); #else @@ -417,8 +399,6 @@ void __init setup_arch(char **cmdline_p) parse_early_param(); - uncached_init(); - plat_early_device_setup(); /* Let earlyprintk output early console messages */ @@ -429,21 +409,28 @@ void __init setup_arch(char **cmdline_p) sh_mv_setup(); sh_mv.mv_mem_init(); - /* - * Find the highest page frame number we have available - */ - max_pfn = PFN_DOWN(__pa(memory_end)); + early_reserve_mem(); + + lmb_enforce_memory_limit(memory_limit); + lmb_analyze(); + + lmb_dump_all(); /* * Determine low and high memory ranges: */ - max_low_pfn = max_pfn; + max_low_pfn = max_pfn = lmb_end_of_DRAM() >> PAGE_SHIFT; min_low_pfn = __MEMORY_START >> PAGE_SHIFT; nodes_clear(node_online_map); + memory_start = (unsigned long)__va(__MEMORY_START); + memory_end = memory_start + (memory_limit ?: lmb_phys_mem_size()); + + uncached_init(); pmb_init(); - setup_memory(); + do_init_bootmem(); + plat_mem_setup(); sparse_init(); #ifdef CONFIG_DUMMY_CONSOLE -- cgit v0.10.2 From bbd725435ddb1cac732f7a8c23c21ff67f24c60f Mon Sep 17 00:00:00 2001 From: Andreas Meissner Date: Mon, 10 May 2010 04:47:49 -0700 Subject: IPv4: unresolved multicast route cleanup Fixes the expiration timer for unresolved multicast route entries. In case new multicast routing requests come in faster than the expiration timeout occurs (e.g. zap through multicast TV streams), the timer is prevented from being called at time for already existing entries. As the single timer is resetted to default whenever a new entry is made, the timeout for existing unresolved entires are missed and/or not updated. As a consequence new requests are denied when the limit of unresolved entries has been reached because old entries live longer than they are supposed to. The solution is to reset the timer only for the first unresolved entry in the multicast routing cache. All other timers are already set and updated correctly within the timer function itself by now. Signed-off by: Andreas Meissner Signed-off-by: David S. Miller diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 9d4f6d1..ec19a89 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -754,7 +754,8 @@ ipmr_cache_unresolved(struct net *net, vifi_t vifi, struct sk_buff *skb) c->next = mfc_unres_queue; mfc_unres_queue = c; - mod_timer(&ipmr_expire_timer, c->mfc_un.unres.expires); + if (atomic_read(&net->ipv4.cache_resolve_queue_len) == 1) + mod_timer(&ipmr_expire_timer, c->mfc_un.unres.expires); } /* -- cgit v0.10.2 From f0ecde1466f21edf577b809735f4f35f354777a0 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 10 May 2010 04:59:07 -0700 Subject: net: Fix FDDI and TR config checks in ipv4 arp and LLC. Need to check both CONFIG_FOO and CONFIG_FOO_MODULE Signed-off-by: David S. Miller diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 6e74706..80769f1 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -661,13 +661,13 @@ struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip, #endif #endif -#ifdef CONFIG_FDDI +#if defined(CONFIG_FDDI) || defined(CONFIG_FDDI_MODULE) case ARPHRD_FDDI: arp->ar_hrd = htons(ARPHRD_ETHER); arp->ar_pro = htons(ETH_P_IP); break; #endif -#ifdef CONFIG_TR +#if defined(CONFIG_TR) || defined(CONFIG_TR_MODULE) case ARPHRD_IEEE802_TR: arp->ar_hrd = htons(ARPHRD_IEEE802); arp->ar_pro = htons(ETH_P_IP); @@ -1051,7 +1051,7 @@ static int arp_req_set(struct net *net, struct arpreq *r, return -EINVAL; } switch (dev->type) { -#ifdef CONFIG_FDDI +#if defined(CONFIG_FDDI) || defined(CONFIG_FDDI_MODULE) case ARPHRD_FDDI: /* * According to RFC 1390, FDDI devices should accept ARP diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c index a432f0e..94e7fca 100644 --- a/net/llc/llc_sap.c +++ b/net/llc/llc_sap.c @@ -31,7 +31,7 @@ static int llc_mac_header_len(unsigned short devtype) case ARPHRD_ETHER: case ARPHRD_LOOPBACK: return sizeof(struct ethhdr); -#ifdef CONFIG_TR +#if defined(CONFIG_TR) || defined(CONFIG_TR_MODULE) case ARPHRD_IEEE802_TR: return sizeof(struct trh_hdr); #endif -- cgit v0.10.2 From 7f8264539c62378cccbdf9b598927b034bef4a92 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 10 May 2010 10:51:25 -0300 Subject: perf newt: Use newtAddComponent() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of newtAddComponents(just-one-entry, NULL), that is not needed if, like in this browser, we're adding just one component at a time. Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index 7a123a9..e283a6e 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -31,7 +31,7 @@ struct ui_progress *ui_progress__new(const char *title, u64 total) self->scale = newtScale(0, 0, cols, total); if (self->scale == NULL) goto out_free_form; - newtFormAddComponents(self->form, self->scale, NULL); + newtFormAddComponent(self->form, self->scale); newtRefresh(); } @@ -107,7 +107,7 @@ static int popup_menu(int argc, char * const argv[]) if (listbox == NULL) goto out_destroy_form; - newtFormAddComponents(form, listbox, NULL); + newtFormAddComponent(form, listbox); for (i = 0; i < argc; ++i) { int len = strlen(argv[i]); @@ -365,7 +365,7 @@ static void map_symbol__annotate_browser(const struct map_symbol *self, newtCenteredWindow(max_line_len + 2, rows - 5, self->sym->name); form = newt_form__new(); - newtFormAddComponents(form, tree, NULL); + newtFormAddComponent(form, tree); newtFormRun(form, &es); newtFormDestroy(form); -- cgit v0.10.2 From 51c8176472de1551a301b676e36a61884e0e8494 Mon Sep 17 00:00:00 2001 From: Suresh Jayaraman Date: Mon, 10 May 2010 15:15:24 +0530 Subject: cifs: remove unused parameter from cifs_posix_open_inode_helper() ..a left over from the commit 3321b791b2e8897323f8c044a0c77ff25781381c. Cc: Jeff Layton Signed-off-by: Suresh Jayaraman Signed-off-by: Steve French diff --git a/fs/cifs/file.c b/fs/cifs/file.c index d53d630..a83541e 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -108,8 +108,7 @@ static inline int cifs_get_disposition(unsigned int flags) /* all arguments to this function must be checked for validity in caller */ static inline int cifs_posix_open_inode_helper(struct inode *inode, struct file *file, - struct cifsInodeInfo *pCifsInode, - struct cifsFileInfo *pCifsFile, __u32 oplock, + struct cifsInodeInfo *pCifsInode, __u32 oplock, u16 netfid) { @@ -311,7 +310,7 @@ int cifs_open(struct inode *inode, struct file *file) pCifsFile = cifs_fill_filedata(file); cifs_posix_open_inode_helper(inode, file, pCifsInode, - pCifsFile, oplock, netfid); + oplock, netfid); goto out; } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { if (tcon->ses->serverNOS) -- cgit v0.10.2 From cdd5b75b0cd24c4d6a98b12a219217b1ccfe2586 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 10 May 2010 10:56:50 -0300 Subject: perf callchains: Use zalloc to allocate objects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index ac14861..21a52e0 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c @@ -167,7 +167,7 @@ create_child(struct callchain_node *parent, bool inherit_children) { struct callchain_node *new; - new = malloc(sizeof(*new)); + new = zalloc(sizeof(*new)); if (!new) { perror("not enough memory to create child for code path tree"); return NULL; @@ -213,7 +213,7 @@ fill_node(struct callchain_node *node, struct resolved_chain *chain, int start) for (i = start; i < chain->nr; i++) { struct callchain_list *call; - call = malloc(sizeof(*call)); + call = zalloc(sizeof(*call)); if (!call) { perror("not enough memory for the code path tree"); return; @@ -386,7 +386,7 @@ int append_chain(struct callchain_node *root, struct ip_callchain *chain, if (!chain->nr) return 0; - filtered = malloc(sizeof(*filtered) + + filtered = zalloc(sizeof(*filtered) + chain->nr * sizeof(struct resolved_ip)); if (!filtered) return -ENOMEM; -- cgit v0.10.2 From 482c45331519524e4aeaf8a9084a445500822b85 Mon Sep 17 00:00:00 2001 From: Stefan Lippers-Hollmann Date: Mon, 10 May 2010 17:14:34 +0200 Subject: ALSA: Revert "ALSA: hda/realtek: quirk for D945GCLF2 mainboard" This reverts commit 7aee67466536bbf8bb44a95712c848a61c5a0acd. As it doesn't seem to be universally valid for all mainboard revisions of the D945GCLF2 and breaks snd-hda-intel/ snd-hda-codec-realtek on the Intel Corporation "D945GCLF2" (LF94510J.86A.0229.2009.0729.0209) mainboard. 00:1b.0 Audio device [0403]: Intel Corporation N10/ICH 7 Family High Definition Audio Controller [8086:27d8] (rev 01) Signed-off-by: Stefan Lippers-Hollmann Cc: [2.6.33] Signed-off-by: Takashi Iwai diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 7404dba..886d8e4 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -17871,7 +17871,6 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = { ALC662_3ST_6ch_DIG), SND_PCI_QUIRK_MASK(0x1854, 0xf000, 0x2000, "ASUS H13-200x", ALC663_ASUS_H13), - SND_PCI_QUIRK(0x8086, 0xd604, "Intel mobo", ALC662_3ST_2ch_DIG), {} }; -- cgit v0.10.2 From d118f8ba6ac2af2bf11d40cba657c813f0f39ca2 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 10 May 2010 12:51:05 -0300 Subject: perf session: create_kernel_maps should use ->host_machine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using machines__create_kernel_maps(..., HOST_KERNEL_ID) it would create another machine instance for the host machine, and since 1f626bc we have it out of the machines rb_tree. Fix it by using machine__create_kernel_maps(&self->host_machine) directly. Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index c088d8f..4130036 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -69,11 +69,10 @@ void perf_session__update_sample_type(struct perf_session *self) int perf_session__create_kernel_maps(struct perf_session *self) { - struct rb_root *machines = &self->machines; - int ret = machines__create_kernel_maps(machines, HOST_KERNEL_ID); + int ret = machine__create_kernel_maps(&self->host_machine); if (ret >= 0) - ret = machines__create_guest_kernel_maps(machines); + ret = machines__create_guest_kernel_maps(&self->machines); return ret; } -- cgit v0.10.2 From 1c02c4d2e92f2097f1bba63ec71560b0e05a7f36 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 10 May 2010 13:04:11 -0300 Subject: perf hist: Introduce hists class and move lots of methods to it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In cbbc79a we introduced support for multiple events by introducing a new "event_stat_id" struct and then made several perf_session methods receive a point to it instead of a pointer to perf_session, and kept the event_stats and hists rb_tree in perf_session. While working on the new newt based browser, I realised that it would be better to introduce a new class, "hists" (short for "histograms"), renaming the "event_stat_id" struct and the perf_session methods that were really "hists" methods, as they manipulate only struct hists members, not touching anything in the other perf_session members. Other optimizations, such as calculating the maximum lenght of a symbol name present in an hists instance will be possible as we add them, avoiding a re-traversal just for finding that information. The rationale for the name "hists" to replace "event_stat_id" is that we may have multiple sets of hists for the same event_stat id, as, for instance, the 'perf diff' tool has, so event stat id is not what characterizes what this struct and the functions that manipulate it do. Cc: Eric B Munson Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index c7ac45a..3940964 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -96,8 +96,7 @@ static int annotate__hist_hit(struct hist_entry *he, u64 ip) return 0; } -static int perf_session__add_hist_entry(struct perf_session *self, - struct addr_location *al) +static int hists__add_entry(struct hists *self, struct addr_location *al) { struct hist_entry *he; @@ -112,7 +111,7 @@ static int perf_session__add_hist_entry(struct perf_session *self, return 0; } - he = __perf_session__add_hist_entry(&self->hists, al, NULL, 1); + he = __hists__add_entry(self, al, NULL, 1); if (he == NULL) return -ENOMEM; @@ -132,7 +131,7 @@ static int process_sample_event(event_t *event, struct perf_session *session) return -1; } - if (!al.filtered && perf_session__add_hist_entry(session, &al)) { + if (!al.filtered && hists__add_entry(&session->hists, &al)) { pr_warning("problem incrementing symbol count, " "skipping event\n"); return -1; @@ -514,11 +513,11 @@ static void annotate_sym(struct hist_entry *he) free_source_line(he, len); } -static void perf_session__find_annotations(struct perf_session *self) +static void hists__find_annotations(struct hists *self) { struct rb_node *nd; - for (nd = rb_first(&self->hists); nd; nd = rb_next(nd)) { + for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) { struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node); struct sym_priv *priv; @@ -570,9 +569,9 @@ static int __cmd_annotate(void) if (verbose > 2) perf_session__fprintf_dsos(session, stdout); - perf_session__collapse_resort(&session->hists); - perf_session__output_resort(&session->hists, session->event_total[0]); - perf_session__find_annotations(session); + hists__collapse_resort(&session->hists); + hists__output_resort(&session->hists); + hists__find_annotations(&session->hists); out_delete: perf_session__delete(session); diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 613a5c4..3a95a02 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -22,10 +22,10 @@ static char diff__default_sort_order[] = "dso,symbol"; static bool force; static bool show_displacement; -static int perf_session__add_hist_entry(struct perf_session *self, - struct addr_location *al, u64 count) +static int hists__add_entry(struct hists *self, + struct addr_location *al, u64 count) { - if (__perf_session__add_hist_entry(&self->hists, al, NULL, count) != NULL) + if (__hists__add_entry(self, al, NULL, count) != NULL) return 0; return -ENOMEM; } @@ -49,12 +49,12 @@ static int diff__process_sample_event(event_t *event, struct perf_session *sessi event__parse_sample(event, session->sample_type, &data); - if (perf_session__add_hist_entry(session, &al, data.period)) { + if (hists__add_entry(&session->hists, &al, data.period)) { pr_warning("problem incrementing symbol count, skipping event\n"); return -1; } - session->events_stats.total += data.period; + session->hists.stats.total += data.period; return 0; } @@ -87,35 +87,34 @@ static void perf_session__insert_hist_entry_by_name(struct rb_root *root, rb_insert_color(&he->rb_node, root); } -static void perf_session__resort_hist_entries(struct perf_session *self) +static void hists__resort_entries(struct hists *self) { unsigned long position = 1; struct rb_root tmp = RB_ROOT; - struct rb_node *next = rb_first(&self->hists); + struct rb_node *next = rb_first(&self->entries); while (next != NULL) { struct hist_entry *n = rb_entry(next, struct hist_entry, rb_node); next = rb_next(&n->rb_node); - rb_erase(&n->rb_node, &self->hists); + rb_erase(&n->rb_node, &self->entries); n->position = position++; perf_session__insert_hist_entry_by_name(&tmp, n); } - self->hists = tmp; + self->entries = tmp; } -static void perf_session__set_hist_entries_positions(struct perf_session *self) +static void hists__set_positions(struct hists *self) { - perf_session__output_resort(&self->hists, self->events_stats.total); - perf_session__resort_hist_entries(self); + hists__output_resort(self); + hists__resort_entries(self); } -static struct hist_entry * -perf_session__find_hist_entry(struct perf_session *self, - struct hist_entry *he) +static struct hist_entry *hists__find_entry(struct hists *self, + struct hist_entry *he) { - struct rb_node *n = self->hists.rb_node; + struct rb_node *n = self->entries.rb_node; while (n) { struct hist_entry *iter = rb_entry(n, struct hist_entry, rb_node); @@ -132,14 +131,13 @@ perf_session__find_hist_entry(struct perf_session *self, return NULL; } -static void perf_session__match_hists(struct perf_session *old_session, - struct perf_session *new_session) +static void hists__match(struct hists *older, struct hists *newer) { struct rb_node *nd; - for (nd = rb_first(&new_session->hists); nd; nd = rb_next(nd)) { + for (nd = rb_first(&newer->entries); nd; nd = rb_next(nd)) { struct hist_entry *pos = rb_entry(nd, struct hist_entry, rb_node); - pos->pair = perf_session__find_hist_entry(old_session, pos); + pos->pair = hists__find_entry(older, pos); } } @@ -159,15 +157,13 @@ static int __cmd_diff(void) goto out_delete; } - perf_session__output_resort(&session[1]->hists, - session[1]->events_stats.total); + hists__output_resort(&session[1]->hists); if (show_displacement) - perf_session__set_hist_entries_positions(session[0]); + hists__set_positions(&session[0]->hists); - perf_session__match_hists(session[0], session[1]); - perf_session__fprintf_hists(&session[1]->hists, session[0], - show_displacement, stdout, - session[1]->events_stats.total); + hists__match(&session[0]->hists, &session[1]->hists); + hists__fprintf(&session[1]->hists, &session[0]->hists, + show_displacement, stdout); out_delete: for (i = 0; i < 2; ++i) perf_session__delete(session[i]); diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 642a6d8..53077fd 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -44,16 +44,17 @@ static char *pretty_printing_style = default_pretty_printing_style; static char callchain_default_opt[] = "fractal,0.5"; -static struct event_stat_id *get_stats(struct perf_session *self, - u64 event_stream, u32 type, u64 config) +static struct hists *perf_session__hists_findnew(struct perf_session *self, + u64 event_stream, u32 type, + u64 config) { - struct rb_node **p = &self->stats_by_id.rb_node; + struct rb_node **p = &self->hists_tree.rb_node; struct rb_node *parent = NULL; - struct event_stat_id *iter, *new; + struct hists *iter, *new; while (*p != NULL) { parent = *p; - iter = rb_entry(parent, struct event_stat_id, rb_node); + iter = rb_entry(parent, struct hists, rb_node); if (iter->config == config) return iter; @@ -64,15 +65,15 @@ static struct event_stat_id *get_stats(struct perf_session *self, p = &(*p)->rb_left; } - new = malloc(sizeof(struct event_stat_id)); + new = malloc(sizeof(struct hists)); if (new == NULL) return NULL; - memset(new, 0, sizeof(struct event_stat_id)); + memset(new, 0, sizeof(struct hists)); new->event_stream = event_stream; new->config = config; new->type = type; rb_link_node(&new->rb_node, parent, p); - rb_insert_color(&new->rb_node, &self->stats_by_id); + rb_insert_color(&new->rb_node, &self->hists_tree); return new; } @@ -84,7 +85,7 @@ static int perf_session__add_hist_entry(struct perf_session *self, struct symbol *parent = NULL; int err = -ENOMEM; struct hist_entry *he; - struct event_stat_id *stats; + struct hists *hists; struct perf_event_attr *attr; if ((sort__has_parent || symbol_conf.use_callchain) && data->callchain) { @@ -96,13 +97,12 @@ static int perf_session__add_hist_entry(struct perf_session *self, attr = perf_header__find_attr(data->id, &self->header); if (attr) - stats = get_stats(self, data->id, attr->type, attr->config); + hists = perf_session__hists_findnew(self, data->id, attr->type, attr->config); else - stats = get_stats(self, data->id, 0, 0); - if (stats == NULL) + hists = perf_session__hists_findnew(self, data->id, 0, 0); + if (hists == NULL) goto out_free_syms; - he = __perf_session__add_hist_entry(&stats->hists, al, parent, - data->period); + he = __hists__add_entry(hists, al, parent, data->period); if (he == NULL) goto out_free_syms; err = 0; @@ -117,18 +117,19 @@ static int add_event_total(struct perf_session *session, struct sample_data *data, struct perf_event_attr *attr) { - struct event_stat_id *stats; + struct hists *hists; if (attr) - stats = get_stats(session, data->id, attr->type, attr->config); + hists = perf_session__hists_findnew(session, data->id, + attr->type, attr->config); else - stats = get_stats(session, data->id, 0, 0); + hists = perf_session__hists_findnew(session, data->id, 0, 0); - if (!stats) + if (!hists) return -ENOMEM; - stats->stats.total += data->period; - session->events_stats.total += data->period; + hists->stats.total += data->period; + session->hists.stats.total += data->period; return 0; } @@ -292,35 +293,33 @@ static int __cmd_report(void) if (verbose > 2) perf_session__fprintf_dsos(session, stdout); - next = rb_first(&session->stats_by_id); + next = rb_first(&session->hists_tree); while (next) { - struct event_stat_id *stats; + struct hists *hists; u64 nr_hists; - stats = rb_entry(next, struct event_stat_id, rb_node); - perf_session__collapse_resort(&stats->hists); - nr_hists = perf_session__output_resort(&stats->hists, - stats->stats.total); + hists = rb_entry(next, struct hists, rb_node); + hists__collapse_resort(hists); + nr_hists = hists__output_resort(hists); if (use_browser) - perf_session__browse_hists(&stats->hists, nr_hists, - stats->stats.total, help, + perf_session__browse_hists(&hists->entries, nr_hists, + hists->stats.total, help, input_name); else { - if (rb_first(&session->stats_by_id) == - rb_last(&session->stats_by_id)) + if (rb_first(&session->hists.entries) == + rb_last(&session->hists.entries)) fprintf(stdout, "# Samples: %Ld\n#\n", - stats->stats.total); + hists->stats.total); else fprintf(stdout, "# Samples: %Ld %s\n#\n", - stats->stats.total, - __event_name(stats->type, stats->config)); + hists->stats.total, + __event_name(hists->type, hists->config)); - perf_session__fprintf_hists(&stats->hists, NULL, false, stdout, - stats->stats.total); + hists__fprintf(hists, NULL, false, stdout); fprintf(stdout, "\n\n"); } - next = rb_next(&stats->rb_node); + next = rb_next(&hists->rb_node); } if (!use_browser && sort_order == default_sort_order && diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 9c483e9..6e268ca 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -107,7 +107,7 @@ static int process_sample_event(event_t *event, struct perf_session *session) data.time, thread->comm); } - session->events_stats.total += data.period; + session->hists.stats.total += data.period; return 0; } diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index d2ea9dd..cce006e 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -368,7 +368,7 @@ int event__process_comm(event_t *self, struct perf_session *session) int event__process_lost(event_t *self, struct perf_session *session) { dump_printf(": id:%Ld: lost:%Ld\n", self->lost.id, self->lost.lost); - session->events_stats.lost += self->lost.lost; + session->hists.stats.lost += self->lost.lost; return 0; } diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 6cc1b1d..48c2cc9 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -131,20 +131,6 @@ typedef union event_union { struct build_id_event build_id; } event_t; -struct events_stats { - u64 total; - u64 lost; -}; - -struct event_stat_id { - struct rb_node rb_node; - struct rb_root hists; - struct events_stats stats; - u64 config; - u64 event_stream; - u32 type; -}; - void event__print_totals(void); struct perf_session; diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 0f154a5..410cf56 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -8,21 +8,21 @@ struct callchain_param callchain_param = { .min_percent = 0.5 }; -static void perf_session__add_cpumode_count(struct hist_entry *he, - unsigned int cpumode, u64 count) +static void hist_entry__add_cpumode_count(struct hist_entry *self, + unsigned int cpumode, u64 count) { switch (cpumode) { case PERF_RECORD_MISC_KERNEL: - he->count_sys += count; + self->count_sys += count; break; case PERF_RECORD_MISC_USER: - he->count_us += count; + self->count_us += count; break; case PERF_RECORD_MISC_GUEST_KERNEL: - he->count_guest_sys += count; + self->count_guest_sys += count; break; case PERF_RECORD_MISC_GUEST_USER: - he->count_guest_us += count; + self->count_guest_us += count; break; default: break; @@ -47,12 +47,11 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template) return self; } -struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists, - struct addr_location *al, - struct symbol *sym_parent, - u64 count) +struct hist_entry *__hists__add_entry(struct hists *self, + struct addr_location *al, + struct symbol *sym_parent, u64 count) { - struct rb_node **p = &hists->rb_node; + struct rb_node **p = &self->entries.rb_node; struct rb_node *parent = NULL; struct hist_entry *he; struct hist_entry entry = { @@ -89,9 +88,9 @@ struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists, if (!he) return NULL; rb_link_node(&he->rb_node, parent, p); - rb_insert_color(&he->rb_node, hists); + rb_insert_color(&he->rb_node, &self->entries); out: - perf_session__add_cpumode_count(he, al->cpumode, count); + hist_entry__add_cpumode_count(he, al->cpumode, count); return he; } @@ -167,7 +166,7 @@ static void collapse__insert_entry(struct rb_root *root, struct hist_entry *he) rb_insert_color(&he->rb_node, root); } -void perf_session__collapse_resort(struct rb_root *hists) +void hists__collapse_resort(struct hists *self) { struct rb_root tmp; struct rb_node *next; @@ -177,28 +176,28 @@ void perf_session__collapse_resort(struct rb_root *hists) return; tmp = RB_ROOT; - next = rb_first(hists); + next = rb_first(&self->entries); while (next) { n = rb_entry(next, struct hist_entry, rb_node); next = rb_next(&n->rb_node); - rb_erase(&n->rb_node, hists); + rb_erase(&n->rb_node, &self->entries); collapse__insert_entry(&tmp, n); } - *hists = tmp; + self->entries = tmp; } /* * reverse the map, sort on count. */ -static void perf_session__insert_output_hist_entry(struct rb_root *root, - struct hist_entry *he, - u64 min_callchain_hits) +static void __hists__insert_output_entry(struct rb_root *entries, + struct hist_entry *he, + u64 min_callchain_hits) { - struct rb_node **p = &root->rb_node; + struct rb_node **p = &entries->rb_node; struct rb_node *parent = NULL; struct hist_entry *iter; @@ -217,10 +216,10 @@ static void perf_session__insert_output_hist_entry(struct rb_root *root, } rb_link_node(&he->rb_node, parent, p); - rb_insert_color(&he->rb_node, root); + rb_insert_color(&he->rb_node, entries); } -u64 perf_session__output_resort(struct rb_root *hists, u64 total_samples) +u64 hists__output_resort(struct hists *self) { struct rb_root tmp; struct rb_node *next; @@ -228,23 +227,21 @@ u64 perf_session__output_resort(struct rb_root *hists, u64 total_samples) u64 min_callchain_hits; u64 nr_hists = 0; - min_callchain_hits = - total_samples * (callchain_param.min_percent / 100); + min_callchain_hits = self->stats.total * (callchain_param.min_percent / 100); tmp = RB_ROOT; - next = rb_first(hists); + next = rb_first(&self->entries); while (next) { n = rb_entry(next, struct hist_entry, rb_node); next = rb_next(&n->rb_node); - rb_erase(&n->rb_node, hists); - perf_session__insert_output_hist_entry(&tmp, n, - min_callchain_hits); + rb_erase(&n->rb_node, &self->entries); + __hists__insert_output_entry(&tmp, n, min_callchain_hits); ++nr_hists; } - *hists = tmp; + self->entries = tmp; return nr_hists; } @@ -500,12 +497,9 @@ static size_t hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self, return ret; } -int hist_entry__snprintf(struct hist_entry *self, - char *s, size_t size, - struct perf_session *pair_session, - bool show_displacement, - long displacement, bool color, - u64 session_total) +int hist_entry__snprintf(struct hist_entry *self, char *s, size_t size, + struct hists *pair_hists, bool show_displacement, + long displacement, bool color, u64 session_total) { struct sort_entry *se; u64 count, total, count_sys, count_us, count_guest_sys, count_guest_us; @@ -515,9 +509,9 @@ int hist_entry__snprintf(struct hist_entry *self, if (symbol_conf.exclude_other && !self->parent) return 0; - if (pair_session) { + if (pair_hists) { count = self->pair ? self->pair->count : 0; - total = pair_session->events_stats.total; + total = pair_hists->stats.total; count_sys = self->pair ? self->pair->count_sys : 0; count_us = self->pair ? self->pair->count_us : 0; count_guest_sys = self->pair ? self->pair->count_guest_sys : 0; @@ -569,7 +563,7 @@ int hist_entry__snprintf(struct hist_entry *self, ret += snprintf(s + ret, size - ret, "%11lld", count); } - if (pair_session) { + if (pair_hists) { char bf[32]; double old_percent = 0, new_percent = 0, diff; @@ -615,14 +609,12 @@ int hist_entry__snprintf(struct hist_entry *self, return ret; } -int hist_entry__fprintf(struct hist_entry *self, - struct perf_session *pair_session, - bool show_displacement, - long displacement, FILE *fp, +int hist_entry__fprintf(struct hist_entry *self, struct hists *pair_hists, + bool show_displacement, long displacement, FILE *fp, u64 session_total) { char bf[512]; - hist_entry__snprintf(self, bf, sizeof(bf), pair_session, + hist_entry__snprintf(self, bf, sizeof(bf), pair_hists, show_displacement, displacement, true, session_total); return fprintf(fp, "%s\n", bf); @@ -644,10 +636,8 @@ static size_t hist_entry__fprintf_callchain(struct hist_entry *self, FILE *fp, left_margin); } -size_t perf_session__fprintf_hists(struct rb_root *hists, - struct perf_session *pair, - bool show_displacement, FILE *fp, - u64 session_total) +size_t hists__fprintf(struct hists *self, struct hists *pair, + bool show_displacement, FILE *fp) { struct sort_entry *se; struct rb_node *nd; @@ -753,7 +743,7 @@ size_t perf_session__fprintf_hists(struct rb_root *hists, fprintf(fp, "\n#\n"); print_entries: - for (nd = rb_first(hists); nd; nd = rb_next(nd)) { + for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) { struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); if (show_displacement) { @@ -765,10 +755,10 @@ print_entries: ++position; } ret += hist_entry__fprintf(h, pair, show_displacement, - displacement, fp, session_total); + displacement, fp, self->stats.total); if (symbol_conf.use_callchain) - ret += hist_entry__fprintf_callchain(h, fp, session_total); + ret += hist_entry__fprintf_callchain(h, fp, self->stats.total); if (h->ms.map == NULL && verbose > 1) { __map_groups__fprintf_maps(&h->thread->mg, diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index b49013a..bdde81e 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -6,34 +6,40 @@ extern struct callchain_param callchain_param; -struct perf_session; struct hist_entry; struct addr_location; struct symbol; struct rb_root; -struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists, - struct addr_location *al, - struct symbol *parent, - u64 count); +struct events_stats { + u64 total; + u64 lost; +}; + +struct hists { + struct rb_node rb_node; + struct rb_root entries; + struct events_stats stats; + u64 config; + u64 event_stream; + u32 type; +}; + +struct hist_entry *__hists__add_entry(struct hists *self, + struct addr_location *al, + struct symbol *parent, u64 count); extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *); extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *); -int hist_entry__fprintf(struct hist_entry *self, - struct perf_session *pair_session, - bool show_displacement, - long displacement, FILE *fp, - u64 session_total); -int hist_entry__snprintf(struct hist_entry *self, - char *bf, size_t size, - struct perf_session *pair_session, - bool show_displacement, long displacement, - bool color, u64 session_total); +int hist_entry__fprintf(struct hist_entry *self, struct hists *pair_hists, + bool show_displacement, long displacement, FILE *fp, + u64 total); +int hist_entry__snprintf(struct hist_entry *self, char *bf, size_t size, + struct hists *pair_hists, bool show_displacement, + long displacement, bool color, u64 total); void hist_entry__free(struct hist_entry *); -u64 perf_session__output_resort(struct rb_root *hists, u64 total_samples); -void perf_session__collapse_resort(struct rb_root *hists); -size_t perf_session__fprintf_hists(struct rb_root *hists, - struct perf_session *pair, - bool show_displacement, FILE *fp, - u64 session_total); +u64 hists__output_resort(struct hists *self); +void hists__collapse_resort(struct hists *self); +size_t hists__fprintf(struct hists *self, struct hists *pair, + bool show_displacement, FILE *fp); #endif /* __PERF_HIST_H */ diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 4130036..72a7f6a 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -89,7 +89,7 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc memcpy(self->filename, filename, len); self->threads = RB_ROOT; - self->stats_by_id = RB_ROOT; + self->hists_tree = RB_ROOT; self->last_match = NULL; self->mmap_window = 32; self->cwd = NULL; diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 242d528..46190f9 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -1,6 +1,7 @@ #ifndef __PERF_SESSION_H #define __PERF_SESSION_H +#include "hist.h" #include "event.h" #include "header.h" #include "symbol.h" @@ -28,11 +29,16 @@ struct perf_session { struct thread *last_match; struct machine host_machine; struct rb_root machines; - struct events_stats events_stats; - struct rb_root stats_by_id; + struct rb_root hists_tree; unsigned long event_total[PERF_RECORD_MAX]; unsigned long unknown_events; - struct rb_root hists; + /* + * FIXME: should point to the first entry in hists_tree and + * be a hists instance. Right now its only 'report' + * that is using ->hists_tree while all the rest use + * ->hists. + */ + struct hists hists; u64 sample_type; int fd; bool fd_pipe; -- cgit v0.10.2 From f7422464b57088071201cd94027662d8469f153b Mon Sep 17 00:00:00 2001 From: Ian Kent Date: Mon, 10 May 2010 16:46:08 +0800 Subject: autofs4-2.6.34-rc1 - fix link_count usage After commit 1f36f774b2 ("Switch !O_CREAT case to use of do_last()") in 2.6.34-rc1 autofs direct mounts stopped working. This is caused by current->link_count being 0 when ->follow_link() is called from do_filp_open(). I can't work out why this hasn't been seen before Als patch series. This patch removes the autofs dependence on current->link_count. Signed-off-by: Ian Kent Cc: Al Viro Signed-off-by: Linus Torvalds diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 109a6c6..e8e5e63 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c @@ -177,8 +177,7 @@ static int try_to_fill_dentry(struct dentry *dentry, int flags) } /* Trigger mount for path component or follow link */ } else if (ino->flags & AUTOFS_INF_PENDING || - autofs4_need_mount(flags) || - current->link_count) { + autofs4_need_mount(flags)) { DPRINTK("waiting for mount name=%.*s", dentry->d_name.len, dentry->d_name.name); @@ -262,7 +261,7 @@ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd) spin_unlock(&dcache_lock); spin_unlock(&sbi->fs_lock); - status = try_to_fill_dentry(dentry, 0); + status = try_to_fill_dentry(dentry, nd->flags); if (status) goto out_error; -- cgit v0.10.2 From c9ad488289144ae5ef53b012e15895ef1f5e4bb6 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Thu, 6 May 2010 11:45:45 +0300 Subject: x86: Eliminate TS_XSAVE The fpu code currently uses current->thread_info->status & TS_XSAVE as a way to distinguish between XSAVE capable processors and older processors. The decision is not really task specific; instead we use the task status to avoid a global memory reference - the value should be the same across all threads. Eliminate this tie-in into the task structure by using an alternative instruction keyed off the XSAVE cpu feature; this results in shorter and faster code, without introducing a global memory reference. [ hpa: in the future, this probably should use an asm jmp ] Signed-off-by: Avi Kivity Acked-by: Suresh Siddha LKML-Reference: <1273135546-29690-2-git-send-email-avi@redhat.com> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/include/asm/i387.h b/arch/x86/include/asm/i387.h index da29309..a301a68 100644 --- a/arch/x86/include/asm/i387.h +++ b/arch/x86/include/asm/i387.h @@ -56,6 +56,18 @@ extern int restore_i387_xstate_ia32(void __user *buf); #define X87_FSW_ES (1 << 7) /* Exception Summary */ +static inline bool use_xsave(void) +{ + u8 has_xsave; + + alternative_io("mov $0, %0", + "mov $1, %0", + X86_FEATURE_XSAVE, + "=g"(has_xsave)); + + return has_xsave; +} + #ifdef CONFIG_X86_64 /* Ignore delayed exceptions from user space */ @@ -99,7 +111,7 @@ static inline void clear_fpu_state(struct task_struct *tsk) /* * xsave header may indicate the init state of the FP. */ - if ((task_thread_info(tsk)->status & TS_XSAVE) && + if (use_xsave() && !(xstate->xsave_hdr.xstate_bv & XSTATE_FP)) return; @@ -164,7 +176,7 @@ static inline void fxsave(struct task_struct *tsk) static inline void __save_init_fpu(struct task_struct *tsk) { - if (task_thread_info(tsk)->status & TS_XSAVE) + if (use_xsave()) xsave(tsk); else fxsave(tsk); @@ -218,7 +230,7 @@ static inline int fxrstor_checking(struct i387_fxsave_struct *fx) */ static inline void __save_init_fpu(struct task_struct *tsk) { - if (task_thread_info(tsk)->status & TS_XSAVE) { + if (use_xsave()) { struct xsave_struct *xstate = &tsk->thread.xstate->xsave; struct i387_fxsave_struct *fx = &tsk->thread.xstate->fxsave; @@ -266,7 +278,7 @@ end: static inline int restore_fpu_checking(struct task_struct *tsk) { - if (task_thread_info(tsk)->status & TS_XSAVE) + if (use_xsave()) return xrstor_checking(&tsk->thread.xstate->xsave); else return fxrstor_checking(&tsk->thread.xstate->fxsave); diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h index e0d2890..e9e3415 100644 --- a/arch/x86/include/asm/thread_info.h +++ b/arch/x86/include/asm/thread_info.h @@ -244,7 +244,6 @@ static inline struct thread_info *current_thread_info(void) #define TS_POLLING 0x0004 /* true if in idle loop and not sleeping */ #define TS_RESTORE_SIGMASK 0x0008 /* restore signal mask in do_signal() */ -#define TS_XSAVE 0x0010 /* Use xsave/xrstor */ #define tsk_is_polling(t) (task_thread_info(t)->status & TS_POLLING) diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 4868e4a..c1c00d0 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -1243,10 +1243,7 @@ void __cpuinit cpu_init(void) /* * Force FPU initialization: */ - if (cpu_has_xsave) - current_thread_info()->status = TS_XSAVE; - else - current_thread_info()->status = 0; + current_thread_info()->status = 0; clear_used_math(); mxcsr_feature_mask_init(); diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index 54c31c2..14ca1dc 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c @@ -102,10 +102,7 @@ void __cpuinit fpu_init(void) mxcsr_feature_mask_init(); /* clean state in init */ - if (cpu_has_xsave) - current_thread_info()->status = TS_XSAVE; - else - current_thread_info()->status = 0; + current_thread_info()->status = 0; clear_used_math(); } #endif /* CONFIG_X86_64 */ diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index 782c3a36..c1b0a11 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c @@ -99,7 +99,7 @@ int save_i387_xstate(void __user *buf) if (err) return err; - if (task_thread_info(tsk)->status & TS_XSAVE) + if (use_xsave()) err = xsave_user(buf); else err = fxsave_user(buf); @@ -116,7 +116,7 @@ int save_i387_xstate(void __user *buf) clear_used_math(); /* trigger finit */ - if (task_thread_info(tsk)->status & TS_XSAVE) { + if (use_xsave()) { struct _fpstate __user *fx = buf; struct _xstate __user *x = buf; u64 xstate_bv; @@ -225,7 +225,7 @@ int restore_i387_xstate(void __user *buf) clts(); task_thread_info(current)->status |= TS_USEDFPU; } - if (task_thread_info(tsk)->status & TS_XSAVE) + if (use_xsave()) err = restore_user_xstate(buf); else err = fxrstor_checking((__force struct i387_fxsave_struct *) -- cgit v0.10.2 From 86603283326c9e95e5ad4e9fdddeec93cac5d9ad Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Thu, 6 May 2010 11:45:46 +0300 Subject: x86: Introduce 'struct fpu' and related API Currently all fpu state access is through tsk->thread.xstate. Since we wish to generalize fpu access to non-task contexts, wrap the state in a new 'struct fpu' and convert existing access to use an fpu API. Signal frame handlers are not converted to the API since they will remain task context only things. Signed-off-by: Avi Kivity Acked-by: Suresh Siddha LKML-Reference: <1273135546-29690-3-git-send-email-avi@redhat.com> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/include/asm/i387.h b/arch/x86/include/asm/i387.h index a301a68..1a8cca3 100644 --- a/arch/x86/include/asm/i387.h +++ b/arch/x86/include/asm/i387.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -103,10 +104,10 @@ static inline int fxrstor_checking(struct i387_fxsave_struct *fx) values. The kernel data segment can be sometimes 0 and sometimes new user value. Both should be ok. Use the PDA as safe address because it should be already in L1. */ -static inline void clear_fpu_state(struct task_struct *tsk) +static inline void fpu_clear(struct fpu *fpu) { - struct xsave_struct *xstate = &tsk->thread.xstate->xsave; - struct i387_fxsave_struct *fx = &tsk->thread.xstate->fxsave; + struct xsave_struct *xstate = &fpu->state->xsave; + struct i387_fxsave_struct *fx = &fpu->state->fxsave; /* * xsave header may indicate the init state of the FP. @@ -123,6 +124,11 @@ static inline void clear_fpu_state(struct task_struct *tsk) X86_FEATURE_FXSAVE_LEAK); } +static inline void clear_fpu_state(struct task_struct *tsk) +{ + fpu_clear(&tsk->thread.fpu); +} + static inline int fxsave_user(struct i387_fxsave_struct __user *fx) { int err; @@ -147,7 +153,7 @@ static inline int fxsave_user(struct i387_fxsave_struct __user *fx) return err; } -static inline void fxsave(struct task_struct *tsk) +static inline void fpu_fxsave(struct fpu *fpu) { /* Using "rex64; fxsave %0" is broken because, if the memory operand uses any extended registers for addressing, a second REX prefix @@ -157,42 +163,45 @@ static inline void fxsave(struct task_struct *tsk) /* Using "fxsaveq %0" would be the ideal choice, but is only supported starting with gas 2.16. */ __asm__ __volatile__("fxsaveq %0" - : "=m" (tsk->thread.xstate->fxsave)); + : "=m" (fpu->state->fxsave)); #elif 0 /* Using, as a workaround, the properly prefixed form below isn't accepted by any binutils version so far released, complaining that the same type of prefix is used twice if an extended register is needed for addressing (fix submitted to mainline 2005-11-21). */ __asm__ __volatile__("rex64/fxsave %0" - : "=m" (tsk->thread.xstate->fxsave)); + : "=m" (fpu->state->fxsave)); #else /* This, however, we can work around by forcing the compiler to select an addressing mode that doesn't require extended registers. */ __asm__ __volatile__("rex64/fxsave (%1)" - : "=m" (tsk->thread.xstate->fxsave) - : "cdaSDb" (&tsk->thread.xstate->fxsave)); + : "=m" (fpu->state->fxsave) + : "cdaSDb" (&fpu->state->fxsave)); #endif } -static inline void __save_init_fpu(struct task_struct *tsk) +static inline void fpu_save_init(struct fpu *fpu) { if (use_xsave()) - xsave(tsk); + fpu_xsave(fpu); else - fxsave(tsk); + fpu_fxsave(fpu); - clear_fpu_state(tsk); + fpu_clear(fpu); +} + +static inline void __save_init_fpu(struct task_struct *tsk) +{ + fpu_save_init(&tsk->thread.fpu); task_thread_info(tsk)->status &= ~TS_USEDFPU; } #else /* CONFIG_X86_32 */ #ifdef CONFIG_MATH_EMULATION -extern void finit_task(struct task_struct *tsk); +extern void finit_soft_fpu(struct i387_soft_struct *soft); #else -static inline void finit_task(struct task_struct *tsk) -{ -} +static inline void finit_soft_fpu(struct i387_soft_struct *soft) {} #endif static inline void tolerant_fwait(void) @@ -228,13 +237,13 @@ static inline int fxrstor_checking(struct i387_fxsave_struct *fx) /* * These must be called with preempt disabled */ -static inline void __save_init_fpu(struct task_struct *tsk) +static inline void fpu_save_init(struct fpu *fpu) { if (use_xsave()) { - struct xsave_struct *xstate = &tsk->thread.xstate->xsave; - struct i387_fxsave_struct *fx = &tsk->thread.xstate->fxsave; + struct xsave_struct *xstate = &fpu->state->xsave; + struct i387_fxsave_struct *fx = &fpu->state->fxsave; - xsave(tsk); + fpu_xsave(fpu); /* * xsave header may indicate the init state of the FP. @@ -258,8 +267,8 @@ static inline void __save_init_fpu(struct task_struct *tsk) "fxsave %[fx]\n" "bt $7,%[fsw] ; jnc 1f ; fnclex\n1:", X86_FEATURE_FXSR, - [fx] "m" (tsk->thread.xstate->fxsave), - [fsw] "m" (tsk->thread.xstate->fxsave.swd) : "memory"); + [fx] "m" (fpu->state->fxsave), + [fsw] "m" (fpu->state->fxsave.swd) : "memory"); clear_state: /* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception is pending. Clear the x87 state here by setting it to fixed @@ -271,17 +280,34 @@ clear_state: X86_FEATURE_FXSAVE_LEAK, [addr] "m" (safe_address)); end: + ; +} + +static inline void __save_init_fpu(struct task_struct *tsk) +{ + fpu_save_init(&tsk->thread.fpu); task_thread_info(tsk)->status &= ~TS_USEDFPU; } + #endif /* CONFIG_X86_64 */ -static inline int restore_fpu_checking(struct task_struct *tsk) +static inline int fpu_fxrstor_checking(struct fpu *fpu) +{ + return fxrstor_checking(&fpu->state->fxsave); +} + +static inline int fpu_restore_checking(struct fpu *fpu) { if (use_xsave()) - return xrstor_checking(&tsk->thread.xstate->xsave); + return fpu_xrstor_checking(fpu); else - return fxrstor_checking(&tsk->thread.xstate->fxsave); + return fpu_fxrstor_checking(fpu); +} + +static inline int restore_fpu_checking(struct task_struct *tsk) +{ + return fpu_restore_checking(&tsk->thread.fpu); } /* @@ -409,30 +435,59 @@ static inline void clear_fpu(struct task_struct *tsk) static inline unsigned short get_fpu_cwd(struct task_struct *tsk) { if (cpu_has_fxsr) { - return tsk->thread.xstate->fxsave.cwd; + return tsk->thread.fpu.state->fxsave.cwd; } else { - return (unsigned short)tsk->thread.xstate->fsave.cwd; + return (unsigned short)tsk->thread.fpu.state->fsave.cwd; } } static inline unsigned short get_fpu_swd(struct task_struct *tsk) { if (cpu_has_fxsr) { - return tsk->thread.xstate->fxsave.swd; + return tsk->thread.fpu.state->fxsave.swd; } else { - return (unsigned short)tsk->thread.xstate->fsave.swd; + return (unsigned short)tsk->thread.fpu.state->fsave.swd; } } static inline unsigned short get_fpu_mxcsr(struct task_struct *tsk) { if (cpu_has_xmm) { - return tsk->thread.xstate->fxsave.mxcsr; + return tsk->thread.fpu.state->fxsave.mxcsr; } else { return MXCSR_DEFAULT; } } +static bool fpu_allocated(struct fpu *fpu) +{ + return fpu->state != NULL; +} + +static inline int fpu_alloc(struct fpu *fpu) +{ + if (fpu_allocated(fpu)) + return 0; + fpu->state = kmem_cache_alloc(task_xstate_cachep, GFP_KERNEL); + if (!fpu->state) + return -ENOMEM; + WARN_ON((unsigned long)fpu->state & 15); + return 0; +} + +static inline void fpu_free(struct fpu *fpu) +{ + if (fpu->state) { + kmem_cache_free(task_xstate_cachep, fpu->state); + fpu->state = NULL; + } +} + +static inline void fpu_copy(struct fpu *dst, struct fpu *src) +{ + memcpy(dst->state, src->state, xstate_size); +} + #endif /* __ASSEMBLY__ */ #define PSHUFB_XMM5_XMM0 .byte 0x66, 0x0f, 0x38, 0x00, 0xc5 diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index b753ea5..b684f58 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -380,6 +380,10 @@ union thread_xstate { struct xsave_struct xsave; }; +struct fpu { + union thread_xstate *state; +}; + #ifdef CONFIG_X86_64 DECLARE_PER_CPU(struct orig_ist, orig_ist); @@ -457,7 +461,7 @@ struct thread_struct { unsigned long trap_no; unsigned long error_code; /* floating point and extended processor state */ - union thread_xstate *xstate; + struct fpu fpu; #ifdef CONFIG_X86_32 /* Virtual 86 mode info */ struct vm86_struct __user *vm86_info; diff --git a/arch/x86/include/asm/xsave.h b/arch/x86/include/asm/xsave.h index ddc04cc..2c4390c 100644 --- a/arch/x86/include/asm/xsave.h +++ b/arch/x86/include/asm/xsave.h @@ -37,8 +37,9 @@ extern int check_for_xstate(struct i387_fxsave_struct __user *buf, void __user *fpstate, struct _fpx_sw_bytes *sw); -static inline int xrstor_checking(struct xsave_struct *fx) +static inline int fpu_xrstor_checking(struct fpu *fpu) { + struct xsave_struct *fx = &fpu->state->xsave; int err; asm volatile("1: .byte " REX_PREFIX "0x0f,0xae,0x2f\n\t" @@ -110,12 +111,12 @@ static inline void xrstor_state(struct xsave_struct *fx, u64 mask) : "memory"); } -static inline void xsave(struct task_struct *tsk) +static inline void fpu_xsave(struct fpu *fpu) { /* This, however, we can work around by forcing the compiler to select an addressing mode that doesn't require extended registers. */ __asm__ __volatile__(".byte " REX_PREFIX "0x0f,0xae,0x27" - : : "D" (&(tsk->thread.xstate->xsave)), + : : "D" (&(fpu->state->xsave)), "a" (-1), "d"(-1) : "memory"); } #endif diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index 14ca1dc..86cef6b 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c @@ -107,57 +107,57 @@ void __cpuinit fpu_init(void) } #endif /* CONFIG_X86_64 */ -/* - * The _current_ task is using the FPU for the first time - * so initialize it and set the mxcsr to its default - * value at reset if we support XMM instructions and then - * remeber the current task has used the FPU. - */ -int init_fpu(struct task_struct *tsk) +static void fpu_finit(struct fpu *fpu) { - if (tsk_used_math(tsk)) { - if (HAVE_HWFP && tsk == current) - unlazy_fpu(tsk); - return 0; - } - - /* - * Memory allocation at the first usage of the FPU and other state. - */ - if (!tsk->thread.xstate) { - tsk->thread.xstate = kmem_cache_alloc(task_xstate_cachep, - GFP_KERNEL); - if (!tsk->thread.xstate) - return -ENOMEM; - } - #ifdef CONFIG_X86_32 if (!HAVE_HWFP) { - memset(tsk->thread.xstate, 0, xstate_size); - finit_task(tsk); - set_stopped_child_used_math(tsk); - return 0; + finit_soft_fpu(&fpu->state->soft); + return; } #endif if (cpu_has_fxsr) { - struct i387_fxsave_struct *fx = &tsk->thread.xstate->fxsave; + struct i387_fxsave_struct *fx = &fpu->state->fxsave; memset(fx, 0, xstate_size); fx->cwd = 0x37f; if (cpu_has_xmm) fx->mxcsr = MXCSR_DEFAULT; } else { - struct i387_fsave_struct *fp = &tsk->thread.xstate->fsave; + struct i387_fsave_struct *fp = &fpu->state->fsave; memset(fp, 0, xstate_size); fp->cwd = 0xffff037fu; fp->swd = 0xffff0000u; fp->twd = 0xffffffffu; fp->fos = 0xffff0000u; } +} + +/* + * The _current_ task is using the FPU for the first time + * so initialize it and set the mxcsr to its default + * value at reset if we support XMM instructions and then + * remeber the current task has used the FPU. + */ +int init_fpu(struct task_struct *tsk) +{ + int ret; + + if (tsk_used_math(tsk)) { + if (HAVE_HWFP && tsk == current) + unlazy_fpu(tsk); + return 0; + } + /* - * Only the device not available exception or ptrace can call init_fpu. + * Memory allocation at the first usage of the FPU and other state. */ + ret = fpu_alloc(&tsk->thread.fpu); + if (ret) + return ret; + + fpu_finit(&tsk->thread.fpu); + set_stopped_child_used_math(tsk); return 0; } @@ -191,7 +191,7 @@ int xfpregs_get(struct task_struct *target, const struct user_regset *regset, return ret; return user_regset_copyout(&pos, &count, &kbuf, &ubuf, - &target->thread.xstate->fxsave, 0, -1); + &target->thread.fpu.state->fxsave, 0, -1); } int xfpregs_set(struct task_struct *target, const struct user_regset *regset, @@ -208,19 +208,19 @@ int xfpregs_set(struct task_struct *target, const struct user_regset *regset, return ret; ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, - &target->thread.xstate->fxsave, 0, -1); + &target->thread.fpu.state->fxsave, 0, -1); /* * mxcsr reserved bits must be masked to zero for security reasons. */ - target->thread.xstate->fxsave.mxcsr &= mxcsr_feature_mask; + target->thread.fpu.state->fxsave.mxcsr &= mxcsr_feature_mask; /* * update the header bits in the xsave header, indicating the * presence of FP and SSE state. */ if (cpu_has_xsave) - target->thread.xstate->xsave.xsave_hdr.xstate_bv |= XSTATE_FPSSE; + target->thread.fpu.state->xsave.xsave_hdr.xstate_bv |= XSTATE_FPSSE; return ret; } @@ -243,14 +243,14 @@ int xstateregs_get(struct task_struct *target, const struct user_regset *regset, * memory layout in the thread struct, so that we can copy the entire * xstateregs to the user using one user_regset_copyout(). */ - memcpy(&target->thread.xstate->fxsave.sw_reserved, + memcpy(&target->thread.fpu.state->fxsave.sw_reserved, xstate_fx_sw_bytes, sizeof(xstate_fx_sw_bytes)); /* * Copy the xstate memory layout. */ ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, - &target->thread.xstate->xsave, 0, -1); + &target->thread.fpu.state->xsave, 0, -1); return ret; } @@ -269,14 +269,14 @@ int xstateregs_set(struct task_struct *target, const struct user_regset *regset, return ret; ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, - &target->thread.xstate->xsave, 0, -1); + &target->thread.fpu.state->xsave, 0, -1); /* * mxcsr reserved bits must be masked to zero for security reasons. */ - target->thread.xstate->fxsave.mxcsr &= mxcsr_feature_mask; + target->thread.fpu.state->fxsave.mxcsr &= mxcsr_feature_mask; - xsave_hdr = &target->thread.xstate->xsave.xsave_hdr; + xsave_hdr = &target->thread.fpu.state->xsave.xsave_hdr; xsave_hdr->xstate_bv &= pcntxt_mask; /* @@ -362,7 +362,7 @@ static inline u32 twd_fxsr_to_i387(struct i387_fxsave_struct *fxsave) static void convert_from_fxsr(struct user_i387_ia32_struct *env, struct task_struct *tsk) { - struct i387_fxsave_struct *fxsave = &tsk->thread.xstate->fxsave; + struct i387_fxsave_struct *fxsave = &tsk->thread.fpu.state->fxsave; struct _fpreg *to = (struct _fpreg *) &env->st_space[0]; struct _fpxreg *from = (struct _fpxreg *) &fxsave->st_space[0]; int i; @@ -402,7 +402,7 @@ static void convert_to_fxsr(struct task_struct *tsk, const struct user_i387_ia32_struct *env) { - struct i387_fxsave_struct *fxsave = &tsk->thread.xstate->fxsave; + struct i387_fxsave_struct *fxsave = &tsk->thread.fpu.state->fxsave; struct _fpreg *from = (struct _fpreg *) &env->st_space[0]; struct _fpxreg *to = (struct _fpxreg *) &fxsave->st_space[0]; int i; @@ -442,7 +442,7 @@ int fpregs_get(struct task_struct *target, const struct user_regset *regset, if (!cpu_has_fxsr) { return user_regset_copyout(&pos, &count, &kbuf, &ubuf, - &target->thread.xstate->fsave, 0, + &target->thread.fpu.state->fsave, 0, -1); } @@ -472,7 +472,7 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset, if (!cpu_has_fxsr) { return user_regset_copyin(&pos, &count, &kbuf, &ubuf, - &target->thread.xstate->fsave, 0, -1); + &target->thread.fpu.state->fsave, 0, -1); } if (pos > 0 || count < sizeof(env)) @@ -487,7 +487,7 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset, * presence of FP. */ if (cpu_has_xsave) - target->thread.xstate->xsave.xsave_hdr.xstate_bv |= XSTATE_FP; + target->thread.fpu.state->xsave.xsave_hdr.xstate_bv |= XSTATE_FP; return ret; } @@ -498,7 +498,7 @@ int fpregs_set(struct task_struct *target, const struct user_regset *regset, static inline int save_i387_fsave(struct _fpstate_ia32 __user *buf) { struct task_struct *tsk = current; - struct i387_fsave_struct *fp = &tsk->thread.xstate->fsave; + struct i387_fsave_struct *fp = &tsk->thread.fpu.state->fsave; fp->status = fp->swd; if (__copy_to_user(buf, fp, sizeof(struct i387_fsave_struct))) @@ -509,7 +509,7 @@ static inline int save_i387_fsave(struct _fpstate_ia32 __user *buf) static int save_i387_fxsave(struct _fpstate_ia32 __user *buf) { struct task_struct *tsk = current; - struct i387_fxsave_struct *fx = &tsk->thread.xstate->fxsave; + struct i387_fxsave_struct *fx = &tsk->thread.fpu.state->fxsave; struct user_i387_ia32_struct env; int err = 0; @@ -544,7 +544,7 @@ static int save_i387_xsave(void __user *buf) * header as well as change any contents in the memory layout. * xrestore as part of sigreturn will capture all the changes. */ - tsk->thread.xstate->xsave.xsave_hdr.xstate_bv |= XSTATE_FPSSE; + tsk->thread.fpu.state->xsave.xsave_hdr.xstate_bv |= XSTATE_FPSSE; if (save_i387_fxsave(fx) < 0) return -1; @@ -596,7 +596,7 @@ static inline int restore_i387_fsave(struct _fpstate_ia32 __user *buf) { struct task_struct *tsk = current; - return __copy_from_user(&tsk->thread.xstate->fsave, buf, + return __copy_from_user(&tsk->thread.fpu.state->fsave, buf, sizeof(struct i387_fsave_struct)); } @@ -607,10 +607,10 @@ static int restore_i387_fxsave(struct _fpstate_ia32 __user *buf, struct user_i387_ia32_struct env; int err; - err = __copy_from_user(&tsk->thread.xstate->fxsave, &buf->_fxsr_env[0], + err = __copy_from_user(&tsk->thread.fpu.state->fxsave, &buf->_fxsr_env[0], size); /* mxcsr reserved bits must be masked to zero for security reasons */ - tsk->thread.xstate->fxsave.mxcsr &= mxcsr_feature_mask; + tsk->thread.fpu.state->fxsave.mxcsr &= mxcsr_feature_mask; if (err || __copy_from_user(&env, buf, sizeof(env))) return 1; convert_to_fxsr(tsk, &env); @@ -626,7 +626,7 @@ static int restore_i387_xsave(void __user *buf) struct i387_fxsave_struct __user *fx = (struct i387_fxsave_struct __user *) &fx_user->_fxsr_env[0]; struct xsave_hdr_struct *xsave_hdr = - ¤t->thread.xstate->xsave.xsave_hdr; + ¤t->thread.fpu.state->xsave.xsave_hdr; u64 mask; int err; diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 28ad9f4..f18fd9c 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -32,25 +32,22 @@ struct kmem_cache *task_xstate_cachep; int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) { + int ret; + *dst = *src; - if (src->thread.xstate) { - dst->thread.xstate = kmem_cache_alloc(task_xstate_cachep, - GFP_KERNEL); - if (!dst->thread.xstate) - return -ENOMEM; - WARN_ON((unsigned long)dst->thread.xstate & 15); - memcpy(dst->thread.xstate, src->thread.xstate, xstate_size); + if (fpu_allocated(&src->thread.fpu)) { + memset(&dst->thread.fpu, 0, sizeof(dst->thread.fpu)); + ret = fpu_alloc(&dst->thread.fpu); + if (ret) + return ret; + fpu_copy(&dst->thread.fpu, &src->thread.fpu); } return 0; } void free_thread_xstate(struct task_struct *tsk) { - if (tsk->thread.xstate) { - kmem_cache_free(task_xstate_cachep, tsk->thread.xstate); - tsk->thread.xstate = NULL; - } - + fpu_free(&tsk->thread.fpu); WARN(tsk->thread.ds_ctx, "leaking DS context\n"); } diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index f6c6266..0a7a4f5 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -317,7 +317,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) /* we're going to use this soon, after a few expensive things */ if (preload_fpu) - prefetch(next->xstate); + prefetch(next->fpu.state); /* * Reload esp0. diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 17cb329..979215f 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -396,7 +396,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) /* we're going to use this soon, after a few expensive things */ if (preload_fpu) - prefetch(next->xstate); + prefetch(next->fpu.state); /* * Reload esp0, LDT and the page table pointer: diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index c1b0a11..37e68fc 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c @@ -109,7 +109,7 @@ int save_i387_xstate(void __user *buf) task_thread_info(tsk)->status &= ~TS_USEDFPU; stts(); } else { - if (__copy_to_user(buf, &tsk->thread.xstate->fxsave, + if (__copy_to_user(buf, &tsk->thread.fpu.state->fxsave, xstate_size)) return -1; } diff --git a/arch/x86/math-emu/fpu_aux.c b/arch/x86/math-emu/fpu_aux.c index aa09870..62797f9 100644 --- a/arch/x86/math-emu/fpu_aux.c +++ b/arch/x86/math-emu/fpu_aux.c @@ -30,10 +30,10 @@ static void fclex(void) } /* Needs to be externally visible */ -void finit_task(struct task_struct *tsk) +void finit_soft_fpu(struct i387_soft_struct *soft) { - struct i387_soft_struct *soft = &tsk->thread.xstate->soft; struct address *oaddr, *iaddr; + memset(soft, 0, sizeof(*soft)); soft->cwd = 0x037f; soft->swd = 0; soft->ftop = 0; /* We don't keep top in the status word internally. */ @@ -52,7 +52,7 @@ void finit_task(struct task_struct *tsk) void finit(void) { - finit_task(current); + finit_task(¤t->thread.fpu); } /* -- cgit v0.10.2 From fae683f764f91f31ab45512e70cc8cc81d4d157b Mon Sep 17 00:00:00 2001 From: Suresh Jayaraman Date: Mon, 10 May 2010 20:00:05 +0530 Subject: cifs: add comments explaining cifs_new_fileinfo behavior The comments make it clear the otherwise subtle behavior of cifs_new_fileinfo(). Signed-off-by: Suresh Jayaraman Reviewed-by: Shirish Pargaonkar -- fs/cifs/dir.c | 18 ++++++++++++++++-- 1 files changed, 16 insertions(+), 2 deletions(-) Signed-off-by: Steve French diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index d791d07..bd363df 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -129,6 +129,12 @@ cifs_bp_rename_retry: return full_path; } +/* + * When called with struct file pointer set to NULL, there is no way we could + * update file->private_data, but getting it stuck on openFileList provides a + * way to access it from cifs_fill_filedata and thereby set file->private_data + * from cifs_open. + */ struct cifsFileInfo * cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, struct file *file, struct vfsmount *mnt, unsigned int oflags) @@ -251,6 +257,10 @@ int cifs_posix_open(char *full_path, struct inode **pinode, cifs_fattr_to_inode(*pinode, &fattr); } + /* + * cifs_fill_filedata() takes care of setting cifsFileInfo pointer to + * file->private_data. + */ if (mnt) cifs_new_fileinfo(*pinode, *pnetfid, NULL, mnt, oflags); @@ -466,8 +476,12 @@ cifs_create_set_dentry: /* mknod case - do not leave file open */ CIFSSMBClose(xid, tcon, fileHandle); } else if (!(posix_create) && (newinode)) { - cifs_new_fileinfo(newinode, fileHandle, NULL, - nd->path.mnt, oflags); + /* + * cifs_fill_filedata() takes care of setting cifsFileInfo + * pointer to file->private_data. + */ + cifs_new_fileinfo(newinode, fileHandle, NULL, nd->path.mnt, + oflags); } cifs_create_out: kfree(buf); -- cgit v0.10.2 From 2b3fc35f6919344e3cf722dde8308f47235c0b70 Mon Sep 17 00:00:00 2001 From: Lai Jiangshan Date: Tue, 20 Apr 2010 16:23:07 +0800 Subject: rcu: optionally leave lockdep enabled after RCU lockdep splat There is no need to disable lockdep after an RCU lockdep splat, so remove the debug_lockdeps_off() from lockdep_rcu_dereference(). To avoid repeated lockdep splats, use a static variable in the inlined rcu_dereference_check() and rcu_dereference_protected() macros so that a given instance splats only once, but so that multiple instances can be detected per boot. This is controlled by a new config variable CONFIG_PROVE_RCU_REPEATEDLY, which is disabled by default. This provides the normal lockdep behavior by default, but permits people who want to find multiple RCU-lockdep splats per boot to easily do so. Requested-by: Eric Paris Signed-off-by: Lai Jiangshan Tested-by: Eric Paris Signed-off-by: Paul E. McKenney diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index db266bb..4dca275 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -192,6 +192,15 @@ static inline int rcu_read_lock_sched_held(void) extern int rcu_my_thread_group_empty(void); +#define __do_rcu_dereference_check(c) \ + do { \ + static bool __warned; \ + if (debug_lockdep_rcu_enabled() && !__warned && !(c)) { \ + __warned = true; \ + lockdep_rcu_dereference(__FILE__, __LINE__); \ + } \ + } while (0) + /** * rcu_dereference_check - rcu_dereference with debug checking * @p: The pointer to read, prior to dereferencing @@ -221,8 +230,7 @@ extern int rcu_my_thread_group_empty(void); */ #define rcu_dereference_check(p, c) \ ({ \ - if (debug_lockdep_rcu_enabled() && !(c)) \ - lockdep_rcu_dereference(__FILE__, __LINE__); \ + __do_rcu_dereference_check(c); \ rcu_dereference_raw(p); \ }) @@ -239,8 +247,7 @@ extern int rcu_my_thread_group_empty(void); */ #define rcu_dereference_protected(p, c) \ ({ \ - if (debug_lockdep_rcu_enabled() && !(c)) \ - lockdep_rcu_dereference(__FILE__, __LINE__); \ + __do_rcu_dereference_check(c); \ (p); \ }) diff --git a/kernel/lockdep.c b/kernel/lockdep.c index 2594e1c..3a756ba 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c @@ -3801,8 +3801,11 @@ void lockdep_rcu_dereference(const char *file, const int line) { struct task_struct *curr = current; +#ifndef CONFIG_PROVE_RCU_REPEATEDLY if (!debug_locks_off()) return; +#endif /* #ifdef CONFIG_PROVE_RCU_REPEATEDLY */ + /* Note: the following can be executed concurrently, so be careful. */ printk("\n===================================================\n"); printk( "[ INFO: suspicious rcu_dereference_check() usage. ]\n"); printk( "---------------------------------------------------\n"); diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 935248b..94090b4 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -512,6 +512,18 @@ config PROVE_RCU Say N if you are unsure. +config PROVE_RCU_REPEATEDLY + bool "RCU debugging: don't disable PROVE_RCU on first splat" + depends on PROVE_RCU + default n + help + By itself, PROVE_RCU will disable checking upon issuing the + first warning (or "splat"). This feature prevents such + disabling, allowing multiple RCU-lockdep warnings to be printed + on a single reboot. + + Say N if you are unsure. + config LOCKDEP bool depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT -- cgit v0.10.2 From d25eb9442bb2c38c1e742f0fa764d7132d72593f Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Thu, 18 Mar 2010 21:36:51 -0700 Subject: rcu: substitute set_need_resched for sending resched IPIs This patch adds a check to __rcu_pending() that does a local set_need_resched() if the current CPU is holding up the current grace period and if force_quiescent_state() will be called soon. The goal is to reduce the probability that force_quiescent_state() will need to do smp_send_reschedule(), which sends an IPI and is therefore more expensive on most architectures. Signed-off-by: "Paul E. McKenney" diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 3ec8160..e54c123 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -1499,6 +1499,16 @@ static int __rcu_pending(struct rcu_state *rsp, struct rcu_data *rdp) /* Is the RCU core waiting for a quiescent state from this CPU? */ if (rdp->qs_pending) { + + /* + * If force_quiescent_state() coming soon and this CPU + * needs a quiescent state, and this is either RCU-sched + * or RCU-bh, force a local reschedule. + */ + if (!rdp->preemptable && + ULONG_CMP_LT(ACCESS_ONCE(rsp->jiffies_force_qs) - 1, + jiffies)) + set_need_resched(); rdp->n_rp_qs_pending++; return 1; } -- cgit v0.10.2 From f261414f0d56dd1a0e34888e27d1d4902ad052f3 Mon Sep 17 00:00:00 2001 From: Lai Jiangshan Date: Sun, 28 Mar 2010 11:15:20 +0800 Subject: rcu: make dead code really dead cleanup: make dead code really dead Signed-off-by: Lai Jiangshan Signed-off-by: Paul E. McKenney diff --git a/kernel/rcutree.c b/kernel/rcutree.c index e54c123..6042fb8 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -1236,11 +1236,11 @@ static void force_quiescent_state(struct rcu_state *rsp, int relaxed) break; /* grace period idle or initializing, ignore. */ case RCU_SAVE_DYNTICK: - - raw_spin_unlock(&rnp->lock); /* irqs remain disabled */ if (RCU_SIGNAL_INIT != RCU_SAVE_DYNTICK) break; /* So gcc recognizes the dead code. */ + raw_spin_unlock(&rnp->lock); /* irqs remain disabled */ + /* Record dyntick-idle state. */ force_qs_rnp(rsp, dyntick_save_progress_counter); raw_spin_lock(&rnp->lock); /* irqs already disabled */ -- cgit v0.10.2 From 0c34029abdfdea64420cb4264c4e91a776b22157 Mon Sep 17 00:00:00 2001 From: Lai Jiangshan Date: Sun, 28 Mar 2010 11:12:30 +0800 Subject: rcu: move some code from macro to function Shrink the RCU_INIT_FLAVOR() macro by moving all but the initialization of the ->rda[] array to rcu_init_one(). The call to rcu_init_one() can then be moved to the end of the RCU_INIT_FLAVOR() macro, which is required because rcu_boot_init_percpu_data(), which is now called from rcu_init_one(), depends on the initialization of the ->rda[] array. Signed-off-by: Lai Jiangshan Signed-off-by: Paul E. McKenney diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 6042fb8..86bb949 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -1859,6 +1859,14 @@ static void __init rcu_init_one(struct rcu_state *rsp) INIT_LIST_HEAD(&rnp->blocked_tasks[3]); } } + + rnp = rsp->level[NUM_RCU_LVLS - 1]; + for_each_possible_cpu(i) { + if (i > rnp->grphi) + rnp++; + rsp->rda[i]->mynode = rnp; + rcu_boot_init_percpu_data(i, rsp); + } } /* @@ -1869,19 +1877,11 @@ static void __init rcu_init_one(struct rcu_state *rsp) #define RCU_INIT_FLAVOR(rsp, rcu_data) \ do { \ int i; \ - int j; \ - struct rcu_node *rnp; \ \ - rcu_init_one(rsp); \ - rnp = (rsp)->level[NUM_RCU_LVLS - 1]; \ - j = 0; \ for_each_possible_cpu(i) { \ - if (i > rnp[j].grphi) \ - j++; \ - per_cpu(rcu_data, i).mynode = &rnp[j]; \ (rsp)->rda[i] = &per_cpu(rcu_data, i); \ - rcu_boot_init_percpu_data(i, rsp); \ } \ + rcu_init_one(rsp); \ } while (0) void __init rcu_init(void) -- cgit v0.10.2 From 5db356736acb9ba717df1aa9444e4e44cbb30a71 Mon Sep 17 00:00:00 2001 From: Lai Jiangshan Date: Tue, 30 Mar 2010 18:40:36 +0800 Subject: rcu: ignore offline CPUs in last non-dyntick-idle CPU check Offline CPUs are not in nohz_cpu_mask, but can be ignored when checking for the last non-dyntick-idle CPU. This patch therefore only checks online CPUs for not being dyntick idle, allowing fast entry into full-system dyntick-idle state even when there are some offline CPUs. Signed-off-by: Lai Jiangshan Signed-off-by: Paul E. McKenney diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index 79b53bd..687c4e9 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h @@ -1016,7 +1016,7 @@ int rcu_needs_cpu(int cpu) /* Don't bother unless we are the last non-dyntick-idle CPU. */ for_each_cpu_not(thatcpu, nohz_cpu_mask) - if (thatcpu != cpu) { + if (cpu_online(thatcpu) && thatcpu != cpu) { per_cpu(rcu_dyntick_drain, cpu) = 0; per_cpu(rcu_dyntick_holdoff, cpu) = jiffies - 1; return rcu_needs_cpu_quick_check(cpu); -- cgit v0.10.2 From d20200b591f59847ab6a5c23507084a7d29e23c5 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Tue, 30 Mar 2010 10:52:21 -0700 Subject: rcu: Fix bogus CONFIG_PROVE_LOCKING in comments to reflect reality. It is CONFIG_DEBUG_LOCK_ALLOC rather than CONFIG_PROVE_LOCKING, so fix it. Signed-off-by: Paul E. McKenney diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 4dca275..a150af0 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -106,8 +106,8 @@ extern int debug_lockdep_rcu_enabled(void); /** * rcu_read_lock_held - might we be in RCU read-side critical section? * - * If CONFIG_PROVE_LOCKING is selected and enabled, returns nonzero iff in - * an RCU read-side critical section. In absence of CONFIG_PROVE_LOCKING, + * If CONFIG_DEBUG_LOCK_ALLOC is selected, returns nonzero iff in an RCU + * read-side critical section. In absence of CONFIG_DEBUG_LOCK_ALLOC, * this assumes we are in an RCU read-side critical section unless it can * prove otherwise. * @@ -129,11 +129,12 @@ extern int rcu_read_lock_bh_held(void); /** * rcu_read_lock_sched_held - might we be in RCU-sched read-side critical section? * - * If CONFIG_PROVE_LOCKING is selected and enabled, returns nonzero iff in an - * RCU-sched read-side critical section. In absence of CONFIG_PROVE_LOCKING, - * this assumes we are in an RCU-sched read-side critical section unless it - * can prove otherwise. Note that disabling of preemption (including - * disabling irqs) counts as an RCU-sched read-side critical section. + * If CONFIG_DEBUG_LOCK_ALLOC is selected, returns nonzero iff in an + * RCU-sched read-side critical section. In absence of + * CONFIG_DEBUG_LOCK_ALLOC, this assumes we are in an RCU-sched read-side + * critical section unless it can prove otherwise. Note that disabling + * of preemption (including disabling irqs) counts as an RCU-sched + * read-side critical section. * * Check rcu_scheduler_active to prevent false positives during boot. */ diff --git a/include/linux/srcu.h b/include/linux/srcu.h index 4d5ecb2..9c01f10 100644 --- a/include/linux/srcu.h +++ b/include/linux/srcu.h @@ -84,8 +84,8 @@ long srcu_batches_completed(struct srcu_struct *sp); /** * srcu_read_lock_held - might we be in SRCU read-side critical section? * - * If CONFIG_PROVE_LOCKING is selected and enabled, returns nonzero iff in - * an SRCU read-side critical section. In absence of CONFIG_PROVE_LOCKING, + * If CONFIG_DEBUG_LOCK_ALLOC is selected, returns nonzero iff in an SRCU + * read-side critical section. In absence of CONFIG_DEBUG_LOCK_ALLOC, * this assumes we are in an SRCU read-side critical section unless it can * prove otherwise. */ -- cgit v0.10.2 From 32c141a0a1dfa29e0a07d78bec0c0919fc4b9f88 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Tue, 30 Mar 2010 10:59:28 -0700 Subject: rcu: fix now-bogus rcu_scheduler_active comments. The rcu_scheduler_active check has been wrapped into the new debug_lockdep_rcu_enabled() function, so update the comments to reflect this new reality. Signed-off-by: Paul E. McKenney diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index a150af0..02537a7 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -111,7 +111,8 @@ extern int debug_lockdep_rcu_enabled(void); * this assumes we are in an RCU read-side critical section unless it can * prove otherwise. * - * Check rcu_scheduler_active to prevent false positives during boot. + * Check debug_lockdep_rcu_enabled() to prevent false positives during boot + * and while lockdep is disabled. */ static inline int rcu_read_lock_held(void) { @@ -136,7 +137,8 @@ extern int rcu_read_lock_bh_held(void); * of preemption (including disabling irqs) counts as an RCU-sched * read-side critical section. * - * Check rcu_scheduler_active to prevent false positives during boot. + * Check debug_lockdep_rcu_enabled() to prevent false positives during boot + * and while lockdep is disabled. */ #ifdef CONFIG_PREEMPT static inline int rcu_read_lock_sched_held(void) -- cgit v0.10.2 From da848c47bc6e873a54a445ea1960423a495b6b32 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Tue, 30 Mar 2010 15:46:01 -0700 Subject: rcu: shrink rcutiny by making synchronize_rcu_bh() be inline Because synchronize_rcu_bh() is identical to synchronize_sched(), make the former a static inline invoking the latter, saving the overhead of an EXPORT_SYMBOL_GPL() and the duplicate code. Signed-off-by: Paul E. McKenney diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 02537a7..d8fb2ab 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -56,8 +56,6 @@ struct rcu_head { }; /* Exported common interfaces */ -extern void synchronize_rcu_bh(void); -extern void synchronize_sched(void); extern void rcu_barrier(void); extern void rcu_barrier_bh(void); extern void rcu_barrier_sched(void); diff --git a/include/linux/rcutiny.h b/include/linux/rcutiny.h index a519587..bbeb55b 100644 --- a/include/linux/rcutiny.h +++ b/include/linux/rcutiny.h @@ -74,7 +74,17 @@ static inline void rcu_sched_force_quiescent_state(void) { } -#define synchronize_rcu synchronize_sched +extern void synchronize_sched(void); + +static inline void synchronize_rcu(void) +{ + synchronize_sched(); +} + +static inline void synchronize_rcu_bh(void) +{ + synchronize_sched(); +} static inline void synchronize_rcu_expedited(void) { diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h index 42cc3a0..7484fe6 100644 --- a/include/linux/rcutree.h +++ b/include/linux/rcutree.h @@ -86,6 +86,8 @@ static inline void __rcu_read_unlock_bh(void) extern void call_rcu_sched(struct rcu_head *head, void (*func)(struct rcu_head *rcu)); +extern void synchronize_rcu_bh(void); +extern void synchronize_sched(void); extern void synchronize_rcu_expedited(void); static inline void synchronize_rcu_bh_expedited(void) diff --git a/kernel/rcutiny.c b/kernel/rcutiny.c index 9f6d9ff..272c6d2 100644 --- a/kernel/rcutiny.c +++ b/kernel/rcutiny.c @@ -187,7 +187,8 @@ static void rcu_process_callbacks(struct softirq_action *unused) * * Cool, huh? (Due to Josh Triplett.) * - * But we want to make this a static inline later. + * But we want to make this a static inline later. The cond_resched() + * currently makes this problematic. */ void synchronize_sched(void) { @@ -195,12 +196,6 @@ void synchronize_sched(void) } EXPORT_SYMBOL_GPL(synchronize_sched); -void synchronize_rcu_bh(void) -{ - synchronize_sched(); -} -EXPORT_SYMBOL_GPL(synchronize_rcu_bh); - /* * Helper function for call_rcu() and call_rcu_bh(). */ -- cgit v0.10.2 From 99652b54de1ee094236f7171485214071af4ef31 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Tue, 30 Mar 2010 15:50:01 -0700 Subject: rcu: rename rcutiny rcu_ctrlblk to rcu_sched_ctrlblk Make naming line up in preparation for CONFIG_TINY_PREEMPT_RCU. Signed-off-by: Paul E. McKenney diff --git a/kernel/rcutiny.c b/kernel/rcutiny.c index 272c6d2..d9f8a62 100644 --- a/kernel/rcutiny.c +++ b/kernel/rcutiny.c @@ -44,9 +44,9 @@ struct rcu_ctrlblk { }; /* Definition for rcupdate control block. */ -static struct rcu_ctrlblk rcu_ctrlblk = { - .donetail = &rcu_ctrlblk.rcucblist, - .curtail = &rcu_ctrlblk.rcucblist, +static struct rcu_ctrlblk rcu_sched_ctrlblk = { + .donetail = &rcu_sched_ctrlblk.rcucblist, + .curtail = &rcu_sched_ctrlblk.rcucblist, }; static struct rcu_ctrlblk rcu_bh_ctrlblk = { @@ -108,7 +108,8 @@ static int rcu_qsctr_help(struct rcu_ctrlblk *rcp) */ void rcu_sched_qs(int cpu) { - if (rcu_qsctr_help(&rcu_ctrlblk) + rcu_qsctr_help(&rcu_bh_ctrlblk)) + if (rcu_qsctr_help(&rcu_sched_ctrlblk) + + rcu_qsctr_help(&rcu_bh_ctrlblk)) raise_softirq(RCU_SOFTIRQ); } @@ -173,7 +174,7 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp) */ static void rcu_process_callbacks(struct softirq_action *unused) { - __rcu_process_callbacks(&rcu_ctrlblk); + __rcu_process_callbacks(&rcu_sched_ctrlblk); __rcu_process_callbacks(&rcu_bh_ctrlblk); } @@ -221,7 +222,7 @@ static void __call_rcu(struct rcu_head *head, */ void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu)) { - __call_rcu(head, func, &rcu_ctrlblk); + __call_rcu(head, func, &rcu_sched_ctrlblk); } EXPORT_SYMBOL_GPL(call_rcu); -- cgit v0.10.2 From 25502a6c13745f4650cc59322bd198194f55e796 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Thu, 1 Apr 2010 17:37:01 -0700 Subject: rcu: refactor RCU's context-switch handling The addition of preemptible RCU to treercu resulted in a bit of confusion and inefficiency surrounding the handling of context switches for RCU-sched and for RCU-preempt. For RCU-sched, a context switch is a quiescent state, pure and simple, just like it always has been. For RCU-preempt, a context switch is in no way a quiescent state, but special handling is required when a task blocks in an RCU read-side critical section. However, the callout from the scheduler and the outer loop in ksoftirqd still calls something named rcu_sched_qs(), whose name is no longer accurate. Furthermore, when rcu_check_callbacks() notes an RCU-sched quiescent state, it ends up unnecessarily (though harmlessly, aside from the performance hit) enqueuing the current task if it happens to be running in an RCU-preempt read-side critical section. This not only increases the maximum latency of scheduler_tick(), it also needlessly increases the overhead of the next outermost rcu_read_unlock() invocation. This patch addresses this situation by separating the notion of RCU's context-switch handling from that of RCU-sched's quiescent states. The context-switch handling is covered by rcu_note_context_switch() in general and by rcu_preempt_note_context_switch() for preemptible RCU. This permits rcu_sched_qs() to handle quiescent states and only quiescent states. It also reduces the maximum latency of scheduler_tick(), though probably by much less than a microsecond. Finally, it means that tasks within preemptible-RCU read-side critical sections avoid incurring the overhead of queuing unless there really is a context switch. Suggested-by: Lai Jiangshan Acked-by: Lai Jiangshan Signed-off-by: Paul E. McKenney Cc: Ingo Molnar Cc: Peter Zijlstra diff --git a/include/linux/rcutiny.h b/include/linux/rcutiny.h index bbeb55b..ff22b97 100644 --- a/include/linux/rcutiny.h +++ b/include/linux/rcutiny.h @@ -29,6 +29,10 @@ void rcu_sched_qs(int cpu); void rcu_bh_qs(int cpu); +static inline void rcu_note_context_switch(int cpu) +{ + rcu_sched_qs(cpu); +} #define __rcu_read_lock() preempt_disable() #define __rcu_read_unlock() preempt_enable() diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h index 7484fe6..b9f7460 100644 --- a/include/linux/rcutree.h +++ b/include/linux/rcutree.h @@ -34,6 +34,7 @@ struct notifier_block; extern void rcu_sched_qs(int cpu); extern void rcu_bh_qs(int cpu); +extern void rcu_note_context_switch(int cpu); extern int rcu_needs_cpu(int cpu); extern int rcu_expedited_torture_stats(char *page); diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 86bb949..e336313 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -97,25 +97,32 @@ static int rcu_gp_in_progress(struct rcu_state *rsp) */ void rcu_sched_qs(int cpu) { - struct rcu_data *rdp; + struct rcu_data *rdp = &per_cpu(rcu_sched_data, cpu); - rdp = &per_cpu(rcu_sched_data, cpu); rdp->passed_quiesc_completed = rdp->gpnum - 1; barrier(); rdp->passed_quiesc = 1; - rcu_preempt_note_context_switch(cpu); } void rcu_bh_qs(int cpu) { - struct rcu_data *rdp; + struct rcu_data *rdp = &per_cpu(rcu_bh_data, cpu); - rdp = &per_cpu(rcu_bh_data, cpu); rdp->passed_quiesc_completed = rdp->gpnum - 1; barrier(); rdp->passed_quiesc = 1; } +/* + * Note a context switch. This is a quiescent state for RCU-sched, + * and requires special handling for preemptible RCU. + */ +void rcu_note_context_switch(int cpu) +{ + rcu_sched_qs(cpu); + rcu_preempt_note_context_switch(cpu); +} + #ifdef CONFIG_NO_HZ DEFINE_PER_CPU(struct rcu_dynticks, rcu_dynticks) = { .dynticks_nesting = 1, diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index 687c4e9..f9bc83a 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h @@ -75,13 +75,19 @@ EXPORT_SYMBOL_GPL(rcu_force_quiescent_state); * that this just means that the task currently running on the CPU is * not in a quiescent state. There might be any number of tasks blocked * while in an RCU read-side critical section. + * + * Unlike the other rcu_*_qs() functions, callers to this function + * must disable irqs in order to protect the assignment to + * ->rcu_read_unlock_special. */ static void rcu_preempt_qs(int cpu) { struct rcu_data *rdp = &per_cpu(rcu_preempt_data, cpu); + rdp->passed_quiesc_completed = rdp->gpnum - 1; barrier(); rdp->passed_quiesc = 1; + current->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_NEED_QS; } /* @@ -144,9 +150,8 @@ static void rcu_preempt_note_context_switch(int cpu) * grace period, then the fact that the task has been enqueued * means that we continue to block the current grace period. */ - rcu_preempt_qs(cpu); local_irq_save(flags); - t->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_NEED_QS; + rcu_preempt_qs(cpu); local_irq_restore(flags); } @@ -236,7 +241,6 @@ static void rcu_read_unlock_special(struct task_struct *t) */ special = t->rcu_read_unlock_special; if (special & RCU_READ_UNLOCK_NEED_QS) { - t->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_NEED_QS; rcu_preempt_qs(smp_processor_id()); } @@ -473,7 +477,6 @@ static void rcu_preempt_check_callbacks(int cpu) struct task_struct *t = current; if (t->rcu_read_lock_nesting == 0) { - t->rcu_read_unlock_special &= ~RCU_READ_UNLOCK_NEED_QS; rcu_preempt_qs(cpu); return; } diff --git a/kernel/sched.c b/kernel/sched.c index 3c2a54f..d8a213c 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -3706,7 +3706,7 @@ need_resched: preempt_disable(); cpu = smp_processor_id(); rq = cpu_rq(cpu); - rcu_sched_qs(cpu); + rcu_note_context_switch(cpu); prev = rq->curr; switch_count = &prev->nivcsw; diff --git a/kernel/softirq.c b/kernel/softirq.c index 7c1a67e..0db913a 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -716,7 +716,7 @@ static int run_ksoftirqd(void * __bind_cpu) preempt_enable_no_resched(); cond_resched(); preempt_disable(); - rcu_sched_qs((long)__bind_cpu); + rcu_note_context_switch((long)__bind_cpu); } preempt_enable(); set_current_state(TASK_INTERRUPTIBLE); -- cgit v0.10.2 From bbad937983147c017c25406860287cb94da9af7c Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Fri, 2 Apr 2010 16:17:17 -0700 Subject: rcu: slim down rcutiny by removing rcu_scheduler_active and friends TINY_RCU does not need rcu_scheduler_active unless CONFIG_DEBUG_LOCK_ALLOC. So conditionally compile rcu_scheduler_active in order to slim down rcutiny a bit more. Also gets rid of an EXPORT_SYMBOL_GPL, which is responsible for most of the slimming. Signed-off-by: Paul E. McKenney diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index d8fb2ab..23be3a702 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -64,8 +64,6 @@ extern int sched_expedited_torture_stats(char *page); /* Internal to kernel */ extern void rcu_init(void); -extern int rcu_scheduler_active; -extern void rcu_scheduler_starting(void); #if defined(CONFIG_TREE_RCU) || defined(CONFIG_TREE_PREEMPT_RCU) #include @@ -178,7 +176,7 @@ static inline int rcu_read_lock_bh_held(void) #ifdef CONFIG_PREEMPT static inline int rcu_read_lock_sched_held(void) { - return !rcu_scheduler_active || preempt_count() != 0 || irqs_disabled(); + return preempt_count() != 0 || irqs_disabled(); } #else /* #ifdef CONFIG_PREEMPT */ static inline int rcu_read_lock_sched_held(void) diff --git a/include/linux/rcutiny.h b/include/linux/rcutiny.h index ff22b97..14e5a76 100644 --- a/include/linux/rcutiny.h +++ b/include/linux/rcutiny.h @@ -128,4 +128,17 @@ static inline int rcu_preempt_depth(void) return 0; } +#ifdef CONFIG_DEBUG_LOCK_ALLOC + +extern int rcu_scheduler_active __read_mostly; +extern void rcu_scheduler_starting(void); + +#else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ + +static inline void rcu_scheduler_starting(void) +{ +} + +#endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */ + #endif /* __LINUX_RCUTINY_H */ diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h index b9f7460..4828205 100644 --- a/include/linux/rcutree.h +++ b/include/linux/rcutree.h @@ -123,4 +123,7 @@ static inline int rcu_blocking_is_gp(void) return num_online_cpus() == 1; } +extern void rcu_scheduler_starting(void); +extern int rcu_scheduler_active __read_mostly; + #endif /* __LINUX_RCUTREE_H */ diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c index 49d808e..72a8dc9 100644 --- a/kernel/rcupdate.c +++ b/kernel/rcupdate.c @@ -44,7 +44,6 @@ #include #include #include -#include #include #ifdef CONFIG_DEBUG_LOCK_ALLOC @@ -64,9 +63,6 @@ struct lockdep_map rcu_sched_lock_map = EXPORT_SYMBOL_GPL(rcu_sched_lock_map); #endif -int rcu_scheduler_active __read_mostly; -EXPORT_SYMBOL_GPL(rcu_scheduler_active); - #ifdef CONFIG_DEBUG_LOCK_ALLOC int debug_lockdep_rcu_enabled(void) @@ -97,21 +93,6 @@ EXPORT_SYMBOL_GPL(rcu_read_lock_bh_held); #endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ /* - * This function is invoked towards the end of the scheduler's initialization - * process. Before this is called, the idle task might contain - * RCU read-side critical sections (during which time, this idle - * task is booting the system). After this function is called, the - * idle tasks are prohibited from containing RCU read-side critical - * sections. - */ -void rcu_scheduler_starting(void) -{ - WARN_ON(num_online_cpus() != 1); - WARN_ON(nr_context_switches() > 0); - rcu_scheduler_active = 1; -} - -/* * Awaken the corresponding synchronize_rcu() instance now that a * grace period has elapsed. */ diff --git a/kernel/rcutiny.c b/kernel/rcutiny.c index d9f8a62..b1804ff 100644 --- a/kernel/rcutiny.c +++ b/kernel/rcutiny.c @@ -54,6 +54,11 @@ static struct rcu_ctrlblk rcu_bh_ctrlblk = { .curtail = &rcu_bh_ctrlblk.rcucblist, }; +#ifdef CONFIG_DEBUG_LOCK_ALLOC +int rcu_scheduler_active __read_mostly; +EXPORT_SYMBOL_GPL(rcu_scheduler_active); +#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ + #ifdef CONFIG_NO_HZ static long rcu_dynticks_nesting = 1; @@ -276,3 +281,5 @@ void __init rcu_init(void) { open_softirq(RCU_SOFTIRQ, rcu_process_callbacks); } + +#include "rcutiny_plugin.h" diff --git a/kernel/rcutiny_plugin.h b/kernel/rcutiny_plugin.h new file mode 100644 index 0000000..d223a92bc --- /dev/null +++ b/kernel/rcutiny_plugin.h @@ -0,0 +1,39 @@ +/* + * Read-Copy Update mechanism for mutual exclusion (tree-based version) + * Internal non-public definitions that provide either classic + * or preemptable semantics. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright IBM Corporation, 2009 + * + * Author: Paul E. McKenney + */ + +#ifdef CONFIG_DEBUG_LOCK_ALLOC + +#include + +/* + * During boot, we forgive RCU lockdep issues. After this function is + * invoked, we start taking RCU lockdep issues seriously. + */ +void rcu_scheduler_starting(void) +{ + WARN_ON(nr_context_switches() > 0); + rcu_scheduler_active = 1; +} + +#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ diff --git a/kernel/rcutree.c b/kernel/rcutree.c index e336313..3623f8e 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -46,6 +46,7 @@ #include #include #include +#include #include "rcutree.h" @@ -80,6 +81,9 @@ DEFINE_PER_CPU(struct rcu_data, rcu_sched_data); struct rcu_state rcu_bh_state = RCU_STATE_INITIALIZER(rcu_bh_state); DEFINE_PER_CPU(struct rcu_data, rcu_bh_data); +int rcu_scheduler_active __read_mostly; +EXPORT_SYMBOL_GPL(rcu_scheduler_active); + /* * Return true if an RCU grace period is in progress. The ACCESS_ONCE()s * permit this function to be invoked without holding the root rcu_node @@ -1784,6 +1788,21 @@ static int __cpuinit rcu_cpu_notify(struct notifier_block *self, } /* + * This function is invoked towards the end of the scheduler's initialization + * process. Before this is called, the idle task might contain + * RCU read-side critical sections (during which time, this idle + * task is booting the system). After this function is called, the + * idle tasks are prohibited from containing RCU read-side critical + * sections. This function also enables RCU lockdep checking. + */ +void rcu_scheduler_starting(void) +{ + WARN_ON(num_online_cpus() != 1); + WARN_ON(nr_context_switches() > 0); + rcu_scheduler_active = 1; +} + +/* * Compute the per-level fanout, either using the exact fanout specified * or balancing the tree, depending on CONFIG_RCU_FANOUT_EXACT. */ -- cgit v0.10.2 From 55ec936ff4e57cc626db336a7bf33b267390e9b4 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Tue, 13 Apr 2010 12:22:33 -0700 Subject: rcu: enable CPU_STALL_VERBOSE by default The CPU_STALL_VERBOSE kernel configuration parameter was added to 2.6.34 to identify any preempted/blocked tasks that were preventing the current grace period from completing when running preemptible RCU. As is conventional for new configurations parameters, this defaulted disabled. It is now time to enable it by default. Signed-off-by: Paul E. McKenney diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 94090b4..930a9e5 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -805,7 +805,7 @@ config RCU_CPU_STALL_DETECTOR config RCU_CPU_STALL_VERBOSE bool "Print additional per-task information for RCU_CPU_STALL_DETECTOR" depends on RCU_CPU_STALL_DETECTOR && TREE_PREEMPT_RCU - default n + default y help This option causes RCU to printk detailed per-task information for any tasks that are stalling the current RCU grace period. -- cgit v0.10.2 From c68de2097a8799549a3c3bf27cbfeea24a604284 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Thu, 15 Apr 2010 10:12:40 -0700 Subject: rcu: disable CPU stall warnings upon panic The current RCU CPU stall warnings remain enabled even after a panic occurs, which some people have found to be a bit counterproductive. This patch therefore uses a notifier to disable stall warnings once a panic occurs. Signed-off-by: Paul E. McKenney diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 3623f8e..595fb83 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -449,6 +449,8 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp) #ifdef CONFIG_RCU_CPU_STALL_DETECTOR +int rcu_cpu_stall_panicking __read_mostly; + static void record_gp_stall_check_time(struct rcu_state *rsp) { rsp->gp_start = jiffies; @@ -526,6 +528,8 @@ static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp) long delta; struct rcu_node *rnp; + if (rcu_cpu_stall_panicking) + return; delta = jiffies - rsp->jiffies_stall; rnp = rdp->mynode; if ((rnp->qsmask & rdp->grpmask) && delta >= 0) { @@ -540,6 +544,21 @@ static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp) } } +static int rcu_panic(struct notifier_block *this, unsigned long ev, void *ptr) +{ + rcu_cpu_stall_panicking = 1; + return NOTIFY_DONE; +} + +static struct notifier_block rcu_panic_block = { + .notifier_call = rcu_panic, +}; + +static void __init check_cpu_stall_init(void) +{ + atomic_notifier_chain_register(&panic_notifier_list, &rcu_panic_block); +} + #else /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ static void record_gp_stall_check_time(struct rcu_state *rsp) @@ -550,6 +569,10 @@ static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp) { } +static void __init check_cpu_stall_init(void) +{ +} + #endif /* #else #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ /* @@ -1934,6 +1957,7 @@ void __init rcu_init(void) cpu_notifier(rcu_cpu_notify, 0); for_each_online_cpu(cpu) rcu_cpu_notify(NULL, CPU_UP_PREPARE, (void *)(long)cpu); + check_cpu_stall_init(); } #include "rcutree_plugin.h" -- cgit v0.10.2 From 26845c2860cebebe6ce2d9d01ae3cb3db84b7e29 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Tue, 13 Apr 2010 14:19:23 -0700 Subject: rcu: print boot-time console messages if RCU configs out of ordinary Print boot-time messages if tracing is enabled, if fanout is set to non-default values, if exact fanout is specified, if accelerated dyntick-idle grace periods have been enabled, if RCU-lockdep is enabled, if rcutorture has been boot-time enabled, if the CPU stall detector has been disabled, or if four-level hierarchy has been enabled. This is all for TREE_RCU and TREE_PREEMPT_RCU. TINY_RCU will be handled separately, if at all. Suggested-by: Josh Triplett Signed-off-by: Paul E. McKenney diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 595fb83..ec6196f 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -1938,12 +1938,6 @@ void __init rcu_init(void) int cpu; rcu_bootup_announce(); -#ifdef CONFIG_RCU_CPU_STALL_DETECTOR - printk(KERN_INFO "RCU-based detection of stalled CPUs is enabled.\n"); -#endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ -#if NUM_RCU_LVL_4 != 0 - printk(KERN_INFO "Experimental four-level hierarchy is enabled.\n"); -#endif /* #if NUM_RCU_LVL_4 != 0 */ RCU_INIT_FLAVOR(&rcu_sched_state, rcu_sched_data); RCU_INIT_FLAVOR(&rcu_bh_state, rcu_bh_data); __rcu_init_preempt(); diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index f9bc83a..0ae2339 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h @@ -26,6 +26,45 @@ #include +/* + * Check the RCU kernel configuration parameters and print informative + * messages about anything out of the ordinary. If you like #ifdef, you + * will love this function. + */ +static void __init rcu_bootup_announce_oddness(void) +{ +#ifdef CONFIG_RCU_TRACE + printk(KERN_INFO "\tRCU debugfs-based tracing is enabled.\n"); +#endif +#if (defined(CONFIG_64BIT) && CONFIG_RCU_FANOUT != 64) || (!defined(CONFIG_64BIT) && CONFIG_RCU_FANOUT != 32) + printk(KERN_INFO "\tCONFIG_RCU_FANOUT set to non-default value of %d\n", + CONFIG_RCU_FANOUT); +#endif +#ifdef CONFIG_RCU_FANOUT_EXACT + printk(KERN_INFO "\tHierarchical RCU autobalancing is disabled.\n"); +#endif +#ifdef CONFIG_RCU_FAST_NO_HZ + printk(KERN_INFO + "\tRCU dyntick-idle grace-period acceleration is enabled.\n"); +#endif +#ifdef CONFIG_PROVE_RCU + printk(KERN_INFO "\tRCU lockdep checking is enabled.\n"); +#endif +#ifdef CONFIG_RCU_TORTURE_TEST_RUNNABLE + printk(KERN_INFO "\tRCU torture testing starts during boot.\n"); +#endif +#ifndef CONFIG_RCU_CPU_STALL_DETECTOR + printk(KERN_INFO + "\tRCU-based detection of stalled CPUs is disabled.\n"); +#endif +#ifndef CONFIG_RCU_CPU_STALL_VERBOSE + printk(KERN_INFO "\tVerbose stalled-CPUs detection is disabled.\n"); +#endif +#if NUM_RCU_LVL_4 != 0 + printk(KERN_INFO "\tExperimental four-level hierarchy is enabled.\n"); +#endif +} + #ifdef CONFIG_TREE_PREEMPT_RCU struct rcu_state rcu_preempt_state = RCU_STATE_INITIALIZER(rcu_preempt_state); @@ -38,8 +77,8 @@ static int rcu_preempted_readers_exp(struct rcu_node *rnp); */ static void __init rcu_bootup_announce(void) { - printk(KERN_INFO - "Experimental preemptable hierarchical RCU implementation.\n"); + printk(KERN_INFO "Preemptable hierarchical RCU implementation.\n"); + rcu_bootup_announce_oddness(); } /* @@ -757,6 +796,7 @@ void exit_rcu(void) static void __init rcu_bootup_announce(void) { printk(KERN_INFO "Hierarchical RCU implementation.\n"); + rcu_bootup_announce_oddness(); } /* -- cgit v0.10.2 From 4300aa642cc9ecb35f2e0683dd294fb790ef028c Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Tue, 13 Apr 2010 16:18:22 -0700 Subject: rcu: improve RCU CPU stall-warning messages The existing RCU CPU stall-warning messages can be confusing, especially in the case where one CPU detects a single other stalled CPU. In addition, the console messages did not say which flavor of RCU detected the stall, which can make it difficult to work out exactly what is causing the stall. This commit improves these messages. Requested-by: Dhaval Giani Signed-off-by: Paul E. McKenney diff --git a/kernel/rcutree.c b/kernel/rcutree.c index ec6196f..f391886 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -54,8 +54,8 @@ static struct lock_class_key rcu_node_class[NUM_RCU_LVLS]; -#define RCU_STATE_INITIALIZER(name) { \ - .level = { &name.node[0] }, \ +#define RCU_STATE_INITIALIZER(structname) { \ + .level = { &structname.node[0] }, \ .levelcnt = { \ NUM_RCU_LVL_0, /* root of hierarchy. */ \ NUM_RCU_LVL_1, \ @@ -66,13 +66,14 @@ static struct lock_class_key rcu_node_class[NUM_RCU_LVLS]; .signaled = RCU_GP_IDLE, \ .gpnum = -300, \ .completed = -300, \ - .onofflock = __RAW_SPIN_LOCK_UNLOCKED(&name.onofflock), \ + .onofflock = __RAW_SPIN_LOCK_UNLOCKED(&structname.onofflock), \ .orphan_cbs_list = NULL, \ - .orphan_cbs_tail = &name.orphan_cbs_list, \ + .orphan_cbs_tail = &structname.orphan_cbs_list, \ .orphan_qlen = 0, \ - .fqslock = __RAW_SPIN_LOCK_UNLOCKED(&name.fqslock), \ + .fqslock = __RAW_SPIN_LOCK_UNLOCKED(&structname.fqslock), \ .n_force_qs = 0, \ .n_force_qs_ngp = 0, \ + .name = #structname, \ } struct rcu_state rcu_sched_state = RCU_STATE_INITIALIZER(rcu_sched_state); @@ -483,7 +484,8 @@ static void print_other_cpu_stall(struct rcu_state *rsp) /* OK, time to rat on our buddy... */ - printk(KERN_ERR "INFO: RCU detected CPU stalls:"); + printk(KERN_ERR "INFO: %s detected stalls on CPUs/tasks: {", + rsp->name); rcu_for_each_leaf_node(rsp, rnp) { raw_spin_lock_irqsave(&rnp->lock, flags); rcu_print_task_stall(rnp); @@ -494,7 +496,7 @@ static void print_other_cpu_stall(struct rcu_state *rsp) if (rnp->qsmask & (1UL << cpu)) printk(" %d", rnp->grplo + cpu); } - printk(" (detected by %d, t=%ld jiffies)\n", + printk("} (detected by %d, t=%ld jiffies)\n", smp_processor_id(), (long)(jiffies - rsp->gp_start)); trigger_all_cpu_backtrace(); @@ -510,8 +512,8 @@ static void print_cpu_stall(struct rcu_state *rsp) unsigned long flags; struct rcu_node *rnp = rcu_get_root(rsp); - printk(KERN_ERR "INFO: RCU detected CPU %d stall (t=%lu jiffies)\n", - smp_processor_id(), jiffies - rsp->gp_start); + printk(KERN_ERR "INFO: %s detected stall on CPU %d (t=%lu jiffies)\n", + rsp->name, smp_processor_id(), jiffies - rsp->gp_start); trigger_all_cpu_backtrace(); raw_spin_lock_irqsave(&rnp->lock, flags); diff --git a/kernel/rcutree.h b/kernel/rcutree.h index 4a525a3..11f1711 100644 --- a/kernel/rcutree.h +++ b/kernel/rcutree.h @@ -326,6 +326,7 @@ struct rcu_state { unsigned long jiffies_stall; /* Time at which to check */ /* for CPU stalls. */ #endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ + char *name; /* Name of structure. */ }; /* Return values for rcu_preempt_offline_tasks(). */ -- cgit v0.10.2 From 4a90a0681cf6cd21cd444184302aa045156486b3 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Wed, 14 Apr 2010 16:48:11 -0700 Subject: rcu: permit discontiguous cpu_possible_mask CPU numbering TREE_RCU assumes that CPU numbering is contiguous, but some users need large holes in the numbering to better map to hardware layout. This patch makes TREE_RCU (and TREE_PREEMPT_RCU) tolerate large holes in the CPU numbering. However, NR_CPUS must still be greater than the largest CPU number. Signed-off-by: Paul E. McKenney diff --git a/kernel/rcutree.c b/kernel/rcutree.c index f391886..c60fd74 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -1913,7 +1913,7 @@ static void __init rcu_init_one(struct rcu_state *rsp) rnp = rsp->level[NUM_RCU_LVLS - 1]; for_each_possible_cpu(i) { - if (i > rnp->grphi) + while (i > rnp->grphi) rnp++; rsp->rda[i]->mynode = rnp; rcu_boot_init_percpu_data(i, rsp); -- cgit v0.10.2 From d21670acab9fcb4bc74a40b68a6941059234c55c Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Wed, 14 Apr 2010 17:39:26 -0700 Subject: rcu: reduce the number of spurious RCU_SOFTIRQ invocations Lai Jiangshan noted that up to 10% of the RCU_SOFTIRQ are spurious, and traced this down to the fact that the current grace-period machinery will uselessly raise RCU_SOFTIRQ when a given CPU needs to go through a quiescent state, but has not yet done so. In this situation, there might well be nothing that RCU_SOFTIRQ can do, and the overhead can be worth worrying about in the ksoftirqd case. This patch therefore avoids raising RCU_SOFTIRQ in this situation. Changes since v1 (http://lkml.org/lkml/2010/3/30/122 from Lai Jiangshan): o Omit the rcu_qs_pending() prechecks, as they aren't that much less expensive than the quiescent-state checks. o Merge with the set_need_resched() patch that reduces IPIs. o Add the new n_rp_report_qs field to the rcu_pending tracing output. o Update the tracing documentation accordingly. Signed-off-by: Lai Jiangshan Signed-off-by: Paul E. McKenney diff --git a/Documentation/RCU/trace.txt b/Documentation/RCU/trace.txt index 8608fd8..efd8cc9 100644 --- a/Documentation/RCU/trace.txt +++ b/Documentation/RCU/trace.txt @@ -256,23 +256,23 @@ o Each element of the form "1/1 0:127 ^0" represents one struct The output of "cat rcu/rcu_pending" looks as follows: rcu_sched: - 0 np=255892 qsp=53936 cbr=0 cng=14417 gpc=10033 gps=24320 nf=6445 nn=146741 - 1 np=261224 qsp=54638 cbr=0 cng=25723 gpc=16310 gps=2849 nf=5912 nn=155792 - 2 np=237496 qsp=49664 cbr=0 cng=2762 gpc=45478 gps=1762 nf=1201 nn=136629 - 3 np=236249 qsp=48766 cbr=0 cng=286 gpc=48049 gps=1218 nf=207 nn=137723 - 4 np=221310 qsp=46850 cbr=0 cng=26 gpc=43161 gps=4634 nf=3529 nn=123110 - 5 np=237332 qsp=48449 cbr=0 cng=54 gpc=47920 gps=3252 nf=201 nn=137456 - 6 np=219995 qsp=46718 cbr=0 cng=50 gpc=42098 gps=6093 nf=4202 nn=120834 - 7 np=249893 qsp=49390 cbr=0 cng=72 gpc=38400 gps=17102 nf=41 nn=144888 + 0 np=255892 qsp=53936 rpq=85 cbr=0 cng=14417 gpc=10033 gps=24320 nf=6445 nn=146741 + 1 np=261224 qsp=54638 rpq=33 cbr=0 cng=25723 gpc=16310 gps=2849 nf=5912 nn=155792 + 2 np=237496 qsp=49664 rpq=23 cbr=0 cng=2762 gpc=45478 gps=1762 nf=1201 nn=136629 + 3 np=236249 qsp=48766 rpq=98 cbr=0 cng=286 gpc=48049 gps=1218 nf=207 nn=137723 + 4 np=221310 qsp=46850 rpq=7 cbr=0 cng=26 gpc=43161 gps=4634 nf=3529 nn=123110 + 5 np=237332 qsp=48449 rpq=9 cbr=0 cng=54 gpc=47920 gps=3252 nf=201 nn=137456 + 6 np=219995 qsp=46718 rpq=12 cbr=0 cng=50 gpc=42098 gps=6093 nf=4202 nn=120834 + 7 np=249893 qsp=49390 rpq=42 cbr=0 cng=72 gpc=38400 gps=17102 nf=41 nn=144888 rcu_bh: - 0 np=146741 qsp=1419 cbr=0 cng=6 gpc=0 gps=0 nf=2 nn=145314 - 1 np=155792 qsp=12597 cbr=0 cng=0 gpc=4 gps=8 nf=3 nn=143180 - 2 np=136629 qsp=18680 cbr=0 cng=0 gpc=7 gps=6 nf=0 nn=117936 - 3 np=137723 qsp=2843 cbr=0 cng=0 gpc=10 gps=7 nf=0 nn=134863 - 4 np=123110 qsp=12433 cbr=0 cng=0 gpc=4 gps=2 nf=0 nn=110671 - 5 np=137456 qsp=4210 cbr=0 cng=0 gpc=6 gps=5 nf=0 nn=133235 - 6 np=120834 qsp=9902 cbr=0 cng=0 gpc=6 gps=3 nf=2 nn=110921 - 7 np=144888 qsp=26336 cbr=0 cng=0 gpc=8 gps=2 nf=0 nn=118542 + 0 np=146741 qsp=1419 rpq=6 cbr=0 cng=6 gpc=0 gps=0 nf=2 nn=145314 + 1 np=155792 qsp=12597 rpq=3 cbr=0 cng=0 gpc=4 gps=8 nf=3 nn=143180 + 2 np=136629 qsp=18680 rpq=1 cbr=0 cng=0 gpc=7 gps=6 nf=0 nn=117936 + 3 np=137723 qsp=2843 rpq=0 cbr=0 cng=0 gpc=10 gps=7 nf=0 nn=134863 + 4 np=123110 qsp=12433 rpq=0 cbr=0 cng=0 gpc=4 gps=2 nf=0 nn=110671 + 5 np=137456 qsp=4210 rpq=1 cbr=0 cng=0 gpc=6 gps=5 nf=0 nn=133235 + 6 np=120834 qsp=9902 rpq=2 cbr=0 cng=0 gpc=6 gps=3 nf=2 nn=110921 + 7 np=144888 qsp=26336 rpq=0 cbr=0 cng=0 gpc=8 gps=2 nf=0 nn=118542 As always, this is once again split into "rcu_sched" and "rcu_bh" portions, with CONFIG_TREE_PREEMPT_RCU kernels having an additional @@ -284,6 +284,9 @@ o "np" is the number of times that __rcu_pending() has been invoked o "qsp" is the number of times that the RCU was waiting for a quiescent state from this CPU. +o "rpq" is the number of times that the CPU had passed through + a quiescent state, but not yet reported it to RCU. + o "cbr" is the number of times that this CPU had RCU callbacks that had passed through a grace period, and were thus ready to be invoked. diff --git a/kernel/rcutree.c b/kernel/rcutree.c index c60fd74..ba69969 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -1161,8 +1161,6 @@ static void rcu_do_batch(struct rcu_state *rsp, struct rcu_data *rdp) */ void rcu_check_callbacks(int cpu, int user) { - if (!rcu_pending(cpu)) - return; /* if nothing for RCU to do. */ if (user || (idle_cpu(cpu) && rcu_scheduler_active && !in_softirq() && hardirq_count() <= (1 << HARDIRQ_SHIFT))) { @@ -1194,7 +1192,8 @@ void rcu_check_callbacks(int cpu, int user) rcu_bh_qs(cpu); } rcu_preempt_check_callbacks(cpu); - raise_softirq(RCU_SOFTIRQ); + if (rcu_pending(cpu)) + raise_softirq(RCU_SOFTIRQ); } #ifdef CONFIG_SMP @@ -1534,18 +1533,20 @@ static int __rcu_pending(struct rcu_state *rsp, struct rcu_data *rdp) check_cpu_stall(rsp, rdp); /* Is the RCU core waiting for a quiescent state from this CPU? */ - if (rdp->qs_pending) { + if (rdp->qs_pending && !rdp->passed_quiesc) { /* * If force_quiescent_state() coming soon and this CPU * needs a quiescent state, and this is either RCU-sched * or RCU-bh, force a local reschedule. */ + rdp->n_rp_qs_pending++; if (!rdp->preemptable && ULONG_CMP_LT(ACCESS_ONCE(rsp->jiffies_force_qs) - 1, jiffies)) set_need_resched(); - rdp->n_rp_qs_pending++; + } else if (rdp->qs_pending && rdp->passed_quiesc) { + rdp->n_rp_report_qs++; return 1; } diff --git a/kernel/rcutree.h b/kernel/rcutree.h index 11f1711..14c040b 100644 --- a/kernel/rcutree.h +++ b/kernel/rcutree.h @@ -223,6 +223,7 @@ struct rcu_data { /* 5) __rcu_pending() statistics. */ unsigned long n_rcu_pending; /* rcu_pending() calls since boot. */ unsigned long n_rp_qs_pending; + unsigned long n_rp_report_qs; unsigned long n_rp_cb_ready; unsigned long n_rp_cpu_needs_gp; unsigned long n_rp_gp_completed; diff --git a/kernel/rcutree_trace.c b/kernel/rcutree_trace.c index d45db2e..36c95b4 100644 --- a/kernel/rcutree_trace.c +++ b/kernel/rcutree_trace.c @@ -241,11 +241,13 @@ static const struct file_operations rcugp_fops = { static void print_one_rcu_pending(struct seq_file *m, struct rcu_data *rdp) { seq_printf(m, "%3d%cnp=%ld " - "qsp=%ld cbr=%ld cng=%ld gpc=%ld gps=%ld nf=%ld nn=%ld\n", + "qsp=%ld rpq=%ld cbr=%ld cng=%ld " + "gpc=%ld gps=%ld nf=%ld nn=%ld\n", rdp->cpu, cpu_is_offline(rdp->cpu) ? '!' : ' ', rdp->n_rcu_pending, rdp->n_rp_qs_pending, + rdp->n_rp_report_qs, rdp->n_rp_cb_ready, rdp->n_rp_cpu_needs_gp, rdp->n_rp_gp_completed, -- cgit v0.10.2 From f1d507beeab1d1d60a1c58eac7dc81522c6f4629 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Thu, 15 Apr 2010 15:49:46 -0700 Subject: rcu: improve the RCU CPU-stall warning documentation The existing Documentation/RCU/stallwarn.txt has proven unhelpful, so rework it a bit. In particular, show how to interpret the stall-warning messages. Signed-off-by: Paul E. McKenney diff --git a/Documentation/RCU/stallwarn.txt b/Documentation/RCU/stallwarn.txt index 1423d25..44c6dcc9 100644 --- a/Documentation/RCU/stallwarn.txt +++ b/Documentation/RCU/stallwarn.txt @@ -3,35 +3,79 @@ Using RCU's CPU Stall Detector The CONFIG_RCU_CPU_STALL_DETECTOR kernel config parameter enables RCU's CPU stall detector, which detects conditions that unduly delay RCU grace periods. The stall detector's idea of what constitutes -"unduly delayed" is controlled by a pair of C preprocessor macros: +"unduly delayed" is controlled by a set of C preprocessor macros: RCU_SECONDS_TILL_STALL_CHECK This macro defines the period of time that RCU will wait from the beginning of a grace period until it issues an RCU CPU - stall warning. It is normally ten seconds. + stall warning. This time period is normally ten seconds. RCU_SECONDS_TILL_STALL_RECHECK This macro defines the period of time that RCU will wait after - issuing a stall warning until it issues another stall warning. - It is normally set to thirty seconds. + issuing a stall warning until it issues another stall warning + for the same stall. This time period is normally set to thirty + seconds. RCU_STALL_RAT_DELAY - The CPU stall detector tries to make the offending CPU rat on itself, - as this often gives better-quality stack traces. However, if - the offending CPU does not detect its own stall in the number - of jiffies specified by RCU_STALL_RAT_DELAY, then other CPUs will - complain. This is normally set to two jiffies. + The CPU stall detector tries to make the offending CPU print its + own warnings, as this often gives better-quality stack traces. + However, if the offending CPU does not detect its own stall in + the number of jiffies specified by RCU_STALL_RAT_DELAY, then + some other CPU will complain. This delay is normally set to + two jiffies. -The following problems can result in an RCU CPU stall warning: +When a CPU detects that it is stalling, it will print a message similar +to the following: + +INFO: rcu_sched_state detected stall on CPU 5 (t=2500 jiffies) + +This message indicates that CPU 5 detected that it was causing a stall, +and that the stall was affecting RCU-sched. This message will normally be +followed by a stack dump of the offending CPU. On TREE_RCU kernel builds, +RCU and RCU-sched are implemented by the same underlying mechanism, +while on TREE_PREEMPT_RCU kernel builds, RCU is instead implemented +by rcu_preempt_state. + +On the other hand, if the offending CPU fails to print out a stall-warning +message quickly enough, some other CPU will print a message similar to +the following: + +INFO: rcu_bh_state detected stalls on CPUs/tasks: { 3 5 } (detected by 2, 2502 jiffies) + +This message indicates that CPU 2 detected that CPUs 3 and 5 were both +causing stalls, and that the stall was affecting RCU-bh. This message +will normally be followed by stack dumps for each CPU. Please note that +TREE_PREEMPT_RCU builds can be stalled by tasks as well as by CPUs, +and that the tasks will be indicated by PID, for example, "P3421". +It is even possible for a rcu_preempt_state stall to be caused by both +CPUs -and- tasks, in which case the offending CPUs and tasks will all +be called out in the list. + +Finally, if the grace period ends just as the stall warning starts +printing, there will be a spurious stall-warning message: + +INFO: rcu_bh_state detected stalls on CPUs/tasks: { } (detected by 4, 2502 jiffies) + +This is rare, but does happen from time to time in real life. + +So your kernel printed an RCU CPU stall warning. The next question is +"What caused it?" The following problems can result in RCU CPU stall +warnings: o A CPU looping in an RCU read-side critical section. -o A CPU looping with interrupts disabled. +o A CPU looping with interrupts disabled. This condition can + result in RCU-sched and RCU-bh stalls. -o A CPU looping with preemption disabled. +o A CPU looping with preemption disabled. This condition can + result in RCU-sched stalls and, if ksoftirqd is in use, RCU-bh + stalls. + +o A CPU looping with bottom halves disabled. This condition can + result in RCU-sched and RCU-bh stalls. o For !CONFIG_PREEMPT kernels, a CPU looping anywhere in the kernel without invoking schedule(). @@ -39,20 +83,24 @@ o For !CONFIG_PREEMPT kernels, a CPU looping anywhere in the kernel o A bug in the RCU implementation. o A hardware failure. This is quite unlikely, but has occurred - at least once in a former life. A CPU failed in a running system, + at least once in real life. A CPU failed in a running system, becoming unresponsive, but not causing an immediate crash. This resulted in a series of RCU CPU stall warnings, eventually leading the realization that the CPU had failed. -The RCU, RCU-sched, and RCU-bh implementations have CPU stall warning. -SRCU does not do so directly, but its calls to synchronize_sched() will -result in RCU-sched detecting any CPU stalls that might be occurring. - -To diagnose the cause of the stall, inspect the stack traces. The offending -function will usually be near the top of the stack. If you have a series -of stall warnings from a single extended stall, comparing the stack traces -can often help determine where the stall is occurring, which will usually -be in the function nearest the top of the stack that stays the same from -trace to trace. +The RCU, RCU-sched, and RCU-bh implementations have CPU stall +warning. SRCU does not have its own CPU stall warnings, but its +calls to synchronize_sched() will result in RCU-sched detecting +RCU-sched-related CPU stalls. Please note that RCU only detects +CPU stalls when there is a grace period in progress. No grace period, +no CPU stall warnings. + +To diagnose the cause of the stall, inspect the stack traces. +The offending function will usually be near the top of the stack. +If you have a series of stall warnings from a single extended stall, +comparing the stack traces can often help determine where the stall +is occurring, which will usually be in the function nearest the top of +that portion of the stack which remains the same from trace to trace. +If you can reliably trigger the stall, ftrace can be quite helpful. RCU bugs can often be debugged with the help of CONFIG_RCU_TRACE. -- cgit v0.10.2 From d14aada8e20bdf81ffd43f433b123972cf575b32 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Mon, 19 Apr 2010 22:24:22 -0700 Subject: rcu: make SRCU usable in modules Add a #include for mutex.h to allow SRCU to be more easily used in kernel modules. Signed-off-by: Lai Jiangshan Signed-off-by: Paul E. McKenney diff --git a/include/linux/srcu.h b/include/linux/srcu.h index 9c01f10..4d5d2f5 100644 --- a/include/linux/srcu.h +++ b/include/linux/srcu.h @@ -27,6 +27,8 @@ #ifndef _LINUX_SRCU_H #define _LINUX_SRCU_H +#include + struct srcu_struct_array { int c[2]; }; -- cgit v0.10.2 From 77e38ed347162423c6b72e06c865a121081c2bb6 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Sun, 25 Apr 2010 21:04:29 -0700 Subject: rcu: RCU_FAST_NO_HZ must check RCU dyntick state The current version of RCU_FAST_NO_HZ reproduces the old CLASSIC_RCU dyntick-idle bug, as it fails to detect CPUs that have interrupted or NMIed out of dyntick-idle mode. Fix this by making rcu_needs_cpu() check the state in the per-CPU rcu_dynticks variables, thus correctly detecting the dyntick-idle state from an RCU perspective. Signed-off-by: Paul E. McKenney diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index 0ae2339..9b18227 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h @@ -1051,6 +1051,8 @@ static DEFINE_PER_CPU(unsigned long, rcu_dyntick_holdoff); int rcu_needs_cpu(int cpu) { int c = 0; + int snap; + int snap_nmi; int thatcpu; /* Check for being in the holdoff period. */ @@ -1058,12 +1060,18 @@ int rcu_needs_cpu(int cpu) return rcu_needs_cpu_quick_check(cpu); /* Don't bother unless we are the last non-dyntick-idle CPU. */ - for_each_cpu_not(thatcpu, nohz_cpu_mask) - if (cpu_online(thatcpu) && thatcpu != cpu) { + for_each_online_cpu(thatcpu) { + if (thatcpu == cpu) + continue; + snap = per_cpu(rcu_dynticks, thatcpu)->dynticks; + snap_nmi = per_cpu(rcu_dynticks, thatcpu)->dynticks_nmi; + smp_mb(); /* Order sampling of snap with end of grace period. */ + if (((snap & 0x1) != 0) || ((snap_nmi & 0x1) != 0)) { per_cpu(rcu_dyntick_drain, cpu) = 0; per_cpu(rcu_dyntick_holdoff, cpu) = jiffies - 1; return rcu_needs_cpu_quick_check(cpu); } + } /* Check and update the rcu_dyntick_drain sequencing. */ if (per_cpu(rcu_dyntick_drain, cpu) <= 0) { -- cgit v0.10.2 From d822ed1094032ab524344a9a474c93128d9c2159 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Sat, 8 May 2010 19:58:22 -0700 Subject: rcu: fix build bug in RCU_FAST_NO_HZ builds Signed-off-by: Paul E. McKenney diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index 9b18227..ac7d80f 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h @@ -1063,8 +1063,8 @@ int rcu_needs_cpu(int cpu) for_each_online_cpu(thatcpu) { if (thatcpu == cpu) continue; - snap = per_cpu(rcu_dynticks, thatcpu)->dynticks; - snap_nmi = per_cpu(rcu_dynticks, thatcpu)->dynticks_nmi; + snap = per_cpu(rcu_dynticks, thatcpu).dynticks; + snap_nmi = per_cpu(rcu_dynticks, thatcpu).dynticks_nmi; smp_mb(); /* Order sampling of snap with end of grace period. */ if (((snap & 0x1) != 0) || ((snap_nmi & 0x1) != 0)) { per_cpu(rcu_dyntick_drain, cpu) = 0; -- cgit v0.10.2 From c3f8978ea332cd4be88e12574452a025892ac9af Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 10 May 2010 13:37:16 -0700 Subject: x86, fpu: Unbreak FPU emulation Unbreak FPU emulation, broken by checkin 86603283326c9e95e5ad4e9fdddeec93cac5d9ad: x86: Introduce 'struct fpu' and related API Signed-off-by: H. Peter Anvin Cc: Avi Kivity Cc: Suresh Siddha LKML-Reference: <1273135546-29690-3-git-send-email-avi@redhat.com> diff --git a/arch/x86/math-emu/fpu_aux.c b/arch/x86/math-emu/fpu_aux.c index 62797f9..dc8adad 100644 --- a/arch/x86/math-emu/fpu_aux.c +++ b/arch/x86/math-emu/fpu_aux.c @@ -52,7 +52,7 @@ void finit_soft_fpu(struct i387_soft_struct *soft) void finit(void) { - finit_task(¤t->thread.fpu); + finit_soft_fpu(¤t->thread.fpu.state->soft); } /* diff --git a/arch/x86/math-emu/fpu_entry.c b/arch/x86/math-emu/fpu_entry.c index 5d87f58..7718541 100644 --- a/arch/x86/math-emu/fpu_entry.c +++ b/arch/x86/math-emu/fpu_entry.c @@ -681,7 +681,7 @@ int fpregs_soft_set(struct task_struct *target, unsigned int pos, unsigned int count, const void *kbuf, const void __user *ubuf) { - struct i387_soft_struct *s387 = &target->thread.xstate->soft; + struct i387_soft_struct *s387 = &target->thread.fpu.state->soft; void *space = s387->st_space; int ret; int offset, other, i, tags, regnr, tag, newtop; @@ -733,7 +733,7 @@ int fpregs_soft_get(struct task_struct *target, unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) { - struct i387_soft_struct *s387 = &target->thread.xstate->soft; + struct i387_soft_struct *s387 = &target->thread.fpu.state->soft; const void *space = s387->st_space; int ret; int offset = (S387->ftop & 7) * 10, other = 80 - offset; diff --git a/arch/x86/math-emu/fpu_system.h b/arch/x86/math-emu/fpu_system.h index 50fa0ec..2c61441 100644 --- a/arch/x86/math-emu/fpu_system.h +++ b/arch/x86/math-emu/fpu_system.h @@ -31,7 +31,7 @@ #define SEG_EXPAND_DOWN(s) (((s).b & ((1 << 11) | (1 << 10))) \ == (1 << 10)) -#define I387 (current->thread.xstate) +#define I387 (current->thread.fpu.state) #define FPU_info (I387->soft.info) #define FPU_CS (*(unsigned short *) &(FPU_info->regs->cs)) -- cgit v0.10.2 From dce8bf4e115aa44d590802ce3554e926840c9042 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 10 May 2010 13:41:41 -0700 Subject: x86, fpu: Use the proper asm constraint in use_xsave() The proper constraint for a receiving 8-bit variable is "=qm", not "=g" which equals "=rim"; even though the "i" will never match, bugs can and do happen due to the difference between "q" and "r". Signed-off-by: H. Peter Anvin Cc: Avi Kivity Cc: Suresh Siddha LKML-Reference: <1273135546-29690-2-git-send-email-avi@redhat.com> diff --git a/arch/x86/include/asm/i387.h b/arch/x86/include/asm/i387.h index 1a8cca3..8002e9c 100644 --- a/arch/x86/include/asm/i387.h +++ b/arch/x86/include/asm/i387.h @@ -64,7 +64,7 @@ static inline bool use_xsave(void) alternative_io("mov $0, %0", "mov $1, %0", X86_FEATURE_XSAVE, - "=g"(has_xsave)); + "=qm" (has_xsave)); return has_xsave; } -- cgit v0.10.2 From fefb0b94bbab858be0909a7eb5ef357e0f996a79 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 10 May 2010 13:57:51 -0300 Subject: perf hist: Calculate max_sym name len and nr_entries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Better done when we are adding entries, be it initially of when we're re-sorting the histograms. Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 53077fd..d7c7529 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -296,13 +296,13 @@ static int __cmd_report(void) next = rb_first(&session->hists_tree); while (next) { struct hists *hists; - u64 nr_hists; hists = rb_entry(next, struct hists, rb_node); hists__collapse_resort(hists); - nr_hists = hists__output_resort(hists); + hists__output_resort(hists); if (use_browser) - perf_session__browse_hists(&hists->entries, nr_hists, + perf_session__browse_hists(&hists->entries, + hists->nr_entries, hists->stats.total, help, input_name); else { diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 410cf56..e34fd24 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -47,6 +47,13 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template) return self; } +static void hists__inc_nr_entries(struct hists *self, struct hist_entry *entry) +{ + if (entry->ms.sym && self->max_sym_namelen < entry->ms.sym->namelen) + self->max_sym_namelen = entry->ms.sym->namelen; + ++self->nr_entries; +} + struct hist_entry *__hists__add_entry(struct hists *self, struct addr_location *al, struct symbol *sym_parent, u64 count) @@ -89,6 +96,7 @@ struct hist_entry *__hists__add_entry(struct hists *self, return NULL; rb_link_node(&he->rb_node, parent, p); rb_insert_color(&he->rb_node, &self->entries); + hists__inc_nr_entries(self, he); out: hist_entry__add_cpumode_count(he, al->cpumode, count); return he; @@ -137,7 +145,7 @@ void hist_entry__free(struct hist_entry *he) * collapse the histogram */ -static void collapse__insert_entry(struct rb_root *root, struct hist_entry *he) +static bool collapse__insert_entry(struct rb_root *root, struct hist_entry *he) { struct rb_node **p = &root->rb_node; struct rb_node *parent = NULL; @@ -153,7 +161,7 @@ static void collapse__insert_entry(struct rb_root *root, struct hist_entry *he) if (!cmp) { iter->count += he->count; hist_entry__free(he); - return; + return false; } if (cmp < 0) @@ -164,6 +172,7 @@ static void collapse__insert_entry(struct rb_root *root, struct hist_entry *he) rb_link_node(&he->rb_node, parent, p); rb_insert_color(&he->rb_node, root); + return true; } void hists__collapse_resort(struct hists *self) @@ -177,13 +186,16 @@ void hists__collapse_resort(struct hists *self) tmp = RB_ROOT; next = rb_first(&self->entries); + self->nr_entries = 0; + self->max_sym_namelen = 0; while (next) { n = rb_entry(next, struct hist_entry, rb_node); next = rb_next(&n->rb_node); rb_erase(&n->rb_node, &self->entries); - collapse__insert_entry(&tmp, n); + if (collapse__insert_entry(&tmp, n)) + hists__inc_nr_entries(self, n); } self->entries = tmp; @@ -219,30 +231,31 @@ static void __hists__insert_output_entry(struct rb_root *entries, rb_insert_color(&he->rb_node, entries); } -u64 hists__output_resort(struct hists *self) +void hists__output_resort(struct hists *self) { struct rb_root tmp; struct rb_node *next; struct hist_entry *n; u64 min_callchain_hits; - u64 nr_hists = 0; min_callchain_hits = self->stats.total * (callchain_param.min_percent / 100); tmp = RB_ROOT; next = rb_first(&self->entries); + self->nr_entries = 0; + self->max_sym_namelen = 0; + while (next) { n = rb_entry(next, struct hist_entry, rb_node); next = rb_next(&n->rb_node); rb_erase(&n->rb_node, &self->entries); __hists__insert_output_entry(&tmp, n, min_callchain_hits); - ++nr_hists; + hists__inc_nr_entries(self, n); } self->entries = tmp; - return nr_hists; } static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin) diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index bdde81e..1b18d04 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -19,10 +19,12 @@ struct events_stats { struct hists { struct rb_node rb_node; struct rb_root entries; + u64 nr_entries; struct events_stats stats; u64 config; u64 event_stream; u32 type; + u32 max_sym_namelen; }; struct hist_entry *__hists__add_entry(struct hists *self, @@ -38,7 +40,7 @@ int hist_entry__snprintf(struct hist_entry *self, char *bf, size_t size, long displacement, bool color, u64 total); void hist_entry__free(struct hist_entry *); -u64 hists__output_resort(struct hists *self); +void hists__output_resort(struct hists *self); void hists__collapse_resort(struct hists *self); size_t hists__fprintf(struct hists *self, struct hists *pair, bool show_displacement, FILE *fp); diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 994efdb..ecccc8d 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -130,8 +130,9 @@ static struct symbol *symbol__new(u64 start, u64 len, const char *name) if (symbol_conf.priv_size) self = ((void *)self) + symbol_conf.priv_size; - self->start = start; - self->end = len ? start + len - 1 : start; + self->start = start; + self->end = len ? start + len - 1 : start; + self->namelen = namelen - 1; pr_debug4("%s: %s %#Lx-%#Lx\n", __func__, name, start, self->end); diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index edff866..6389d1a 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -54,6 +54,7 @@ struct symbol { struct rb_node rb_node; u64 start; u64 end; + u16 namelen; char name[0]; }; -- cgit v0.10.2 From c3f5fd287aa897f710f3305367a1d256c9cf3e83 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Sun, 9 May 2010 23:46:52 -0500 Subject: perf/trace/scripting: failed-syscalls script cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A couple small fixes for the failed syscalls script: - The script description says it can be restricted to a specific comm, make it so. - silence the match output in the shell script Cc: Frédéric Weisbecker Cc: Ingo Molnar LKML-Reference: <1273466820-9330-2-git-send-email-tzanussi@gmail.com> Signed-off-by: Tom Zanussi Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/scripts/perl/bin/failed-syscalls-report b/tools/perf/scripts/perl/bin/failed-syscalls-report index f634608..e3a5e55 100644 --- a/tools/perf/scripts/perl/bin/failed-syscalls-report +++ b/tools/perf/scripts/perl/bin/failed-syscalls-report @@ -2,7 +2,7 @@ # description: system-wide failed syscalls # args: [comm] if [ $# -gt 0 ] ; then - if ! expr match "$1" "-" ; then + if ! expr match "$1" "-" > /dev/null ; then comm=$1 shift fi diff --git a/tools/perf/scripts/perl/failed-syscalls.pl b/tools/perf/scripts/perl/failed-syscalls.pl index c18e7e2..94bc25a 100644 --- a/tools/perf/scripts/perl/failed-syscalls.pl +++ b/tools/perf/scripts/perl/failed-syscalls.pl @@ -11,6 +11,8 @@ use Perf::Trace::Core; use Perf::Trace::Context; use Perf::Trace::Util; +my $for_comm = shift; + my %failed_syscalls; sub raw_syscalls::sys_exit @@ -33,6 +35,8 @@ sub trace_end foreach my $comm (sort {$failed_syscalls{$b} <=> $failed_syscalls{$a}} keys %failed_syscalls) { - printf("%-20s %10s\n", $comm, $failed_syscalls{$comm}); + next if ($for_comm && $comm ne $for_comm); + + printf("%-20s %10s\n", $comm, $failed_syscalls{$comm}); } } -- cgit v0.10.2 From 6922c3d772711239e75ddaea760e6b0535e7e7a6 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Sun, 9 May 2010 23:46:53 -0500 Subject: perf/trace/scripting: rw-by-pid script cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some minor fixes for the rw-by-pid script: - Fix nuisance 'use of uninitialized value' warnings - Change the failed read/write sections to sort by error counts Cc: Frédéric Weisbecker Cc: Ingo Molnar LKML-Reference: <1273466820-9330-3-git-send-email-tzanussi@gmail.com> Signed-off-by: Tom Zanussi Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/scripts/perl/rw-by-pid.pl b/tools/perf/scripts/perl/rw-by-pid.pl index da601fa..9db23c9 100644 --- a/tools/perf/scripts/perl/rw-by-pid.pl +++ b/tools/perf/scripts/perl/rw-by-pid.pl @@ -79,12 +79,12 @@ sub trace_end printf("%6s %-20s %10s %10s %10s\n", "------", "--------------------", "-----------", "----------", "----------"); - foreach my $pid (sort {$reads{$b}{bytes_read} <=> - $reads{$a}{bytes_read}} keys %reads) { - my $comm = $reads{$pid}{comm}; - my $total_reads = $reads{$pid}{total_reads}; - my $bytes_requested = $reads{$pid}{bytes_requested}; - my $bytes_read = $reads{$pid}{bytes_read}; + foreach my $pid (sort { ($reads{$b}{bytes_read} || 0) <=> + ($reads{$a}{bytes_read} || 0) } keys %reads) { + my $comm = $reads{$pid}{comm} || ""; + my $total_reads = $reads{$pid}{total_reads} || 0; + my $bytes_requested = $reads{$pid}{bytes_requested} || 0; + my $bytes_read = $reads{$pid}{bytes_read} || 0; printf("%6s %-20s %10s %10s %10s\n", $pid, $comm, $total_reads, $bytes_requested, $bytes_read); @@ -96,16 +96,23 @@ sub trace_end printf("%6s %20s %6s %10s\n", "------", "--------------------", "------", "----------"); - foreach my $pid (keys %reads) { - my $comm = $reads{$pid}{comm}; - foreach my $err (sort {$reads{$b}{comm} cmp $reads{$a}{comm}} - keys %{$reads{$pid}{errors}}) { - my $errors = $reads{$pid}{errors}{$err}; + my @errcounts = (); - printf("%6d %-20s %6d %10s\n", $pid, $comm, $err, $errors); + foreach my $pid (keys %reads) { + foreach my $error (keys %{$reads{$pid}{errors}}) { + my $comm = $reads{$pid}{comm} || ""; + my $errcount = $reads{$pid}{errors}{$error} || 0; + push @errcounts, [$pid, $comm, $error, $errcount]; } } + @errcounts = sort { $b->[3] <=> $a->[3] } @errcounts; + + for my $i (0 .. $#errcounts) { + printf("%6d %-20s %6d %10s\n", $errcounts[$i][0], + $errcounts[$i][1], $errcounts[$i][2], $errcounts[$i][3]); + } + printf("\nwrite counts by pid:\n\n"); printf("%6s %20s %10s %10s\n", "pid", "comm", @@ -113,11 +120,11 @@ sub trace_end printf("%6s %-20s %10s %10s\n", "------", "--------------------", "-----------", "----------"); - foreach my $pid (sort {$writes{$b}{bytes_written} <=> - $writes{$a}{bytes_written}} keys %writes) { - my $comm = $writes{$pid}{comm}; - my $total_writes = $writes{$pid}{total_writes}; - my $bytes_written = $writes{$pid}{bytes_written}; + foreach my $pid (sort { ($writes{$b}{bytes_written} || 0) <=> + ($writes{$a}{bytes_written} || 0)} keys %writes) { + my $comm = $writes{$pid}{comm} || ""; + my $total_writes = $writes{$pid}{total_writes} || 0; + my $bytes_written = $writes{$pid}{bytes_written} || 0; printf("%6s %-20s %10s %10s\n", $pid, $comm, $total_writes, $bytes_written); @@ -129,16 +136,23 @@ sub trace_end printf("%6s %20s %6s %10s\n", "------", "--------------------", "------", "----------"); - foreach my $pid (keys %writes) { - my $comm = $writes{$pid}{comm}; - foreach my $err (sort {$writes{$b}{comm} cmp $writes{$a}{comm}} - keys %{$writes{$pid}{errors}}) { - my $errors = $writes{$pid}{errors}{$err}; + @errcounts = (); - printf("%6d %-20s %6d %10s\n", $pid, $comm, $err, $errors); + foreach my $pid (keys %writes) { + foreach my $error (keys %{$writes{$pid}{errors}}) { + my $comm = $writes{$pid}{comm} || ""; + my $errcount = $writes{$pid}{errors}{$error} || 0; + push @errcounts, [$pid, $comm, $error, $errcount]; } } + @errcounts = sort { $b->[3] <=> $a->[3] } @errcounts; + + for my $i (0 .. $#errcounts) { + printf("%6d %-20s %6d %10s\n", $errcounts[$i][0], + $errcounts[$i][1], $errcounts[$i][2], $errcounts[$i][3]); + } + print_unhandled(); } -- cgit v0.10.2 From e88a4bfbcda440b1c6b9d5a31a554a6ad9686182 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Sun, 9 May 2010 23:46:54 -0500 Subject: perf/trace/scripting: rwtop script cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A couple of fixes for the rwtop script: - printing the totals and clearing the hashes in the signal handler eventually leads to various random and serious problems when running the rwtop script continuously. Moving the print_totals() calls to the event handlers solves that problem, and the event handlers are invoked frequently enough that it doesn't affect the timeliness of the output. - Fix nuisance 'use of uninitialized value' warnings Cc: Frédéric Weisbecker Cc: Ingo Molnar Message-Id: <1273466820-9330-4-git-send-email-tzanussi@gmail.com> Signed-off-by: Tom Zanussi Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/scripts/perl/rwtop.pl b/tools/perf/scripts/perl/rwtop.pl index ec2ab49..4bb3ecd 100644 --- a/tools/perf/scripts/perl/rwtop.pl +++ b/tools/perf/scripts/perl/rwtop.pl @@ -21,6 +21,7 @@ use Perf::Trace::Util; my $default_interval = 3; my $nlines = 20; my $print_thread; +my $print_pending = 0; my %reads; my %writes; @@ -36,6 +37,8 @@ sub syscalls::sys_exit_read $common_pid, $common_comm, $nr, $ret) = @_; + print_check(); + if ($ret > 0) { $reads{$common_pid}{bytes_read} += $ret; } else { @@ -52,6 +55,8 @@ sub syscalls::sys_enter_read $common_pid, $common_comm, $nr, $fd, $buf, $count) = @_; + print_check(); + $reads{$common_pid}{bytes_requested} += $count; $reads{$common_pid}{total_reads}++; $reads{$common_pid}{comm} = $common_comm; @@ -63,6 +68,8 @@ sub syscalls::sys_exit_write $common_pid, $common_comm, $nr, $ret) = @_; + print_check(); + if ($ret <= 0) { $writes{$common_pid}{errors}{$ret}++; } @@ -74,6 +81,8 @@ sub syscalls::sys_enter_write $common_pid, $common_comm, $nr, $fd, $buf, $count) = @_; + print_check(); + $writes{$common_pid}{bytes_written} += $count; $writes{$common_pid}{total_writes}++; $writes{$common_pid}{comm} = $common_comm; @@ -81,7 +90,7 @@ sub syscalls::sys_enter_write sub trace_begin { - $SIG{ALRM} = \&print_totals; + $SIG{ALRM} = \&set_print_pending; alarm 1; } @@ -91,6 +100,20 @@ sub trace_end print_totals(); } +sub print_check() +{ + if ($print_pending == 1) { + $print_pending = 0; + print_totals(); + } +} + +sub set_print_pending() +{ + $print_pending = 1; + alarm $interval; +} + sub print_totals { my $count; @@ -106,12 +129,12 @@ sub print_totals printf("%6s %-20s %10s %10s %10s\n", "------", "--------------------", "----------", "----------", "----------"); - foreach my $pid (sort {$reads{$b}{bytes_read} <=> - $reads{$a}{bytes_read}} keys %reads) { - my $comm = $reads{$pid}{comm}; - my $total_reads = $reads{$pid}{total_reads}; - my $bytes_requested = $reads{$pid}{bytes_requested}; - my $bytes_read = $reads{$pid}{bytes_read}; + foreach my $pid (sort { ($reads{$b}{bytes_read} || 0) <=> + ($reads{$a}{bytes_read} || 0) } keys %reads) { + my $comm = $reads{$pid}{comm} || ""; + my $total_reads = $reads{$pid}{total_reads} || 0; + my $bytes_requested = $reads{$pid}{bytes_requested} || 0; + my $bytes_read = $reads{$pid}{bytes_read} || 0; printf("%6s %-20s %10s %10s %10s\n", $pid, $comm, $total_reads, $bytes_requested, $bytes_read); @@ -130,11 +153,11 @@ sub print_totals printf("%6s %-20s %10s %13s\n", "------", "--------------------", "----------", "-------------"); - foreach my $pid (sort {$writes{$b}{bytes_written} <=> - $writes{$a}{bytes_written}} keys %writes) { - my $comm = $writes{$pid}{comm}; - my $total_writes = $writes{$pid}{total_writes}; - my $bytes_written = $writes{$pid}{bytes_written}; + foreach my $pid (sort { ($writes{$b}{bytes_written} || 0) <=> + ($writes{$a}{bytes_written} || 0)} keys %writes) { + my $comm = $writes{$pid}{comm} || ""; + my $total_writes = $writes{$pid}{total_writes} || 0; + my $bytes_written = $writes{$pid}{bytes_written} || 0; printf("%6s %-20s %10s %13s\n", $pid, $comm, $total_writes, $bytes_written); @@ -146,7 +169,6 @@ sub print_totals %reads = (); %writes = (); - alarm $interval; } my %unhandled; -- cgit v0.10.2 From e366728d57cb8c708f76b282ae194c6044355b5f Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Sun, 9 May 2010 23:46:55 -0500 Subject: perf/trace/scripting: wakeup-latency script cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some minor fixes for the wakeup-latency script: - Fix nuisance 'use of uninitialized value' warnings - Avoid divide-by-zero error Cc: Frédéric Weisbecker Cc: Ingo Molnar LKML-Reference: <1273466820-9330-5-git-send-email-tzanussi@gmail.com> Signed-off-by: Tom Zanussi Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/scripts/perl/wakeup-latency.pl b/tools/perf/scripts/perl/wakeup-latency.pl index ed58ef2..d9143dc 100644 --- a/tools/perf/scripts/perl/wakeup-latency.pl +++ b/tools/perf/scripts/perl/wakeup-latency.pl @@ -22,8 +22,8 @@ my %last_wakeup; my $max_wakeup_latency; my $min_wakeup_latency; -my $total_wakeup_latency; -my $total_wakeups; +my $total_wakeup_latency = 0; +my $total_wakeups = 0; sub sched::sched_switch { @@ -67,8 +67,12 @@ sub trace_end { printf("wakeup_latency stats:\n\n"); print "total_wakeups: $total_wakeups\n"; - printf("avg_wakeup_latency (ns): %u\n", - avg($total_wakeup_latency, $total_wakeups)); + if ($total_wakeups) { + printf("avg_wakeup_latency (ns): %u\n", + avg($total_wakeup_latency, $total_wakeups)); + } else { + printf("avg_wakeup_latency (ns): N/A\n"); + } printf("min_wakeup_latency (ns): %u\n", $min_wakeup_latency); printf("max_wakeup_latency (ns): %u\n", $max_wakeup_latency); -- cgit v0.10.2 From a3412d9b358d37fce4527fd67ea601635f2b9496 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Sun, 9 May 2010 23:46:56 -0500 Subject: perf/trace/scripting: workqueue-stats script cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some minor fixes for the workqueue-stats script: - Fix nuisance 'use of uninitialized value' warnings Cc: Frédéric Weisbecker Cc: Ingo Molnar LKML-Reference: <1273466820-9330-6-git-send-email-tzanussi@gmail.com> Signed-off-by: Tom Zanussi Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/scripts/perl/workqueue-stats.pl b/tools/perf/scripts/perl/workqueue-stats.pl index 511302c..b84b126 100644 --- a/tools/perf/scripts/perl/workqueue-stats.pl +++ b/tools/perf/scripts/perl/workqueue-stats.pl @@ -71,9 +71,9 @@ sub trace_end printf("%3s %6s %6s\t%-20s\n", "---", "---", "----", "----"); foreach my $pidhash (@cpus) { while ((my $pid, my $wqhash) = each %$pidhash) { - my $ins = $$wqhash{'inserted'}; - my $exe = $$wqhash{'executed'}; - my $comm = $$wqhash{'comm'}; + my $ins = $$wqhash{'inserted'} || 0; + my $exe = $$wqhash{'executed'} || 0; + my $comm = $$wqhash{'comm'} || ""; if ($ins || $exe) { printf("%3u %6u %6u\t%-20s\n", $cpu, $ins, $exe, $comm); } @@ -87,9 +87,9 @@ sub trace_end printf("%3s %6s %6s\t%-20s\n", "---", "-------", "---------", "----"); foreach my $pidhash (@cpus) { while ((my $pid, my $wqhash) = each %$pidhash) { - my $created = $$wqhash{'created'}; - my $destroyed = $$wqhash{'destroyed'}; - my $comm = $$wqhash{'comm'}; + my $created = $$wqhash{'created'} || 0; + my $destroyed = $$wqhash{'destroyed'} || 0; + my $comm = $$wqhash{'comm'} || ""; if ($created || $destroyed) { printf("%3u %6u %6u\t%-20s\n", $cpu, $created, $destroyed, $comm); -- cgit v0.10.2 From 3824a4e8da9791f4eed99d69bfcdb3b42f440426 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Sun, 9 May 2010 23:46:57 -0500 Subject: perf/trace/scripting: don't show script start/stop messages by default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only print the script start/stop messages in verbose mode - users normally don't care and it just clutters up the output. Cc: Frédéric Weisbecker Cc: Ingo Molnar LKML-Reference: <1273466820-9330-7-git-send-email-tzanussi@gmail.com> Signed-off-by: Tom Zanussi Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 6e268ca..95fcb05 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -53,6 +53,8 @@ static void setup_scripting(void) static int cleanup_scripting(void) { + pr_debug("\nperf trace script stopped\n"); + return scripting_ops->stop_script(); } @@ -703,6 +705,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used) err = scripting_ops->start_script(script_name, argc, argv); if (err) goto out; + pr_debug("perf trace started with script %s\n\n", script_name); } err = __cmd_trace(session); diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index 5376378..b059dc5 100644 --- a/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/tools/perf/util/scripting-engines/trace-event-perl.c @@ -371,7 +371,6 @@ static int perl_start_script(const char *script, int argc, const char **argv) run_start_sub(); free(command_line); - fprintf(stderr, "perf trace started with Perl script %s\n\n", script); return 0; error: perl_free(my_perl); @@ -394,8 +393,6 @@ static int perl_stop_script(void) perl_destruct(my_perl); perl_free(my_perl); - fprintf(stderr, "\nperf trace Perl script stopped\n"); - return 0; } diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 6a72f14..81f39ca 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -374,8 +374,6 @@ static int python_start_script(const char *script, int argc, const char **argv) } free(command_line); - fprintf(stderr, "perf trace started with Python script %s\n\n", - script); return err; error: @@ -407,8 +405,6 @@ out: Py_XDECREF(main_module); Py_Finalize(); - fprintf(stderr, "\nperf trace Python script stopped\n"); - return err; } -- cgit v0.10.2 From a4ab0c12975d1286b2696370f5e0576450609bf0 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Sun, 9 May 2010 23:46:58 -0500 Subject: perf/trace/scripting: failed-syscalls-by-pid script cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A small fixe for the failed syscalls by pid script: - silence the match output in the shell script Cc: Frédéric Weisbecker Cc: Ingo Molnar LKML-Reference: <1273466820-9330-8-git-send-email-tzanussi@gmail.com> Signed-off-by: Tom Zanussi Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/scripts/python/bin/failed-syscalls-by-pid-report b/tools/perf/scripts/python/bin/failed-syscalls-by-pid-report index 8c128ef..3029354 100644 --- a/tools/perf/scripts/python/bin/failed-syscalls-by-pid-report +++ b/tools/perf/scripts/python/bin/failed-syscalls-by-pid-report @@ -2,7 +2,7 @@ # description: system-wide failed syscalls, by pid # args: [comm] if [ $# -gt 0 ] ; then - if ! expr match "$1" "-" ; then + if ! expr match "$1" "-" > /dev/null ; then comm=$1 shift fi -- cgit v0.10.2 From 79e653f1bf2e52d12a952366e782dadf590b9d1d Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Sun, 9 May 2010 23:46:59 -0500 Subject: perf/trace/scripting: syscall-counts-by-pid script cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A small fix for the syscall counts by pid script: - silence the match output in the shell script Cc: Frédéric Weisbecker Cc: Ingo Molnar LKML-Reference: <1273466820-9330-9-git-send-email-tzanussi@gmail.com> Signed-off-by: Tom Zanussi Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/scripts/python/bin/syscall-counts-by-pid-report b/tools/perf/scripts/python/bin/syscall-counts-by-pid-report index c53362e..9e9d8dd 100644 --- a/tools/perf/scripts/python/bin/syscall-counts-by-pid-report +++ b/tools/perf/scripts/python/bin/syscall-counts-by-pid-report @@ -2,7 +2,7 @@ # description: system-wide syscall counts, by pid # args: [comm] if [ $# -gt 0 ] ; then - if ! expr match "$1" "-" ; then + if ! expr match "$1" "-" > /dev/null ; then comm=$1 shift fi -- cgit v0.10.2 From e61a639a794063d78fd248a37ce2c21d5c81fc19 Mon Sep 17 00:00:00 2001 From: Tom Zanussi Date: Sun, 9 May 2010 23:47:00 -0500 Subject: perf/trace/scripting: syscall-counts script cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A small fix for the syscall counts script: - silence the match output in the shell script Cc: Frédéric Weisbecker Cc: Ingo Molnar LKML-Reference: <1273466820-9330-10-git-send-email-tzanussi@gmail.com> Signed-off-by: Tom Zanussi Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/scripts/python/bin/syscall-counts-report b/tools/perf/scripts/python/bin/syscall-counts-report index 8c21552..dc076b6 100644 --- a/tools/perf/scripts/python/bin/syscall-counts-report +++ b/tools/perf/scripts/python/bin/syscall-counts-report @@ -2,7 +2,7 @@ # description: system-wide syscall counts # args: [comm] if [ $# -gt 0 ] ; then - if ! expr match "$1" "-" ; then + if ! expr match "$1" "-" > /dev/null ; then comm=$1 shift fi -- cgit v0.10.2 From a5d8e467f83f6672104f276223a88e3b50cbd375 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Sat, 17 Apr 2010 08:48:38 -0400 Subject: Debugobjects transition check Implement a basic state machine checker in the debugobjects. This state machine checker detects races and inconsistencies within the "active" life of a debugobject. The checker only keeps track of the current state; all the state machine logic is kept at the object instance level. The checker works by adding a supplementary "unsigned int astate" field to the debug_obj structure. It keeps track of the current "active state" of the object. The only constraints that are imposed on the states by the debugobjects system is that: - activation of an object sets the current active state to 0, - deactivation of an object expects the current active state to be 0. For the rest of the states, the state mapping is determined by the specific object instance. Therefore, the logic keeping track of the state machine is within the specialized instance, without any need to know about it at the debugobject level. The current object active state is changed by calling: debug_object_active_state(addr, descr, expect, next) where "expect" is the expected state and "next" is the next state to move to if the expected state is found. A warning is generated if the expected is not found. Signed-off-by: Mathieu Desnoyers Reviewed-by: Thomas Gleixner Acked-by: David S. Miller CC: "Paul E. McKenney" CC: akpm@linux-foundation.org CC: mingo@elte.hu CC: laijs@cn.fujitsu.com CC: dipankar@in.ibm.com CC: josh@joshtriplett.org CC: dvhltc@us.ibm.com CC: niv@us.ibm.com CC: peterz@infradead.org CC: rostedt@goodmis.org CC: Valdis.Kletnieks@vt.edu CC: dhowells@redhat.com CC: eric.dumazet@gmail.com CC: Alexey Dobriyan Signed-off-by: Paul E. McKenney diff --git a/include/linux/debugobjects.h b/include/linux/debugobjects.h index 8c243aa..597692f 100644 --- a/include/linux/debugobjects.h +++ b/include/linux/debugobjects.h @@ -20,12 +20,14 @@ struct debug_obj_descr; * struct debug_obj - representaion of an tracked object * @node: hlist node to link the object into the tracker list * @state: tracked object state + * @astate: current active state * @object: pointer to the real object * @descr: pointer to an object type specific debug description structure */ struct debug_obj { struct hlist_node node; enum debug_obj_state state; + unsigned int astate; void *object; struct debug_obj_descr *descr; }; @@ -60,6 +62,15 @@ extern void debug_object_deactivate(void *addr, struct debug_obj_descr *descr); extern void debug_object_destroy (void *addr, struct debug_obj_descr *descr); extern void debug_object_free (void *addr, struct debug_obj_descr *descr); +/* + * Active state: + * - Set at 0 upon initialization. + * - Must return to 0 before deactivation. + */ +extern void +debug_object_active_state(void *addr, struct debug_obj_descr *descr, + unsigned int expect, unsigned int next); + extern void debug_objects_early_init(void); extern void debug_objects_mem_init(void); #else diff --git a/lib/debugobjects.c b/lib/debugobjects.c index b862b30..076464f 100644 --- a/lib/debugobjects.c +++ b/lib/debugobjects.c @@ -141,6 +141,7 @@ alloc_object(void *addr, struct debug_bucket *b, struct debug_obj_descr *descr) obj->object = addr; obj->descr = descr; obj->state = ODEBUG_STATE_NONE; + obj->astate = 0; hlist_del(&obj->node); hlist_add_head(&obj->node, &b->list); @@ -252,8 +253,10 @@ static void debug_print_object(struct debug_obj *obj, char *msg) if (limit < 5 && obj->descr != descr_test) { limit++; - WARN(1, KERN_ERR "ODEBUG: %s %s object type: %s\n", msg, - obj_states[obj->state], obj->descr->name); + WARN(1, KERN_ERR "ODEBUG: %s %s (active state %u) " + "object type: %s\n", + msg, obj_states[obj->state], obj->astate, + obj->descr->name); } debug_objects_warnings++; } @@ -447,7 +450,10 @@ void debug_object_deactivate(void *addr, struct debug_obj_descr *descr) case ODEBUG_STATE_INIT: case ODEBUG_STATE_INACTIVE: case ODEBUG_STATE_ACTIVE: - obj->state = ODEBUG_STATE_INACTIVE; + if (!obj->astate) + obj->state = ODEBUG_STATE_INACTIVE; + else + debug_print_object(obj, "deactivate"); break; case ODEBUG_STATE_DESTROYED: @@ -553,6 +559,53 @@ out_unlock: raw_spin_unlock_irqrestore(&db->lock, flags); } +/** + * debug_object_active_state - debug checks object usage state machine + * @addr: address of the object + * @descr: pointer to an object specific debug description structure + * @expect: expected state + * @next: state to move to if expected state is found + */ +void +debug_object_active_state(void *addr, struct debug_obj_descr *descr, + unsigned int expect, unsigned int next) +{ + struct debug_bucket *db; + struct debug_obj *obj; + unsigned long flags; + + if (!debug_objects_enabled) + return; + + db = get_bucket((unsigned long) addr); + + raw_spin_lock_irqsave(&db->lock, flags); + + obj = lookup_object(addr, db); + if (obj) { + switch (obj->state) { + case ODEBUG_STATE_ACTIVE: + if (obj->astate == expect) + obj->astate = next; + else + debug_print_object(obj, "active_state"); + break; + + default: + debug_print_object(obj, "active_state"); + break; + } + } else { + struct debug_obj o = { .object = addr, + .state = ODEBUG_STATE_NOTAVAILABLE, + .descr = descr }; + + debug_print_object(&o, "active_state"); + } + + raw_spin_unlock_irqrestore(&db->lock, flags); +} + #ifdef CONFIG_DEBUG_OBJECTS_FREE static void __debug_check_no_obj_freed(const void *address, unsigned long size) { -- cgit v0.10.2 From 4376030a54860dedab9d848dfa7cc700a6025c0b Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Sat, 17 Apr 2010 08:48:39 -0400 Subject: rcu head introduce rcu head init on stack PEM: o Would it be possible to make this bisectable as follows? a. Insert a new patch after current patch 4/6 that defines destroy_rcu_head_on_stack(), init_rcu_head_on_stack(), and init_rcu_head() with their !CONFIG_DEBUG_OBJECTS_RCU_HEAD definitions. This patch performs this transition. Signed-off-by: Mathieu Desnoyers CC: "Paul E. McKenney" CC: David S. Miller CC: akpm@linux-foundation.org CC: mingo@elte.hu CC: laijs@cn.fujitsu.com CC: dipankar@in.ibm.com CC: josh@joshtriplett.org CC: dvhltc@us.ibm.com CC: niv@us.ibm.com CC: tglx@linutronix.de CC: peterz@infradead.org CC: rostedt@goodmis.org CC: Valdis.Kletnieks@vt.edu CC: dhowells@redhat.com CC: eric.dumazet@gmail.com CC: Alexey Dobriyan Signed-off-by: Paul E. McKenney diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 23be3a702..b653b4a 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -79,6 +79,14 @@ extern void rcu_init(void); (ptr)->next = NULL; (ptr)->func = NULL; \ } while (0) +static inline void init_rcu_head_on_stack(struct rcu_head *head) +{ +} + +static inline void destroy_rcu_head_on_stack(struct rcu_head *head) +{ +} + #ifdef CONFIG_DEBUG_LOCK_ALLOC extern struct lockdep_map rcu_lock_map; -- cgit v0.10.2 From 474b62f573360947e2740458bde3778d420e1b40 Mon Sep 17 00:00:00 2001 From: Jongpill Lee Date: Fri, 19 Mar 2010 15:33:12 +0900 Subject: ARM: S5P6440: Bug fix on PWM Timer This patch fixes return value in below functions - pwm_cfg_src_is_tclk - tcfg_to_divisor - pwm_tdiv_has_div1 - pwm_tdiv_div_bits And this patch changes Copyright ordering, and addes 'based on' information. Signed-off-by: Jongpill Lee Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5p6440/include/mach/pwm-clock.h b/arch/arm/mach-s5p6440/include/mach/pwm-clock.h index c4bb7c5..6a2a02f 100644 --- a/arch/arm/mach-s5p6440/include/mach/pwm-clock.h +++ b/arch/arm/mach-s5p6440/include/mach/pwm-clock.h @@ -1,11 +1,14 @@ /* linux/arch/arm/mach-s5p6440/include/mach/pwm-clock.h * + * Copyright (c) 2009 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Copyright 2008 Openmoko, Inc. * Copyright 2008 Simtec Electronics * Ben Dooks * http://armlinux.simtec.co.uk/ * - * Copyright 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ + * Based on arch/arm/mach-s3c64xx/include/mach/pwm-clock.h * * S5P6440 - pwm clock and timer support * @@ -14,16 +17,19 @@ * published by the Free Software Foundation. */ +#ifndef __ASM_ARCH_PWMCLK_H +#define __ASM_ARCH_PWMCLK_H __FILE__ + /** * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk - * @cfg: The timer TCFG1 register bits shifted down to 0. + * @tcfg: The timer TCFG1 register bits shifted down to 0. * * Return true if the given configuration from TCFG1 is a TCLK instead * any of the TDIV clocks. */ static inline int pwm_cfg_src_is_tclk(unsigned long tcfg) { - return tcfg == S3C2410_TCFG1_MUX_TCLK; + return 0; } /** @@ -35,7 +41,7 @@ static inline int pwm_cfg_src_is_tclk(unsigned long tcfg) */ static inline unsigned long tcfg_to_divisor(unsigned long tcfg1) { - return 1 << (1 + tcfg1); + return 1 << tcfg1; } /** @@ -45,7 +51,7 @@ static inline unsigned long tcfg_to_divisor(unsigned long tcfg1) */ static inline unsigned int pwm_tdiv_has_div1(void) { - return 0; + return 1; } /** @@ -56,7 +62,9 @@ static inline unsigned int pwm_tdiv_has_div1(void) */ static inline unsigned long pwm_tdiv_div_bits(unsigned int div) { - return ilog2(div) - 1; + return ilog2(div); } -#define S3C_TCFG1_MUX_TCLK S3C2410_TCFG1_MUX_TCLK +#define S3C_TCFG1_MUX_TCLK 0 + +#endif /* __ASM_ARCH_PWMCLK_H */ -- cgit v0.10.2 From dcd897dba163e746cd98d8290c5a18dc47157c64 Mon Sep 17 00:00:00 2001 From: Jongpill Lee Date: Fri, 19 Mar 2010 15:33:22 +0900 Subject: ARM: S5P6442: Bug fix on PWM Timer This patch fixes return value in below functions - pwm_cfg_src_is_tclk - tcfg_to_divisor - pwm_tdiv_has_div1 - pwm_tdiv_div_bits And this patch changes Copyright ordering. Signed-off-by: Jongpill Lee Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5p6442/include/mach/pwm-clock.h b/arch/arm/mach-s5p6442/include/mach/pwm-clock.h index 15e8525..2724b37 100644 --- a/arch/arm/mach-s5p6442/include/mach/pwm-clock.h +++ b/arch/arm/mach-s5p6442/include/mach/pwm-clock.h @@ -1,13 +1,14 @@ /* linux/arch/arm/mach-s5p6442/include/mach/pwm-clock.h * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Copyright 2008 Openmoko, Inc. * Copyright 2008 Simtec Electronics * Ben Dooks * http://armlinux.simtec.co.uk/ * - * Copyright 2010 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * Based on arch/arm/plat-s3c24xx/include/mach/pwm-clock.h + * Based on arch/arm/mach-s3c64xx/include/mach/pwm-clock.h * * S5P6442 - pwm clock and timer support * @@ -21,14 +22,14 @@ /** * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk - * @cfg: The timer TCFG1 register bits shifted down to 0. + * @tcfg: The timer TCFG1 register bits shifted down to 0. * * Return true if the given configuration from TCFG1 is a TCLK instead * any of the TDIV clocks. */ static inline int pwm_cfg_src_is_tclk(unsigned long tcfg) { - return tcfg == S3C2410_TCFG1_MUX_TCLK; + return tcfg == S3C64XX_TCFG1_MUX_TCLK; } /** @@ -40,7 +41,7 @@ static inline int pwm_cfg_src_is_tclk(unsigned long tcfg) */ static inline unsigned long tcfg_to_divisor(unsigned long tcfg1) { - return 1 << (1 + tcfg1); + return 1 << tcfg1; } /** @@ -50,7 +51,7 @@ static inline unsigned long tcfg_to_divisor(unsigned long tcfg1) */ static inline unsigned int pwm_tdiv_has_div1(void) { - return 0; + return 1; } /** @@ -61,9 +62,9 @@ static inline unsigned int pwm_tdiv_has_div1(void) */ static inline unsigned long pwm_tdiv_div_bits(unsigned int div) { - return ilog2(div) - 1; + return ilog2(div); } -#define S3C_TCFG1_MUX_TCLK S3C2410_TCFG1_MUX_TCLK +#define S3C_TCFG1_MUX_TCLK S3C64XX_TCFG1_MUX_TCLK #endif /* __ASM_ARCH_PWMCLK_H */ -- cgit v0.10.2 From b78232da3f85950a207bbcb64db46fd95b581465 Mon Sep 17 00:00:00 2001 From: Jongpill Lee Date: Fri, 19 Mar 2010 15:33:31 +0900 Subject: ARM: S5PV210: Bug fix on PWM Timer This patch fixes return value in below functions - pwm_cfg_src_is_tclk - tcfg_to_divisor - pwm_tdiv_has_div1 - pwm_tdiv_div_bits And this patch changes Copyright ordering. Signed-off-by: Jongpill Lee Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5pv210/include/mach/pwm-clock.h b/arch/arm/mach-s5pv210/include/mach/pwm-clock.h index 69027fe..f8a9f1b 100644 --- a/arch/arm/mach-s5pv210/include/mach/pwm-clock.h +++ b/arch/arm/mach-s5pv210/include/mach/pwm-clock.h @@ -1,13 +1,14 @@ /* linux/arch/arm/mach-s5pv210/include/mach/pwm-clock.h * + * Copyright (c) 2009 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Copyright 2008 Openmoko, Inc. * Copyright 2008 Simtec Electronics * Ben Dooks * http://armlinux.simtec.co.uk/ * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * Based on arch/arm/plat-s3c24xx/include/mach/pwm-clock.h + * Based on arch/arm/mach-s3c64xx/include/mach/pwm-clock.h * * S5PV210 - pwm clock and timer support * @@ -21,14 +22,14 @@ /** * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk - * @cfg: The timer TCFG1 register bits shifted down to 0. + * @tcfg: The timer TCFG1 register bits shifted down to 0. * * Return true if the given configuration from TCFG1 is a TCLK instead * any of the TDIV clocks. */ static inline int pwm_cfg_src_is_tclk(unsigned long tcfg) { - return tcfg == S3C2410_TCFG1_MUX_TCLK; + return tcfg == S3C64XX_TCFG1_MUX_TCLK; } /** @@ -40,7 +41,7 @@ static inline int pwm_cfg_src_is_tclk(unsigned long tcfg) */ static inline unsigned long tcfg_to_divisor(unsigned long tcfg1) { - return 1 << (1 + tcfg1); + return 1 << tcfg1; } /** @@ -50,7 +51,7 @@ static inline unsigned long tcfg_to_divisor(unsigned long tcfg1) */ static inline unsigned int pwm_tdiv_has_div1(void) { - return 0; + return 1; } /** @@ -61,9 +62,9 @@ static inline unsigned int pwm_tdiv_has_div1(void) */ static inline unsigned long pwm_tdiv_div_bits(unsigned int div) { - return ilog2(div) - 1; + return ilog2(div); } -#define S3C_TCFG1_MUX_TCLK S3C2410_TCFG1_MUX_TCLK +#define S3C_TCFG1_MUX_TCLK S3C64XX_TCFG1_MUX_TCLK #endif /* __ASM_ARCH_PWMCLK_H */ -- cgit v0.10.2 From f001d5b28bc583c85281a9ce315ac16970201eae Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Mon, 19 Apr 2010 20:05:08 +0900 Subject: ARM: S5P: Add USB External Crystal clock definition Add USB external crystal clock definition Xusbxti to common S5P clock code. Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/plat-s5p/clock.c b/arch/arm/plat-s5p/clock.c index aa96e33..3fef951 100644 --- a/arch/arm/plat-s5p/clock.c +++ b/arch/arm/plat-s5p/clock.c @@ -33,6 +33,11 @@ struct clk clk_ext_xtal_mux = { .id = -1, }; +struct clk clk_xusbxti = { + .name = "xusbxti", + .id = -1, +}; + static struct clk s5p_clk_27m = { .name = "clk_27m", .id = -1, diff --git a/arch/arm/plat-s5p/include/plat/s5p-clock.h b/arch/arm/plat-s5p/include/plat/s5p-clock.h index 56fb8b4..a476a9f 100644 --- a/arch/arm/plat-s5p/include/plat/s5p-clock.h +++ b/arch/arm/plat-s5p/include/plat/s5p-clock.h @@ -23,6 +23,7 @@ #define clk_fin_vpll clk_ext_xtal_mux extern struct clk clk_ext_xtal_mux; +extern struct clk clk_xusbxti; extern struct clk clk_48m; extern struct clk clk_fout_apll; extern struct clk clk_fout_mpll; -- cgit v0.10.2 From f3d51e13fea901729fef15bf1c32ca004d45476e Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Mon, 10 May 2010 14:01:02 +0000 Subject: sh: hwblk index rework Rework the sh7722/sh7723/sh7724 hwblk code to use the hwblk id as index in the mstp clock array. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/include/asm/hwblk.h b/arch/sh/include/asm/hwblk.h index 5d3ccae..4984d29 100644 --- a/arch/sh/include/asm/hwblk.h +++ b/arch/sh/include/asm/hwblk.h @@ -59,7 +59,7 @@ void hwblk_cnt_dec(struct hwblk_info *info, int hwblk, int cnt); /* allow clocks to enable and disable hardware blocks */ #define SH_HWBLK_CLK(_name, _id, _parent, _hwblk, _flags) \ -{ \ +[_hwblk] = { \ .name = _name, \ .id = _id, \ .parent = _parent, \ diff --git a/arch/sh/kernel/cpu/hwblk.c b/arch/sh/kernel/cpu/hwblk.c index 67a1e81..3e985aa 100644 --- a/arch/sh/kernel/cpu/hwblk.c +++ b/arch/sh/kernel/cpu/hwblk.c @@ -146,6 +146,11 @@ int __init sh_hwblk_clk_register(struct clk *clks, int nr) for (k = 0; !ret && (k < nr); k++) { clkp = clks + k; + + /* skip over clocks using hwblk 0 (HWBLK_UNKNOWN) */ + if (!clkp->arch_flags) + continue; + clkp->ops = &sh_hwblk_clk_ops; ret |= clk_register(clkp); } diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c index 107b200..e5b6f47 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c @@ -157,7 +157,7 @@ struct clk div6_clks[] = { #define B_CLK &div4_clks[DIV4_B] #define U_CLK &div4_clks[DIV4_U] -static struct clk mstp_clks[] = { +static struct clk mstp_clks[HWBLK_NR] = { SH_HWBLK_CLK("uram0", -1, U_CLK, HWBLK_URAM, CLK_ENABLE_ON_INIT), SH_HWBLK_CLK("xymem0", -1, B_CLK, HWBLK_XYMEM, CLK_ENABLE_ON_INIT), SH_HWBLK_CLK("tmu_fck", -1, P_CLK, HWBLK_TMU, 0), @@ -213,7 +213,7 @@ int __init arch_clk_init(void) ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks)); if (!ret) - ret = sh_hwblk_clk_register(mstp_clks, ARRAY_SIZE(mstp_clks)); + ret = sh_hwblk_clk_register(mstp_clks, HWBLK_NR); return ret; } diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c index fc86c88..390bdb5 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c @@ -218,32 +218,32 @@ static struct clk_lookup lookups[] = { /* TMU0 */ .dev_id = "sh_tmu.0", .con_id = "tmu_fck", - .clk = &mstp_clks[11], /* tmu012_fck */ + .clk = &mstp_clks[HWBLK_TMU0], }, { /* TMU1 */ .dev_id = "sh_tmu.1", .con_id = "tmu_fck", - .clk = &mstp_clks[11], + .clk = &mstp_clks[HWBLK_TMU0], }, { /* TMU2 */ .dev_id = "sh_tmu.2", .con_id = "tmu_fck", - .clk = &mstp_clks[11], + .clk = &mstp_clks[HWBLK_TMU0], }, { /* TMU3 */ .dev_id = "sh_tmu.3", .con_id = "tmu_fck", - .clk = &mstp_clks[15], /* tmu345_fck */ + .clk = &mstp_clks[HWBLK_TMU1], }, { /* TMU4 */ .dev_id = "sh_tmu.4", .con_id = "tmu_fck", - .clk = &mstp_clks[15], + .clk = &mstp_clks[HWBLK_TMU1], }, { /* TMU5 */ .dev_id = "sh_tmu.5", .con_id = "tmu_fck", - .clk = &mstp_clks[15], + .clk = &mstp_clks[HWBLK_TMU1], }, }; @@ -277,7 +277,7 @@ int __init arch_clk_init(void) ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks)); if (!ret) - ret = sh_hwblk_clk_register(mstp_clks, ARRAY_SIZE(mstp_clks)); + ret = sh_hwblk_clk_register(mstp_clks, HWBLK_NR); return ret; } diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c index f1583a2..c5d4891 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c @@ -178,7 +178,7 @@ struct clk div6_clks[] = { #define I_CLK (&div4_clks[DIV4_I]) #define SH_CLK (&div4_clks[DIV4_SH]) -static struct clk mstp_clks[] = { +static struct clk mstp_clks[HWBLK_NR] = { SH_HWBLK_CLK("tlb0", -1, I_CLK, HWBLK_TLB, CLK_ENABLE_ON_INIT), SH_HWBLK_CLK("ic0", -1, I_CLK, HWBLK_IC, CLK_ENABLE_ON_INIT), SH_HWBLK_CLK("oc0", -1, I_CLK, HWBLK_OC, CLK_ENABLE_ON_INIT), @@ -240,32 +240,32 @@ static struct clk_lookup lookups[] = { /* TMU0 */ .dev_id = "sh_tmu.0", .con_id = "tmu_fck", - .clk = &mstp_clks[12], /* tmu012_fck */ + .clk = &mstp_clks[HWBLK_TMU0], }, { /* TMU1 */ .dev_id = "sh_tmu.1", .con_id = "tmu_fck", - .clk = &mstp_clks[12], + .clk = &mstp_clks[HWBLK_TMU0], }, { /* TMU2 */ .dev_id = "sh_tmu.2", .con_id = "tmu_fck", - .clk = &mstp_clks[12], + .clk = &mstp_clks[HWBLK_TMU0], }, { /* TMU3 */ .dev_id = "sh_tmu.3", .con_id = "tmu_fck", - .clk = &mstp_clks[16], /* tmu345_fck */ + .clk = &mstp_clks[HWBLK_TMU1], }, { /* TMU4 */ .dev_id = "sh_tmu.4", .con_id = "tmu_fck", - .clk = &mstp_clks[16], + .clk = &mstp_clks[HWBLK_TMU1], }, { /* TMU5 */ .dev_id = "sh_tmu.5", .con_id = "tmu_fck", - .clk = &mstp_clks[16], + .clk = &mstp_clks[HWBLK_TMU1], }, }; @@ -291,7 +291,7 @@ int __init arch_clk_init(void) ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks)); if (!ret) - ret = sh_hwblk_clk_register(mstp_clks, ARRAY_SIZE(mstp_clks)); + ret = sh_hwblk_clk_register(mstp_clks, HWBLK_NR); return ret; } -- cgit v0.10.2 From e4e06697977bf6731d940ab1bd84e16cb53c3ae3 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Mon, 10 May 2010 14:01:12 +0000 Subject: sh: scif and tmu clkdev changes Modify sh7722/sh7723/sh7724 to use clkdev for TMU and SCIF clock lookups. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c index e5b6f47..ed57c63 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -164,9 +165,9 @@ static struct clk mstp_clks[HWBLK_NR] = { SH_HWBLK_CLK("cmt_fck", -1, R_CLK, HWBLK_CMT, 0), SH_HWBLK_CLK("rwdt0", -1, R_CLK, HWBLK_RWDT, 0), SH_HWBLK_CLK("flctl0", -1, P_CLK, HWBLK_FLCTL, 0), - SH_HWBLK_CLK("sci_fck", 0, P_CLK, HWBLK_SCIF0, 0), - SH_HWBLK_CLK("sci_fck", 1, P_CLK, HWBLK_SCIF1, 0), - SH_HWBLK_CLK("sci_fck", 2, P_CLK, HWBLK_SCIF2, 0), + SH_HWBLK_CLK("sci_fck", -1, P_CLK, HWBLK_SCIF0, 0), + SH_HWBLK_CLK("sci_fck", -1, P_CLK, HWBLK_SCIF1, 0), + SH_HWBLK_CLK("sci_fck", -1, P_CLK, HWBLK_SCIF2, 0), SH_HWBLK_CLK("i2c0", -1, P_CLK, HWBLK_IIC, 0), SH_HWBLK_CLK("rtc0", -1, R_CLK, HWBLK_RTC, 0), @@ -185,6 +186,40 @@ static struct clk mstp_clks[HWBLK_NR] = { SH_HWBLK_CLK("lcdc0", -1, P_CLK, HWBLK_LCDC, 0), }; +static struct clk_lookup lookups[] = { + { + /* TMU0 */ + .dev_id = "sh_tmu.0", + .con_id = "tmu_fck", + .clk = &mstp_clks[HWBLK_TMU], + }, { + /* TMU1 */ + .dev_id = "sh_tmu.1", + .con_id = "tmu_fck", + .clk = &mstp_clks[HWBLK_TMU], + }, { + /* TMU2 */ + .dev_id = "sh_tmu.2", + .con_id = "tmu_fck", + .clk = &mstp_clks[HWBLK_TMU], + }, { + /* SCIF0 */ + .dev_id = "sh-sci.0", + .con_id = "sci_fck", + .clk = &mstp_clks[HWBLK_SCIF0], + }, { + /* SCIF1 */ + .dev_id = "sh-sci.1", + .con_id = "sci_fck", + .clk = &mstp_clks[HWBLK_SCIF1], + }, { + /* SCIF2 */ + .dev_id = "sh-sci.2", + .con_id = "sci_fck", + .clk = &mstp_clks[HWBLK_SCIF2], + }, +}; + int __init arch_clk_init(void) { int k, ret = 0; @@ -198,6 +233,8 @@ int __init arch_clk_init(void) for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++) ret = clk_register(main_clks[k]); + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); + if (!ret) ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table); diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c index 390bdb5..d92d7cd 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c @@ -179,12 +179,12 @@ static struct clk mstp_clks[] = { SH_HWBLK_CLK("dmac1", -1, B_CLK, HWBLK_DMAC1, 0), SH_HWBLK_CLK("tmu345_fck", -1, P_CLK, HWBLK_TMU1, 0), SH_HWBLK_CLK("flctl0", -1, P_CLK, HWBLK_FLCTL, 0), - SH_HWBLK_CLK("sci_fck", 0, P_CLK, HWBLK_SCIF0, 0), - SH_HWBLK_CLK("sci_fck", 1, P_CLK, HWBLK_SCIF1, 0), - SH_HWBLK_CLK("sci_fck", 2, P_CLK, HWBLK_SCIF2, 0), - SH_HWBLK_CLK("sci_fck", 3, B_CLK, HWBLK_SCIF3, 0), - SH_HWBLK_CLK("sci_fck", 4, B_CLK, HWBLK_SCIF4, 0), - SH_HWBLK_CLK("sci_fck", 5, B_CLK, HWBLK_SCIF5, 0), + SH_HWBLK_CLK("sci_fck", -1, P_CLK, HWBLK_SCIF0, 0), + SH_HWBLK_CLK("sci_fck", -1, P_CLK, HWBLK_SCIF1, 0), + SH_HWBLK_CLK("sci_fck", -1, P_CLK, HWBLK_SCIF2, 0), + SH_HWBLK_CLK("sci_fck", -1, B_CLK, HWBLK_SCIF3, 0), + SH_HWBLK_CLK("sci_fck", -1, B_CLK, HWBLK_SCIF4, 0), + SH_HWBLK_CLK("sci_fck", -1, B_CLK, HWBLK_SCIF5, 0), SH_HWBLK_CLK("msiof0", -1, B_CLK, HWBLK_MSIOF0, 0), SH_HWBLK_CLK("msiof1", -1, B_CLK, HWBLK_MSIOF1, 0), SH_HWBLK_CLK("meram0", -1, SH_CLK, HWBLK_MERAM, 0), @@ -244,6 +244,36 @@ static struct clk_lookup lookups[] = { .dev_id = "sh_tmu.5", .con_id = "tmu_fck", .clk = &mstp_clks[HWBLK_TMU1], + }, { + /* SCIF0 */ + .dev_id = "sh-sci.0", + .con_id = "sci_fck", + .clk = &mstp_clks[HWBLK_SCIF0], + }, { + /* SCIF1 */ + .dev_id = "sh-sci.1", + .con_id = "sci_fck", + .clk = &mstp_clks[HWBLK_SCIF1], + }, { + /* SCIF2 */ + .dev_id = "sh-sci.2", + .con_id = "sci_fck", + .clk = &mstp_clks[HWBLK_SCIF2], + }, { + /* SCIF3 */ + .dev_id = "sh-sci.3", + .con_id = "sci_fck", + .clk = &mstp_clks[HWBLK_SCIF3], + }, { + /* SCIF4 */ + .dev_id = "sh-sci.4", + .con_id = "sci_fck", + .clk = &mstp_clks[HWBLK_SCIF4], + }, { + /* SCIF5 */ + .dev_id = "sh-sci.5", + .con_id = "sci_fck", + .clk = &mstp_clks[HWBLK_SCIF5], }, }; diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c index c5d4891..0c2aa34 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c @@ -196,12 +196,12 @@ static struct clk mstp_clks[HWBLK_NR] = { SH_HWBLK_CLK("rwdt0", -1, R_CLK, HWBLK_RWDT, 0), SH_HWBLK_CLK("dmac1", -1, B_CLK, HWBLK_DMAC1, 0), SH_HWBLK_CLK("tmu345_fck", -1, P_CLK, HWBLK_TMU1, 0), - SH_HWBLK_CLK("sci_fck", 0, P_CLK, HWBLK_SCIF0, 0), - SH_HWBLK_CLK("sci_fck", 1, P_CLK, HWBLK_SCIF1, 0), - SH_HWBLK_CLK("sci_fck", 2, P_CLK, HWBLK_SCIF2, 0), - SH_HWBLK_CLK("sci_fck", 3, B_CLK, HWBLK_SCIF3, 0), - SH_HWBLK_CLK("sci_fck", 4, B_CLK, HWBLK_SCIF4, 0), - SH_HWBLK_CLK("sci_fck", 5, B_CLK, HWBLK_SCIF5, 0), + SH_HWBLK_CLK("sci_fck", -1, P_CLK, HWBLK_SCIF0, 0), + SH_HWBLK_CLK("sci_fck", -1, P_CLK, HWBLK_SCIF1, 0), + SH_HWBLK_CLK("sci_fck", -1, P_CLK, HWBLK_SCIF2, 0), + SH_HWBLK_CLK("sci_fck", -1, B_CLK, HWBLK_SCIF3, 0), + SH_HWBLK_CLK("sci_fck", -1, B_CLK, HWBLK_SCIF4, 0), + SH_HWBLK_CLK("sci_fck", -1, B_CLK, HWBLK_SCIF5, 0), SH_HWBLK_CLK("msiof0", -1, B_CLK, HWBLK_MSIOF0, 0), SH_HWBLK_CLK("msiof1", -1, B_CLK, HWBLK_MSIOF1, 0), @@ -266,6 +266,36 @@ static struct clk_lookup lookups[] = { .dev_id = "sh_tmu.5", .con_id = "tmu_fck", .clk = &mstp_clks[HWBLK_TMU1], + }, { + /* SCIF0 */ + .dev_id = "sh-sci.0", + .con_id = "sci_fck", + .clk = &mstp_clks[HWBLK_SCIF0], + }, { + /* SCIF1 */ + .dev_id = "sh-sci.1", + .con_id = "sci_fck", + .clk = &mstp_clks[HWBLK_SCIF1], + }, { + /* SCIF2 */ + .dev_id = "sh-sci.2", + .con_id = "sci_fck", + .clk = &mstp_clks[HWBLK_SCIF2], + }, { + /* SCIF3 */ + .dev_id = "sh-sci.3", + .con_id = "sci_fck", + .clk = &mstp_clks[HWBLK_SCIF3], + }, { + /* SCIF4 */ + .dev_id = "sh-sci.4", + .con_id = "sci_fck", + .clk = &mstp_clks[HWBLK_SCIF4], + }, { + /* SCIF5 */ + .dev_id = "sh-sci.5", + .con_id = "sci_fck", + .clk = &mstp_clks[HWBLK_SCIF5], }, }; -- cgit v0.10.2 From fd30401b07fdcf21e4be87fd276d1b2c84d712a3 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Mon, 10 May 2010 14:01:22 +0000 Subject: sh: tie in hwblk clocks using clkdev Use clkdev for lookup of hwblk clocks on sh7722/sh7723/sh7724. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c index ed57c63..2a122e0 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c @@ -186,7 +186,12 @@ static struct clk mstp_clks[HWBLK_NR] = { SH_HWBLK_CLK("lcdc0", -1, P_CLK, HWBLK_LCDC, 0), }; +#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } + static struct clk_lookup lookups[] = { + /* MSTP clocks */ + CLKDEV_CON_ID("uram0", &mstp_clks[HWBLK_URAM]), + CLKDEV_CON_ID("xymem0", &mstp_clks[HWBLK_XYMEM]), { /* TMU0 */ .dev_id = "sh_tmu.0", @@ -202,7 +207,11 @@ static struct clk_lookup lookups[] = { .dev_id = "sh_tmu.2", .con_id = "tmu_fck", .clk = &mstp_clks[HWBLK_TMU], - }, { + }, + CLKDEV_CON_ID("cmt_fck", &mstp_clks[HWBLK_CMT]), + CLKDEV_CON_ID("rwdt0", &mstp_clks[HWBLK_RWDT]), + CLKDEV_CON_ID("flctl0", &mstp_clks[HWBLK_FLCTL]), + { /* SCIF0 */ .dev_id = "sh-sci.0", .con_id = "sci_fck", @@ -218,6 +227,20 @@ static struct clk_lookup lookups[] = { .con_id = "sci_fck", .clk = &mstp_clks[HWBLK_SCIF2], }, + CLKDEV_CON_ID("i2c0", &mstp_clks[HWBLK_IIC]), + CLKDEV_CON_ID("rtc0", &mstp_clks[HWBLK_RTC]), + CLKDEV_CON_ID("sdhi0", &mstp_clks[HWBLK_SDHI]), + CLKDEV_CON_ID("keysc0", &mstp_clks[HWBLK_KEYSC]), + CLKDEV_CON_ID("usbf0", &mstp_clks[HWBLK_USBF]), + CLKDEV_CON_ID("2dg0", &mstp_clks[HWBLK_2DG]), + CLKDEV_CON_ID("siu0", &mstp_clks[HWBLK_SIU]), + CLKDEV_CON_ID("vou0", &mstp_clks[HWBLK_VOU]), + CLKDEV_CON_ID("jpu0", &mstp_clks[HWBLK_JPU]), + CLKDEV_CON_ID("beu0", &mstp_clks[HWBLK_BEU]), + CLKDEV_CON_ID("ceu0", &mstp_clks[HWBLK_CEU]), + CLKDEV_CON_ID("veu0", &mstp_clks[HWBLK_VEU]), + CLKDEV_CON_ID("vpu0", &mstp_clks[HWBLK_VPU]), + CLKDEV_CON_ID("lcdc0", &mstp_clks[HWBLK_LCDC]), }; int __init arch_clk_init(void) diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c index d92d7cd..36e17dc 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c @@ -213,7 +213,21 @@ static struct clk mstp_clks[] = { SH_HWBLK_CLK("lcdc0", -1, B_CLK, HWBLK_LCDC, 0), }; +#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } + static struct clk_lookup lookups[] = { + /* MSTP clocks */ + CLKDEV_CON_ID("tlb0", &mstp_clks[HWBLK_TLB]), + CLKDEV_CON_ID("ic0", &mstp_clks[HWBLK_IC]), + CLKDEV_CON_ID("oc0", &mstp_clks[HWBLK_OC]), + CLKDEV_CON_ID("l2c0", &mstp_clks[HWBLK_L2C]), + CLKDEV_CON_ID("ilmem0", &mstp_clks[HWBLK_ILMEM]), + CLKDEV_CON_ID("fpu0", &mstp_clks[HWBLK_FPU]), + CLKDEV_CON_ID("intc0", &mstp_clks[HWBLK_INTC]), + CLKDEV_CON_ID("dmac0", &mstp_clks[HWBLK_DMAC0]), + CLKDEV_CON_ID("sh0", &mstp_clks[HWBLK_SHYWAY]), + CLKDEV_CON_ID("hudi0", &mstp_clks[HWBLK_HUDI]), + CLKDEV_CON_ID("ubc0", &mstp_clks[HWBLK_UBC]), { /* TMU0 */ .dev_id = "sh_tmu.0", @@ -229,7 +243,11 @@ static struct clk_lookup lookups[] = { .dev_id = "sh_tmu.2", .con_id = "tmu_fck", .clk = &mstp_clks[HWBLK_TMU0], - }, { + }, + CLKDEV_CON_ID("cmt_fck", &mstp_clks[HWBLK_CMT]), + CLKDEV_CON_ID("rwdt0", &mstp_clks[HWBLK_RWDT]), + CLKDEV_CON_ID("dmac1", &mstp_clks[HWBLK_DMAC1]), + { /* TMU3 */ .dev_id = "sh_tmu.3", .con_id = "tmu_fck", @@ -244,7 +262,9 @@ static struct clk_lookup lookups[] = { .dev_id = "sh_tmu.5", .con_id = "tmu_fck", .clk = &mstp_clks[HWBLK_TMU1], - }, { + }, + CLKDEV_CON_ID("flctl0", &mstp_clks[HWBLK_FLCTL]), + { /* SCIF0 */ .dev_id = "sh-sci.0", .con_id = "sci_fck", @@ -275,6 +295,30 @@ static struct clk_lookup lookups[] = { .con_id = "sci_fck", .clk = &mstp_clks[HWBLK_SCIF5], }, + CLKDEV_CON_ID("msiof0", &mstp_clks[HWBLK_MSIOF0]), + CLKDEV_CON_ID("msiof1", &mstp_clks[HWBLK_MSIOF1]), + CLKDEV_CON_ID("meram0", &mstp_clks[HWBLK_MERAM]), + CLKDEV_CON_ID("i2c0", &mstp_clks[HWBLK_IIC]), + CLKDEV_CON_ID("rtc0", &mstp_clks[HWBLK_RTC]), + CLKDEV_CON_ID("atapi0", &mstp_clks[HWBLK_ATAPI]), + CLKDEV_CON_ID("adc0", &mstp_clks[HWBLK_ADC]), + CLKDEV_CON_ID("tpu0", &mstp_clks[HWBLK_TPU]), + CLKDEV_CON_ID("irda0", &mstp_clks[HWBLK_IRDA]), + CLKDEV_CON_ID("tsif0", &mstp_clks[HWBLK_TSIF]), + CLKDEV_CON_ID("icb0", &mstp_clks[HWBLK_ICB]), + CLKDEV_CON_ID("sdhi0", &mstp_clks[HWBLK_SDHI0]), + CLKDEV_CON_ID("sdhi1", &mstp_clks[HWBLK_SDHI1]), + CLKDEV_CON_ID("keysc0", &mstp_clks[HWBLK_KEYSC]), + CLKDEV_CON_ID("usb0", &mstp_clks[HWBLK_USB]), + CLKDEV_CON_ID("2dg0", &mstp_clks[HWBLK_2DG]), + CLKDEV_CON_ID("siu0", &mstp_clks[HWBLK_SIU]), + CLKDEV_CON_ID("veu1", &mstp_clks[HWBLK_VEU2H1]), + CLKDEV_CON_ID("vou0", &mstp_clks[HWBLK_VOU]), + CLKDEV_CON_ID("beu0", &mstp_clks[HWBLK_BEU]), + CLKDEV_CON_ID("ceu0", &mstp_clks[HWBLK_CEU]), + CLKDEV_CON_ID("veu0", &mstp_clks[HWBLK_VEU2H0]), + CLKDEV_CON_ID("vpu0", &mstp_clks[HWBLK_VPU]), + CLKDEV_CON_ID("lcdc0", &mstp_clks[HWBLK_LCDC]), }; int __init arch_clk_init(void) diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c index 0c2aa34..fe59f34 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c @@ -235,7 +235,22 @@ static struct clk mstp_clks[HWBLK_NR] = { SH_HWBLK_CLK("lcdc0", -1, B_CLK, HWBLK_LCDC, 0), }; +#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } + static struct clk_lookup lookups[] = { + /* MSTP clocks */ + CLKDEV_CON_ID("tlb0", &mstp_clks[HWBLK_TLB]), + CLKDEV_CON_ID("ic0", &mstp_clks[HWBLK_IC]), + CLKDEV_CON_ID("oc0", &mstp_clks[HWBLK_OC]), + CLKDEV_CON_ID("rs0", &mstp_clks[HWBLK_RSMEM]), + CLKDEV_CON_ID("ilmem0", &mstp_clks[HWBLK_ILMEM]), + CLKDEV_CON_ID("l2c0", &mstp_clks[HWBLK_L2C]), + CLKDEV_CON_ID("fpu0", &mstp_clks[HWBLK_FPU]), + CLKDEV_CON_ID("intc0", &mstp_clks[HWBLK_INTC]), + CLKDEV_CON_ID("dmac0", &mstp_clks[HWBLK_DMAC0]), + CLKDEV_CON_ID("sh0", &mstp_clks[HWBLK_SHYWAY]), + CLKDEV_CON_ID("hudi0", &mstp_clks[HWBLK_HUDI]), + CLKDEV_CON_ID("ubc0", &mstp_clks[HWBLK_UBC]), { /* TMU0 */ .dev_id = "sh_tmu.0", @@ -256,7 +271,11 @@ static struct clk_lookup lookups[] = { .dev_id = "sh_tmu.3", .con_id = "tmu_fck", .clk = &mstp_clks[HWBLK_TMU1], - }, { + }, + CLKDEV_CON_ID("cmt_fck", &mstp_clks[HWBLK_CMT]), + CLKDEV_CON_ID("rwdt0", &mstp_clks[HWBLK_RWDT]), + CLKDEV_CON_ID("dmac1", &mstp_clks[HWBLK_DMAC1]), + { /* TMU4 */ .dev_id = "sh_tmu.4", .con_id = "tmu_fck", @@ -297,6 +316,35 @@ static struct clk_lookup lookups[] = { .con_id = "sci_fck", .clk = &mstp_clks[HWBLK_SCIF5], }, + CLKDEV_CON_ID("msiof0", &mstp_clks[HWBLK_MSIOF0]), + CLKDEV_CON_ID("msiof1", &mstp_clks[HWBLK_MSIOF1]), + CLKDEV_CON_ID("keysc0", &mstp_clks[HWBLK_KEYSC]), + CLKDEV_CON_ID("rtc0", &mstp_clks[HWBLK_RTC]), + CLKDEV_CON_ID("i2c0", &mstp_clks[HWBLK_IIC0]), + CLKDEV_CON_ID("i2c1", &mstp_clks[HWBLK_IIC1]), + CLKDEV_CON_ID("mmc0", &mstp_clks[HWBLK_MMC]), + CLKDEV_CON_ID("eth0", &mstp_clks[HWBLK_ETHER]), + CLKDEV_CON_ID("atapi0", &mstp_clks[HWBLK_ATAPI]), + CLKDEV_CON_ID("tpu0", &mstp_clks[HWBLK_TPU]), + CLKDEV_CON_ID("irda0", &mstp_clks[HWBLK_IRDA]), + CLKDEV_CON_ID("tsif0", &mstp_clks[HWBLK_TSIF]), + CLKDEV_CON_ID("usb1", &mstp_clks[HWBLK_USB1]), + CLKDEV_CON_ID("usb0", &mstp_clks[HWBLK_USB0]), + CLKDEV_CON_ID("2dg0", &mstp_clks[HWBLK_2DG]), + CLKDEV_CON_ID("sdhi0", &mstp_clks[HWBLK_SDHI0]), + CLKDEV_CON_ID("sdhi1", &mstp_clks[HWBLK_SDHI1]), + CLKDEV_CON_ID("veu1", &mstp_clks[HWBLK_VEU1]), + CLKDEV_CON_ID("ceu1", &mstp_clks[HWBLK_CEU1]), + CLKDEV_CON_ID("beu1", &mstp_clks[HWBLK_BEU1]), + CLKDEV_CON_ID("2ddmac0", &mstp_clks[HWBLK_2DDMAC]), + CLKDEV_CON_ID("spu0", &mstp_clks[HWBLK_SPU]), + CLKDEV_CON_ID("jpu0", &mstp_clks[HWBLK_JPU]), + CLKDEV_CON_ID("vou0", &mstp_clks[HWBLK_VOU]), + CLKDEV_CON_ID("beu0", &mstp_clks[HWBLK_BEU0]), + CLKDEV_CON_ID("ceu0", &mstp_clks[HWBLK_CEU0]), + CLKDEV_CON_ID("veu0", &mstp_clks[HWBLK_VEU0]), + CLKDEV_CON_ID("vpu0", &mstp_clks[HWBLK_VPU]), + CLKDEV_CON_ID("lcdc0", &mstp_clks[HWBLK_LCDC]), }; int __init arch_clk_init(void) -- cgit v0.10.2 From d97432f1014c73bbace9eb1e67742c1bcab0c3cd Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Mon, 10 May 2010 14:01:34 +0000 Subject: sh: allow registering clocks without name Modify the SuperH clock code to support struct clk with NULL as name. Such clocks will not be hooked up to debugfs. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c index 9ded1bc..073f4ff 100644 --- a/arch/sh/kernel/cpu/clock.c +++ b/arch/sh/kernel/cpu/clock.c @@ -415,7 +415,7 @@ struct clk *clk_get(struct device *dev, const char *id) mutex_lock(&clock_list_sem); list_for_each_entry(p, &clock_list, node) { - if (p->id == idno && + if (p->name && p->id == idno && strcmp(id, p->name) == 0 && try_module_get(p->owner)) { clk = p; goto found; @@ -423,7 +423,8 @@ struct clk *clk_get(struct device *dev, const char *id) } list_for_each_entry(p, &clock_list, node) { - if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { + if (p->name && + strcmp(id, p->name) == 0 && try_module_get(p->owner)) { clk = p; break; } @@ -594,7 +595,7 @@ static int clk_debugfs_register(struct clk *c) return err; } - if (!c->dentry) { + if (!c->dentry && c->name) { err = clk_debugfs_register_one(c); if (err) return err; -- cgit v0.10.2 From 08134c3c629bf128245f721391b96a858d88e997 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Mon, 10 May 2010 14:01:44 +0000 Subject: sh: get rid of hwblk clock names Remove the clock name from sh7722/sh7723/sh7724 hwblk clocks. Lookup is handled by clkdev. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/include/asm/hwblk.h b/arch/sh/include/asm/hwblk.h index 4984d29..855e945 100644 --- a/arch/sh/include/asm/hwblk.h +++ b/arch/sh/include/asm/hwblk.h @@ -58,13 +58,11 @@ void hwblk_cnt_inc(struct hwblk_info *info, int hwblk, int cnt); void hwblk_cnt_dec(struct hwblk_info *info, int hwblk, int cnt); /* allow clocks to enable and disable hardware blocks */ -#define SH_HWBLK_CLK(_name, _id, _parent, _hwblk, _flags) \ -[_hwblk] = { \ - .name = _name, \ - .id = _id, \ - .parent = _parent, \ - .arch_flags = _hwblk, \ - .flags = _flags, \ +#define SH_HWBLK_CLK(_hwblk, _parent, _flags) \ +[_hwblk] = { \ + .parent = _parent, \ + .arch_flags = _hwblk, \ + .flags = _flags, \ } int sh_hwblk_clk_register(struct clk *clks, int nr); diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c index 2a122e0..151bc3e 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c @@ -153,37 +153,32 @@ struct clk div6_clks[] = { SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0), }; -#define R_CLK &r_clk -#define P_CLK &div4_clks[DIV4_P] -#define B_CLK &div4_clks[DIV4_B] -#define U_CLK &div4_clks[DIV4_U] - static struct clk mstp_clks[HWBLK_NR] = { - SH_HWBLK_CLK("uram0", -1, U_CLK, HWBLK_URAM, CLK_ENABLE_ON_INIT), - SH_HWBLK_CLK("xymem0", -1, B_CLK, HWBLK_XYMEM, CLK_ENABLE_ON_INIT), - SH_HWBLK_CLK("tmu_fck", -1, P_CLK, HWBLK_TMU, 0), - SH_HWBLK_CLK("cmt_fck", -1, R_CLK, HWBLK_CMT, 0), - SH_HWBLK_CLK("rwdt0", -1, R_CLK, HWBLK_RWDT, 0), - SH_HWBLK_CLK("flctl0", -1, P_CLK, HWBLK_FLCTL, 0), - SH_HWBLK_CLK("sci_fck", -1, P_CLK, HWBLK_SCIF0, 0), - SH_HWBLK_CLK("sci_fck", -1, P_CLK, HWBLK_SCIF1, 0), - SH_HWBLK_CLK("sci_fck", -1, P_CLK, HWBLK_SCIF2, 0), - - SH_HWBLK_CLK("i2c0", -1, P_CLK, HWBLK_IIC, 0), - SH_HWBLK_CLK("rtc0", -1, R_CLK, HWBLK_RTC, 0), - - SH_HWBLK_CLK("sdhi0", -1, P_CLK, HWBLK_SDHI, 0), - SH_HWBLK_CLK("keysc0", -1, R_CLK, HWBLK_KEYSC, 0), - SH_HWBLK_CLK("usbf0", -1, P_CLK, HWBLK_USBF, 0), - SH_HWBLK_CLK("2dg0", -1, B_CLK, HWBLK_2DG, 0), - SH_HWBLK_CLK("siu0", -1, B_CLK, HWBLK_SIU, 0), - SH_HWBLK_CLK("vou0", -1, B_CLK, HWBLK_VOU, 0), - SH_HWBLK_CLK("jpu0", -1, B_CLK, HWBLK_JPU, 0), - SH_HWBLK_CLK("beu0", -1, B_CLK, HWBLK_BEU, 0), - SH_HWBLK_CLK("ceu0", -1, B_CLK, HWBLK_CEU, 0), - SH_HWBLK_CLK("veu0", -1, B_CLK, HWBLK_VEU, 0), - SH_HWBLK_CLK("vpu0", -1, B_CLK, HWBLK_VPU, 0), - SH_HWBLK_CLK("lcdc0", -1, P_CLK, HWBLK_LCDC, 0), + SH_HWBLK_CLK(HWBLK_URAM, &div4_clks[DIV4_U], CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK(HWBLK_XYMEM, &div4_clks[DIV4_B], CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK(HWBLK_TMU, &div4_clks[DIV4_P], 0), + SH_HWBLK_CLK(HWBLK_CMT, &r_clk, 0), + SH_HWBLK_CLK(HWBLK_RWDT, &r_clk, 0), + SH_HWBLK_CLK(HWBLK_FLCTL, &div4_clks[DIV4_P], 0), + SH_HWBLK_CLK(HWBLK_SCIF0, &div4_clks[DIV4_P], 0), + SH_HWBLK_CLK(HWBLK_SCIF1, &div4_clks[DIV4_P], 0), + SH_HWBLK_CLK(HWBLK_SCIF2, &div4_clks[DIV4_P], 0), + + SH_HWBLK_CLK(HWBLK_IIC, &div4_clks[DIV4_P], 0), + SH_HWBLK_CLK(HWBLK_RTC, &r_clk, 0), + + SH_HWBLK_CLK(HWBLK_SDHI, &div4_clks[DIV4_P], 0), + SH_HWBLK_CLK(HWBLK_KEYSC, &r_clk, 0), + SH_HWBLK_CLK(HWBLK_USBF, &div4_clks[DIV4_P], 0), + SH_HWBLK_CLK(HWBLK_2DG, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_SIU, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_VOU, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_JPU, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_BEU, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_CEU, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_VEU, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_VPU, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_LCDC, &div4_clks[DIV4_P], 0), }; #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c index 36e17dc..b433185 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c @@ -153,64 +153,57 @@ struct clk div6_clks[] = { SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0), }; -#define R_CLK (&r_clk) -#define P_CLK (&div4_clks[DIV4_P]) -#define B_CLK (&div4_clks[DIV4_B]) -#define U_CLK (&div4_clks[DIV4_U]) -#define I_CLK (&div4_clks[DIV4_I]) -#define SH_CLK (&div4_clks[DIV4_SH]) - static struct clk mstp_clks[] = { /* See page 60 of Datasheet V1.0: Overview -> Block Diagram */ - SH_HWBLK_CLK("tlb0", -1, I_CLK, HWBLK_TLB, CLK_ENABLE_ON_INIT), - SH_HWBLK_CLK("ic0", -1, I_CLK, HWBLK_IC, CLK_ENABLE_ON_INIT), - SH_HWBLK_CLK("oc0", -1, I_CLK, HWBLK_OC, CLK_ENABLE_ON_INIT), - SH_HWBLK_CLK("l2c0", -1, SH_CLK, HWBLK_L2C, CLK_ENABLE_ON_INIT), - SH_HWBLK_CLK("ilmem0", -1, I_CLK, HWBLK_ILMEM, CLK_ENABLE_ON_INIT), - SH_HWBLK_CLK("fpu0", -1, I_CLK, HWBLK_FPU, CLK_ENABLE_ON_INIT), - SH_HWBLK_CLK("intc0", -1, I_CLK, HWBLK_INTC, CLK_ENABLE_ON_INIT), - SH_HWBLK_CLK("dmac0", -1, B_CLK, HWBLK_DMAC0, 0), - SH_HWBLK_CLK("sh0", -1, SH_CLK, HWBLK_SHYWAY, CLK_ENABLE_ON_INIT), - SH_HWBLK_CLK("hudi0", -1, P_CLK, HWBLK_HUDI, 0), - SH_HWBLK_CLK("ubc0", -1, I_CLK, HWBLK_UBC, 0), - SH_HWBLK_CLK("tmu012_fck", -1, P_CLK, HWBLK_TMU0, 0), - SH_HWBLK_CLK("cmt_fck", -1, R_CLK, HWBLK_CMT, 0), - SH_HWBLK_CLK("rwdt0", -1, R_CLK, HWBLK_RWDT, 0), - SH_HWBLK_CLK("dmac1", -1, B_CLK, HWBLK_DMAC1, 0), - SH_HWBLK_CLK("tmu345_fck", -1, P_CLK, HWBLK_TMU1, 0), - SH_HWBLK_CLK("flctl0", -1, P_CLK, HWBLK_FLCTL, 0), - SH_HWBLK_CLK("sci_fck", -1, P_CLK, HWBLK_SCIF0, 0), - SH_HWBLK_CLK("sci_fck", -1, P_CLK, HWBLK_SCIF1, 0), - SH_HWBLK_CLK("sci_fck", -1, P_CLK, HWBLK_SCIF2, 0), - SH_HWBLK_CLK("sci_fck", -1, B_CLK, HWBLK_SCIF3, 0), - SH_HWBLK_CLK("sci_fck", -1, B_CLK, HWBLK_SCIF4, 0), - SH_HWBLK_CLK("sci_fck", -1, B_CLK, HWBLK_SCIF5, 0), - SH_HWBLK_CLK("msiof0", -1, B_CLK, HWBLK_MSIOF0, 0), - SH_HWBLK_CLK("msiof1", -1, B_CLK, HWBLK_MSIOF1, 0), - SH_HWBLK_CLK("meram0", -1, SH_CLK, HWBLK_MERAM, 0), - - SH_HWBLK_CLK("i2c0", -1, P_CLK, HWBLK_IIC, 0), - SH_HWBLK_CLK("rtc0", -1, R_CLK, HWBLK_RTC, 0), - - SH_HWBLK_CLK("atapi0", -1, SH_CLK, HWBLK_ATAPI, 0), - SH_HWBLK_CLK("adc0", -1, P_CLK, HWBLK_ADC, 0), - SH_HWBLK_CLK("tpu0", -1, B_CLK, HWBLK_TPU, 0), - SH_HWBLK_CLK("irda0", -1, P_CLK, HWBLK_IRDA, 0), - SH_HWBLK_CLK("tsif0", -1, B_CLK, HWBLK_TSIF, 0), - SH_HWBLK_CLK("icb0", -1, B_CLK, HWBLK_ICB, CLK_ENABLE_ON_INIT), - SH_HWBLK_CLK("sdhi0", -1, B_CLK, HWBLK_SDHI0, 0), - SH_HWBLK_CLK("sdhi1", -1, B_CLK, HWBLK_SDHI1, 0), - SH_HWBLK_CLK("keysc0", -1, R_CLK, HWBLK_KEYSC, 0), - SH_HWBLK_CLK("usb0", -1, B_CLK, HWBLK_USB, 0), - SH_HWBLK_CLK("2dg0", -1, B_CLK, HWBLK_2DG, 0), - SH_HWBLK_CLK("siu0", -1, B_CLK, HWBLK_SIU, 0), - SH_HWBLK_CLK("veu1", -1, B_CLK, HWBLK_VEU2H1, 0), - SH_HWBLK_CLK("vou0", -1, B_CLK, HWBLK_VOU, 0), - SH_HWBLK_CLK("beu0", -1, B_CLK, HWBLK_BEU, 0), - SH_HWBLK_CLK("ceu0", -1, B_CLK, HWBLK_CEU, 0), - SH_HWBLK_CLK("veu0", -1, B_CLK, HWBLK_VEU2H0, 0), - SH_HWBLK_CLK("vpu0", -1, B_CLK, HWBLK_VPU, 0), - SH_HWBLK_CLK("lcdc0", -1, B_CLK, HWBLK_LCDC, 0), + SH_HWBLK_CLK(HWBLK_TLB, &div4_clks[DIV4_I], CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK(HWBLK_IC, &div4_clks[DIV4_I], CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK(HWBLK_OC, &div4_clks[DIV4_I], CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK(HWBLK_L2C, &div4_clks[DIV4_SH], CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK(HWBLK_ILMEM, &div4_clks[DIV4_I], CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK(HWBLK_FPU, &div4_clks[DIV4_I], CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK(HWBLK_INTC, &div4_clks[DIV4_I], CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK(HWBLK_DMAC0, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_SHYWAY, &div4_clks[DIV4_SH], CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK(HWBLK_HUDI, &div4_clks[DIV4_P], 0), + SH_HWBLK_CLK(HWBLK_UBC, &div4_clks[DIV4_I], 0), + SH_HWBLK_CLK(HWBLK_TMU0, &div4_clks[DIV4_P], 0), + SH_HWBLK_CLK(HWBLK_CMT, &r_clk, 0), + SH_HWBLK_CLK(HWBLK_RWDT, &r_clk, 0), + SH_HWBLK_CLK(HWBLK_DMAC1, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_TMU1, &div4_clks[DIV4_P], 0), + SH_HWBLK_CLK(HWBLK_FLCTL, &div4_clks[DIV4_P], 0), + SH_HWBLK_CLK(HWBLK_SCIF0, &div4_clks[DIV4_P], 0), + SH_HWBLK_CLK(HWBLK_SCIF1, &div4_clks[DIV4_P], 0), + SH_HWBLK_CLK(HWBLK_SCIF2, &div4_clks[DIV4_P], 0), + SH_HWBLK_CLK(HWBLK_SCIF3, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_SCIF4, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_SCIF5, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_MSIOF0, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_MSIOF1, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_MERAM, &div4_clks[DIV4_SH], 0), + + SH_HWBLK_CLK(HWBLK_IIC, &div4_clks[DIV4_P], 0), + SH_HWBLK_CLK(HWBLK_RTC, &r_clk, 0), + + SH_HWBLK_CLK(HWBLK_ATAPI, &div4_clks[DIV4_SH], 0), + SH_HWBLK_CLK(HWBLK_ADC, &div4_clks[DIV4_P], 0), + SH_HWBLK_CLK(HWBLK_TPU, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_IRDA, &div4_clks[DIV4_P], 0), + SH_HWBLK_CLK(HWBLK_TSIF, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_ICB, &div4_clks[DIV4_B], CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK(HWBLK_SDHI0, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_SDHI1, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_KEYSC, &r_clk, 0), + SH_HWBLK_CLK(HWBLK_USB, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_2DG, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_SIU, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_VEU2H1, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_VOU, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_BEU, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_CEU, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_VEU2H0, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_VPU, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_LCDC, &div4_clks[DIV4_B], 0), }; #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c index fe59f34..6f3d400 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c @@ -172,67 +172,61 @@ struct clk div6_clks[] = { SH_CLK_DIV6("spu_clk", &div3_clk, SPUCLKCR, CLK_ENABLE_ON_INIT), }; -#define R_CLK (&r_clk) -#define P_CLK (&div4_clks[DIV4_P]) -#define B_CLK (&div4_clks[DIV4_B]) -#define I_CLK (&div4_clks[DIV4_I]) -#define SH_CLK (&div4_clks[DIV4_SH]) - static struct clk mstp_clks[HWBLK_NR] = { - SH_HWBLK_CLK("tlb0", -1, I_CLK, HWBLK_TLB, CLK_ENABLE_ON_INIT), - SH_HWBLK_CLK("ic0", -1, I_CLK, HWBLK_IC, CLK_ENABLE_ON_INIT), - SH_HWBLK_CLK("oc0", -1, I_CLK, HWBLK_OC, CLK_ENABLE_ON_INIT), - SH_HWBLK_CLK("rs0", -1, B_CLK, HWBLK_RSMEM, CLK_ENABLE_ON_INIT), - SH_HWBLK_CLK("ilmem0", -1, I_CLK, HWBLK_ILMEM, CLK_ENABLE_ON_INIT), - SH_HWBLK_CLK("l2c0", -1, SH_CLK, HWBLK_L2C, CLK_ENABLE_ON_INIT), - SH_HWBLK_CLK("fpu0", -1, I_CLK, HWBLK_FPU, CLK_ENABLE_ON_INIT), - SH_HWBLK_CLK("intc0", -1, P_CLK, HWBLK_INTC, CLK_ENABLE_ON_INIT), - SH_HWBLK_CLK("dmac0", -1, B_CLK, HWBLK_DMAC0, 0), - SH_HWBLK_CLK("sh0", -1, SH_CLK, HWBLK_SHYWAY, CLK_ENABLE_ON_INIT), - SH_HWBLK_CLK("hudi0", -1, P_CLK, HWBLK_HUDI, 0), - SH_HWBLK_CLK("ubc0", -1, I_CLK, HWBLK_UBC, 0), - SH_HWBLK_CLK("tmu012_fck", -1, P_CLK, HWBLK_TMU0, 0), - SH_HWBLK_CLK("cmt_fck", -1, R_CLK, HWBLK_CMT, 0), - SH_HWBLK_CLK("rwdt0", -1, R_CLK, HWBLK_RWDT, 0), - SH_HWBLK_CLK("dmac1", -1, B_CLK, HWBLK_DMAC1, 0), - SH_HWBLK_CLK("tmu345_fck", -1, P_CLK, HWBLK_TMU1, 0), - SH_HWBLK_CLK("sci_fck", -1, P_CLK, HWBLK_SCIF0, 0), - SH_HWBLK_CLK("sci_fck", -1, P_CLK, HWBLK_SCIF1, 0), - SH_HWBLK_CLK("sci_fck", -1, P_CLK, HWBLK_SCIF2, 0), - SH_HWBLK_CLK("sci_fck", -1, B_CLK, HWBLK_SCIF3, 0), - SH_HWBLK_CLK("sci_fck", -1, B_CLK, HWBLK_SCIF4, 0), - SH_HWBLK_CLK("sci_fck", -1, B_CLK, HWBLK_SCIF5, 0), - SH_HWBLK_CLK("msiof0", -1, B_CLK, HWBLK_MSIOF0, 0), - SH_HWBLK_CLK("msiof1", -1, B_CLK, HWBLK_MSIOF1, 0), - - SH_HWBLK_CLK("keysc0", -1, R_CLK, HWBLK_KEYSC, 0), - SH_HWBLK_CLK("rtc0", -1, R_CLK, HWBLK_RTC, 0), - SH_HWBLK_CLK("i2c0", -1, P_CLK, HWBLK_IIC0, 0), - SH_HWBLK_CLK("i2c1", -1, P_CLK, HWBLK_IIC1, 0), - - SH_HWBLK_CLK("mmc0", -1, B_CLK, HWBLK_MMC, 0), - SH_HWBLK_CLK("eth0", -1, B_CLK, HWBLK_ETHER, 0), - SH_HWBLK_CLK("atapi0", -1, B_CLK, HWBLK_ATAPI, 0), - SH_HWBLK_CLK("tpu0", -1, B_CLK, HWBLK_TPU, 0), - SH_HWBLK_CLK("irda0", -1, P_CLK, HWBLK_IRDA, 0), - SH_HWBLK_CLK("tsif0", -1, B_CLK, HWBLK_TSIF, 0), - SH_HWBLK_CLK("usb1", -1, B_CLK, HWBLK_USB1, 0), - SH_HWBLK_CLK("usb0", -1, B_CLK, HWBLK_USB0, 0), - SH_HWBLK_CLK("2dg0", -1, B_CLK, HWBLK_2DG, 0), - SH_HWBLK_CLK("sdhi0", -1, B_CLK, HWBLK_SDHI0, 0), - SH_HWBLK_CLK("sdhi1", -1, B_CLK, HWBLK_SDHI1, 0), - SH_HWBLK_CLK("veu1", -1, B_CLK, HWBLK_VEU1, 0), - SH_HWBLK_CLK("ceu1", -1, B_CLK, HWBLK_CEU1, 0), - SH_HWBLK_CLK("beu1", -1, B_CLK, HWBLK_BEU1, 0), - SH_HWBLK_CLK("2ddmac0", -1, SH_CLK, HWBLK_2DDMAC, 0), - SH_HWBLK_CLK("spu0", -1, B_CLK, HWBLK_SPU, 0), - SH_HWBLK_CLK("jpu0", -1, B_CLK, HWBLK_JPU, 0), - SH_HWBLK_CLK("vou0", -1, B_CLK, HWBLK_VOU, 0), - SH_HWBLK_CLK("beu0", -1, B_CLK, HWBLK_BEU0, 0), - SH_HWBLK_CLK("ceu0", -1, B_CLK, HWBLK_CEU0, 0), - SH_HWBLK_CLK("veu0", -1, B_CLK, HWBLK_VEU0, 0), - SH_HWBLK_CLK("vpu0", -1, B_CLK, HWBLK_VPU, 0), - SH_HWBLK_CLK("lcdc0", -1, B_CLK, HWBLK_LCDC, 0), + SH_HWBLK_CLK(HWBLK_TLB, &div4_clks[DIV4_I], CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK(HWBLK_IC, &div4_clks[DIV4_I], CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK(HWBLK_OC, &div4_clks[DIV4_I], CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK(HWBLK_RSMEM, &div4_clks[DIV4_B], CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK(HWBLK_ILMEM, &div4_clks[DIV4_I], CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK(HWBLK_L2C, &div4_clks[DIV4_SH], CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK(HWBLK_FPU, &div4_clks[DIV4_I], CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK(HWBLK_INTC, &div4_clks[DIV4_P], CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK(HWBLK_DMAC0, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_SHYWAY, &div4_clks[DIV4_SH], CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK(HWBLK_HUDI, &div4_clks[DIV4_P], 0), + SH_HWBLK_CLK(HWBLK_UBC, &div4_clks[DIV4_I], 0), + SH_HWBLK_CLK(HWBLK_TMU0, &div4_clks[DIV4_P], 0), + SH_HWBLK_CLK(HWBLK_CMT, &r_clk, 0), + SH_HWBLK_CLK(HWBLK_RWDT, &r_clk, 0), + SH_HWBLK_CLK(HWBLK_DMAC1, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_TMU1, &div4_clks[DIV4_P], 0), + SH_HWBLK_CLK(HWBLK_SCIF0, &div4_clks[DIV4_P], 0), + SH_HWBLK_CLK(HWBLK_SCIF1, &div4_clks[DIV4_P], 0), + SH_HWBLK_CLK(HWBLK_SCIF2, &div4_clks[DIV4_P], 0), + SH_HWBLK_CLK(HWBLK_SCIF3, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_SCIF4, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_SCIF5, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_MSIOF0, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_MSIOF1, &div4_clks[DIV4_B], 0), + + SH_HWBLK_CLK(HWBLK_KEYSC, &r_clk, 0), + SH_HWBLK_CLK(HWBLK_RTC, &r_clk, 0), + SH_HWBLK_CLK(HWBLK_IIC0, &div4_clks[DIV4_P], 0), + SH_HWBLK_CLK(HWBLK_IIC1, &div4_clks[DIV4_P], 0), + + SH_HWBLK_CLK(HWBLK_MMC, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_ETHER, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_ATAPI, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_TPU, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_IRDA, &div4_clks[DIV4_P], 0), + SH_HWBLK_CLK(HWBLK_TSIF, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_USB1, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_USB0, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_2DG, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_SDHI0, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_SDHI1, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_VEU1, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_CEU1, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_BEU1, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_2DDMAC, &div4_clks[DIV4_SH], 0), + SH_HWBLK_CLK(HWBLK_SPU, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_JPU, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_VOU, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_BEU0, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_CEU0, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_VEU0, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_VPU, &div4_clks[DIV4_B], 0), + SH_HWBLK_CLK(HWBLK_LCDC, &div4_clks[DIV4_B], 0), }; #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } -- cgit v0.10.2 From 098ec49b684313cbd2ba1e24db61cfda9788ff73 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Mon, 10 May 2010 14:01:55 +0000 Subject: sh: tie in div6 clocks using clkdev Use clkdev for div6 lookup on SH-Mobile processors: sh7343/sh7366/sh7722/sh7723/sh7724 Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c index a63cdca..9e4992a 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c @@ -21,6 +21,7 @@ #include #include #include +#include #include /* SH7343 registers */ @@ -135,8 +136,10 @@ struct clk div4_clks[DIV4_NR] = { [DIV4_SIUB] = DIV4("siub_clk", SCLKBCR, 0, 0x1fff, 0), }; -struct clk div6_clks[] = { - SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0), +enum { DIV6_V, DIV6_NR }; + +struct clk div6_clks[DIV6_NR] = { + [DIV6_V] = SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0), }; #define MSTP(_str, _parent, _reg, _bit, _flags) \ @@ -189,6 +192,13 @@ static struct clk mstp_clks[] = { MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0), }; +#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } + +static struct clk_lookup lookups[] = { + /* DIV6 clocks */ + CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]), +}; + int __init arch_clk_init(void) { int k, ret = 0; @@ -202,11 +212,13 @@ int __init arch_clk_init(void) for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++) ret = clk_register(main_clks[k]); + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); + if (!ret) ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table); if (!ret) - ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks)); + ret = sh_clk_div6_register(div6_clks, DIV6_NR); if (!ret) ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks)); diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c index f99db94..4eeeb24 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c @@ -21,6 +21,7 @@ #include #include #include +#include #include /* SH7366 registers */ @@ -138,8 +139,10 @@ struct clk div4_clks[DIV4_NR] = { [DIV4_SIUB] = DIV4("siub_clk", SCLKBCR, 0, 0x1fff, 0), }; -struct clk div6_clks[] = { - SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0), +enum { DIV6_V, DIV6_NR }; + +struct clk div6_clks[DIV6_NR] = { + [DIV6_V] = SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0), }; #define MSTP(_str, _parent, _reg, _bit, _flags) \ @@ -189,6 +192,13 @@ static struct clk mstp_clks[] = { MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0), }; +#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } + +static struct clk_lookup lookups[] = { + /* DIV6 clocks */ + CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]), +}; + int __init arch_clk_init(void) { int k, ret = 0; @@ -202,11 +212,13 @@ int __init arch_clk_init(void) for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++) ret = clk_register(main_clks[k]); + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); + if (!ret) ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table); if (!ret) - ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks)); + ret = sh_clk_div6_register(div6_clks, DIV6_NR); if (!ret) ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks)); diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c index 151bc3e..d8a7ad8 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c @@ -149,8 +149,10 @@ struct clk div4_reparent_clks[DIV4_REPARENT_NR] = { [DIV4_SIUB] = DIV4("siub_clk", SCLKBCR, 0, 0x1fff, 0), }; -struct clk div6_clks[] = { - SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0), +enum { DIV6_V, DIV6_NR }; + +struct clk div6_clks[DIV6_NR] = { + [DIV6_V] = SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0), }; static struct clk mstp_clks[HWBLK_NR] = { @@ -184,6 +186,9 @@ static struct clk mstp_clks[HWBLK_NR] = { #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } static struct clk_lookup lookups[] = { + /* DIV6 clocks */ + CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]), + /* MSTP clocks */ CLKDEV_CON_ID("uram0", &mstp_clks[HWBLK_URAM]), CLKDEV_CON_ID("xymem0", &mstp_clks[HWBLK_XYMEM]), @@ -265,7 +270,7 @@ int __init arch_clk_init(void) DIV4_REPARENT_NR, &div4_table); if (!ret) - ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks)); + ret = sh_clk_div6_register(div6_clks, DIV6_NR); if (!ret) ret = sh_hwblk_clk_register(mstp_clks, HWBLK_NR); diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c index b433185..edb2414 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c @@ -149,8 +149,10 @@ struct clk div4_reparent_clks[DIV4_REPARENT_NR] = { [DIV4_SIUA] = DIV4("siua_clk", SCLKACR, 0, 0x0dbf, 0), [DIV4_SIUB] = DIV4("siub_clk", SCLKBCR, 0, 0x0dbf, 0), }; -struct clk div6_clks[] = { - SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0), +enum { DIV6_V, DIV6_NR }; + +struct clk div6_clks[DIV6_NR] = { + [DIV6_V] = SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0), }; static struct clk mstp_clks[] = { @@ -209,6 +211,9 @@ static struct clk mstp_clks[] = { #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } static struct clk_lookup lookups[] = { + /* DIV6 clocks */ + CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]), + /* MSTP clocks */ CLKDEV_CON_ID("tlb0", &mstp_clks[HWBLK_TLB]), CLKDEV_CON_ID("ic0", &mstp_clks[HWBLK_IC]), @@ -341,7 +346,7 @@ int __init arch_clk_init(void) DIV4_REPARENT_NR, &div4_table); if (!ret) - ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks)); + ret = sh_clk_div6_register(div6_clks, DIV6_NR); if (!ret) ret = sh_hwblk_clk_register(mstp_clks, HWBLK_NR); diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c index 6f3d400..ad57c00 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c @@ -164,12 +164,17 @@ struct clk div4_clks[DIV4_NR] = { [DIV4_M1] = DIV4("vpu_clk", FRQCRB, 4, 0x2f7c, CLK_ENABLE_ON_INIT), }; -struct clk div6_clks[] = { - SH_CLK_DIV6("video_clk", &div3_clk, VCLKCR, 0), - SH_CLK_DIV6("fsia_clk", &div3_clk, FCLKACR, 0), - SH_CLK_DIV6("fsib_clk", &div3_clk, FCLKBCR, 0), - SH_CLK_DIV6("irda_clk", &div3_clk, IRDACLKCR, 0), - SH_CLK_DIV6("spu_clk", &div3_clk, SPUCLKCR, CLK_ENABLE_ON_INIT), +enum { DIV6_V, DIV6_FA, DIV6_FB, DIV6_I, DIV6_S, DIV6_NR }; + +#define DIV6(_str, _reg, _flags) \ + SH_CLK_DIV6(_str, &div3_clk, _reg, _flags) + +struct clk div6_clks[DIV6_NR] = { + [DIV6_V] = DIV6("video_clk", VCLKCR, 0), + [DIV6_FA] = DIV6("fsia_clk", FCLKACR, 0), + [DIV6_FB] = DIV6("fsib_clk", FCLKBCR, 0), + [DIV6_I] = DIV6("irda_clk", IRDACLKCR, 0), + [DIV6_S] = DIV6("spu_clk", SPUCLKCR, CLK_ENABLE_ON_INIT), }; static struct clk mstp_clks[HWBLK_NR] = { @@ -232,6 +237,13 @@ static struct clk mstp_clks[HWBLK_NR] = { #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } static struct clk_lookup lookups[] = { + /* DIV6 clocks */ + CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]), + CLKDEV_CON_ID("fsia_clk", &div6_clks[DIV6_FA]), + CLKDEV_CON_ID("fsib_clk", &div6_clks[DIV6_FB]), + CLKDEV_CON_ID("irda_clk", &div6_clks[DIV6_I]), + CLKDEV_CON_ID("spu_clk", &div6_clks[DIV6_S]), + /* MSTP clocks */ CLKDEV_CON_ID("tlb0", &mstp_clks[HWBLK_TLB]), CLKDEV_CON_ID("ic0", &mstp_clks[HWBLK_IC]), @@ -360,7 +372,7 @@ int __init arch_clk_init(void) ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table); if (!ret) - ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks)); + ret = sh_clk_div6_register(div6_clks, DIV6_NR); if (!ret) ret = sh_hwblk_clk_register(mstp_clks, HWBLK_NR); -- cgit v0.10.2 From 9e1985e13d42b4b66af94637346849565174309d Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Mon, 10 May 2010 14:02:09 +0000 Subject: sh: get rid of div6 clock names Get rid of div6 clock names on sh7343/sh7366/sh7722/sh7723/sh7724 Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/include/asm/clock.h b/arch/sh/include/asm/clock.h index 4b19179..405a12c 100644 --- a/arch/sh/include/asm/clock.h +++ b/arch/sh/include/asm/clock.h @@ -151,12 +151,11 @@ int sh_clk_div4_enable_register(struct clk *clks, int nr, int sh_clk_div4_reparent_register(struct clk *clks, int nr, struct clk_div4_table *table); -#define SH_CLK_DIV6(_name, _parent, _reg, _flags) \ -{ \ - .name = _name, \ - .parent = _parent, \ - .enable_reg = (void __iomem *)_reg, \ - .flags = _flags, \ +#define SH_CLK_DIV6(_parent, _reg, _flags) \ +{ \ + .parent = _parent, \ + .enable_reg = (void __iomem *)_reg, \ + .flags = _flags, \ } int sh_clk_div6_register(struct clk *clks, int nr); diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c index 9e4992a..a066c43 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c @@ -139,7 +139,7 @@ struct clk div4_clks[DIV4_NR] = { enum { DIV6_V, DIV6_NR }; struct clk div6_clks[DIV6_NR] = { - [DIV6_V] = SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0), + [DIV6_V] = SH_CLK_DIV6(&pll_clk, VCLKCR, 0), }; #define MSTP(_str, _parent, _reg, _bit, _flags) \ diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c index 4eeeb24..44cc5a0 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c @@ -142,7 +142,7 @@ struct clk div4_clks[DIV4_NR] = { enum { DIV6_V, DIV6_NR }; struct clk div6_clks[DIV6_NR] = { - [DIV6_V] = SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0), + [DIV6_V] = SH_CLK_DIV6(&pll_clk, VCLKCR, 0), }; #define MSTP(_str, _parent, _reg, _bit, _flags) \ diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c index d8a7ad8..2798cea 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c @@ -152,7 +152,7 @@ struct clk div4_reparent_clks[DIV4_REPARENT_NR] = { enum { DIV6_V, DIV6_NR }; struct clk div6_clks[DIV6_NR] = { - [DIV6_V] = SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0), + [DIV6_V] = SH_CLK_DIV6(&pll_clk, VCLKCR, 0), }; static struct clk mstp_clks[HWBLK_NR] = { diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c index edb2414..500715f 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c @@ -152,7 +152,7 @@ struct clk div4_reparent_clks[DIV4_REPARENT_NR] = { enum { DIV6_V, DIV6_NR }; struct clk div6_clks[DIV6_NR] = { - [DIV6_V] = SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0), + [DIV6_V] = SH_CLK_DIV6(&pll_clk, VCLKCR, 0), }; static struct clk mstp_clks[] = { diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c index ad57c00..2bbff53 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c @@ -166,15 +166,12 @@ struct clk div4_clks[DIV4_NR] = { enum { DIV6_V, DIV6_FA, DIV6_FB, DIV6_I, DIV6_S, DIV6_NR }; -#define DIV6(_str, _reg, _flags) \ - SH_CLK_DIV6(_str, &div3_clk, _reg, _flags) - struct clk div6_clks[DIV6_NR] = { - [DIV6_V] = DIV6("video_clk", VCLKCR, 0), - [DIV6_FA] = DIV6("fsia_clk", FCLKACR, 0), - [DIV6_FB] = DIV6("fsib_clk", FCLKBCR, 0), - [DIV6_I] = DIV6("irda_clk", IRDACLKCR, 0), - [DIV6_S] = DIV6("spu_clk", SPUCLKCR, CLK_ENABLE_ON_INIT), + [DIV6_V] = SH_CLK_DIV6(&div3_clk, VCLKCR, 0), + [DIV6_FA] = SH_CLK_DIV6(&div3_clk, FCLKACR, 0), + [DIV6_FB] = SH_CLK_DIV6(&div3_clk, FCLKBCR, 0), + [DIV6_I] = SH_CLK_DIV6(&div3_clk, IRDACLKCR, 0), + [DIV6_S] = SH_CLK_DIV6(&div3_clk, SPUCLKCR, CLK_ENABLE_ON_INIT), }; static struct clk mstp_clks[HWBLK_NR] = { -- cgit v0.10.2 From 4f615d575c17195f975cf8314be54f362d859a3f Mon Sep 17 00:00:00 2001 From: Hiroshi DOYU Date: Mon, 10 May 2010 14:50:55 +0300 Subject: sh: clkfwk: Use debugfs_remove_recursive() for rewinding Rewinding each debugfs entries to unregister if an error happens. Based on the commit ca4caa4e1d45f9542fa54263974d0ef637157b4a Signed-off-by: Hiroshi DOYU Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c index 073f4ff..a725c7f 100644 --- a/arch/sh/kernel/cpu/clock.c +++ b/arch/sh/kernel/cpu/clock.c @@ -621,7 +621,7 @@ static int __init clk_debugfs_init(void) } return 0; err_out: - debugfs_remove(clk_debugfs_root); /* REVISIT: Cleanup correctly */ + debugfs_remove_recursive(clk_debugfs_root); return err; } late_initcall(clk_debugfs_init); -- cgit v0.10.2 From c9ff04c941d2cd87d27496d7fee8923238bb2ebb Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 11 May 2010 14:01:45 +1000 Subject: drm/radeon: Fix 3 regressions - since buffer rework Commit b4fe945405e477cded91772b4fec854705443dd5 introduced 3 bugs, fix them: * Use the right command dword for second packet offset in RADEON_CNTL_PAINT/BITBLT_MULTI. * Don't leak memory if drm_buffer_copy_from_user() fails. * Don't call drm_buffer_unprocessed() unless drm_buffer_alloc() and drm_buffer_copy_from_user() have been called successfully first. Signed-off-by: Jean Delvare Cc: Pauli Nieminen Signed-off-by: Dave Airlie diff --git a/drivers/gpu/drm/radeon/radeon_state.c b/drivers/gpu/drm/radeon/radeon_state.c index 40ab6d9..cc5316d 100644 --- a/drivers/gpu/drm/radeon/radeon_state.c +++ b/drivers/gpu/drm/radeon/radeon_state.c @@ -424,7 +424,7 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t * if ((*cmd & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) && (*cmd & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { u32 *cmd3 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 3); - offset = *cmd << 10; + offset = *cmd3 << 10; if (radeon_check_and_fixup_offset (dev_priv, file_priv, &offset)) { DRM_ERROR("Invalid second packet offset\n"); @@ -2895,9 +2895,12 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, return rv; rv = drm_buffer_copy_from_user(cmdbuf->buffer, buffer, cmdbuf->bufsz); - if (rv) + if (rv) { + drm_buffer_free(cmdbuf->buffer); return rv; - } + } + } else + goto done; orig_nbox = cmdbuf->nbox; @@ -2905,8 +2908,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, int temp; temp = r300_do_cp_cmdbuf(dev, file_priv, cmdbuf); - if (cmdbuf->bufsz != 0) - drm_buffer_free(cmdbuf->buffer); + drm_buffer_free(cmdbuf->buffer); return temp; } @@ -3012,16 +3014,15 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, } } - if (cmdbuf->bufsz != 0) - drm_buffer_free(cmdbuf->buffer); + drm_buffer_free(cmdbuf->buffer); + done: DRM_DEBUG("DONE\n"); COMMIT_RING(); return 0; err: - if (cmdbuf->bufsz != 0) - drm_buffer_free(cmdbuf->buffer); + drm_buffer_free(cmdbuf->buffer); return -EINVAL; } -- cgit v0.10.2 From 4bc277ac9cae60e11fe2e557e4ea4acb56d3dc9a Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 11 May 2010 13:32:19 +0900 Subject: sh: bootmem refactoring. This reworks much of the bootmem setup and initialization code allowing us to get rid of duplicate work between the NUMA and non-NUMA cases. The end result is that we end up with a much more flexible interface for supporting more complex topologies (fake NUMA, highmem, etc, etc.) which is entirely LMB backed. This is an incremental step for more NUMA work as well as gradually enabling migration off of bootmem entirely. Signed-off-by: Paul Mundt diff --git a/arch/sh/include/asm/mmzone.h b/arch/sh/include/asm/mmzone.h index 94f04b2..8887baf 100644 --- a/arch/sh/include/asm/mmzone.h +++ b/arch/sh/include/asm/mmzone.h @@ -44,6 +44,8 @@ void __init plat_mem_setup(void); /* arch/sh/kernel/setup.c */ void __init __add_active_range(unsigned int nid, unsigned long start_pfn, unsigned long end_pfn); +/* arch/sh/mm/init.c */ +void __init allocate_pgdat(unsigned int nid); #endif /* __KERNEL__ */ #endif /* __ASM_SH_MMZONE_H */ diff --git a/arch/sh/include/asm/setup.h b/arch/sh/include/asm/setup.h index 4758325..01fa17a 100644 --- a/arch/sh/include/asm/setup.h +++ b/arch/sh/include/asm/setup.h @@ -19,6 +19,7 @@ #define COMMAND_LINE ((char *) (PARAM+0x100)) void sh_mv_setup(void); +void check_for_initrd(void); #endif /* __KERNEL__ */ diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index f6a2db1..61404ed 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -114,31 +114,7 @@ static int __init early_parse_mem(char *p) } early_param("mem", early_parse_mem); -/* - * Register fully available low RAM pages with the bootmem allocator. - */ -static void __init register_bootmem_low_pages(void) -{ - unsigned long curr_pfn, last_pfn, pages; - - /* - * We are rounding up the start address of usable memory: - */ - curr_pfn = PFN_UP(__MEMORY_START); - - /* - * ... and at the end of the usable range downwards: - */ - last_pfn = PFN_DOWN(__pa(memory_end)); - - if (last_pfn > max_low_pfn) - last_pfn = max_low_pfn; - - pages = last_pfn - curr_pfn; - free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(pages)); -} - -static void __init check_for_initrd(void) +void __init check_for_initrd(void) { #ifdef CONFIG_BLK_DEV_INITRD unsigned long start, end; @@ -240,85 +216,6 @@ void __init __add_active_range(unsigned int nid, unsigned long start_pfn, add_active_range(nid, start_pfn, end_pfn); } -void __init do_init_bootmem(void) -{ - unsigned long bootmap_size; - unsigned long bootmap_pages, bootmem_paddr; - u64 total_pages = lmb_phys_mem_size() >> PAGE_SHIFT; - int i; - - bootmap_pages = bootmem_bootmap_pages(total_pages); - - bootmem_paddr = lmb_alloc(bootmap_pages << PAGE_SHIFT, PAGE_SIZE); - - /* - * Find a proper area for the bootmem bitmap. After this - * bootstrap step all allocations (until the page allocator - * is intact) must be done via bootmem_alloc(). - */ - bootmap_size = init_bootmem_node(NODE_DATA(0), - bootmem_paddr >> PAGE_SHIFT, - min_low_pfn, max_low_pfn); - - /* Add active regions with valid PFNs. */ - for (i = 0; i < lmb.memory.cnt; i++) { - unsigned long start_pfn, end_pfn; - start_pfn = lmb.memory.region[i].base >> PAGE_SHIFT; - end_pfn = start_pfn + lmb_size_pages(&lmb.memory, i); - __add_active_range(0, start_pfn, end_pfn); - } - - /* - * Add all physical memory to the bootmem map and mark each - * area as present. - */ - register_bootmem_low_pages(); - - /* Reserve the sections we're already using. */ - for (i = 0; i < lmb.reserved.cnt; i++) - reserve_bootmem(lmb.reserved.region[i].base, - lmb_size_bytes(&lmb.reserved, i), - BOOTMEM_DEFAULT); - - node_set_online(0); - - sparse_memory_present_with_active_regions(0); -} - -static void __init early_reserve_mem(void) -{ - unsigned long start_pfn; - - /* - * Partially used pages are not usable - thus - * we are rounding upwards: - */ - start_pfn = PFN_UP(__pa(_end)); - - /* - * Reserve the kernel text and - * Reserve the bootmem bitmap. We do this in two steps (first step - * was init_bootmem()), because this catches the (definitely buggy) - * case of us accidentally initializing the bootmem allocator with - * an invalid RAM area. - */ - lmb_reserve(__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET, - (PFN_PHYS(start_pfn) + PAGE_SIZE - 1) - - (__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET)); - - /* - * Reserve physical pages below CONFIG_ZERO_PAGE_OFFSET. - */ - if (CONFIG_ZERO_PAGE_OFFSET != 0) - lmb_reserve(__MEMORY_START, CONFIG_ZERO_PAGE_OFFSET); - - /* - * Handle additional early reservations - */ - check_for_initrd(); - reserve_crashkernel(); -} - /* * Note: elfcorehdr_addr is not just limited to vmcore. It is also used by * is_kdump_kernel() to determine if we are booting after a panic. Hence @@ -342,10 +239,6 @@ void __init __weak plat_early_device_setup(void) { } -void __init __weak plat_mem_setup(void) -{ -} - void __init setup_arch(char **cmdline_p) { enable_mmu(); @@ -401,44 +294,16 @@ void __init setup_arch(char **cmdline_p) plat_early_device_setup(); - /* Let earlyprintk output early console messages */ - early_platform_driver_probe("earlyprintk", 1, 1); - - lmb_init(); - sh_mv_setup(); - sh_mv.mv_mem_init(); - - early_reserve_mem(); - lmb_enforce_memory_limit(memory_limit); - lmb_analyze(); - - lmb_dump_all(); - - /* - * Determine low and high memory ranges: - */ - max_low_pfn = max_pfn = lmb_end_of_DRAM() >> PAGE_SHIFT; - min_low_pfn = __MEMORY_START >> PAGE_SHIFT; - - nodes_clear(node_online_map); - - memory_start = (unsigned long)__va(__MEMORY_START); - memory_end = memory_start + (memory_limit ?: lmb_phys_mem_size()); + /* Let earlyprintk output early console messages */ + early_platform_driver_probe("earlyprintk", 1, 1); - uncached_init(); - pmb_init(); - do_init_bootmem(); - plat_mem_setup(); - sparse_init(); + paging_init(); #ifdef CONFIG_DUMMY_CONSOLE conswitchp = &dummy_con; #endif - paging_init(); - - ioremap_fixed_init(); /* Perform the machine specific initialisation */ if (likely(sh_mv.mv_setup)) diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c index 9c5400b..7f3cb52 100644 --- a/arch/sh/mm/init.c +++ b/arch/sh/mm/init.c @@ -17,11 +17,14 @@ #include #include #include +#include #include #include +#include #include #include #include +#include #include #include @@ -33,6 +36,11 @@ void __init generic_mem_init(void) lmb_add(__MEMORY_START, __MEMORY_SIZE); } +void __init __weak plat_mem_setup(void) +{ + /* Nothing to see here, move along. */ +} + #ifdef CONFIG_MMU static pte_t *__get_pte_phys(unsigned long addr) { @@ -158,15 +166,166 @@ void __init page_table_range_init(unsigned long start, unsigned long end, } #endif /* CONFIG_MMU */ -/* - * paging_init() sets up the page tables - */ +void __init allocate_pgdat(unsigned int nid) +{ + unsigned long start_pfn, end_pfn; +#ifdef CONFIG_NEED_MULTIPLE_NODES + unsigned long phys; +#endif + + get_pfn_range_for_nid(nid, &start_pfn, &end_pfn); + +#ifdef CONFIG_NEED_MULTIPLE_NODES + phys = __lmb_alloc_base(sizeof(struct pglist_data), + SMP_CACHE_BYTES, end_pfn << PAGE_SHIFT); + /* Retry with all of system memory */ + if (!phys) + phys = __lmb_alloc_base(sizeof(struct pglist_data), + SMP_CACHE_BYTES, lmb_end_of_DRAM()); + if (!phys) + panic("Can't allocate pgdat for node %d\n", nid); + + NODE_DATA(nid) = __va(phys); + memset(NODE_DATA(nid), 0, sizeof(struct pglist_data)); + + NODE_DATA(nid)->bdata = &bootmem_node_data[nid]; +#endif + + NODE_DATA(nid)->node_start_pfn = start_pfn; + NODE_DATA(nid)->node_spanned_pages = end_pfn - start_pfn; +} + +static void __init bootmem_init_one_node(unsigned int nid) +{ + unsigned long total_pages, paddr; + unsigned long end_pfn; + struct pglist_data *p; + int i; + + p = NODE_DATA(nid); + + /* Nothing to do.. */ + if (!p->node_spanned_pages) + return; + + end_pfn = p->node_start_pfn + p->node_spanned_pages; + + total_pages = bootmem_bootmap_pages(p->node_spanned_pages); + + paddr = lmb_alloc(total_pages << PAGE_SHIFT, PAGE_SIZE); + if (!paddr) + panic("Can't allocate bootmap for nid[%d]\n", nid); + + init_bootmem_node(p, paddr >> PAGE_SHIFT, p->node_start_pfn, end_pfn); + + free_bootmem_with_active_regions(nid, end_pfn); + + /* + * XXX Handle initial reservations for the system memory node + * only for the moment, we'll refactor this later for handling + * reservations in other nodes. + */ + if (nid == 0) { + /* Reserve the sections we're already using. */ + for (i = 0; i < lmb.reserved.cnt; i++) + reserve_bootmem(lmb.reserved.region[i].base, + lmb_size_bytes(&lmb.reserved, i), + BOOTMEM_DEFAULT); + } + + sparse_memory_present_with_active_regions(nid); +} + +static void __init do_init_bootmem(void) +{ + int i; + + /* Add active regions with valid PFNs. */ + for (i = 0; i < lmb.memory.cnt; i++) { + unsigned long start_pfn, end_pfn; + start_pfn = lmb.memory.region[i].base >> PAGE_SHIFT; + end_pfn = start_pfn + lmb_size_pages(&lmb.memory, i); + __add_active_range(0, start_pfn, end_pfn); + } + + /* All of system RAM sits in node 0 for the non-NUMA case */ + allocate_pgdat(0); + node_set_online(0); + + plat_mem_setup(); + + for_each_online_node(i) + bootmem_init_one_node(i); + + sparse_init(); +} + +static void __init early_reserve_mem(void) +{ + unsigned long start_pfn; + + /* + * Partially used pages are not usable - thus + * we are rounding upwards: + */ + start_pfn = PFN_UP(__pa(_end)); + + /* + * Reserve the kernel text and Reserve the bootmem bitmap. We do + * this in two steps (first step was init_bootmem()), because + * this catches the (definitely buggy) case of us accidentally + * initializing the bootmem allocator with an invalid RAM area. + */ + lmb_reserve(__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET, + (PFN_PHYS(start_pfn) + PAGE_SIZE - 1) - + (__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET)); + + /* + * Reserve physical pages below CONFIG_ZERO_PAGE_OFFSET. + */ + if (CONFIG_ZERO_PAGE_OFFSET != 0) + lmb_reserve(__MEMORY_START, CONFIG_ZERO_PAGE_OFFSET); + + /* + * Handle additional early reservations + */ + check_for_initrd(); + reserve_crashkernel(); +} + void __init paging_init(void) { unsigned long max_zone_pfns[MAX_NR_ZONES]; unsigned long vaddr, end; int nid; + lmb_init(); + + sh_mv.mv_mem_init(); + + early_reserve_mem(); + + lmb_enforce_memory_limit(memory_limit); + lmb_analyze(); + + lmb_dump_all(); + + /* + * Determine low and high memory ranges: + */ + max_low_pfn = max_pfn = lmb_end_of_DRAM() >> PAGE_SHIFT; + min_low_pfn = __MEMORY_START >> PAGE_SHIFT; + + nodes_clear(node_online_map); + + memory_start = (unsigned long)__va(__MEMORY_START); + memory_end = memory_start + (memory_limit ?: lmb_phys_mem_size()); + + uncached_init(); + pmb_init(); + do_init_bootmem(); + ioremap_fixed_init(); + /* We don't need to map the kernel through the TLB, as * it is permanatly mapped using P1. So clear the * entire pgd. */ -- cgit v0.10.2 From dfbca89987b74c34d9b1a2414b0e5ccee65347e0 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 11 May 2010 13:50:29 +0900 Subject: sh: Reject small mappings for PMB bolting. The minimum section size for the PMB is 16M, so just always error out early if the specified size is too small. This permits us to unconditionally call in to pmb_bolt_mapping() with variable sizes without wasting a TLB and cache flush for the range. Signed-off-by: Paul Mundt diff --git a/arch/sh/mm/pmb.c b/arch/sh/mm/pmb.c index e9f5384..18623ba 100644 --- a/arch/sh/mm/pmb.c +++ b/arch/sh/mm/pmb.c @@ -341,6 +341,8 @@ int pmb_bolt_mapping(unsigned long vaddr, phys_addr_t phys, unsigned long flags, pmb_flags; int i, mapped; + if (size < SZ_16M) + return -EINVAL; if (!pmb_addr_valid(vaddr, size)) return -EFAULT; if (pmb_mapping_exists(vaddr, phys, size)) -- cgit v0.10.2 From 21823259a70b7a2a21eea1d48c25a6f38896dd11 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 11 May 2010 13:52:50 +0900 Subject: sh: Ensure active regions have a backing PMB entry. In the NUMA or memory hot-add case where system memory has been partitioned up, we immediately run in to a situation where the existing PMB entry doesn't cover the new range (primarily as a result of the entry size being shrunk to match the node size early in the initialization). In order to fix this up it's necessary to preload a PMB mapping for the new range prior to activation in order to circumvent reset by MMU. Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 61404ed..57bd938 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -191,13 +191,18 @@ void __init __add_active_range(unsigned int nid, unsigned long start_pfn, unsigned long end_pfn) { struct resource *res = &mem_resources[nid]; + unsigned long start, end; WARN_ON(res->name); /* max one active range per node for now */ + start = start_pfn << PAGE_SHIFT; + end = end_pfn << PAGE_SHIFT; + res->name = "System RAM"; - res->start = start_pfn << PAGE_SHIFT; - res->end = (end_pfn << PAGE_SHIFT) - 1; + res->start = start; + res->end = end - 1; res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; + if (request_resource(&iomem_resource, res)) { pr_err("unable to request memory_resource 0x%lx 0x%lx\n", start_pfn, end_pfn); @@ -213,6 +218,14 @@ void __init __add_active_range(unsigned int nid, unsigned long start_pfn, request_resource(res, &data_resource); request_resource(res, &bss_resource); + /* + * Also make sure that there is a PMB mapping that covers this + * range before we attempt to activate it, to avoid reset by MMU. + * We can hit this path with NUMA or memory hot-add. + */ + pmb_bolt_mapping((unsigned long)__va(start), start, end - start, + PAGE_KERNEL); + add_active_range(nid, start_pfn, end_pfn); } -- cgit v0.10.2 From d861f7bf14808b9f457cb32c34585e97df60f140 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 10 May 2010 15:35:11 -0700 Subject: Input: iforce - add Guillemot Jet Leader Force Feedback This device features a RUDDER on the knob. Signed-off-by: Marek Vasut Signed-off-by: Dmitry Torokhov diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index b1edd77..5956d89 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c @@ -54,6 +54,9 @@ static signed short btn_avb_wheel[] = static signed short abs_joystick[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, -1 }; +static signed short abs_joystick_rudder[] = +{ ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER, ABS_HAT0X, ABS_HAT0Y, -1 }; + static signed short abs_avb_pegasus[] = { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, -1 }; @@ -76,6 +79,7 @@ static struct iforce_device iforce_device[] = { { 0x061c, 0xc0a4, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, //? { 0x061c, 0xc084, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, { 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, //? + { 0x06f8, 0x0001, "Guillemot Jet Leader Force Feedback", btn_joystick, abs_joystick_rudder, ff_iforce }, { 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //? { 0x06f8, 0x0004, "Gullemot Jet Leader 3D", btn_joystick, abs_joystick, ff_iforce }, //? { 0x06d6, 0x29bc, "Trust Force Feedback Race Master", btn_wheel, abs_wheel, ff_iforce }, diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c index b41303d..6c96631 100644 --- a/drivers/input/joystick/iforce/iforce-usb.c +++ b/drivers/input/joystick/iforce/iforce-usb.c @@ -212,6 +212,7 @@ static struct usb_device_id iforce_usb_ids [] = { { USB_DEVICE(0x061c, 0xc0a4) }, /* ACT LABS Force RS */ { USB_DEVICE(0x061c, 0xc084) }, /* ACT LABS Force RS */ { USB_DEVICE(0x06f8, 0x0001) }, /* Guillemot Race Leader Force Feedback */ + { USB_DEVICE(0x06f8, 0x0003) }, /* Guillemot Jet Leader Force Feedback */ { USB_DEVICE(0x06f8, 0x0004) }, /* Guillemot Force Feedback Racing Wheel */ { USB_DEVICE(0x06f8, 0xa302) }, /* Guillemot Jet Leader 3D */ { } /* Terminating entry */ -- cgit v0.10.2 From 513d8be9883fe0a7a73d216c7cecd20e7c9effda Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 10 May 2010 15:35:11 -0700 Subject: Input: iforce - fix Guillemot Jet Leader 3D entry USB ID entry for "Guillemot Jet Leader 3D" in iforce-main.c did not match one used in iforce-usb.c Signed-off-by: Marek Vasut Signed-off-by: Dmitry Torokhov diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index 5956d89..405febd 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c @@ -81,7 +81,7 @@ static struct iforce_device iforce_device[] = { { 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, //? { 0x06f8, 0x0001, "Guillemot Jet Leader Force Feedback", btn_joystick, abs_joystick_rudder, ff_iforce }, { 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //? - { 0x06f8, 0x0004, "Gullemot Jet Leader 3D", btn_joystick, abs_joystick, ff_iforce }, //? + { 0x06f8, 0xa302, "Guillemot Jet Leader 3D", btn_joystick, abs_joystick, ff_iforce }, //? { 0x06d6, 0x29bc, "Trust Force Feedback Race Master", btn_wheel, abs_wheel, ff_iforce }, { 0x0000, 0x0000, "Unknown I-Force Device [%04x:%04x]", btn_joystick, abs_joystick, ff_iforce } }; -- cgit v0.10.2 From 0ebf9e3692d640917fb792a7494d05e1f5b1058f Mon Sep 17 00:00:00 2001 From: Daniel T Chen Date: Mon, 10 May 2010 21:50:04 +0200 Subject: ALSA: hda: Fix 0 dB for Lenovo models using Conexant CX20549 (Venice) Reference: http://mailman.alsa-project.org/pipermail/alsa-devel/2010-May/027525.html As reported on the mailing list, we also need to cap to the 0 dB offset for Lenovo models, else the sound will be distorted. Reported-and-Tested-by: Tim Starling Cc: Signed-off-by: Daniel T Chen Signed-off-by: Takashi Iwai diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index d8213e2..feabb44 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -1197,9 +1197,10 @@ static int patch_cxt5045(struct hda_codec *codec) case 0x103c: case 0x1631: case 0x1734: - /* HP, Packard Bell, & Fujitsu-Siemens laptops have really bad - * sound over 0dB on NID 0x17. Fix max PCM level to 0 dB - * (originally it has 0x2b steps with 0dB offset 0x14) + case 0x17aa: + /* HP, Packard Bell, Fujitsu-Siemens & Lenovo laptops have + * really bad sound over 0dB on NID 0x17. Fix max PCM level to + * 0 dB (originally it has 0x2b steps with 0dB offset 0x14) */ snd_hda_override_amp_caps(codec, 0x17, HDA_INPUT, (0x14 << AC_AMPCAP_OFFSET_SHIFT) | -- cgit v0.10.2 From 4b478ee2a1251d99813a90afeb0f809b3a8b04fb Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 11 May 2010 15:24:04 +0900 Subject: sh: All SH-X3 cores support NUMA and SMP, update Kconfig. Signed-off-by: Paul Mundt diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index c2325bd..67ca505 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -236,6 +236,8 @@ config CPU_SHX2 config CPU_SHX3 bool select DMA_COHERENT + select SYS_SUPPORTS_SMP + select SYS_SUPPORTS_NUMA config ARCH_SHMOBILE bool @@ -452,18 +454,12 @@ config CPU_SUBTYPE_SH7786 select CPU_SH4A select CPU_SHX3 select CPU_HAS_PTEAEX - select ARCH_SPARSEMEM_ENABLE - select SYS_SUPPORTS_NUMA - select SYS_SUPPORTS_SMP select GENERIC_CLOCKEVENTS_BROADCAST if SMP config CPU_SUBTYPE_SHX3 bool "Support SH-X3 processor" select CPU_SH4A select CPU_SHX3 - select ARCH_SPARSEMEM_ENABLE - select SYS_SUPPORTS_NUMA - select SYS_SUPPORTS_SMP select GENERIC_CLOCKEVENTS_BROADCAST if SMP # SH4AL-DSP Processor Support -- cgit v0.10.2 From e3174cfd2a1e28fff774681f00a0eef3d31da970 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 11 May 2010 08:31:49 +0200 Subject: Revert "perf: Fix exit() vs PERF_FORMAT_GROUP" This reverts commit 4fd38e4595e2f6c9d27732c042a0e16b2753049c. It causes various crashes and hangs when events are activated. The cause is not fully understood yet but we need to revert it because the effects are severe. Reported-by: Stephane Eranian Reported-by: Lin Ming Cc: Peter Zijlstra Cc: Corey Ashford Cc: Mike Galbraith Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo Cc: Frederic Weisbecker LKML-Reference: Signed-off-by: Ingo Molnar diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 4924c96..3fd5c82 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -575,7 +575,6 @@ struct pmu { * enum perf_event_active_state - the states of a event */ enum perf_event_active_state { - PERF_EVENT_STATE_FREE = -3, PERF_EVENT_STATE_ERROR = -2, PERF_EVENT_STATE_OFF = -1, PERF_EVENT_STATE_INACTIVE = 0, diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 180151f..a904746 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -334,9 +334,6 @@ list_del_event(struct perf_event *event, struct perf_event_context *ctx) if (event->state > PERF_EVENT_STATE_OFF) event->state = PERF_EVENT_STATE_OFF; - if (event->state > PERF_EVENT_STATE_FREE) - return; - /* * If this was a group event with sibling events then * upgrade the siblings to singleton events by adding them @@ -1871,8 +1868,6 @@ int perf_event_release_kernel(struct perf_event *event) { struct perf_event_context *ctx = event->ctx; - event->state = PERF_EVENT_STATE_FREE; - WARN_ON_ONCE(ctx->parent_ctx); /* * There are two ways this annotation is useful: -- cgit v0.10.2 From 26ebe0a28986f4845b2c5bea43ac5cc0b9f27f0a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 11 May 2010 08:36:29 +0200 Subject: ALSA: hda - Fix mute-LED GPIO pin for HP dv series Old HP dv series seem to use the GPIO pin 0 for controlling the mute LED although the pin is a large package, where the newer models use GPIO 3 in such a case. For fixing the regression from the previous kernels, set spec->gpio_led statically for these model quirks. Signed-off-by: Takashi Iwai diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 12825aa0..eb4ea3d 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -4766,6 +4766,9 @@ static void set_hp_led_gpio(struct hda_codec *codec) struct sigmatel_spec *spec = codec->spec; unsigned int gpio; + if (spec->gpio_led) + return; + gpio = snd_hda_param_read(codec, codec->afg, AC_PAR_GPIO_CAP); gpio &= AC_GPIO_IO_COUNT; if (gpio > 3) @@ -5683,11 +5686,13 @@ again: * detection. */ spec->hp_detect = 1; + spec->gpio_led = 0x01; break; case STAC_HP_HDX: spec->num_dmics = 1; spec->num_dmuxes = 1; spec->num_smuxes = 1; + spec->gpio_led = 0x08; break; } -- cgit v0.10.2 From de068ec048f807d4f62b7dda100c23a1365f086f Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Wed, 5 May 2010 22:07:39 +0200 Subject: perf: Fix static strings treated like dynamic ones The raw_field_ptr() helper, used to retrieve the address of a field inside a trace event, treats every strings as if they were dynamic ie: having a secondary level of indirection to retrieve their contents. FIELD_IS_STRING doesn't mean FIELD_IS_DYNAMIC, we only need to compute the secondary dereference for the latter case. This fixes perf sched segfaults, bad cmdline report and may be some other bugs. Reported-by: Jason Baron Reported-by: Arnaldo Carvalho de Melo Signed-off-by: Frederic Weisbecker Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Tom Zanussi diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index 9b3c20f..613c9cc 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c @@ -1925,7 +1925,7 @@ void *raw_field_ptr(struct event *event, const char *name, void *data) if (!field) return NULL; - if (field->flags & FIELD_IS_STRING) { + if (field->flags & FIELD_IS_DYNAMIC) { int offset; offset = *(int *)(data + field->offset); -- cgit v0.10.2 From 829e92458532b1dbfeb972435d45bb060cdbf5a3 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Tue, 27 Apr 2010 18:33:49 -0400 Subject: kprobes/x86: Fix removed int3 checking order Fix kprobe/x86 to check removed int3 when failing to get kprobe from hlist. Since we have a time window between checking int3 exists on probed address and getting kprobe on that address, we can have following scenario: ------- CPU1 CPU2 hit int3 check int3 exists remove int3 remove kprobe from hlist get kprobe from hlist no kprobe->OOPS! ------- This patch moves int3 checking if there is no kprobe on that address for fixing this problem as follows: ------ CPU1 CPU2 hit int3 remove int3 remove kprobe from hlist get kprobe from hlist no kprobe->check int3 exists ->rollback&retry ------ Signed-off-by: Masami Hiramatsu Acked-by: Ananth N Mavinakayanahalli Cc: systemtap Cc: DLE Cc: Dave Anderson Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo Cc: Frederic Weisbecker LKML-Reference: <20100427223348.2322.9112.stgit@localhost6.localdomain6> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c index b43bbae..1658efd 100644 --- a/arch/x86/kernel/kprobes.c +++ b/arch/x86/kernel/kprobes.c @@ -534,20 +534,6 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) struct kprobe_ctlblk *kcb; addr = (kprobe_opcode_t *)(regs->ip - sizeof(kprobe_opcode_t)); - if (*addr != BREAKPOINT_INSTRUCTION) { - /* - * The breakpoint instruction was removed right - * after we hit it. Another cpu has removed - * either a probepoint or a debugger breakpoint - * at this address. In either case, no further - * handling of this interrupt is appropriate. - * Back up over the (now missing) int3 and run - * the original instruction. - */ - regs->ip = (unsigned long)addr; - return 1; - } - /* * We don't want to be preempted for the entire * duration of kprobe processing. We conditionally @@ -579,6 +565,19 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) setup_singlestep(p, regs, kcb, 0); return 1; } + } else if (*addr != BREAKPOINT_INSTRUCTION) { + /* + * The breakpoint instruction was removed right + * after we hit it. Another cpu has removed + * either a probepoint or a debugger breakpoint + * at this address. In either case, no further + * handling of this interrupt is appropriate. + * Back up over the (now missing) int3 and run + * the original instruction. + */ + regs->ip = (unsigned long)addr; + preempt_enable_no_resched(); + return 1; } else if (kprobe_running()) { p = __get_cpu_var(current_kprobe); if (p->break_handler && p->break_handler(p, regs)) { -- cgit v0.10.2 From d1bf8cf6b911001d50f2079c158cb5dd9782e187 Mon Sep 17 00:00:00 2001 From: Ken Milmore Date: Tue, 11 May 2010 09:17:46 +0200 Subject: hwmon: (asc7621) Bug fixes * Allow fan minimum RPM to be set to zero without triggering alarms. * Fix voltage scaling arithmetic and correct scale factors. * Correct fan1-fan4 alarm bit shifts. * Correct register address for temp3_smoothing_enable. * Read the alarm registers with high priority. Signed-off-by: Ken Milmore Signed-off-by: Jean Delvare diff --git a/drivers/hwmon/asc7621.c b/drivers/hwmon/asc7621.c index 7f94810..0f388ad 100644 --- a/drivers/hwmon/asc7621.c +++ b/drivers/hwmon/asc7621.c @@ -268,8 +268,11 @@ static ssize_t store_fan16(struct device *dev, if (strict_strtol(buf, 10, &reqval)) return -EINVAL; + /* If a minimum RPM of zero is requested, then we set the register to + 0xffff. This value allows the fan to be stopped completely without + generating an alarm. */ reqval = - (SENSORS_LIMIT((reqval) <= 0 ? 0 : 5400000 / (reqval), 0, 65534)); + (reqval <= 0 ? 0xffff : SENSORS_LIMIT(5400000 / reqval, 0, 0xfffe)); mutex_lock(&data->update_lock); data->reg[param->msb[0]] = (reqval >> 8) & 0xff; @@ -285,8 +288,9 @@ static ssize_t store_fan16(struct device *dev, * Voltages are scaled in the device so that the nominal voltage * is 3/4ths of the 0-255 range (i.e. 192). * If all voltages are 'normal' then all voltage registers will - * read 0xC0. This doesn't help us if we don't have a point of refernce. - * The data sheet however provides us with the full scale value for each + * read 0xC0. + * + * The data sheet provides us with the 3/4 scale value for each voltage * which is stored in in_scaling. The sda->index parameter value provides * the index into in_scaling. * @@ -295,7 +299,7 @@ static ssize_t store_fan16(struct device *dev, */ static int asc7621_in_scaling[] = { - 3320, 3000, 4380, 6640, 16000 + 2500, 2250, 3300, 5000, 12000 }; static ssize_t show_in10(struct device *dev, struct device_attribute *attr, @@ -306,19 +310,12 @@ static ssize_t show_in10(struct device *dev, struct device_attribute *attr, u8 nr = sda->index; mutex_lock(&data->update_lock); - regval = (data->reg[param->msb[0]] * asc7621_in_scaling[nr]) / 256; - - /* The LSB value is a 2-bit scaling of the MSB's LSbit value. - * I.E. If the maximim voltage for this input is 6640 millivolts then - * a MSB register value of 0 = 0mv and 255 = 6640mv. - * A 1 step change therefore represents 25.9mv (6640 / 256). - * The extra 2-bits therefore represent increments of 6.48mv. - */ - regval += ((asc7621_in_scaling[nr] / 256) / 4) * - (data->reg[param->lsb[0]] >> 6); - + regval = (data->reg[param->msb[0]] << 8) | (data->reg[param->lsb[0]]); mutex_unlock(&data->update_lock); + /* The LSB value is a 2-bit scaling of the MSB's LSbit value. */ + regval = (regval >> 6) * asc7621_in_scaling[nr] / (0xc0 << 2); + return sprintf(buf, "%u\n", regval); } @@ -331,7 +328,7 @@ static ssize_t show_in8(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%u\n", ((data->reg[param->msb[0]] * - asc7621_in_scaling[nr]) / 256)); + asc7621_in_scaling[nr]) / 0xc0)); } static ssize_t store_in8(struct device *dev, struct device_attribute *attr, @@ -344,9 +341,11 @@ static ssize_t store_in8(struct device *dev, struct device_attribute *attr, if (strict_strtol(buf, 10, &reqval)) return -EINVAL; - reqval = SENSORS_LIMIT(reqval, 0, asc7621_in_scaling[nr]); + reqval = SENSORS_LIMIT(reqval, 0, 0xffff); + + reqval = reqval * 0xc0 / asc7621_in_scaling[nr]; - reqval = (reqval * 255 + 128) / asc7621_in_scaling[nr]; + reqval = SENSORS_LIMIT(reqval, 0, 0xff); mutex_lock(&data->update_lock); data->reg[param->msb[0]] = reqval; @@ -846,11 +845,11 @@ static struct asc7621_param asc7621_params[] = { PWRITE(in3_max, 3, PRI_LOW, 0x4b, 0, 0, 0, in8), PWRITE(in4_max, 4, PRI_LOW, 0x4d, 0, 0, 0, in8), - PREAD(in0_alarm, 0, PRI_LOW, 0x41, 0, 0x01, 0, bitmask), - PREAD(in1_alarm, 1, PRI_LOW, 0x41, 0, 0x01, 1, bitmask), - PREAD(in2_alarm, 2, PRI_LOW, 0x41, 0, 0x01, 2, bitmask), - PREAD(in3_alarm, 3, PRI_LOW, 0x41, 0, 0x01, 3, bitmask), - PREAD(in4_alarm, 4, PRI_LOW, 0x42, 0, 0x01, 0, bitmask), + PREAD(in0_alarm, 0, PRI_HIGH, 0x41, 0, 0x01, 0, bitmask), + PREAD(in1_alarm, 1, PRI_HIGH, 0x41, 0, 0x01, 1, bitmask), + PREAD(in2_alarm, 2, PRI_HIGH, 0x41, 0, 0x01, 2, bitmask), + PREAD(in3_alarm, 3, PRI_HIGH, 0x41, 0, 0x01, 3, bitmask), + PREAD(in4_alarm, 4, PRI_HIGH, 0x42, 0, 0x01, 0, bitmask), PREAD(fan1_input, 0, PRI_HIGH, 0x29, 0x28, 0, 0, fan16), PREAD(fan2_input, 1, PRI_HIGH, 0x2b, 0x2a, 0, 0, fan16), @@ -862,10 +861,10 @@ static struct asc7621_param asc7621_params[] = { PWRITE(fan3_min, 2, PRI_LOW, 0x59, 0x58, 0, 0, fan16), PWRITE(fan4_min, 3, PRI_LOW, 0x5b, 0x5a, 0, 0, fan16), - PREAD(fan1_alarm, 0, PRI_LOW, 0x42, 0, 0x01, 0, bitmask), - PREAD(fan2_alarm, 1, PRI_LOW, 0x42, 0, 0x01, 1, bitmask), - PREAD(fan3_alarm, 2, PRI_LOW, 0x42, 0, 0x01, 2, bitmask), - PREAD(fan4_alarm, 3, PRI_LOW, 0x42, 0, 0x01, 3, bitmask), + PREAD(fan1_alarm, 0, PRI_HIGH, 0x42, 0, 0x01, 2, bitmask), + PREAD(fan2_alarm, 1, PRI_HIGH, 0x42, 0, 0x01, 3, bitmask), + PREAD(fan3_alarm, 2, PRI_HIGH, 0x42, 0, 0x01, 4, bitmask), + PREAD(fan4_alarm, 3, PRI_HIGH, 0x42, 0, 0x01, 5, bitmask), PREAD(temp1_input, 0, PRI_HIGH, 0x25, 0x10, 0, 0, temp10), PREAD(temp2_input, 1, PRI_HIGH, 0x26, 0x15, 0, 0, temp10), @@ -886,10 +885,10 @@ static struct asc7621_param asc7621_params[] = { PWRITE(temp3_max, 2, PRI_LOW, 0x53, 0, 0, 0, temp8), PWRITE(temp4_max, 3, PRI_LOW, 0x35, 0, 0, 0, temp8), - PREAD(temp1_alarm, 0, PRI_LOW, 0x41, 0, 0x01, 4, bitmask), - PREAD(temp2_alarm, 1, PRI_LOW, 0x41, 0, 0x01, 5, bitmask), - PREAD(temp3_alarm, 2, PRI_LOW, 0x41, 0, 0x01, 6, bitmask), - PREAD(temp4_alarm, 3, PRI_LOW, 0x43, 0, 0x01, 0, bitmask), + PREAD(temp1_alarm, 0, PRI_HIGH, 0x41, 0, 0x01, 4, bitmask), + PREAD(temp2_alarm, 1, PRI_HIGH, 0x41, 0, 0x01, 5, bitmask), + PREAD(temp3_alarm, 2, PRI_HIGH, 0x41, 0, 0x01, 6, bitmask), + PREAD(temp4_alarm, 3, PRI_HIGH, 0x43, 0, 0x01, 0, bitmask), PWRITE(temp1_source, 0, PRI_LOW, 0x02, 0, 0x07, 4, bitmask), PWRITE(temp2_source, 1, PRI_LOW, 0x02, 0, 0x07, 0, bitmask), @@ -898,7 +897,7 @@ static struct asc7621_param asc7621_params[] = { PWRITE(temp1_smoothing_enable, 0, PRI_LOW, 0x62, 0, 0x01, 3, bitmask), PWRITE(temp2_smoothing_enable, 1, PRI_LOW, 0x63, 0, 0x01, 7, bitmask), - PWRITE(temp3_smoothing_enable, 2, PRI_LOW, 0x64, 0, 0x01, 3, bitmask), + PWRITE(temp3_smoothing_enable, 2, PRI_LOW, 0x63, 0, 0x01, 3, bitmask), PWRITE(temp4_smoothing_enable, 3, PRI_LOW, 0x3c, 0, 0x01, 3, bitmask), PWRITE(temp1_smoothing_time, 0, PRI_LOW, 0x62, 0, 0x07, 0, temp_st), -- cgit v0.10.2 From 0559a538899d48e7d730affb9df2abb13a7d9008 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Tue, 11 May 2010 09:17:47 +0200 Subject: hwmon: (applesmc) Correct sysfs fan error handling The current code will not remove the sysfs files for fan numbers three and up. Also, upon exit, fans one and two are removed regardless of their existence. This patch cleans up the sysfs error handling for the fans. Signed-off-by: Henrik Rydberg Signed-off-by: Jean Delvare diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index 0f28d91..f085c18 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c @@ -195,6 +195,9 @@ static unsigned int applesmc_accelerometer; /* Indicates whether this computer has light sensors and keyboard backlight. */ static unsigned int applesmc_light; +/* The number of fans handled by the driver */ +static unsigned int fans_handled; + /* Indicates which temperature sensors set to use. */ static unsigned int applesmc_temperature_set; @@ -1492,39 +1495,24 @@ static int __init applesmc_init(void) /* create fan files */ count = applesmc_get_fan_count(); - if (count < 0) { + if (count < 0) printk(KERN_ERR "applesmc: Cannot get the number of fans.\n"); - } else { + else printk(KERN_INFO "applesmc: %d fans found.\n", count); - switch (count) { - default: - printk(KERN_WARNING "applesmc: More than 4 fans found," - " but at most 4 fans are supported" - " by the driver.\n"); - case 4: - ret = sysfs_create_group(&pdev->dev.kobj, - &fan_attribute_groups[3]); - if (ret) - goto out_key_enumeration; - case 3: - ret = sysfs_create_group(&pdev->dev.kobj, - &fan_attribute_groups[2]); - if (ret) - goto out_key_enumeration; - case 2: - ret = sysfs_create_group(&pdev->dev.kobj, - &fan_attribute_groups[1]); - if (ret) - goto out_key_enumeration; - case 1: - ret = sysfs_create_group(&pdev->dev.kobj, - &fan_attribute_groups[0]); - if (ret) - goto out_fan_1; - case 0: - ; - } + if (count > 4) { + count = 4; + printk(KERN_WARNING "applesmc: More than 4 fans found," + " but at most 4 fans are supported" + " by the driver.\n"); + } + + while (fans_handled < count) { + ret = sysfs_create_group(&pdev->dev.kobj, + &fan_attribute_groups[fans_handled]); + if (ret) + goto out_fans; + fans_handled++; } for (i = 0; @@ -1593,10 +1581,10 @@ out_accelerometer: applesmc_release_accelerometer(); out_temperature: sysfs_remove_group(&pdev->dev.kobj, &temperature_attributes_group); - sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[0]); -out_fan_1: - sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[1]); -out_key_enumeration: +out_fans: + while (fans_handled) + sysfs_remove_group(&pdev->dev.kobj, + &fan_attribute_groups[--fans_handled]); sysfs_remove_group(&pdev->dev.kobj, &key_enumeration_group); out_name: sysfs_remove_file(&pdev->dev.kobj, &dev_attr_name.attr); @@ -1622,8 +1610,9 @@ static void __exit applesmc_exit(void) if (applesmc_accelerometer) applesmc_release_accelerometer(); sysfs_remove_group(&pdev->dev.kobj, &temperature_attributes_group); - sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[0]); - sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[1]); + while (fans_handled) + sysfs_remove_group(&pdev->dev.kobj, + &fan_attribute_groups[--fans_handled]); sysfs_remove_group(&pdev->dev.kobj, &key_enumeration_group); sysfs_remove_file(&pdev->dev.kobj, &dev_attr_name.attr); platform_device_unregister(pdev); -- cgit v0.10.2 From fcef85c0c122f90f57f2f3ef0caeaf6404d6e8f3 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 6 May 2010 15:42:23 +0900 Subject: ARM: SAMSUNG: Add spinlock locking to GPIO banks Add locking to each GPIO bank to allow for SMP capable code to use the gpiolib functions. See the gpio-core.h header file for more information. Signed-off-by: Ben Dooks diff --git a/arch/arm/plat-samsung/gpio-config.c b/arch/arm/plat-samsung/gpio-config.c index 3282db3..a76eef5 100644 --- a/arch/arm/plat-samsung/gpio-config.c +++ b/arch/arm/plat-samsung/gpio-config.c @@ -33,9 +33,9 @@ int s3c_gpio_cfgpin(unsigned int pin, unsigned int config) offset = pin - chip->chip.base; - local_irq_save(flags); + s3c_gpio_lock(chip, flags); ret = s3c_gpio_do_setcfg(chip, offset, config); - local_irq_restore(flags); + s3c_gpio_unlock(chip, flags); return ret; } @@ -51,9 +51,9 @@ unsigned s3c_gpio_getcfg(unsigned int pin) if (chip) { offset = pin - chip->chip.base; - local_irq_save(flags); + s3c_gpio_lock(chip, flags); ret = s3c_gpio_do_getcfg(chip, offset); - local_irq_restore(flags); + s3c_gpio_unlock(chip, flags); } return ret; @@ -72,9 +72,9 @@ int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull) offset = pin - chip->chip.base; - local_irq_save(flags); + s3c_gpio_lock(chip, flags); ret = s3c_gpio_do_setpull(chip, offset, pull); - local_irq_restore(flags); + s3c_gpio_unlock(chip, flags); return ret; } diff --git a/arch/arm/plat-samsung/gpio.c b/arch/arm/plat-samsung/gpio.c index 28d2ab8..b83a833 100644 --- a/arch/arm/plat-samsung/gpio.c +++ b/arch/arm/plat-samsung/gpio.c @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -52,14 +53,14 @@ static int s3c_gpiolib_input(struct gpio_chip *chip, unsigned offset) unsigned long flags; unsigned long con; - local_irq_save(flags); + s3c_gpio_lock(ourchip, flags); con = __raw_readl(base + 0x00); con &= ~(3 << (offset * 2)); __raw_writel(con, base + 0x00); - local_irq_restore(flags); + s3c_gpio_unlock(ourchip, flags); return 0; } @@ -72,7 +73,7 @@ static int s3c_gpiolib_output(struct gpio_chip *chip, unsigned long dat; unsigned long con; - local_irq_save(flags); + s3c_gpio_lock(ourchip, flags); dat = __raw_readl(base + 0x04); dat &= ~(1 << offset); @@ -87,7 +88,7 @@ static int s3c_gpiolib_output(struct gpio_chip *chip, __raw_writel(con, base + 0x00); __raw_writel(dat, base + 0x04); - local_irq_restore(flags); + s3c_gpio_unlock(ourchip, flags); return 0; } @@ -99,7 +100,7 @@ static void s3c_gpiolib_set(struct gpio_chip *chip, unsigned long flags; unsigned long dat; - local_irq_save(flags); + s3c_gpio_lock(ourchip, flags); dat = __raw_readl(base + 0x04); dat &= ~(1 << offset); @@ -107,7 +108,7 @@ static void s3c_gpiolib_set(struct gpio_chip *chip, dat |= 1 << offset; __raw_writel(dat, base + 0x04); - local_irq_restore(flags); + s3c_gpio_unlock(ourchip, flags); } static int s3c_gpiolib_get(struct gpio_chip *chip, unsigned offset) @@ -131,6 +132,8 @@ __init void s3c_gpiolib_add(struct s3c_gpio_chip *chip) BUG_ON(!gc->label); BUG_ON(!gc->ngpio); + spin_lock_init(&chip->lock); + if (!gc->direction_input) gc->direction_input = s3c_gpiolib_input; if (!gc->direction_output) diff --git a/arch/arm/plat-samsung/include/plat/gpio-core.h b/arch/arm/plat-samsung/include/plat/gpio-core.h index f0584f2..f3a68d1 100644 --- a/arch/arm/plat-samsung/include/plat/gpio-core.h +++ b/arch/arm/plat-samsung/include/plat/gpio-core.h @@ -44,16 +44,26 @@ struct s3c_gpio_cfg; * @chip: The chip structure to be exported via gpiolib. * @base: The base pointer to the gpio configuration registers. * @config: special function and pull-resistor control information. + * @lock: Lock for exclusive access to this gpio bank. * @pm_save: Save information for suspend/resume support. * * This wrapper provides the necessary information for the Samsung * specific gpios being registered with gpiolib. + * + * The lock protects each gpio bank from multiple access of the shared + * configuration registers, or from reading of data whilst another thread + * is writing to the register set. + * + * Each chip has its own lock to avoid any contention between different + * CPU cores trying to get one lock for different GPIO banks, where each + * bank of GPIO has its own register space and configuration registers. */ struct s3c_gpio_chip { struct gpio_chip chip; struct s3c_gpio_cfg *config; struct s3c_gpio_pm *pm; void __iomem *base; + spinlock_t lock; #ifdef CONFIG_PM u32 pm_save[4]; #endif @@ -138,3 +148,7 @@ extern struct s3c_gpio_pm s3c_gpio_pm_4bit; #define __gpio_pm(x) NULL #endif /* CONFIG_PM */ + +/* locking wrappers to deal with multiple access to the same gpio bank */ +#define s3c_gpio_lock(_oc, _fl) spin_lock_irqsave(&(_oc)->lock, _fl) +#define s3c_gpio_unlock(_oc, _fl) spin_unlock_irqrestore(&(_oc)->lock, _fl) -- cgit v0.10.2 From 050735b08ca8a016bbace4445fa025b88fee770b Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 11 May 2010 11:51:53 +0200 Subject: perf: Fix exit() vs PERF_FORMAT_GROUP Both Stephane and Corey reported that PERF_FORMAT_GROUP didn't work as expected if the task the counters were attached to quit before the read() call. The cause is that we unconditionally destroy the grouping when we remove counters from their context. Fix this by splitting off the group destroy from the list removal such that perf_event_remove_from_context() does not do this and change perf_event_release() to do so. Reported-by: Corey Ashford Reported-by: Stephane Eranian Signed-off-by: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Frederic Weisbecker Cc: Paul Mackerras Cc: # .34.x LKML-Reference: <1273571513.5605.3527.camel@twins> Signed-off-by: Ingo Molnar diff --git a/kernel/perf_event.c b/kernel/perf_event.c index a904746..c97e825 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -308,8 +308,6 @@ list_add_event(struct perf_event *event, struct perf_event_context *ctx) static void list_del_event(struct perf_event *event, struct perf_event_context *ctx) { - struct perf_event *sibling, *tmp; - if (list_empty(&event->group_entry)) return; ctx->nr_events--; @@ -333,6 +331,12 @@ list_del_event(struct perf_event *event, struct perf_event_context *ctx) */ if (event->state > PERF_EVENT_STATE_OFF) event->state = PERF_EVENT_STATE_OFF; +} + +static void +perf_destroy_group(struct perf_event *event, struct perf_event_context *ctx) +{ + struct perf_event *sibling, *tmp; /* * If this was a group event with sibling events then @@ -1868,6 +1872,12 @@ int perf_event_release_kernel(struct perf_event *event) { struct perf_event_context *ctx = event->ctx; + /* + * Remove from the PMU, can't get re-enabled since we got + * here because the last ref went. + */ + perf_event_disable(event); + WARN_ON_ONCE(ctx->parent_ctx); /* * There are two ways this annotation is useful: @@ -1882,7 +1892,10 @@ int perf_event_release_kernel(struct perf_event *event) * to trigger the AB-BA case. */ mutex_lock_nested(&ctx->mutex, SINGLE_DEPTH_NESTING); - perf_event_remove_from_context(event); + raw_spin_lock_irq(&ctx->lock); + list_del_event(event, ctx); + perf_destroy_group(event, ctx); + raw_spin_unlock_irq(&ctx->lock); mutex_unlock(&ctx->mutex); mutex_lock(&event->owner->perf_event_mutex); -- cgit v0.10.2 From 96c21a460a37880abfbc8445d5b098dbab958a29 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 11 May 2010 16:19:10 +0200 Subject: perf: Fix exit() vs event-groups Corey reported that the value scale times of group siblings are not updated when the monitored task dies. The problem appears to be that we only update the group leader's time values, fix it by updating the whole group. Reported-by: Corey Ashford Signed-off-by: Peter Zijlstra Cc: Paul Mackerras Cc: Mike Galbraith Cc: Arnaldo Carvalho de Melo Cc: Frederic Weisbecker Cc: # .34.x LKML-Reference: <1273588935.1810.6.camel@laptop> Signed-off-by: Ingo Molnar diff --git a/kernel/perf_event.c b/kernel/perf_event.c index c97e825..a4fa381 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c @@ -255,6 +255,18 @@ static void update_event_times(struct perf_event *event) event->total_time_running = run_end - event->tstamp_running; } +/* + * Update total_time_enabled and total_time_running for all events in a group. + */ +static void update_group_times(struct perf_event *leader) +{ + struct perf_event *event; + + update_event_times(leader); + list_for_each_entry(event, &leader->sibling_list, group_entry) + update_event_times(event); +} + static struct list_head * ctx_group_list(struct perf_event *event, struct perf_event_context *ctx) { @@ -320,7 +332,7 @@ list_del_event(struct perf_event *event, struct perf_event_context *ctx) if (event->group_leader != event) event->group_leader->nr_siblings--; - update_event_times(event); + update_group_times(event); /* * If event was in error state, then keep it @@ -502,18 +514,6 @@ retry: } /* - * Update total_time_enabled and total_time_running for all events in a group. - */ -static void update_group_times(struct perf_event *leader) -{ - struct perf_event *event; - - update_event_times(leader); - list_for_each_entry(event, &leader->sibling_list, group_entry) - update_event_times(event); -} - -/* * Cross CPU call to disable a performance event */ static void __perf_event_disable(void *info) -- cgit v0.10.2 From 8e6d5573af55435160d329f6ae3fe16a0abbdaec Mon Sep 17 00:00:00 2001 From: Lin Ming Date: Sat, 8 May 2010 20:28:41 +1000 Subject: perf, powerpc: Implement group scheduling transactional APIs [paulus@samba.org: Set cpuhw->event[i]->hw.config in power_pmu_commit_txn.] Signed-off-by: Lin Ming Signed-off-by: Paul Mackerras Signed-off-by: Peter Zijlstra LKML-Reference: <20100508102841.GA10650@brick.ozlabs.ibm.com> Signed-off-by: Ingo Molnar diff --git a/arch/powerpc/kernel/perf_event.c b/arch/powerpc/kernel/perf_event.c index 08460a2..43b83c3 100644 --- a/arch/powerpc/kernel/perf_event.c +++ b/arch/powerpc/kernel/perf_event.c @@ -35,6 +35,9 @@ struct cpu_hw_events { u64 alternatives[MAX_HWEVENTS][MAX_EVENT_ALTERNATIVES]; unsigned long amasks[MAX_HWEVENTS][MAX_EVENT_ALTERNATIVES]; unsigned long avalues[MAX_HWEVENTS][MAX_EVENT_ALTERNATIVES]; + + unsigned int group_flag; + int n_txn_start; }; DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events); @@ -718,66 +721,6 @@ static int collect_events(struct perf_event *group, int max_count, return n; } -static void event_sched_in(struct perf_event *event) -{ - event->state = PERF_EVENT_STATE_ACTIVE; - event->oncpu = smp_processor_id(); - event->tstamp_running += event->ctx->time - event->tstamp_stopped; - if (is_software_event(event)) - event->pmu->enable(event); -} - -/* - * Called to enable a whole group of events. - * Returns 1 if the group was enabled, or -EAGAIN if it could not be. - * Assumes the caller has disabled interrupts and has - * frozen the PMU with hw_perf_save_disable. - */ -int hw_perf_group_sched_in(struct perf_event *group_leader, - struct perf_cpu_context *cpuctx, - struct perf_event_context *ctx) -{ - struct cpu_hw_events *cpuhw; - long i, n, n0; - struct perf_event *sub; - - if (!ppmu) - return 0; - cpuhw = &__get_cpu_var(cpu_hw_events); - n0 = cpuhw->n_events; - n = collect_events(group_leader, ppmu->n_counter - n0, - &cpuhw->event[n0], &cpuhw->events[n0], - &cpuhw->flags[n0]); - if (n < 0) - return -EAGAIN; - if (check_excludes(cpuhw->event, cpuhw->flags, n0, n)) - return -EAGAIN; - i = power_check_constraints(cpuhw, cpuhw->events, cpuhw->flags, n + n0); - if (i < 0) - return -EAGAIN; - cpuhw->n_events = n0 + n; - cpuhw->n_added += n; - - /* - * OK, this group can go on; update event states etc., - * and enable any software events - */ - for (i = n0; i < n0 + n; ++i) - cpuhw->event[i]->hw.config = cpuhw->events[i]; - cpuctx->active_oncpu += n; - n = 1; - event_sched_in(group_leader); - list_for_each_entry(sub, &group_leader->sibling_list, group_entry) { - if (sub->state != PERF_EVENT_STATE_OFF) { - event_sched_in(sub); - ++n; - } - } - ctx->nr_active += n; - - return 1; -} - /* * Add a event to the PMU. * If all events are not already frozen, then we disable and @@ -805,12 +748,22 @@ static int power_pmu_enable(struct perf_event *event) cpuhw->event[n0] = event; cpuhw->events[n0] = event->hw.config; cpuhw->flags[n0] = event->hw.event_base; + + /* + * If group events scheduling transaction was started, + * skip the schedulability test here, it will be peformed + * at commit time(->commit_txn) as a whole + */ + if (cpuhw->group_flag & PERF_EVENT_TXN_STARTED) + goto nocheck; + if (check_excludes(cpuhw->event, cpuhw->flags, n0, 1)) goto out; if (power_check_constraints(cpuhw, cpuhw->events, cpuhw->flags, n0 + 1)) goto out; - event->hw.config = cpuhw->events[n0]; + +nocheck: ++cpuhw->n_events; ++cpuhw->n_added; @@ -896,11 +849,65 @@ static void power_pmu_unthrottle(struct perf_event *event) local_irq_restore(flags); } +/* + * Start group events scheduling transaction + * Set the flag to make pmu::enable() not perform the + * schedulability test, it will be performed at commit time + */ +void power_pmu_start_txn(const struct pmu *pmu) +{ + struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events); + + cpuhw->group_flag |= PERF_EVENT_TXN_STARTED; + cpuhw->n_txn_start = cpuhw->n_events; +} + +/* + * Stop group events scheduling transaction + * Clear the flag and pmu::enable() will perform the + * schedulability test. + */ +void power_pmu_cancel_txn(const struct pmu *pmu) +{ + struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events); + + cpuhw->group_flag &= ~PERF_EVENT_TXN_STARTED; +} + +/* + * Commit group events scheduling transaction + * Perform the group schedulability test as a whole + * Return 0 if success + */ +int power_pmu_commit_txn(const struct pmu *pmu) +{ + struct cpu_hw_events *cpuhw; + long i, n; + + if (!ppmu) + return -EAGAIN; + cpuhw = &__get_cpu_var(cpu_hw_events); + n = cpuhw->n_events; + if (check_excludes(cpuhw->event, cpuhw->flags, 0, n)) + return -EAGAIN; + i = power_check_constraints(cpuhw, cpuhw->events, cpuhw->flags, n); + if (i < 0) + return -EAGAIN; + + for (i = cpuhw->n_txn_start; i < n; ++i) + cpuhw->event[i]->hw.config = cpuhw->events[i]; + + return 0; +} + struct pmu power_pmu = { .enable = power_pmu_enable, .disable = power_pmu_disable, .read = power_pmu_read, .unthrottle = power_pmu_unthrottle, + .start_txn = power_pmu_start_txn, + .cancel_txn = power_pmu_cancel_txn, + .commit_txn = power_pmu_commit_txn, }; /* -- cgit v0.10.2 From a52357259680fe5368c2fabf5949209e231f2aa2 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Tue, 11 May 2010 17:12:33 +0200 Subject: x86/amd-iommu: Add amd_iommu=off command line option This patch adds a command line option to tell the AMD IOMMU driver to not initialize any IOMMU it finds. Signed-off-by: Joerg Roedel diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 839b21b..0c6c560 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -324,6 +324,8 @@ and is between 256 and 4096 characters. It is defined in the file they are unmapped. Otherwise they are flushed before they will be reused, which is a lot of faster + off - do not initialize any AMD IOMMU found in + the system amijoy.map= [HW,JOY] Amiga joystick support Map of devices attached to JOY0DAT and JOY1DAT diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 6360abf..3bacb4d 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -120,6 +120,7 @@ struct ivmd_header { bool amd_iommu_dump; static int __initdata amd_iommu_detected; +static bool __initdata amd_iommu_disabled; u16 amd_iommu_last_bdf; /* largest PCI device id we have to handle */ @@ -1372,6 +1373,9 @@ void __init amd_iommu_detect(void) if (no_iommu || (iommu_detected && !gart_iommu_aperture)) return; + if (amd_iommu_disabled) + return; + if (acpi_table_parse("IVRS", early_amd_iommu_detect) == 0) { iommu_detected = 1; amd_iommu_detected = 1; @@ -1401,6 +1405,8 @@ static int __init parse_amd_iommu_options(char *str) for (; *str; ++str) { if (strncmp(str, "fullflush", 9) == 0) amd_iommu_unmap_flush = true; + if (strncmp(str, "off", 3) == 0) + amd_iommu_disabled = true; } return 1; -- cgit v0.10.2 From 5700929d2209c5e2038f340bacc91e9818439cdf Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Mon, 15 Mar 2010 22:23:09 +0800 Subject: input: remove now deprecated corgi_ts.c touchscreen driver The corgi touchscreen is now deprecated in favour of the generic ads7846.c driver. The noise reduction technique used in corgi_ts.c, which is to wait till vsync before ADC sampling, is also integrated into ads7846 driver now. Provided that the original driver is not generic and is difficult to maintain, it will be removed now. Signed-off-by: Eric Miao Cc: Richard Purdie Cc: Pavel Machek Cc: Dmitry Torokhov diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 8a8fa4d..3d1ade2 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -99,22 +99,6 @@ config TOUCHSCREEN_BITSY To compile this driver as a module, choose M here: the module will be called h3600_ts_input. -config TOUCHSCREEN_CORGI - tristate "SharpSL (Corgi and Spitz series) touchscreen driver (DEPRECATED)" - depends on PXA_SHARPSL - select CORGI_SSP_DEPRECATED - help - Say Y here to enable the driver for the touchscreen on the - Sharp SL-C7xx and SL-Cxx00 series of PDAs. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called corgi_ts. - - NOTE: this driver is deprecated, try enable SPI and generic - ADS7846-based touchscreen driver. - config TOUCHSCREEN_DA9034 tristate "Touchscreen support for Dialog Semiconductor DA9034" depends on PMIC_DA903X diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 7fef7d5..41145d0 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -12,7 +12,6 @@ obj-$(CONFIG_TOUCHSCREEN_AD7879) += ad7879.o obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o -obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c deleted file mode 100644 index 94a1919..0000000 --- a/drivers/input/touchscreen/corgi_ts.c +++ /dev/null @@ -1,385 +0,0 @@ -/* - * Touchscreen driver for Sharp SL-C7xx and SL-Cxx00 models - * - * Copyright (c) 2004-2005 Richard Purdie - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - - -#define PWR_MODE_ACTIVE 0 -#define PWR_MODE_SUSPEND 1 - -#define X_AXIS_MAX 3830 -#define X_AXIS_MIN 150 -#define Y_AXIS_MAX 3830 -#define Y_AXIS_MIN 190 -#define PRESSURE_MIN 0 -#define PRESSURE_MAX 15000 - -struct ts_event { - short pressure; - short x; - short y; -}; - -struct corgi_ts { - struct input_dev *input; - struct timer_list timer; - struct ts_event tc; - int pendown; - int power_mode; - int irq_gpio; - struct corgits_machinfo *machinfo; -}; - -#ifdef CONFIG_PXA25x -#define CCNT(a) asm volatile ("mrc p14, 0, %0, C1, C0, 0" : "=r"(a)) -#define PMNC_GET(x) asm volatile ("mrc p14, 0, %0, C0, C0, 0" : "=r"(x)) -#define PMNC_SET(x) asm volatile ("mcr p14, 0, %0, C0, C0, 0" : : "r"(x)) -#endif -#ifdef CONFIG_PXA27x -#define CCNT(a) asm volatile ("mrc p14, 0, %0, C1, C1, 0" : "=r"(a)) -#define PMNC_GET(x) asm volatile ("mrc p14, 0, %0, C0, C1, 0" : "=r"(x)) -#define PMNC_SET(x) asm volatile ("mcr p14, 0, %0, C0, C1, 0" : : "r"(x)) -#endif - -/* ADS7846 Touch Screen Controller bit definitions */ -#define ADSCTRL_PD0 (1u << 0) /* PD0 */ -#define ADSCTRL_PD1 (1u << 1) /* PD1 */ -#define ADSCTRL_DFR (1u << 2) /* SER/DFR */ -#define ADSCTRL_MOD (1u << 3) /* Mode */ -#define ADSCTRL_ADR_SH 4 /* Address setting */ -#define ADSCTRL_STS (1u << 7) /* Start Bit */ - -/* External Functions */ -extern unsigned int get_clk_frequency_khz(int info); - -static unsigned long calc_waittime(struct corgi_ts *corgi_ts) -{ - unsigned long hsync_invperiod = corgi_ts->machinfo->get_hsync_invperiod(); - - if (hsync_invperiod) - return get_clk_frequency_khz(0)*1000/hsync_invperiod; - else - return 0; -} - -static int sync_receive_data_send_cmd(struct corgi_ts *corgi_ts, int doRecive, int doSend, - unsigned int address, unsigned long wait_time) -{ - unsigned long timer1 = 0, timer2, pmnc = 0; - int pos = 0; - - if (wait_time && doSend) { - PMNC_GET(pmnc); - if (!(pmnc & 0x01)) - PMNC_SET(0x01); - - /* polling HSync */ - corgi_ts->machinfo->wait_hsync(); - /* get CCNT */ - CCNT(timer1); - } - - if (doRecive) - pos = corgi_ssp_ads7846_get(); - - if (doSend) { - int cmd = ADSCTRL_PD0 | ADSCTRL_PD1 | (address << ADSCTRL_ADR_SH) | ADSCTRL_STS; - /* dummy command */ - corgi_ssp_ads7846_put(cmd); - corgi_ssp_ads7846_get(); - - if (wait_time) { - /* Wait after HSync */ - CCNT(timer2); - if (timer2-timer1 > wait_time) { - /* too slow - timeout, try again */ - corgi_ts->machinfo->wait_hsync(); - /* get CCNT */ - CCNT(timer1); - /* Wait after HSync */ - CCNT(timer2); - } - while (timer2 - timer1 < wait_time) - CCNT(timer2); - } - corgi_ssp_ads7846_put(cmd); - if (wait_time && !(pmnc & 0x01)) - PMNC_SET(pmnc); - } - return pos; -} - -static int read_xydata(struct corgi_ts *corgi_ts) -{ - unsigned int x, y, z1, z2; - unsigned long flags, wait_time; - - /* critical section */ - local_irq_save(flags); - corgi_ssp_ads7846_lock(); - wait_time = calc_waittime(corgi_ts); - - /* Y-axis */ - sync_receive_data_send_cmd(corgi_ts, 0, 1, 1u, wait_time); - - /* Y-axis */ - sync_receive_data_send_cmd(corgi_ts, 1, 1, 1u, wait_time); - - /* X-axis */ - y = sync_receive_data_send_cmd(corgi_ts, 1, 1, 5u, wait_time); - - /* Z1 */ - x = sync_receive_data_send_cmd(corgi_ts, 1, 1, 3u, wait_time); - - /* Z2 */ - z1 = sync_receive_data_send_cmd(corgi_ts, 1, 1, 4u, wait_time); - z2 = sync_receive_data_send_cmd(corgi_ts, 1, 0, 4u, wait_time); - - /* Power-Down Enable */ - corgi_ssp_ads7846_put((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - corgi_ssp_ads7846_get(); - - corgi_ssp_ads7846_unlock(); - local_irq_restore(flags); - - if (x== 0 || y == 0 || z1 == 0 || (x * (z2 - z1) / z1) >= 15000) { - corgi_ts->tc.pressure = 0; - return 0; - } - - corgi_ts->tc.x = x; - corgi_ts->tc.y = y; - corgi_ts->tc.pressure = (x * (z2 - z1)) / z1; - return 1; -} - -static void new_data(struct corgi_ts *corgi_ts) -{ - struct input_dev *dev = corgi_ts->input; - - if (corgi_ts->power_mode != PWR_MODE_ACTIVE) - return; - - if (!corgi_ts->tc.pressure && corgi_ts->pendown == 0) - return; - - input_report_abs(dev, ABS_X, corgi_ts->tc.x); - input_report_abs(dev, ABS_Y, corgi_ts->tc.y); - input_report_abs(dev, ABS_PRESSURE, corgi_ts->tc.pressure); - input_report_key(dev, BTN_TOUCH, corgi_ts->pendown); - input_sync(dev); -} - -static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer) -{ - if ((GPLR(IRQ_TO_GPIO(corgi_ts->irq_gpio)) & GPIO_bit(IRQ_TO_GPIO(corgi_ts->irq_gpio))) == 0) { - /* Disable Interrupt */ - set_irq_type(corgi_ts->irq_gpio, IRQ_TYPE_NONE); - if (read_xydata(corgi_ts)) { - corgi_ts->pendown = 1; - new_data(corgi_ts); - } - mod_timer(&corgi_ts->timer, jiffies + HZ / 100); - } else { - if (corgi_ts->pendown == 1 || corgi_ts->pendown == 2) { - mod_timer(&corgi_ts->timer, jiffies + HZ / 100); - corgi_ts->pendown++; - return; - } - - if (corgi_ts->pendown) { - corgi_ts->tc.pressure = 0; - new_data(corgi_ts); - } - - /* Enable Falling Edge */ - set_irq_type(corgi_ts->irq_gpio, IRQ_TYPE_EDGE_FALLING); - corgi_ts->pendown = 0; - } -} - -static void corgi_ts_timer(unsigned long data) -{ - struct corgi_ts *corgits_data = (struct corgi_ts *) data; - - ts_interrupt_main(corgits_data, 1); -} - -static irqreturn_t ts_interrupt(int irq, void *dev_id) -{ - struct corgi_ts *corgits_data = dev_id; - - ts_interrupt_main(corgits_data, 0); - return IRQ_HANDLED; -} - -#ifdef CONFIG_PM -static int corgits_suspend(struct platform_device *dev, pm_message_t state) -{ - struct corgi_ts *corgi_ts = platform_get_drvdata(dev); - - if (corgi_ts->pendown) { - del_timer_sync(&corgi_ts->timer); - corgi_ts->tc.pressure = 0; - new_data(corgi_ts); - corgi_ts->pendown = 0; - } - corgi_ts->power_mode = PWR_MODE_SUSPEND; - - corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - - return 0; -} - -static int corgits_resume(struct platform_device *dev) -{ - struct corgi_ts *corgi_ts = platform_get_drvdata(dev); - - corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - /* Enable Falling Edge */ - set_irq_type(corgi_ts->irq_gpio, IRQ_TYPE_EDGE_FALLING); - corgi_ts->power_mode = PWR_MODE_ACTIVE; - - return 0; -} -#else -#define corgits_suspend NULL -#define corgits_resume NULL -#endif - -static int __devinit corgits_probe(struct platform_device *pdev) -{ - struct corgi_ts *corgi_ts; - struct input_dev *input_dev; - int err = -ENOMEM; - - corgi_ts = kzalloc(sizeof(struct corgi_ts), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!corgi_ts || !input_dev) - goto fail1; - - platform_set_drvdata(pdev, corgi_ts); - - corgi_ts->machinfo = pdev->dev.platform_data; - corgi_ts->irq_gpio = platform_get_irq(pdev, 0); - - if (corgi_ts->irq_gpio < 0) { - err = -ENODEV; - goto fail1; - } - - corgi_ts->input = input_dev; - - init_timer(&corgi_ts->timer); - corgi_ts->timer.data = (unsigned long) corgi_ts; - corgi_ts->timer.function = corgi_ts_timer; - - input_dev->name = "Corgi Touchscreen"; - input_dev->phys = "corgits/input0"; - input_dev->id.bustype = BUS_HOST; - input_dev->id.vendor = 0x0001; - input_dev->id.product = 0x0002; - input_dev->id.version = 0x0100; - input_dev->dev.parent = &pdev->dev; - - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); - input_set_abs_params(input_dev, ABS_X, X_AXIS_MIN, X_AXIS_MAX, 0, 0); - input_set_abs_params(input_dev, ABS_Y, Y_AXIS_MIN, Y_AXIS_MAX, 0, 0); - input_set_abs_params(input_dev, ABS_PRESSURE, PRESSURE_MIN, PRESSURE_MAX, 0, 0); - - pxa_gpio_mode(IRQ_TO_GPIO(corgi_ts->irq_gpio) | GPIO_IN); - - /* Initiaize ADS7846 Difference Reference mode */ - corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - mdelay(5); - corgi_ssp_ads7846_putget((3u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - mdelay(5); - corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - mdelay(5); - corgi_ssp_ads7846_putget((5u << ADSCTRL_ADR_SH) | ADSCTRL_STS); - mdelay(5); - - if (request_irq(corgi_ts->irq_gpio, ts_interrupt, IRQF_DISABLED, "ts", corgi_ts)) { - err = -EBUSY; - goto fail1; - } - - err = input_register_device(corgi_ts->input); - if (err) - goto fail2; - - corgi_ts->power_mode = PWR_MODE_ACTIVE; - - /* Enable Falling Edge */ - set_irq_type(corgi_ts->irq_gpio, IRQ_TYPE_EDGE_FALLING); - - return 0; - - fail2: free_irq(corgi_ts->irq_gpio, corgi_ts); - fail1: input_free_device(input_dev); - kfree(corgi_ts); - return err; -} - -static int __devexit corgits_remove(struct platform_device *pdev) -{ - struct corgi_ts *corgi_ts = platform_get_drvdata(pdev); - - free_irq(corgi_ts->irq_gpio, corgi_ts); - del_timer_sync(&corgi_ts->timer); - corgi_ts->machinfo->put_hsync(); - input_unregister_device(corgi_ts->input); - kfree(corgi_ts); - - return 0; -} - -static struct platform_driver corgits_driver = { - .probe = corgits_probe, - .remove = __devexit_p(corgits_remove), - .suspend = corgits_suspend, - .resume = corgits_resume, - .driver = { - .name = "corgi-ts", - .owner = THIS_MODULE, - }, -}; - -static int __init corgits_init(void) -{ - return platform_driver_register(&corgits_driver); -} - -static void __exit corgits_exit(void) -{ - platform_driver_unregister(&corgits_driver); -} - -module_init(corgits_init); -module_exit(corgits_exit); - -MODULE_AUTHOR("Richard Purdie "); -MODULE_DESCRIPTION("Corgi TouchScreen Driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:corgi-ts"); -- cgit v0.10.2 From 639b91a364fafea24fc1d2e8853c12ce45d4ceea Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Mon, 15 Mar 2010 22:39:27 +0800 Subject: [ARM] pxa: remove now un-used corgi_ssp.c and corgi_lcd.c The only use of corgi_ssp.c is corgi_ts.c, which is now deprecated and removed. Remove corgi_ssp.c and corgi_lcd.c and their relevant function declarations and data structures. Signed-off-by: Eric Miao Cc: Richard Purdie Cc: Pavel Machek diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 05df0b7..6237d74 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -531,18 +531,6 @@ Who: Eric Miao ---------------------------- -What: corgi_ssp and corgi_ts driver -When: 2.6.35 -Files: arch/arm/mach-pxa/corgi_ssp.c, drivers/input/touchscreen/corgi_ts.c -Why: The corgi touchscreen is now deprecated in favour of the generic - ads7846.c driver. The noise reduction technique used in corgi_ts.c, - that's to wait till vsync before ADC sampling, is also integrated into - ads7846 driver now. Provided that the original driver is not generic - and is difficult to maintain, it will be removed later. -Who: Eric Miao - ----------------------------- - What: capifs When: February 2011 Files: drivers/isdn/capi/capifs.* diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index 5b6ee46..089579f 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -461,15 +461,6 @@ config SHARPSL_PM_MAX1111 select HWMON select SENSORS_MAX1111 -config CORGI_SSP_DEPRECATED - bool - select PXA_SSP - select PXA_SSP_LEGACY - help - This option will include corgi_ssp.c and corgi_lcd.c - that corgi_ts.c and other legacy drivers (corgi_bl.c - and sharpsl_pm.c) may depend on. - config MACH_POODLE bool "Enable Sharp SL-5600 (Poodle) Support" depends on PXA_SHARPSL diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index 86bc87b..a83aff3 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -80,7 +80,6 @@ obj-$(CONFIG_MACH_PALMLD) += palmld.o obj-$(CONFIG_PALM_TREO) += palmtreo.o obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o sharpsl_pm.o corgi_pm.o obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o sharpsl_pm.o spitz_pm.o -obj-$(CONFIG_CORGI_SSP_DEPRECATED) += corgi_ssp.o corgi_lcd.o obj-$(CONFIG_MACH_POODLE) += poodle.o obj-$(CONFIG_MACH_TOSA) += tosa.o obj-$(CONFIG_MACH_ICONTROL) += icontrol.o mxm8x10.o diff --git a/arch/arm/mach-pxa/corgi_lcd.c b/arch/arm/mach-pxa/corgi_lcd.c deleted file mode 100644 index d9b9631..0000000 --- a/arch/arm/mach-pxa/corgi_lcd.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - * linux/arch/arm/mach-pxa/corgi_lcd.c - * - * Corgi/Spitz LCD Specific Code - * - * Copyright (C) 2005 Richard Purdie - * - * Connectivity: - * Corgi - LCD to ATI Imageon w100 (Wallaby) - * Spitz - LCD to PXA Framebuffer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "generic.h" - -/* Register Addresses */ -#define RESCTL_ADRS 0x00 -#define PHACTRL_ADRS 0x01 -#define DUTYCTRL_ADRS 0x02 -#define POWERREG0_ADRS 0x03 -#define POWERREG1_ADRS 0x04 -#define GPOR3_ADRS 0x05 -#define PICTRL_ADRS 0x06 -#define POLCTRL_ADRS 0x07 - -/* Register Bit Definitions */ -#define RESCTL_QVGA 0x01 -#define RESCTL_VGA 0x00 - -#define POWER1_VW_ON 0x01 /* VW Supply FET ON */ -#define POWER1_GVSS_ON 0x02 /* GVSS(-8V) Power Supply ON */ -#define POWER1_VDD_ON 0x04 /* VDD(8V),SVSS(-4V) Power Supply ON */ - -#define POWER1_VW_OFF 0x00 /* VW Supply FET OFF */ -#define POWER1_GVSS_OFF 0x00 /* GVSS(-8V) Power Supply OFF */ -#define POWER1_VDD_OFF 0x00 /* VDD(8V),SVSS(-4V) Power Supply OFF */ - -#define POWER0_COM_DCLK 0x01 /* COM Voltage DC Bias DAC Serial Data Clock */ -#define POWER0_COM_DOUT 0x02 /* COM Voltage DC Bias DAC Serial Data Out */ -#define POWER0_DAC_ON 0x04 /* DAC Power Supply ON */ -#define POWER0_COM_ON 0x08 /* COM Power Supply ON */ -#define POWER0_VCC5_ON 0x10 /* VCC5 Power Supply ON */ - -#define POWER0_DAC_OFF 0x00 /* DAC Power Supply OFF */ -#define POWER0_COM_OFF 0x00 /* COM Power Supply OFF */ -#define POWER0_VCC5_OFF 0x00 /* VCC5 Power Supply OFF */ - -#define PICTRL_INIT_STATE 0x01 -#define PICTRL_INIOFF 0x02 -#define PICTRL_POWER_DOWN 0x04 -#define PICTRL_COM_SIGNAL_OFF 0x08 -#define PICTRL_DAC_SIGNAL_OFF 0x10 - -#define POLCTRL_SYNC_POL_FALL 0x01 -#define POLCTRL_EN_POL_FALL 0x02 -#define POLCTRL_DATA_POL_FALL 0x04 -#define POLCTRL_SYNC_ACT_H 0x08 -#define POLCTRL_EN_ACT_L 0x10 - -#define POLCTRL_SYNC_POL_RISE 0x00 -#define POLCTRL_EN_POL_RISE 0x00 -#define POLCTRL_DATA_POL_RISE 0x00 -#define POLCTRL_SYNC_ACT_L 0x00 -#define POLCTRL_EN_ACT_H 0x00 - -#define PHACTRL_PHASE_MANUAL 0x01 -#define DEFAULT_PHAD_QVGA (9) -#define DEFAULT_COMADJ (125) - -/* - * This is only a psuedo I2C interface. We can't use the standard kernel - * routines as the interface is write only. We just assume the data is acked... - */ -static void lcdtg_ssp_i2c_send(u8 data) -{ - corgi_ssp_lcdtg_send(POWERREG0_ADRS, data); - udelay(10); -} - -static void lcdtg_i2c_send_bit(u8 data) -{ - lcdtg_ssp_i2c_send(data); - lcdtg_ssp_i2c_send(data | POWER0_COM_DCLK); - lcdtg_ssp_i2c_send(data); -} - -static void lcdtg_i2c_send_start(u8 base) -{ - lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK | POWER0_COM_DOUT); - lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK); - lcdtg_ssp_i2c_send(base); -} - -static void lcdtg_i2c_send_stop(u8 base) -{ - lcdtg_ssp_i2c_send(base); - lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK); - lcdtg_ssp_i2c_send(base | POWER0_COM_DCLK | POWER0_COM_DOUT); -} - -static void lcdtg_i2c_send_byte(u8 base, u8 data) -{ - int i; - for (i = 0; i < 8; i++) { - if (data & 0x80) - lcdtg_i2c_send_bit(base | POWER0_COM_DOUT); - else - lcdtg_i2c_send_bit(base); - data <<= 1; - } -} - -static void lcdtg_i2c_wait_ack(u8 base) -{ - lcdtg_i2c_send_bit(base); -} - -static void lcdtg_set_common_voltage(u8 base_data, u8 data) -{ - /* Set Common Voltage to M62332FP via I2C */ - lcdtg_i2c_send_start(base_data); - lcdtg_i2c_send_byte(base_data, 0x9c); - lcdtg_i2c_wait_ack(base_data); - lcdtg_i2c_send_byte(base_data, 0x00); - lcdtg_i2c_wait_ack(base_data); - lcdtg_i2c_send_byte(base_data, data); - lcdtg_i2c_wait_ack(base_data); - lcdtg_i2c_send_stop(base_data); -} - -/* Set Phase Adjust */ -static void lcdtg_set_phadadj(int mode) -{ - int adj; - switch(mode) { - case 480: - case 640: - /* Setting for VGA */ - adj = sharpsl_param.phadadj; - if (adj < 0) { - adj = PHACTRL_PHASE_MANUAL; - } else { - adj = ((adj & 0x0f) << 1) | PHACTRL_PHASE_MANUAL; - } - break; - case 240: - case 320: - default: - /* Setting for QVGA */ - adj = (DEFAULT_PHAD_QVGA << 1) | PHACTRL_PHASE_MANUAL; - break; - } - - corgi_ssp_lcdtg_send(PHACTRL_ADRS, adj); -} - -static int lcd_inited; - -void corgi_lcdtg_hw_init(int mode) -{ - if (!lcd_inited) { - int comadj; - - /* Initialize Internal Logic & Port */ - corgi_ssp_lcdtg_send(PICTRL_ADRS, PICTRL_POWER_DOWN | PICTRL_INIOFF | PICTRL_INIT_STATE - | PICTRL_COM_SIGNAL_OFF | PICTRL_DAC_SIGNAL_OFF); - - corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_OFF - | POWER0_COM_OFF | POWER0_VCC5_OFF); - - corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_OFF); - - /* VDD(+8V), SVSS(-4V) ON */ - corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_ON); - mdelay(3); - - /* DAC ON */ - corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON - | POWER0_COM_OFF | POWER0_VCC5_OFF); - - /* INIB = H, INI = L */ - /* PICTL[0] = H , PICTL[1] = PICTL[2] = PICTL[4] = L */ - corgi_ssp_lcdtg_send(PICTRL_ADRS, PICTRL_INIT_STATE | PICTRL_COM_SIGNAL_OFF); - - /* Set Common Voltage */ - comadj = sharpsl_param.comadj; - if (comadj < 0) - comadj = DEFAULT_COMADJ; - lcdtg_set_common_voltage((POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_OFF), comadj); - - /* VCC5 ON, DAC ON */ - corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON | - POWER0_COM_OFF | POWER0_VCC5_ON); - - /* GVSS(-8V) ON, VDD ON */ - corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_ON | POWER1_VDD_ON); - mdelay(2); - - /* COM SIGNAL ON (PICTL[3] = L) */ - corgi_ssp_lcdtg_send(PICTRL_ADRS, PICTRL_INIT_STATE); - - /* COM ON, DAC ON, VCC5_ON */ - corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_COM_DCLK | POWER0_COM_DOUT | POWER0_DAC_ON - | POWER0_COM_ON | POWER0_VCC5_ON); - - /* VW ON, GVSS ON, VDD ON */ - corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_ON | POWER1_GVSS_ON | POWER1_VDD_ON); - - /* Signals output enable */ - corgi_ssp_lcdtg_send(PICTRL_ADRS, 0); - - /* Set Phase Adjust */ - lcdtg_set_phadadj(mode); - - /* Initialize for Input Signals from ATI */ - corgi_ssp_lcdtg_send(POLCTRL_ADRS, POLCTRL_SYNC_POL_RISE | POLCTRL_EN_POL_RISE - | POLCTRL_DATA_POL_RISE | POLCTRL_SYNC_ACT_L | POLCTRL_EN_ACT_H); - udelay(1000); - - lcd_inited=1; - } else { - lcdtg_set_phadadj(mode); - } - - switch(mode) { - case 480: - case 640: - /* Set Lcd Resolution (VGA) */ - corgi_ssp_lcdtg_send(RESCTL_ADRS, RESCTL_VGA); - break; - case 240: - case 320: - default: - /* Set Lcd Resolution (QVGA) */ - corgi_ssp_lcdtg_send(RESCTL_ADRS, RESCTL_QVGA); - break; - } -} - -void corgi_lcdtg_suspend(void) -{ - /* 60Hz x 2 frame = 16.7msec x 2 = 33.4 msec */ - mdelay(34); - - /* (1)VW OFF */ - corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_ON | POWER1_VDD_ON); - - /* (2)COM OFF */ - corgi_ssp_lcdtg_send(PICTRL_ADRS, PICTRL_COM_SIGNAL_OFF); - corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_ON); - - /* (3)Set Common Voltage Bias 0V */ - lcdtg_set_common_voltage(POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_ON, 0); - - /* (4)GVSS OFF */ - corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_ON); - - /* (5)VCC5 OFF */ - corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_DAC_ON | POWER0_COM_OFF | POWER0_VCC5_OFF); - - /* (6)Set PDWN, INIOFF, DACOFF */ - corgi_ssp_lcdtg_send(PICTRL_ADRS, PICTRL_INIOFF | PICTRL_DAC_SIGNAL_OFF | - PICTRL_POWER_DOWN | PICTRL_COM_SIGNAL_OFF); - - /* (7)DAC OFF */ - corgi_ssp_lcdtg_send(POWERREG0_ADRS, POWER0_DAC_OFF | POWER0_COM_OFF | POWER0_VCC5_OFF); - - /* (8)VDD OFF */ - corgi_ssp_lcdtg_send(POWERREG1_ADRS, POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_OFF); - - lcd_inited = 0; -} - diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c deleted file mode 100644 index 9347254..0000000 --- a/arch/arm/mach-pxa/corgi_ssp.c +++ /dev/null @@ -1,274 +0,0 @@ -/* - * SSP control code for Sharp Corgi devices - * - * Copyright (c) 2004-2005 Richard Purdie - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include "sharpsl.h" - -static DEFINE_SPINLOCK(corgi_ssp_lock); -static struct ssp_dev corgi_ssp_dev; -static struct ssp_state corgi_ssp_state; -static struct corgissp_machinfo *ssp_machinfo; - -/* - * There are three devices connected to the SSP interface: - * 1. A touchscreen controller (TI ADS7846 compatible) - * 2. An LCD controller (with some Backlight functionality) - * 3. A battery monitoring IC (Maxim MAX1111) - * - * Each device uses a different speed/mode of communication. - * - * The touchscreen is very sensitive and the most frequently used - * so the port is left configured for this. - * - * Devices are selected using Chip Selects on GPIOs. - */ - -/* - * ADS7846 Routines - */ -unsigned long corgi_ssp_ads7846_putget(ulong data) -{ - unsigned long flag; - u32 ret = 0; - - spin_lock_irqsave(&corgi_ssp_lock, flag); - if (ssp_machinfo->cs_ads7846 >= 0) - GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); - - ssp_write_word(&corgi_ssp_dev,data); - ssp_read_word(&corgi_ssp_dev, &ret); - - if (ssp_machinfo->cs_ads7846 >= 0) - GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); - spin_unlock_irqrestore(&corgi_ssp_lock, flag); - - return ret; -} - -/* - * NOTE: These functions should always be called in interrupt context - * and use the _lock and _unlock functions. They are very time sensitive. - */ -void corgi_ssp_ads7846_lock(void) -{ - spin_lock(&corgi_ssp_lock); - if (ssp_machinfo->cs_ads7846 >= 0) - GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); -} - -void corgi_ssp_ads7846_unlock(void) -{ - if (ssp_machinfo->cs_ads7846 >= 0) - GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); - spin_unlock(&corgi_ssp_lock); -} - -void corgi_ssp_ads7846_put(ulong data) -{ - ssp_write_word(&corgi_ssp_dev,data); -} - -unsigned long corgi_ssp_ads7846_get(void) -{ - u32 ret = 0; - ssp_read_word(&corgi_ssp_dev, &ret); - return ret; -} - -EXPORT_SYMBOL(corgi_ssp_ads7846_putget); -EXPORT_SYMBOL(corgi_ssp_ads7846_lock); -EXPORT_SYMBOL(corgi_ssp_ads7846_unlock); -EXPORT_SYMBOL(corgi_ssp_ads7846_put); -EXPORT_SYMBOL(corgi_ssp_ads7846_get); - - -/* - * LCD/Backlight Routines - */ -unsigned long corgi_ssp_dac_put(ulong data) -{ - unsigned long flag, sscr1 = SSCR1_SPH; - u32 tmp; - - spin_lock_irqsave(&corgi_ssp_lock, flag); - - if (machine_is_spitz() || machine_is_akita() || machine_is_borzoi()) - sscr1 = 0; - - ssp_disable(&corgi_ssp_dev); - ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), sscr1, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_lcdcon)); - ssp_enable(&corgi_ssp_dev); - - if (ssp_machinfo->cs_lcdcon >= 0) - GPCR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); - ssp_write_word(&corgi_ssp_dev,data); - /* Read null data back from device to prevent SSP overflow */ - ssp_read_word(&corgi_ssp_dev, &tmp); - if (ssp_machinfo->cs_lcdcon >= 0) - GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); - - ssp_disable(&corgi_ssp_dev); - ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846)); - ssp_enable(&corgi_ssp_dev); - - spin_unlock_irqrestore(&corgi_ssp_lock, flag); - - return 0; -} - -void corgi_ssp_lcdtg_send(u8 adrs, u8 data) -{ - corgi_ssp_dac_put(((adrs & 0x07) << 5) | (data & 0x1f)); -} - -void corgi_ssp_blduty_set(int duty) -{ - corgi_ssp_lcdtg_send(0x02,duty); -} - -EXPORT_SYMBOL(corgi_ssp_lcdtg_send); -EXPORT_SYMBOL(corgi_ssp_blduty_set); - -/* - * Max1111 Routines - */ -int corgi_ssp_max1111_get(ulong data) -{ - unsigned long flag; - long voltage = 0, voltage1 = 0, voltage2 = 0; - - spin_lock_irqsave(&corgi_ssp_lock, flag); - if (ssp_machinfo->cs_max1111 >= 0) - GPCR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); - ssp_disable(&corgi_ssp_dev); - ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_max1111)); - ssp_enable(&corgi_ssp_dev); - - udelay(1); - - /* TB1/RB1 */ - ssp_write_word(&corgi_ssp_dev,data); - ssp_read_word(&corgi_ssp_dev, (u32*)&voltage1); /* null read */ - - /* TB12/RB2 */ - ssp_write_word(&corgi_ssp_dev,0); - ssp_read_word(&corgi_ssp_dev, (u32*)&voltage1); - - /* TB13/RB3*/ - ssp_write_word(&corgi_ssp_dev,0); - ssp_read_word(&corgi_ssp_dev, (u32*)&voltage2); - - ssp_disable(&corgi_ssp_dev); - ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846)); - ssp_enable(&corgi_ssp_dev); - if (ssp_machinfo->cs_max1111 >= 0) - GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); - spin_unlock_irqrestore(&corgi_ssp_lock, flag); - - if (voltage1 & 0xc0 || voltage2 & 0x3f) - voltage = -1; - else - voltage = ((voltage1 << 2) & 0xfc) | ((voltage2 >> 6) & 0x03); - - return voltage; -} - -EXPORT_SYMBOL(corgi_ssp_max1111_get); - -/* - * Support Routines - */ - -void __init corgi_ssp_set_machinfo(struct corgissp_machinfo *machinfo) -{ - ssp_machinfo = machinfo; -} - -static int __devinit corgi_ssp_probe(struct platform_device *dev) -{ - int ret; - - /* Chip Select - Disable All */ - if (ssp_machinfo->cs_lcdcon >= 0) - pxa_gpio_mode(ssp_machinfo->cs_lcdcon | GPIO_OUT | GPIO_DFLT_HIGH); - if (ssp_machinfo->cs_max1111 >= 0) - pxa_gpio_mode(ssp_machinfo->cs_max1111 | GPIO_OUT | GPIO_DFLT_HIGH); - if (ssp_machinfo->cs_ads7846 >= 0) - pxa_gpio_mode(ssp_machinfo->cs_ads7846 | GPIO_OUT | GPIO_DFLT_HIGH); - - ret = ssp_init(&corgi_ssp_dev, ssp_machinfo->port, 0); - - if (ret) - printk(KERN_ERR "Unable to register SSP handler!\n"); - else { - ssp_disable(&corgi_ssp_dev); - ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846)); - ssp_enable(&corgi_ssp_dev); - } - - return ret; -} - -static int corgi_ssp_remove(struct platform_device *dev) -{ - ssp_exit(&corgi_ssp_dev); - return 0; -} - -static int corgi_ssp_suspend(struct platform_device *dev, pm_message_t state) -{ - ssp_flush(&corgi_ssp_dev); - ssp_save_state(&corgi_ssp_dev,&corgi_ssp_state); - - return 0; -} - -static int corgi_ssp_resume(struct platform_device *dev) -{ - if (ssp_machinfo->cs_lcdcon >= 0) - GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); /* High - Disable LCD Control/Timing Gen */ - if (ssp_machinfo->cs_max1111 >= 0) - GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); /* High - Disable MAX1111*/ - if (ssp_machinfo->cs_ads7846 >= 0) - GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); /* High - Disable ADS7846*/ - ssp_restore_state(&corgi_ssp_dev,&corgi_ssp_state); - ssp_enable(&corgi_ssp_dev); - - return 0; -} - -static struct platform_driver corgissp_driver = { - .probe = corgi_ssp_probe, - .remove = corgi_ssp_remove, - .suspend = corgi_ssp_suspend, - .resume = corgi_ssp_resume, - .driver = { - .name = "corgi-ssp", - }, -}; - -int __init corgi_ssp_init(void) -{ - return platform_driver_register(&corgissp_driver); -} - -arch_initcall(corgi_ssp_init); diff --git a/arch/arm/mach-pxa/include/mach/corgi.h b/arch/arm/mach-pxa/include/mach/corgi.h index 7239281..585970e 100644 --- a/arch/arm/mach-pxa/include/mach/corgi.h +++ b/arch/arm/mach-pxa/include/mach/corgi.h @@ -113,7 +113,6 @@ * Shared data structures */ extern struct platform_device corgiscoop_device; -extern struct platform_device corgissp_device; #endif /* __ASM_ARCH_CORGI_H */ diff --git a/arch/arm/mach-pxa/sharpsl.h b/arch/arm/mach-pxa/sharpsl.h index 1439785..0cc1203 100644 --- a/arch/arm/mach-pxa/sharpsl.h +++ b/arch/arm/mach-pxa/sharpsl.h @@ -10,29 +10,6 @@ #include /* - * SharpSL SSP Driver - */ -struct corgissp_machinfo { - int port; - int cs_lcdcon; - int cs_ads7846; - int cs_max1111; - int clk_lcdcon; - int clk_ads7846; - int clk_max1111; -}; - -void corgi_ssp_set_machinfo(struct corgissp_machinfo *machinfo); - - -/* - * SharpSL/Corgi LCD Driver - */ -void corgi_lcdtg_suspend(void); -void corgi_lcdtg_hw_init(int mode); - - -/* * SharpSL Battery/PM Driver */ #define READ_GPIO_BIT(x) (GPLR(x) & GPIO_bit(x)) -- cgit v0.10.2 From 793ffb9ed3179906760874689a99d4863d76914e Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Tue, 16 Mar 2010 14:44:05 +0800 Subject: [ARM] pxa: remove the now legacy SSP API Signed-off-by: Eric Miao diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index 089579f..8f7eb12 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -653,11 +653,6 @@ config PXA_SSP help Enable support for PXA2xx SSP ports -config PXA_SSP_LEGACY - bool - help - Support of legacy SSP API - config TOSA_BT tristate "Control the state of built-in bluetooth chip on Sharp SL-6000" depends on MACH_TOSA diff --git a/arch/arm/mach-pxa/include/mach/ssp.h b/arch/arm/mach-pxa/include/mach/ssp.h index be1be5b..8470a73 100644 --- a/arch/arm/mach-pxa/include/mach/ssp.h +++ b/arch/arm/mach-pxa/include/mach/ssp.h @@ -46,41 +46,6 @@ struct ssp_device { int drcmr_tx; }; -#ifdef CONFIG_PXA_SSP_LEGACY -/* - * SSP initialisation flags - */ -#define SSP_NO_IRQ 0x1 /* don't register an irq handler in SSP driver */ - -struct ssp_state { - u32 cr0; - u32 cr1; - u32 to; - u32 psp; -}; - -struct ssp_dev { - struct ssp_device *ssp; - u32 port; - u32 mode; - u32 flags; - u32 psp_flags; - u32 speed; - int irq; -}; - -int ssp_write_word(struct ssp_dev *dev, u32 data); -int ssp_read_word(struct ssp_dev *dev, u32 *data); -int ssp_flush(struct ssp_dev *dev); -void ssp_enable(struct ssp_dev *dev); -void ssp_disable(struct ssp_dev *dev); -void ssp_save_state(struct ssp_dev *dev, struct ssp_state *ssp); -void ssp_restore_state(struct ssp_dev *dev, struct ssp_state *ssp); -int ssp_init(struct ssp_dev *dev, u32 port, u32 init_flags); -int ssp_config(struct ssp_dev *dev, u32 mode, u32 flags, u32 psp_flags, u32 speed); -void ssp_exit(struct ssp_dev *dev); -#endif /* CONFIG_PXA_SSP_LEGACY */ - /** * ssp_write_reg - Write to a SSP register * diff --git a/arch/arm/mach-pxa/ssp.c b/arch/arm/mach-pxa/ssp.c index a81d6db..6e7df7a 100644 --- a/arch/arm/mach-pxa/ssp.c +++ b/arch/arm/mach-pxa/ssp.c @@ -35,278 +35,6 @@ #include #include -#ifdef CONFIG_PXA_SSP_LEGACY - -#define TIMEOUT 100000 - -static irqreturn_t ssp_interrupt(int irq, void *dev_id) -{ - struct ssp_dev *dev = dev_id; - struct ssp_device *ssp = dev->ssp; - unsigned int status; - - status = __raw_readl(ssp->mmio_base + SSSR); - __raw_writel(status, ssp->mmio_base + SSSR); - - if (status & SSSR_ROR) - printk(KERN_WARNING "SSP(%d): receiver overrun\n", dev->port); - - if (status & SSSR_TUR) - printk(KERN_WARNING "SSP(%d): transmitter underrun\n", dev->port); - - if (status & SSSR_BCE) - printk(KERN_WARNING "SSP(%d): bit count error\n", dev->port); - - return IRQ_HANDLED; -} - -/** - * ssp_write_word - write a word to the SSP port - * @data: 32-bit, MSB justified data to write. - * - * Wait for a free entry in the SSP transmit FIFO, and write a data - * word to the SSP port. - * - * The caller is expected to perform the necessary locking. - * - * Returns: - * %-ETIMEDOUT timeout occurred - * 0 success - */ -int ssp_write_word(struct ssp_dev *dev, u32 data) -{ - struct ssp_device *ssp = dev->ssp; - int timeout = TIMEOUT; - - while (!(__raw_readl(ssp->mmio_base + SSSR) & SSSR_TNF)) { - if (!--timeout) - return -ETIMEDOUT; - cpu_relax(); - } - - __raw_writel(data, ssp->mmio_base + SSDR); - - return 0; -} - -/** - * ssp_read_word - read a word from the SSP port - * - * Wait for a data word in the SSP receive FIFO, and return the - * received data. Data is LSB justified. - * - * Note: Currently, if data is not expected to be received, this - * function will wait for ever. - * - * The caller is expected to perform the necessary locking. - * - * Returns: - * %-ETIMEDOUT timeout occurred - * 32-bit data success - */ -int ssp_read_word(struct ssp_dev *dev, u32 *data) -{ - struct ssp_device *ssp = dev->ssp; - int timeout = TIMEOUT; - - while (!(__raw_readl(ssp->mmio_base + SSSR) & SSSR_RNE)) { - if (!--timeout) - return -ETIMEDOUT; - cpu_relax(); - } - - *data = __raw_readl(ssp->mmio_base + SSDR); - return 0; -} - -/** - * ssp_flush - flush the transmit and receive FIFOs - * - * Wait for the SSP to idle, and ensure that the receive FIFO - * is empty. - * - * The caller is expected to perform the necessary locking. - */ -int ssp_flush(struct ssp_dev *dev) -{ - struct ssp_device *ssp = dev->ssp; - int timeout = TIMEOUT * 2; - - /* ensure TX FIFO is empty instead of not full */ - if (cpu_is_pxa3xx()) { - while (__raw_readl(ssp->mmio_base + SSSR) & 0xf00) { - if (!--timeout) - return -ETIMEDOUT; - cpu_relax(); - } - timeout = TIMEOUT * 2; - } - - do { - while (__raw_readl(ssp->mmio_base + SSSR) & SSSR_RNE) { - if (!--timeout) - return -ETIMEDOUT; - (void)__raw_readl(ssp->mmio_base + SSDR); - } - if (!--timeout) - return -ETIMEDOUT; - } while (__raw_readl(ssp->mmio_base + SSSR) & SSSR_BSY); - - return 0; -} - -/** - * ssp_enable - enable the SSP port - * - * Turn on the SSP port. - */ -void ssp_enable(struct ssp_dev *dev) -{ - struct ssp_device *ssp = dev->ssp; - uint32_t sscr0; - - sscr0 = __raw_readl(ssp->mmio_base + SSCR0); - sscr0 |= SSCR0_SSE; - __raw_writel(sscr0, ssp->mmio_base + SSCR0); -} - -/** - * ssp_disable - shut down the SSP port - * - * Turn off the SSP port, optionally powering it down. - */ -void ssp_disable(struct ssp_dev *dev) -{ - struct ssp_device *ssp = dev->ssp; - uint32_t sscr0; - - sscr0 = __raw_readl(ssp->mmio_base + SSCR0); - sscr0 &= ~SSCR0_SSE; - __raw_writel(sscr0, ssp->mmio_base + SSCR0); -} - -/** - * ssp_save_state - save the SSP configuration - * @ssp: pointer to structure to save SSP configuration - * - * Save the configured SSP state for suspend. - */ -void ssp_save_state(struct ssp_dev *dev, struct ssp_state *state) -{ - struct ssp_device *ssp = dev->ssp; - - state->cr0 = __raw_readl(ssp->mmio_base + SSCR0); - state->cr1 = __raw_readl(ssp->mmio_base + SSCR1); - state->to = __raw_readl(ssp->mmio_base + SSTO); - state->psp = __raw_readl(ssp->mmio_base + SSPSP); - - ssp_disable(dev); -} - -/** - * ssp_restore_state - restore a previously saved SSP configuration - * @ssp: pointer to configuration saved by ssp_save_state - * - * Restore the SSP configuration saved previously by ssp_save_state. - */ -void ssp_restore_state(struct ssp_dev *dev, struct ssp_state *state) -{ - struct ssp_device *ssp = dev->ssp; - uint32_t sssr = SSSR_ROR | SSSR_TUR | SSSR_BCE; - - __raw_writel(sssr, ssp->mmio_base + SSSR); - - __raw_writel(state->cr0 & ~SSCR0_SSE, ssp->mmio_base + SSCR0); - __raw_writel(state->cr1, ssp->mmio_base + SSCR1); - __raw_writel(state->to, ssp->mmio_base + SSTO); - __raw_writel(state->psp, ssp->mmio_base + SSPSP); - __raw_writel(state->cr0, ssp->mmio_base + SSCR0); -} - -/** - * ssp_config - configure SSP port settings - * @mode: port operating mode - * @flags: port config flags - * @psp_flags: port PSP config flags - * @speed: port speed - * - * Port MUST be disabled by ssp_disable before making any config changes. - */ -int ssp_config(struct ssp_dev *dev, u32 mode, u32 flags, u32 psp_flags, u32 speed) -{ - struct ssp_device *ssp = dev->ssp; - - dev->mode = mode; - dev->flags = flags; - dev->psp_flags = psp_flags; - dev->speed = speed; - - /* set up port type, speed, port settings */ - __raw_writel((dev->speed | dev->mode), ssp->mmio_base + SSCR0); - __raw_writel(dev->flags, ssp->mmio_base + SSCR1); - __raw_writel(dev->psp_flags, ssp->mmio_base + SSPSP); - - return 0; -} - -/** - * ssp_init - setup the SSP port - * - * initialise and claim resources for the SSP port. - * - * Returns: - * %-ENODEV if the SSP port is unavailable - * %-EBUSY if the resources are already in use - * %0 on success - */ -int ssp_init(struct ssp_dev *dev, u32 port, u32 init_flags) -{ - struct ssp_device *ssp; - int ret; - - ssp = ssp_request(port, "SSP"); - if (ssp == NULL) - return -ENODEV; - - dev->ssp = ssp; - dev->port = port; - - /* do we need to get irq */ - if (!(init_flags & SSP_NO_IRQ)) { - ret = request_irq(ssp->irq, ssp_interrupt, - 0, "SSP", dev); - if (ret) - goto out_region; - dev->irq = ssp->irq; - } else - dev->irq = NO_IRQ; - - /* turn on SSP port clock */ - clk_enable(ssp->clk); - return 0; - -out_region: - ssp_free(ssp); - return ret; -} - -/** - * ssp_exit - undo the effects of ssp_init - * - * release and free resources for the SSP port. - */ -void ssp_exit(struct ssp_dev *dev) -{ - struct ssp_device *ssp = dev->ssp; - - ssp_disable(dev); - if (dev->irq != NO_IRQ) - free_irq(dev->irq, dev); - clk_disable(ssp->clk); - ssp_free(ssp); -} -#endif /* CONFIG_PXA_SSP_LEGACY */ - static DEFINE_MUTEX(ssp_lock); static LIST_HEAD(ssp_list); @@ -491,20 +219,6 @@ static void __exit pxa_ssp_exit(void) arch_initcall(pxa_ssp_init); module_exit(pxa_ssp_exit); -#ifdef CONFIG_PXA_SSP_LEGACY -EXPORT_SYMBOL(ssp_write_word); -EXPORT_SYMBOL(ssp_read_word); -EXPORT_SYMBOL(ssp_flush); -EXPORT_SYMBOL(ssp_enable); -EXPORT_SYMBOL(ssp_disable); -EXPORT_SYMBOL(ssp_save_state); -EXPORT_SYMBOL(ssp_restore_state); -EXPORT_SYMBOL(ssp_init); -EXPORT_SYMBOL(ssp_exit); -EXPORT_SYMBOL(ssp_config); -#endif - MODULE_DESCRIPTION("PXA SSP driver"); MODULE_AUTHOR("Liam Girdwood"); MODULE_LICENSE("GPL"); - -- cgit v0.10.2 From c9840daa70fbb8f6031fcd1f254a3da49a41ea7b Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Tue, 16 Mar 2010 16:48:01 +0800 Subject: [ARM] pxa: correct SSCR0_SCR to support multiple SoCs The previous definitions of SSCR0_SCR and SSCR0_SerClkDiv() prevented them being used simultaneously when supporting multiple PXA SoCs, esp. in drivers/spi/pxa2xx_spi.c, make them correct. The change from SSCR0_SerClkDiv(2) to SSCR0_SCR(2), will make the result a little bit different in pxa2xx_spi_probe(), however, since that's only used as a default initialization value, it's acceptable. Signed-off-by: Eric Miao diff --git a/arch/arm/mach-pxa/include/mach/regs-ssp.h b/arch/arm/mach-pxa/include/mach/regs-ssp.h index 6a2ed35..dd15dc3 100644 --- a/arch/arm/mach-pxa/include/mach/regs-ssp.h +++ b/arch/arm/mach-pxa/include/mach/regs-ssp.h @@ -33,14 +33,7 @@ #define SSCR0_National (0x2 << 4) /* National Microwire */ #define SSCR0_ECS (1 << 6) /* External clock select */ #define SSCR0_SSE (1 << 7) /* Synchronous Serial Port Enable */ - -#if defined(CONFIG_PXA25x) -#define SSCR0_SCR (0x0000ff00) /* Serial Clock Rate (mask) */ -#define SSCR0_SerClkDiv(x) ((((x) - 2)/2) << 8) /* Divisor [2..512] */ -#elif defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) -#define SSCR0_SCR (0x000fff00) /* Serial Clock Rate (mask) */ -#define SSCR0_SerClkDiv(x) (((x) - 1) << 8) /* Divisor [1..4096] */ -#endif +#define SSCR0_SCR(x) ((x) << 8) /* Serial Clock Rate (mask) */ #if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) #define SSCR0_EDSS (1 << 20) /* Extended data size select */ diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index 3682835..35d4e5cd 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c @@ -1318,14 +1318,14 @@ static int setup(struct spi_device *spi) /* NOTE: PXA25x_SSP _could_ use external clocking ... */ if (drv_data->ssp_type != PXA25x_SSP) dev_dbg(&spi->dev, "%ld Hz actual, %s\n", - clk_get_rate(ssp->clk) - / (1 + ((chip->cr0 & SSCR0_SCR) >> 8)), - chip->enable_dma ? "DMA" : "PIO"); + clk_get_rate(ssp->clk) + / (1 + ((chip->cr0 & SSCR0_SCR(0xfff)) >> 8)), + chip->enable_dma ? "DMA" : "PIO"); else dev_dbg(&spi->dev, "%ld Hz actual, %s\n", - clk_get_rate(ssp->clk) / 2 - / (1 + ((chip->cr0 & SSCR0_SCR) >> 8)), - chip->enable_dma ? "DMA" : "PIO"); + clk_get_rate(ssp->clk) / 2 + / (1 + ((chip->cr0 & SSCR0_SCR(0x0ff)) >> 8)), + chip->enable_dma ? "DMA" : "PIO"); if (spi->bits_per_word <= 8) { chip->n_bytes = 1; @@ -1558,7 +1558,7 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev) write_SSCR1(SSCR1_RxTresh(RX_THRESH_DFLT) | SSCR1_TxTresh(TX_THRESH_DFLT), drv_data->ioaddr); - write_SSCR0(SSCR0_SerClkDiv(2) + write_SSCR0(SSCR0_SCR(2) | SSCR0_Motorola | SSCR0_DataSize(8), drv_data->ioaddr); -- cgit v0.10.2 From 83f2889643d8efbc7fe925afbaa114e775699d7c Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Tue, 16 Mar 2010 17:03:20 +0800 Subject: [ARM] pxa: merge regs-ssp.h into ssp.h No need to separate them as they should be together from the begining. Signed-off-by: Eric Miao diff --git a/arch/arm/mach-pxa/include/mach/regs-ssp.h b/arch/arm/mach-pxa/include/mach/regs-ssp.h deleted file mode 100644 index dd15dc3..0000000 --- a/arch/arm/mach-pxa/include/mach/regs-ssp.h +++ /dev/null @@ -1,127 +0,0 @@ -#ifndef __ASM_ARCH_REGS_SSP_H -#define __ASM_ARCH_REGS_SSP_H - -/* - * SSP Serial Port Registers - * PXA250, PXA255, PXA26x and PXA27x SSP controllers are all slightly different. - * PXA255, PXA26x and PXA27x have extra ports, registers and bits. - */ - -#define SSCR0 (0x00) /* SSP Control Register 0 */ -#define SSCR1 (0x04) /* SSP Control Register 1 */ -#define SSSR (0x08) /* SSP Status Register */ -#define SSITR (0x0C) /* SSP Interrupt Test Register */ -#define SSDR (0x10) /* SSP Data Write/Data Read Register */ - -#define SSTO (0x28) /* SSP Time Out Register */ -#define SSPSP (0x2C) /* SSP Programmable Serial Protocol */ -#define SSTSA (0x30) /* SSP Tx Timeslot Active */ -#define SSRSA (0x34) /* SSP Rx Timeslot Active */ -#define SSTSS (0x38) /* SSP Timeslot Status */ -#define SSACD (0x3C) /* SSP Audio Clock Divider */ - -#if defined(CONFIG_PXA3xx) -#define SSACDD (0x40) /* SSP Audio Clock Dither Divider */ -#endif - -/* Common PXA2xx bits first */ -#define SSCR0_DSS (0x0000000f) /* Data Size Select (mask) */ -#define SSCR0_DataSize(x) ((x) - 1) /* Data Size Select [4..16] */ -#define SSCR0_FRF (0x00000030) /* FRame Format (mask) */ -#define SSCR0_Motorola (0x0 << 4) /* Motorola's Serial Peripheral Interface (SPI) */ -#define SSCR0_TI (0x1 << 4) /* Texas Instruments' Synchronous Serial Protocol (SSP) */ -#define SSCR0_National (0x2 << 4) /* National Microwire */ -#define SSCR0_ECS (1 << 6) /* External clock select */ -#define SSCR0_SSE (1 << 7) /* Synchronous Serial Port Enable */ -#define SSCR0_SCR(x) ((x) << 8) /* Serial Clock Rate (mask) */ - -#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) -#define SSCR0_EDSS (1 << 20) /* Extended data size select */ -#define SSCR0_NCS (1 << 21) /* Network clock select */ -#define SSCR0_RIM (1 << 22) /* Receive FIFO overrrun interrupt mask */ -#define SSCR0_TUM (1 << 23) /* Transmit FIFO underrun interrupt mask */ -#define SSCR0_FRDC (0x07000000) /* Frame rate divider control (mask) */ -#define SSCR0_SlotsPerFrm(x) (((x) - 1) << 24) /* Time slots per frame [1..8] */ -#define SSCR0_ACS (1 << 30) /* Audio clock select */ -#define SSCR0_MOD (1 << 31) /* Mode (normal or network) */ -#endif - -#if defined(CONFIG_PXA3xx) -#define SSCR0_FPCKE (1 << 29) /* FIFO packing enable */ -#endif - -#define SSCR1_RIE (1 << 0) /* Receive FIFO Interrupt Enable */ -#define SSCR1_TIE (1 << 1) /* Transmit FIFO Interrupt Enable */ -#define SSCR1_LBM (1 << 2) /* Loop-Back Mode */ -#define SSCR1_SPO (1 << 3) /* Motorola SPI SSPSCLK polarity setting */ -#define SSCR1_SPH (1 << 4) /* Motorola SPI SSPSCLK phase setting */ -#define SSCR1_MWDS (1 << 5) /* Microwire Transmit Data Size */ -#define SSCR1_TFT (0x000003c0) /* Transmit FIFO Threshold (mask) */ -#define SSCR1_TxTresh(x) (((x) - 1) << 6) /* level [1..16] */ -#define SSCR1_RFT (0x00003c00) /* Receive FIFO Threshold (mask) */ -#define SSCR1_RxTresh(x) (((x) - 1) << 10) /* level [1..16] */ - -#define SSSR_TNF (1 << 2) /* Transmit FIFO Not Full */ -#define SSSR_RNE (1 << 3) /* Receive FIFO Not Empty */ -#define SSSR_BSY (1 << 4) /* SSP Busy */ -#define SSSR_TFS (1 << 5) /* Transmit FIFO Service Request */ -#define SSSR_RFS (1 << 6) /* Receive FIFO Service Request */ -#define SSSR_ROR (1 << 7) /* Receive FIFO Overrun */ - -#define SSCR0_TIM (1 << 23) /* Transmit FIFO Under Run Interrupt Mask */ -#define SSCR0_RIM (1 << 22) /* Receive FIFO Over Run interrupt Mask */ -#define SSCR0_NCS (1 << 21) /* Network Clock Select */ -#define SSCR0_EDSS (1 << 20) /* Extended Data Size Select */ - -/* extra bits in PXA255, PXA26x and PXA27x SSP ports */ -#define SSCR0_TISSP (1 << 4) /* TI Sync Serial Protocol */ -#define SSCR0_PSP (3 << 4) /* PSP - Programmable Serial Protocol */ -#define SSCR1_TTELP (1 << 31) /* TXD Tristate Enable Last Phase */ -#define SSCR1_TTE (1 << 30) /* TXD Tristate Enable */ -#define SSCR1_EBCEI (1 << 29) /* Enable Bit Count Error interrupt */ -#define SSCR1_SCFR (1 << 28) /* Slave Clock free Running */ -#define SSCR1_ECRA (1 << 27) /* Enable Clock Request A */ -#define SSCR1_ECRB (1 << 26) /* Enable Clock request B */ -#define SSCR1_SCLKDIR (1 << 25) /* Serial Bit Rate Clock Direction */ -#define SSCR1_SFRMDIR (1 << 24) /* Frame Direction */ -#define SSCR1_RWOT (1 << 23) /* Receive Without Transmit */ -#define SSCR1_TRAIL (1 << 22) /* Trailing Byte */ -#define SSCR1_TSRE (1 << 21) /* Transmit Service Request Enable */ -#define SSCR1_RSRE (1 << 20) /* Receive Service Request Enable */ -#define SSCR1_TINTE (1 << 19) /* Receiver Time-out Interrupt enable */ -#define SSCR1_PINTE (1 << 18) /* Peripheral Trailing Byte Interupt Enable */ -#define SSCR1_IFS (1 << 16) /* Invert Frame Signal */ -#define SSCR1_STRF (1 << 15) /* Select FIFO or EFWR */ -#define SSCR1_EFWR (1 << 14) /* Enable FIFO Write/Read */ - -#define SSSR_BCE (1 << 23) /* Bit Count Error */ -#define SSSR_CSS (1 << 22) /* Clock Synchronisation Status */ -#define SSSR_TUR (1 << 21) /* Transmit FIFO Under Run */ -#define SSSR_EOC (1 << 20) /* End Of Chain */ -#define SSSR_TINT (1 << 19) /* Receiver Time-out Interrupt */ -#define SSSR_PINT (1 << 18) /* Peripheral Trailing Byte Interrupt */ - -#if defined(CONFIG_PXA3xx) -#define SSPSP_EDMYSTOP(x) ((x) << 28) /* Extended Dummy Stop */ -#define SSPSP_EDMYSTRT(x) ((x) << 26) /* Extended Dummy Start */ -#endif - -#define SSPSP_FSRT (1 << 25) /* Frame Sync Relative Timing */ -#define SSPSP_DMYSTOP(x) ((x) << 23) /* Dummy Stop */ -#define SSPSP_SFRMWDTH(x) ((x) << 16) /* Serial Frame Width */ -#define SSPSP_SFRMDLY(x) ((x) << 9) /* Serial Frame Delay */ -#define SSPSP_DMYSTRT(x) ((x) << 7) /* Dummy Start */ -#define SSPSP_STRTDLY(x) ((x) << 4) /* Start Delay */ -#define SSPSP_ETDS (1 << 3) /* End of Transfer data State */ -#define SSPSP_SFRMP (1 << 2) /* Serial Frame Polarity */ -#define SSPSP_SCMODE(x) ((x) << 0) /* Serial Bit Rate Clock Mode */ - -#define SSACD_SCDB (1 << 3) /* SSPSYSCLK Divider Bypass */ -#define SSACD_ACPS(x) ((x) << 4) /* Audio clock PLL select */ -#define SSACD_ACDS(x) ((x) << 0) /* Audio clock divider select */ -#if defined(CONFIG_PXA3xx) -#define SSACD_SCDX8 (1 << 7) /* SYSCLK division ratio select */ -#endif - - -#endif /* __ASM_ARCH_REGS_SSP_H */ diff --git a/arch/arm/mach-pxa/include/mach/ssp.h b/arch/arm/mach-pxa/include/mach/ssp.h index 8470a73..4c4ce62 100644 --- a/arch/arm/mach-pxa/include/mach/ssp.h +++ b/arch/arm/mach-pxa/include/mach/ssp.h @@ -22,6 +22,128 @@ #include #include +/* + * SSP Serial Port Registers + * PXA250, PXA255, PXA26x and PXA27x SSP controllers are all slightly different. + * PXA255, PXA26x and PXA27x have extra ports, registers and bits. + */ + +#define SSCR0 (0x00) /* SSP Control Register 0 */ +#define SSCR1 (0x04) /* SSP Control Register 1 */ +#define SSSR (0x08) /* SSP Status Register */ +#define SSITR (0x0C) /* SSP Interrupt Test Register */ +#define SSDR (0x10) /* SSP Data Write/Data Read Register */ + +#define SSTO (0x28) /* SSP Time Out Register */ +#define SSPSP (0x2C) /* SSP Programmable Serial Protocol */ +#define SSTSA (0x30) /* SSP Tx Timeslot Active */ +#define SSRSA (0x34) /* SSP Rx Timeslot Active */ +#define SSTSS (0x38) /* SSP Timeslot Status */ +#define SSACD (0x3C) /* SSP Audio Clock Divider */ + +#if defined(CONFIG_PXA3xx) +#define SSACDD (0x40) /* SSP Audio Clock Dither Divider */ +#endif + +/* Common PXA2xx bits first */ +#define SSCR0_DSS (0x0000000f) /* Data Size Select (mask) */ +#define SSCR0_DataSize(x) ((x) - 1) /* Data Size Select [4..16] */ +#define SSCR0_FRF (0x00000030) /* FRame Format (mask) */ +#define SSCR0_Motorola (0x0 << 4) /* Motorola's Serial Peripheral Interface (SPI) */ +#define SSCR0_TI (0x1 << 4) /* Texas Instruments' Synchronous Serial Protocol (SSP) */ +#define SSCR0_National (0x2 << 4) /* National Microwire */ +#define SSCR0_ECS (1 << 6) /* External clock select */ +#define SSCR0_SSE (1 << 7) /* Synchronous Serial Port Enable */ +#define SSCR0_SCR(x) ((x) << 8) /* Serial Clock Rate (mask) */ + +#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) +#define SSCR0_EDSS (1 << 20) /* Extended data size select */ +#define SSCR0_NCS (1 << 21) /* Network clock select */ +#define SSCR0_RIM (1 << 22) /* Receive FIFO overrrun interrupt mask */ +#define SSCR0_TUM (1 << 23) /* Transmit FIFO underrun interrupt mask */ +#define SSCR0_FRDC (0x07000000) /* Frame rate divider control (mask) */ +#define SSCR0_SlotsPerFrm(x) (((x) - 1) << 24) /* Time slots per frame [1..8] */ +#define SSCR0_ACS (1 << 30) /* Audio clock select */ +#define SSCR0_MOD (1 << 31) /* Mode (normal or network) */ +#endif + +#if defined(CONFIG_PXA3xx) +#define SSCR0_FPCKE (1 << 29) /* FIFO packing enable */ +#endif + +#define SSCR1_RIE (1 << 0) /* Receive FIFO Interrupt Enable */ +#define SSCR1_TIE (1 << 1) /* Transmit FIFO Interrupt Enable */ +#define SSCR1_LBM (1 << 2) /* Loop-Back Mode */ +#define SSCR1_SPO (1 << 3) /* Motorola SPI SSPSCLK polarity setting */ +#define SSCR1_SPH (1 << 4) /* Motorola SPI SSPSCLK phase setting */ +#define SSCR1_MWDS (1 << 5) /* Microwire Transmit Data Size */ +#define SSCR1_TFT (0x000003c0) /* Transmit FIFO Threshold (mask) */ +#define SSCR1_TxTresh(x) (((x) - 1) << 6) /* level [1..16] */ +#define SSCR1_RFT (0x00003c00) /* Receive FIFO Threshold (mask) */ +#define SSCR1_RxTresh(x) (((x) - 1) << 10) /* level [1..16] */ + +#define SSSR_TNF (1 << 2) /* Transmit FIFO Not Full */ +#define SSSR_RNE (1 << 3) /* Receive FIFO Not Empty */ +#define SSSR_BSY (1 << 4) /* SSP Busy */ +#define SSSR_TFS (1 << 5) /* Transmit FIFO Service Request */ +#define SSSR_RFS (1 << 6) /* Receive FIFO Service Request */ +#define SSSR_ROR (1 << 7) /* Receive FIFO Overrun */ + +#define SSCR0_TIM (1 << 23) /* Transmit FIFO Under Run Interrupt Mask */ +#define SSCR0_RIM (1 << 22) /* Receive FIFO Over Run interrupt Mask */ +#define SSCR0_NCS (1 << 21) /* Network Clock Select */ +#define SSCR0_EDSS (1 << 20) /* Extended Data Size Select */ + +/* extra bits in PXA255, PXA26x and PXA27x SSP ports */ +#define SSCR0_TISSP (1 << 4) /* TI Sync Serial Protocol */ +#define SSCR0_PSP (3 << 4) /* PSP - Programmable Serial Protocol */ +#define SSCR1_TTELP (1 << 31) /* TXD Tristate Enable Last Phase */ +#define SSCR1_TTE (1 << 30) /* TXD Tristate Enable */ +#define SSCR1_EBCEI (1 << 29) /* Enable Bit Count Error interrupt */ +#define SSCR1_SCFR (1 << 28) /* Slave Clock free Running */ +#define SSCR1_ECRA (1 << 27) /* Enable Clock Request A */ +#define SSCR1_ECRB (1 << 26) /* Enable Clock request B */ +#define SSCR1_SCLKDIR (1 << 25) /* Serial Bit Rate Clock Direction */ +#define SSCR1_SFRMDIR (1 << 24) /* Frame Direction */ +#define SSCR1_RWOT (1 << 23) /* Receive Without Transmit */ +#define SSCR1_TRAIL (1 << 22) /* Trailing Byte */ +#define SSCR1_TSRE (1 << 21) /* Transmit Service Request Enable */ +#define SSCR1_RSRE (1 << 20) /* Receive Service Request Enable */ +#define SSCR1_TINTE (1 << 19) /* Receiver Time-out Interrupt enable */ +#define SSCR1_PINTE (1 << 18) /* Peripheral Trailing Byte Interupt Enable */ +#define SSCR1_IFS (1 << 16) /* Invert Frame Signal */ +#define SSCR1_STRF (1 << 15) /* Select FIFO or EFWR */ +#define SSCR1_EFWR (1 << 14) /* Enable FIFO Write/Read */ + +#define SSSR_BCE (1 << 23) /* Bit Count Error */ +#define SSSR_CSS (1 << 22) /* Clock Synchronisation Status */ +#define SSSR_TUR (1 << 21) /* Transmit FIFO Under Run */ +#define SSSR_EOC (1 << 20) /* End Of Chain */ +#define SSSR_TINT (1 << 19) /* Receiver Time-out Interrupt */ +#define SSSR_PINT (1 << 18) /* Peripheral Trailing Byte Interrupt */ + +#if defined(CONFIG_PXA3xx) +#define SSPSP_EDMYSTOP(x) ((x) << 28) /* Extended Dummy Stop */ +#define SSPSP_EDMYSTRT(x) ((x) << 26) /* Extended Dummy Start */ +#endif + +#define SSPSP_FSRT (1 << 25) /* Frame Sync Relative Timing */ +#define SSPSP_DMYSTOP(x) ((x) << 23) /* Dummy Stop */ +#define SSPSP_SFRMWDTH(x) ((x) << 16) /* Serial Frame Width */ +#define SSPSP_SFRMDLY(x) ((x) << 9) /* Serial Frame Delay */ +#define SSPSP_DMYSTRT(x) ((x) << 7) /* Dummy Start */ +#define SSPSP_STRTDLY(x) ((x) << 4) /* Start Delay */ +#define SSPSP_ETDS (1 << 3) /* End of Transfer data State */ +#define SSPSP_SFRMP (1 << 2) /* Serial Frame Polarity */ +#define SSPSP_SCMODE(x) ((x) << 0) /* Serial Bit Rate Clock Mode */ + +#define SSACD_SCDB (1 << 3) /* SSPSYSCLK Divider Bypass */ +#define SSACD_ACPS(x) ((x) << 4) /* Audio clock PLL select */ +#define SSACD_ACDS(x) ((x) << 0) /* Audio clock divider select */ +#if defined(CONFIG_PXA3xx) +#define SSACD_SCDX8 (1 << 7) /* SYSCLK division ratio select */ +#endif + enum pxa_ssp_type { SSP_UNDEFINED = 0, PXA25x_SSP, /* pxa 210, 250, 255, 26x */ diff --git a/arch/arm/mach-pxa/ssp.c b/arch/arm/mach-pxa/ssp.c index 6e7df7a..a9b2d3e 100644 --- a/arch/arm/mach-pxa/ssp.c +++ b/arch/arm/mach-pxa/ssp.c @@ -33,7 +33,6 @@ #include #include #include -#include static DEFINE_MUTEX(ssp_lock); static LIST_HEAD(ssp_list); diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index 35d4e5cd..959e78b 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c @@ -36,7 +36,6 @@ #include #include -#include #include #include diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index 544fd95..2e27962 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c @@ -32,7 +32,6 @@ #include #include -#include #include #include -- cgit v0.10.2 From be1194cca55961b4dd98ea17fb24f0ffc6fa2213 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Tue, 16 Mar 2010 17:21:57 +0800 Subject: [ARM] pxa: remove unnecessary #include of Signed-off-by: Eric Miao diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c index fa527b2..be727ae 100644 --- a/arch/arm/mach-pxa/littleton.c +++ b/arch/arm/mach-pxa/littleton.c @@ -41,7 +41,6 @@ #include #include -#include #include #include #include diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c index d58a524..48b10c7 100644 --- a/arch/arm/mach-pxa/poodle.c +++ b/arch/arm/mach-pxa/poodle.c @@ -45,7 +45,6 @@ #include #include #include -#include #include #include diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c index 4d7c03e..f544e58 100644 --- a/arch/arm/mach-pxa/pxa3xx.c +++ b/arch/arm/mach-pxa/pxa3xx.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include -- cgit v0.10.2 From 54c39b420f017c546fb130a05c14bdb0a7910f98 Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Tue, 16 Mar 2010 17:12:37 +0800 Subject: [ARM] pxa: move ssp into common plat-pxa Signed-off-by: Haojian Zhuang Acked-by: Mark Brown Signed-off-by: Eric Miao diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index 8f7eb12..6dd450a 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -648,11 +648,6 @@ config PXA_SHARP_Cxx00 help Enable common support for Sharp Cxx00 models -config PXA_SSP - tristate - help - Enable support for PXA2xx SSP ports - config TOSA_BT tristate "Control the state of built-in bluetooth chip on Sharp SL-6000" depends on MACH_TOSA diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index a83aff3..cf57fb2 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -14,7 +14,6 @@ obj-$(CONFIG_PXA3xx) += cpufreq-pxa3xx.o endif # Generic drivers that other drivers may depend upon -obj-$(CONFIG_PXA_SSP) += ssp.o # SoC-specific code obj-$(CONFIG_PXA25x) += mfp-pxa2xx.o pxa2xx.o pxa25x.o diff --git a/arch/arm/mach-pxa/include/mach/ssp.h b/arch/arm/mach-pxa/include/mach/ssp.h deleted file mode 100644 index 4c4ce62..0000000 --- a/arch/arm/mach-pxa/include/mach/ssp.h +++ /dev/null @@ -1,196 +0,0 @@ -/* - * ssp.h - * - * Copyright (C) 2003 Russell King, All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This driver supports the following PXA CPU/SSP ports:- - * - * PXA250 SSP - * PXA255 SSP, NSSP - * PXA26x SSP, NSSP, ASSP - * PXA27x SSP1, SSP2, SSP3 - * PXA3xx SSP1, SSP2, SSP3, SSP4 - */ - -#ifndef __ASM_ARCH_SSP_H -#define __ASM_ARCH_SSP_H - -#include -#include - -/* - * SSP Serial Port Registers - * PXA250, PXA255, PXA26x and PXA27x SSP controllers are all slightly different. - * PXA255, PXA26x and PXA27x have extra ports, registers and bits. - */ - -#define SSCR0 (0x00) /* SSP Control Register 0 */ -#define SSCR1 (0x04) /* SSP Control Register 1 */ -#define SSSR (0x08) /* SSP Status Register */ -#define SSITR (0x0C) /* SSP Interrupt Test Register */ -#define SSDR (0x10) /* SSP Data Write/Data Read Register */ - -#define SSTO (0x28) /* SSP Time Out Register */ -#define SSPSP (0x2C) /* SSP Programmable Serial Protocol */ -#define SSTSA (0x30) /* SSP Tx Timeslot Active */ -#define SSRSA (0x34) /* SSP Rx Timeslot Active */ -#define SSTSS (0x38) /* SSP Timeslot Status */ -#define SSACD (0x3C) /* SSP Audio Clock Divider */ - -#if defined(CONFIG_PXA3xx) -#define SSACDD (0x40) /* SSP Audio Clock Dither Divider */ -#endif - -/* Common PXA2xx bits first */ -#define SSCR0_DSS (0x0000000f) /* Data Size Select (mask) */ -#define SSCR0_DataSize(x) ((x) - 1) /* Data Size Select [4..16] */ -#define SSCR0_FRF (0x00000030) /* FRame Format (mask) */ -#define SSCR0_Motorola (0x0 << 4) /* Motorola's Serial Peripheral Interface (SPI) */ -#define SSCR0_TI (0x1 << 4) /* Texas Instruments' Synchronous Serial Protocol (SSP) */ -#define SSCR0_National (0x2 << 4) /* National Microwire */ -#define SSCR0_ECS (1 << 6) /* External clock select */ -#define SSCR0_SSE (1 << 7) /* Synchronous Serial Port Enable */ -#define SSCR0_SCR(x) ((x) << 8) /* Serial Clock Rate (mask) */ - -#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) -#define SSCR0_EDSS (1 << 20) /* Extended data size select */ -#define SSCR0_NCS (1 << 21) /* Network clock select */ -#define SSCR0_RIM (1 << 22) /* Receive FIFO overrrun interrupt mask */ -#define SSCR0_TUM (1 << 23) /* Transmit FIFO underrun interrupt mask */ -#define SSCR0_FRDC (0x07000000) /* Frame rate divider control (mask) */ -#define SSCR0_SlotsPerFrm(x) (((x) - 1) << 24) /* Time slots per frame [1..8] */ -#define SSCR0_ACS (1 << 30) /* Audio clock select */ -#define SSCR0_MOD (1 << 31) /* Mode (normal or network) */ -#endif - -#if defined(CONFIG_PXA3xx) -#define SSCR0_FPCKE (1 << 29) /* FIFO packing enable */ -#endif - -#define SSCR1_RIE (1 << 0) /* Receive FIFO Interrupt Enable */ -#define SSCR1_TIE (1 << 1) /* Transmit FIFO Interrupt Enable */ -#define SSCR1_LBM (1 << 2) /* Loop-Back Mode */ -#define SSCR1_SPO (1 << 3) /* Motorola SPI SSPSCLK polarity setting */ -#define SSCR1_SPH (1 << 4) /* Motorola SPI SSPSCLK phase setting */ -#define SSCR1_MWDS (1 << 5) /* Microwire Transmit Data Size */ -#define SSCR1_TFT (0x000003c0) /* Transmit FIFO Threshold (mask) */ -#define SSCR1_TxTresh(x) (((x) - 1) << 6) /* level [1..16] */ -#define SSCR1_RFT (0x00003c00) /* Receive FIFO Threshold (mask) */ -#define SSCR1_RxTresh(x) (((x) - 1) << 10) /* level [1..16] */ - -#define SSSR_TNF (1 << 2) /* Transmit FIFO Not Full */ -#define SSSR_RNE (1 << 3) /* Receive FIFO Not Empty */ -#define SSSR_BSY (1 << 4) /* SSP Busy */ -#define SSSR_TFS (1 << 5) /* Transmit FIFO Service Request */ -#define SSSR_RFS (1 << 6) /* Receive FIFO Service Request */ -#define SSSR_ROR (1 << 7) /* Receive FIFO Overrun */ - -#define SSCR0_TIM (1 << 23) /* Transmit FIFO Under Run Interrupt Mask */ -#define SSCR0_RIM (1 << 22) /* Receive FIFO Over Run interrupt Mask */ -#define SSCR0_NCS (1 << 21) /* Network Clock Select */ -#define SSCR0_EDSS (1 << 20) /* Extended Data Size Select */ - -/* extra bits in PXA255, PXA26x and PXA27x SSP ports */ -#define SSCR0_TISSP (1 << 4) /* TI Sync Serial Protocol */ -#define SSCR0_PSP (3 << 4) /* PSP - Programmable Serial Protocol */ -#define SSCR1_TTELP (1 << 31) /* TXD Tristate Enable Last Phase */ -#define SSCR1_TTE (1 << 30) /* TXD Tristate Enable */ -#define SSCR1_EBCEI (1 << 29) /* Enable Bit Count Error interrupt */ -#define SSCR1_SCFR (1 << 28) /* Slave Clock free Running */ -#define SSCR1_ECRA (1 << 27) /* Enable Clock Request A */ -#define SSCR1_ECRB (1 << 26) /* Enable Clock request B */ -#define SSCR1_SCLKDIR (1 << 25) /* Serial Bit Rate Clock Direction */ -#define SSCR1_SFRMDIR (1 << 24) /* Frame Direction */ -#define SSCR1_RWOT (1 << 23) /* Receive Without Transmit */ -#define SSCR1_TRAIL (1 << 22) /* Trailing Byte */ -#define SSCR1_TSRE (1 << 21) /* Transmit Service Request Enable */ -#define SSCR1_RSRE (1 << 20) /* Receive Service Request Enable */ -#define SSCR1_TINTE (1 << 19) /* Receiver Time-out Interrupt enable */ -#define SSCR1_PINTE (1 << 18) /* Peripheral Trailing Byte Interupt Enable */ -#define SSCR1_IFS (1 << 16) /* Invert Frame Signal */ -#define SSCR1_STRF (1 << 15) /* Select FIFO or EFWR */ -#define SSCR1_EFWR (1 << 14) /* Enable FIFO Write/Read */ - -#define SSSR_BCE (1 << 23) /* Bit Count Error */ -#define SSSR_CSS (1 << 22) /* Clock Synchronisation Status */ -#define SSSR_TUR (1 << 21) /* Transmit FIFO Under Run */ -#define SSSR_EOC (1 << 20) /* End Of Chain */ -#define SSSR_TINT (1 << 19) /* Receiver Time-out Interrupt */ -#define SSSR_PINT (1 << 18) /* Peripheral Trailing Byte Interrupt */ - -#if defined(CONFIG_PXA3xx) -#define SSPSP_EDMYSTOP(x) ((x) << 28) /* Extended Dummy Stop */ -#define SSPSP_EDMYSTRT(x) ((x) << 26) /* Extended Dummy Start */ -#endif - -#define SSPSP_FSRT (1 << 25) /* Frame Sync Relative Timing */ -#define SSPSP_DMYSTOP(x) ((x) << 23) /* Dummy Stop */ -#define SSPSP_SFRMWDTH(x) ((x) << 16) /* Serial Frame Width */ -#define SSPSP_SFRMDLY(x) ((x) << 9) /* Serial Frame Delay */ -#define SSPSP_DMYSTRT(x) ((x) << 7) /* Dummy Start */ -#define SSPSP_STRTDLY(x) ((x) << 4) /* Start Delay */ -#define SSPSP_ETDS (1 << 3) /* End of Transfer data State */ -#define SSPSP_SFRMP (1 << 2) /* Serial Frame Polarity */ -#define SSPSP_SCMODE(x) ((x) << 0) /* Serial Bit Rate Clock Mode */ - -#define SSACD_SCDB (1 << 3) /* SSPSYSCLK Divider Bypass */ -#define SSACD_ACPS(x) ((x) << 4) /* Audio clock PLL select */ -#define SSACD_ACDS(x) ((x) << 0) /* Audio clock divider select */ -#if defined(CONFIG_PXA3xx) -#define SSACD_SCDX8 (1 << 7) /* SYSCLK division ratio select */ -#endif - -enum pxa_ssp_type { - SSP_UNDEFINED = 0, - PXA25x_SSP, /* pxa 210, 250, 255, 26x */ - PXA25x_NSSP, /* pxa 255, 26x (including ASSP) */ - PXA27x_SSP, -}; - -struct ssp_device { - struct platform_device *pdev; - struct list_head node; - - struct clk *clk; - void __iomem *mmio_base; - unsigned long phys_base; - - const char *label; - int port_id; - int type; - int use_count; - int irq; - int drcmr_rx; - int drcmr_tx; -}; - -/** - * ssp_write_reg - Write to a SSP register - * - * @dev: SSP device to access - * @reg: Register to write to - * @val: Value to be written. - */ -static inline void ssp_write_reg(struct ssp_device *dev, u32 reg, u32 val) -{ - __raw_writel(val, dev->mmio_base + reg); -} - -/** - * ssp_read_reg - Read from a SSP register - * - * @dev: SSP device to access - * @reg: Register to read from - */ -static inline u32 ssp_read_reg(struct ssp_device *dev, u32 reg) -{ - return __raw_readl(dev->mmio_base + reg); -} - -struct ssp_device *ssp_request(int port, const char *label); -void ssp_free(struct ssp_device *); -#endif /* __ASM_ARCH_SSP_H */ diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c index 48b10c7..dcb1788 100644 --- a/arch/arm/mach-pxa/poodle.c +++ b/arch/arm/mach-pxa/poodle.c @@ -40,12 +40,12 @@ #include #include #include -#include #include #include #include #include #include +#include #include #include diff --git a/arch/arm/mach-pxa/ssp.c b/arch/arm/mach-pxa/ssp.c deleted file mode 100644 index a9b2d3e..0000000 --- a/arch/arm/mach-pxa/ssp.c +++ /dev/null @@ -1,223 +0,0 @@ -/* - * linux/arch/arm/mach-pxa/ssp.c - * - * based on linux/arch/arm/mach-sa1100/ssp.c by Russell King - * - * Copyright (C) 2003 Russell King. - * Copyright (C) 2003 Wolfson Microelectronics PLC - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * PXA2xx SSP driver. This provides the generic core for simple - * IO-based SSP applications and allows easy port setup for DMA access. - * - * Author: Liam Girdwood - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -static DEFINE_MUTEX(ssp_lock); -static LIST_HEAD(ssp_list); - -struct ssp_device *ssp_request(int port, const char *label) -{ - struct ssp_device *ssp = NULL; - - mutex_lock(&ssp_lock); - - list_for_each_entry(ssp, &ssp_list, node) { - if (ssp->port_id == port && ssp->use_count == 0) { - ssp->use_count++; - ssp->label = label; - break; - } - } - - mutex_unlock(&ssp_lock); - - if (&ssp->node == &ssp_list) - return NULL; - - return ssp; -} -EXPORT_SYMBOL(ssp_request); - -void ssp_free(struct ssp_device *ssp) -{ - mutex_lock(&ssp_lock); - if (ssp->use_count) { - ssp->use_count--; - ssp->label = NULL; - } else - dev_err(&ssp->pdev->dev, "device already free\n"); - mutex_unlock(&ssp_lock); -} -EXPORT_SYMBOL(ssp_free); - -static int __devinit ssp_probe(struct platform_device *pdev) -{ - const struct platform_device_id *id = platform_get_device_id(pdev); - struct resource *res; - struct ssp_device *ssp; - int ret = 0; - - ssp = kzalloc(sizeof(struct ssp_device), GFP_KERNEL); - if (ssp == NULL) { - dev_err(&pdev->dev, "failed to allocate memory"); - return -ENOMEM; - } - ssp->pdev = pdev; - - ssp->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(ssp->clk)) { - ret = PTR_ERR(ssp->clk); - goto err_free; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { - dev_err(&pdev->dev, "no memory resource defined\n"); - ret = -ENODEV; - goto err_free_clk; - } - - res = request_mem_region(res->start, res->end - res->start + 1, - pdev->name); - if (res == NULL) { - dev_err(&pdev->dev, "failed to request memory resource\n"); - ret = -EBUSY; - goto err_free_clk; - } - - ssp->phys_base = res->start; - - ssp->mmio_base = ioremap(res->start, res->end - res->start + 1); - if (ssp->mmio_base == NULL) { - dev_err(&pdev->dev, "failed to ioremap() registers\n"); - ret = -ENODEV; - goto err_free_mem; - } - - ssp->irq = platform_get_irq(pdev, 0); - if (ssp->irq < 0) { - dev_err(&pdev->dev, "no IRQ resource defined\n"); - ret = -ENODEV; - goto err_free_io; - } - - res = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (res == NULL) { - dev_err(&pdev->dev, "no SSP RX DRCMR defined\n"); - ret = -ENODEV; - goto err_free_io; - } - ssp->drcmr_rx = res->start; - - res = platform_get_resource(pdev, IORESOURCE_DMA, 1); - if (res == NULL) { - dev_err(&pdev->dev, "no SSP TX DRCMR defined\n"); - ret = -ENODEV; - goto err_free_io; - } - ssp->drcmr_tx = res->start; - - /* PXA2xx/3xx SSP ports starts from 1 and the internal pdev->id - * starts from 0, do a translation here - */ - ssp->port_id = pdev->id + 1; - ssp->use_count = 0; - ssp->type = (int)id->driver_data; - - mutex_lock(&ssp_lock); - list_add(&ssp->node, &ssp_list); - mutex_unlock(&ssp_lock); - - platform_set_drvdata(pdev, ssp); - return 0; - -err_free_io: - iounmap(ssp->mmio_base); -err_free_mem: - release_mem_region(res->start, res->end - res->start + 1); -err_free_clk: - clk_put(ssp->clk); -err_free: - kfree(ssp); - return ret; -} - -static int __devexit ssp_remove(struct platform_device *pdev) -{ - struct resource *res; - struct ssp_device *ssp; - - ssp = platform_get_drvdata(pdev); - if (ssp == NULL) - return -ENODEV; - - iounmap(ssp->mmio_base); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(res->start, res->end - res->start + 1); - - clk_put(ssp->clk); - - mutex_lock(&ssp_lock); - list_del(&ssp->node); - mutex_unlock(&ssp_lock); - - kfree(ssp); - return 0; -} - -static const struct platform_device_id ssp_id_table[] = { - { "pxa25x-ssp", PXA25x_SSP }, - { "pxa25x-nssp", PXA25x_NSSP }, - { "pxa27x-ssp", PXA27x_SSP }, - { }, -}; - -static struct platform_driver ssp_driver = { - .probe = ssp_probe, - .remove = __devexit_p(ssp_remove), - .driver = { - .owner = THIS_MODULE, - .name = "pxa2xx-ssp", - }, - .id_table = ssp_id_table, -}; - -static int __init pxa_ssp_init(void) -{ - return platform_driver_register(&ssp_driver); -} - -static void __exit pxa_ssp_exit(void) -{ - platform_driver_unregister(&ssp_driver); -} - -arch_initcall(pxa_ssp_init); -module_exit(pxa_ssp_exit); - -MODULE_DESCRIPTION("PXA SSP driver"); -MODULE_AUTHOR("Liam Girdwood"); -MODULE_LICENSE("GPL"); diff --git a/arch/arm/plat-pxa/Kconfig b/arch/arm/plat-pxa/Kconfig index b158e98..da53395 100644 --- a/arch/arm/plat-pxa/Kconfig +++ b/arch/arm/plat-pxa/Kconfig @@ -1,3 +1,8 @@ if PLAT_PXA +config PXA_SSP + tristate + help + Enable support for PXA2xx SSP ports + endif diff --git a/arch/arm/plat-pxa/Makefile b/arch/arm/plat-pxa/Makefile index 0264bfb..4aacdd1 100644 --- a/arch/arm/plat-pxa/Makefile +++ b/arch/arm/plat-pxa/Makefile @@ -9,3 +9,4 @@ obj-$(CONFIG_PXA3xx) += mfp.o obj-$(CONFIG_ARCH_MMP) += mfp.o obj-$(CONFIG_HAVE_PWM) += pwm.o +obj-$(CONFIG_PXA_SSP) += ssp.o diff --git a/arch/arm/plat-pxa/include/plat/ssp.h b/arch/arm/plat-pxa/include/plat/ssp.h new file mode 100644 index 0000000..4c4ce62 --- /dev/null +++ b/arch/arm/plat-pxa/include/plat/ssp.h @@ -0,0 +1,196 @@ +/* + * ssp.h + * + * Copyright (C) 2003 Russell King, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This driver supports the following PXA CPU/SSP ports:- + * + * PXA250 SSP + * PXA255 SSP, NSSP + * PXA26x SSP, NSSP, ASSP + * PXA27x SSP1, SSP2, SSP3 + * PXA3xx SSP1, SSP2, SSP3, SSP4 + */ + +#ifndef __ASM_ARCH_SSP_H +#define __ASM_ARCH_SSP_H + +#include +#include + +/* + * SSP Serial Port Registers + * PXA250, PXA255, PXA26x and PXA27x SSP controllers are all slightly different. + * PXA255, PXA26x and PXA27x have extra ports, registers and bits. + */ + +#define SSCR0 (0x00) /* SSP Control Register 0 */ +#define SSCR1 (0x04) /* SSP Control Register 1 */ +#define SSSR (0x08) /* SSP Status Register */ +#define SSITR (0x0C) /* SSP Interrupt Test Register */ +#define SSDR (0x10) /* SSP Data Write/Data Read Register */ + +#define SSTO (0x28) /* SSP Time Out Register */ +#define SSPSP (0x2C) /* SSP Programmable Serial Protocol */ +#define SSTSA (0x30) /* SSP Tx Timeslot Active */ +#define SSRSA (0x34) /* SSP Rx Timeslot Active */ +#define SSTSS (0x38) /* SSP Timeslot Status */ +#define SSACD (0x3C) /* SSP Audio Clock Divider */ + +#if defined(CONFIG_PXA3xx) +#define SSACDD (0x40) /* SSP Audio Clock Dither Divider */ +#endif + +/* Common PXA2xx bits first */ +#define SSCR0_DSS (0x0000000f) /* Data Size Select (mask) */ +#define SSCR0_DataSize(x) ((x) - 1) /* Data Size Select [4..16] */ +#define SSCR0_FRF (0x00000030) /* FRame Format (mask) */ +#define SSCR0_Motorola (0x0 << 4) /* Motorola's Serial Peripheral Interface (SPI) */ +#define SSCR0_TI (0x1 << 4) /* Texas Instruments' Synchronous Serial Protocol (SSP) */ +#define SSCR0_National (0x2 << 4) /* National Microwire */ +#define SSCR0_ECS (1 << 6) /* External clock select */ +#define SSCR0_SSE (1 << 7) /* Synchronous Serial Port Enable */ +#define SSCR0_SCR(x) ((x) << 8) /* Serial Clock Rate (mask) */ + +#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) +#define SSCR0_EDSS (1 << 20) /* Extended data size select */ +#define SSCR0_NCS (1 << 21) /* Network clock select */ +#define SSCR0_RIM (1 << 22) /* Receive FIFO overrrun interrupt mask */ +#define SSCR0_TUM (1 << 23) /* Transmit FIFO underrun interrupt mask */ +#define SSCR0_FRDC (0x07000000) /* Frame rate divider control (mask) */ +#define SSCR0_SlotsPerFrm(x) (((x) - 1) << 24) /* Time slots per frame [1..8] */ +#define SSCR0_ACS (1 << 30) /* Audio clock select */ +#define SSCR0_MOD (1 << 31) /* Mode (normal or network) */ +#endif + +#if defined(CONFIG_PXA3xx) +#define SSCR0_FPCKE (1 << 29) /* FIFO packing enable */ +#endif + +#define SSCR1_RIE (1 << 0) /* Receive FIFO Interrupt Enable */ +#define SSCR1_TIE (1 << 1) /* Transmit FIFO Interrupt Enable */ +#define SSCR1_LBM (1 << 2) /* Loop-Back Mode */ +#define SSCR1_SPO (1 << 3) /* Motorola SPI SSPSCLK polarity setting */ +#define SSCR1_SPH (1 << 4) /* Motorola SPI SSPSCLK phase setting */ +#define SSCR1_MWDS (1 << 5) /* Microwire Transmit Data Size */ +#define SSCR1_TFT (0x000003c0) /* Transmit FIFO Threshold (mask) */ +#define SSCR1_TxTresh(x) (((x) - 1) << 6) /* level [1..16] */ +#define SSCR1_RFT (0x00003c00) /* Receive FIFO Threshold (mask) */ +#define SSCR1_RxTresh(x) (((x) - 1) << 10) /* level [1..16] */ + +#define SSSR_TNF (1 << 2) /* Transmit FIFO Not Full */ +#define SSSR_RNE (1 << 3) /* Receive FIFO Not Empty */ +#define SSSR_BSY (1 << 4) /* SSP Busy */ +#define SSSR_TFS (1 << 5) /* Transmit FIFO Service Request */ +#define SSSR_RFS (1 << 6) /* Receive FIFO Service Request */ +#define SSSR_ROR (1 << 7) /* Receive FIFO Overrun */ + +#define SSCR0_TIM (1 << 23) /* Transmit FIFO Under Run Interrupt Mask */ +#define SSCR0_RIM (1 << 22) /* Receive FIFO Over Run interrupt Mask */ +#define SSCR0_NCS (1 << 21) /* Network Clock Select */ +#define SSCR0_EDSS (1 << 20) /* Extended Data Size Select */ + +/* extra bits in PXA255, PXA26x and PXA27x SSP ports */ +#define SSCR0_TISSP (1 << 4) /* TI Sync Serial Protocol */ +#define SSCR0_PSP (3 << 4) /* PSP - Programmable Serial Protocol */ +#define SSCR1_TTELP (1 << 31) /* TXD Tristate Enable Last Phase */ +#define SSCR1_TTE (1 << 30) /* TXD Tristate Enable */ +#define SSCR1_EBCEI (1 << 29) /* Enable Bit Count Error interrupt */ +#define SSCR1_SCFR (1 << 28) /* Slave Clock free Running */ +#define SSCR1_ECRA (1 << 27) /* Enable Clock Request A */ +#define SSCR1_ECRB (1 << 26) /* Enable Clock request B */ +#define SSCR1_SCLKDIR (1 << 25) /* Serial Bit Rate Clock Direction */ +#define SSCR1_SFRMDIR (1 << 24) /* Frame Direction */ +#define SSCR1_RWOT (1 << 23) /* Receive Without Transmit */ +#define SSCR1_TRAIL (1 << 22) /* Trailing Byte */ +#define SSCR1_TSRE (1 << 21) /* Transmit Service Request Enable */ +#define SSCR1_RSRE (1 << 20) /* Receive Service Request Enable */ +#define SSCR1_TINTE (1 << 19) /* Receiver Time-out Interrupt enable */ +#define SSCR1_PINTE (1 << 18) /* Peripheral Trailing Byte Interupt Enable */ +#define SSCR1_IFS (1 << 16) /* Invert Frame Signal */ +#define SSCR1_STRF (1 << 15) /* Select FIFO or EFWR */ +#define SSCR1_EFWR (1 << 14) /* Enable FIFO Write/Read */ + +#define SSSR_BCE (1 << 23) /* Bit Count Error */ +#define SSSR_CSS (1 << 22) /* Clock Synchronisation Status */ +#define SSSR_TUR (1 << 21) /* Transmit FIFO Under Run */ +#define SSSR_EOC (1 << 20) /* End Of Chain */ +#define SSSR_TINT (1 << 19) /* Receiver Time-out Interrupt */ +#define SSSR_PINT (1 << 18) /* Peripheral Trailing Byte Interrupt */ + +#if defined(CONFIG_PXA3xx) +#define SSPSP_EDMYSTOP(x) ((x) << 28) /* Extended Dummy Stop */ +#define SSPSP_EDMYSTRT(x) ((x) << 26) /* Extended Dummy Start */ +#endif + +#define SSPSP_FSRT (1 << 25) /* Frame Sync Relative Timing */ +#define SSPSP_DMYSTOP(x) ((x) << 23) /* Dummy Stop */ +#define SSPSP_SFRMWDTH(x) ((x) << 16) /* Serial Frame Width */ +#define SSPSP_SFRMDLY(x) ((x) << 9) /* Serial Frame Delay */ +#define SSPSP_DMYSTRT(x) ((x) << 7) /* Dummy Start */ +#define SSPSP_STRTDLY(x) ((x) << 4) /* Start Delay */ +#define SSPSP_ETDS (1 << 3) /* End of Transfer data State */ +#define SSPSP_SFRMP (1 << 2) /* Serial Frame Polarity */ +#define SSPSP_SCMODE(x) ((x) << 0) /* Serial Bit Rate Clock Mode */ + +#define SSACD_SCDB (1 << 3) /* SSPSYSCLK Divider Bypass */ +#define SSACD_ACPS(x) ((x) << 4) /* Audio clock PLL select */ +#define SSACD_ACDS(x) ((x) << 0) /* Audio clock divider select */ +#if defined(CONFIG_PXA3xx) +#define SSACD_SCDX8 (1 << 7) /* SYSCLK division ratio select */ +#endif + +enum pxa_ssp_type { + SSP_UNDEFINED = 0, + PXA25x_SSP, /* pxa 210, 250, 255, 26x */ + PXA25x_NSSP, /* pxa 255, 26x (including ASSP) */ + PXA27x_SSP, +}; + +struct ssp_device { + struct platform_device *pdev; + struct list_head node; + + struct clk *clk; + void __iomem *mmio_base; + unsigned long phys_base; + + const char *label; + int port_id; + int type; + int use_count; + int irq; + int drcmr_rx; + int drcmr_tx; +}; + +/** + * ssp_write_reg - Write to a SSP register + * + * @dev: SSP device to access + * @reg: Register to write to + * @val: Value to be written. + */ +static inline void ssp_write_reg(struct ssp_device *dev, u32 reg, u32 val) +{ + __raw_writel(val, dev->mmio_base + reg); +} + +/** + * ssp_read_reg - Read from a SSP register + * + * @dev: SSP device to access + * @reg: Register to read from + */ +static inline u32 ssp_read_reg(struct ssp_device *dev, u32 reg) +{ + return __raw_readl(dev->mmio_base + reg); +} + +struct ssp_device *ssp_request(int port, const char *label); +void ssp_free(struct ssp_device *); +#endif /* __ASM_ARCH_SSP_H */ diff --git a/arch/arm/plat-pxa/ssp.c b/arch/arm/plat-pxa/ssp.c new file mode 100644 index 0000000..5fe2301 --- /dev/null +++ b/arch/arm/plat-pxa/ssp.c @@ -0,0 +1,223 @@ +/* + * linux/arch/arm/mach-pxa/ssp.c + * + * based on linux/arch/arm/mach-sa1100/ssp.c by Russell King + * + * Copyright (C) 2003 Russell King. + * Copyright (C) 2003 Wolfson Microelectronics PLC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * PXA2xx SSP driver. This provides the generic core for simple + * IO-based SSP applications and allows easy port setup for DMA access. + * + * Author: Liam Girdwood + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static DEFINE_MUTEX(ssp_lock); +static LIST_HEAD(ssp_list); + +struct ssp_device *ssp_request(int port, const char *label) +{ + struct ssp_device *ssp = NULL; + + mutex_lock(&ssp_lock); + + list_for_each_entry(ssp, &ssp_list, node) { + if (ssp->port_id == port && ssp->use_count == 0) { + ssp->use_count++; + ssp->label = label; + break; + } + } + + mutex_unlock(&ssp_lock); + + if (&ssp->node == &ssp_list) + return NULL; + + return ssp; +} +EXPORT_SYMBOL(ssp_request); + +void ssp_free(struct ssp_device *ssp) +{ + mutex_lock(&ssp_lock); + if (ssp->use_count) { + ssp->use_count--; + ssp->label = NULL; + } else + dev_err(&ssp->pdev->dev, "device already free\n"); + mutex_unlock(&ssp_lock); +} +EXPORT_SYMBOL(ssp_free); + +static int __devinit ssp_probe(struct platform_device *pdev) +{ + const struct platform_device_id *id = platform_get_device_id(pdev); + struct resource *res; + struct ssp_device *ssp; + int ret = 0; + + ssp = kzalloc(sizeof(struct ssp_device), GFP_KERNEL); + if (ssp == NULL) { + dev_err(&pdev->dev, "failed to allocate memory"); + return -ENOMEM; + } + ssp->pdev = pdev; + + ssp->clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(ssp->clk)) { + ret = PTR_ERR(ssp->clk); + goto err_free; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + dev_err(&pdev->dev, "no memory resource defined\n"); + ret = -ENODEV; + goto err_free_clk; + } + + res = request_mem_region(res->start, res->end - res->start + 1, + pdev->name); + if (res == NULL) { + dev_err(&pdev->dev, "failed to request memory resource\n"); + ret = -EBUSY; + goto err_free_clk; + } + + ssp->phys_base = res->start; + + ssp->mmio_base = ioremap(res->start, res->end - res->start + 1); + if (ssp->mmio_base == NULL) { + dev_err(&pdev->dev, "failed to ioremap() registers\n"); + ret = -ENODEV; + goto err_free_mem; + } + + ssp->irq = platform_get_irq(pdev, 0); + if (ssp->irq < 0) { + dev_err(&pdev->dev, "no IRQ resource defined\n"); + ret = -ENODEV; + goto err_free_io; + } + + res = platform_get_resource(pdev, IORESOURCE_DMA, 0); + if (res == NULL) { + dev_err(&pdev->dev, "no SSP RX DRCMR defined\n"); + ret = -ENODEV; + goto err_free_io; + } + ssp->drcmr_rx = res->start; + + res = platform_get_resource(pdev, IORESOURCE_DMA, 1); + if (res == NULL) { + dev_err(&pdev->dev, "no SSP TX DRCMR defined\n"); + ret = -ENODEV; + goto err_free_io; + } + ssp->drcmr_tx = res->start; + + /* PXA2xx/3xx SSP ports starts from 1 and the internal pdev->id + * starts from 0, do a translation here + */ + ssp->port_id = pdev->id + 1; + ssp->use_count = 0; + ssp->type = (int)id->driver_data; + + mutex_lock(&ssp_lock); + list_add(&ssp->node, &ssp_list); + mutex_unlock(&ssp_lock); + + platform_set_drvdata(pdev, ssp); + return 0; + +err_free_io: + iounmap(ssp->mmio_base); +err_free_mem: + release_mem_region(res->start, res->end - res->start + 1); +err_free_clk: + clk_put(ssp->clk); +err_free: + kfree(ssp); + return ret; +} + +static int __devexit ssp_remove(struct platform_device *pdev) +{ + struct resource *res; + struct ssp_device *ssp; + + ssp = platform_get_drvdata(pdev); + if (ssp == NULL) + return -ENODEV; + + iounmap(ssp->mmio_base); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(res->start, res->end - res->start + 1); + + clk_put(ssp->clk); + + mutex_lock(&ssp_lock); + list_del(&ssp->node); + mutex_unlock(&ssp_lock); + + kfree(ssp); + return 0; +} + +static const struct platform_device_id ssp_id_table[] = { + { "pxa25x-ssp", PXA25x_SSP }, + { "pxa25x-nssp", PXA25x_NSSP }, + { "pxa27x-ssp", PXA27x_SSP }, + { }, +}; + +static struct platform_driver ssp_driver = { + .probe = ssp_probe, + .remove = __devexit_p(ssp_remove), + .driver = { + .owner = THIS_MODULE, + .name = "pxa2xx-ssp", + }, + .id_table = ssp_id_table, +}; + +static int __init pxa_ssp_init(void) +{ + return platform_driver_register(&ssp_driver); +} + +static void __exit pxa_ssp_exit(void) +{ + platform_driver_unregister(&ssp_driver); +} + +arch_initcall(pxa_ssp_init); +module_exit(pxa_ssp_exit); + +MODULE_DESCRIPTION("PXA SSP driver"); +MODULE_AUTHOR("Liam Girdwood"); +MODULE_LICENSE("GPL"); diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index 959e78b..50d6b78 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c @@ -36,7 +36,7 @@ #include #include -#include +#include #include MODULE_AUTHOR("Stephen Street"); diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index 2e27962..6271a10 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include "pxa2xx-pcm.h" #include "pxa-ssp.h" -- cgit v0.10.2 From 866d091dcb043594626d4facf7c6fcffcc7c8d35 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Tue, 16 Mar 2010 17:30:15 +0800 Subject: [ARM] pxa: remove incorrect select PXA_SSP in Kconfig PXA_SSP is actually used by drivers like drivers/spi/pxa2xx_spi.c and sound/soc/pxa/pxa-ssp.c, not by boards. Remove those incorrect 'select' from Kconfig and make SOC_PXA_SSP to select. Signed-off-by: Eric Miao diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index 6dd450a..352dc4f 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -19,7 +19,6 @@ config MACH_MAINSTONE config MACH_ZYLONITE bool select PXA3xx - select PXA_SSP select HAVE_PWM select PXA_HAVE_BOARD_IRQS @@ -39,7 +38,6 @@ config MACH_LITTLETON select PXA3xx select CPU_PXA300 select CPU_PXA310 - select PXA_SSP config MACH_TAVOREVB bool "PXA930 Evaluation Board (aka TavorEVB)" @@ -98,7 +96,6 @@ config MACH_ARMCORE select PXA27x select IWMMXT select PXA25x - select PXA_SSP config MACH_EM_X270 bool "CompuLab EM-x270 platform" @@ -161,7 +158,6 @@ config MACH_XCEP select MTD_CFI select MTD_CHAR select SMC91X - select PXA_SSP help PXA255 based Single Board Computer with SMC 91C111 ethernet chip and 64 MB of flash. Tuned for usage in Libera instruments for particle accelerators. @@ -180,7 +176,6 @@ config MACH_TRIZEPS4WL depends on TRIZEPS_PXA select TRIZEPS_PCMCIA select PXA27x - select PXA_SSP choice prompt "Select base board for Trizeps module" @@ -217,7 +212,6 @@ config MACH_PCM027 bool "Phytec phyCORE-PXA270 CPU module (PCM-027)" select PXA27x select IWMMXT - select PXA_SSP select PXA_HAVE_BOARD_IRQS config MACH_PCM990_BASEBOARD @@ -261,7 +255,6 @@ config MACH_H4700 bool "HP iPAQ hx4700" select PXA27x select IWMMXT - select PXA_SSP select HAVE_PWM select PXA_HAVE_BOARD_IRQS @@ -277,7 +270,6 @@ config MACH_MAGICIAN bool "Enable HTC Magician Support" select PXA27x select IWMMXT - select PXA_SSP select HAVE_PWM select PXA_HAVE_BOARD_IRQS @@ -431,13 +423,11 @@ config MACH_RAUMFELD_CONNECTOR bool "Raumfeld Connector" select PXA3xx select CPU_PXA300 - select PXA_SSP config MACH_RAUMFELD_SPEAKER bool "Raumfeld Speaker" select PXA3xx select CPU_PXA300 - select PXA_SSP config PXA_SHARPSL bool "SHARP Zaurus SL-5600, SL-C7xx and SL-Cxx00 Models" @@ -466,7 +456,6 @@ config MACH_POODLE depends on PXA_SHARPSL select PXA25x select SHARP_LOCOMO - select PXA_SSP select PXA_HAVE_BOARD_IRQS config MACH_CORGI @@ -636,14 +625,12 @@ config CPU_PXA950 config PXA_SHARP_C7xx bool - select PXA_SSP select SHARPSL_PM help Enable support for all Sharp C7xx models config PXA_SHARP_Cxx00 bool - select PXA_SSP select SHARPSL_PM help Enable common support for Sharp Cxx00 models diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index 376e14a..78e6121 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig @@ -23,6 +23,7 @@ config SND_PXA2XX_SOC_I2S config SND_PXA_SOC_SSP tristate + select PXA_SSP config SND_PXA2XX_SOC_CORGI tristate "SoC Audio support for Sharp Zaurus SL-C7x0" -- cgit v0.10.2 From 004690f05244e1a41824cda7dc4feb7804964dc6 Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Fri, 19 Mar 2010 11:52:39 -0400 Subject: [ARM] pxa: simplify ifdef in ssp.h Try to keep minimum ifdef in ssp.h. Some of the definitions are valid only to specific SoCs, and device drivers should be responsible to take care of these difference. Signed-off-by: Haojian Zhuang Signed-off-by: Eric Miao diff --git a/arch/arm/plat-pxa/include/plat/ssp.h b/arch/arm/plat-pxa/include/plat/ssp.h index 4c4ce62..74f70c7 100644 --- a/arch/arm/plat-pxa/include/plat/ssp.h +++ b/arch/arm/plat-pxa/include/plat/ssp.h @@ -40,10 +40,7 @@ #define SSRSA (0x34) /* SSP Rx Timeslot Active */ #define SSTSS (0x38) /* SSP Timeslot Status */ #define SSACD (0x3C) /* SSP Audio Clock Divider */ - -#if defined(CONFIG_PXA3xx) #define SSACDD (0x40) /* SSP Audio Clock Dither Divider */ -#endif /* Common PXA2xx bits first */ #define SSCR0_DSS (0x0000000f) /* Data Size Select (mask) */ @@ -56,20 +53,17 @@ #define SSCR0_SSE (1 << 7) /* Synchronous Serial Port Enable */ #define SSCR0_SCR(x) ((x) << 8) /* Serial Clock Rate (mask) */ -#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx) +/* PXA27x, PXA3xx */ #define SSCR0_EDSS (1 << 20) /* Extended data size select */ #define SSCR0_NCS (1 << 21) /* Network clock select */ #define SSCR0_RIM (1 << 22) /* Receive FIFO overrrun interrupt mask */ #define SSCR0_TUM (1 << 23) /* Transmit FIFO underrun interrupt mask */ #define SSCR0_FRDC (0x07000000) /* Frame rate divider control (mask) */ #define SSCR0_SlotsPerFrm(x) (((x) - 1) << 24) /* Time slots per frame [1..8] */ +#define SSCR0_FPCKE (1 << 29) /* FIFO packing enable */ #define SSCR0_ACS (1 << 30) /* Audio clock select */ #define SSCR0_MOD (1 << 31) /* Mode (normal or network) */ -#endif -#if defined(CONFIG_PXA3xx) -#define SSCR0_FPCKE (1 << 29) /* FIFO packing enable */ -#endif #define SSCR1_RIE (1 << 0) /* Receive FIFO Interrupt Enable */ #define SSCR1_TIE (1 << 1) /* Transmit FIFO Interrupt Enable */ @@ -89,10 +83,6 @@ #define SSSR_RFS (1 << 6) /* Receive FIFO Service Request */ #define SSSR_ROR (1 << 7) /* Receive FIFO Overrun */ -#define SSCR0_TIM (1 << 23) /* Transmit FIFO Under Run Interrupt Mask */ -#define SSCR0_RIM (1 << 22) /* Receive FIFO Over Run interrupt Mask */ -#define SSCR0_NCS (1 << 21) /* Network Clock Select */ -#define SSCR0_EDSS (1 << 20) /* Extended Data Size Select */ /* extra bits in PXA255, PXA26x and PXA27x SSP ports */ #define SSCR0_TISSP (1 << 4) /* TI Sync Serial Protocol */ @@ -122,27 +112,26 @@ #define SSSR_TINT (1 << 19) /* Receiver Time-out Interrupt */ #define SSSR_PINT (1 << 18) /* Peripheral Trailing Byte Interrupt */ -#if defined(CONFIG_PXA3xx) -#define SSPSP_EDMYSTOP(x) ((x) << 28) /* Extended Dummy Stop */ -#define SSPSP_EDMYSTRT(x) ((x) << 26) /* Extended Dummy Start */ -#endif -#define SSPSP_FSRT (1 << 25) /* Frame Sync Relative Timing */ -#define SSPSP_DMYSTOP(x) ((x) << 23) /* Dummy Stop */ -#define SSPSP_SFRMWDTH(x) ((x) << 16) /* Serial Frame Width */ -#define SSPSP_SFRMDLY(x) ((x) << 9) /* Serial Frame Delay */ -#define SSPSP_DMYSTRT(x) ((x) << 7) /* Dummy Start */ -#define SSPSP_STRTDLY(x) ((x) << 4) /* Start Delay */ -#define SSPSP_ETDS (1 << 3) /* End of Transfer data State */ -#define SSPSP_SFRMP (1 << 2) /* Serial Frame Polarity */ #define SSPSP_SCMODE(x) ((x) << 0) /* Serial Bit Rate Clock Mode */ +#define SSPSP_SFRMP (1 << 2) /* Serial Frame Polarity */ +#define SSPSP_ETDS (1 << 3) /* End of Transfer data State */ +#define SSPSP_STRTDLY(x) ((x) << 4) /* Start Delay */ +#define SSPSP_DMYSTRT(x) ((x) << 7) /* Dummy Start */ +#define SSPSP_SFRMDLY(x) ((x) << 9) /* Serial Frame Delay */ +#define SSPSP_SFRMWDTH(x) ((x) << 16) /* Serial Frame Width */ +#define SSPSP_DMYSTOP(x) ((x) << 23) /* Dummy Stop */ +#define SSPSP_FSRT (1 << 25) /* Frame Sync Relative Timing */ + +/* PXA3xx */ +#define SSPSP_EDMYSTRT(x) ((x) << 26) /* Extended Dummy Start */ +#define SSPSP_EDMYSTOP(x) ((x) << 28) /* Extended Dummy Stop */ +#define SSPSP_TIMING_MASK (0x7f8001f0) #define SSACD_SCDB (1 << 3) /* SSPSYSCLK Divider Bypass */ #define SSACD_ACPS(x) ((x) << 4) /* Audio clock PLL select */ #define SSACD_ACDS(x) ((x) << 0) /* Audio clock divider select */ -#if defined(CONFIG_PXA3xx) #define SSACD_SCDX8 (1 << 7) /* SYSCLK division ratio select */ -#endif enum pxa_ssp_type { SSP_UNDEFINED = 0, -- cgit v0.10.2 From 7e4992288e55f1e15f7498ead618b3943f5cfd3f Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Fri, 19 Mar 2010 11:53:17 -0400 Subject: [ARM] mmp: support ssp in pxa168 Support ssp devices in PXA168. PXA168 could reuse the code of PXA SSP. Signed-off-by: Haojian Zhuang Signed-off-by: Eric Miao diff --git a/arch/arm/mach-mmp/include/mach/irqs.h b/arch/arm/mach-mmp/include/mach/irqs.h index 0270119..b379cde 100644 --- a/arch/arm/mach-mmp/include/mach/irqs.h +++ b/arch/arm/mach-mmp/include/mach/irqs.h @@ -5,10 +5,10 @@ * Interrupt numbers for PXA168 */ #define IRQ_PXA168_NONE (-1) -#define IRQ_PXA168_SSP3 0 -#define IRQ_PXA168_SSP2 1 -#define IRQ_PXA168_SSP1 2 -#define IRQ_PXA168_SSP0 3 +#define IRQ_PXA168_SSP4 0 +#define IRQ_PXA168_SSP3 1 +#define IRQ_PXA168_SSP2 2 +#define IRQ_PXA168_SSP1 3 #define IRQ_PXA168_PMIC_INT 4 #define IRQ_PXA168_RTC_INT 5 #define IRQ_PXA168_RTC_ALARM 6 @@ -20,7 +20,7 @@ #define IRQ_PXA168_TIMER2 14 #define IRQ_PXA168_TIMER3 15 #define IRQ_PXA168_CMU 16 -#define IRQ_PXA168_SSP4 17 +#define IRQ_PXA168_SSP5 17 #define IRQ_PXA168_MSP_WAKEUP 19 #define IRQ_PXA168_CF_WAKEUP 20 #define IRQ_PXA168_XD_WAKEUP 21 diff --git a/arch/arm/mach-mmp/include/mach/pxa168.h b/arch/arm/mach-mmp/include/mach/pxa168.h index 3ad612c..3b2bd5d 100644 --- a/arch/arm/mach-mmp/include/mach/pxa168.h +++ b/arch/arm/mach-mmp/include/mach/pxa168.h @@ -14,6 +14,11 @@ extern struct pxa_device_desc pxa168_device_pwm1; extern struct pxa_device_desc pxa168_device_pwm2; extern struct pxa_device_desc pxa168_device_pwm3; extern struct pxa_device_desc pxa168_device_pwm4; +extern struct pxa_device_desc pxa168_device_ssp1; +extern struct pxa_device_desc pxa168_device_ssp2; +extern struct pxa_device_desc pxa168_device_ssp3; +extern struct pxa_device_desc pxa168_device_ssp4; +extern struct pxa_device_desc pxa168_device_ssp5; extern struct pxa_device_desc pxa168_device_nand; static inline int pxa168_add_uart(int id) @@ -67,6 +72,22 @@ static inline int pxa168_add_pwm(int id) return pxa_register_device(d, NULL, 0); } +static inline int pxa168_add_ssp(int id) +{ + struct pxa_device_desc *d = NULL; + + switch (id) { + case 1: d = &pxa168_device_ssp1; break; + case 2: d = &pxa168_device_ssp2; break; + case 3: d = &pxa168_device_ssp3; break; + case 4: d = &pxa168_device_ssp4; break; + case 5: d = &pxa168_device_ssp5; break; + default: + return -EINVAL; + } + return pxa_register_device(d, NULL, 0); +} + static inline int pxa168_add_nand(struct pxa3xx_nand_platform_data *info) { return pxa_register_device(&pxa168_device_nand, info, sizeof(*info)); diff --git a/arch/arm/mach-mmp/include/mach/regs-apbc.h b/arch/arm/mach-mmp/include/mach/regs-apbc.h index 712af03..1a96585 100644 --- a/arch/arm/mach-mmp/include/mach/regs-apbc.h +++ b/arch/arm/mach-mmp/include/mach/regs-apbc.h @@ -26,8 +26,6 @@ #define APBC_PXA168_PWM2 APBC_REG(0x010) #define APBC_PXA168_PWM3 APBC_REG(0x014) #define APBC_PXA168_PWM4 APBC_REG(0x018) -#define APBC_PXA168_SSP1 APBC_REG(0x01c) -#define APBC_PXA168_SSP2 APBC_REG(0x020) #define APBC_PXA168_RTC APBC_REG(0x028) #define APBC_PXA168_TWSI0 APBC_REG(0x02c) #define APBC_PXA168_KPC APBC_REG(0x030) @@ -35,14 +33,16 @@ #define APBC_PXA168_AIB APBC_REG(0x03c) #define APBC_PXA168_SW_JTAG APBC_REG(0x040) #define APBC_PXA168_ONEWIRE APBC_REG(0x048) -#define APBC_PXA168_SSP3 APBC_REG(0x04c) #define APBC_PXA168_ASFAR APBC_REG(0x050) #define APBC_PXA168_ASSAR APBC_REG(0x054) -#define APBC_PXA168_SSP4 APBC_REG(0x058) -#define APBC_PXA168_SSP5 APBC_REG(0x05c) #define APBC_PXA168_TWSI1 APBC_REG(0x06c) #define APBC_PXA168_UART3 APBC_REG(0x070) #define APBC_PXA168_AC97 APBC_REG(0x084) +#define APBC_PXA168_SSP1 APBC_REG(0x81c) +#define APBC_PXA168_SSP2 APBC_REG(0x820) +#define APBC_PXA168_SSP3 APBC_REG(0x84c) +#define APBC_PXA168_SSP4 APBC_REG(0x858) +#define APBC_PXA168_SSP5 APBC_REG(0x85c) /* * APB Clock register offsets for PXA910 diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c index 1873c82..652ae66 100644 --- a/arch/arm/mach-mmp/pxa168.c +++ b/arch/arm/mach-mmp/pxa168.c @@ -72,6 +72,11 @@ static APBC_CLK(pwm1, PXA168_PWM1, 1, 13000000); static APBC_CLK(pwm2, PXA168_PWM2, 1, 13000000); static APBC_CLK(pwm3, PXA168_PWM3, 1, 13000000); static APBC_CLK(pwm4, PXA168_PWM4, 1, 13000000); +static APBC_CLK(ssp1, PXA168_SSP1, 4, 0); +static APBC_CLK(ssp2, PXA168_SSP2, 4, 0); +static APBC_CLK(ssp3, PXA168_SSP3, 4, 0); +static APBC_CLK(ssp4, PXA168_SSP4, 4, 0); +static APBC_CLK(ssp5, PXA168_SSP5, 4, 0); static APMU_CLK(nand, NAND, 0x01db, 208000000); @@ -85,6 +90,11 @@ static struct clk_lookup pxa168_clkregs[] = { INIT_CLKREG(&clk_pwm2, "pxa168-pwm.1", NULL), INIT_CLKREG(&clk_pwm3, "pxa168-pwm.2", NULL), INIT_CLKREG(&clk_pwm4, "pxa168-pwm.3", NULL), + INIT_CLKREG(&clk_ssp1, "pxa168-ssp.0", NULL), + INIT_CLKREG(&clk_ssp2, "pxa168-ssp.1", NULL), + INIT_CLKREG(&clk_ssp3, "pxa168-ssp.2", NULL), + INIT_CLKREG(&clk_ssp4, "pxa168-ssp.3", NULL), + INIT_CLKREG(&clk_ssp5, "pxa168-ssp.4", NULL), INIT_CLKREG(&clk_nand, "pxa3xx-nand", NULL), }; @@ -132,3 +142,8 @@ PXA168_DEVICE(pwm2, "pxa168-pwm", 1, NONE, 0xd401a400, 0x10); PXA168_DEVICE(pwm3, "pxa168-pwm", 2, NONE, 0xd401a800, 0x10); PXA168_DEVICE(pwm4, "pxa168-pwm", 3, NONE, 0xd401ac00, 0x10); PXA168_DEVICE(nand, "pxa3xx-nand", -1, NAND, 0xd4283000, 0x80, 97, 99); +PXA168_DEVICE(ssp1, "pxa168-ssp", 0, SSP1, 0xd401b000, 0x40, 52, 53); +PXA168_DEVICE(ssp2, "pxa168-ssp", 1, SSP2, 0xd401c000, 0x40, 54, 55); +PXA168_DEVICE(ssp3, "pxa168-ssp", 2, SSP3, 0xd401f000, 0x40, 56, 57); +PXA168_DEVICE(ssp4, "pxa168-ssp", 3, SSP4, 0xd4020000, 0x40, 58, 59); +PXA168_DEVICE(ssp5, "pxa168-ssp", 4, SSP5, 0xd4021000, 0x40, 60, 61); diff --git a/arch/arm/plat-pxa/include/plat/ssp.h b/arch/arm/plat-pxa/include/plat/ssp.h index 74f70c7..d16d79a 100644 --- a/arch/arm/plat-pxa/include/plat/ssp.h +++ b/arch/arm/plat-pxa/include/plat/ssp.h @@ -138,6 +138,7 @@ enum pxa_ssp_type { PXA25x_SSP, /* pxa 210, 250, 255, 26x */ PXA25x_NSSP, /* pxa 255, 26x (including ASSP) */ PXA27x_SSP, + PXA168_SSP, }; struct ssp_device { diff --git a/arch/arm/plat-pxa/ssp.c b/arch/arm/plat-pxa/ssp.c index 5fe2301..cfebcd8 100644 --- a/arch/arm/plat-pxa/ssp.c +++ b/arch/arm/plat-pxa/ssp.c @@ -192,6 +192,7 @@ static const struct platform_device_id ssp_id_table[] = { { "pxa25x-ssp", PXA25x_SSP }, { "pxa25x-nssp", PXA25x_NSSP }, { "pxa27x-ssp", PXA27x_SSP }, + { "pxa168-ssp", PXA168_SSP }, { }, }; -- cgit v0.10.2 From 07871c195a5ec7d59d34994c123472b113da09ba Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Fri, 19 Mar 2010 11:55:14 -0400 Subject: [ARM] mmp: enable ssp in aspenite Configure both ssp and wm8753 in aspenite. Signed-off-by: Haojian Zhuang Signed-off-by: Eric Miao diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c index a2d307e..244655d 100644 --- a/arch/arm/mach-mmp/aspenite.c +++ b/arch/arm/mach-mmp/aspenite.c @@ -59,6 +59,13 @@ static unsigned long common_pin_config[] __initdata = { /* UART1 */ GPIO107_UART1_RXD, GPIO108_UART1_TXD, + + /* SSP1 */ + GPIO113_I2S_MCLK, + GPIO114_I2S_FRM, + GPIO115_I2S_BCLK, + GPIO116_I2S_RXD, + GPIO117_I2S_TXD, }; static struct smc91x_platdata smc91x_info = { @@ -123,12 +130,18 @@ static struct pxa3xx_nand_platform_data aspenite_nand_info = { .nr_parts = ARRAY_SIZE(aspenite_nand_partitions), }; +static struct i2c_board_info aspenite_i2c_info[] __initdata = { + { I2C_BOARD_INFO("wm8753", 0x1b), }, +}; + static void __init common_init(void) { mfp_config(ARRAY_AND_SIZE(common_pin_config)); /* on-chip devices */ pxa168_add_uart(1); + pxa168_add_twsi(1, NULL, ARRAY_AND_SIZE(aspenite_i2c_info)); + pxa168_add_ssp(1); pxa168_add_nand(&aspenite_nand_info); /* off-chip devices */ -- cgit v0.10.2 From 077de1ad5ad8b4e08fd8853ae7e4cc628c1a369b Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 22 Mar 2010 16:11:55 +0800 Subject: [ARM] pxa: avoid NULL dereferencing in error handling of ssp.c The assignments of res to the results of the two calls to platform_get_resource make it impossible to use res in the error handling code in the arguments to release_mem_region. The semantic match that finds the former problem is as follows: (http://coccinelle.lip6.fr/) // @r exists@ expression E, E1; identifier f; statement S1,S3; iterator iter; @@ if ((E == NULL && ...) || ...) { ... when != false ((E == NULL && ...) || ...) when != true ((E != NULL && ...) || ...) when != iter(E,...) S1 when != E = E1 ( sizeof(E->f) | * E->f ) ... when any return ...; } else S3 // Signed-off-by: Julia Lawall Signed-off-by: Eric Miao diff --git a/arch/arm/plat-pxa/ssp.c b/arch/arm/plat-pxa/ssp.c index cfebcd8..3bf704d 100644 --- a/arch/arm/plat-pxa/ssp.c +++ b/arch/arm/plat-pxa/ssp.c @@ -92,6 +92,22 @@ static int __devinit ssp_probe(struct platform_device *pdev) goto err_free; } + res = platform_get_resource(pdev, IORESOURCE_DMA, 0); + if (res == NULL) { + dev_err(&pdev->dev, "no SSP RX DRCMR defined\n"); + ret = -ENODEV; + goto err_free_clk; + } + ssp->drcmr_rx = res->start; + + res = platform_get_resource(pdev, IORESOURCE_DMA, 1); + if (res == NULL) { + dev_err(&pdev->dev, "no SSP TX DRCMR defined\n"); + ret = -ENODEV; + goto err_free_clk; + } + ssp->drcmr_tx = res->start; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { dev_err(&pdev->dev, "no memory resource defined\n"); @@ -123,22 +139,6 @@ static int __devinit ssp_probe(struct platform_device *pdev) goto err_free_io; } - res = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (res == NULL) { - dev_err(&pdev->dev, "no SSP RX DRCMR defined\n"); - ret = -ENODEV; - goto err_free_io; - } - ssp->drcmr_rx = res->start; - - res = platform_get_resource(pdev, IORESOURCE_DMA, 1); - if (res == NULL) { - dev_err(&pdev->dev, "no SSP TX DRCMR defined\n"); - ret = -ENODEV; - goto err_free_io; - } - ssp->drcmr_tx = res->start; - /* PXA2xx/3xx SSP ports starts from 1 and the internal pdev->id * starts from 0, do a translation here */ -- cgit v0.10.2 From c8ee5c69516fdd973b981e3ac12d49b3133930cd Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 22 Mar 2010 16:16:24 +0800 Subject: [ARM] pxa: use resource_size() in ssp.c Signed-off-by: Julia Lawall Signed-off-by: Eric Miao diff --git a/arch/arm/plat-pxa/ssp.c b/arch/arm/plat-pxa/ssp.c index 3bf704d..52c07cc 100644 --- a/arch/arm/plat-pxa/ssp.c +++ b/arch/arm/plat-pxa/ssp.c @@ -115,7 +115,7 @@ static int __devinit ssp_probe(struct platform_device *pdev) goto err_free_clk; } - res = request_mem_region(res->start, res->end - res->start + 1, + res = request_mem_region(res->start, resource_size(res), pdev->name); if (res == NULL) { dev_err(&pdev->dev, "failed to request memory resource\n"); @@ -125,7 +125,7 @@ static int __devinit ssp_probe(struct platform_device *pdev) ssp->phys_base = res->start; - ssp->mmio_base = ioremap(res->start, res->end - res->start + 1); + ssp->mmio_base = ioremap(res->start, resource_size(res)); if (ssp->mmio_base == NULL) { dev_err(&pdev->dev, "failed to ioremap() registers\n"); ret = -ENODEV; @@ -156,7 +156,7 @@ static int __devinit ssp_probe(struct platform_device *pdev) err_free_io: iounmap(ssp->mmio_base); err_free_mem: - release_mem_region(res->start, res->end - res->start + 1); + release_mem_region(res->start, resource_size(res)); err_free_clk: clk_put(ssp->clk); err_free: @@ -176,7 +176,7 @@ static int __devexit ssp_remove(struct platform_device *pdev) iounmap(ssp->mmio_base); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(res->start, res->end - res->start + 1); + release_mem_region(res->start, resource_size(res)); clk_put(ssp->clk); -- cgit v0.10.2 From 1106143d7ab43ba07678c88c85417df219354ae8 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Mon, 11 Jan 2010 21:25:15 +0800 Subject: [ARM] pxa: add MFP_LPM_KEEP_OUTPUT flag to pin config Some pins are expected to keep their last level during suspend, and introduce MFP_LPM_KEEP_OUTPUT for this. Signed-off-by: Eric Miao diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h b/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h index 658b28e..c54cef2 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h @@ -25,6 +25,8 @@ #define MFP_DIR(x) (((x) >> 23) & 0x1) #define MFP_LPM_CAN_WAKEUP (0x1 << 24) +#define MFP_LPM_KEEP_OUTPUT (0x1 << 25) + #define WAKEUP_ON_EDGE_RISE (MFP_LPM_CAN_WAKEUP | MFP_LPM_EDGE_RISE) #define WAKEUP_ON_EDGE_FALL (MFP_LPM_CAN_WAKEUP | MFP_LPM_EDGE_FALL) #define WAKEUP_ON_EDGE_BOTH (MFP_LPM_CAN_WAKEUP | MFP_LPM_EDGE_BOTH) diff --git a/arch/arm/mach-pxa/mfp-pxa2xx.c b/arch/arm/mach-pxa/mfp-pxa2xx.c index cf6b720..c98b5a8 100644 --- a/arch/arm/mach-pxa/mfp-pxa2xx.c +++ b/arch/arm/mach-pxa/mfp-pxa2xx.c @@ -328,6 +328,17 @@ static int pxa2xx_mfp_suspend(struct sys_device *d, pm_message_t state) { int i; + /* set corresponding PGSR bit of those marked MFP_LPM_KEEP_OUTPUT */ + for (i = 0; i < pxa_last_gpio; i++) { + if ((gpio_desc[i].config & MFP_LPM_KEEP_OUTPUT) && + (GPDR(i) & GPIO_bit(i))) { + if (GPLR(i) & GPIO_bit(i)) + PGSR(i) |= GPIO_bit(i); + else + PGSR(i) &= ~GPIO_bit(i); + } + } + for (i = 0; i <= gpio_to_bank(pxa_last_gpio); i++) { saved_gafr[0][i] = GAFR_L(i); -- cgit v0.10.2 From c09f431c338cf032c68ea68915f4dd85d92fd526 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Tue, 20 Apr 2010 14:52:50 +0800 Subject: [ARM] pxa: allow keypad GPIOs to wakeup when configured as generic Signed-off-by: Eric Miao diff --git a/arch/arm/mach-pxa/mfp-pxa2xx.c b/arch/arm/mach-pxa/mfp-pxa2xx.c index c98b5a8..e5b7921 100644 --- a/arch/arm/mach-pxa/mfp-pxa2xx.c +++ b/arch/arm/mach-pxa/mfp-pxa2xx.c @@ -178,8 +178,17 @@ int gpio_set_wake(unsigned int gpio, unsigned int on) if (!d->valid) return -EINVAL; - if (d->keypad_gpio) - return -EINVAL; + /* Allow keypad GPIOs to wakeup system when + * configured as generic GPIOs. + */ + if (d->keypad_gpio && (MFP_AF(d->config) == 0) && + (d->config & MFP_LPM_CAN_WAKEUP)) { + if (on) + PKWR |= d->mask; + else + PKWR &= ~d->mask; + return 0; + } mux_taken = (PWER & d->mux_mask) & (~d->mask); if (on && mux_taken) @@ -239,21 +248,25 @@ static int pxa27x_pkwr_gpio[] = { int keypad_set_wake(unsigned int on) { unsigned int i, gpio, mask = 0; - - if (!on) { - PKWR = 0; - return 0; - } + struct gpio_desc *d; for (i = 0; i < ARRAY_SIZE(pxa27x_pkwr_gpio); i++) { gpio = pxa27x_pkwr_gpio[i]; + d = &gpio_desc[gpio]; - if (gpio_desc[gpio].config & MFP_LPM_CAN_WAKEUP) + /* skip if configured as generic GPIO */ + if (MFP_AF(d->config) == 0) + continue; + + if (d->config & MFP_LPM_CAN_WAKEUP) mask |= gpio_desc[gpio].mask; } - PKWR = mask; + if (on) + PKWR |= mask; + else + PKWR &= ~mask; return 0; } -- cgit v0.10.2 From 1fe8c2bcad52d16e4d31d3680b9bb536c56df3d8 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Tue, 27 Apr 2010 11:14:24 +0800 Subject: [ARM] pxa: allow MFP_LPM_INPUT to be explicitly specified Signed-off-by: Eric Miao diff --git a/arch/arm/mach-pxa/mfp-pxa2xx.c b/arch/arm/mach-pxa/mfp-pxa2xx.c index e5b7921..1d1419b 100644 --- a/arch/arm/mach-pxa/mfp-pxa2xx.c +++ b/arch/arm/mach-pxa/mfp-pxa2xx.c @@ -81,6 +81,7 @@ static int __mfp_config_gpio(unsigned gpio, unsigned long c) PGSR(bank) &= ~mask; is_out = 1; break; + case MFP_LPM_INPUT: case MFP_LPM_DEFAULT: break; default: diff --git a/arch/arm/plat-pxa/mfp.c b/arch/arm/plat-pxa/mfp.c index be58f9f..b77e018 100644 --- a/arch/arm/plat-pxa/mfp.c +++ b/arch/arm/plat-pxa/mfp.c @@ -110,6 +110,7 @@ static const unsigned long mfpr_lpm[] = { MFPR_LPM_PULL_LOW, MFPR_LPM_PULL_HIGH, MFPR_LPM_FLOAT, + MFPR_LPM_INPUT, }; /* mapping of MFP_PULL_* definitions to MFPR_PULL_* register bits */ -- cgit v0.10.2 From b6eede112673678f8a7a1680d6ad12245443829d Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Mon, 11 Jan 2010 16:17:25 +0800 Subject: [ARM] pxa/spitz: use generic GPIO API and remove pxa_gpio_mode() REVISIT: change to GPIO18 is ugly, need to make sure whether that's really necessary - GPIO18_RDY as an VLIO input signal - we don't normally need to do such kind of trick during low power mode. Signed-off-by: Eric Miao diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 01bdd75..451029e 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -86,6 +86,7 @@ static unsigned long spitz_pin_config[] __initdata = { /* GPIOs */ GPIO9_GPIO, /* SPITZ_GPIO_nSD_DETECT */ + GPIO16_GPIO, /* SPITZ_GPIO_SYNC */ GPIO81_GPIO, /* SPITZ_GPIO_nSD_WP */ GPIO41_GPIO, /* SPITZ_GPIO_USB_CONNECT */ GPIO37_GPIO, /* SPITZ_GPIO_USB_HOST */ @@ -119,7 +120,8 @@ static unsigned long spitz_pin_config[] __initdata = { GPIO117_I2C_SCL, GPIO118_I2C_SDA, - GPIO1_GPIO | WAKEUP_ON_EDGE_RISE, + GPIO0_GPIO | WAKEUP_ON_EDGE_RISE, /* SPITZ_GPIO_KEY_INT */ + GPIO1_GPIO | WAKEUP_ON_EDGE_FALL, /* SPITZ_GPIO_RESET */ }; /* diff --git a/arch/arm/mach-pxa/spitz_pm.c b/arch/arm/mach-pxa/spitz_pm.c index fc5a70c..4209ddf 100644 --- a/arch/arm/mach-pxa/spitz_pm.c +++ b/arch/arm/mach-pxa/spitz_pm.c @@ -24,9 +24,10 @@ #include #include -#include -#include +#include + #include "sharpsl.h" +#include "generic.h" #define SHARPSL_CHARGE_ON_VOLT 0x99 /* 2.9V */ #define SHARPSL_CHARGE_ON_TEMP 0xe0 /* 2.9V */ @@ -37,10 +38,17 @@ static int spitz_last_ac_status; +static struct gpio spitz_charger_gpios[] = { + { SPITZ_GPIO_KEY_INT, GPIOF_IN, "Keyboard Interrupt" }, + { SPITZ_GPIO_SYNC, GPIOF_IN, "Sync" }, + { SPITZ_GPIO_ADC_TEMP_ON, GPIOF_OUT_INIT_LOW, "ADC Temp On" }, + { SPITZ_GPIO_JK_B, GPIOF_OUT_INIT_LOW, "JK B" }, + { SPITZ_GPIO_CHRG_ON, GPIOF_OUT_INIT_LOW, "Charger On" }, +}; + static void spitz_charger_init(void) { - pxa_gpio_mode(SPITZ_GPIO_KEY_INT | GPIO_IN); - pxa_gpio_mode(SPITZ_GPIO_SYNC | GPIO_IN); + gpio_request_array(ARRAY_AND_SIZE(spitz_charger_gpios)); } static void spitz_measure_temp(int on) @@ -76,6 +84,11 @@ static void spitz_discharge1(int on) gpio_set_value(SPITZ_GPIO_LED_GREEN, on); } +static unsigned long gpio18_config[] = { + GPIO18_RDY, + GPIO18_GPIO, +}; + static void spitz_presuspend(void) { spitz_last_ac_status = sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN); @@ -97,7 +110,9 @@ static void spitz_presuspend(void) PGSR3 &= ~SPITZ_GPIO_G3_STROBE_BIT; PGSR2 |= GPIO_bit(SPITZ_GPIO_KEY_STROBE0); - pxa_gpio_mode(GPIO18_RDY|GPIO_OUT | GPIO_DFLT_HIGH); + pxa2xx_mfp_config(&gpio18_config[0], 1); + gpio_request_one(18, GPIOF_OUT_INIT_HIGH, "Unknown"); + gpio_free(18); PRER = GPIO_bit(SPITZ_GPIO_KEY_INT); PFER = GPIO_bit(SPITZ_GPIO_KEY_INT) | GPIO_bit(SPITZ_GPIO_RESET); @@ -114,8 +129,7 @@ static void spitz_presuspend(void) static void spitz_postsuspend(void) { - pxa_gpio_mode(GPIO18_RDY_MD); - pxa_gpio_mode(10 | GPIO_IN); + pxa2xx_mfp_config(&gpio18_config[1], 1); } static int spitz_should_wakeup(unsigned int resume_on_alarm) -- cgit v0.10.2 From e63f591a8ce5d3b5214a14d6cebaad7b6c1c4b4c Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Fri, 8 Jan 2010 13:32:46 +0800 Subject: [ARM] pxa/corgi: use generic GPIO API and remove pxa_gpio_mode() Signed-off-by: Eric Miao diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index da3156d86..788343d 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -130,11 +130,15 @@ static unsigned long corgi_pin_config[] __initdata = { /* GPIO */ GPIO9_GPIO, /* CORGI_GPIO_nSD_DETECT */ GPIO7_GPIO, /* CORGI_GPIO_nSD_WP */ - GPIO33_GPIO, /* CORGI_GPIO_SD_PWR */ + GPIO21_GPIO, /* CORGI_GPIO_ADC_TEMP */ GPIO22_GPIO, /* CORGI_GPIO_IR_ON */ + GPIO33_GPIO, /* CORGI_GPIO_SD_PWR */ + GPIO38_GPIO, /* CORGI_GPIO_CHRG_ON */ + GPIO43_GPIO, /* CORGI_GPIO_CHRG_UKN */ GPIO44_GPIO, /* CORGI_GPIO_HSYNC */ - GPIO1_GPIO | WAKEUP_ON_EDGE_RISE, + GPIO0_GPIO | WAKEUP_ON_EDGE_BOTH, /* CORGI_GPIO_KEY_INT */ + GPIO1_GPIO | WAKEUP_ON_EDGE_RISE, /* CORGI_GPIO_AC_IN */ }; /* diff --git a/arch/arm/mach-pxa/corgi_pm.c b/arch/arm/mach-pxa/corgi_pm.c index d4a0733..bb68347 100644 --- a/arch/arm/mach-pxa/corgi_pm.c +++ b/arch/arm/mach-pxa/corgi_pm.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -25,7 +26,8 @@ #include #include #include -#include + +#include "generic.h" #include "sharpsl.h" #define SHARPSL_CHARGE_ON_VOLT 0x99 /* 2.9V */ @@ -35,44 +37,42 @@ #define SHARPSL_FATAL_ACIN_VOLT 182 /* 3.45V */ #define SHARPSL_FATAL_NOACIN_VOLT 170 /* 3.40V */ +static struct gpio charger_gpios[] = { + { CORGI_GPIO_ADC_TEMP_ON, GPIOF_OUT_INIT_LOW, "ADC Temp On" }, + { CORGI_GPIO_CHRG_ON, GPIOF_OUT_INIT_LOW, "Charger On" }, + { CORGI_GPIO_CHRG_UKN, GPIOF_OUT_INIT_LOW, "Charger Unknown" }, + { CORGI_GPIO_KEY_INT, GPIOF_IN, "Key Interrupt" }, +}; + static void corgi_charger_init(void) { - pxa_gpio_mode(CORGI_GPIO_ADC_TEMP_ON | GPIO_OUT); - pxa_gpio_mode(CORGI_GPIO_CHRG_ON | GPIO_OUT); - pxa_gpio_mode(CORGI_GPIO_CHRG_UKN | GPIO_OUT); - pxa_gpio_mode(CORGI_GPIO_KEY_INT | GPIO_IN); + gpio_request_array(ARRAY_AND_SIZE(charger_gpios)); } static void corgi_measure_temp(int on) { - if (on) - GPSR(CORGI_GPIO_ADC_TEMP_ON) = GPIO_bit(CORGI_GPIO_ADC_TEMP_ON); - else - GPCR(CORGI_GPIO_ADC_TEMP_ON) = GPIO_bit(CORGI_GPIO_ADC_TEMP_ON); + gpio_set_value(CORGI_GPIO_ADC_TEMP_ON, on); } static void corgi_charge(int on) { if (on) { if (machine_is_corgi() && (sharpsl_pm.flags & SHARPSL_SUSPENDED)) { - GPCR(CORGI_GPIO_CHRG_ON) = GPIO_bit(CORGI_GPIO_CHRG_ON); - GPSR(CORGI_GPIO_CHRG_UKN) = GPIO_bit(CORGI_GPIO_CHRG_UKN); + gpio_set_value(CORGI_GPIO_CHRG_ON, 0); + gpio_set_value(CORGI_GPIO_CHRG_UKN, 1); } else { - GPSR(CORGI_GPIO_CHRG_ON) = GPIO_bit(CORGI_GPIO_CHRG_ON); - GPCR(CORGI_GPIO_CHRG_UKN) = GPIO_bit(CORGI_GPIO_CHRG_UKN); + gpio_set_value(CORGI_GPIO_CHRG_ON, 1); + gpio_set_value(CORGI_GPIO_CHRG_UKN, 0); } } else { - GPCR(CORGI_GPIO_CHRG_ON) = GPIO_bit(CORGI_GPIO_CHRG_ON); - GPCR(CORGI_GPIO_CHRG_UKN) = GPIO_bit(CORGI_GPIO_CHRG_UKN); + gpio_set_value(CORGI_GPIO_CHRG_ON, 0); + gpio_set_value(CORGI_GPIO_CHRG_UKN, 0); } } static void corgi_discharge(int on) { - if (on) - GPSR(CORGI_GPIO_DISCHARGE_ON) = GPIO_bit(CORGI_GPIO_DISCHARGE_ON); - else - GPCR(CORGI_GPIO_DISCHARGE_ON) = GPIO_bit(CORGI_GPIO_DISCHARGE_ON); + gpio_set_value(CORGI_GPIO_DISCHARGE_ON, on); } static void corgi_presuspend(void) -- cgit v0.10.2 From cb432b358dced89bd2af86b3f783a0a99e489421 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Mon, 11 Jan 2010 21:27:21 +0800 Subject: [ARM] pxa/corgi: cleanup GPIO configurations and low power mode settings Signed-off-by: Eric Miao diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index 788343d..f8e2959 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -106,18 +106,18 @@ static unsigned long corgi_pin_config[] __initdata = { GPIO8_MMC_CS0, /* GPIO Matrix Keypad */ - GPIO66_GPIO, /* column 0 */ - GPIO67_GPIO, /* column 1 */ - GPIO68_GPIO, /* column 2 */ - GPIO69_GPIO, /* column 3 */ - GPIO70_GPIO, /* column 4 */ - GPIO71_GPIO, /* column 5 */ - GPIO72_GPIO, /* column 6 */ - GPIO73_GPIO, /* column 7 */ - GPIO74_GPIO, /* column 8 */ - GPIO75_GPIO, /* column 9 */ - GPIO76_GPIO, /* column 10 */ - GPIO77_GPIO, /* column 11 */ + GPIO66_GPIO | MFP_LPM_DRIVE_HIGH, /* column 0 */ + GPIO67_GPIO | MFP_LPM_DRIVE_HIGH, /* column 1 */ + GPIO68_GPIO | MFP_LPM_DRIVE_HIGH, /* column 2 */ + GPIO69_GPIO | MFP_LPM_DRIVE_HIGH, /* column 3 */ + GPIO70_GPIO | MFP_LPM_DRIVE_HIGH, /* column 4 */ + GPIO71_GPIO | MFP_LPM_DRIVE_HIGH, /* column 5 */ + GPIO72_GPIO | MFP_LPM_DRIVE_HIGH, /* column 6 */ + GPIO73_GPIO | MFP_LPM_DRIVE_HIGH, /* column 7 */ + GPIO74_GPIO | MFP_LPM_DRIVE_HIGH, /* column 8 */ + GPIO75_GPIO | MFP_LPM_DRIVE_HIGH, /* column 9 */ + GPIO76_GPIO | MFP_LPM_DRIVE_HIGH, /* column 10 */ + GPIO77_GPIO | MFP_LPM_DRIVE_HIGH, /* column 11 */ GPIO58_GPIO, /* row 0 */ GPIO59_GPIO, /* row 1 */ GPIO60_GPIO, /* row 2 */ @@ -128,17 +128,20 @@ static unsigned long corgi_pin_config[] __initdata = { GPIO65_GPIO, /* row 7 */ /* GPIO */ - GPIO9_GPIO, /* CORGI_GPIO_nSD_DETECT */ - GPIO7_GPIO, /* CORGI_GPIO_nSD_WP */ - GPIO21_GPIO, /* CORGI_GPIO_ADC_TEMP */ - GPIO22_GPIO, /* CORGI_GPIO_IR_ON */ - GPIO33_GPIO, /* CORGI_GPIO_SD_PWR */ - GPIO38_GPIO, /* CORGI_GPIO_CHRG_ON */ - GPIO43_GPIO, /* CORGI_GPIO_CHRG_UKN */ - GPIO44_GPIO, /* CORGI_GPIO_HSYNC */ + GPIO9_GPIO, /* CORGI_GPIO_nSD_DETECT */ + GPIO7_GPIO, /* CORGI_GPIO_nSD_WP */ + GPIO11_GPIO | WAKEUP_ON_EDGE_BOTH, /* CORGI_GPIO_MAIN_BAT_{LOW,COVER} */ + GPIO13_GPIO | MFP_LPM_KEEP_OUTPUT, /* CORGI_GPIO_LED_ORANGE */ + GPIO21_GPIO, /* CORGI_GPIO_ADC_TEMP */ + GPIO22_GPIO, /* CORGI_GPIO_IR_ON */ + GPIO33_GPIO, /* CORGI_GPIO_SD_PWR */ + GPIO38_GPIO | MFP_LPM_KEEP_OUTPUT, /* CORGI_GPIO_CHRG_ON */ + GPIO43_GPIO | MFP_LPM_KEEP_OUTPUT, /* CORGI_GPIO_CHRG_UKN */ + GPIO44_GPIO, /* CORGI_GPIO_HSYNC */ GPIO0_GPIO | WAKEUP_ON_EDGE_BOTH, /* CORGI_GPIO_KEY_INT */ GPIO1_GPIO | WAKEUP_ON_EDGE_RISE, /* CORGI_GPIO_AC_IN */ + GPIO3_GPIO | WAKEUP_ON_EDGE_BOTH, /* CORGI_GPIO_WAKEUP */ }; /* @@ -676,6 +679,15 @@ static void __init corgi_init(void) pxa2xx_mfp_config(ARRAY_AND_SIZE(corgi_pin_config)); + /* allow wakeup from various GPIOs */ + gpio_set_wake(CORGI_GPIO_KEY_INT, 1); + gpio_set_wake(CORGI_GPIO_WAKEUP, 1); + gpio_set_wake(CORGI_GPIO_AC_IN, 1); + gpio_set_wake(CORGI_GPIO_CHRG_FULL, 1); + + if (!machine_is_corgi()) + gpio_set_wake(CORGI_GPIO_MAIN_BAT_LOW, 1); + pxa_set_ffuart_info(NULL); pxa_set_btuart_info(NULL); pxa_set_stuart_info(NULL); diff --git a/arch/arm/mach-pxa/corgi_pm.c b/arch/arm/mach-pxa/corgi_pm.c index bb68347..3f1dc74 100644 --- a/arch/arm/mach-pxa/corgi_pm.c +++ b/arch/arm/mach-pxa/corgi_pm.c @@ -77,45 +77,6 @@ static void corgi_discharge(int on) static void corgi_presuspend(void) { - int i; - unsigned long wakeup_mask; - - /* charging , so CHARGE_ON bit is HIGH during OFF. */ - if (READ_GPIO_BIT(CORGI_GPIO_CHRG_ON)) - PGSR1 |= GPIO_bit(CORGI_GPIO_CHRG_ON); - else - PGSR1 &= ~GPIO_bit(CORGI_GPIO_CHRG_ON); - - if (READ_GPIO_BIT(CORGI_GPIO_LED_ORANGE)) - PGSR0 |= GPIO_bit(CORGI_GPIO_LED_ORANGE); - else - PGSR0 &= ~GPIO_bit(CORGI_GPIO_LED_ORANGE); - - if (READ_GPIO_BIT(CORGI_GPIO_CHRG_UKN)) - PGSR1 |= GPIO_bit(CORGI_GPIO_CHRG_UKN); - else - PGSR1 &= ~GPIO_bit(CORGI_GPIO_CHRG_UKN); - - /* Resume on keyboard power key */ - PGSR2 = (PGSR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(0); - - wakeup_mask = GPIO_bit(CORGI_GPIO_KEY_INT) | GPIO_bit(CORGI_GPIO_WAKEUP) | GPIO_bit(CORGI_GPIO_AC_IN) | GPIO_bit(CORGI_GPIO_CHRG_FULL); - - if (!machine_is_corgi()) - wakeup_mask |= GPIO_bit(CORGI_GPIO_MAIN_BAT_LOW); - - PWER = wakeup_mask | PWER_RTC; - PRER = wakeup_mask; - PFER = wakeup_mask; - - for (i = 0; i <=15; i++) { - if (PRER & PFER & GPIO_bit(i)) { - if (GPLR0 & GPIO_bit(i) ) - PRER &= ~GPIO_bit(i); - else - PFER &= ~GPIO_bit(i); - } - } } static void corgi_postsuspend(void) -- cgit v0.10.2 From cb8f3c7dea960c27fcc66830cdaab82b13f1b597 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Tue, 27 Apr 2010 14:43:03 +0800 Subject: [ARM] pxa/tosa: move CONFIG_KEYBOARD_TOSA_USE_EXT_KEYCODES to mach/Kconfig Tosa is now able to use generic matrix keypad driver instead of the deprecated tosakbd.c, where CONFIG_KEYBOARD_TOSA_USE_EXT_KEYCODES is still useful. Move it to mach/Kconfig. Signed-off-by: Eric Miao diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index 352dc4f..454cd5d 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -643,6 +643,18 @@ config TOSA_BT This is a simple driver that is able to control the state of built in bluetooth chip on tosa. +config TOSA_USE_EXT_KEYCODES + bool "Tosa keyboard: use extended keycodes" + depends on MACH_TOSA + default n + help + Say Y here to enable the tosa keyboard driver to generate extended + (>= 127) keycodes. Be aware, that they can't be correctly interpreted + by either console keyboard driver or by Kdrive keybd driver. + + Say Y only if you know, what you are doing! + + config PXA_HAVE_BOARD_IRQS bool diff --git a/arch/arm/mach-pxa/include/mach/tosa.h b/arch/arm/mach-pxa/include/mach/tosa.h index 4df2d38..1bbd1f2 100644 --- a/arch/arm/mach-pxa/include/mach/tosa.h +++ b/arch/arm/mach-pxa/include/mach/tosa.h @@ -167,7 +167,7 @@ #define TOSA_KEY_SYNC KEY_102ND /* ??? */ -#ifndef CONFIG_KEYBOARD_TOSA_USE_EXT_KEYCODES +#ifndef CONFIG_TOSA_USE_EXT_KEYCODES #define TOSA_KEY_RECORD KEY_YEN #define TOSA_KEY_ADDRESSBOOK KEY_KATAKANA #define TOSA_KEY_CANCEL KEY_ESC diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 64c1023..a74ee12 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -426,16 +426,6 @@ config KEYBOARD_TOSA To compile this driver as a module, choose M here: the module will be called tosakbd. -config KEYBOARD_TOSA_USE_EXT_KEYCODES - bool "Tosa keyboard: use extended keycodes" - depends on KEYBOARD_TOSA - help - Say Y here to enable the tosa keyboard driver to generate extended - (>= 127) keycodes. Be aware, that they can't be correctly interpreted - by either console keyboard driver or by Kdrive keybd driver. - - Say Y only if you know, what you are doing! - config KEYBOARD_XTKBD tristate "XT keyboard" select SERIO -- cgit v0.10.2 From 25646d70a0d386ab923a189f9790aeae3eb4f1b5 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Tue, 27 Apr 2010 14:50:54 +0800 Subject: input: remove obsolete {corgi,spitz,tosa}kbd.c Signed-off-by: Eric Miao diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 6237d74..a5e3811 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -520,17 +520,6 @@ Who: Hans de Goede ---------------------------- -What: corgikbd, spitzkbd, tosakbd driver -When: 2.6.35 -Files: drivers/input/keyboard/{corgi,spitz,tosa}kbd.c -Why: We now have a generic GPIO based matrix keyboard driver that - are fully capable of handling all the keys on these devices. - The original drivers manipulate the GPIO registers directly - and so are difficult to maintain. -Who: Eric Miao - ----------------------------- - What: capifs When: February 2011 Files: drivers/isdn/capi/capifs.* diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index a74ee12..a829338 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -143,19 +143,6 @@ config KEYBOARD_BFIN To compile this driver as a module, choose M here: the module will be called bf54x-keys. -config KEYBOARD_CORGI - tristate "Corgi keyboard (deprecated)" - depends on PXA_SHARPSL - help - Say Y here to enable the keyboard on the Sharp Zaurus SL-C7xx - series of PDAs. - - This driver is now deprecated, use generic GPIO based matrix - keyboard driver instead. - - To compile this driver as a module, choose M here: the - module will be called corgikbd. - config KEYBOARD_LKKBD tristate "DECstation/VAXstation LK201/LK401 keyboard" select SERIO @@ -339,19 +326,6 @@ config KEYBOARD_PXA930_ROTARY To compile this driver as a module, choose M here: the module will be called pxa930_rotary. -config KEYBOARD_SPITZ - tristate "Spitz keyboard (deprecated)" - depends on PXA_SHARPSL - help - Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000, - SL-C3000 and Sl-C3100 series of PDAs. - - This driver is now deprecated, use generic GPIO based matrix - keyboard driver instead. - - To compile this driver as a module, choose M here: the - module will be called spitzkbd. - config KEYBOARD_STOWAWAY tristate "Stowaway keyboard" select SERIO @@ -414,18 +388,6 @@ config KEYBOARD_TWL4030 To compile this driver as a module, choose M here: the module will be called twl4030_keypad. -config KEYBOARD_TOSA - tristate "Tosa keyboard (deprecated)" - depends on MACH_TOSA - help - Say Y here to enable the keyboard on the Sharp Zaurus SL-6000x (Tosa) - - This driver is now deprecated, use generic GPIO based matrix - keyboard driver instead. - - To compile this driver as a module, choose M here: the - module will be called tosakbd. - config KEYBOARD_XTKBD tristate "XT keyboard" select SERIO diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 706c6b5..9a74127e 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -11,7 +11,6 @@ obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o -obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o @@ -33,10 +32,8 @@ obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o obj-$(CONFIG_KEYBOARD_QT2160) += qt2160.o obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o -obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o -obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c deleted file mode 100644 index 634af6a..0000000 --- a/drivers/input/keyboard/corgikbd.c +++ /dev/null @@ -1,414 +0,0 @@ -/* - * Keyboard driver for Sharp Corgi models (SL-C7xx) - * - * Copyright (c) 2004-2005 Richard Purdie - * - * Based on xtkbd.c/locomkbd.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define KB_ROWS 8 -#define KB_COLS 12 -#define KB_ROWMASK(r) (1 << (r)) -#define SCANCODE(r,c) ( ((r)<<4) + (c) + 1 ) -/* zero code, 124 scancodes */ -#define NR_SCANCODES ( SCANCODE(KB_ROWS-1,KB_COLS-1) +1 +1 ) - -#define SCAN_INTERVAL (50) /* ms */ -#define HINGE_SCAN_INTERVAL (250) /* ms */ - -#define CORGI_KEY_CALENDER KEY_F1 -#define CORGI_KEY_ADDRESS KEY_F2 -#define CORGI_KEY_FN KEY_F3 -#define CORGI_KEY_CANCEL KEY_F4 -#define CORGI_KEY_OFF KEY_SUSPEND -#define CORGI_KEY_EXOK KEY_F5 -#define CORGI_KEY_EXCANCEL KEY_F6 -#define CORGI_KEY_EXJOGDOWN KEY_F7 -#define CORGI_KEY_EXJOGUP KEY_F8 -#define CORGI_KEY_JAP1 KEY_LEFTCTRL -#define CORGI_KEY_JAP2 KEY_LEFTALT -#define CORGI_KEY_MAIL KEY_F10 -#define CORGI_KEY_OK KEY_F11 -#define CORGI_KEY_MENU KEY_F12 - -static unsigned char corgikbd_keycode[NR_SCANCODES] = { - 0, /* 0 */ - 0, KEY_1, KEY_3, KEY_5, KEY_6, KEY_7, KEY_9, KEY_0, KEY_BACKSPACE, 0, 0, 0, 0, 0, 0, 0, /* 1-16 */ - 0, KEY_2, KEY_4, KEY_R, KEY_Y, KEY_8, KEY_I, KEY_O, KEY_P, 0, 0, 0, 0, 0, 0, 0, /* 17-32 */ - KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */ - CORGI_KEY_CALENDER, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */ - CORGI_KEY_ADDRESS, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, 0, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, /* 65-80 */ - CORGI_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, 0, CORGI_KEY_FN, 0, 0, 0, 0, /* 81-96 */ - KEY_SYSRQ, CORGI_KEY_JAP1, CORGI_KEY_JAP2, CORGI_KEY_CANCEL, CORGI_KEY_OK, CORGI_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0, /* 97-112 */ - CORGI_KEY_OFF, CORGI_KEY_EXOK, CORGI_KEY_EXCANCEL, CORGI_KEY_EXJOGDOWN, CORGI_KEY_EXJOGUP, 0, 0, 0, 0, 0, 0, 0, /* 113-124 */ -}; - - -struct corgikbd { - unsigned char keycode[ARRAY_SIZE(corgikbd_keycode)]; - struct input_dev *input; - - spinlock_t lock; - struct timer_list timer; - struct timer_list htimer; - - unsigned int suspended; - unsigned long suspend_jiffies; -}; - -#define KB_DISCHARGE_DELAY 10 -#define KB_ACTIVATE_DELAY 10 - -/* Helper functions for reading the keyboard matrix - * Note: We should really be using the generic gpio functions to alter - * GPDR but it requires a function call per GPIO bit which is - * excessive when we need to access 12 bits at once, multiple times. - * These functions must be called within local_irq_save()/local_irq_restore() - * or similar. - */ -static inline void corgikbd_discharge_all(void) -{ - /* STROBE All HiZ */ - GPCR2 = CORGI_GPIO_ALL_STROBE_BIT; - GPDR2 &= ~CORGI_GPIO_ALL_STROBE_BIT; -} - -static inline void corgikbd_activate_all(void) -{ - /* STROBE ALL -> High */ - GPSR2 = CORGI_GPIO_ALL_STROBE_BIT; - GPDR2 |= CORGI_GPIO_ALL_STROBE_BIT; - - udelay(KB_DISCHARGE_DELAY); - - /* Clear any interrupts we may have triggered when altering the GPIO lines */ - GEDR1 = CORGI_GPIO_HIGH_SENSE_BIT; - GEDR2 = CORGI_GPIO_LOW_SENSE_BIT; -} - -static inline void corgikbd_activate_col(int col) -{ - /* STROBE col -> High, not col -> HiZ */ - GPSR2 = CORGI_GPIO_STROBE_BIT(col); - GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col); -} - -static inline void corgikbd_reset_col(int col) -{ - /* STROBE col -> Low */ - GPCR2 = CORGI_GPIO_STROBE_BIT(col); - /* STROBE col -> out, not col -> HiZ */ - GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col); -} - -#define GET_ROWS_STATUS(c) (((GPLR1 & CORGI_GPIO_HIGH_SENSE_BIT) >> CORGI_GPIO_HIGH_SENSE_RSHIFT) | ((GPLR2 & CORGI_GPIO_LOW_SENSE_BIT) << CORGI_GPIO_LOW_SENSE_LSHIFT)) - -/* - * The corgi keyboard only generates interrupts when a key is pressed. - * When a key is pressed, we enable a timer which then scans the - * keyboard to detect when the key is released. - */ - -/* Scan the hardware keyboard and push any changes up through the input layer */ -static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data) -{ - unsigned int row, col, rowd; - unsigned long flags; - unsigned int num_pressed; - - if (corgikbd_data->suspended) - return; - - spin_lock_irqsave(&corgikbd_data->lock, flags); - - num_pressed = 0; - for (col = 0; col < KB_COLS; col++) { - /* - * Discharge the output driver capacitatance - * in the keyboard matrix. (Yes it is significant..) - */ - - corgikbd_discharge_all(); - udelay(KB_DISCHARGE_DELAY); - - corgikbd_activate_col(col); - udelay(KB_ACTIVATE_DELAY); - - rowd = GET_ROWS_STATUS(col); - for (row = 0; row < KB_ROWS; row++) { - unsigned int scancode, pressed; - - scancode = SCANCODE(row, col); - pressed = rowd & KB_ROWMASK(row); - - input_report_key(corgikbd_data->input, corgikbd_data->keycode[scancode], pressed); - - if (pressed) - num_pressed++; - - if (pressed && (corgikbd_data->keycode[scancode] == CORGI_KEY_OFF) - && time_after(jiffies, corgikbd_data->suspend_jiffies + HZ)) { - input_event(corgikbd_data->input, EV_PWR, CORGI_KEY_OFF, 1); - corgikbd_data->suspend_jiffies=jiffies; - } - } - corgikbd_reset_col(col); - } - - corgikbd_activate_all(); - - input_sync(corgikbd_data->input); - - /* if any keys are pressed, enable the timer */ - if (num_pressed) - mod_timer(&corgikbd_data->timer, jiffies + msecs_to_jiffies(SCAN_INTERVAL)); - - spin_unlock_irqrestore(&corgikbd_data->lock, flags); -} - -/* - * corgi keyboard interrupt handler. - */ -static irqreturn_t corgikbd_interrupt(int irq, void *dev_id) -{ - struct corgikbd *corgikbd_data = dev_id; - - if (!timer_pending(&corgikbd_data->timer)) { - /** wait chattering delay **/ - udelay(20); - corgikbd_scankeyboard(corgikbd_data); - } - - return IRQ_HANDLED; -} - -/* - * corgi timer checking for released keys - */ -static void corgikbd_timer_callback(unsigned long data) -{ - struct corgikbd *corgikbd_data = (struct corgikbd *) data; - corgikbd_scankeyboard(corgikbd_data); -} - -/* - * The hinge switches generate no interrupt so they need to be - * monitored by a timer. - * - * We debounce the switches and pass them to the input system. - * - * gprr == 0x00 - Keyboard with Landscape Screen - * 0x08 - No Keyboard with Portrait Screen - * 0x0c - Keyboard and Screen Closed - */ - -#define READ_GPIO_BIT(x) (GPLR(x) & GPIO_bit(x)) -#define HINGE_STABLE_COUNT 2 -static int sharpsl_hinge_state; -static int hinge_count; - -static void corgikbd_hinge_timer(unsigned long data) -{ - struct corgikbd *corgikbd_data = (struct corgikbd *) data; - unsigned long gprr; - unsigned long flags; - - gprr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_GPRR) & (CORGI_SCP_SWA | CORGI_SCP_SWB); - gprr |= (READ_GPIO_BIT(CORGI_GPIO_AK_INT) != 0); - if (gprr != sharpsl_hinge_state) { - hinge_count = 0; - sharpsl_hinge_state = gprr; - } else if (hinge_count < HINGE_STABLE_COUNT) { - hinge_count++; - if (hinge_count >= HINGE_STABLE_COUNT) { - spin_lock_irqsave(&corgikbd_data->lock, flags); - - input_report_switch(corgikbd_data->input, SW_LID, ((sharpsl_hinge_state & CORGI_SCP_SWA) != 0)); - input_report_switch(corgikbd_data->input, SW_TABLET_MODE, ((sharpsl_hinge_state & CORGI_SCP_SWB) != 0)); - input_report_switch(corgikbd_data->input, SW_HEADPHONE_INSERT, (READ_GPIO_BIT(CORGI_GPIO_AK_INT) != 0)); - input_sync(corgikbd_data->input); - - spin_unlock_irqrestore(&corgikbd_data->lock, flags); - } - } - mod_timer(&corgikbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); -} - -#ifdef CONFIG_PM -static int corgikbd_suspend(struct platform_device *dev, pm_message_t state) -{ - int i; - struct corgikbd *corgikbd = platform_get_drvdata(dev); - - corgikbd->suspended = 1; - /* strobe 0 is the power key so this can't be made an input for - powersaving therefore i = 1 */ - for (i = 1; i < CORGI_KEY_STROBE_NUM; i++) - pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_IN); - - return 0; -} - -static int corgikbd_resume(struct platform_device *dev) -{ - int i; - struct corgikbd *corgikbd = platform_get_drvdata(dev); - - for (i = 1; i < CORGI_KEY_STROBE_NUM; i++) - pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH); - - /* Upon resume, ignore the suspend key for a short while */ - corgikbd->suspend_jiffies=jiffies; - corgikbd->suspended = 0; - - return 0; -} -#else -#define corgikbd_suspend NULL -#define corgikbd_resume NULL -#endif - -static int __devinit corgikbd_probe(struct platform_device *pdev) -{ - struct corgikbd *corgikbd; - struct input_dev *input_dev; - int i, err = -ENOMEM; - - corgikbd = kzalloc(sizeof(struct corgikbd), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!corgikbd || !input_dev) - goto fail; - - platform_set_drvdata(pdev, corgikbd); - - corgikbd->input = input_dev; - spin_lock_init(&corgikbd->lock); - - /* Init Keyboard rescan timer */ - init_timer(&corgikbd->timer); - corgikbd->timer.function = corgikbd_timer_callback; - corgikbd->timer.data = (unsigned long) corgikbd; - - /* Init Hinge Timer */ - init_timer(&corgikbd->htimer); - corgikbd->htimer.function = corgikbd_hinge_timer; - corgikbd->htimer.data = (unsigned long) corgikbd; - - corgikbd->suspend_jiffies=jiffies; - - memcpy(corgikbd->keycode, corgikbd_keycode, sizeof(corgikbd->keycode)); - - input_dev->name = "Corgi Keyboard"; - input_dev->phys = "corgikbd/input0"; - input_dev->id.bustype = BUS_HOST; - input_dev->id.vendor = 0x0001; - input_dev->id.product = 0x0001; - input_dev->id.version = 0x0100; - input_dev->dev.parent = &pdev->dev; - - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | - BIT_MASK(EV_PWR) | BIT_MASK(EV_SW); - input_dev->keycode = corgikbd->keycode; - input_dev->keycodesize = sizeof(unsigned char); - input_dev->keycodemax = ARRAY_SIZE(corgikbd_keycode); - - for (i = 0; i < ARRAY_SIZE(corgikbd_keycode); i++) - set_bit(corgikbd->keycode[i], input_dev->keybit); - clear_bit(0, input_dev->keybit); - set_bit(SW_LID, input_dev->swbit); - set_bit(SW_TABLET_MODE, input_dev->swbit); - set_bit(SW_HEADPHONE_INSERT, input_dev->swbit); - - err = input_register_device(corgikbd->input); - if (err) - goto fail; - - mod_timer(&corgikbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); - - /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */ - for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) { - pxa_gpio_mode(CORGI_GPIO_KEY_SENSE(i) | GPIO_IN); - if (request_irq(CORGI_IRQ_GPIO_KEY_SENSE(i), corgikbd_interrupt, - IRQF_DISABLED | IRQF_TRIGGER_RISING, - "corgikbd", corgikbd)) - printk(KERN_WARNING "corgikbd: Can't get IRQ: %d!\n", i); - } - - /* Set Strobe lines as outputs - set high */ - for (i = 0; i < CORGI_KEY_STROBE_NUM; i++) - pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH); - - /* Setup the headphone jack as an input */ - pxa_gpio_mode(CORGI_GPIO_AK_INT | GPIO_IN); - - return 0; - - fail: input_free_device(input_dev); - kfree(corgikbd); - return err; -} - -static int __devexit corgikbd_remove(struct platform_device *pdev) -{ - int i; - struct corgikbd *corgikbd = platform_get_drvdata(pdev); - - for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) - free_irq(CORGI_IRQ_GPIO_KEY_SENSE(i), corgikbd); - - del_timer_sync(&corgikbd->htimer); - del_timer_sync(&corgikbd->timer); - - input_unregister_device(corgikbd->input); - - kfree(corgikbd); - - return 0; -} - -static struct platform_driver corgikbd_driver = { - .probe = corgikbd_probe, - .remove = __devexit_p(corgikbd_remove), - .suspend = corgikbd_suspend, - .resume = corgikbd_resume, - .driver = { - .name = "corgi-keyboard", - .owner = THIS_MODULE, - }, -}; - -static int __init corgikbd_init(void) -{ - return platform_driver_register(&corgikbd_driver); -} - -static void __exit corgikbd_exit(void) -{ - platform_driver_unregister(&corgikbd_driver); -} - -module_init(corgikbd_init); -module_exit(corgikbd_exit); - -MODULE_AUTHOR("Richard Purdie "); -MODULE_DESCRIPTION("Corgi Keyboard Driver"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:corgi-keyboard"); diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c deleted file mode 100644 index 1396742..0000000 --- a/drivers/input/keyboard/spitzkbd.c +++ /dev/null @@ -1,496 +0,0 @@ -/* - * Keyboard driver for Sharp Spitz, Borzoi and Akita (SL-Cxx00 series) - * - * Copyright (c) 2005 Richard Purdie - * - * Based on corgikbd.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define KB_ROWS 7 -#define KB_COLS 11 -#define KB_ROWMASK(r) (1 << (r)) -#define SCANCODE(r,c) (((r)<<4) + (c) + 1) -#define NR_SCANCODES ((KB_ROWS<<4) + 1) - -#define SCAN_INTERVAL (50) /* ms */ -#define HINGE_SCAN_INTERVAL (150) /* ms */ - -#define SPITZ_KEY_CALENDER KEY_F1 -#define SPITZ_KEY_ADDRESS KEY_F2 -#define SPITZ_KEY_FN KEY_F3 -#define SPITZ_KEY_CANCEL KEY_F4 -#define SPITZ_KEY_EXOK KEY_F5 -#define SPITZ_KEY_EXCANCEL KEY_F6 -#define SPITZ_KEY_EXJOGDOWN KEY_F7 -#define SPITZ_KEY_EXJOGUP KEY_F8 -#define SPITZ_KEY_JAP1 KEY_LEFTALT -#define SPITZ_KEY_JAP2 KEY_RIGHTCTRL -#define SPITZ_KEY_SYNC KEY_F9 -#define SPITZ_KEY_MAIL KEY_F10 -#define SPITZ_KEY_OK KEY_F11 -#define SPITZ_KEY_MENU KEY_F12 - -static unsigned char spitzkbd_keycode[NR_SCANCODES] = { - 0, /* 0 */ - KEY_LEFTCTRL, KEY_1, KEY_3, KEY_5, KEY_6, KEY_7, KEY_9, KEY_0, KEY_BACKSPACE, SPITZ_KEY_EXOK, SPITZ_KEY_EXCANCEL, 0, 0, 0, 0, 0, /* 1-16 */ - 0, KEY_2, KEY_4, KEY_R, KEY_Y, KEY_8, KEY_I, KEY_O, KEY_P, SPITZ_KEY_EXJOGDOWN, SPITZ_KEY_EXJOGUP, 0, 0, 0, 0, 0, /* 17-32 */ - KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */ - SPITZ_KEY_ADDRESS, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */ - SPITZ_KEY_CALENDER, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0, /* 65-80 */ - SPITZ_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, SPITZ_KEY_FN, 0, 0, 0, 0, 0, /* 81-96 */ - KEY_SYSRQ, SPITZ_KEY_JAP1, SPITZ_KEY_JAP2, SPITZ_KEY_CANCEL, SPITZ_KEY_OK, SPITZ_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0 /* 97-112 */ -}; - -static int spitz_strobes[] = { - SPITZ_GPIO_KEY_STROBE0, - SPITZ_GPIO_KEY_STROBE1, - SPITZ_GPIO_KEY_STROBE2, - SPITZ_GPIO_KEY_STROBE3, - SPITZ_GPIO_KEY_STROBE4, - SPITZ_GPIO_KEY_STROBE5, - SPITZ_GPIO_KEY_STROBE6, - SPITZ_GPIO_KEY_STROBE7, - SPITZ_GPIO_KEY_STROBE8, - SPITZ_GPIO_KEY_STROBE9, - SPITZ_GPIO_KEY_STROBE10, -}; - -static int spitz_senses[] = { - SPITZ_GPIO_KEY_SENSE0, - SPITZ_GPIO_KEY_SENSE1, - SPITZ_GPIO_KEY_SENSE2, - SPITZ_GPIO_KEY_SENSE3, - SPITZ_GPIO_KEY_SENSE4, - SPITZ_GPIO_KEY_SENSE5, - SPITZ_GPIO_KEY_SENSE6, -}; - -struct spitzkbd { - unsigned char keycode[ARRAY_SIZE(spitzkbd_keycode)]; - struct input_dev *input; - char phys[32]; - - spinlock_t lock; - struct timer_list timer; - struct timer_list htimer; - - unsigned int suspended; - unsigned long suspend_jiffies; -}; - -#define KB_DISCHARGE_DELAY 10 -#define KB_ACTIVATE_DELAY 10 - -/* Helper functions for reading the keyboard matrix - * Note: We should really be using the generic gpio functions to alter - * GPDR but it requires a function call per GPIO bit which is - * excessive when we need to access 11 bits at once, multiple times. - * These functions must be called within local_irq_save()/local_irq_restore() - * or similar. - */ -static inline void spitzkbd_discharge_all(void) -{ - /* STROBE All HiZ */ - GPCR0 = SPITZ_GPIO_G0_STROBE_BIT; - GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT; - GPCR1 = SPITZ_GPIO_G1_STROBE_BIT; - GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT; - GPCR2 = SPITZ_GPIO_G2_STROBE_BIT; - GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT; - GPCR3 = SPITZ_GPIO_G3_STROBE_BIT; - GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT; -} - -static inline void spitzkbd_activate_all(void) -{ - /* STROBE ALL -> High */ - GPSR0 = SPITZ_GPIO_G0_STROBE_BIT; - GPDR0 |= SPITZ_GPIO_G0_STROBE_BIT; - GPSR1 = SPITZ_GPIO_G1_STROBE_BIT; - GPDR1 |= SPITZ_GPIO_G1_STROBE_BIT; - GPSR2 = SPITZ_GPIO_G2_STROBE_BIT; - GPDR2 |= SPITZ_GPIO_G2_STROBE_BIT; - GPSR3 = SPITZ_GPIO_G3_STROBE_BIT; - GPDR3 |= SPITZ_GPIO_G3_STROBE_BIT; - - udelay(KB_DISCHARGE_DELAY); - - /* Clear any interrupts we may have triggered when altering the GPIO lines */ - GEDR0 = SPITZ_GPIO_G0_SENSE_BIT; - GEDR1 = SPITZ_GPIO_G1_SENSE_BIT; - GEDR2 = SPITZ_GPIO_G2_SENSE_BIT; - GEDR3 = SPITZ_GPIO_G3_SENSE_BIT; -} - -static inline void spitzkbd_activate_col(int col) -{ - int gpio = spitz_strobes[col]; - GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT; - GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT; - GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT; - GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT; - GPSR(gpio) = GPIO_bit(gpio); - GPDR(gpio) |= GPIO_bit(gpio); -} - -static inline void spitzkbd_reset_col(int col) -{ - int gpio = spitz_strobes[col]; - GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT; - GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT; - GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT; - GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT; - GPCR(gpio) = GPIO_bit(gpio); - GPDR(gpio) |= GPIO_bit(gpio); -} - -static inline int spitzkbd_get_row_status(int col) -{ - return ((GPLR0 >> 12) & 0x01) | ((GPLR0 >> 16) & 0x02) - | ((GPLR2 >> 25) & 0x04) | ((GPLR1 << 1) & 0x08) - | ((GPLR1 >> 0) & 0x10) | ((GPLR1 >> 1) & 0x60); -} - -/* - * The spitz keyboard only generates interrupts when a key is pressed. - * When a key is pressed, we enable a timer which then scans the - * keyboard to detect when the key is released. - */ - -/* Scan the hardware keyboard and push any changes up through the input layer */ -static void spitzkbd_scankeyboard(struct spitzkbd *spitzkbd_data) -{ - unsigned int row, col, rowd; - unsigned long flags; - unsigned int num_pressed, pwrkey = ((GPLR(SPITZ_GPIO_ON_KEY) & GPIO_bit(SPITZ_GPIO_ON_KEY)) != 0); - - if (spitzkbd_data->suspended) - return; - - spin_lock_irqsave(&spitzkbd_data->lock, flags); - - num_pressed = 0; - for (col = 0; col < KB_COLS; col++) { - /* - * Discharge the output driver capacitatance - * in the keyboard matrix. (Yes it is significant..) - */ - - spitzkbd_discharge_all(); - udelay(KB_DISCHARGE_DELAY); - - spitzkbd_activate_col(col); - udelay(KB_ACTIVATE_DELAY); - - rowd = spitzkbd_get_row_status(col); - for (row = 0; row < KB_ROWS; row++) { - unsigned int scancode, pressed; - - scancode = SCANCODE(row, col); - pressed = rowd & KB_ROWMASK(row); - - input_report_key(spitzkbd_data->input, spitzkbd_data->keycode[scancode], pressed); - - if (pressed) - num_pressed++; - } - spitzkbd_reset_col(col); - } - - spitzkbd_activate_all(); - - input_report_key(spitzkbd_data->input, SPITZ_KEY_SYNC, (GPLR(SPITZ_GPIO_SYNC) & GPIO_bit(SPITZ_GPIO_SYNC)) != 0 ); - input_report_key(spitzkbd_data->input, KEY_SUSPEND, pwrkey); - - if (pwrkey && time_after(jiffies, spitzkbd_data->suspend_jiffies + msecs_to_jiffies(1000))) { - input_event(spitzkbd_data->input, EV_PWR, KEY_SUSPEND, 1); - spitzkbd_data->suspend_jiffies = jiffies; - } - - input_sync(spitzkbd_data->input); - - /* if any keys are pressed, enable the timer */ - if (num_pressed) - mod_timer(&spitzkbd_data->timer, jiffies + msecs_to_jiffies(SCAN_INTERVAL)); - - spin_unlock_irqrestore(&spitzkbd_data->lock, flags); -} - -/* - * spitz keyboard interrupt handler. - */ -static irqreturn_t spitzkbd_interrupt(int irq, void *dev_id) -{ - struct spitzkbd *spitzkbd_data = dev_id; - - if (!timer_pending(&spitzkbd_data->timer)) { - /** wait chattering delay **/ - udelay(20); - spitzkbd_scankeyboard(spitzkbd_data); - } - - return IRQ_HANDLED; -} - -/* - * spitz timer checking for released keys - */ -static void spitzkbd_timer_callback(unsigned long data) -{ - struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data; - - spitzkbd_scankeyboard(spitzkbd_data); -} - -/* - * The hinge switches generate an interrupt. - * We debounce the switches and pass them to the input system. - */ - -static irqreturn_t spitzkbd_hinge_isr(int irq, void *dev_id) -{ - struct spitzkbd *spitzkbd_data = dev_id; - - if (!timer_pending(&spitzkbd_data->htimer)) - mod_timer(&spitzkbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); - - return IRQ_HANDLED; -} - -#define HINGE_STABLE_COUNT 2 -static int sharpsl_hinge_state; -static int hinge_count; - -static void spitzkbd_hinge_timer(unsigned long data) -{ - struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data; - unsigned long state; - unsigned long flags; - - state = GPLR(SPITZ_GPIO_SWA) & (GPIO_bit(SPITZ_GPIO_SWA)|GPIO_bit(SPITZ_GPIO_SWB)); - state |= (GPLR(SPITZ_GPIO_AK_INT) & GPIO_bit(SPITZ_GPIO_AK_INT)); - if (state != sharpsl_hinge_state) { - hinge_count = 0; - sharpsl_hinge_state = state; - } else if (hinge_count < HINGE_STABLE_COUNT) { - hinge_count++; - } - - if (hinge_count >= HINGE_STABLE_COUNT) { - spin_lock_irqsave(&spitzkbd_data->lock, flags); - - input_report_switch(spitzkbd_data->input, SW_LID, ((GPLR(SPITZ_GPIO_SWA) & GPIO_bit(SPITZ_GPIO_SWA)) != 0)); - input_report_switch(spitzkbd_data->input, SW_TABLET_MODE, ((GPLR(SPITZ_GPIO_SWB) & GPIO_bit(SPITZ_GPIO_SWB)) != 0)); - input_report_switch(spitzkbd_data->input, SW_HEADPHONE_INSERT, ((GPLR(SPITZ_GPIO_AK_INT) & GPIO_bit(SPITZ_GPIO_AK_INT)) != 0)); - input_sync(spitzkbd_data->input); - - spin_unlock_irqrestore(&spitzkbd_data->lock, flags); - } else { - mod_timer(&spitzkbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); - } -} - -#ifdef CONFIG_PM -static int spitzkbd_suspend(struct platform_device *dev, pm_message_t state) -{ - int i; - struct spitzkbd *spitzkbd = platform_get_drvdata(dev); - spitzkbd->suspended = 1; - - /* Set Strobe lines as inputs - *except* strobe line 0 leave this - enabled so we can detect a power button press for resume */ - for (i = 1; i < SPITZ_KEY_STROBE_NUM; i++) - pxa_gpio_mode(spitz_strobes[i] | GPIO_IN); - - return 0; -} - -static int spitzkbd_resume(struct platform_device *dev) -{ - int i; - struct spitzkbd *spitzkbd = platform_get_drvdata(dev); - - for (i = 0; i < SPITZ_KEY_STROBE_NUM; i++) - pxa_gpio_mode(spitz_strobes[i] | GPIO_OUT | GPIO_DFLT_HIGH); - - /* Upon resume, ignore the suspend key for a short while */ - spitzkbd->suspend_jiffies = jiffies; - spitzkbd->suspended = 0; - - return 0; -} -#else -#define spitzkbd_suspend NULL -#define spitzkbd_resume NULL -#endif - -static int __devinit spitzkbd_probe(struct platform_device *dev) -{ - struct spitzkbd *spitzkbd; - struct input_dev *input_dev; - int i, err = -ENOMEM; - - spitzkbd = kzalloc(sizeof(struct spitzkbd), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!spitzkbd || !input_dev) - goto fail; - - platform_set_drvdata(dev, spitzkbd); - strcpy(spitzkbd->phys, "spitzkbd/input0"); - - spin_lock_init(&spitzkbd->lock); - - /* Init Keyboard rescan timer */ - init_timer(&spitzkbd->timer); - spitzkbd->timer.function = spitzkbd_timer_callback; - spitzkbd->timer.data = (unsigned long) spitzkbd; - - /* Init Hinge Timer */ - init_timer(&spitzkbd->htimer); - spitzkbd->htimer.function = spitzkbd_hinge_timer; - spitzkbd->htimer.data = (unsigned long) spitzkbd; - - spitzkbd->suspend_jiffies = jiffies; - - spitzkbd->input = input_dev; - - input_dev->name = "Spitz Keyboard"; - input_dev->phys = spitzkbd->phys; - input_dev->dev.parent = &dev->dev; - - input_dev->id.bustype = BUS_HOST; - input_dev->id.vendor = 0x0001; - input_dev->id.product = 0x0001; - input_dev->id.version = 0x0100; - - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | - BIT_MASK(EV_PWR) | BIT_MASK(EV_SW); - input_dev->keycode = spitzkbd->keycode; - input_dev->keycodesize = sizeof(unsigned char); - input_dev->keycodemax = ARRAY_SIZE(spitzkbd_keycode); - - memcpy(spitzkbd->keycode, spitzkbd_keycode, sizeof(spitzkbd->keycode)); - for (i = 0; i < ARRAY_SIZE(spitzkbd_keycode); i++) - set_bit(spitzkbd->keycode[i], input_dev->keybit); - clear_bit(0, input_dev->keybit); - set_bit(KEY_SUSPEND, input_dev->keybit); - set_bit(SW_LID, input_dev->swbit); - set_bit(SW_TABLET_MODE, input_dev->swbit); - set_bit(SW_HEADPHONE_INSERT, input_dev->swbit); - - err = input_register_device(input_dev); - if (err) - goto fail; - - mod_timer(&spitzkbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); - - /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */ - for (i = 0; i < SPITZ_KEY_SENSE_NUM; i++) { - pxa_gpio_mode(spitz_senses[i] | GPIO_IN); - if (request_irq(IRQ_GPIO(spitz_senses[i]), spitzkbd_interrupt, - IRQF_DISABLED|IRQF_TRIGGER_RISING, - "Spitzkbd Sense", spitzkbd)) - printk(KERN_WARNING "spitzkbd: Can't get Sense IRQ: %d!\n", i); - } - - /* Set Strobe lines as outputs - set high */ - for (i = 0; i < SPITZ_KEY_STROBE_NUM; i++) - pxa_gpio_mode(spitz_strobes[i] | GPIO_OUT | GPIO_DFLT_HIGH); - - pxa_gpio_mode(SPITZ_GPIO_SYNC | GPIO_IN); - pxa_gpio_mode(SPITZ_GPIO_ON_KEY | GPIO_IN); - pxa_gpio_mode(SPITZ_GPIO_SWA | GPIO_IN); - pxa_gpio_mode(SPITZ_GPIO_SWB | GPIO_IN); - - request_irq(SPITZ_IRQ_GPIO_SYNC, spitzkbd_interrupt, - IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "Spitzkbd Sync", spitzkbd); - request_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd_interrupt, - IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "Spitzkbd PwrOn", spitzkbd); - request_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd_hinge_isr, - IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "Spitzkbd SWA", spitzkbd); - request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr, - IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "Spitzkbd SWB", spitzkbd); - request_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd_hinge_isr, - IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "Spitzkbd HP", spitzkbd); - - return 0; - - fail: input_free_device(input_dev); - kfree(spitzkbd); - return err; -} - -static int __devexit spitzkbd_remove(struct platform_device *dev) -{ - int i; - struct spitzkbd *spitzkbd = platform_get_drvdata(dev); - - for (i = 0; i < SPITZ_KEY_SENSE_NUM; i++) - free_irq(IRQ_GPIO(spitz_senses[i]), spitzkbd); - - free_irq(SPITZ_IRQ_GPIO_SYNC, spitzkbd); - free_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd); - free_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd); - free_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd); - free_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd); - - del_timer_sync(&spitzkbd->htimer); - del_timer_sync(&spitzkbd->timer); - - input_unregister_device(spitzkbd->input); - - kfree(spitzkbd); - - return 0; -} - -static struct platform_driver spitzkbd_driver = { - .probe = spitzkbd_probe, - .remove = __devexit_p(spitzkbd_remove), - .suspend = spitzkbd_suspend, - .resume = spitzkbd_resume, - .driver = { - .name = "spitz-keyboard", - .owner = THIS_MODULE, - }, -}; - -static int __init spitzkbd_init(void) -{ - return platform_driver_register(&spitzkbd_driver); -} - -static void __exit spitzkbd_exit(void) -{ - platform_driver_unregister(&spitzkbd_driver); -} - -module_init(spitzkbd_init); -module_exit(spitzkbd_exit); - -MODULE_AUTHOR("Richard Purdie "); -MODULE_DESCRIPTION("Spitz Keyboard Driver"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:spitz-keyboard"); diff --git a/drivers/input/keyboard/tosakbd.c b/drivers/input/keyboard/tosakbd.c deleted file mode 100644 index 3910f26..0000000 --- a/drivers/input/keyboard/tosakbd.c +++ /dev/null @@ -1,431 +0,0 @@ -/* - * Keyboard driver for Sharp Tosa models (SL-6000x) - * - * Copyright (c) 2005 Dirk Opfer - * Copyright (c) 2007 Dmitry Baryshkov - * - * Based on xtkbd.c/locomkbd.c/corgikbd.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define KB_ROWMASK(r) (1 << (r)) -#define SCANCODE(r, c) (((r)<<4) + (c) + 1) -#define NR_SCANCODES SCANCODE(TOSA_KEY_SENSE_NUM - 1, TOSA_KEY_STROBE_NUM - 1) + 1 - -#define SCAN_INTERVAL (HZ/10) - -#define KB_DISCHARGE_DELAY 10 -#define KB_ACTIVATE_DELAY 10 - -static unsigned short tosakbd_keycode[NR_SCANCODES] = { -0, -0, KEY_W, 0, 0, 0, KEY_K, KEY_BACKSPACE, KEY_P, -0, 0, 0, 0, 0, 0, 0, 0, -KEY_Q, KEY_E, KEY_T, KEY_Y, 0, KEY_O, KEY_I, KEY_COMMA, -0, 0, 0, 0, 0, 0, 0, 0, -KEY_A, KEY_D, KEY_G, KEY_U, 0, KEY_L, KEY_ENTER, KEY_DOT, -0, 0, 0, 0, 0, 0, 0, 0, -KEY_Z, KEY_C, KEY_V, KEY_J, TOSA_KEY_ADDRESSBOOK, TOSA_KEY_CANCEL, TOSA_KEY_CENTER, TOSA_KEY_OK, -KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0, 0, -KEY_S, KEY_R, KEY_B, KEY_N, TOSA_KEY_CALENDAR, TOSA_KEY_HOMEPAGE, KEY_LEFTCTRL, TOSA_KEY_LIGHT, -0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, -KEY_TAB, KEY_SLASH, KEY_H, KEY_M, TOSA_KEY_MENU, 0, KEY_UP, 0, -0, 0, TOSA_KEY_FN, 0, 0, 0, 0, 0, -KEY_X, KEY_F, KEY_SPACE, KEY_APOSTROPHE, TOSA_KEY_MAIL, KEY_LEFT, KEY_DOWN, KEY_RIGHT, -0, 0, 0, -}; - -struct tosakbd { - unsigned short keycode[ARRAY_SIZE(tosakbd_keycode)]; - struct input_dev *input; - bool suspended; - spinlock_t lock; /* protect kbd scanning */ - struct timer_list timer; -}; - - -/* Helper functions for reading the keyboard matrix - * Note: We should really be using the generic gpio functions to alter - * GPDR but it requires a function call per GPIO bit which is - * excessive when we need to access 12 bits at once, multiple times. - * These functions must be called within local_irq_save()/local_irq_restore() - * or similar. - */ -#define GET_ROWS_STATUS(c) ((GPLR2 & TOSA_GPIO_ALL_SENSE_BIT) >> TOSA_GPIO_ALL_SENSE_RSHIFT) - -static inline void tosakbd_discharge_all(void) -{ - /* STROBE All HiZ */ - GPCR1 = TOSA_GPIO_HIGH_STROBE_BIT; - GPDR1 &= ~TOSA_GPIO_HIGH_STROBE_BIT; - GPCR2 = TOSA_GPIO_LOW_STROBE_BIT; - GPDR2 &= ~TOSA_GPIO_LOW_STROBE_BIT; -} - -static inline void tosakbd_activate_all(void) -{ - /* STROBE ALL -> High */ - GPSR1 = TOSA_GPIO_HIGH_STROBE_BIT; - GPDR1 |= TOSA_GPIO_HIGH_STROBE_BIT; - GPSR2 = TOSA_GPIO_LOW_STROBE_BIT; - GPDR2 |= TOSA_GPIO_LOW_STROBE_BIT; - - udelay(KB_DISCHARGE_DELAY); - - /* STATE CLEAR */ - GEDR2 |= TOSA_GPIO_ALL_SENSE_BIT; -} - -static inline void tosakbd_activate_col(int col) -{ - if (col <= 5) { - /* STROBE col -> High, not col -> HiZ */ - GPSR1 = TOSA_GPIO_STROBE_BIT(col); - GPDR1 = (GPDR1 & ~TOSA_GPIO_HIGH_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); - } else { - /* STROBE col -> High, not col -> HiZ */ - GPSR2 = TOSA_GPIO_STROBE_BIT(col); - GPDR2 = (GPDR2 & ~TOSA_GPIO_LOW_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); - } -} - -static inline void tosakbd_reset_col(int col) -{ - if (col <= 5) { - /* STROBE col -> Low */ - GPCR1 = TOSA_GPIO_STROBE_BIT(col); - /* STROBE col -> out, not col -> HiZ */ - GPDR1 = (GPDR1 & ~TOSA_GPIO_HIGH_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); - } else { - /* STROBE col -> Low */ - GPCR2 = TOSA_GPIO_STROBE_BIT(col); - /* STROBE col -> out, not col -> HiZ */ - GPDR2 = (GPDR2 & ~TOSA_GPIO_LOW_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); - } -} -/* - * The tosa keyboard only generates interrupts when a key is pressed. - * So when a key is pressed, we enable a timer. This timer scans the - * keyboard, and this is how we detect when the key is released. - */ - -/* Scan the hardware keyboard and push any changes up through the input layer */ -static void tosakbd_scankeyboard(struct platform_device *dev) -{ - struct tosakbd *tosakbd = platform_get_drvdata(dev); - unsigned int row, col, rowd; - unsigned long flags; - unsigned int num_pressed = 0; - - spin_lock_irqsave(&tosakbd->lock, flags); - - if (tosakbd->suspended) - goto out; - - for (col = 0; col < TOSA_KEY_STROBE_NUM; col++) { - /* - * Discharge the output driver capacitatance - * in the keyboard matrix. (Yes it is significant..) - */ - tosakbd_discharge_all(); - udelay(KB_DISCHARGE_DELAY); - - tosakbd_activate_col(col); - udelay(KB_ACTIVATE_DELAY); - - rowd = GET_ROWS_STATUS(col); - - for (row = 0; row < TOSA_KEY_SENSE_NUM; row++) { - unsigned int scancode, pressed; - scancode = SCANCODE(row, col); - pressed = rowd & KB_ROWMASK(row); - - if (pressed && !tosakbd->keycode[scancode]) - dev_warn(&dev->dev, - "unhandled scancode: 0x%02x\n", - scancode); - - input_report_key(tosakbd->input, - tosakbd->keycode[scancode], - pressed); - if (pressed) - num_pressed++; - } - - tosakbd_reset_col(col); - } - - tosakbd_activate_all(); - - input_sync(tosakbd->input); - - /* if any keys are pressed, enable the timer */ - if (num_pressed) - mod_timer(&tosakbd->timer, jiffies + SCAN_INTERVAL); - - out: - spin_unlock_irqrestore(&tosakbd->lock, flags); -} - -/* - * tosa keyboard interrupt handler. - */ -static irqreturn_t tosakbd_interrupt(int irq, void *__dev) -{ - struct platform_device *dev = __dev; - struct tosakbd *tosakbd = platform_get_drvdata(dev); - - if (!timer_pending(&tosakbd->timer)) { - /** wait chattering delay **/ - udelay(20); - tosakbd_scankeyboard(dev); - } - - return IRQ_HANDLED; -} - -/* - * tosa timer checking for released keys - */ -static void tosakbd_timer_callback(unsigned long __dev) -{ - struct platform_device *dev = (struct platform_device *)__dev; - - tosakbd_scankeyboard(dev); -} - -#ifdef CONFIG_PM -static int tosakbd_suspend(struct platform_device *dev, pm_message_t state) -{ - struct tosakbd *tosakbd = platform_get_drvdata(dev); - unsigned long flags; - - spin_lock_irqsave(&tosakbd->lock, flags); - tosakbd->suspended = true; - spin_unlock_irqrestore(&tosakbd->lock, flags); - - del_timer_sync(&tosakbd->timer); - - return 0; -} - -static int tosakbd_resume(struct platform_device *dev) -{ - struct tosakbd *tosakbd = platform_get_drvdata(dev); - - tosakbd->suspended = false; - tosakbd_scankeyboard(dev); - - return 0; -} -#else -#define tosakbd_suspend NULL -#define tosakbd_resume NULL -#endif - -static int __devinit tosakbd_probe(struct platform_device *pdev) { - - int i; - struct tosakbd *tosakbd; - struct input_dev *input_dev; - int error; - - tosakbd = kzalloc(sizeof(struct tosakbd), GFP_KERNEL); - if (!tosakbd) - return -ENOMEM; - - input_dev = input_allocate_device(); - if (!input_dev) { - kfree(tosakbd); - return -ENOMEM; - } - - platform_set_drvdata(pdev, tosakbd); - - spin_lock_init(&tosakbd->lock); - - /* Init Keyboard rescan timer */ - init_timer(&tosakbd->timer); - tosakbd->timer.function = tosakbd_timer_callback; - tosakbd->timer.data = (unsigned long) pdev; - - tosakbd->input = input_dev; - - input_set_drvdata(input_dev, tosakbd); - input_dev->name = "Tosa Keyboard"; - input_dev->phys = "tosakbd/input0"; - input_dev->dev.parent = &pdev->dev; - - input_dev->id.bustype = BUS_HOST; - input_dev->id.vendor = 0x0001; - input_dev->id.product = 0x0001; - input_dev->id.version = 0x0100; - - input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); - input_dev->keycode = tosakbd->keycode; - input_dev->keycodesize = sizeof(tosakbd->keycode[0]); - input_dev->keycodemax = ARRAY_SIZE(tosakbd_keycode); - - memcpy(tosakbd->keycode, tosakbd_keycode, sizeof(tosakbd_keycode)); - - for (i = 0; i < ARRAY_SIZE(tosakbd_keycode); i++) - __set_bit(tosakbd->keycode[i], input_dev->keybit); - __clear_bit(KEY_RESERVED, input_dev->keybit); - - /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */ - for (i = 0; i < TOSA_KEY_SENSE_NUM; i++) { - int gpio = TOSA_GPIO_KEY_SENSE(i); - int irq; - error = gpio_request(gpio, "tosakbd"); - if (error < 0) { - printk(KERN_ERR "tosakbd: failed to request GPIO %d, " - " error %d\n", gpio, error); - goto fail; - } - - error = gpio_direction_input(TOSA_GPIO_KEY_SENSE(i)); - if (error < 0) { - printk(KERN_ERR "tosakbd: failed to configure input" - " direction for GPIO %d, error %d\n", - gpio, error); - gpio_free(gpio); - goto fail; - } - - irq = gpio_to_irq(gpio); - if (irq < 0) { - error = irq; - printk(KERN_ERR "gpio-keys: Unable to get irq number" - " for GPIO %d, error %d\n", - gpio, error); - gpio_free(gpio); - goto fail; - } - - error = request_irq(irq, tosakbd_interrupt, - IRQF_DISABLED | IRQF_TRIGGER_RISING, - "tosakbd", pdev); - - if (error) { - printk("tosakbd: Can't get IRQ: %d: error %d!\n", - irq, error); - gpio_free(gpio); - goto fail; - } - } - - /* Set Strobe lines as outputs - set high */ - for (i = 0; i < TOSA_KEY_STROBE_NUM; i++) { - int gpio = TOSA_GPIO_KEY_STROBE(i); - error = gpio_request(gpio, "tosakbd"); - if (error < 0) { - printk(KERN_ERR "tosakbd: failed to request GPIO %d, " - " error %d\n", gpio, error); - goto fail2; - } - - error = gpio_direction_output(gpio, 1); - if (error < 0) { - printk(KERN_ERR "tosakbd: failed to configure input" - " direction for GPIO %d, error %d\n", - gpio, error); - gpio_free(gpio); - goto fail2; - } - - } - - error = input_register_device(input_dev); - if (error) { - printk(KERN_ERR "tosakbd: Unable to register input device, " - "error: %d\n", error); - goto fail2; - } - - printk(KERN_INFO "input: Tosa Keyboard Registered\n"); - - return 0; - -fail2: - while (--i >= 0) - gpio_free(TOSA_GPIO_KEY_STROBE(i)); - - i = TOSA_KEY_SENSE_NUM; -fail: - while (--i >= 0) { - free_irq(gpio_to_irq(TOSA_GPIO_KEY_SENSE(i)), pdev); - gpio_free(TOSA_GPIO_KEY_SENSE(i)); - } - - platform_set_drvdata(pdev, NULL); - input_free_device(input_dev); - kfree(tosakbd); - - return error; -} - -static int __devexit tosakbd_remove(struct platform_device *dev) -{ - int i; - struct tosakbd *tosakbd = platform_get_drvdata(dev); - - for (i = 0; i < TOSA_KEY_STROBE_NUM; i++) - gpio_free(TOSA_GPIO_KEY_STROBE(i)); - - for (i = 0; i < TOSA_KEY_SENSE_NUM; i++) { - free_irq(gpio_to_irq(TOSA_GPIO_KEY_SENSE(i)), dev); - gpio_free(TOSA_GPIO_KEY_SENSE(i)); - } - - del_timer_sync(&tosakbd->timer); - - input_unregister_device(tosakbd->input); - - kfree(tosakbd); - - return 0; -} - -static struct platform_driver tosakbd_driver = { - .probe = tosakbd_probe, - .remove = __devexit_p(tosakbd_remove), - .suspend = tosakbd_suspend, - .resume = tosakbd_resume, - .driver = { - .name = "tosa-keyboard", - .owner = THIS_MODULE, - }, -}; - -static int __devinit tosakbd_init(void) -{ - return platform_driver_register(&tosakbd_driver); -} - -static void __exit tosakbd_exit(void) -{ - platform_driver_unregister(&tosakbd_driver); -} - -module_init(tosakbd_init); -module_exit(tosakbd_exit); - -MODULE_AUTHOR("Dirk Opfer "); -MODULE_DESCRIPTION("Tosa Keyboard Driver"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:tosa-keyboard"); -- cgit v0.10.2 From b1d9bf1d9836dcee235f49bb4eb5ba4450a3a678 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Tue, 27 Apr 2010 15:09:33 +0800 Subject: [ARM] pxa: remove pxa_gpio_mode() and files Signed-off-by: Eric Miao diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c index 3126a35..baabb3c 100644 --- a/arch/arm/mach-pxa/generic.c +++ b/arch/arm/mach-pxa/generic.c @@ -28,7 +28,6 @@ #include #include -#include #include "generic.h" @@ -128,33 +127,3 @@ void __init pxa_map_io(void) iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc)); get_clk_frequency_khz(1); } - -/* - * Configure pins for GPIO or other functions - */ -int pxa_gpio_mode(int gpio_mode) -{ - unsigned long flags; - int gpio = gpio_mode & GPIO_MD_MASK_NR; - int fn = (gpio_mode & GPIO_MD_MASK_FN) >> 8; - int gafr; - - if (gpio > pxa_last_gpio) - return -EINVAL; - - local_irq_save(flags); - if (gpio_mode & GPIO_DFLT_LOW) - GPCR(gpio) = GPIO_bit(gpio); - else if (gpio_mode & GPIO_DFLT_HIGH) - GPSR(gpio) = GPIO_bit(gpio); - if (gpio_mode & GPIO_MD_MASK_DIR) - GPDR(gpio) |= GPIO_bit(gpio); - else - GPDR(gpio) &= ~GPIO_bit(gpio); - gafr = GAFR(gpio) & ~(0x3 << (((gpio) & 0xf)*2)); - GAFR(gpio) = gafr | (fn << (((gpio) & 0xf)*2)); - local_irq_restore(flags); - - return 0; -} -EXPORT_SYMBOL(pxa_gpio_mode); diff --git a/arch/arm/mach-pxa/include/mach/pxa2xx-gpio.h b/arch/arm/mach-pxa/include/mach/pxa2xx-gpio.h deleted file mode 100644 index 1209c44..0000000 --- a/arch/arm/mach-pxa/include/mach/pxa2xx-gpio.h +++ /dev/null @@ -1,375 +0,0 @@ -#ifndef __ASM_ARCH_PXA2XX_GPIO_H -#define __ASM_ARCH_PXA2XX_GPIO_H - -#warning Please use mfp-pxa2[57]x.h instead of pxa2xx-gpio.h - -#include - -/* GPIO alternate function assignments */ - -#define GPIO1_RST 1 /* reset */ -#define GPIO6_MMCCLK 6 /* MMC Clock */ -#define GPIO7_48MHz 7 /* 48 MHz clock output */ -#define GPIO8_MMCCS0 8 /* MMC Chip Select 0 */ -#define GPIO9_MMCCS1 9 /* MMC Chip Select 1 */ -#define GPIO10_RTCCLK 10 /* real time clock (1 Hz) */ -#define GPIO11_3_6MHz 11 /* 3.6 MHz oscillator out */ -#define GPIO12_32KHz 12 /* 32 kHz out */ -#define GPIO12_CIF_DD_7 12 /* Camera data pin 7 */ -#define GPIO13_MBGNT 13 /* memory controller grant */ -#define GPIO14_MBREQ 14 /* alternate bus master request */ -#define GPIO15_nCS_1 15 /* chip select 1 */ -#define GPIO16_PWM0 16 /* PWM0 output */ -#define GPIO17_PWM1 17 /* PWM1 output */ -#define GPIO17_CIF_DD_6 17 /* Camera data pin 6 */ -#define GPIO18_RDY 18 /* Ext. Bus Ready */ -#define GPIO19_DREQ1 19 /* External DMA Request */ -#define GPIO20_DREQ0 20 /* External DMA Request */ -#define GPIO23_SCLK 23 /* SSP clock */ -#define GPIO23_CIF_MCLK 23 /* Camera Master Clock */ -#define GPIO24_SFRM 24 /* SSP Frame */ -#define GPIO24_CIF_FV 24 /* Camera frame start signal */ -#define GPIO25_STXD 25 /* SSP transmit */ -#define GPIO25_CIF_LV 25 /* Camera line start signal */ -#define GPIO26_SRXD 26 /* SSP receive */ -#define GPIO26_CIF_PCLK 26 /* Camera Pixel Clock */ -#define GPIO27_SEXTCLK 27 /* SSP ext_clk */ -#define GPIO27_CIF_DD_0 27 /* Camera data pin 0 */ -#define GPIO28_BITCLK 28 /* AC97/I2S bit_clk */ -#define GPIO29_SDATA_IN 29 /* AC97 Sdata_in0 / I2S Sdata_in */ -#define GPIO30_SDATA_OUT 30 /* AC97/I2S Sdata_out */ -#define GPIO31_SYNC 31 /* AC97/I2S sync */ -#define GPIO32_SDATA_IN1 32 /* AC97 Sdata_in1 */ -#define GPIO32_SYSCLK 32 /* I2S System Clock */ -#define GPIO32_MMCCLK 32 /* MMC Clock (PXA270) */ -#define GPIO33_nCS_5 33 /* chip select 5 */ -#define GPIO34_FFRXD 34 /* FFUART receive */ -#define GPIO34_MMCCS0 34 /* MMC Chip Select 0 */ -#define GPIO35_FFCTS 35 /* FFUART Clear to send */ -#define GPIO36_FFDCD 36 /* FFUART Data carrier detect */ -#define GPIO37_FFDSR 37 /* FFUART data set ready */ -#define GPIO38_FFRI 38 /* FFUART Ring Indicator */ -#define GPIO39_MMCCS1 39 /* MMC Chip Select 1 */ -#define GPIO39_FFTXD 39 /* FFUART transmit data */ -#define GPIO40_FFDTR 40 /* FFUART data terminal Ready */ -#define GPIO41_FFRTS 41 /* FFUART request to send */ -#define GPIO42_BTRXD 42 /* BTUART receive data */ -#define GPIO42_HWRXD 42 /* HWUART receive data */ -#define GPIO42_CIF_MCLK 42 /* Camera Master Clock */ -#define GPIO43_BTTXD 43 /* BTUART transmit data */ -#define GPIO43_HWTXD 43 /* HWUART transmit data */ -#define GPIO43_CIF_FV 43 /* Camera frame start signal */ -#define GPIO44_BTCTS 44 /* BTUART clear to send */ -#define GPIO44_HWCTS 44 /* HWUART clear to send */ -#define GPIO44_CIF_LV 44 /* Camera line start signal */ -#define GPIO45_BTRTS 45 /* BTUART request to send */ -#define GPIO45_HWRTS 45 /* HWUART request to send */ -#define GPIO45_AC97_SYSCLK 45 /* AC97 System Clock */ -#define GPIO45_CIF_PCLK 45 /* Camera Pixel Clock */ -#define GPIO46_ICPRXD 46 /* ICP receive data */ -#define GPIO46_STRXD 46 /* STD_UART receive data */ -#define GPIO47_ICPTXD 47 /* ICP transmit data */ -#define GPIO47_STTXD 47 /* STD_UART transmit data */ -#define GPIO47_CIF_DD_0 47 /* Camera data pin 0 */ -#define GPIO48_nPOE 48 /* Output Enable for Card Space */ -#define GPIO48_CIF_DD_5 48 /* Camera data pin 5 */ -#define GPIO49_nPWE 49 /* Write Enable for Card Space */ -#define GPIO50_nPIOR 50 /* I/O Read for Card Space */ -#define GPIO50_CIF_DD_3 50 /* Camera data pin 3 */ -#define GPIO51_nPIOW 51 /* I/O Write for Card Space */ -#define GPIO51_CIF_DD_2 51 /* Camera data pin 2 */ -#define GPIO52_nPCE_1 52 /* Card Enable for Card Space */ -#define GPIO52_CIF_DD_4 52 /* Camera data pin 4 */ -#define GPIO53_nPCE_2 53 /* Card Enable for Card Space */ -#define GPIO53_MMCCLK 53 /* MMC Clock */ -#define GPIO53_CIF_MCLK 53 /* Camera Master Clock */ -#define GPIO54_MMCCLK 54 /* MMC Clock */ -#define GPIO54_pSKTSEL 54 /* Socket Select for Card Space */ -#define GPIO54_nPCE_2 54 /* Card Enable for Card Space (PXA27x) */ -#define GPIO54_CIF_PCLK 54 /* Camera Pixel Clock */ -#define GPIO55_nPREG 55 /* Card Address bit 26 */ -#define GPIO55_CIF_DD_1 55 /* Camera data pin 1 */ -#define GPIO56_nPWAIT 56 /* Wait signal for Card Space */ -#define GPIO57_nIOIS16 57 /* Bus Width select for I/O Card Space */ -#define GPIO58_LDD_0 58 /* LCD data pin 0 */ -#define GPIO59_LDD_1 59 /* LCD data pin 1 */ -#define GPIO60_LDD_2 60 /* LCD data pin 2 */ -#define GPIO61_LDD_3 61 /* LCD data pin 3 */ -#define GPIO62_LDD_4 62 /* LCD data pin 4 */ -#define GPIO63_LDD_5 63 /* LCD data pin 5 */ -#define GPIO64_LDD_6 64 /* LCD data pin 6 */ -#define GPIO65_LDD_7 65 /* LCD data pin 7 */ -#define GPIO66_LDD_8 66 /* LCD data pin 8 */ -#define GPIO66_MBREQ 66 /* alternate bus master req */ -#define GPIO67_LDD_9 67 /* LCD data pin 9 */ -#define GPIO67_MMCCS0 67 /* MMC Chip Select 0 */ -#define GPIO68_LDD_10 68 /* LCD data pin 10 */ -#define GPIO68_MMCCS1 68 /* MMC Chip Select 1 */ -#define GPIO69_LDD_11 69 /* LCD data pin 11 */ -#define GPIO69_MMCCLK 69 /* MMC_CLK */ -#define GPIO70_LDD_12 70 /* LCD data pin 12 */ -#define GPIO70_RTCCLK 70 /* Real Time clock (1 Hz) */ -#define GPIO71_LDD_13 71 /* LCD data pin 13 */ -#define GPIO71_3_6MHz 71 /* 3.6 MHz Oscillator clock */ -#define GPIO72_LDD_14 72 /* LCD data pin 14 */ -#define GPIO72_32kHz 72 /* 32 kHz clock */ -#define GPIO73_LDD_15 73 /* LCD data pin 15 */ -#define GPIO73_MBGNT 73 /* Memory controller grant */ -#define GPIO74_LCD_FCLK 74 /* LCD Frame clock */ -#define GPIO75_LCD_LCLK 75 /* LCD line clock */ -#define GPIO76_LCD_PCLK 76 /* LCD Pixel clock */ -#define GPIO77_LCD_ACBIAS 77 /* LCD AC Bias */ -#define GPIO78_nCS_2 78 /* chip select 2 */ -#define GPIO79_nCS_3 79 /* chip select 3 */ -#define GPIO80_nCS_4 80 /* chip select 4 */ -#define GPIO81_NSCLK 81 /* NSSP clock */ -#define GPIO81_CIF_DD_0 81 /* Camera data pin 0 */ -#define GPIO82_NSFRM 82 /* NSSP Frame */ -#define GPIO82_CIF_DD_5 82 /* Camera data pin 5 */ -#define GPIO83_NSTXD 83 /* NSSP transmit */ -#define GPIO83_CIF_DD_4 83 /* Camera data pin 4 */ -#define GPIO84_NSRXD 84 /* NSSP receive */ -#define GPIO84_CIF_FV 84 /* Camera frame start signal */ -#define GPIO85_nPCE_1 85 /* Card Enable for Card Space (PXA27x) */ -#define GPIO85_CIF_LV 85 /* Camera line start signal */ -#define GPIO90_CIF_DD_4 90 /* Camera data pin 4 */ -#define GPIO91_CIF_DD_5 91 /* Camera data pin 5 */ -#define GPIO92_MMCDAT0 92 /* MMC DAT0 (PXA27x) */ -#define GPIO93_CIF_DD_6 93 /* Camera data pin 6 */ -#define GPIO94_CIF_DD_5 94 /* Camera data pin 5 */ -#define GPIO95_CIF_DD_4 95 /* Camera data pin 4 */ -#define GPIO96_FFRXD 96 /* FFUART recieve */ -#define GPIO98_FFRTS 98 /* FFUART request to send */ -#define GPIO98_CIF_DD_0 98 /* Camera data pin 0 */ -#define GPIO99_FFTXD 99 /* FFUART transmit data */ -#define GPIO100_FFCTS 100 /* FFUART Clear to send */ -#define GPIO102_nPCE_1 102 /* PCMCIA (PXA27x) */ -#define GPIO103_CIF_DD_3 103 /* Camera data pin 3 */ -#define GPIO104_CIF_DD_2 104 /* Camera data pin 2 */ -#define GPIO105_CIF_DD_1 105 /* Camera data pin 1 */ -#define GPIO106_CIF_DD_9 106 /* Camera data pin 9 */ -#define GPIO107_CIF_DD_8 107 /* Camera data pin 8 */ -#define GPIO108_CIF_DD_7 108 /* Camera data pin 7 */ -#define GPIO109_MMCDAT1 109 /* MMC DAT1 (PXA27x) */ -#define GPIO110_MMCDAT2 110 /* MMC DAT2 (PXA27x) */ -#define GPIO110_MMCCS0 110 /* MMC Chip Select 0 (PXA27x) */ -#define GPIO111_MMCDAT3 111 /* MMC DAT3 (PXA27x) */ -#define GPIO111_MMCCS1 111 /* MMC Chip Select 1 (PXA27x) */ -#define GPIO112_MMCCMD 112 /* MMC CMD (PXA27x) */ -#define GPIO113_I2S_SYSCLK 113 /* I2S System Clock (PXA27x) */ -#define GPIO113_AC97_RESET_N 113 /* AC97 NRESET on (PXA27x) */ -#define GPIO114_CIF_DD_1 114 /* Camera data pin 1 */ -#define GPIO115_CIF_DD_3 115 /* Camera data pin 3 */ -#define GPIO116_CIF_DD_2 116 /* Camera data pin 2 */ - -/* GPIO alternate function mode & direction */ - -#define GPIO_IN 0x000 -#define GPIO_OUT 0x080 -#define GPIO_ALT_FN_1_IN 0x100 -#define GPIO_ALT_FN_1_OUT 0x180 -#define GPIO_ALT_FN_2_IN 0x200 -#define GPIO_ALT_FN_2_OUT 0x280 -#define GPIO_ALT_FN_3_IN 0x300 -#define GPIO_ALT_FN_3_OUT 0x380 -#define GPIO_MD_MASK_NR 0x07f -#define GPIO_MD_MASK_DIR 0x080 -#define GPIO_MD_MASK_FN 0x300 -#define GPIO_DFLT_LOW 0x400 -#define GPIO_DFLT_HIGH 0x800 - -#define GPIO1_RTS_MD ( 1 | GPIO_ALT_FN_1_IN) -#define GPIO6_MMCCLK_MD ( 6 | GPIO_ALT_FN_1_OUT) -#define GPIO7_48MHz_MD ( 7 | GPIO_ALT_FN_1_OUT) -#define GPIO8_MMCCS0_MD ( 8 | GPIO_ALT_FN_1_OUT) -#define GPIO9_MMCCS1_MD ( 9 | GPIO_ALT_FN_1_OUT) -#define GPIO10_RTCCLK_MD (10 | GPIO_ALT_FN_1_OUT) -#define GPIO11_3_6MHz_MD (11 | GPIO_ALT_FN_1_OUT) -#define GPIO12_32KHz_MD (12 | GPIO_ALT_FN_1_OUT) -#define GPIO12_CIF_DD_7_MD (12 | GPIO_ALT_FN_2_IN) -#define GPIO13_MBGNT_MD (13 | GPIO_ALT_FN_2_OUT) -#define GPIO14_MBREQ_MD (14 | GPIO_ALT_FN_1_IN) -#define GPIO15_nCS_1_MD (15 | GPIO_ALT_FN_2_OUT) -#define GPIO16_PWM0_MD (16 | GPIO_ALT_FN_2_OUT) -#define GPIO17_PWM1_MD (17 | GPIO_ALT_FN_2_OUT) -#define GPIO17_CIF_DD_6_MD (17 | GPIO_ALT_FN_2_IN) -#define GPIO18_RDY_MD (18 | GPIO_ALT_FN_1_IN) -#define GPIO19_DREQ1_MD (19 | GPIO_ALT_FN_1_IN) -#define GPIO20_DREQ0_MD (20 | GPIO_ALT_FN_1_IN) -#define GPIO23_CIF_MCLK_MD (23 | GPIO_ALT_FN_1_OUT) -#define GPIO23_SCLK_MD (23 | GPIO_ALT_FN_2_OUT) -#define GPIO24_CIF_FV_MD (24 | GPIO_ALT_FN_1_OUT) -#define GPIO24_SFRM_MD (24 | GPIO_ALT_FN_2_OUT) -#define GPIO25_CIF_LV_MD (25 | GPIO_ALT_FN_1_OUT) -#define GPIO25_STXD_MD (25 | GPIO_ALT_FN_2_OUT) -#define GPIO26_SRXD_MD (26 | GPIO_ALT_FN_1_IN) -#define GPIO26_CIF_PCLK_MD (26 | GPIO_ALT_FN_2_IN) -#define GPIO27_SEXTCLK_MD (27 | GPIO_ALT_FN_1_IN) -#define GPIO27_CIF_DD_0_MD (27 | GPIO_ALT_FN_3_IN) -#define GPIO28_BITCLK_AC97_MD (28 | GPIO_ALT_FN_1_IN) -#define GPIO28_BITCLK_IN_I2S_MD (28 | GPIO_ALT_FN_2_IN) -#define GPIO28_BITCLK_OUT_I2S_MD (28 | GPIO_ALT_FN_1_OUT) -#define GPIO29_SDATA_IN_AC97_MD (29 | GPIO_ALT_FN_1_IN) -#define GPIO29_SDATA_IN_I2S_MD (29 | GPIO_ALT_FN_2_IN) -#define GPIO30_SDATA_OUT_AC97_MD (30 | GPIO_ALT_FN_2_OUT) -#define GPIO30_SDATA_OUT_I2S_MD (30 | GPIO_ALT_FN_1_OUT) -#define GPIO31_SYNC_I2S_MD (31 | GPIO_ALT_FN_1_OUT) -#define GPIO31_SYNC_AC97_MD (31 | GPIO_ALT_FN_2_OUT) -#define GPIO32_SDATA_IN1_AC97_MD (32 | GPIO_ALT_FN_1_IN) -#define GPIO32_SYSCLK_I2S_MD (32 | GPIO_ALT_FN_1_OUT) -#define GPIO32_MMCCLK_MD (32 | GPIO_ALT_FN_2_OUT) -#define GPIO33_nCS_5_MD (33 | GPIO_ALT_FN_2_OUT) -#define GPIO34_FFRXD_MD (34 | GPIO_ALT_FN_1_IN) -#define GPIO34_MMCCS0_MD (34 | GPIO_ALT_FN_2_OUT) -#define GPIO35_FFCTS_MD (35 | GPIO_ALT_FN_1_IN) -#define GPIO35_KP_MKOUT6_MD (35 | GPIO_ALT_FN_2_OUT) -#define GPIO36_FFDCD_MD (36 | GPIO_ALT_FN_1_IN) -#define GPIO37_FFDSR_MD (37 | GPIO_ALT_FN_1_IN) -#define GPIO38_FFRI_MD (38 | GPIO_ALT_FN_1_IN) -#define GPIO39_MMCCS1_MD (39 | GPIO_ALT_FN_1_OUT) -#define GPIO39_FFTXD_MD (39 | GPIO_ALT_FN_2_OUT) -#define GPIO40_FFDTR_MD (40 | GPIO_ALT_FN_2_OUT) -#define GPIO41_FFRTS_MD (41 | GPIO_ALT_FN_2_OUT) -#define GPIO41_KP_MKOUT7_MD (41 | GPIO_ALT_FN_1_OUT) -#define GPIO42_BTRXD_MD (42 | GPIO_ALT_FN_1_IN) -#define GPIO42_HWRXD_MD (42 | GPIO_ALT_FN_3_IN) -#define GPIO42_CIF_MCLK_MD (42 | GPIO_ALT_FN_3_OUT) -#define GPIO43_BTTXD_MD (43 | GPIO_ALT_FN_2_OUT) -#define GPIO43_HWTXD_MD (43 | GPIO_ALT_FN_3_OUT) -#define GPIO43_CIF_FV_MD (43 | GPIO_ALT_FN_3_OUT) -#define GPIO44_BTCTS_MD (44 | GPIO_ALT_FN_1_IN) -#define GPIO44_HWCTS_MD (44 | GPIO_ALT_FN_3_IN) -#define GPIO44_CIF_LV_MD (44 | GPIO_ALT_FN_3_OUT) -#define GPIO45_CIF_PCLK_MD (45 | GPIO_ALT_FN_3_IN) -#define GPIO45_BTRTS_MD (45 | GPIO_ALT_FN_2_OUT) -#define GPIO45_HWRTS_MD (45 | GPIO_ALT_FN_3_OUT) -#define GPIO45_SYSCLK_AC97_MD (45 | GPIO_ALT_FN_1_OUT) -#define GPIO46_ICPRXD_MD (46 | GPIO_ALT_FN_1_IN) -#define GPIO46_STRXD_MD (46 | GPIO_ALT_FN_2_IN) -#define GPIO47_CIF_DD_0_MD (47 | GPIO_ALT_FN_1_IN) -#define GPIO47_ICPTXD_MD (47 | GPIO_ALT_FN_2_OUT) -#define GPIO47_STTXD_MD (47 | GPIO_ALT_FN_1_OUT) -#define GPIO48_CIF_DD_5_MD (48 | GPIO_ALT_FN_1_IN) -#define GPIO48_nPOE_MD (48 | GPIO_ALT_FN_2_OUT) -#define GPIO48_HWTXD_MD (48 | GPIO_ALT_FN_1_OUT) -#define GPIO48_nPOE_MD (48 | GPIO_ALT_FN_2_OUT) -#define GPIO49_HWRXD_MD (49 | GPIO_ALT_FN_1_IN) -#define GPIO49_nPWE_MD (49 | GPIO_ALT_FN_2_OUT) -#define GPIO50_CIF_DD_3_MD (50 | GPIO_ALT_FN_1_IN) -#define GPIO50_nPIOR_MD (50 | GPIO_ALT_FN_2_OUT) -#define GPIO50_HWCTS_MD (50 | GPIO_ALT_FN_1_IN) -#define GPIO50_CIF_DD_3_MD (50 | GPIO_ALT_FN_1_IN) -#define GPIO51_CIF_DD_2_MD (51 | GPIO_ALT_FN_1_IN) -#define GPIO51_nPIOW_MD (51 | GPIO_ALT_FN_2_OUT) -#define GPIO51_HWRTS_MD (51 | GPIO_ALT_FN_1_OUT) -#define GPIO51_CIF_DD_2_MD (51 | GPIO_ALT_FN_1_IN) -#define GPIO52_nPCE_1_MD (52 | GPIO_ALT_FN_2_OUT) -#define GPIO52_CIF_DD_4_MD (52 | GPIO_ALT_FN_1_IN) -#define GPIO53_nPCE_2_MD (53 | GPIO_ALT_FN_2_OUT) -#define GPIO53_MMCCLK_MD (53 | GPIO_ALT_FN_1_OUT) -#define GPIO53_CIF_MCLK_MD (53 | GPIO_ALT_FN_2_OUT) -#define GPIO54_MMCCLK_MD (54 | GPIO_ALT_FN_1_OUT) -#define GPIO54_nPCE_2_MD (54 | GPIO_ALT_FN_2_OUT) -#define GPIO54_pSKTSEL_MD (54 | GPIO_ALT_FN_2_OUT) -#define GPIO54_CIF_PCLK_MD (54 | GPIO_ALT_FN_3_IN) -#define GPIO55_nPREG_MD (55 | GPIO_ALT_FN_2_OUT) -#define GPIO55_CIF_DD_1_MD (55 | GPIO_ALT_FN_1_IN) -#define GPIO56_nPWAIT_MD (56 | GPIO_ALT_FN_1_IN) -#define GPIO57_nIOIS16_MD (57 | GPIO_ALT_FN_1_IN) -#define GPIO58_LDD_0_MD (58 | GPIO_ALT_FN_2_OUT) -#define GPIO59_LDD_1_MD (59 | GPIO_ALT_FN_2_OUT) -#define GPIO60_LDD_2_MD (60 | GPIO_ALT_FN_2_OUT) -#define GPIO61_LDD_3_MD (61 | GPIO_ALT_FN_2_OUT) -#define GPIO62_LDD_4_MD (62 | GPIO_ALT_FN_2_OUT) -#define GPIO63_LDD_5_MD (63 | GPIO_ALT_FN_2_OUT) -#define GPIO64_LDD_6_MD (64 | GPIO_ALT_FN_2_OUT) -#define GPIO65_LDD_7_MD (65 | GPIO_ALT_FN_2_OUT) -#define GPIO66_LDD_8_MD (66 | GPIO_ALT_FN_2_OUT) -#define GPIO66_MBREQ_MD (66 | GPIO_ALT_FN_1_IN) -#define GPIO67_LDD_9_MD (67 | GPIO_ALT_FN_2_OUT) -#define GPIO67_MMCCS0_MD (67 | GPIO_ALT_FN_1_OUT) -#define GPIO68_LDD_10_MD (68 | GPIO_ALT_FN_2_OUT) -#define GPIO68_MMCCS1_MD (68 | GPIO_ALT_FN_1_OUT) -#define GPIO69_LDD_11_MD (69 | GPIO_ALT_FN_2_OUT) -#define GPIO69_MMCCLK_MD (69 | GPIO_ALT_FN_1_OUT) -#define GPIO70_LDD_12_MD (70 | GPIO_ALT_FN_2_OUT) -#define GPIO70_RTCCLK_MD (70 | GPIO_ALT_FN_1_OUT) -#define GPIO71_LDD_13_MD (71 | GPIO_ALT_FN_2_OUT) -#define GPIO71_3_6MHz_MD (71 | GPIO_ALT_FN_1_OUT) -#define GPIO72_LDD_14_MD (72 | GPIO_ALT_FN_2_OUT) -#define GPIO72_32kHz_MD (72 | GPIO_ALT_FN_1_OUT) -#define GPIO73_LDD_15_MD (73 | GPIO_ALT_FN_2_OUT) -#define GPIO73_MBGNT_MD (73 | GPIO_ALT_FN_1_OUT) -#define GPIO74_LCD_FCLK_MD (74 | GPIO_ALT_FN_2_OUT) -#define GPIO75_LCD_LCLK_MD (75 | GPIO_ALT_FN_2_OUT) -#define GPIO76_LCD_PCLK_MD (76 | GPIO_ALT_FN_2_OUT) -#define GPIO77_LCD_ACBIAS_MD (77 | GPIO_ALT_FN_2_OUT) -#define GPIO78_nCS_2_MD (78 | GPIO_ALT_FN_2_OUT) -#define GPIO78_nPCE_2_MD (78 | GPIO_ALT_FN_1_OUT) -#define GPIO79_nCS_3_MD (79 | GPIO_ALT_FN_2_OUT) -#define GPIO79_pSKTSEL_MD (79 | GPIO_ALT_FN_1_OUT) -#define GPIO80_nCS_4_MD (80 | GPIO_ALT_FN_2_OUT) -#define GPIO81_NSSP_CLK_OUT (81 | GPIO_ALT_FN_1_OUT) -#define GPIO81_NSSP_CLK_IN (81 | GPIO_ALT_FN_1_IN) -#define GPIO81_CIF_DD_0_MD (81 | GPIO_ALT_FN_2_IN) -#define GPIO82_NSSP_FRM_OUT (82 | GPIO_ALT_FN_1_OUT) -#define GPIO82_NSSP_FRM_IN (82 | GPIO_ALT_FN_1_IN) -#define GPIO82_CIF_DD_5_MD (82 | GPIO_ALT_FN_3_IN) -#define GPIO83_NSSP_TX (83 | GPIO_ALT_FN_1_OUT) -#define GPIO83_NSSP_RX (83 | GPIO_ALT_FN_2_IN) -#define GPIO83_CIF_DD_4_MD (83 | GPIO_ALT_FN_3_IN) -#define GPIO84_NSSP_TX (84 | GPIO_ALT_FN_1_OUT) -#define GPIO84_NSSP_RX (84 | GPIO_ALT_FN_2_IN) -#define GPIO84_CIF_FV_MD (84 | GPIO_ALT_FN_3_IN) -#define GPIO85_nPCE_1_MD (85 | GPIO_ALT_FN_1_OUT) -#define GPIO85_CIF_LV_MD (85 | GPIO_ALT_FN_3_IN) -#define GPIO86_nPCE_1_MD (86 | GPIO_ALT_FN_1_OUT) -#define GPIO88_USBH1_PWR_MD (88 | GPIO_ALT_FN_1_IN) -#define GPIO89_USBH1_PEN_MD (89 | GPIO_ALT_FN_2_OUT) -#define GPIO90_CIF_DD_4_MD (90 | GPIO_ALT_FN_3_IN) -#define GPIO91_CIF_DD_5_MD (91 | GPIO_ALT_FN_3_IN) -#define GPIO92_MMCDAT0_MD (92 | GPIO_ALT_FN_1_OUT) -#define GPIO93_CIF_DD_6_MD (93 | GPIO_ALT_FN_2_IN) -#define GPIO94_CIF_DD_5_MD (94 | GPIO_ALT_FN_2_IN) -#define GPIO95_CIF_DD_4_MD (95 | GPIO_ALT_FN_2_IN) -#define GPIO95_KP_MKIN6_MD (95 | GPIO_ALT_FN_3_IN) -#define GPIO96_KP_DKIN3_MD (96 | GPIO_ALT_FN_1_IN) -#define GPIO96_FFRXD_MD (96 | GPIO_ALT_FN_3_IN) -#define GPIO97_KP_MKIN3_MD (97 | GPIO_ALT_FN_3_IN) -#define GPIO98_CIF_DD_0_MD (98 | GPIO_ALT_FN_2_IN) -#define GPIO98_FFRTS_MD (98 | GPIO_ALT_FN_3_OUT) -#define GPIO99_FFTXD_MD (99 | GPIO_ALT_FN_3_OUT) -#define GPIO100_KP_MKIN0_MD (100 | GPIO_ALT_FN_1_IN) -#define GPIO101_KP_MKIN1_MD (101 | GPIO_ALT_FN_1_IN) -#define GPIO102_nPCE_1_MD (102 | GPIO_ALT_FN_1_OUT) -#define GPIO102_KP_MKIN2_MD (102 | GPIO_ALT_FN_1_IN) -#define GPIO103_CIF_DD_3_MD (103 | GPIO_ALT_FN_1_IN) -#define GPIO103_KP_MKOUT0_MD (103 | GPIO_ALT_FN_2_OUT) -#define GPIO104_CIF_DD_2_MD (104 | GPIO_ALT_FN_1_IN) -#define GPIO104_pSKTSEL_MD (104 | GPIO_ALT_FN_1_OUT) -#define GPIO104_KP_MKOUT1_MD (104 | GPIO_ALT_FN_2_OUT) -#define GPIO105_CIF_DD_1_MD (105 | GPIO_ALT_FN_1_IN) -#define GPIO105_KP_MKOUT2_MD (105 | GPIO_ALT_FN_2_OUT) -#define GPIO106_CIF_DD_9_MD (106 | GPIO_ALT_FN_1_IN) -#define GPIO106_KP_MKOUT3_MD (106 | GPIO_ALT_FN_2_OUT) -#define GPIO107_CIF_DD_8_MD (107 | GPIO_ALT_FN_1_IN) -#define GPIO107_KP_MKOUT4_MD (107 | GPIO_ALT_FN_2_OUT) -#define GPIO108_CIF_DD_7_MD (108 | GPIO_ALT_FN_1_IN) -#define GPIO108_KP_MKOUT5_MD (108 | GPIO_ALT_FN_2_OUT) -#define GPIO109_MMCDAT1_MD (109 | GPIO_ALT_FN_1_OUT) -#define GPIO110_MMCDAT2_MD (110 | GPIO_ALT_FN_1_OUT) -#define GPIO110_MMCCS0_MD (110 | GPIO_ALT_FN_1_OUT) -#define GPIO111_MMCDAT3_MD (111 | GPIO_ALT_FN_1_OUT) -#define GPIO110_MMCCS1_MD (111 | GPIO_ALT_FN_1_OUT) -#define GPIO112_MMCCMD_MD (112 | GPIO_ALT_FN_1_OUT) -#define GPIO113_I2S_SYSCLK_MD (113 | GPIO_ALT_FN_1_OUT) -#define GPIO113_AC97_RESET_N_MD (113 | GPIO_ALT_FN_2_OUT) -#define GPIO117_I2CSCL_MD (117 | GPIO_ALT_FN_1_IN) -#define GPIO118_I2CSDA_MD (118 | GPIO_ALT_FN_1_IN) - -/* - * Handy routine to set GPIO alternate functions - */ -extern int pxa_gpio_mode( int gpio_mode ); - -#endif /* __ASM_ARCH_PXA2XX_GPIO_H */ diff --git a/arch/arm/mach-pxa/sharpsl_pm.c b/arch/arm/mach-pxa/sharpsl_pm.c index 463d874..cb47672 100644 --- a/arch/arm/mach-pxa/sharpsl_pm.c +++ b/arch/arm/mach-pxa/sharpsl_pm.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include -- cgit v0.10.2 From 03ba7e07f5025710470b12e18e2b9b2979d836db Mon Sep 17 00:00:00 2001 From: Igor Grinberg Date: Tue, 9 Mar 2010 11:43:48 +0200 Subject: [ARM] pxa/cm-x300.c: add battery charger support Signed-off-by: Igor Grinberg Signed-off-by: Eric Miao diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c index d37cfa1..0e538d8 100644 --- a/arch/arm/mach-pxa/cm-x300.c +++ b/arch/arm/mach-pxa/cm-x300.c @@ -30,6 +30,8 @@ #include #include +#include +#include #include #include @@ -584,12 +586,65 @@ static void __init cm_x300_init_rtc(void) static inline void cm_x300_init_rtc(void) {} #endif +/* Battery */ +struct power_supply_info cm_x300_psy_info = { + .name = "battery", + .technology = POWER_SUPPLY_TECHNOLOGY_LIPO, + .voltage_max_design = 4200000, + .voltage_min_design = 3000000, + .use_for_apm = 1, +}; + +static void cm_x300_battery_low(void) +{ +#if defined(CONFIG_APM_EMULATION) + apm_queue_event(APM_LOW_BATTERY); +#endif +} + +static void cm_x300_battery_critical(void) +{ +#if defined(CONFIG_APM_EMULATION) + apm_queue_event(APM_CRITICAL_SUSPEND); +#endif +} + +struct da9030_battery_info cm_x300_battery_info = { + .battery_info = &cm_x300_psy_info, + + .charge_milliamp = 1000, + .charge_millivolt = 4200, + + .vbat_low = 3600, + .vbat_crit = 3400, + .vbat_charge_start = 4100, + .vbat_charge_stop = 4200, + .vbat_charge_restart = 4000, + + .vcharge_min = 3200, + .vcharge_max = 5500, + + .tbat_low = 197, + .tbat_high = 78, + .tbat_restart = 100, + + .batmon_interval = 0, + + .battery_low = cm_x300_battery_low, + .battery_critical = cm_x300_battery_critical, +}; + /* DA9030 */ struct da903x_subdev_info cm_x300_da9030_subdevs[] = { { .name = "da903x-backlight", .id = DA9030_ID_WLED, - } + }, + { + .name = "da903x-battery", + .id = DA9030_ID_BAT, + .platform_data = &cm_x300_battery_info, + }, }; static struct da903x_platform_data cm_x300_da9030_info = { -- cgit v0.10.2 From d768c67c0cc70c7817585676a40e0d2a9094bdbe Mon Sep 17 00:00:00 2001 From: Igor Grinberg Date: Tue, 9 Mar 2010 11:43:49 +0200 Subject: [ARM] pxa/cm-x300: da903x WLED is not connected on cm-x300 Signed-off-by: Igor Grinberg Signed-off-by: Eric Miao diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c index 0e538d8..13fdfd8 100644 --- a/arch/arm/mach-pxa/cm-x300.c +++ b/arch/arm/mach-pxa/cm-x300.c @@ -637,10 +637,6 @@ struct da9030_battery_info cm_x300_battery_info = { /* DA9030 */ struct da903x_subdev_info cm_x300_da9030_subdevs[] = { { - .name = "da903x-backlight", - .id = DA9030_ID_WLED, - }, - { .name = "da903x-battery", .id = DA9030_ID_BAT, .platform_data = &cm_x300_battery_info, -- cgit v0.10.2 From e4e309708eeb87a5b2429bc1f9bd1bc469d5a8b0 Mon Sep 17 00:00:00 2001 From: Igor Grinberg Date: Tue, 9 Mar 2010 11:43:50 +0200 Subject: [ARM] pxa/cm-x300: fix da903x IRQ line assignment Signed-off-by: Igor Grinberg Signed-off-by: Eric Miao diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c index 13fdfd8..6fba9a0 100644 --- a/arch/arm/mach-pxa/cm-x300.c +++ b/arch/arm/mach-pxa/cm-x300.c @@ -650,7 +650,7 @@ static struct da903x_platform_data cm_x300_da9030_info = { static struct i2c_board_info cm_x300_pmic_info = { I2C_BOARD_INFO("da9030", 0x49), - .irq = IRQ_GPIO(0), + .irq = IRQ_WAKEUP0, .platform_data = &cm_x300_da9030_info, }; -- cgit v0.10.2 From d176d64b54c72ee00f825dddd63830f8bd2b5155 Mon Sep 17 00:00:00 2001 From: Igor Grinberg Date: Tue, 9 Mar 2010 11:43:51 +0200 Subject: [ARM] pxa/cm-x300: add regulator on vcc_core Signed-off-by: Igor Grinberg Signed-off-by: Eric Miao diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c index 6fba9a0..2012588 100644 --- a/arch/arm/mach-pxa/cm-x300.c +++ b/arch/arm/mach-pxa/cm-x300.c @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -634,6 +635,27 @@ struct da9030_battery_info cm_x300_battery_info = { .battery_critical = cm_x300_battery_critical, }; +static struct regulator_consumer_supply buck2_consumers[] = { + { + .dev = NULL, + .supply = "vcc_core", + }, +}; + +static struct regulator_init_data buck2_data = { + .constraints = { + .min_uV = 1375000, + .max_uV = 1375000, + .state_mem = { + .enabled = 0, + }, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + .apply_uV = 1, + }, + .num_consumer_supplies = ARRAY_SIZE(buck2_consumers), + .consumer_supplies = buck2_consumers, +}; + /* DA9030 */ struct da903x_subdev_info cm_x300_da9030_subdevs[] = { { @@ -641,6 +663,11 @@ struct da903x_subdev_info cm_x300_da9030_subdevs[] = { .id = DA9030_ID_BAT, .platform_data = &cm_x300_battery_info, }, + { + .name = "da903x-regulator", + .id = DA9030_ID_BUCK2, + .platform_data = &buck2_data, + }, }; static struct da903x_platform_data cm_x300_da9030_info = { -- cgit v0.10.2 From 818809752303b5b792dde4ace6321e8ccc180f65 Mon Sep 17 00:00:00 2001 From: Igor Grinberg Date: Tue, 9 Mar 2010 11:43:52 +0200 Subject: [ARM] pxa/cm-x300: update the memory fixup. CM-X300 bootloader passes DRAM configuration information in ATAGS, however, the first memory bank is reported at actual physical address 0x8000000. Use the configuration information supplied by the bootloader and cope with the necessity to have PHYS_ADDR=0xa0000000. Signed-off-by: Igor Grinberg Signed-off-by: Mike Rapoport Signed-off-by: Eric Miao diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c index 2012588..be9dc7a 100644 --- a/arch/arm/mach-pxa/cm-x300.c +++ b/arch/arm/mach-pxa/cm-x300.c @@ -767,13 +767,13 @@ static void __init cm_x300_init(void) static void __init cm_x300_fixup(struct machine_desc *mdesc, struct tag *tags, char **cmdline, struct meminfo *mi) { - mi->nr_banks = 2; - mi->bank[0].start = 0xa0000000; - mi->bank[0].node = 0; - mi->bank[0].size = (64*1024*1024); - mi->bank[1].start = 0xc0000000; - mi->bank[1].node = 0; - mi->bank[1].size = (64*1024*1024); + /* Make sure that mi->bank[0].start = PHYS_ADDR */ + for (; tags->hdr.size; tags = tag_next(tags)) + if (tags->hdr.tag == ATAG_MEM && + tags->u.mem.start == 0x80000000) { + tags->u.mem.start = 0xa0000000; + break; + } } MACHINE_START(CM_X300, "CM-X300 module") -- cgit v0.10.2 From b637799248520d711f0fdc64666131c1c869cfbc Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 28 Feb 2010 12:41:23 +0100 Subject: [ARM] pxa: add basic support for the Aeronix Zipit Z2 handheld This patch adds support for the Zipit Z2. The parts missing from this patch are the battery support, SPI driver for the LCD and support for the Silicon Serial ID chip. Signed-off-by: Marek Vasut Signed-off-by: Eric Miao diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index 454cd5d..2e4122d 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -561,6 +561,12 @@ config MACH_E800 Say Y here if you intend to run this kernel on a Toshiba e800 family PDA. +config MACH_ZIPIT2 + bool "Zipit Z2 Handheld" + select PXA27x + select HAVE_PWM + select PXA_HAVE_BOARD_IRQS + endmenu config PXA25x diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index cf57fb2..e929231 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -92,6 +92,7 @@ obj-$(CONFIG_MACH_E800) += e800.o obj-$(CONFIG_MACH_RAUMFELD_RC) += raumfeld.o obj-$(CONFIG_MACH_RAUMFELD_CONNECTOR) += raumfeld.o obj-$(CONFIG_MACH_RAUMFELD_SPEAKER) += raumfeld.o +obj-$(CONFIG_MACH_ZIPIT2) += z2.o # Support for blinky lights led-y := leds.o diff --git a/arch/arm/mach-pxa/include/mach/z2.h b/arch/arm/mach-pxa/include/mach/z2.h new file mode 100644 index 0000000..8835c16 --- /dev/null +++ b/arch/arm/mach-pxa/include/mach/z2.h @@ -0,0 +1,41 @@ +/* + * arch/arm/mach-pxa/include/mach/z2.h + * + * Author: Ken McGuire + * Created: Feb 6, 2009 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef ASM_ARCH_ZIPIT2_H +#define ASM_ARCH_ZIPIT2_H + +/* LEDs */ +#define GPIO10_ZIPITZ2_LED_WIFI 10 +#define GPIO85_ZIPITZ2_LED_CHARGED 85 +#define GPIO83_ZIPITZ2_LED_CHARGING 83 + +/* SD/MMC */ +#define GPIO96_ZIPITZ2_SD_DETECT 96 + +/* GPIO Buttons */ +#define GPIO1_ZIPITZ2_POWER_BUTTON 1 +#define GPIO98_ZIPITZ2_LID_BUTTON 98 + +/* Libertas GSPI8686 WiFi */ +#define GPIO14_ZIPITZ2_WIFI_RESET 14 +#define GPIO15_ZIPITZ2_WIFI_POWER 15 +#define GPIO24_ZIPITZ2_WIFI_CS 24 +#define GPIO36_ZIPITZ2_WIFI_IRQ 36 + +/* LCD */ +#define GPIO19_ZIPITZ2_LCD_RESET 19 +#define GPIO88_ZIPITZ2_LCD_CS 88 + +/* MISC GPIOs */ +#define GPIO0_ZIPITZ2_AC_DETECT 0 +#define GPIO37_ZIPITZ2_HEADSET_DETECT 37 + +#endif diff --git a/arch/arm/mach-pxa/z2.c b/arch/arm/mach-pxa/z2.c new file mode 100644 index 0000000..c837318 --- /dev/null +++ b/arch/arm/mach-pxa/z2.c @@ -0,0 +1,609 @@ +/* + * linux/arch/arm/mach-pxa/z2.c + * + * Support for the Zipit Z2 Handheld device. + * + * Author: Ken McGuire + * Created: Jan 25, 2009 + * Based on mainstone.c as modified for the Zipit Z2. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "generic.h" +#include "devices.h" + +/****************************************************************************** + * Pin configuration + ******************************************************************************/ +static unsigned long z2_pin_config[] = { + + /* LCD - 16bpp Active TFT */ + GPIO58_LCD_LDD_0, + GPIO59_LCD_LDD_1, + GPIO60_LCD_LDD_2, + GPIO61_LCD_LDD_3, + GPIO62_LCD_LDD_4, + GPIO63_LCD_LDD_5, + GPIO64_LCD_LDD_6, + GPIO65_LCD_LDD_7, + GPIO66_LCD_LDD_8, + GPIO67_LCD_LDD_9, + GPIO68_LCD_LDD_10, + GPIO69_LCD_LDD_11, + GPIO70_LCD_LDD_12, + GPIO71_LCD_LDD_13, + GPIO72_LCD_LDD_14, + GPIO73_LCD_LDD_15, + GPIO74_LCD_FCLK, + GPIO75_LCD_LCLK, + GPIO76_LCD_PCLK, + GPIO77_LCD_BIAS, + GPIO19_GPIO, /* LCD reset */ + GPIO88_GPIO, /* LCD chipselect */ + + /* PWM */ + GPIO115_PWM1_OUT, /* Keypad Backlight */ + GPIO11_PWM2_OUT, /* LCD Backlight */ + + /* MMC */ + GPIO32_MMC_CLK, + GPIO112_MMC_CMD, + GPIO92_MMC_DAT_0, + GPIO109_MMC_DAT_1, + GPIO110_MMC_DAT_2, + GPIO111_MMC_DAT_3, + GPIO96_GPIO, /* SD detect */ + + /* STUART */ + GPIO46_STUART_RXD, + GPIO47_STUART_TXD, + + /* Keypad */ + GPIO100_KP_MKIN_0 | WAKEUP_ON_LEVEL_HIGH, + GPIO101_KP_MKIN_1 | WAKEUP_ON_LEVEL_HIGH, + GPIO102_KP_MKIN_2 | WAKEUP_ON_LEVEL_HIGH, + GPIO34_KP_MKIN_3 | WAKEUP_ON_LEVEL_HIGH, + GPIO38_KP_MKIN_4 | WAKEUP_ON_LEVEL_HIGH, + GPIO16_KP_MKIN_5 | WAKEUP_ON_LEVEL_HIGH, + GPIO17_KP_MKIN_6 | WAKEUP_ON_LEVEL_HIGH, + GPIO103_KP_MKOUT_0, + GPIO104_KP_MKOUT_1, + GPIO105_KP_MKOUT_2, + GPIO106_KP_MKOUT_3, + GPIO107_KP_MKOUT_4, + GPIO108_KP_MKOUT_5, + GPIO35_KP_MKOUT_6, + GPIO41_KP_MKOUT_7, + + /* I2C */ + GPIO117_I2C_SCL, + GPIO118_I2C_SDA, + + /* SSP1 */ + GPIO23_SSP1_SCLK, /* SSP1_SCK */ + GPIO25_SSP1_TXD, /* SSP1_TXD */ + GPIO26_SSP1_RXD, /* SSP1_RXD */ + + /* SSP2 */ + GPIO22_SSP2_SCLK, /* SSP2_SCK */ + GPIO13_SSP2_TXD, /* SSP2_TXD */ + GPIO40_SSP2_RXD, /* SSP2_RXD */ + + /* LEDs */ + GPIO10_GPIO, /* WiFi LED */ + GPIO83_GPIO, /* Charging LED */ + GPIO85_GPIO, /* Charged LED */ + + /* I2S */ + GPIO28_I2S_BITCLK_OUT, + GPIO29_I2S_SDATA_IN, + GPIO30_I2S_SDATA_OUT, + GPIO31_I2S_SYNC, + GPIO113_I2S_SYSCLK, + + /* MISC */ + GPIO0_GPIO, /* AC power detect */ + GPIO1_GPIO, /* Power button */ + GPIO37_GPIO, /* Headphone detect */ + GPIO98_GPIO, /* Lid switch */ + GPIO14_GPIO, /* WiFi Reset */ + GPIO15_GPIO, /* WiFi Power */ + GPIO24_GPIO, /* WiFi CS */ + GPIO36_GPIO, /* WiFi IRQ */ + GPIO88_GPIO, /* LCD CS */ +}; + +/****************************************************************************** + * NOR Flash + ******************************************************************************/ +#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE) +static struct resource z2_flash_resource = { + .start = PXA_CS0_PHYS, + .end = PXA_CS0_PHYS + SZ_8M - 1, + .flags = IORESOURCE_MEM, +}; + +static struct mtd_partition z2_flash_parts[] = { + { + .name = "U-Boot Bootloader", + .offset = 0x0, + .size = 0x20000, + }, + { + .name = "Linux Kernel", + .offset = 0x20000, + .size = 0x220000, + }, + { + .name = "Filesystem", + .offset = 0x240000, + .size = 0x5b0000, + }, + { + .name = "U-Boot Environment", + .offset = 0x7f0000, + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct physmap_flash_data z2_flash_data = { + .width = 2, + .parts = z2_flash_parts, + .nr_parts = ARRAY_SIZE(z2_flash_parts), +}; + +static struct platform_device z2_flash = { + .name = "physmap-flash", + .id = -1, + .resource = &z2_flash_resource, + .num_resources = 1, + .dev = { + .platform_data = &z2_flash_data, + }, +}; + +static void __init z2_nor_init(void) +{ + platform_device_register(&z2_flash); +} +#else +static inline void z2_nor_init(void) {} +#endif + +/****************************************************************************** + * Backlight + ******************************************************************************/ +#if defined(CONFIG_BACKLIGHT_PWM) || defined(CONFIG_BACKLIGHT_PWM_MODULE) +static struct platform_pwm_backlight_data z2_backlight_data[] = { + [0] = { + /* Keypad Backlight */ + .pwm_id = 1, + .max_brightness = 1023, + .dft_brightness = 512, + .pwm_period_ns = 1260320, + }, + [1] = { + /* LCD Backlight */ + .pwm_id = 2, + .max_brightness = 1023, + .dft_brightness = 512, + .pwm_period_ns = 1260320, + }, +}; + +static struct platform_device z2_backlight_devices[2] = { + { + .name = "pwm-backlight", + .id = 0, + .dev = { + .platform_data = &z2_backlight_data[1], + }, + }, + { + .name = "pwm-backlight", + .id = 1, + .dev = { + .platform_data = &z2_backlight_data[0], + }, + }, +}; +static void __init z2_pwm_init(void) +{ + platform_device_register(&z2_backlight_devices[0]); + platform_device_register(&z2_backlight_devices[1]); +} +#else +static inline void z2_pwm_init(void) {} +#endif + +/****************************************************************************** + * Framebuffer + ******************************************************************************/ +#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE) +static struct pxafb_mode_info z2_lcd_modes[] = { +{ + .pixclock = 192000, + .xres = 240, + .yres = 320, + .bpp = 16, + + .left_margin = 4, + .right_margin = 8, + .upper_margin = 4, + .lower_margin = 8, + + .hsync_len = 4, + .vsync_len = 4, +}, +}; + +static struct pxafb_mach_info z2_lcd_screen = { + .modes = z2_lcd_modes, + .num_modes = ARRAY_SIZE(z2_lcd_modes), + .lcd_conn = LCD_COLOR_TFT_16BPP | LCD_BIAS_ACTIVE_LOW | + LCD_ALTERNATE_MAPPING, +}; + +static void __init z2_lcd_init(void) +{ + set_pxa_fb_info(&z2_lcd_screen); +} +#else +static inline void z2_lcd_init(void) {} +#endif + +/****************************************************************************** + * SD/MMC card controller + ******************************************************************************/ +#if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE) +static struct pxamci_platform_data z2_mci_platform_data = { + .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, + .gpio_card_detect = GPIO96_ZIPITZ2_SD_DETECT, + .gpio_power = -1, + .gpio_card_ro = -1, + .detect_delay = 20, +}; + +static void __init z2_mmc_init(void) +{ + pxa_set_mci_info(&z2_mci_platform_data); +} +#else +static inline void z2_mmc_init(void) {} +#endif + +/****************************************************************************** + * LEDs + ******************************************************************************/ +#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE) +struct gpio_led z2_gpio_leds[] = { +{ + .name = "z2:green:wifi", + .default_trigger = "none", + .gpio = GPIO10_ZIPITZ2_LED_WIFI, + .active_low = 1, +}, { + .name = "z2:green:charged", + .default_trigger = "none", + .gpio = GPIO85_ZIPITZ2_LED_CHARGED, + .active_low = 1, +}, { + .name = "z2:amber:charging", + .default_trigger = "none", + .gpio = GPIO83_ZIPITZ2_LED_CHARGING, + .active_low = 1, +}, +}; + +static struct gpio_led_platform_data z2_gpio_led_info = { + .leds = z2_gpio_leds, + .num_leds = ARRAY_SIZE(z2_gpio_leds), +}; + +static struct platform_device z2_leds = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &z2_gpio_led_info, + } +}; + +static void __init z2_leds_init(void) +{ + platform_device_register(&z2_leds); +} +#else +static inline void z2_leds_init(void) {} +#endif + +/****************************************************************************** + * GPIO keyboard + ******************************************************************************/ +#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE) +static unsigned int z2_matrix_keys[] = { + KEY(0, 0, KEY_OPTION), + KEY(1, 0, KEY_UP), + KEY(2, 0, KEY_DOWN), + KEY(3, 0, KEY_LEFT), + KEY(4, 0, KEY_RIGHT), + KEY(5, 0, KEY_END), + KEY(6, 0, KEY_KPPLUS), + + KEY(0, 1, KEY_HOME), + KEY(1, 1, KEY_Q), + KEY(2, 1, KEY_I), + KEY(3, 1, KEY_G), + KEY(4, 1, KEY_X), + KEY(5, 1, KEY_ENTER), + KEY(6, 1, KEY_KPMINUS), + + KEY(0, 2, KEY_PAGEUP), + KEY(1, 2, KEY_W), + KEY(2, 2, KEY_O), + KEY(3, 2, KEY_H), + KEY(4, 2, KEY_C), + KEY(5, 2, KEY_LEFTALT), + + KEY(0, 3, KEY_PAGEDOWN), + KEY(1, 3, KEY_E), + KEY(2, 3, KEY_P), + KEY(3, 3, KEY_J), + KEY(4, 3, KEY_V), + KEY(5, 3, KEY_LEFTSHIFT), + + KEY(0, 4, KEY_ESC), + KEY(1, 4, KEY_R), + KEY(2, 4, KEY_A), + KEY(3, 4, KEY_K), + KEY(4, 4, KEY_B), + KEY(5, 4, KEY_LEFTCTRL), + + KEY(0, 5, KEY_TAB), + KEY(1, 5, KEY_T), + KEY(2, 5, KEY_S), + KEY(3, 5, KEY_L), + KEY(4, 5, KEY_N), + KEY(5, 5, KEY_SPACE), + + KEY(0, 6, KEY_STOPCD), + KEY(1, 6, KEY_Y), + KEY(2, 6, KEY_D), + KEY(3, 6, KEY_BACKSPACE), + KEY(4, 6, KEY_M), + KEY(5, 6, KEY_COMMA), + + KEY(0, 7, KEY_PLAYCD), + KEY(1, 7, KEY_U), + KEY(2, 7, KEY_F), + KEY(3, 7, KEY_Z), + KEY(4, 7, KEY_SEMICOLON), + KEY(5, 7, KEY_DOT), +}; + +static struct pxa27x_keypad_platform_data z2_keypad_platform_data = { + .matrix_key_rows = 7, + .matrix_key_cols = 8, + .matrix_key_map = z2_matrix_keys, + .matrix_key_map_size = ARRAY_SIZE(z2_matrix_keys), + + .debounce_interval = 30, +}; + +static void __init z2_mkp_init(void) +{ + pxa_set_keypad_info(&z2_keypad_platform_data); +} +#else +static inline void z2_mkp_init(void) {} +#endif + +/****************************************************************************** + * GPIO keys + ******************************************************************************/ +#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE) +static struct gpio_keys_button z2_pxa_buttons[] = { + {KEY_POWER, GPIO1_ZIPITZ2_POWER_BUTTON, 0, "Power Button" }, + {KEY_CLOSE, GPIO98_ZIPITZ2_LID_BUTTON, 0, "Lid Button" }, +}; + +static struct gpio_keys_platform_data z2_pxa_keys_data = { + .buttons = z2_pxa_buttons, + .nbuttons = ARRAY_SIZE(z2_pxa_buttons), +}; + +static struct platform_device z2_pxa_keys = { + .name = "gpio-keys", + .id = -1, + .dev = { + .platform_data = &z2_pxa_keys_data, + }, +}; + +static void __init z2_keys_init(void) +{ + platform_device_register(&z2_pxa_keys); +} +#else +static inline void z2_keys_init(void) {} +#endif + +/****************************************************************************** + * SSP Devices - WiFi and LCD control + ******************************************************************************/ +#if defined(CONFIG_SPI_PXA2XX) || defined(CONFIG_SPI_PXA2XX_MODULE) +/* WiFi */ +static int z2_lbs_spi_setup(struct spi_device *spi) +{ + int ret = 0; + + ret = gpio_request(GPIO15_ZIPITZ2_WIFI_POWER, "WiFi Power"); + if (ret) + goto err; + + ret = gpio_direction_output(GPIO15_ZIPITZ2_WIFI_POWER, 1); + if (ret) + goto err2; + + ret = gpio_request(GPIO14_ZIPITZ2_WIFI_RESET, "WiFi Reset"); + if (ret) + goto err2; + + ret = gpio_direction_output(GPIO14_ZIPITZ2_WIFI_RESET, 0); + if (ret) + goto err3; + + /* Reset the card */ + mdelay(180); + gpio_set_value(GPIO14_ZIPITZ2_WIFI_RESET, 1); + mdelay(20); + + spi->bits_per_word = 16; + spi->mode = SPI_MODE_2, + + spi_setup(spi); + + return 0; + +err3: + gpio_free(GPIO14_ZIPITZ2_WIFI_RESET); +err2: + gpio_free(GPIO15_ZIPITZ2_WIFI_POWER); +err: + return ret; +}; + +static int z2_lbs_spi_teardown(struct spi_device *spi) +{ + gpio_set_value(GPIO14_ZIPITZ2_WIFI_RESET, 0); + gpio_set_value(GPIO15_ZIPITZ2_WIFI_POWER, 0); + gpio_free(GPIO14_ZIPITZ2_WIFI_RESET); + gpio_free(GPIO15_ZIPITZ2_WIFI_POWER); + return 0; + +}; + +static struct pxa2xx_spi_chip z2_lbs_chip_info = { + .rx_threshold = 8, + .tx_threshold = 8, + .timeout = 1000, + .gpio_cs = GPIO24_ZIPITZ2_WIFI_CS, +}; + +static struct libertas_spi_platform_data z2_lbs_pdata = { + .use_dummy_writes = 1, + .setup = z2_lbs_spi_setup, + .teardown = z2_lbs_spi_teardown, +}; + +/* LCD */ +static struct pxa2xx_spi_chip lms283_chip_info = { + .rx_threshold = 1, + .tx_threshold = 1, + .timeout = 64, + .gpio_cs = GPIO88_ZIPITZ2_LCD_CS, +}; + +static const struct lms283gf05_pdata lms283_pdata = { + .reset_gpio = GPIO19_ZIPITZ2_LCD_RESET, +}; + +static struct spi_board_info spi_board_info[] __initdata = { +{ + .modalias = "libertas_spi", + .platform_data = &z2_lbs_pdata, + .controller_data = &z2_lbs_chip_info, + .irq = gpio_to_irq(GPIO36_ZIPITZ2_WIFI_IRQ), + .max_speed_hz = 13000000, + .bus_num = 1, + .chip_select = 0, +}, +{ + .modalias = "lms283gf05", + .controller_data = &lms283_chip_info, + .platform_data = &lms283_pdata, + .max_speed_hz = 400000, + .bus_num = 2, + .chip_select = 0, +}, +}; + +static struct pxa2xx_spi_master pxa_ssp1_master_info = { + .clock_enable = CKEN_SSP, + .num_chipselect = 1, + .enable_dma = 1, +}; + +static struct pxa2xx_spi_master pxa_ssp2_master_info = { + .clock_enable = CKEN_SSP2, + .num_chipselect = 1, +}; + +static void __init z2_spi_init(void) +{ + pxa2xx_set_spi_info(1, &pxa_ssp1_master_info); + pxa2xx_set_spi_info(2, &pxa_ssp2_master_info); + spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info)); +} +#else +static inline void z2_spi_init(void) {} +#endif + +/****************************************************************************** + * Machine init + ******************************************************************************/ +static void __init z2_init(void) +{ + pxa2xx_mfp_config(ARRAY_AND_SIZE(z2_pin_config)); + + z2_lcd_init(); + z2_mmc_init(); + z2_mkp_init(); + + pxa_set_i2c_info(NULL); + + z2_spi_init(); + z2_nor_init(); + z2_pwm_init(); + z2_leds_init(); + z2_keys_init(); +} + +MACHINE_START(ZIPIT2, "Zipit Z2") + .phys_io = 0x40000000, + .boot_params = 0xa0000100, + .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, + .map_io = pxa_map_io, + .init_irq = pxa27x_init_irq, + .timer = &pxa_timer, + .init_machine = z2_init, +MACHINE_END -- cgit v0.10.2 From 543cd84255f499a53d409014bc5ba71543474b05 Mon Sep 17 00:00:00 2001 From: Marek Date: Tue, 9 Mar 2010 04:04:12 +0100 Subject: [ARM] pxa: add basic support for Voipac PXA270 SBC This patch adds basic support for the Voipac PXA270 SBC. The device consists of the following hardware: - PXA270 @ 520 MHz - 256MB RAM (sparsemem, 2*128MB regions) - 64MB NOR flash - 640x480 LCD - Ports: 2xUHC, 1xUDC, 1xPCMCIA, VGA, FFUART, 2xPS2, Speaker, MIC Signed-off-by: Marek Vasut Signed-off-by: Eric Miao diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index 2e4122d..e4a0452 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -249,6 +249,12 @@ config MACH_COLIBRI320 select PXA3xx select CPU_PXA320 +config MACH_VPAC270 + bool "Voipac PXA270" + select PXA27x + help + PXA270 based Single Board Computer. + comment "End-user Products (sorted by vendor name)" config MACH_H4700 diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index e929231..b8f1f4b 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -61,6 +61,7 @@ obj-$(CONFIG_MACH_PCM990_BASEBOARD) += pcm990-baseboard.o obj-$(CONFIG_MACH_COLIBRI) += colibri-pxa270.o obj-$(CONFIG_MACH_COLIBRI300) += colibri-pxa3xx.o colibri-pxa300.o obj-$(CONFIG_MACH_COLIBRI320) += colibri-pxa3xx.o colibri-pxa320.o +obj-$(CONFIG_MACH_VPAC270) += vpac270.o # End-user Products obj-$(CONFIG_MACH_H4700) += hx4700.o diff --git a/arch/arm/mach-pxa/include/mach/vpac270.h b/arch/arm/mach-pxa/include/mach/vpac270.h new file mode 100644 index 0000000..8f8eaed --- /dev/null +++ b/arch/arm/mach-pxa/include/mach/vpac270.h @@ -0,0 +1,26 @@ +/* + * GPIOs and interrupts for Voipac PXA270 + * + * Copyright (C) 2010 + * Marek Vasut + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#ifndef _INCLUDE_VPAC270_H_ +#define _INCLUDE_VPAC270_H_ + +#define GPIO1_VPAC270_USER_BTN 1 + +#define GPIO15_VPAC270_LED_ORANGE 15 + +#define GPIO81_VPAC270_BKL_ON 81 +#define GPIO83_VPAC270_NL_ON 83 + +#define GPIO52_VPAC270_SD_READONLY 52 +#define GPIO53_VPAC270_SD_DETECT_N 53 + +#endif diff --git a/arch/arm/mach-pxa/vpac270.c b/arch/arm/mach-pxa/vpac270.c new file mode 100644 index 0000000..710a17c --- /dev/null +++ b/arch/arm/mach-pxa/vpac270.c @@ -0,0 +1,305 @@ +/* + * Hardware definitions for Voipac PXA270 + * + * Copyright (C) 2010 + * Marek Vasut + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include "generic.h" +#include "devices.h" + +/****************************************************************************** + * Pin configuration + ******************************************************************************/ +static unsigned long vpac270_pin_config[] __initdata = { + /* MMC */ + GPIO32_MMC_CLK, + GPIO92_MMC_DAT_0, + GPIO109_MMC_DAT_1, + GPIO110_MMC_DAT_2, + GPIO111_MMC_DAT_3, + GPIO112_MMC_CMD, + GPIO53_GPIO, /* SD detect */ + GPIO52_GPIO, /* SD r/o switch */ + + /* GPIO KEYS */ + GPIO1_GPIO, /* USER BTN */ + + /* LEDs */ + GPIO15_GPIO, /* orange led */ + + /* FFUART */ + GPIO34_FFUART_RXD, + GPIO39_FFUART_TXD, + GPIO27_FFUART_RTS, + GPIO100_FFUART_CTS, + GPIO33_FFUART_DSR, + GPIO40_FFUART_DTR, + GPIO10_FFUART_DCD, + GPIO38_FFUART_RI, + + /* LCD */ + GPIO58_LCD_LDD_0, + GPIO59_LCD_LDD_1, + GPIO60_LCD_LDD_2, + GPIO61_LCD_LDD_3, + GPIO62_LCD_LDD_4, + GPIO63_LCD_LDD_5, + GPIO64_LCD_LDD_6, + GPIO65_LCD_LDD_7, + GPIO66_LCD_LDD_8, + GPIO67_LCD_LDD_9, + GPIO68_LCD_LDD_10, + GPIO69_LCD_LDD_11, + GPIO70_LCD_LDD_12, + GPIO71_LCD_LDD_13, + GPIO72_LCD_LDD_14, + GPIO73_LCD_LDD_15, + GPIO86_LCD_LDD_16, + GPIO87_LCD_LDD_17, + GPIO74_LCD_FCLK, + GPIO75_LCD_LCLK, + GPIO76_LCD_PCLK, + GPIO77_LCD_BIAS, +}; + +/****************************************************************************** + * NOR Flash + ******************************************************************************/ +#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE) +static struct mtd_partition vpac270_partitions[] = { + { + .name = "Flash", + .offset = 0x00000000, + .size = MTDPART_SIZ_FULL, + } +}; + +static struct physmap_flash_data vpac270_flash_data[] = { + { + .width = 2, /* bankwidth in bytes */ + .parts = vpac270_partitions, + .nr_parts = ARRAY_SIZE(vpac270_partitions) + } +}; + +static struct resource vpac270_flash_resource = { + .start = PXA_CS0_PHYS, + .end = PXA_CS0_PHYS + SZ_64M - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device vpac270_flash = { + .name = "physmap-flash", + .id = 0, + .resource = &vpac270_flash_resource, + .num_resources = 1, + .dev = { + .platform_data = vpac270_flash_data, + }, +}; +static void __init vpac270_nor_init(void) +{ + platform_device_register(&vpac270_flash); +} +#else +static inline void vpac270_nor_init(void) {} +#endif + +/****************************************************************************** + * SD/MMC card controller + ******************************************************************************/ +#if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE) +static struct pxamci_platform_data vpac270_mci_platform_data = { + .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, + .gpio_card_detect = GPIO53_VPAC270_SD_DETECT_N, + .gpio_card_ro = GPIO52_VPAC270_SD_READONLY, + .detect_delay = 20, +}; + +static void __init vpac270_mmc_init(void) +{ + pxa_set_mci_info(&vpac270_mci_platform_data); +} +#else +static inline void vpac270_mmc_init(void) {} +#endif + +/****************************************************************************** + * GPIO keys + ******************************************************************************/ +#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE) +static struct gpio_keys_button vpac270_pxa_buttons[] = { + {KEY_POWER, GPIO1_VPAC270_USER_BTN, 0, "USER BTN"}, +}; + +static struct gpio_keys_platform_data vpac270_pxa_keys_data = { + .buttons = vpac270_pxa_buttons, + .nbuttons = ARRAY_SIZE(vpac270_pxa_buttons), +}; + +static struct platform_device vpac270_pxa_keys = { + .name = "gpio-keys", + .id = -1, + .dev = { + .platform_data = &vpac270_pxa_keys_data, + }, +}; + +static void __init vpac270_keys_init(void) +{ + platform_device_register(&vpac270_pxa_keys); +} +#else +static inline void vpac270_keys_init(void) {} +#endif + +/****************************************************************************** + * LED + ******************************************************************************/ +#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE) +struct gpio_led vpac270_gpio_leds[] = { +{ + .name = "vpac270:orange:user", + .default_trigger = "none", + .gpio = GPIO15_VPAC270_LED_ORANGE, + .active_low = 1, +} +}; + +static struct gpio_led_platform_data vpac270_gpio_led_info = { + .leds = vpac270_gpio_leds, + .num_leds = ARRAY_SIZE(vpac270_gpio_leds), +}; + +static struct platform_device vpac270_leds = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &vpac270_gpio_led_info, + } +}; + +static void __init vpac270_leds_init(void) +{ + platform_device_register(&vpac270_leds); +} +#else +static inline void vpac270_leds_init(void) {} +#endif + +/****************************************************************************** + * Framebuffer + ******************************************************************************/ +#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE) +static struct pxafb_mode_info vpac270_lcd_modes[] = { +{ + .pixclock = 57692, + .xres = 640, + .yres = 480, + .bpp = 32, + .depth = 18, + + .left_margin = 144, + .right_margin = 32, + .upper_margin = 13, + .lower_margin = 30, + + .hsync_len = 32, + .vsync_len = 2, + + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, +}, +}; + +static struct pxafb_mach_info vpac270_lcd_screen = { + .modes = vpac270_lcd_modes, + .num_modes = ARRAY_SIZE(vpac270_lcd_modes), + .lcd_conn = LCD_COLOR_TFT_18BPP, +}; + +static void vpac270_lcd_power(int on, struct fb_var_screeninfo *info) +{ + gpio_set_value(GPIO81_VPAC270_BKL_ON, on); +} + +static void __init vpac270_lcd_init(void) +{ + int ret; + + ret = gpio_request(GPIO81_VPAC270_BKL_ON, "BKL-ON"); + if (ret) { + pr_err("Requesting BKL-ON GPIO failed!\n"); + goto err; + } + + ret = gpio_direction_output(GPIO81_VPAC270_BKL_ON, 1); + if (ret) { + pr_err("Setting BKL-ON GPIO direction failed!\n"); + goto err2; + } + + vpac270_lcd_screen.pxafb_lcd_power = vpac270_lcd_power; + set_pxa_fb_info(&vpac270_lcd_screen); + return; + +err2: + gpio_free(GPIO81_VPAC270_BKL_ON); +err: + return; +} +#else +static inline void vpac270_lcd_init(void) {} +#endif + +/****************************************************************************** + * Machine init + ******************************************************************************/ +static void __init vpac270_init(void) +{ + pxa2xx_mfp_config(ARRAY_AND_SIZE(vpac270_pin_config)); + + pxa_set_ffuart_info(NULL); + pxa_set_btuart_info(NULL); + pxa_set_stuart_info(NULL); + + vpac270_lcd_init(); + vpac270_mmc_init(); + vpac270_nor_init(); + vpac270_leds_init(); + vpac270_keys_init(); +} + +MACHINE_START(VPAC270, "Voipac PXA270") + .phys_io = 0x40000000, + .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, + .boot_params = 0xa0000100, + .map_io = pxa_map_io, + .init_irq = pxa27x_init_irq, + .timer = &pxa_timer, + .init_machine = vpac270_init +MACHINE_END -- cgit v0.10.2 From addff0faecfc5e73e8a742687255cef847e260db Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 10 Mar 2010 04:16:28 +0100 Subject: [ARM] pxa: add support for Voipac PXA270 PCMCIA PCMCIA support for Voipac PXA270 Signed-off-by: Marek Vasut Signed-off-by: Eric Miao diff --git a/arch/arm/mach-pxa/include/mach/vpac270.h b/arch/arm/mach-pxa/include/mach/vpac270.h index 8f8eaed..a77e310 100644 --- a/arch/arm/mach-pxa/include/mach/vpac270.h +++ b/arch/arm/mach-pxa/include/mach/vpac270.h @@ -23,4 +23,12 @@ #define GPIO52_VPAC270_SD_READONLY 52 #define GPIO53_VPAC270_SD_DETECT_N 53 +#define GPIO84_VPAC270_PCMCIA_CD 84 +#define GPIO35_VPAC270_PCMCIA_RDY 35 +#define GPIO107_VPAC270_PCMCIA_PPEN 107 +#define GPIO11_VPAC270_PCMCIA_RESET 11 +#define GPIO17_VPAC270_CF_CD 17 +#define GPIO12_VPAC270_CF_RDY 12 +#define GPIO16_VPAC270_CF_RESET 16 + #endif diff --git a/arch/arm/mach-pxa/vpac270.c b/arch/arm/mach-pxa/vpac270.c index 710a17c..f1b0737 100644 --- a/arch/arm/mach-pxa/vpac270.c +++ b/arch/arm/mach-pxa/vpac270.c @@ -85,6 +85,26 @@ static unsigned long vpac270_pin_config[] __initdata = { GPIO75_LCD_LCLK, GPIO76_LCD_PCLK, GPIO77_LCD_BIAS, + + /* PCMCIA */ + GPIO48_nPOE, + GPIO49_nPWE, + GPIO50_nPIOR, + GPIO51_nPIOW, + GPIO85_nPCE_1, + GPIO54_nPCE_2, + GPIO55_nPREG, + GPIO57_nIOIS16, + GPIO56_nPWAIT, + GPIO104_PSKTSEL, + GPIO84_GPIO, /* PCMCIA CD */ + GPIO35_GPIO, /* PCMCIA RDY */ + GPIO107_GPIO, /* PCMCIA PPEN */ + GPIO11_GPIO, /* PCMCIA RESET */ + GPIO17_GPIO, /* CF CD */ + GPIO12_GPIO, /* CF RDY */ + GPIO16_GPIO, /* CF RESET */ + }; /****************************************************************************** diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index d189e47..a44733d 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig @@ -234,7 +234,8 @@ config PCMCIA_PXA2XX depends on ARM && ARCH_PXA && PCMCIA depends on (ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL \ || MACH_ARMCORE || ARCH_PXA_PALM || TRIZEPS_PCMCIA \ - || ARCOM_PCMCIA || ARCH_PXA_ESERIES || MACH_STARGATE2) + || ARCOM_PCMCIA || ARCH_PXA_ESERIES || MACH_STARGATE2 \ + || MACH_VPAC270) select PCMCIA_SOC_COMMON help Say Y here to include support for the PXA2xx PCMCIA controller diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index 381b031..4dae361 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile @@ -66,6 +66,7 @@ pxa2xx-obj-$(CONFIG_MACH_PALMTC) += pxa2xx_palmtc.o pxa2xx-obj-$(CONFIG_MACH_PALMLD) += pxa2xx_palmld.o pxa2xx-obj-$(CONFIG_MACH_E740) += pxa2xx_e740.o pxa2xx-obj-$(CONFIG_MACH_STARGATE2) += pxa2xx_stargate2.o +pxa2xx-obj-$(CONFIG_MACH_VPAC270) += pxa2xx_vpac270.o obj-$(CONFIG_PCMCIA_PXA2XX) += pxa2xx_base.o $(pxa2xx-obj-y) diff --git a/drivers/pcmcia/pxa2xx_vpac270.c b/drivers/pcmcia/pxa2xx_vpac270.c new file mode 100644 index 0000000..55627ec --- /dev/null +++ b/drivers/pcmcia/pxa2xx_vpac270.c @@ -0,0 +1,229 @@ +/* + * linux/drivers/pcmcia/pxa2xx_vpac270.c + * + * Driver for Voipac PXA270 PCMCIA and CF sockets + * + * Copyright (C) 2010 + * Marek Vasut + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include + +#include + +#include +#include + +#include "soc_common.h" + +static struct pcmcia_irqs cd_irqs[] = { + { + .sock = 0, + .irq = IRQ_GPIO(GPIO84_VPAC270_PCMCIA_CD), + .str = "PCMCIA CD" + }, + { + .sock = 1, + .irq = IRQ_GPIO(GPIO17_VPAC270_CF_CD), + .str = "CF CD" + }, +}; + +static int vpac270_pcmcia_hw_init(struct soc_pcmcia_socket *skt) +{ + int ret; + + if (skt->nr == 0) { + ret = gpio_request(GPIO84_VPAC270_PCMCIA_CD, "PCMCIA CD"); + if (ret) + goto err1; + ret = gpio_direction_input(GPIO84_VPAC270_PCMCIA_CD); + if (ret) + goto err2; + + ret = gpio_request(GPIO35_VPAC270_PCMCIA_RDY, "PCMCIA RDY"); + if (ret) + goto err2; + ret = gpio_direction_input(GPIO35_VPAC270_PCMCIA_RDY); + if (ret) + goto err3; + + ret = gpio_request(GPIO107_VPAC270_PCMCIA_PPEN, "PCMCIA PPEN"); + if (ret) + goto err3; + ret = gpio_direction_output(GPIO107_VPAC270_PCMCIA_PPEN, 0); + if (ret) + goto err4; + + ret = gpio_request(GPIO11_VPAC270_PCMCIA_RESET, "PCMCIA RESET"); + if (ret) + goto err4; + ret = gpio_direction_output(GPIO11_VPAC270_PCMCIA_RESET, 0); + if (ret) + goto err5; + + skt->socket.pci_irq = gpio_to_irq(GPIO35_VPAC270_PCMCIA_RDY); + + return soc_pcmcia_request_irqs(skt, &cd_irqs[0], 1); + +err5: + gpio_free(GPIO11_VPAC270_PCMCIA_RESET); +err4: + gpio_free(GPIO107_VPAC270_PCMCIA_PPEN); +err3: + gpio_free(GPIO35_VPAC270_PCMCIA_RDY); +err2: + gpio_free(GPIO84_VPAC270_PCMCIA_CD); +err1: + return ret; + + } else { + ret = gpio_request(GPIO17_VPAC270_CF_CD, "CF CD"); + if (ret) + goto err6; + ret = gpio_direction_input(GPIO17_VPAC270_CF_CD); + if (ret) + goto err7; + + ret = gpio_request(GPIO12_VPAC270_CF_RDY, "CF RDY"); + if (ret) + goto err7; + ret = gpio_direction_input(GPIO12_VPAC270_CF_RDY); + if (ret) + goto err8; + + ret = gpio_request(GPIO16_VPAC270_CF_RESET, "CF RESET"); + if (ret) + goto err8; + ret = gpio_direction_output(GPIO16_VPAC270_CF_RESET, 0); + if (ret) + goto err9; + + skt->socket.pci_irq = gpio_to_irq(GPIO12_VPAC270_CF_RDY); + + return soc_pcmcia_request_irqs(skt, &cd_irqs[1], 1); + +err9: + gpio_free(GPIO16_VPAC270_CF_RESET); +err8: + gpio_free(GPIO12_VPAC270_CF_RDY); +err7: + gpio_free(GPIO17_VPAC270_CF_CD); +err6: + return ret; + + } +} + +static void vpac270_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) +{ + gpio_free(GPIO11_VPAC270_PCMCIA_RESET); + gpio_free(GPIO107_VPAC270_PCMCIA_PPEN); + gpio_free(GPIO35_VPAC270_PCMCIA_RDY); + gpio_free(GPIO84_VPAC270_PCMCIA_CD); + gpio_free(GPIO16_VPAC270_CF_RESET); + gpio_free(GPIO12_VPAC270_CF_RDY); + gpio_free(GPIO17_VPAC270_CF_CD); +} + +static void vpac270_pcmcia_socket_state(struct soc_pcmcia_socket *skt, + struct pcmcia_state *state) +{ + if (skt->nr == 0) { + state->detect = !gpio_get_value(GPIO84_VPAC270_PCMCIA_CD); + state->ready = !!gpio_get_value(GPIO35_VPAC270_PCMCIA_RDY); + } else { + state->detect = !gpio_get_value(GPIO17_VPAC270_CF_CD); + state->ready = !!gpio_get_value(GPIO12_VPAC270_CF_RDY); + } + state->bvd1 = 1; + state->bvd2 = 1; + state->wrprot = 0; + state->vs_3v = 1; + state->vs_Xv = 0; +} + +static int +vpac270_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, + const socket_state_t *state) +{ + if (skt->nr == 0) { + gpio_set_value(GPIO11_VPAC270_PCMCIA_RESET, + (state->flags & SS_RESET)); + gpio_set_value(GPIO107_VPAC270_PCMCIA_PPEN, + !(state->Vcc == 33 || state->Vcc == 50)); + } else { + gpio_set_value(GPIO16_VPAC270_CF_RESET, + (state->flags & SS_RESET)); + } + + return 0; +} + +static void vpac270_pcmcia_socket_init(struct soc_pcmcia_socket *skt) +{ +} + +static void vpac270_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) +{ +} + +static struct pcmcia_low_level vpac270_pcmcia_ops = { + .owner = THIS_MODULE, + + .first = 0, + .nr = 2, + + .hw_init = vpac270_pcmcia_hw_init, + .hw_shutdown = vpac270_pcmcia_hw_shutdown, + + .socket_state = vpac270_pcmcia_socket_state, + .configure_socket = vpac270_pcmcia_configure_socket, + + .socket_init = vpac270_pcmcia_socket_init, + .socket_suspend = vpac270_pcmcia_socket_suspend, +}; + +static struct platform_device *vpac270_pcmcia_device; + +static int __init vpac270_pcmcia_init(void) +{ + int ret; + + if (!machine_is_vpac270()) + return -ENODEV; + + vpac270_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1); + if (!vpac270_pcmcia_device) + return -ENOMEM; + + ret = platform_device_add_data(vpac270_pcmcia_device, + &vpac270_pcmcia_ops, sizeof(vpac270_pcmcia_ops)); + + if (!ret) + ret = platform_device_add(vpac270_pcmcia_device); + + if (ret) + platform_device_put(vpac270_pcmcia_device); + + return ret; +} + +static void __exit vpac270_pcmcia_exit(void) +{ + platform_device_unregister(vpac270_pcmcia_device); +} + +module_init(vpac270_pcmcia_init); +module_exit(vpac270_pcmcia_exit); + +MODULE_AUTHOR("Marek Vasut "); +MODULE_DESCRIPTION("PCMCIA support for Voipac PXA270"); +MODULE_ALIAS("platform:pxa2xx-pcmcia"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 3d98f8816adafce2933599902fd9a5c0ccedd822 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 10 Mar 2010 05:24:27 +0100 Subject: [ARM] pxa/vpac270: UDC and UHC support NOTE: I wasn't able to get it running without reseting the HXOE (so it's there based on my tests with the hardware). I'll have to investigate it properly when I have more time. Signed-off-by: Marek Vasut Reviewed-by: Robert Jarzmik Signed-off-by: Eric Miao diff --git a/arch/arm/mach-pxa/include/mach/vpac270.h b/arch/arm/mach-pxa/include/mach/vpac270.h index a77e310..9f7b460 100644 --- a/arch/arm/mach-pxa/include/mach/vpac270.h +++ b/arch/arm/mach-pxa/include/mach/vpac270.h @@ -31,4 +31,5 @@ #define GPIO12_VPAC270_CF_RDY 12 #define GPIO16_VPAC270_CF_RESET 16 +#define GPIO41_VPAC270_UDC_DETECT 41 #endif diff --git a/arch/arm/mach-pxa/vpac270.c b/arch/arm/mach-pxa/vpac270.c index f1b0737..b2bef61 100644 --- a/arch/arm/mach-pxa/vpac270.c +++ b/arch/arm/mach-pxa/vpac270.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,9 @@ #include #include #include +#include +#include +#include #include "generic.h" #include "devices.h" @@ -105,6 +109,14 @@ static unsigned long vpac270_pin_config[] __initdata = { GPIO12_GPIO, /* CF RDY */ GPIO16_GPIO, /* CF RESET */ + /* UHC */ + GPIO88_USBH1_PWR, + GPIO89_USBH1_PEN, + GPIO119_USBH2_PWR, + GPIO120_USBH2_PEN, + + /* UDC */ + GPIO41_GPIO, }; /****************************************************************************** @@ -233,6 +245,70 @@ static inline void vpac270_leds_init(void) {} #endif /****************************************************************************** + * USB Host + ******************************************************************************/ +#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) +static int vpac270_ohci_init(struct device *dev) +{ + UP2OCR = UP2OCR_HXS | UP2OCR_HXOE | UP2OCR_DPPDE | UP2OCR_DMPDE; + return 0; +} + +static struct pxaohci_platform_data vpac270_ohci_info = { + .port_mode = PMM_PERPORT_MODE, + .flags = ENABLE_PORT1 | ENABLE_PORT2 | + POWER_CONTROL_LOW | POWER_SENSE_LOW, + .init = vpac270_ohci_init, +}; + +static void __init vpac270_uhc_init(void) +{ + pxa_set_ohci_info(&vpac270_ohci_info); +} +#else +static inline void vpac270_uhc_init(void) {} +#endif + +/****************************************************************************** + * USB Gadget + ******************************************************************************/ +#if defined(CONFIG_USB_GADGET_PXA27X)||defined(CONFIG_USB_GADGET_PXA27X_MODULE) +static struct gpio_vbus_mach_info vpac270_gpio_vbus_info = { + .gpio_vbus = GPIO41_VPAC270_UDC_DETECT, + .gpio_pullup = -1, +}; + +static struct platform_device vpac270_gpio_vbus = { + .name = "gpio-vbus", + .id = -1, + .dev = { + .platform_data = &vpac270_gpio_vbus_info, + }, +}; + +static void vpac270_udc_command(int cmd) +{ + if (cmd == PXA2XX_UDC_CMD_CONNECT) + UP2OCR |= UP2OCR_HXOE | UP2OCR_DPPUE | UP2OCR_DPPUBE; + else if (cmd == PXA2XX_UDC_CMD_DISCONNECT) + UP2OCR &= ~(UP2OCR_HXOE | UP2OCR_DPPUE | UP2OCR_DPPUBE); +} + +static struct pxa2xx_udc_mach_info vpac270_udc_info __initdata = { + .udc_command = vpac270_udc_command, + .gpio_pullup = -1, +}; + +static void __init vpac270_udc_init(void) +{ + pxa_set_udc_info(&vpac270_udc_info); + platform_device_register(&vpac270_gpio_vbus); +} +#else +static inline void vpac270_udc_init(void) {} +#endif + +/****************************************************************************** * Framebuffer ******************************************************************************/ #if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE) @@ -312,6 +388,8 @@ static void __init vpac270_init(void) vpac270_nor_init(); vpac270_leds_init(); vpac270_keys_init(); + vpac270_uhc_init(); + vpac270_udc_init(); } MACHINE_START(VPAC270, "Voipac PXA270") -- cgit v0.10.2 From 947fb57e3a6be2920423de42a503eea08b0c0763 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 10 Mar 2010 05:38:54 +0100 Subject: [ARM] pxa/vpac270: add ethernet support Signed-off-by: Marek Vasut Signed-off-by: Eric Miao diff --git a/arch/arm/mach-pxa/include/mach/vpac270.h b/arch/arm/mach-pxa/include/mach/vpac270.h index 9f7b460..b90b380d 100644 --- a/arch/arm/mach-pxa/include/mach/vpac270.h +++ b/arch/arm/mach-pxa/include/mach/vpac270.h @@ -32,4 +32,7 @@ #define GPIO16_VPAC270_CF_RESET 16 #define GPIO41_VPAC270_UDC_DETECT 41 + +#define GPIO114_VPAC270_ETH_IRQ 114 + #endif diff --git a/arch/arm/mach-pxa/vpac270.c b/arch/arm/mach-pxa/vpac270.c index b2bef61..56cc245 100644 --- a/arch/arm/mach-pxa/vpac270.c +++ b/arch/arm/mach-pxa/vpac270.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -117,6 +118,9 @@ static unsigned long vpac270_pin_config[] __initdata = { /* UDC */ GPIO41_GPIO, + + /* Ethernet */ + GPIO114_GPIO, /* IRQ */ }; /****************************************************************************** @@ -309,6 +313,50 @@ static inline void vpac270_udc_init(void) {} #endif /****************************************************************************** + * Ethernet + ******************************************************************************/ +#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE) +static struct resource vpac270_dm9000_resources[] = { + [0] = { + .start = PXA_CS2_PHYS + 0x300, + .end = PXA_CS2_PHYS + 0x303, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = PXA_CS2_PHYS + 0x304, + .end = PXA_CS2_PHYS + 0x343, + .flags = IORESOURCE_MEM, + }, + [2] = { + .start = IRQ_GPIO(GPIO114_VPAC270_ETH_IRQ), + .end = IRQ_GPIO(GPIO114_VPAC270_ETH_IRQ), + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, + }, +}; + +static struct dm9000_plat_data vpac270_dm9000_platdata = { + .flags = DM9000_PLATF_32BITONLY, +}; + +static struct platform_device vpac270_dm9000_device = { + .name = "dm9000", + .id = -1, + .num_resources = ARRAY_SIZE(vpac270_dm9000_resources), + .resource = vpac270_dm9000_resources, + .dev = { + .platform_data = &vpac270_dm9000_platdata, + } +}; + +static void __init vpac270_eth_init(void) +{ + platform_device_register(&vpac270_dm9000_device); +} +#else +static inline void vpac270_eth_init(void) {} +#endif + +/****************************************************************************** * Framebuffer ******************************************************************************/ #if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE) @@ -390,6 +438,7 @@ static void __init vpac270_init(void) vpac270_keys_init(); vpac270_uhc_init(); vpac270_udc_init(); + vpac270_eth_init(); } MACHINE_START(VPAC270, "Voipac PXA270") -- cgit v0.10.2 From 1a8fb70e484589105a77f44bcd11e531c5fbe789 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 26 Mar 2010 04:45:54 +0100 Subject: [ARM] pxa/vpac270: Add touchscreen support This adds support for the UCB1400 touchscreen found in the VPAC270 device. Signed-off-by: Marek Vasut Signed-off-by: Eric Miao diff --git a/arch/arm/mach-pxa/vpac270.c b/arch/arm/mach-pxa/vpac270.c index 56cc245..fa428ca 100644 --- a/arch/arm/mach-pxa/vpac270.c +++ b/arch/arm/mach-pxa/vpac270.c @@ -22,11 +22,13 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -121,6 +123,15 @@ static unsigned long vpac270_pin_config[] __initdata = { /* Ethernet */ GPIO114_GPIO, /* IRQ */ + + /* AC97 */ + GPIO28_AC97_BITCLK, + GPIO29_AC97_SDATA_IN_0, + GPIO30_AC97_SDATA_OUT, + GPIO31_AC97_SYNC, + GPIO95_AC97_nRESET, + GPIO98_AC97_SYSCLK, + GPIO113_GPIO, /* TS IRQ */ }; /****************************************************************************** @@ -357,6 +368,36 @@ static inline void vpac270_eth_init(void) {} #endif /****************************************************************************** + * Audio and Touchscreen + ******************************************************************************/ +#if defined(CONFIG_TOUCHSCREEN_UCB1400) || \ + defined(CONFIG_TOUCHSCREEN_UCB1400_MODULE) +static pxa2xx_audio_ops_t vpac270_ac97_pdata = { + .reset_gpio = 95, +}; + +static struct ucb1400_pdata vpac270_ucb1400_pdata = { + .irq = IRQ_GPIO(113), +}; + +static struct platform_device vpac270_ucb1400_device = { + .name = "ucb1400_core", + .id = -1, + .dev = { + .platform_data = &vpac270_ucb1400_pdata, + }, +}; + +static void __init vpac270_ts_init(void) +{ + pxa_set_ac97_info(&vpac270_ac97_pdata); + platform_device_register(&vpac270_ucb1400_device); +} +#else +static inline void vpac270_ts_init(void) {} +#endif + +/****************************************************************************** * Framebuffer ******************************************************************************/ #if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE) @@ -439,6 +480,7 @@ static void __init vpac270_init(void) vpac270_uhc_init(); vpac270_udc_init(); vpac270_eth_init(); + vpac270_ts_init(); } MACHINE_START(VPAC270, "Voipac PXA270") -- cgit v0.10.2 From 83a4a1022654cbb9dd55fcf7c28807a634db54bc Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 26 Mar 2010 05:38:10 +0100 Subject: [ARM] pxa/vpac270: Add DS1339 RTC support Signed-off-by: Marek Vasut Signed-off-by: Eric Miao diff --git a/arch/arm/mach-pxa/vpac270.c b/arch/arm/mach-pxa/vpac270.c index fa428ca..0a9647b 100644 --- a/arch/arm/mach-pxa/vpac270.c +++ b/arch/arm/mach-pxa/vpac270.c @@ -36,6 +36,8 @@ #include #include +#include + #include "generic.h" #include "devices.h" @@ -132,6 +134,10 @@ static unsigned long vpac270_pin_config[] __initdata = { GPIO95_AC97_nRESET, GPIO98_AC97_SYSCLK, GPIO113_GPIO, /* TS IRQ */ + + /* I2C */ + GPIO117_I2C_SCL, + GPIO118_I2C_SDA, }; /****************************************************************************** @@ -398,6 +404,25 @@ static inline void vpac270_ts_init(void) {} #endif /****************************************************************************** + * RTC + ******************************************************************************/ +#if defined(CONFIG_RTC_DRV_DS1307) || defined(CONFIG_RTC_DRV_DS1307_MODULE) +static struct i2c_board_info __initdata vpac270_i2c_devs[] = { + { + I2C_BOARD_INFO("ds1339", 0x68), + }, +}; + +static void __init vpac270_rtc_init(void) +{ + pxa_set_i2c_info(NULL); + i2c_register_board_info(0, ARRAY_AND_SIZE(vpac270_i2c_devs)); +} +#else +static inline void vpac270_rtc_init(void) {} +#endif + +/****************************************************************************** * Framebuffer ******************************************************************************/ #if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE) @@ -481,6 +506,7 @@ static void __init vpac270_init(void) vpac270_udc_init(); vpac270_eth_init(); vpac270_ts_init(); + vpac270_rtc_init(); } MACHINE_START(VPAC270, "Voipac PXA270") -- cgit v0.10.2 From 052345aec01cbd22285771eee6e08486c07d3bcc Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 26 Apr 2010 21:46:07 +0200 Subject: [ARM] pxa/vpac270: add ide support This patch adds support for the on-board IDE channel. I tested this with a CDROM connected over 2.5-3.5 IDE reduction with external power supplied to the CDROM. This was not tested with the Voipac 270-HDD-000 (official Voipac HDD module), but I expect no problems. Signed-off-by: Marek Vasut Signed-off-by: Eric Miao diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index e4a0452..3b51741 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -252,6 +252,7 @@ config MACH_COLIBRI320 config MACH_VPAC270 bool "Voipac PXA270" select PXA27x + select HAVE_PATA_PLATFORM help PXA270 based Single Board Computer. diff --git a/arch/arm/mach-pxa/include/mach/vpac270.h b/arch/arm/mach-pxa/include/mach/vpac270.h index b90b380d..0d82c47 100644 --- a/arch/arm/mach-pxa/include/mach/vpac270.h +++ b/arch/arm/mach-pxa/include/mach/vpac270.h @@ -35,4 +35,6 @@ #define GPIO114_VPAC270_ETH_IRQ 114 +#define GPIO36_VPAC270_IDE_IRQ 36 + #endif diff --git a/arch/arm/mach-pxa/vpac270.c b/arch/arm/mach-pxa/vpac270.c index 0a9647b..6575b8f 100644 --- a/arch/arm/mach-pxa/vpac270.c +++ b/arch/arm/mach-pxa/vpac270.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -138,6 +139,10 @@ static unsigned long vpac270_pin_config[] __initdata = { /* I2C */ GPIO117_I2C_SCL, GPIO118_I2C_SDA, + + /* IDE */ + GPIO36_GPIO, /* IDE IRQ */ + GPIO80_DREQ_1, }; /****************************************************************************** @@ -487,6 +492,50 @@ static inline void vpac270_lcd_init(void) {} #endif /****************************************************************************** + * PATA IDE + ******************************************************************************/ +#if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE) +static struct pata_platform_info vpac270_pata_pdata = { + .ioport_shift = 1, + .irq_flags = IRQF_TRIGGER_RISING, +}; + +static struct resource vpac270_ide_resources[] = { + [0] = { /* I/O Base address */ + .start = PXA_CS3_PHYS + 0x120, + .end = PXA_CS3_PHYS + 0x13f, + .flags = IORESOURCE_MEM + }, + [1] = { /* CTL Base address */ + .start = PXA_CS3_PHYS + 0x15c, + .end = PXA_CS3_PHYS + 0x15f, + .flags = IORESOURCE_MEM + }, + [2] = { /* IDE IRQ pin */ + .start = gpio_to_irq(GPIO36_VPAC270_IDE_IRQ), + .end = gpio_to_irq(GPIO36_VPAC270_IDE_IRQ), + .flags = IORESOURCE_IRQ + } +}; + +static struct platform_device vpac270_ide_device = { + .name = "pata_platform", + .num_resources = ARRAY_SIZE(vpac270_ide_resources), + .resource = vpac270_ide_resources, + .dev = { + .platform_data = &vpac270_pata_pdata, + } +}; + +static void __init vpac270_ide_init(void) +{ + platform_device_register(&vpac270_ide_device); +} +#else +static inline void vpac270_ide_init(void) {} +#endif + +/****************************************************************************** * Machine init ******************************************************************************/ static void __init vpac270_init(void) @@ -507,6 +556,7 @@ static void __init vpac270_init(void) vpac270_eth_init(); vpac270_ts_init(); vpac270_rtc_init(); + vpac270_ide_init(); } MACHINE_START(VPAC270, "Voipac PXA270") -- cgit v0.10.2 From aeec1346884688b86ac7f0f36fb30aba30b459d8 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 26 Apr 2010 23:23:48 +0200 Subject: [ARM] pxa/vpac270: remove TS_IRQ magic number The touchscreen GPIO IRQ was used as a magic number. Define it properly in the board header file. This is a simple cleanup patch. Signed-off-by: Marek Vasut Signed-off-by: Eric Miao diff --git a/arch/arm/mach-pxa/include/mach/vpac270.h b/arch/arm/mach-pxa/include/mach/vpac270.h index 0d82c47..7bfa3dd 100644 --- a/arch/arm/mach-pxa/include/mach/vpac270.h +++ b/arch/arm/mach-pxa/include/mach/vpac270.h @@ -37,4 +37,6 @@ #define GPIO36_VPAC270_IDE_IRQ 36 +#define GPIO113_VPAC270_TS_IRQ 113 + #endif diff --git a/arch/arm/mach-pxa/vpac270.c b/arch/arm/mach-pxa/vpac270.c index 6575b8f..a1b39c4 100644 --- a/arch/arm/mach-pxa/vpac270.c +++ b/arch/arm/mach-pxa/vpac270.c @@ -388,7 +388,7 @@ static pxa2xx_audio_ops_t vpac270_ac97_pdata = { }; static struct ucb1400_pdata vpac270_ucb1400_pdata = { - .irq = IRQ_GPIO(113), + .irq = IRQ_GPIO(GPIO113_VPAC270_TS_IRQ), }; static struct platform_device vpac270_ucb1400_device = { -- cgit v0.10.2 From bcc399bb491e0971d84aba593d79d3addf5d31ee Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 1 May 2010 06:54:36 +0200 Subject: [ARM] pxa/vpac270: add OneNAND support Signed-off-by: Marek Vasut Signed-off-by: Eric Miao diff --git a/arch/arm/mach-pxa/vpac270.c b/arch/arm/mach-pxa/vpac270.c index a1b39c4..46ad1b7 100644 --- a/arch/arm/mach-pxa/vpac270.c +++ b/arch/arm/mach-pxa/vpac270.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -149,7 +150,7 @@ static unsigned long vpac270_pin_config[] __initdata = { * NOR Flash ******************************************************************************/ #if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE) -static struct mtd_partition vpac270_partitions[] = { +static struct mtd_partition vpac270_nor_partitions[] = { { .name = "Flash", .offset = 0x00000000, @@ -160,8 +161,8 @@ static struct mtd_partition vpac270_partitions[] = { static struct physmap_flash_data vpac270_flash_data[] = { { .width = 2, /* bankwidth in bytes */ - .parts = vpac270_partitions, - .nr_parts = ARRAY_SIZE(vpac270_partitions) + .parts = vpac270_nor_partitions, + .nr_parts = ARRAY_SIZE(vpac270_nor_partitions) } }; @@ -189,6 +190,49 @@ static inline void vpac270_nor_init(void) {} #endif /****************************************************************************** + * OneNAND Flash + ******************************************************************************/ +#if defined(CONFIG_MTD_ONENAND) || defined(CONFIG_MTD_ONENAND_MODULE) +static struct mtd_partition vpac270_onenand_partitions[] = { + { + .name = "Flash", + .offset = 0x00000000, + .size = MTDPART_SIZ_FULL, + } +}; + +static struct onenand_platform_data vpac270_onenand_info = { + .parts = vpac270_onenand_partitions, + .nr_parts = ARRAY_SIZE(vpac270_onenand_partitions), +}; + +static struct resource vpac270_onenand_resources[] = { + [0] = { + .start = PXA_CS0_PHYS, + .end = PXA_CS0_PHYS + SZ_1M, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device vpac270_onenand = { + .name = "onenand-flash", + .id = -1, + .resource = vpac270_onenand_resources, + .num_resources = ARRAY_SIZE(vpac270_onenand_resources), + .dev = { + .platform_data = &vpac270_onenand_info, + }, +}; + +static void __init vpac270_onenand_init(void) +{ + platform_device_register(&vpac270_onenand); +} +#else +static void __init vpac270_onenand_init(void) {} +#endif + +/****************************************************************************** * SD/MMC card controller ******************************************************************************/ #if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE) @@ -549,6 +593,7 @@ static void __init vpac270_init(void) vpac270_lcd_init(); vpac270_mmc_init(); vpac270_nor_init(); + vpac270_onenand_init(); vpac270_leds_init(); vpac270_keys_init(); vpac270_uhc_init(); -- cgit v0.10.2 From fb25cb33096e2f86be5e45fecbc4d20eb66a9953 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 2 May 2010 06:10:25 +0200 Subject: [ARM] pxa/vpac270: fix now invalid bit of UP2OCR This patch removes write to UP2OCR[DMSTATE] (ex-UP2OCR_DPPUBE) which is invalid on PXA270C5 and later. Signed-off-by: Marek Vasut Signed-off-by: Eric Miao diff --git a/arch/arm/mach-pxa/vpac270.c b/arch/arm/mach-pxa/vpac270.c index 46ad1b7..0954c24 100644 --- a/arch/arm/mach-pxa/vpac270.c +++ b/arch/arm/mach-pxa/vpac270.c @@ -359,9 +359,9 @@ static struct platform_device vpac270_gpio_vbus = { static void vpac270_udc_command(int cmd) { if (cmd == PXA2XX_UDC_CMD_CONNECT) - UP2OCR |= UP2OCR_HXOE | UP2OCR_DPPUE | UP2OCR_DPPUBE; + UP2OCR = UP2OCR_HXOE | UP2OCR_DPPUE; else if (cmd == PXA2XX_UDC_CMD_DISCONNECT) - UP2OCR &= ~(UP2OCR_HXOE | UP2OCR_DPPUE | UP2OCR_DPPUBE); + UP2OCR = UP2OCR_HXOE; } static struct pxa2xx_udc_mach_info vpac270_udc_info __initdata = { -- cgit v0.10.2 From e66b6d8e86a67c637203684ab76ea760dccb10f9 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 26 Mar 2010 06:51:32 +0100 Subject: MAINTAINERS: New MAINTAINERS entries for Zipit Z2 and Voipac PXA270 Signed-off-by: Marek Vasut Signed-off-by: Eric Miao diff --git a/MAINTAINERS b/MAINTAINERS index d5b0b1b..aa02bf2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -994,6 +994,20 @@ W: http://www.arm.linux.org.uk/ S: Maintained F: arch/arm/vfp/ +ARM/VOIPAC PXA270 SUPPORT +M: Marek Vasut +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +S: Maintained +F: arch/arm/mach-pxa/vpac270.c +F: arch/arm/mach-pxa/include/mach-pxa/vpac270.h + +ARM/ZIPIT Z2 SUPPORT +M: Marek Vasut +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +S: Maintained +F: arch/arm/mach-pxa/z2.c +F: arch/arm/mach-pxa/include/mach-pxa/z2.h + ASC7621 HARDWARE MONITOR DRIVER M: George Joseph L: lm-sensors@lm-sensors.org -- cgit v0.10.2 From f97cab28b1895ecb0aa317cc785bb209f57fc1e8 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Wed, 14 Apr 2010 07:00:42 +0800 Subject: [ARM] pxa: make it clear by converting MMC 'delay_detect' to millisecond delay_detect in HZ is confusing, convert it to be millisecond based. And thus remove those unnecessary call to msecs_to_jiffies() at runtime for this field. Other constants are converted assuming HZ == 100, which are basically true for those platforms. The assignment in csb726.c was incorrect, and is fixed in this patch as a result. Signed-off-by: Eric Miao Acked-by: Robert Jarzmik Acked-by: Marc Zyngier Acked-by: Marek Vasut Acked-by: Mike Rapoport Acked-by: Daniel Mack diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c index be9dc7a..fdda6be 100644 --- a/arch/arm/mach-pxa/cm-x300.c +++ b/arch/arm/mach-pxa/cm-x300.c @@ -433,7 +433,7 @@ static inline void cm_x300_init_nand(void) {} #if defined(CONFIG_MMC) || defined(CONFIG_MMC_MODULE) static struct pxamci_platform_data cm_x300_mci_platform_data = { - .detect_delay = 20, + .detect_delay_ms = 200, .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, .gpio_card_detect = GPIO82_MMC_IRQ, .gpio_card_ro = GPIO85_MMC_WP, @@ -454,7 +454,7 @@ static void cm_x300_mci2_exit(struct device *dev, void *data) } static struct pxamci_platform_data cm_x300_mci2_platform_data = { - .detect_delay = 20, + .detect_delay_ms = 200, .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, .init = cm_x300_mci2_init, .exit = cm_x300_mci2_exit, diff --git a/arch/arm/mach-pxa/colibri-pxa3xx.c b/arch/arm/mach-pxa/colibri-pxa3xx.c index e6c0a22..199afa2 100644 --- a/arch/arm/mach-pxa/colibri-pxa3xx.c +++ b/arch/arm/mach-pxa/colibri-pxa3xx.c @@ -96,7 +96,7 @@ static void colibri_pxa3xx_mci_exit(struct device *dev, void *data) } static struct pxamci_platform_data colibri_pxa3xx_mci_platform_data = { - .detect_delay = 20, + .detect_delay_ms = 200, .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, .init = colibri_pxa3xx_mci_init, .exit = colibri_pxa3xx_mci_exit, diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index f8e2959..3d1dcb9 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -444,6 +444,7 @@ static struct platform_device corgiled_device = { * to give the card a chance to fully insert/eject. */ static struct pxamci_platform_data corgi_mci_platform_data = { + .detect_delay_ms = 250, .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, .gpio_card_detect = -1, .gpio_card_ro = CORGI_GPIO_nSD_WP, @@ -695,7 +696,6 @@ static void __init corgi_init(void) corgi_init_spi(); pxa_set_udc_info(&udc_info); - corgi_mci_platform_data.detect_delay = msecs_to_jiffies(250); pxa_set_mci_info(&corgi_mci_platform_data); pxa_set_ficp_info(&corgi_ficp_platform_data); pxa_set_i2c_info(NULL); diff --git a/arch/arm/mach-pxa/csb726.c b/arch/arm/mach-pxa/csb726.c index 88575b8..91fd4fe 100644 --- a/arch/arm/mach-pxa/csb726.c +++ b/arch/arm/mach-pxa/csb726.c @@ -125,18 +125,9 @@ static unsigned long csb726_pin_config[] = { GPIO118_I2C_SDA, }; -static struct pxamci_platform_data csb726_mci_data; - -static int csb726_mci_init(struct device *dev, - irq_handler_t detect, void *data) -{ - csb726_mci_data.detect_delay = msecs_to_jiffies(500); - return 0; -} - static struct pxamci_platform_data csb726_mci = { + .detect_delay_ms = 500, .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, - .init = csb726_mci_init, /* FIXME setpower */ .gpio_card_detect = CSB726_GPIO_MMC_DETECT, .gpio_card_ro = CSB726_GPIO_MMC_RO, diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c index aab04f3..0517c17 100644 --- a/arch/arm/mach-pxa/em-x270.c +++ b/arch/arm/mach-pxa/em-x270.c @@ -626,6 +626,7 @@ static int em_x270_mci_get_ro(struct device *dev) } static struct pxamci_platform_data em_x270_mci_platform_data = { + .detect_delay_ms = 250, .ocr_mask = MMC_VDD_20_21|MMC_VDD_21_22|MMC_VDD_22_23| MMC_VDD_24_25|MMC_VDD_25_26|MMC_VDD_26_27| MMC_VDD_27_28|MMC_VDD_28_29|MMC_VDD_29_30| @@ -643,7 +644,6 @@ static void __init em_x270_init_mmc(void) if (machine_is_em_x270()) em_x270_mci_platform_data.get_ro = em_x270_mci_get_ro; - em_x270_mci_platform_data.detect_delay = msecs_to_jiffies(250); pxa_set_mci_info(&em_x270_mci_platform_data); } #else diff --git a/arch/arm/mach-pxa/include/mach/mmc.h b/arch/arm/mach-pxa/include/mach/mmc.h index 02a69dc..9eb515b 100644 --- a/arch/arm/mach-pxa/include/mach/mmc.h +++ b/arch/arm/mach-pxa/include/mach/mmc.h @@ -9,7 +9,7 @@ struct mmc_host; struct pxamci_platform_data { unsigned int ocr_mask; /* available voltages */ - unsigned long detect_delay; /* delay in jiffies before detecting cards after interrupt */ + unsigned long detect_delay_ms; /* delay in millisecond before detecting cards after interrupt */ int (*init)(struct device *, irq_handler_t , void *); int (*get_ro)(struct device *); void (*setpower)(struct device *, unsigned int); diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c index be727ae..9b90461 100644 --- a/arch/arm/mach-pxa/littleton.c +++ b/arch/arm/mach-pxa/littleton.c @@ -271,7 +271,7 @@ static inline void littleton_init_keypad(void) {} #if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE) static struct pxamci_platform_data littleton_mci_platform_data = { - .detect_delay = 20, + .detect_delay_ms = 200, .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, .gpio_card_detect = GPIO_MMC1_CARD_DETECT, .gpio_card_ro = -1, diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c index 63d65a2..330c328 100644 --- a/arch/arm/mach-pxa/lubbock.c +++ b/arch/arm/mach-pxa/lubbock.c @@ -478,7 +478,7 @@ static void lubbock_mci_exit(struct device *dev, void *data) static struct pxamci_platform_data lubbock_mci_platform_data = { .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, - .detect_delay = 1, + .detect_delay_ms = 10, .init = lubbock_mci_init, .get_ro = lubbock_mci_get_ro, .exit = lubbock_mci_exit, diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c index 7a50ed8..d60db87 100644 --- a/arch/arm/mach-pxa/mioa701.c +++ b/arch/arm/mach-pxa/mioa701.c @@ -426,6 +426,7 @@ struct gpio_vbus_mach_info gpio_vbus_data = { * to give the card a chance to fully insert/eject. */ static struct pxamci_platform_data mioa701_mci_info = { + .detect_delay_ms = 250, .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, .gpio_card_detect = GPIO15_SDIO_INSERT, .gpio_card_ro = GPIO78_SDIO_RO, @@ -791,7 +792,6 @@ static void __init mioa701_machine_init(void) mio_gpio_request(ARRAY_AND_SIZE(global_gpios)); bootstrap_init(); set_pxa_fb_info(&mioa701_pxafb_info); - mioa701_mci_info.detect_delay = msecs_to_jiffies(250); pxa_set_mci_info(&mioa701_mci_info); pxa_set_keypad_info(&mioa701_keypad_info); wm97xx_bat_set_pdata(&mioa701_battery_data); diff --git a/arch/arm/mach-pxa/mxm8x10.c b/arch/arm/mach-pxa/mxm8x10.c index 8c9c6f0..462167a 100644 --- a/arch/arm/mach-pxa/mxm8x10.c +++ b/arch/arm/mach-pxa/mxm8x10.c @@ -325,7 +325,7 @@ static mfp_cfg_t mfp_cfg[] __initdata = { #if defined(CONFIG_MMC) static struct pxamci_platform_data mxm_8x10_mci_platform_data = { .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, - .detect_delay = 1, + .detect_delay_ms = 10, .gpio_card_detect = MXM_8X10_SD_nCD, .gpio_card_ro = MXM_8X10_SD_WP, .gpio_power = -1 diff --git a/arch/arm/mach-pxa/palmld.c b/arch/arm/mach-pxa/palmld.c index f70c75b..1963819 100644 --- a/arch/arm/mach-pxa/palmld.c +++ b/arch/arm/mach-pxa/palmld.c @@ -168,7 +168,7 @@ static struct pxamci_platform_data palmld_mci_platform_data = { .gpio_card_detect = GPIO_NR_PALMLD_SD_DETECT_N, .gpio_card_ro = GPIO_NR_PALMLD_SD_READONLY, .gpio_power = GPIO_NR_PALMLD_SD_POWER, - .detect_delay = 20, + .detect_delay_ms = 200, }; /****************************************************************************** diff --git a/arch/arm/mach-pxa/palmt5.c b/arch/arm/mach-pxa/palmt5.c index d902a81..5305a39 100644 --- a/arch/arm/mach-pxa/palmt5.c +++ b/arch/arm/mach-pxa/palmt5.c @@ -110,7 +110,7 @@ static struct pxamci_platform_data palmt5_mci_platform_data = { .gpio_card_detect = GPIO_NR_PALMT5_SD_DETECT_N, .gpio_card_ro = GPIO_NR_PALMT5_SD_READONLY, .gpio_power = GPIO_NR_PALMT5_SD_POWER, - .detect_delay = 20, + .detect_delay_ms = 200, }; /****************************************************************************** diff --git a/arch/arm/mach-pxa/palmtc.c b/arch/arm/mach-pxa/palmtc.c index 717d7a6..033b567 100644 --- a/arch/arm/mach-pxa/palmtc.c +++ b/arch/arm/mach-pxa/palmtc.c @@ -121,7 +121,7 @@ static struct pxamci_platform_data palmtc_mci_platform_data = { .gpio_power = GPIO_NR_PALMTC_SD_POWER, .gpio_card_ro = GPIO_NR_PALMTC_SD_READONLY, .gpio_card_detect = GPIO_NR_PALMTC_SD_DETECT_N, - .detect_delay = 20, + .detect_delay_ms = 200, }; /****************************************************************************** diff --git a/arch/arm/mach-pxa/palmtx.c b/arch/arm/mach-pxa/palmtx.c index 007b58c..ecc1a40 100644 --- a/arch/arm/mach-pxa/palmtx.c +++ b/arch/arm/mach-pxa/palmtx.c @@ -170,7 +170,7 @@ static struct pxamci_platform_data palmtx_mci_platform_data = { .gpio_card_detect = GPIO_NR_PALMTX_SD_DETECT_N, .gpio_card_ro = GPIO_NR_PALMTX_SD_READONLY, .gpio_power = GPIO_NR_PALMTX_SD_POWER, - .detect_delay = 20, + .detect_delay_ms = 200, }; /****************************************************************************** diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c index 9d0ecea1..f56ae10 100644 --- a/arch/arm/mach-pxa/pcm990-baseboard.c +++ b/arch/arm/mach-pxa/pcm990-baseboard.c @@ -326,7 +326,7 @@ static void pcm990_mci_exit(struct device *dev, void *data) #define MSECS_PER_JIFFY (1000/HZ) static struct pxamci_platform_data pcm990_mci_platform_data = { - .detect_delay = 250 / MSECS_PER_JIFFY, + .detect_delay_ms = 250, .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, .init = pcm990_mci_init, .setpower = pcm990_mci_setpower, diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c index dcb1788..f4abdaa 100644 --- a/arch/arm/mach-pxa/poodle.c +++ b/arch/arm/mach-pxa/poodle.c @@ -276,6 +276,7 @@ static void poodle_mci_exit(struct device *dev, void *data) } static struct pxamci_platform_data poodle_mci_platform_data = { + .detect_delay_ms = 250, .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, .init = poodle_mci_init, .setpower = poodle_mci_setpower, @@ -449,7 +450,6 @@ static void __init poodle_init(void) set_pxa_fb_parent(&poodle_locomo_device.dev); set_pxa_fb_info(&poodle_fb_info); pxa_set_udc_info(&udc_info); - poodle_mci_platform_data.detect_delay = msecs_to_jiffies(250); pxa_set_mci_info(&poodle_mci_platform_data); pxa_set_ficp_info(&poodle_ficp_platform_data); pxa_set_i2c_info(NULL); diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c index d12667b..d4b61b3 100644 --- a/arch/arm/mach-pxa/raumfeld.c +++ b/arch/arm/mach-pxa/raumfeld.c @@ -714,7 +714,7 @@ static void raumfeld_mci_exit(struct device *dev, void *data) static struct pxamci_platform_data raumfeld_mci_platform_data = { .init = raumfeld_mci_init, .exit = raumfeld_mci_exit, - .detect_delay = 20, + .detect_delay_ms = 200, .gpio_card_detect = -1, .gpio_card_ro = -1, .gpio_power = -1, diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 451029e..4d2413e 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -539,6 +539,7 @@ static void spitz_mci_setpower(struct device *dev, unsigned int vdd) } static struct pxamci_platform_data spitz_mci_platform_data = { + .detect_delay_ms = 250, .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, .setpower = spitz_mci_setpower, .gpio_card_detect = SPITZ_GPIO_nSD_DETECT, @@ -759,7 +760,6 @@ static void __init common_init(void) spitz_init_spi(); platform_add_devices(devices, ARRAY_SIZE(devices)); - spitz_mci_platform_data.detect_delay = msecs_to_jiffies(250); pxa_set_mci_info(&spitz_mci_platform_data); pxa_set_ohci_info(&spitz_ohci_platform_data); pxa_set_ficp_info(&spitz_ficp_platform_data); diff --git a/arch/arm/mach-pxa/stargate2.c b/arch/arm/mach-pxa/stargate2.c index 2041eb1..af40d2a 100644 --- a/arch/arm/mach-pxa/stargate2.c +++ b/arch/arm/mach-pxa/stargate2.c @@ -464,8 +464,6 @@ static struct platform_device smc91x_device = { -static struct pxamci_platform_data stargate2_mci_platform_data; - /* * The card detect interrupt isn't debounced so we delay it by 250ms * to give the card a chance to fully insert / eject. @@ -489,8 +487,6 @@ static int stargate2_mci_init(struct device *dev, goto free_power_en; } gpio_direction_input(SG2_GPIO_nSD_DETECT); - /* Delay to allow for full insertion */ - stargate2_mci_platform_data.detect_delay = msecs_to_jiffies(250); err = request_irq(IRQ_GPIO(SG2_GPIO_nSD_DETECT), stargate2_detect_int, @@ -529,6 +525,7 @@ static void stargate2_mci_exit(struct device *dev, void *data) } static struct pxamci_platform_data stargate2_mci_platform_data = { + .detect_delay_ms = 250, .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, .init = stargate2_mci_init, .setpower = stargate2_mci_setpower, diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index ad552791..7512b82 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -275,6 +275,7 @@ static void tosa_mci_exit(struct device *dev, void *data) } static struct pxamci_platform_data tosa_mci_platform_data = { + .detect_delay_ms = 250, .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, .init = tosa_mci_init, .exit = tosa_mci_exit, @@ -926,7 +927,6 @@ static void __init tosa_init(void) dummy = gpiochip_reserve(TOSA_SCOOP_JC_GPIO_BASE, 12); dummy = gpiochip_reserve(TOSA_TC6393XB_GPIO_BASE, 16); - tosa_mci_platform_data.detect_delay = msecs_to_jiffies(250); pxa_set_mci_info(&tosa_mci_platform_data); pxa_set_udc_info(&udc_info); pxa_set_ficp_info(&tosa_ficp_platform_data); diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c index 797f254..6968911 100644 --- a/arch/arm/mach-pxa/trizeps4.c +++ b/arch/arm/mach-pxa/trizeps4.c @@ -349,7 +349,7 @@ static void trizeps4_mci_exit(struct device *dev, void *data) static struct pxamci_platform_data trizeps4_mci_platform_data = { .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, - .detect_delay = 1, + .detect_delay_ms= 10, .init = trizeps4_mci_init, .exit = trizeps4_mci_exit, .get_ro = NULL, /* write-protection not supported */ diff --git a/arch/arm/mach-pxa/vpac270.c b/arch/arm/mach-pxa/vpac270.c index 0954c24..9884fa9 100644 --- a/arch/arm/mach-pxa/vpac270.c +++ b/arch/arm/mach-pxa/vpac270.c @@ -240,7 +240,7 @@ static struct pxamci_platform_data vpac270_mci_platform_data = { .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, .gpio_card_detect = GPIO53_VPAC270_SD_DETECT_N, .gpio_card_ro = GPIO52_VPAC270_SD_READONLY, - .detect_delay = 20, + .detect_delay_ms = 200, }; static void __init vpac270_mmc_init(void) diff --git a/arch/arm/mach-pxa/z2.c b/arch/arm/mach-pxa/z2.c index c837318..f5d1ae3 100644 --- a/arch/arm/mach-pxa/z2.c +++ b/arch/arm/mach-pxa/z2.c @@ -291,7 +291,7 @@ static struct pxamci_platform_data z2_mci_platform_data = { .gpio_card_detect = GPIO96_ZIPITZ2_SD_DETECT, .gpio_power = -1, .gpio_card_ro = -1, - .detect_delay = 20, + .detect_delay_ms = 200, }; static void __init z2_mmc_init(void) diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c index 39896d8..3680f6a 100644 --- a/arch/arm/mach-pxa/zeus.c +++ b/arch/arm/mach-pxa/zeus.c @@ -644,7 +644,7 @@ static struct pxafb_mach_info zeus_fb_info = { static struct pxamci_platform_data zeus_mci_platform_data = { .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, - .detect_delay = HZ/4, + .detect_delay_ms = 250, .gpio_card_detect = ZEUS_MMC_CD_GPIO, .gpio_card_ro = ZEUS_MMC_WP_GPIO, .gpio_card_ro_invert = 1, diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c index 2b4043c..c479cbe 100644 --- a/arch/arm/mach-pxa/zylonite.c +++ b/arch/arm/mach-pxa/zylonite.c @@ -218,7 +218,7 @@ static inline void zylonite_init_lcd(void) {} #if defined(CONFIG_MMC) static struct pxamci_platform_data zylonite_mci_platform_data = { - .detect_delay = 20, + .detect_delay_ms= 200, .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, .gpio_card_detect = EXT_GPIO(0), .gpio_card_ro = EXT_GPIO(2), @@ -226,7 +226,7 @@ static struct pxamci_platform_data zylonite_mci_platform_data = { }; static struct pxamci_platform_data zylonite_mci2_platform_data = { - .detect_delay = 20, + .detect_delay_ms= 200, .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, .gpio_card_detect = EXT_GPIO(1), .gpio_card_ro = EXT_GPIO(3), @@ -234,7 +234,7 @@ static struct pxamci_platform_data zylonite_mci2_platform_data = { }; static struct pxamci_platform_data zylonite_mci3_platform_data = { - .detect_delay = 20, + .detect_delay_ms= 200, .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, .gpio_card_detect = EXT_GPIO(30), .gpio_card_ro = EXT_GPIO(31), diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index 0ed4895..e4f00e7 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c @@ -544,7 +544,7 @@ static irqreturn_t pxamci_detect_irq(int irq, void *devid) { struct pxamci_host *host = mmc_priv(devid); - mmc_detect_change(devid, host->pdata->detect_delay); + mmc_detect_change(devid, msecs_to_jiffies(host->pdata->detect_delay_ms)); return IRQ_HANDLED; } -- cgit v0.10.2 From e598863690d956ad4e18904bb5b6c63fea1ad255 Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Wed, 28 Apr 2010 10:48:24 -0400 Subject: [ARM] mmp: update clock register function Use clk_add_table in order to sync with clock driver. Signed-off-by: Haojian Zhuang Signed-off-by: Eric Miao diff --git a/arch/arm/mach-mmp/mmp2.c b/arch/arm/mach-mmp/mmp2.c index 72eb9da..cca3992 100644 --- a/arch/arm/mach-mmp/mmp2.c +++ b/arch/arm/mach-mmp/mmp2.c @@ -101,7 +101,7 @@ static int __init mmp2_init(void) if (cpu_is_mmp2()) { mfp_init_base(MFPR_VIRT_BASE); mfp_init_addr(mmp2_addr_map); - clks_register(ARRAY_AND_SIZE(mmp2_clkregs)); + clkdev_add_table(ARRAY_AND_SIZE(mmp2_clkregs)); } return 0; -- cgit v0.10.2 From 66b196475031c748a5861390a4fadb915e14ccdc Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Wed, 28 Apr 2010 10:59:45 -0400 Subject: [ARM] mmp: enable L2 in mmp2 Enable Tauros2 L2 in mmp2. Tauros2 L2 is shared in Marvell ARM cores. Signed-off-by: Haojian Zhuang Signed-off-by: Eric Miao diff --git a/arch/arm/configs/mmp2_defconfig b/arch/arm/configs/mmp2_defconfig index 03f76cf..db89363 100644 --- a/arch/arm/configs/mmp2_defconfig +++ b/arch/arm/configs/mmp2_defconfig @@ -246,6 +246,8 @@ CONFIG_ARM_THUMB=y # CONFIG_CPU_ICACHE_DISABLE is not set # CONFIG_CPU_DCACHE_DISABLE is not set # CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_OUTER_CACHE=y +CONFIG_CACHE_TAUROS2=y CONFIG_ARM_L1_CACHE_SHIFT=5 # CONFIG_ARM_ERRATA_411920 is not set CONFIG_COMMON_CLKDEV=y diff --git a/arch/arm/mach-mmp/mmp2.c b/arch/arm/mach-mmp/mmp2.c index cca3992..e236ec0 100644 --- a/arch/arm/mach-mmp/mmp2.c +++ b/arch/arm/mach-mmp/mmp2.c @@ -15,6 +15,8 @@ #include #include +#include + #include #include #include @@ -99,6 +101,9 @@ static struct clk_lookup mmp2_clkregs[] = { static int __init mmp2_init(void) { if (cpu_is_mmp2()) { +#ifdef CONFIG_CACHE_TAUROS2 + tauros2_init(); +#endif mfp_init_base(MFPR_VIRT_BASE); mfp_init_addr(mmp2_addr_map); clkdev_add_table(ARRAY_AND_SIZE(mmp2_clkregs)); diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 5bd7c89..6989126 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -769,7 +769,7 @@ config CACHE_L2X0 config CACHE_TAUROS2 bool "Enable the Tauros2 L2 cache controller" - depends on ARCH_DOVE + depends on (ARCH_DOVE || ARCH_MMP) default y select OUTER_CACHE help -- cgit v0.10.2 From d24123bfae56aef5a38a7c89fd588f1bd7584751 Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Wed, 28 Apr 2010 11:32:30 -0400 Subject: [ARM] mmp: update mmp2 defconfig Enable MAX8649 & MAX8925 regulator, dynamic debug, Marvell Jasper platform. Disable DNOTIFY, MAX8660 regulator, 88pm860x PMIC. Signed-off-by: Haojian Zhuang Signed-off-by: Eric Miao diff --git a/arch/arm/configs/mmp2_defconfig b/arch/arm/configs/mmp2_defconfig index db89363..4b55dcb 100644 --- a/arch/arm/configs/mmp2_defconfig +++ b/arch/arm/configs/mmp2_defconfig @@ -1,13 +1,14 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Tue Jan 5 13:55:22 2010 +# Linux kernel version: 2.6.34-rc5 +# Wed Apr 28 11:23:19 2010 # CONFIG_ARM=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y CONFIG_GENERIC_GPIO=y CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_HAVE_PROC_CPU=y CONFIG_GENERIC_HARDIRQS=y CONFIG_STACKTRACE_SUPPORT=y CONFIG_HAVE_LATENCYTOP_SUPPORT=y @@ -18,6 +19,7 @@ CONFIG_GENERIC_IRQ_PROBE=y CONFIG_RWSEM_GENERIC_SPINLOCK=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y CONFIG_VECTORS_BASE=0xffff0000 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" @@ -32,6 +34,12 @@ CONFIG_LOCK_KERNEL=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_LOCALVERSION="" CONFIG_LOCALVERSION_AUTO=y +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_BZIP2 is not set +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -52,7 +60,6 @@ CONFIG_RCU_FANOUT=32 # CONFIG_TREE_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -85,10 +92,14 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_AIO=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y # # Kernel Performance Events And Counters # +# CONFIG_PERF_EVENTS is not set +# CONFIG_PERF_COUNTERS is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_COMPAT_BRK=y CONFIG_SLAB=y @@ -104,6 +115,7 @@ CONFIG_HAVE_CLK=y # # GCOV-based kernel profiling # +# CONFIG_GCOV_KERNEL is not set # CONFIG_SLOW_WORK is not set CONFIG_HAVE_GENERIC_DMA_COHERENT=y CONFIG_SLABINFO=y @@ -170,6 +182,7 @@ CONFIG_MMU=y # CONFIG_ARCH_REALVIEW is not set # CONFIG_ARCH_VERSATILE is not set # CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_BCMRING is not set # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_GEMINI is not set # CONFIG_ARCH_EBSA110 is not set @@ -179,7 +192,6 @@ CONFIG_MMU=y # CONFIG_ARCH_STMP3XXX is not set # CONFIG_ARCH_NETX is not set # CONFIG_ARCH_H720X is not set -# CONFIG_ARCH_NOMADIK is not set # CONFIG_ARCH_IOP13XX is not set # CONFIG_ARCH_IOP32X is not set # CONFIG_ARCH_IOP33X is not set @@ -196,21 +208,26 @@ CONFIG_ARCH_MMP=y # CONFIG_ARCH_KS8695 is not set # CONFIG_ARCH_NS9XXX is not set # CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_NUC93X is not set # CONFIG_ARCH_PNX4008 is not set # CONFIG_ARCH_PXA is not set # CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_SHMOBILE is not set # CONFIG_ARCH_RPC is not set # CONFIG_ARCH_SA1100 is not set # CONFIG_ARCH_S3C2410 is not set # CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5P6440 is not set +# CONFIG_ARCH_S5P6442 is not set # CONFIG_ARCH_S5PC1XX is not set +# CONFIG_ARCH_S5PV210 is not set # CONFIG_ARCH_SHARK is not set # CONFIG_ARCH_LH7A40X is not set # CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_U8500 is not set +# CONFIG_ARCH_NOMADIK is not set # CONFIG_ARCH_DAVINCI is not set # CONFIG_ARCH_OMAP is not set -# CONFIG_ARCH_BCMRING is not set -# CONFIG_ARCH_U8500 is not set # CONFIG_MACH_TAVOREVB is not set # @@ -218,8 +235,10 @@ CONFIG_ARCH_MMP=y # # CONFIG_MACH_ASPENITE is not set # CONFIG_MACH_ZYLONITE2 is not set +# CONFIG_MACH_AVENGERS_LITE is not set # CONFIG_MACH_TTC_DKB is not set CONFIG_MACH_FLINT=y +CONFIG_MACH_MARVELL_JASPER=y CONFIG_CPU_MMP2=y CONFIG_PLAT_PXA=y @@ -249,6 +268,7 @@ CONFIG_ARM_THUMB=y CONFIG_OUTER_CACHE=y CONFIG_CACHE_TAUROS2=y CONFIG_ARM_L1_CACHE_SHIFT=5 +CONFIG_CPU_HAS_PMU=y # CONFIG_ARM_ERRATA_411920 is not set CONFIG_COMMON_CLKDEV=y @@ -300,7 +320,7 @@ CONFIG_ALIGNMENT_TRAP=y # CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_CMDLINE="root=/dev/nfs rootfstype=nfs nfsroot=192.168.1.100:/nfsroot/ ip=192.168.1.101:192.168.1.100::255.255.255.0::eth0:on console=ttyS0,115200 mem=128M user_debug=255" +CONFIG_CMDLINE="root=/dev/nfs rootfstype=nfs nfsroot=192.168.1.100:/nfsroot/ ip=192.168.1.101:192.168.1.100::255.255.255.0::eth0:on console=ttyS2,38400 mem=128M user_debug=255" # CONFIG_XIP_KERNEL is not set # CONFIG_KEXEC is not set @@ -340,7 +360,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -534,6 +553,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set # CONFIG_SCSI_DMA is not set @@ -642,6 +662,7 @@ CONFIG_SERIAL_PXA=y CONFIG_SERIAL_PXA_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set # CONFIG_LEGACY_PTYS is not set @@ -669,6 +690,7 @@ CONFIG_I2C_HELPER_AUTO=y CONFIG_I2C_PXA=y # CONFIG_I2C_PXA_SLAVE is not set # CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set # # External I2C/SMBus adapter drivers @@ -681,15 +703,9 @@ CONFIG_I2C_PXA=y # # CONFIG_I2C_PCA_PLATFORM is not set # CONFIG_I2C_STUB is not set - -# -# Miscellaneous I2C Chip support -# -# CONFIG_SENSORS_TSL2550 is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set # CONFIG_SPI is not set # @@ -704,13 +720,16 @@ CONFIG_GPIOLIB=y # # Memory mapped GPIO expanders: # +# CONFIG_GPIO_IT8761E is not set # # I2C GPIO expanders: # +# CONFIG_GPIO_MAX7300 is not set # CONFIG_GPIO_MAX732X is not set # CONFIG_GPIO_PCA953X is not set # CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_ADP5588 is not set # # PCI GPIO expanders: @@ -739,10 +758,12 @@ CONFIG_SSB_POSSIBLE=y # Multifunction device drivers # CONFIG_MFD_CORE=y +# CONFIG_MFD_88PM860X is not set # CONFIG_MFD_SM501 is not set # CONFIG_MFD_ASIC3 is not set # CONFIG_HTC_EGPIO is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set # CONFIG_TPS65010 is not set # CONFIG_TWL4030_CORE is not set # CONFIG_MFD_TMIO is not set @@ -751,24 +772,27 @@ CONFIG_MFD_CORE=y # CONFIG_MFD_TC6393XB is not set # CONFIG_PMIC_DA903X is not set # CONFIG_PMIC_ADP5520 is not set +CONFIG_MFD_MAX8925=y # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X is not set # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set # CONFIG_MFD_PCF50633 is not set # CONFIG_AB3100_CORE is not set -CONFIG_MFD_88PM8607=y CONFIG_REGULATOR=y # CONFIG_REGULATOR_DEBUG is not set +# CONFIG_REGULATOR_DUMMY is not set # CONFIG_REGULATOR_FIXED_VOLTAGE is not set # CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set # CONFIG_REGULATOR_USERSPACE_CONSUMER is not set # CONFIG_REGULATOR_BQ24022 is not set # CONFIG_REGULATOR_MAX1586 is not set -CONFIG_REGULATOR_MAX8660=y +CONFIG_REGULATOR_MAX8649=y +# CONFIG_REGULATOR_MAX8660 is not set +CONFIG_REGULATOR_MAX8925=y # CONFIG_REGULATOR_LP3971 is not set # CONFIG_REGULATOR_TPS65023 is not set # CONFIG_REGULATOR_TPS6507X is not set -CONFIG_REGULATOR_88PM8607=y # CONFIG_MEDIA_SUPPORT is not set # @@ -783,6 +807,7 @@ CONFIG_LCD_CLASS_DEVICE=y # CONFIG_LCD_PLATFORM is not set CONFIG_BACKLIGHT_CLASS_DEVICE=y CONFIG_BACKLIGHT_GENERIC=y +CONFIG_BACKLIGHT_MAX8925=y # # Display device support @@ -823,6 +848,7 @@ CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_DRV_DS1374 is not set # CONFIG_RTC_DRV_DS1672 is not set # CONFIG_RTC_DRV_MAX6900 is not set +CONFIG_RTC_DRV_MAX8925=y # CONFIG_RTC_DRV_RS5C372 is not set # CONFIG_RTC_DRV_ISL1208 is not set # CONFIG_RTC_DRV_X1205 is not set @@ -874,7 +900,6 @@ CONFIG_RTC_INTF_DEV=y # CONFIG_EXT2_FS is not set # CONFIG_EXT3_FS is not set # CONFIG_EXT4_FS is not set -CONFIG_EXT4_USE_FOR_EXT23=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set CONFIG_FS_POSIX_ACL=y @@ -885,7 +910,7 @@ CONFIG_FS_POSIX_ACL=y # CONFIG_NILFS2_FS is not set CONFIG_FILE_LOCKING=y CONFIG_FSNOTIFY=y -CONFIG_DNOTIFY=y +# CONFIG_DNOTIFY is not set CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set @@ -942,6 +967,7 @@ CONFIG_JFFS2_ZLIB=y # CONFIG_JFFS2_LZO is not set CONFIG_JFFS2_RTIME=y # CONFIG_JFFS2_RUBIN is not set +# CONFIG_LOGFS is not set CONFIG_CRAMFS=y # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -969,6 +995,7 @@ CONFIG_SUNRPC_GSS=y CONFIG_RPCSEC_GSS_KRB5=y # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -992,7 +1019,7 @@ CONFIG_FRAME_WARN=1024 CONFIG_MAGIC_SYSRQ=y # CONFIG_STRIP_ASM_SYMS is not set # CONFIG_UNUSED_SYMBOLS is not set -# CONFIG_DEBUG_FS is not set +CONFIG_DEBUG_FS=y # CONFIG_HEADERS_CHECK is not set CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_SHIRQ is not set @@ -1034,6 +1061,7 @@ CONFIG_DEBUG_MEMORY_INIT=y # CONFIG_BACKTRACE_SELF_TEST is not set # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_LKDTM is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set # CONFIG_SYSCTL_SYSCALL_CHECK is not set @@ -1054,6 +1082,7 @@ CONFIG_BRANCH_PROFILE_NONE=y # CONFIG_KMEMTRACE is not set # CONFIG_WORKQUEUE_TRACER is not set # CONFIG_BLK_DEV_IO_TRACE is not set +CONFIG_DYNAMIC_DEBUG=y # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set @@ -1061,9 +1090,7 @@ CONFIG_ARM_UNWIND=y CONFIG_DEBUG_USER=y CONFIG_DEBUG_ERRORS=y # CONFIG_DEBUG_STACK_USAGE is not set -CONFIG_DEBUG_LL=y -# CONFIG_EARLY_PRINTK is not set -# CONFIG_DEBUG_ICEDCC is not set +# CONFIG_DEBUG_LL is not set # CONFIG_OC_ETM is not set # -- cgit v0.10.2 From 55d3936d30affccb904f9294a3076ccb7bf09688 Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Wed, 28 Apr 2010 11:43:00 -0400 Subject: [ARM] mmp: configure gpio pins from 128 to 192 In mmp2, 6 banks of GPIO registers are supported. So we can support 192 GPIO pins at most. Signed-off-by: Haojian Zhuang Signed-off-by: Eric Miao diff --git a/arch/arm/mach-mmp/include/mach/gpio.h b/arch/arm/mach-mmp/include/mach/gpio.h index ab26d13..ee8b02e 100644 --- a/arch/arm/mach-mmp/include/mach/gpio.h +++ b/arch/arm/mach-mmp/include/mach/gpio.h @@ -10,7 +10,7 @@ #define BANK_OFF(n) (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2)) #define GPIO_REG(x) (*((volatile u32 *)(GPIO_REGS_VIRT + (x)))) -#define NR_BUILTIN_GPIO (128) +#define NR_BUILTIN_GPIO (192) #define gpio_to_bank(gpio) ((gpio) >> 5) #define gpio_to_irq(gpio) (IRQ_GPIO_START + (gpio)) -- cgit v0.10.2 From 8ae84427bb05c2921dcb0200b161b904028b5784 Mon Sep 17 00:00:00 2001 From: Mingliang Hu Date: Mon, 12 Apr 2010 17:55:21 +0800 Subject: [ARM] mmp: fix clock tick rate in mmp2 In MMP2, clock tick rate should be 6500000. Signed-off-by: Mingliang Hu Signed-off-by: Haojian Zhuang Signed-off-by: Eric Miao diff --git a/arch/arm/mach-mmp/include/mach/timex.h b/arch/arm/mach-mmp/include/mach/timex.h index 6cebbd0..70c9f1d 100644 --- a/arch/arm/mach-mmp/include/mach/timex.h +++ b/arch/arm/mach-mmp/include/mach/timex.h @@ -6,4 +6,8 @@ * published by the Free Software Foundation. */ +#ifdef CONFIG_CPU_MMP2 +#define CLOCK_TICK_RATE 6500000 +#else #define CLOCK_TICK_RATE 3250000 +#endif -- cgit v0.10.2 From 7f39403c56b01a8c023e8eb9ebe89007cdc4f4e6 Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Wed, 28 Apr 2010 15:18:59 -0400 Subject: [ARM] mmp: update mfp setting Update mfp setting for mmp2. Signed-off-by: Haojian Zhuang Signed-off-by: Eric Miao diff --git a/arch/arm/mach-mmp/include/mach/mfp-mmp2.h b/arch/arm/mach-mmp/include/mach/mfp-mmp2.h index 9f9f814..761c2da 100644 --- a/arch/arm/mach-mmp/include/mach/mfp-mmp2.h +++ b/arch/arm/mach-mmp/include/mach/mfp-mmp2.h @@ -9,6 +9,175 @@ #define MFP_DRIVE_FAST (0x8 << 13) /* GPIO */ +#define GPIO0_GPIO0 MFP_CFG(GPIO0, AF0) +#define GPIO1_GPIO1 MFP_CFG(GPIO1, AF0) +#define GPIO2_GPIO2 MFP_CFG(GPIO2, AF0) +#define GPIO3_GPIO3 MFP_CFG(GPIO3, AF0) +#define GPIO4_GPIO4 MFP_CFG(GPIO4, AF0) +#define GPIO5_GPIO5 MFP_CFG(GPIO5, AF0) +#define GPIO6_GPIO6 MFP_CFG(GPIO6, AF0) +#define GPIO7_GPIO7 MFP_CFG(GPIO7, AF0) +#define GPIO8_GPIO8 MFP_CFG(GPIO8, AF0) +#define GPIO9_GPIO9 MFP_CFG(GPIO9, AF0) +#define GPIO10_GPIO10 MFP_CFG(GPIO10, AF0) +#define GPIO11_GPIO11 MFP_CFG(GPIO11, AF0) +#define GPIO12_GPIO12 MFP_CFG(GPIO12, AF0) +#define GPIO13_GPIO13 MFP_CFG(GPIO13, AF0) +#define GPIO14_GPIO14 MFP_CFG(GPIO14, AF0) +#define GPIO15_GPIO15 MFP_CFG(GPIO15, AF0) +#define GPIO16_GPIO16 MFP_CFG(GPIO16, AF0) +#define GPIO17_GPIO17 MFP_CFG(GPIO17, AF0) +#define GPIO18_GPIO18 MFP_CFG(GPIO18, AF0) +#define GPIO19_GPIO19 MFP_CFG(GPIO19, AF0) +#define GPIO20_GPIO20 MFP_CFG(GPIO20, AF0) +#define GPIO21_GPIO21 MFP_CFG(GPIO21, AF0) +#define GPIO22_GPIO22 MFP_CFG(GPIO22, AF0) +#define GPIO23_GPIO23 MFP_CFG(GPIO23, AF0) +#define GPIO24_GPIO24 MFP_CFG(GPIO24, AF0) +#define GPIO25_GPIO25 MFP_CFG(GPIO25, AF0) +#define GPIO26_GPIO26 MFP_CFG(GPIO26, AF0) +#define GPIO27_GPIO27 MFP_CFG(GPIO27, AF0) +#define GPIO28_GPIO28 MFP_CFG(GPIO28, AF0) +#define GPIO29_GPIO29 MFP_CFG(GPIO29, AF0) +#define GPIO30_GPIO30 MFP_CFG(GPIO30, AF0) +#define GPIO31_GPIO31 MFP_CFG(GPIO31, AF0) +#define GPIO32_GPIO32 MFP_CFG(GPIO32, AF0) +#define GPIO33_GPIO33 MFP_CFG(GPIO33, AF0) +#define GPIO34_GPIO34 MFP_CFG(GPIO34, AF0) +#define GPIO35_GPIO35 MFP_CFG(GPIO35, AF0) +#define GPIO36_GPIO36 MFP_CFG(GPIO36, AF0) +#define GPIO37_GPIO37 MFP_CFG(GPIO37, AF0) +#define GPIO38_GPIO38 MFP_CFG(GPIO38, AF0) +#define GPIO39_GPIO39 MFP_CFG(GPIO39, AF0) +#define GPIO40_GPIO40 MFP_CFG(GPIO40, AF0) +#define GPIO41_GPIO41 MFP_CFG(GPIO41, AF0) +#define GPIO42_GPIO42 MFP_CFG(GPIO42, AF0) +#define GPIO43_GPIO43 MFP_CFG(GPIO43, AF0) +#define GPIO44_GPIO44 MFP_CFG(GPIO44, AF0) +#define GPIO45_GPIO45 MFP_CFG(GPIO45, AF0) +#define GPIO46_GPIO46 MFP_CFG(GPIO46, AF0) +#define GPIO47_GPIO47 MFP_CFG(GPIO47, AF0) +#define GPIO48_GPIO48 MFP_CFG(GPIO48, AF0) +#define GPIO49_GPIO49 MFP_CFG(GPIO49, AF0) +#define GPIO50_GPIO50 MFP_CFG(GPIO50, AF0) +#define GPIO51_GPIO51 MFP_CFG(GPIO51, AF0) +#define GPIO52_GPIO52 MFP_CFG(GPIO52, AF0) +#define GPIO53_GPIO53 MFP_CFG(GPIO53, AF0) +#define GPIO54_GPIO54 MFP_CFG(GPIO54, AF0) +#define GPIO55_GPIO55 MFP_CFG(GPIO55, AF0) +#define GPIO56_GPIO56 MFP_CFG(GPIO56, AF0) +#define GPIO57_GPIO57 MFP_CFG(GPIO57, AF0) +#define GPIO58_GPIO58 MFP_CFG(GPIO58, AF0) +#define GPIO59_GPIO59 MFP_CFG(GPIO59, AF0) +#define GPIO60_GPIO60 MFP_CFG(GPIO60, AF0) +#define GPIO61_GPIO61 MFP_CFG(GPIO61, AF0) +#define GPIO62_GPIO62 MFP_CFG(GPIO62, AF0) +#define GPIO63_GPIO63 MFP_CFG(GPIO63, AF0) +#define GPIO64_GPIO64 MFP_CFG(GPIO64, AF0) +#define GPIO65_GPIO65 MFP_CFG(GPIO65, AF0) +#define GPIO66_GPIO66 MFP_CFG(GPIO66, AF0) +#define GPIO67_GPIO67 MFP_CFG(GPIO67, AF0) +#define GPIO68_GPIO68 MFP_CFG(GPIO68, AF0) +#define GPIO69_GPIO69 MFP_CFG(GPIO69, AF0) +#define GPIO70_GPIO70 MFP_CFG(GPIO70, AF0) +#define GPIO71_GPIO71 MFP_CFG(GPIO71, AF0) +#define GPIO72_GPIO72 MFP_CFG(GPIO72, AF0) +#define GPIO73_GPIO73 MFP_CFG(GPIO73, AF0) +#define GPIO74_GPIO74 MFP_CFG(GPIO74, AF0) +#define GPIO75_GPIO75 MFP_CFG(GPIO75, AF0) +#define GPIO76_GPIO76 MFP_CFG(GPIO76, AF0) +#define GPIO77_GPIO77 MFP_CFG(GPIO77, AF0) +#define GPIO78_GPIO78 MFP_CFG(GPIO78, AF0) +#define GPIO79_GPIO79 MFP_CFG(GPIO79, AF0) +#define GPIO80_GPIO80 MFP_CFG(GPIO80, AF0) +#define GPIO81_GPIO81 MFP_CFG(GPIO81, AF0) +#define GPIO82_GPIO82 MFP_CFG(GPIO82, AF0) +#define GPIO83_GPIO83 MFP_CFG(GPIO83, AF0) +#define GPIO84_GPIO84 MFP_CFG(GPIO84, AF0) +#define GPIO85_GPIO85 MFP_CFG(GPIO85, AF0) +#define GPIO86_GPIO86 MFP_CFG(GPIO86, AF0) +#define GPIO87_GPIO87 MFP_CFG(GPIO87, AF0) +#define GPIO88_GPIO88 MFP_CFG(GPIO88, AF0) +#define GPIO89_GPIO89 MFP_CFG(GPIO89, AF0) +#define GPIO90_GPIO90 MFP_CFG(GPIO90, AF0) +#define GPIO91_GPIO91 MFP_CFG(GPIO91, AF0) +#define GPIO92_GPIO92 MFP_CFG(GPIO92, AF0) +#define GPIO93_GPIO93 MFP_CFG(GPIO93, AF0) +#define GPIO94_GPIO94 MFP_CFG(GPIO94, AF0) +#define GPIO95_GPIO95 MFP_CFG(GPIO95, AF0) +#define GPIO96_GPIO96 MFP_CFG(GPIO96, AF0) +#define GPIO97_GPIO97 MFP_CFG(GPIO97, AF0) +#define GPIO98_GPIO98 MFP_CFG(GPIO98, AF0) +#define GPIO99_GPIO99 MFP_CFG(GPIO99, AF0) +#define GPIO100_GPIO100 MFP_CFG(GPIO100, AF0) +#define GPIO101_GPIO101 MFP_CFG(GPIO101, AF0) +#define GPIO102_GPIO102 MFP_CFG(GPIO102, AF1) +#define GPIO103_GPIO103 MFP_CFG(GPIO103, AF1) +#define GPIO104_GPIO104 MFP_CFG(GPIO104, AF1) +#define GPIO105_GPIO105 MFP_CFG(GPIO105, AF1) +#define GPIO106_GPIO106 MFP_CFG(GPIO106, AF1) +#define GPIO107_GPIO107 MFP_CFG(GPIO107, AF1) +#define GPIO108_GPIO108 MFP_CFG(GPIO108, AF1) +#define GPIO109_GPIO109 MFP_CFG(GPIO109, AF1) +#define GPIO110_GPIO110 MFP_CFG(GPIO110, AF1) +#define GPIO111_GPIO111 MFP_CFG(GPIO111, AF1) +#define GPIO112_GPIO112 MFP_CFG(GPIO112, AF1) +#define GPIO113_GPIO113 MFP_CFG(GPIO113, AF1) +#define GPIO114_GPIO114 MFP_CFG(GPIO114, AF0) +#define GPIO115_GPIO115 MFP_CFG(GPIO115, AF0) +#define GPIO116_GPIO116 MFP_CFG(GPIO116, AF0) +#define GPIO117_GPIO117 MFP_CFG(GPIO117, AF0) +#define GPIO118_GPIO118 MFP_CFG(GPIO118, AF0) +#define GPIO119_GPIO119 MFP_CFG(GPIO119, AF0) +#define GPIO120_GPIO120 MFP_CFG(GPIO120, AF0) +#define GPIO121_GPIO121 MFP_CFG(GPIO121, AF0) +#define GPIO122_GPIO122 MFP_CFG(GPIO122, AF0) +#define GPIO123_GPIO123 MFP_CFG(GPIO123, AF0) +#define GPIO124_GPIO124 MFP_CFG(GPIO124, AF0) +#define GPIO125_GPIO125 MFP_CFG(GPIO125, AF0) +#define GPIO126_GPIO126 MFP_CFG(GPIO126, AF0) +#define GPIO127_GPIO127 MFP_CFG(GPIO127, AF0) +#define GPIO128_GPIO128 MFP_CFG(GPIO128, AF0) +#define GPIO129_GPIO129 MFP_CFG(GPIO129, AF0) +#define GPIO130_GPIO130 MFP_CFG(GPIO130, AF0) +#define GPIO131_GPIO131 MFP_CFG(GPIO131, AF0) +#define GPIO132_GPIO132 MFP_CFG(GPIO132, AF0) +#define GPIO133_GPIO133 MFP_CFG(GPIO133, AF0) +#define GPIO134_GPIO134 MFP_CFG(GPIO134, AF0) +#define GPIO135_GPIO135 MFP_CFG(GPIO135, AF0) +#define GPIO136_GPIO136 MFP_CFG(GPIO136, AF0) +#define GPIO137_GPIO137 MFP_CFG(GPIO137, AF0) +#define GPIO138_GPIO138 MFP_CFG(GPIO138, AF0) +#define GPIO139_GPIO139 MFP_CFG(GPIO139, AF0) +#define GPIO140_GPIO140 MFP_CFG(GPIO140, AF0) +#define GPIO141_GPIO141 MFP_CFG(GPIO141, AF0) +#define GPIO142_GPIO142 MFP_CFG(GPIO142, AF1) +#define GPIO143_GPIO143 MFP_CFG(GPIO143, AF1) +#define GPIO144_GPIO144 MFP_CFG(GPIO144, AF1) +#define GPIO145_GPIO145 MFP_CFG(GPIO145, AF1) +#define GPIO146_GPIO146 MFP_CFG(GPIO146, AF1) +#define GPIO147_GPIO147 MFP_CFG(GPIO147, AF1) +#define GPIO148_GPIO148 MFP_CFG(GPIO148, AF1) +#define GPIO149_GPIO149 MFP_CFG(GPIO149, AF1) +#define GPIO150_GPIO150 MFP_CFG(GPIO150, AF1) +#define GPIO151_GPIO151 MFP_CFG(GPIO151, AF1) +#define GPIO152_GPIO152 MFP_CFG(GPIO152, AF1) +#define GPIO153_GPIO153 MFP_CFG(GPIO153, AF1) +#define GPIO154_GPIO154 MFP_CFG(GPIO154, AF1) +#define GPIO155_GPIO155 MFP_CFG(GPIO155, AF1) +#define GPIO156_GPIO156 MFP_CFG(GPIO156, AF1) +#define GPIO157_GPIO157 MFP_CFG(GPIO157, AF1) +#define GPIO158_GPIO158 MFP_CFG(GPIO158, AF1) +#define GPIO159_GPIO159 MFP_CFG(GPIO159, AF1) +#define GPIO160_GPIO160 MFP_CFG(GPIO160, AF1) +#define GPIO161_GPIO161 MFP_CFG(GPIO161, AF1) +#define GPIO162_GPIO162 MFP_CFG(GPIO162, AF1) +#define GPIO163_GPIO163 MFP_CFG(GPIO163, AF1) +#define GPIO164_GPIO164 MFP_CFG(GPIO164, AF1) +#define GPIO165_GPIO165 MFP_CFG(GPIO165, AF1) +#define GPIO166_GPIO166 MFP_CFG(GPIO166, AF1) +#define GPIO167_GPIO167 MFP_CFG(GPIO167, AF1) +#define GPIO168_GPIO168 MFP_CFG(GPIO168, AF1) /* DFI */ #define GPIO108_DFI_D15 MFP_CFG(GPIO108, AF0) @@ -47,7 +216,6 @@ /* Ethernet */ #define GPIO155_SM_ADVMUX MFP_CFG(GPIO155, AF2) -#define GPIO155_GPIO155 MFP_CFG(GPIO155, AF1) /* UART1 */ #define GPIO45_UART1_RXD MFP_CFG(GPIO45, AF1) @@ -159,6 +327,8 @@ #define GPIO44_TWSI2_SDA MFP_CFG_DRV(GPIO44, AF1, SLOW) #define GPIO71_TWSI3_SCL MFP_CFG_DRV(GPIO71, AF1, SLOW) #define GPIO72_TWSI3_SDA MFP_CFG_DRV(GPIO72, AF1, SLOW) +#define TWSI4_SCL MFP_CFG_DRV(TWSI4_SCL, AF0, SLOW) +#define TWSI4_SDA MFP_CFG_DRV(TWSI4_SDA, AF0, SLOW) #define GPIO99_TWSI5_SCL MFP_CFG_DRV(GPIO99, AF4, SLOW) #define GPIO100_TWSI5_SDA MFP_CFG_DRV(GPIO100, AF4, SLOW) #define GPIO97_TWSI6_SCL MFP_CFG_DRV(GPIO97, AF2, SLOW) @@ -218,21 +388,6 @@ #define GPIO69_CAM_MCLK MFP_CFG_DRV(GPIO69, AF1, FAST) #define GPIO70_CAM_PCLK MFP_CFG_DRV(GPIO70, AF1, FAST) -/* Wifi */ -#define GPIO45_GPIO45 MFP_CFG(GPIO45, AF0) -#define GPIO46_GPIO46 MFP_CFG(GPIO46, AF0) -#define GPIO21_GPIO21 MFP_CFG(GPIO21, AF0) -#define GPIO22_GPIO22 MFP_CFG(GPIO22, AF0) -#define GPIO55_GPIO55 MFP_CFG(GPIO55, AF0) -#define GPIO56_GPIO56 MFP_CFG(GPIO56, AF0) -#define GPIO57_GPIO57 MFP_CFG(GPIO57, AF0) -#define GPIO58_GPIO58 MFP_CFG(GPIO58, AF0) - -/* Codec*/ -#define GPIO23_GPIO23 MFP_CFG(GPIO23, AF0) - -#define GPIO101_GPIO101 MFP_CFG(GPIO101, AF0) - /* PMIC */ #define PMIC_PMIC_INT MFP_CFG(PMIC_INT, AF0) diff --git a/arch/arm/mach-mmp/mmp2.c b/arch/arm/mach-mmp/mmp2.c index e236ec0..da5cd9d 100644 --- a/arch/arm/mach-mmp/mmp2.c +++ b/arch/arm/mach-mmp/mmp2.c @@ -34,7 +34,50 @@ #define APMASK(i) (GPIO_REGS_VIRT + BANK_OFF(i) + 0x9c) static struct mfp_addr_map mmp2_addr_map[] __initdata = { + + MFP_ADDR_X(GPIO0, GPIO58, 0x54), + MFP_ADDR_X(GPIO59, GPIO73, 0x280), + MFP_ADDR_X(GPIO74, GPIO101, 0x170), + + MFP_ADDR(GPIO102, 0x0), + MFP_ADDR(GPIO103, 0x4), + MFP_ADDR(GPIO104, 0x1fc), + MFP_ADDR(GPIO105, 0x1f8), + MFP_ADDR(GPIO106, 0x1f4), + MFP_ADDR(GPIO107, 0x1f0), + MFP_ADDR(GPIO108, 0x21c), + MFP_ADDR(GPIO109, 0x218), + MFP_ADDR(GPIO110, 0x214), + MFP_ADDR(GPIO111, 0x200), + MFP_ADDR(GPIO112, 0x244), + MFP_ADDR(GPIO113, 0x25c), + MFP_ADDR(GPIO114, 0x164), + MFP_ADDR_X(GPIO115, GPIO122, 0x260), + + MFP_ADDR(GPIO123, 0x148), + MFP_ADDR_X(GPIO124, GPIO141, 0xc), + + MFP_ADDR(GPIO142, 0x8), + MFP_ADDR_X(GPIO143, GPIO151, 0x220), + MFP_ADDR_X(GPIO152, GPIO153, 0x248), + MFP_ADDR_X(GPIO154, GPIO155, 0x254), + MFP_ADDR_X(GPIO156, GPIO159, 0x14c), + + MFP_ADDR(GPIO160, 0x250), + MFP_ADDR(GPIO161, 0x210), + MFP_ADDR(GPIO162, 0x20c), + MFP_ADDR(GPIO163, 0x208), + MFP_ADDR(GPIO164, 0x204), + MFP_ADDR(GPIO165, 0x1ec), + MFP_ADDR(GPIO166, 0x1e8), + MFP_ADDR(GPIO167, 0x1e4), + MFP_ADDR(GPIO168, 0x1e0), + + MFP_ADDR_X(TWSI1_SCL, TWSI1_SDA, 0x140), + MFP_ADDR_X(TWSI4_SCL, TWSI4_SDA, 0x2bc), + MFP_ADDR(PMIC_INT, 0x2c4), + MFP_ADDR(CLK_REQ, 0x160), MFP_ADDR_END, }; diff --git a/arch/arm/plat-pxa/include/plat/mfp.h b/arch/arm/plat-pxa/include/plat/mfp.h index 857a683..9e604c8 100644 --- a/arch/arm/plat-pxa/include/plat/mfp.h +++ b/arch/arm/plat-pxa/include/plat/mfp.h @@ -316,6 +316,13 @@ enum { MFP_PIN_PMIC_INT, MFP_PIN_RDY, + /* additional pins on MMP2 */ + MFP_PIN_TWSI1_SCL, + MFP_PIN_TWSI1_SDA, + MFP_PIN_TWSI4_SCL, + MFP_PIN_TWSI4_SDA, + MFP_PIN_CLK_REQ, + MFP_PIN_MAX, }; -- cgit v0.10.2 From f4557870834b15bcbe14a2fcd1a0338e9f9c89b5 Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Wed, 28 Apr 2010 15:24:24 -0400 Subject: [ARM] mmp: add dma support to mmp2 Add DMA support in MMP2. Signed-off-by: Lei Wen Signed-off-by: Haojian Zhuang Signed-off-by: Eric Miao diff --git a/arch/arm/mach-mmp/mmp2.c b/arch/arm/mach-mmp/mmp2.c index da5cd9d..7f5eb05 100644 --- a/arch/arm/mach-mmp/mmp2.c +++ b/arch/arm/mach-mmp/mmp2.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -149,6 +150,7 @@ static int __init mmp2_init(void) #endif mfp_init_base(MFPR_VIRT_BASE); mfp_init_addr(mmp2_addr_map); + pxa_init_dma(IRQ_MMP2_DMA_RIQ, 16); clkdev_add_table(ARRAY_AND_SIZE(mmp2_clkregs)); } -- cgit v0.10.2 From d49ea9e30bab64280eb93aaf5dedad205a30d28b Mon Sep 17 00:00:00 2001 From: Mingliang Hu Date: Mon, 12 Apr 2010 18:14:18 +0800 Subject: [ARM] mmp: add smc registers definition Signed-off-by: Mingliang Hu Signed-off-by: Haojian Zhuang Signed-off-by: Eric Miao diff --git a/arch/arm/mach-mmp/include/mach/regs-smc.h b/arch/arm/mach-mmp/include/mach/regs-smc.h new file mode 100644 index 0000000..e484d40 --- /dev/null +++ b/arch/arm/mach-mmp/include/mach/regs-smc.h @@ -0,0 +1,37 @@ +/* + * linux/arch/arm/mach-mmp/include/mach/regs-smc.h + * + * Static Memory Controller Registers + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_MACH_REGS_SMC_H +#define __ASM_MACH_REGS_SMC_H + +#include + +#define SMC_VIRT_BASE (AXI_VIRT_BASE + 0x83800) +#define SMC_REG(x) (SMC_VIRT_BASE + (x)) + +#define SMC_MSC0 SMC_REG(0x0020) +#define SMC_MSC1 SMC_REG(0x0024) +#define SMC_SXCNFG0 SMC_REG(0x0030) +#define SMC_SXCNFG1 SMC_REG(0x0034) +#define SMC_MEMCLKCFG SMC_REG(0x0068) +#define SMC_CSDFICFG0 SMC_REG(0x0090) +#define SMC_CSDFICFG1 SMC_REG(0x0094) +#define SMC_CLK_RET_DEL SMC_REG(0x00b0) +#define SMC_ADV_RET_DEL SMC_REG(0x00b4) +#define SMC_CSADRMAP0 SMC_REG(0x00c0) +#define SMC_CSADRMAP1 SMC_REG(0x00c4) +#define SMC_WE_AP0 SMC_REG(0x00e0) +#define SMC_WE_AP1 SMC_REG(0x00e4) +#define SMC_OE_AP0 SMC_REG(0x00f0) +#define SMC_OE_AP1 SMC_REG(0x00f4) +#define SMC_ADV_AP0 SMC_REG(0x0100) +#define SMC_ADV_AP1 SMC_REG(0x0104) + +#endif /* __ASM_MACH_REGS_SMC_H */ -- cgit v0.10.2 From fed240558094058a5d372448b722fed93ddabd6b Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Wed, 28 Apr 2010 15:34:04 -0400 Subject: [ARM] mmp: update twsi index Sync twsi index to register index. It's used to avoid typo error. Signed-off-by: Haojian Zhuang Signed-off-by: Eric Miao diff --git a/arch/arm/mach-mmp/include/mach/mmp2.h b/arch/arm/mach-mmp/include/mach/mmp2.h index 459f3be..fec220b 100644 --- a/arch/arm/mach-mmp/include/mach/mmp2.h +++ b/arch/arm/mach-mmp/include/mach/mmp2.h @@ -39,17 +39,17 @@ static inline int mmp2_add_twsi(int id, struct i2c_pxa_platform_data *data, int ret; switch (id) { - case 0: d = &mmp2_device_twsi1; break; - case 1: d = &mmp2_device_twsi2; break; - case 2: d = &mmp2_device_twsi3; break; - case 3: d = &mmp2_device_twsi4; break; - case 4: d = &mmp2_device_twsi5; break; - case 5: d = &mmp2_device_twsi6; break; + case 1: d = &mmp2_device_twsi1; break; + case 2: d = &mmp2_device_twsi2; break; + case 3: d = &mmp2_device_twsi3; break; + case 4: d = &mmp2_device_twsi4; break; + case 5: d = &mmp2_device_twsi5; break; + case 6: d = &mmp2_device_twsi6; break; default: return -EINVAL; } - ret = i2c_register_board_info(id, info, size); + ret = i2c_register_board_info(id - 1, info, size); if (ret) return ret; -- cgit v0.10.2 From 2503991a56483dc8477a3c6ca86da253eb5f8af9 Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Wed, 28 Apr 2010 15:43:21 -0400 Subject: [ARM] mmp: append device support in jasper Support regulator MAX8649, PMIC MAX8925 into the Jasper. Backlight & power supply components of MAX8925 are enabled in Jasper. Signed-off-by: Haojian Zhuang Acked-by: Mark Brown Signed-off-by: Eric Miao diff --git a/arch/arm/mach-mmp/jasper.c b/arch/arm/mach-mmp/jasper.c index cfd4d66..d77dd41 100644 --- a/arch/arm/mach-mmp/jasper.c +++ b/arch/arm/mach-mmp/jasper.c @@ -15,12 +15,16 @@ #include #include #include +#include +#include +#include #include #include #include #include #include +#include #include "common.h" @@ -58,6 +62,63 @@ static unsigned long jasper_pin_config[] __initdata = { GPIO149_ND_CLE, GPIO112_ND_RDY0, GPIO160_ND_RDY1, + + /* PMIC */ + PMIC_PMIC_INT | MFP_LPM_EDGE_FALL, +}; + +static struct regulator_consumer_supply max8649_supply[] = { + REGULATOR_SUPPLY("vcc_core", NULL), +}; + +static struct regulator_init_data max8649_init_data = { + .constraints = { + .name = "vcc_core range", + .min_uV = 1150000, + .max_uV = 1280000, + .always_on = 1, + .boot_on = 1, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &max8649_supply[0], +}; + +static struct max8649_platform_data jasper_max8649_info = { + .mode = 2, /* VID1 = 1, VID0 = 0 */ + .extclk = 0, + .ramp_timing = MAX8649_RAMP_32MV, + .regulator = &max8649_init_data, +}; + +static struct max8925_backlight_pdata jasper_backlight_data = { + .dual_string = 0, +}; + +static struct max8925_power_pdata jasper_power_data = { + .batt_detect = 0, /* can't detect battery by ID pin */ + .topoff_threshold = MAX8925_TOPOFF_THR_10PER, + .fast_charge = MAX8925_FCHG_1000MA, +}; + +static struct max8925_platform_data jasper_max8925_info = { + .backlight = &jasper_backlight_data, + .power = &jasper_power_data, + .irq_base = IRQ_BOARD_START, +}; + +static struct i2c_board_info jasper_twsi1_info[] = { + [0] = { + .type = "max8649", + .addr = 0x60, + .platform_data = &jasper_max8649_info, + }, + [1] = { + .type = "max8925", + .addr = 0x3c, + .irq = IRQ_MMP2_PMIC, + .platform_data = &jasper_max8925_info, + }, }; static void __init jasper_init(void) @@ -67,6 +128,9 @@ static void __init jasper_init(void) /* on-chip devices */ mmp2_add_uart(1); mmp2_add_uart(3); + mmp2_add_twsi(1, NULL, ARRAY_AND_SIZE(jasper_twsi1_info)); + + regulator_has_full_constraints(); } MACHINE_START(MARVELL_JASPER, "Jasper Development Platform") -- cgit v0.10.2 From baffe1699c68da5040de6b274054adc995795782 Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Wed, 5 May 2010 10:11:15 -0400 Subject: [ARM] pxa: add namespace on ssp In order to prevent code ambiguous, add namespace on functions in ssp driver. Signed-off-by: Haojian Zhuang Acked-by: Liam Girdwood Signed-off-by: Eric Miao diff --git a/arch/arm/plat-pxa/include/plat/ssp.h b/arch/arm/plat-pxa/include/plat/ssp.h index d16d79a..fe43150 100644 --- a/arch/arm/plat-pxa/include/plat/ssp.h +++ b/arch/arm/plat-pxa/include/plat/ssp.h @@ -159,28 +159,28 @@ struct ssp_device { }; /** - * ssp_write_reg - Write to a SSP register + * pxa_ssp_write_reg - Write to a SSP register * * @dev: SSP device to access * @reg: Register to write to * @val: Value to be written. */ -static inline void ssp_write_reg(struct ssp_device *dev, u32 reg, u32 val) +static inline void pxa_ssp_write_reg(struct ssp_device *dev, u32 reg, u32 val) { __raw_writel(val, dev->mmio_base + reg); } /** - * ssp_read_reg - Read from a SSP register + * pxa_ssp_read_reg - Read from a SSP register * * @dev: SSP device to access * @reg: Register to read from */ -static inline u32 ssp_read_reg(struct ssp_device *dev, u32 reg) +static inline u32 pxa_ssp_read_reg(struct ssp_device *dev, u32 reg) { return __raw_readl(dev->mmio_base + reg); } -struct ssp_device *ssp_request(int port, const char *label); -void ssp_free(struct ssp_device *); +struct ssp_device *pxa_ssp_request(int port, const char *label); +void pxa_ssp_free(struct ssp_device *); #endif /* __ASM_ARCH_SSP_H */ diff --git a/arch/arm/plat-pxa/ssp.c b/arch/arm/plat-pxa/ssp.c index 52c07cc..c6357e5 100644 --- a/arch/arm/plat-pxa/ssp.c +++ b/arch/arm/plat-pxa/ssp.c @@ -37,7 +37,7 @@ static DEFINE_MUTEX(ssp_lock); static LIST_HEAD(ssp_list); -struct ssp_device *ssp_request(int port, const char *label) +struct ssp_device *pxa_ssp_request(int port, const char *label) { struct ssp_device *ssp = NULL; @@ -58,9 +58,9 @@ struct ssp_device *ssp_request(int port, const char *label) return ssp; } -EXPORT_SYMBOL(ssp_request); +EXPORT_SYMBOL(pxa_ssp_request); -void ssp_free(struct ssp_device *ssp) +void pxa_ssp_free(struct ssp_device *ssp) { mutex_lock(&ssp_lock); if (ssp->use_count) { @@ -70,9 +70,9 @@ void ssp_free(struct ssp_device *ssp) dev_err(&ssp->pdev->dev, "device already free\n"); mutex_unlock(&ssp_lock); } -EXPORT_SYMBOL(ssp_free); +EXPORT_SYMBOL(pxa_ssp_free); -static int __devinit ssp_probe(struct platform_device *pdev) +static int __devinit pxa_ssp_probe(struct platform_device *pdev) { const struct platform_device_id *id = platform_get_device_id(pdev); struct resource *res; @@ -164,7 +164,7 @@ err_free: return ret; } -static int __devexit ssp_remove(struct platform_device *pdev) +static int __devexit pxa_ssp_remove(struct platform_device *pdev) { struct resource *res; struct ssp_device *ssp; @@ -196,9 +196,9 @@ static const struct platform_device_id ssp_id_table[] = { { }, }; -static struct platform_driver ssp_driver = { - .probe = ssp_probe, - .remove = __devexit_p(ssp_remove), +static struct platform_driver pxa_ssp_driver = { + .probe = pxa_ssp_probe, + .remove = __devexit_p(pxa_ssp_remove), .driver = { .owner = THIS_MODULE, .name = "pxa2xx-ssp", @@ -208,12 +208,12 @@ static struct platform_driver ssp_driver = { static int __init pxa_ssp_init(void) { - return platform_driver_register(&ssp_driver); + return platform_driver_register(&pxa_ssp_driver); } static void __exit pxa_ssp_exit(void) { - platform_driver_unregister(&ssp_driver); + platform_driver_unregister(&pxa_ssp_driver); } arch_initcall(pxa_ssp_init); diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index 50d6b78..e76b1af 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c @@ -1465,7 +1465,7 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev) platform_info = dev->platform_data; - ssp = ssp_request(pdev->id, pdev->name); + ssp = pxa_ssp_request(pdev->id, pdev->name); if (ssp == NULL) { dev_err(&pdev->dev, "failed to request SSP%d\n", pdev->id); return -ENODEV; @@ -1475,7 +1475,7 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev) master = spi_alloc_master(dev, sizeof(struct driver_data) + 16); if (!master) { dev_err(&pdev->dev, "cannot alloc spi_master\n"); - ssp_free(ssp); + pxa_ssp_free(ssp); return -ENOMEM; } drv_data = spi_master_get_devdata(master); @@ -1604,7 +1604,7 @@ out_error_irq_alloc: out_error_master_alloc: spi_master_put(master); - ssp_free(ssp); + pxa_ssp_free(ssp); return status; } @@ -1648,7 +1648,7 @@ static int pxa2xx_spi_remove(struct platform_device *pdev) free_irq(ssp->irq, drv_data); /* Release SSP */ - ssp_free(ssp); + pxa_ssp_free(ssp); /* Disconnect from the SPI framework */ spi_unregister_master(drv_data->master); diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index 6271a10..a1fd23e 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c @@ -56,15 +56,15 @@ struct ssp_priv { static void dump_registers(struct ssp_device *ssp) { dev_dbg(&ssp->pdev->dev, "SSCR0 0x%08x SSCR1 0x%08x SSTO 0x%08x\n", - ssp_read_reg(ssp, SSCR0), ssp_read_reg(ssp, SSCR1), - ssp_read_reg(ssp, SSTO)); + pxa_ssp_read_reg(ssp, SSCR0), pxa_ssp_read_reg(ssp, SSCR1), + pxa_ssp_read_reg(ssp, SSTO)); dev_dbg(&ssp->pdev->dev, "SSPSP 0x%08x SSSR 0x%08x SSACD 0x%08x\n", - ssp_read_reg(ssp, SSPSP), ssp_read_reg(ssp, SSSR), - ssp_read_reg(ssp, SSACD)); + pxa_ssp_read_reg(ssp, SSPSP), pxa_ssp_read_reg(ssp, SSSR), + pxa_ssp_read_reg(ssp, SSACD)); } -static void ssp_enable(struct ssp_device *ssp) +static void pxa_ssp_enable(struct ssp_device *ssp) { uint32_t sscr0; @@ -72,7 +72,7 @@ static void ssp_enable(struct ssp_device *ssp) __raw_writel(sscr0, ssp->mmio_base + SSCR0); } -static void ssp_disable(struct ssp_device *ssp) +static void pxa_ssp_disable(struct ssp_device *ssp) { uint32_t sscr0; @@ -86,7 +86,7 @@ struct pxa2xx_pcm_dma_data { }; static struct pxa2xx_pcm_dma_params * -ssp_get_dma_params(struct ssp_device *ssp, int width4, int out) +pxa_ssp_get_dma_params(struct ssp_device *ssp, int width4, int out) { struct pxa2xx_pcm_dma_data *dma; @@ -118,7 +118,7 @@ static int pxa_ssp_startup(struct snd_pcm_substream *substream, if (!cpu_dai->active) { clk_enable(ssp->clk); - ssp_disable(ssp); + pxa_ssp_disable(ssp); } kfree(snd_soc_dai_get_dma_data(cpu_dai, substream)); @@ -136,7 +136,7 @@ static void pxa_ssp_shutdown(struct snd_pcm_substream *substream, struct ssp_device *ssp = priv->ssp; if (!cpu_dai->active) { - ssp_disable(ssp); + pxa_ssp_disable(ssp); clk_disable(ssp->clk); } @@ -159,7 +159,7 @@ static int pxa_ssp_suspend(struct snd_soc_dai *cpu_dai) priv->to = __raw_readl(ssp->mmio_base + SSTO); priv->psp = __raw_readl(ssp->mmio_base + SSPSP); - ssp_disable(ssp); + pxa_ssp_disable(ssp); clk_disable(ssp->clk); return 0; } @@ -179,7 +179,7 @@ static int pxa_ssp_resume(struct snd_soc_dai *cpu_dai) __raw_writel(priv->psp, ssp->mmio_base + SSPSP); if (cpu_dai->active) - ssp_enable(ssp); + pxa_ssp_enable(ssp); else clk_disable(ssp->clk); @@ -195,9 +195,9 @@ static int pxa_ssp_resume(struct snd_soc_dai *cpu_dai) * ssp_set_clkdiv - set SSP clock divider * @div: serial clock rate divider */ -static void ssp_set_scr(struct ssp_device *ssp, u32 div) +static void pxa_ssp_set_scr(struct ssp_device *ssp, u32 div) { - u32 sscr0 = ssp_read_reg(ssp, SSCR0); + u32 sscr0 = pxa_ssp_read_reg(ssp, SSCR0); if (cpu_is_pxa25x() && ssp->type == PXA25x_SSP) { sscr0 &= ~0x0000ff00; @@ -206,15 +206,15 @@ static void ssp_set_scr(struct ssp_device *ssp, u32 div) sscr0 &= ~0x000fff00; sscr0 |= (div - 1) << 8; /* 1..4096 */ } - ssp_write_reg(ssp, SSCR0, sscr0); + pxa_ssp_write_reg(ssp, SSCR0, sscr0); } /** - * ssp_get_clkdiv - get SSP clock divider + * pxa_ssp_get_clkdiv - get SSP clock divider */ -static u32 ssp_get_scr(struct ssp_device *ssp) +static u32 pxa_ssp_get_scr(struct ssp_device *ssp) { - u32 sscr0 = ssp_read_reg(ssp, SSCR0); + u32 sscr0 = pxa_ssp_read_reg(ssp, SSCR0); u32 div; if (cpu_is_pxa25x() && ssp->type == PXA25x_SSP) @@ -234,7 +234,7 @@ static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai, struct ssp_device *ssp = priv->ssp; int val; - u32 sscr0 = ssp_read_reg(ssp, SSCR0) & + u32 sscr0 = pxa_ssp_read_reg(ssp, SSCR0) & ~(SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ACS); dev_dbg(&ssp->pdev->dev, @@ -262,7 +262,7 @@ static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai, break; case PXA_SSP_CLK_AUDIO: priv->sysclk = 0; - ssp_set_scr(ssp, 1); + pxa_ssp_set_scr(ssp, 1); sscr0 |= SSCR0_ACS; break; default: @@ -273,8 +273,8 @@ static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai, * on PXA2xx. On PXA3xx it must be enabled when doing so. */ if (!cpu_is_pxa3xx()) clk_disable(ssp->clk); - val = ssp_read_reg(ssp, SSCR0) | sscr0; - ssp_write_reg(ssp, SSCR0, val); + val = pxa_ssp_read_reg(ssp, SSCR0) | sscr0; + pxa_ssp_write_reg(ssp, SSCR0, val); if (!cpu_is_pxa3xx()) clk_enable(ssp->clk); @@ -293,11 +293,11 @@ static int pxa_ssp_set_dai_clkdiv(struct snd_soc_dai *cpu_dai, switch (div_id) { case PXA_SSP_AUDIO_DIV_ACDS: - val = (ssp_read_reg(ssp, SSACD) & ~0x7) | SSACD_ACDS(div); - ssp_write_reg(ssp, SSACD, val); + val = (pxa_ssp_read_reg(ssp, SSACD) & ~0x7) | SSACD_ACDS(div); + pxa_ssp_write_reg(ssp, SSACD, val); break; case PXA_SSP_AUDIO_DIV_SCDB: - val = ssp_read_reg(ssp, SSACD); + val = pxa_ssp_read_reg(ssp, SSACD); val &= ~SSACD_SCDB; #if defined(CONFIG_PXA3xx) if (cpu_is_pxa3xx()) @@ -320,10 +320,10 @@ static int pxa_ssp_set_dai_clkdiv(struct snd_soc_dai *cpu_dai, default: return -EINVAL; } - ssp_write_reg(ssp, SSACD, val); + pxa_ssp_write_reg(ssp, SSACD, val); break; case PXA_SSP_DIV_SCR: - ssp_set_scr(ssp, div); + pxa_ssp_set_scr(ssp, div); break; default: return -ENODEV; @@ -340,11 +340,11 @@ static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id, { struct ssp_priv *priv = cpu_dai->private_data; struct ssp_device *ssp = priv->ssp; - u32 ssacd = ssp_read_reg(ssp, SSACD) & ~0x70; + u32 ssacd = pxa_ssp_read_reg(ssp, SSACD) & ~0x70; #if defined(CONFIG_PXA3xx) if (cpu_is_pxa3xx()) - ssp_write_reg(ssp, SSACDD, 0); + pxa_ssp_write_reg(ssp, SSACDD, 0); #endif switch (freq_out) { @@ -382,7 +382,7 @@ static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id, val = tmp; val = (val << 16) | 64; - ssp_write_reg(ssp, SSACDD, val); + pxa_ssp_write_reg(ssp, SSACDD, val); ssacd |= (0x6 << 4); @@ -396,7 +396,7 @@ static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id, return -EINVAL; } - ssp_write_reg(ssp, SSACD, ssacd); + pxa_ssp_write_reg(ssp, SSACD, ssacd); return 0; } @@ -411,7 +411,7 @@ static int pxa_ssp_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, struct ssp_device *ssp = priv->ssp; u32 sscr0; - sscr0 = ssp_read_reg(ssp, SSCR0); + sscr0 = pxa_ssp_read_reg(ssp, SSCR0); sscr0 &= ~(SSCR0_MOD | SSCR0_SlotsPerFrm(8) | SSCR0_EDSS | SSCR0_DSS); /* set slot width */ @@ -428,10 +428,10 @@ static int pxa_ssp_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, sscr0 |= SSCR0_SlotsPerFrm(slots); /* set active slot mask */ - ssp_write_reg(ssp, SSTSA, tx_mask); - ssp_write_reg(ssp, SSRSA, rx_mask); + pxa_ssp_write_reg(ssp, SSTSA, tx_mask); + pxa_ssp_write_reg(ssp, SSRSA, rx_mask); } - ssp_write_reg(ssp, SSCR0, sscr0); + pxa_ssp_write_reg(ssp, SSCR0, sscr0); return 0; } @@ -446,12 +446,12 @@ static int pxa_ssp_set_dai_tristate(struct snd_soc_dai *cpu_dai, struct ssp_device *ssp = priv->ssp; u32 sscr1; - sscr1 = ssp_read_reg(ssp, SSCR1); + sscr1 = pxa_ssp_read_reg(ssp, SSCR1); if (tristate) sscr1 &= ~SSCR1_TTE; else sscr1 |= SSCR1_TTE; - ssp_write_reg(ssp, SSCR1, sscr1); + pxa_ssp_write_reg(ssp, SSCR1, sscr1); return 0; } @@ -475,14 +475,14 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai, return 0; /* we can only change the settings if the port is not in use */ - if (ssp_read_reg(ssp, SSCR0) & SSCR0_SSE) { + if (pxa_ssp_read_reg(ssp, SSCR0) & SSCR0_SSE) { dev_err(&ssp->pdev->dev, "can't change hardware dai format: stream is in use"); return -EINVAL; } /* reset port settings */ - sscr0 = ssp_read_reg(ssp, SSCR0) & + sscr0 = pxa_ssp_read_reg(ssp, SSCR0) & (SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ACS); sscr1 = SSCR1_RxTresh(8) | SSCR1_TxTresh(7); sspsp = 0; @@ -534,9 +534,9 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai, return -EINVAL; } - ssp_write_reg(ssp, SSCR0, sscr0); - ssp_write_reg(ssp, SSCR1, sscr1); - ssp_write_reg(ssp, SSPSP, sspsp); + pxa_ssp_write_reg(ssp, SSCR0, sscr0); + pxa_ssp_write_reg(ssp, SSCR1, sscr1); + pxa_ssp_write_reg(ssp, SSPSP, sspsp); dump_registers(ssp); @@ -565,7 +565,7 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, u32 sscr0; u32 sspsp; int width = snd_pcm_format_physical_width(params_format(params)); - int ttsa = ssp_read_reg(ssp, SSTSA) & 0xf; + int ttsa = pxa_ssp_read_reg(ssp, SSTSA) & 0xf; struct pxa2xx_pcm_dma_params *dma_data; dma_data = snd_soc_dai_get_dma_data(dai, substream); @@ -577,22 +577,22 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, * to force 16-bit frame width on the wire (for S16_LE), even * with two channels. Use 16-bit DMA transfers for this case. */ - dma_data = ssp_get_dma_params(ssp, + dma_data = pxa_ssp_get_dma_params(ssp, ((chn == 2) && (ttsa != 1)) || (width == 32), substream->stream == SNDRV_PCM_STREAM_PLAYBACK); snd_soc_dai_set_dma_data(dai, substream, dma_data); /* we can only change the settings if the port is not in use */ - if (ssp_read_reg(ssp, SSCR0) & SSCR0_SSE) + if (pxa_ssp_read_reg(ssp, SSCR0) & SSCR0_SSE) return 0; /* clear selected SSP bits */ - sscr0 = ssp_read_reg(ssp, SSCR0) & ~(SSCR0_DSS | SSCR0_EDSS); - ssp_write_reg(ssp, SSCR0, sscr0); + sscr0 = pxa_ssp_read_reg(ssp, SSCR0) & ~(SSCR0_DSS | SSCR0_EDSS); + pxa_ssp_write_reg(ssp, SSCR0, sscr0); /* bit size */ - sscr0 = ssp_read_reg(ssp, SSCR0); + sscr0 = pxa_ssp_read_reg(ssp, SSCR0); switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: #ifdef CONFIG_PXA3xx @@ -608,13 +608,13 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(16)); break; } - ssp_write_reg(ssp, SSCR0, sscr0); + pxa_ssp_write_reg(ssp, SSCR0, sscr0); switch (priv->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: - sspsp = ssp_read_reg(ssp, SSPSP); + sspsp = pxa_ssp_read_reg(ssp, SSPSP); - if ((ssp_get_scr(ssp) == 4) && (width == 16)) { + if ((pxa_ssp_get_scr(ssp) == 4) && (width == 16)) { /* This is a special case where the bitclk is 64fs * and we're not dealing with 2*32 bits of audio * samples. @@ -648,7 +648,7 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, sspsp |= SSPSP_DMYSTRT(1); } - ssp_write_reg(ssp, SSPSP, sspsp); + pxa_ssp_write_reg(ssp, SSPSP, sspsp); break; default: break; @@ -679,45 +679,45 @@ static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd, switch (cmd) { case SNDRV_PCM_TRIGGER_RESUME: - ssp_enable(ssp); + pxa_ssp_enable(ssp); break; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - val = ssp_read_reg(ssp, SSCR1); + val = pxa_ssp_read_reg(ssp, SSCR1); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) val |= SSCR1_TSRE; else val |= SSCR1_RSRE; - ssp_write_reg(ssp, SSCR1, val); - val = ssp_read_reg(ssp, SSSR); - ssp_write_reg(ssp, SSSR, val); + pxa_ssp_write_reg(ssp, SSCR1, val); + val = pxa_ssp_read_reg(ssp, SSSR); + pxa_ssp_write_reg(ssp, SSSR, val); break; case SNDRV_PCM_TRIGGER_START: - val = ssp_read_reg(ssp, SSCR1); + val = pxa_ssp_read_reg(ssp, SSCR1); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) val |= SSCR1_TSRE; else val |= SSCR1_RSRE; - ssp_write_reg(ssp, SSCR1, val); - ssp_enable(ssp); + pxa_ssp_write_reg(ssp, SSCR1, val); + pxa_ssp_enable(ssp); break; case SNDRV_PCM_TRIGGER_STOP: - val = ssp_read_reg(ssp, SSCR1); + val = pxa_ssp_read_reg(ssp, SSCR1); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) val &= ~SSCR1_TSRE; else val &= ~SSCR1_RSRE; - ssp_write_reg(ssp, SSCR1, val); + pxa_ssp_write_reg(ssp, SSCR1, val); break; case SNDRV_PCM_TRIGGER_SUSPEND: - ssp_disable(ssp); + pxa_ssp_disable(ssp); break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - val = ssp_read_reg(ssp, SSCR1); + val = pxa_ssp_read_reg(ssp, SSCR1); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) val &= ~SSCR1_TSRE; else val &= ~SSCR1_RSRE; - ssp_write_reg(ssp, SSCR1, val); + pxa_ssp_write_reg(ssp, SSCR1, val); break; default: @@ -739,7 +739,7 @@ static int pxa_ssp_probe(struct platform_device *pdev, if (!priv) return -ENOMEM; - priv->ssp = ssp_request(dai->id + 1, "SoC audio"); + priv->ssp = pxa_ssp_request(dai->id + 1, "SoC audio"); if (priv->ssp == NULL) { ret = -ENODEV; goto err_priv; @@ -759,7 +759,7 @@ static void pxa_ssp_remove(struct platform_device *pdev, struct snd_soc_dai *dai) { struct ssp_priv *priv = dai->private_data; - ssp_free(priv->ssp); + pxa_ssp_free(priv->ssp); } #define PXA_SSP_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ -- cgit v0.10.2 From fdb3603800e7a65bc3cafdfd5a1797d08f09e582 Mon Sep 17 00:00:00 2001 From: Suresh Jayaraman Date: Tue, 11 May 2010 09:46:46 +0530 Subject: cifs: propagate cifs_new_fileinfo() error back to the caller ..otherwise memory allocation errors go undetected. Signed-off-by: Suresh Jayaraman Signed-off-by: Steve French diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index bd363df..86d3c0c 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -261,8 +261,14 @@ int cifs_posix_open(char *full_path, struct inode **pinode, * cifs_fill_filedata() takes care of setting cifsFileInfo pointer to * file->private_data. */ - if (mnt) - cifs_new_fileinfo(*pinode, *pnetfid, NULL, mnt, oflags); + if (mnt) { + struct cifsFileInfo *pfile_info; + + pfile_info = cifs_new_fileinfo(*pinode, *pnetfid, NULL, mnt, + oflags); + if (pfile_info == NULL) + rc = -ENOMEM; + } posix_open_ret: kfree(presp_data); @@ -476,12 +482,15 @@ cifs_create_set_dentry: /* mknod case - do not leave file open */ CIFSSMBClose(xid, tcon, fileHandle); } else if (!(posix_create) && (newinode)) { + struct cifsFileInfo *pfile_info; /* * cifs_fill_filedata() takes care of setting cifsFileInfo * pointer to file->private_data. */ - cifs_new_fileinfo(newinode, fileHandle, NULL, nd->path.mnt, - oflags); + pfile_info = cifs_new_fileinfo(newinode, fileHandle, NULL, + nd->path.mnt, oflags); + if (pfile_info == NULL) + rc = -ENOMEM; } cifs_create_out: kfree(buf); -- cgit v0.10.2 From b09e0190acf88c7fe3b05e3c331e1b2ef5310896 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 11 May 2010 11:10:15 -0300 Subject: perf hist: Adopt filter by dso and by thread methods from the newt browser MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Those are really not specific to the newt code, can be used by other UI frontends. Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index d7c7529..3d67d6b 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -301,10 +301,7 @@ static int __cmd_report(void) hists__collapse_resort(hists); hists__output_resort(hists); if (use_browser) - perf_session__browse_hists(&hists->entries, - hists->nr_entries, - hists->stats.total, help, - input_name); + hists__browse(hists, help, input_name); else { if (rb_first(&session->hists.entries) == rb_last(&session->hists.entries)) diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index e34fd24..baa55be 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -784,3 +784,62 @@ print_entries: return ret; } + +enum hist_filter { + HIST_FILTER__DSO, + HIST_FILTER__THREAD, +}; + +void hists__filter_by_dso(struct hists *self, const struct dso *dso) +{ + struct rb_node *nd; + + self->nr_entries = self->stats.total = 0; + self->max_sym_namelen = 0; + + for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) { + struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); + + if (symbol_conf.exclude_other && !h->parent) + continue; + + if (dso != NULL && (h->ms.map == NULL || h->ms.map->dso != dso)) { + h->filtered |= (1 << HIST_FILTER__DSO); + continue; + } + + h->filtered &= ~(1 << HIST_FILTER__DSO); + if (!h->filtered) { + ++self->nr_entries; + self->stats.total += h->count; + if (h->ms.sym && + self->max_sym_namelen < h->ms.sym->namelen) + self->max_sym_namelen = h->ms.sym->namelen; + } + } +} + +void hists__filter_by_thread(struct hists *self, const struct thread *thread) +{ + struct rb_node *nd; + + self->nr_entries = self->stats.total = 0; + self->max_sym_namelen = 0; + + for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) { + struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); + + if (thread != NULL && h->thread != thread) { + h->filtered |= (1 << HIST_FILTER__THREAD); + continue; + } + h->filtered &= ~(1 << HIST_FILTER__THREAD); + if (!h->filtered) { + ++self->nr_entries; + self->stats.total += h->count; + if (h->ms.sym && + self->max_sym_namelen < h->ms.sym->namelen) + self->max_sym_namelen = h->ms.sym->namelen; + } + } +} diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 1b18d04..1c5f93a 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -44,4 +44,19 @@ void hists__output_resort(struct hists *self); void hists__collapse_resort(struct hists *self); size_t hists__fprintf(struct hists *self, struct hists *pair, bool show_displacement, FILE *fp); + +void hists__filter_by_dso(struct hists *self, const struct dso *dso); +void hists__filter_by_thread(struct hists *self, const struct thread *thread); + +#ifdef NO_NEWT_SUPPORT +static inline int hists__browse(struct hists self __used, + const char *helpline __used, + const char *input_name __used) +{ + return 0; +} +#else +int hists__browse(struct hists *self, const char *helpline, + const char *input_name); +#endif #endif /* __PERF_HIST_H */ diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index e283a6e..638b519 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -410,8 +410,8 @@ static void hist_browser__delete(struct hist_browser *self) free(self); } -static int hist_browser__populate(struct hist_browser *self, struct rb_root *hists, - u64 nr_hists, u64 session_total, const char *title) +static int hist_browser__populate(struct hist_browser *self, struct hists *hists, + const char *title) { int max_len = 0, idx, cols, rows; struct ui_progress *progress; @@ -426,7 +426,7 @@ static int hist_browser__populate(struct hist_browser *self, struct rb_root *his } snprintf(str, sizeof(str), "Samples: %Ld ", - session_total); + hists->stats.total); newtDrawRootText(0, 0, str); newtGetScreenSize(NULL, &rows); @@ -442,24 +442,25 @@ static int hist_browser__populate(struct hist_browser *self, struct rb_root *his newtComponentAddCallback(self->tree, hist_browser__selection, &self->selection); - progress = ui_progress__new("Adding entries to the browser...", nr_hists); + progress = ui_progress__new("Adding entries to the browser...", + hists->nr_entries); if (progress == NULL) return -1; idx = 0; - for (nd = rb_first(hists); nd; nd = rb_next(nd)) { + for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); int len; if (h->filtered) continue; - len = hist_entry__append_browser(h, self->tree, session_total); + len = hist_entry__append_browser(h, self->tree, hists->stats.total); if (len > max_len) max_len = len; if (symbol_conf.use_callchain) hist_entry__append_callchain_browser(h, self->tree, - session_total, idx++); + hists->stats.total, idx++); ++curr_hist; if (curr_hist % 5) ui_progress__update(progress, curr_hist); @@ -490,57 +491,6 @@ static int hist_browser__populate(struct hist_browser *self, struct rb_root *his return 0; } -enum hist_filter { - HIST_FILTER__DSO, - HIST_FILTER__THREAD, -}; - -static u64 hists__filter_by_dso(struct rb_root *hists, const struct dso *dso, - u64 *session_total) -{ - struct rb_node *nd; - u64 nr_hists = 0; - - *session_total = 0; - - for (nd = rb_first(hists); nd; nd = rb_next(nd)) { - struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); - - if (dso != NULL && (h->ms.map == NULL || h->ms.map->dso != dso)) { - h->filtered |= (1 << HIST_FILTER__DSO); - continue; - } - h->filtered &= ~(1 << HIST_FILTER__DSO); - ++nr_hists; - *session_total += h->count; - } - - return nr_hists; -} - -static u64 hists__filter_by_thread(struct rb_root *hists, const struct thread *thread, - u64 *session_total) -{ - struct rb_node *nd; - u64 nr_hists = 0; - - *session_total = 0; - - for (nd = rb_first(hists); nd; nd = rb_next(nd)) { - struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); - - if (thread != NULL && h->thread != thread) { - h->filtered |= (1 << HIST_FILTER__THREAD); - continue; - } - h->filtered &= ~(1 << HIST_FILTER__THREAD); - ++nr_hists; - *session_total += h->count; - } - - return nr_hists; -} - static struct thread *hist_browser__selected_thread(struct hist_browser *self) { int *indexes; @@ -577,9 +527,7 @@ static int hist_browser__title(char *bf, size_t size, const char *input_name, return printed ?: snprintf(bf, size, "Report: %s", input_name); } -int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, - u64 session_total, const char *helpline, - const char *input_name) +int hists__browse(struct hists *self, const char *helpline, const char *input_name) { struct hist_browser *browser = hist_browser__new(); const struct thread *thread_filter = NULL; @@ -595,7 +543,7 @@ int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, hist_browser__title(msg, sizeof(msg), input_name, dso_filter, thread_filter); - if (hist_browser__populate(browser, hists, nr_hists, session_total, msg) < 0) + if (hist_browser__populate(browser, self, msg) < 0) goto out; while (1) { @@ -672,10 +620,10 @@ do_annotate: newtPushHelpLine(msg); dso_filter = dso; } - nr_hists = hists__filter_by_dso(hists, dso_filter, &session_total); + hists__filter_by_dso(self, dso_filter); hist_browser__title(msg, sizeof(msg), input_name, dso_filter, thread_filter); - if (hist_browser__populate(browser, hists, nr_hists, session_total, msg) < 0) + if (hist_browser__populate(browser, self, msg) < 0) goto out; } else if (choice == zoom_thread) { if (thread_filter) { @@ -689,10 +637,10 @@ do_annotate: newtPushHelpLine(msg); thread_filter = thread; } - nr_hists = hists__filter_by_thread(hists, thread_filter, &session_total); + hists__filter_by_thread(self, thread_filter); hist_browser__title(msg, sizeof(msg), input_name, dso_filter, thread_filter); - if (hist_browser__populate(browser, hists, nr_hists, session_total, msg) < 0) + if (hist_browser__populate(browser, self, msg) < 0) goto out; } } diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 46190f9..ce00fa6 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -102,21 +102,6 @@ int perf_session__create_kernel_maps(struct perf_session *self); int do_read(int fd, void *buf, size_t size); void perf_session__update_sample_type(struct perf_session *self); -#ifdef NO_NEWT_SUPPORT -static inline int perf_session__browse_hists(struct rb_root *hists __used, - u64 nr_hists __used, - u64 session_total __used, - const char *helpline __used, - const char *input_name __used) -{ - return 0; -} -#else -int perf_session__browse_hists(struct rb_root *hists, u64 nr_hists, - u64 session_total, const char *helpline, - const char *input_name); -#endif - static inline struct machine *perf_session__find_host_machine(struct perf_session *self) { -- cgit v0.10.2 From 6b3c4ef50441e85dc9b2c9b67e95e8ad1185c15e Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Tue, 11 May 2010 00:59:53 -0400 Subject: perf probe: Check older elfutils and set NO_DWARF Check whether elfutils is older than 0.138 (from which version checking routine has been introduced). And if so, set NO_DWARF because it is hard to check the API dependency without version checking. Signed-off-by: Masami Hiramatsu Reported-by: Robert Richter Cc: Robert Richter Cc: Ingo Molnar LKML-Reference: <20100511045953.9913.19485.stgit@localhost6.localdomain6> Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 0ef5cfe..b28bb73 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -506,8 +506,8 @@ PERFLIBS = $(LIB_FILE) -include config.mak ifndef NO_DWARF -ifneq ($(shell sh -c "(echo '\#include '; echo '\#include '; echo 'int main(void) { Dwarf *dbg; dbg = dwarf_begin(0, DWARF_C_READ); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -I/usr/include/elfutils -ldw -lelf -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y) - msg := $(warning No libdw.h found or old libdw.h found, disables dwarf support. Please install elfutils-devel/libdw-dev); +ifneq ($(shell sh -c "(echo '\#include '; echo '\#include '; echo '\#include '; echo '\#ifndef _ELFUTILS_PREREQ'; echo '\#error'; echo '\#endif'; echo 'int main(void) { Dwarf *dbg; dbg = dwarf_begin(0, DWARF_C_READ); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -I/usr/include/elfutils -ldw -lelf -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y) + msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev); NO_DWARF := 1 endif # Dwarf support endif # NO_DWARF -- cgit v0.10.2 From d11c7addfe0fa501cb54c824c0fac3481d527433 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Mon, 10 May 2010 16:43:35 -0400 Subject: perf symbols: allow forcing use of cplus_demangle For Fedora, I want to force perf to link against libiberty.a for cplus_demangle, rather than libbfd.a for bfd_demangle due to licensing insanity on binutils. (libiberty is LGPL2, libbfd is GPL3.) If we just rely on autodetection, we'll end up with libbfd linked against us, since they're both in binutils-static in the buildroot. Cc: Ingo Molnar LKML-Reference: <20100510204335.GA7565@bombadil.infradead.org> Signed-off-by: Kyle McMartin Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Makefile b/tools/perf/Makefile index b28bb73..0797786 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -592,6 +592,9 @@ endif ifdef NO_DEMANGLE BASIC_CFLAGS += -DNO_DEMANGLE +else ifdef HAVE_CPLUS_DEMANGLE + EXTLIBS += -liberty + BASIC_CFLAGS += -DHAVE_CPLUS_DEMANGLE else has_bfd := $(shell sh -c "(echo '\#include '; echo 'int main(void) { bfd_demangle(0, 0, 0); return 0; }') | $(CC) -x c - $(ALL_CFLAGS) -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) -lbfd "$(QUIET_STDERR)" && echo y") -- cgit v0.10.2 From a93d2f1744206827ccf416e2cdc5018aa503314e Mon Sep 17 00:00:00 2001 From: Changli Gao Date: Fri, 7 May 2010 14:33:26 +0800 Subject: sched, wait: Use wrapper functions epoll should not touch flags in wait_queue_t. This patch introduces a new function __add_wait_queue_exclusive(), for the users, who use wait queue as a LIFO queue. __add_wait_queue_tail_exclusive() is introduced too instead of add_wait_queue_exclusive_locked(). remove_wait_queue_locked() is removed, as it is a duplicate of __remove_wait_queue(), disliked by users, and with less users. Signed-off-by: Changli Gao Signed-off-by: Peter Zijlstra Cc: Alexander Viro Cc: Paul Menage Cc: Li Zefan Cc: Davide Libenzi Cc: LKML-Reference: <1273214006-2979-1-git-send-email-xiaosuo@gmail.com> Signed-off-by: Ingo Molnar diff --git a/fs/eventpoll.c b/fs/eventpoll.c index bd056a5..3817149 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -1140,8 +1140,7 @@ retry: * ep_poll_callback() when events will become available. */ init_waitqueue_entry(&wait, current); - wait.flags |= WQ_FLAG_EXCLUSIVE; - __add_wait_queue(&ep->wq, &wait); + __add_wait_queue_exclusive(&ep->wq, &wait); for (;;) { /* diff --git a/include/linux/wait.h b/include/linux/wait.h index a48e16b..76d96d0 100644 --- a/include/linux/wait.h +++ b/include/linux/wait.h @@ -127,12 +127,26 @@ static inline void __add_wait_queue(wait_queue_head_t *head, wait_queue_t *new) /* * Used for wake-one threads: */ +static inline void __add_wait_queue_exclusive(wait_queue_head_t *q, + wait_queue_t *wait) +{ + wait->flags |= WQ_FLAG_EXCLUSIVE; + __add_wait_queue(q, wait); +} + static inline void __add_wait_queue_tail(wait_queue_head_t *head, - wait_queue_t *new) + wait_queue_t *new) { list_add_tail(&new->task_list, &head->task_list); } +static inline void __add_wait_queue_tail_exclusive(wait_queue_head_t *q, + wait_queue_t *wait) +{ + wait->flags |= WQ_FLAG_EXCLUSIVE; + __add_wait_queue_tail(q, wait); +} + static inline void __remove_wait_queue(wait_queue_head_t *head, wait_queue_t *old) { @@ -404,25 +418,6 @@ do { \ }) /* - * Must be called with the spinlock in the wait_queue_head_t held. - */ -static inline void add_wait_queue_exclusive_locked(wait_queue_head_t *q, - wait_queue_t * wait) -{ - wait->flags |= WQ_FLAG_EXCLUSIVE; - __add_wait_queue_tail(q, wait); -} - -/* - * Must be called with the spinlock in the wait_queue_head_t held. - */ -static inline void remove_wait_queue_locked(wait_queue_head_t *q, - wait_queue_t * wait) -{ - __remove_wait_queue(q, wait); -} - -/* * These are the old interfaces to sleep waiting for an event. * They are racy. DO NOT use them, use the wait_event* interfaces above. * We plan to remove these interfaces. diff --git a/kernel/cgroup.c b/kernel/cgroup.c index e2769e1..4a07d05 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -3010,7 +3010,7 @@ static int cgroup_event_wake(wait_queue_t *wait, unsigned mode, unsigned long flags = (unsigned long)key; if (flags & POLLHUP) { - remove_wait_queue_locked(event->wqh, &event->wait); + __remove_wait_queue(event->wqh, &event->wait); spin_lock(&cgrp->event_list_lock); list_del(&event->list); spin_unlock(&cgrp->event_list_lock); diff --git a/kernel/sched.c b/kernel/sched.c index 39aa9c7..b531d79 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -3983,8 +3983,7 @@ do_wait_for_common(struct completion *x, long timeout, int state) if (!x->done) { DECLARE_WAITQUEUE(wait, current); - wait.flags |= WQ_FLAG_EXCLUSIVE; - __add_wait_queue_tail(&x->wait, &wait); + __add_wait_queue_tail_exclusive(&x->wait, &wait); do { if (signal_pending_state(state, current)) { timeout = -ERESTARTSYS; -- cgit v0.10.2 From 0ceed5db321ac0f9782e77dda476ebe28a8e2199 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 11 May 2010 09:53:18 -0700 Subject: ceph: unregister osd request on failure The osd request wasn't being unregistered when the osd returned a failure code, even though the result was returned to the caller. This would cause it to eventually time out, and then crash the kernel when it tried to resend the request using a stale page vector. Signed-off-by: Sage Weil diff --git a/fs/ceph/osd_client.c b/fs/ceph/osd_client.c index c7b4ded..8128082a 100644 --- a/fs/ceph/osd_client.c +++ b/fs/ceph/osd_client.c @@ -779,16 +779,18 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg, struct ceph_osd_request *req; u64 tid; int numops, object_len, flags; + s32 result; tid = le64_to_cpu(msg->hdr.tid); if (msg->front.iov_len < sizeof(*rhead)) goto bad; numops = le32_to_cpu(rhead->num_ops); object_len = le32_to_cpu(rhead->object_len); + result = le32_to_cpu(rhead->result); if (msg->front.iov_len != sizeof(*rhead) + object_len + numops * sizeof(struct ceph_osd_op)) goto bad; - dout("handle_reply %p tid %llu\n", msg, tid); + dout("handle_reply %p tid %llu result %d\n", msg, tid, (int)result); /* lookup */ mutex_lock(&osdc->request_mutex); @@ -834,7 +836,8 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg, dout("handle_reply tid %llu flags %d\n", tid, flags); /* either this is a read, or we got the safe response */ - if ((flags & CEPH_OSD_FLAG_ONDISK) || + if (result < 0 || + (flags & CEPH_OSD_FLAG_ONDISK) || ((flags & CEPH_OSD_FLAG_WRITE) == 0)) __unregister_request(osdc, req); -- cgit v0.10.2 From 04d000eb358919043da538f197d63f2a5924a525 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 7 May 2010 11:26:34 -0700 Subject: ceph: fix open file counting on snapped inodes when mds returns no caps It's possible the MDS will not issue caps on a snapped inode, in which case an open request may not __ceph_get_fmode(), botching the open file counting. (This is actually a server bug, but the client shouldn't BUG out in this case.) Signed-off-by: Sage Weil diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 261f3e6..85b4d2f 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -733,6 +733,10 @@ no_change: __ceph_get_fmode(ci, cap_fmode); spin_unlock(&inode->i_lock); } + } else if (cap_fmode >= 0) { + pr_warning("mds issued no caps on %llx.%llx\n", + ceph_vinop(inode)); + __ceph_get_fmode(ci, cap_fmode); } /* update delegation info? */ -- cgit v0.10.2 From d85b705663905b3dae30007f824355bdcfcf3f00 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 10 May 2010 10:24:48 -0700 Subject: ceph: resubmit requests on pg mapping change (not just primary change) OSD requests need to be resubmitted on any pg mapping change, not just when the pg primary changes. Resending only when the primary changes results in occasional 'hung' requests during osd cluster recovery or rebalancing. Signed-off-by: Sage Weil diff --git a/fs/ceph/osd_client.c b/fs/ceph/osd_client.c index 8128082a..3514f71 100644 --- a/fs/ceph/osd_client.c +++ b/fs/ceph/osd_client.c @@ -565,7 +565,8 @@ static int __map_osds(struct ceph_osd_client *osdc, { struct ceph_osd_request_head *reqhead = req->r_request->front.iov_base; struct ceph_pg pgid; - int o = -1; + int acting[CEPH_PG_MAX_SIZE]; + int o = -1, num = 0; int err; dout("map_osds %p tid %lld\n", req, req->r_tid); @@ -576,10 +577,16 @@ static int __map_osds(struct ceph_osd_client *osdc, pgid = reqhead->layout.ol_pgid; req->r_pgid = pgid; - o = ceph_calc_pg_primary(osdc->osdmap, pgid); + err = ceph_calc_pg_acting(osdc->osdmap, pgid, acting); + if (err > 0) { + o = acting[0]; + num = err; + } if ((req->r_osd && req->r_osd->o_osd == o && - req->r_sent >= req->r_osd->o_incarnation) || + req->r_sent >= req->r_osd->o_incarnation && + req->r_num_pg_osds == num && + memcmp(req->r_pg_osds, acting, sizeof(acting[0])*num) == 0) || (req->r_osd == NULL && o == -1)) return 0; /* no change */ @@ -587,6 +594,10 @@ static int __map_osds(struct ceph_osd_client *osdc, req->r_tid, le32_to_cpu(pgid.pool), le16_to_cpu(pgid.ps), o, req->r_osd ? req->r_osd->o_osd : -1); + /* record full pg acting set */ + memcpy(req->r_pg_osds, acting, sizeof(acting[0]) * num); + req->r_num_pg_osds = num; + if (req->r_osd) { __cancel_request(req); list_del_init(&req->r_osd_item); @@ -612,7 +623,7 @@ static int __map_osds(struct ceph_osd_client *osdc, __remove_osd_from_lru(req->r_osd); list_add(&req->r_osd_item, &req->r_osd->o_requests); } - err = 1; /* osd changed */ + err = 1; /* osd or pg changed */ out: return err; diff --git a/fs/ceph/osd_client.h b/fs/ceph/osd_client.h index c5191d6..ce77698 100644 --- a/fs/ceph/osd_client.h +++ b/fs/ceph/osd_client.h @@ -48,6 +48,8 @@ struct ceph_osd_request { struct list_head r_osd_item; struct ceph_osd *r_osd; struct ceph_pg r_pgid; + int r_pg_osds[CEPH_PG_MAX_SIZE]; + int r_num_pg_osds; struct ceph_connection *r_con_filling_msg; diff --git a/fs/ceph/osdmap.c b/fs/ceph/osdmap.c index 2e2c15e..cfdd8f4 100644 --- a/fs/ceph/osdmap.c +++ b/fs/ceph/osdmap.c @@ -1041,12 +1041,33 @@ static int *calc_pg_raw(struct ceph_osdmap *osdmap, struct ceph_pg pgid, } /* + * Return acting set for given pgid. + */ +int ceph_calc_pg_acting(struct ceph_osdmap *osdmap, struct ceph_pg pgid, + int *acting) +{ + int rawosds[CEPH_PG_MAX_SIZE], *osds; + int i, o, num = CEPH_PG_MAX_SIZE; + + osds = calc_pg_raw(osdmap, pgid, rawosds, &num); + if (!osds) + return -1; + + /* primary is first up osd */ + o = 0; + for (i = 0; i < num; i++) + if (ceph_osd_is_up(osdmap, osds[i])) + acting[o++] = osds[i]; + return o; +} + +/* * Return primary osd for given pgid, or -1 if none. */ int ceph_calc_pg_primary(struct ceph_osdmap *osdmap, struct ceph_pg pgid) { - int rawosds[10], *osds; - int i, num = ARRAY_SIZE(rawosds); + int rawosds[CEPH_PG_MAX_SIZE], *osds; + int i, num = CEPH_PG_MAX_SIZE; osds = calc_pg_raw(osdmap, pgid, rawosds, &num); if (!osds) @@ -1054,9 +1075,7 @@ int ceph_calc_pg_primary(struct ceph_osdmap *osdmap, struct ceph_pg pgid) /* primary is first up osd */ for (i = 0; i < num; i++) - if (ceph_osd_is_up(osdmap, osds[i])) { + if (ceph_osd_is_up(osdmap, osds[i])) return osds[i]; - break; - } return -1; } diff --git a/fs/ceph/osdmap.h b/fs/ceph/osdmap.h index 8bc9f1e..970b547 100644 --- a/fs/ceph/osdmap.h +++ b/fs/ceph/osdmap.h @@ -120,6 +120,8 @@ extern int ceph_calc_object_layout(struct ceph_object_layout *ol, const char *oid, struct ceph_file_layout *fl, struct ceph_osdmap *osdmap); +extern int ceph_calc_pg_acting(struct ceph_osdmap *osdmap, struct ceph_pg pgid, + int *acting); extern int ceph_calc_pg_primary(struct ceph_osdmap *osdmap, struct ceph_pg pgid); diff --git a/fs/ceph/rados.h b/fs/ceph/rados.h index a1fc1d0..fd56451 100644 --- a/fs/ceph/rados.h +++ b/fs/ceph/rados.h @@ -58,6 +58,7 @@ struct ceph_timespec { #define CEPH_PG_LAYOUT_LINEAR 2 #define CEPH_PG_LAYOUT_HYBRID 3 +#define CEPH_PG_MAX_SIZE 16 /* max # osds in a single pg */ /* * placement group. -- cgit v0.10.2 From 9abf82b8bc93dd904738a71ca69aa5df356d4d24 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Mon, 10 May 2010 21:58:38 -0700 Subject: ceph: fix locking for waking session requests after reconnect The session->s_waiting list is protected by mdsc->mutex, not s_mutex. This was causing (rare) s_waiting list corruption. Fix errors paths too, while we're here. A more thorough cleanup of this function is coming soon. Signed-off-by: Sage Weil diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 60a9a4a..eccc0ec 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -2136,7 +2136,7 @@ static void send_mds_reconnect(struct ceph_mds_client *mdsc, int mds) struct ceph_mds_session *session = NULL; struct ceph_msg *reply; struct rb_node *p; - int err; + int err = -ENOMEM; struct ceph_pagelist *pagelist; pr_info("reconnect to recovering mds%d\n", mds); @@ -2185,7 +2185,7 @@ static void send_mds_reconnect(struct ceph_mds_client *mdsc, int mds) goto fail; err = iterate_session_caps(session, encode_caps_cb, pagelist); if (err < 0) - goto out; + goto fail; /* * snaprealms. we provide mds with the ino, seq (version), and @@ -2213,28 +2213,31 @@ send: reply->nr_pages = calc_pages_for(0, pagelist->length); ceph_con_send(&session->s_con, reply); - if (session) { - session->s_state = CEPH_MDS_SESSION_OPEN; - __wake_requests(mdsc, &session->s_waiting); - } + session->s_state = CEPH_MDS_SESSION_OPEN; + mutex_unlock(&session->s_mutex); + + mutex_lock(&mdsc->mutex); + __wake_requests(mdsc, &session->s_waiting); + mutex_unlock(&mdsc->mutex); + + ceph_put_mds_session(session); -out: up_read(&mdsc->snap_rwsem); - if (session) { - mutex_unlock(&session->s_mutex); - ceph_put_mds_session(session); - } mutex_lock(&mdsc->mutex); return; fail: ceph_msg_put(reply); + up_read(&mdsc->snap_rwsem); + mutex_unlock(&session->s_mutex); + ceph_put_mds_session(session); fail_nomsg: ceph_pagelist_release(pagelist); kfree(pagelist); fail_nopagelist: - pr_err("ENOMEM preparing reconnect for mds%d\n", mds); - goto out; + pr_err("error %d preparing reconnect for mds%d\n", err, mds); + mutex_lock(&mdsc->mutex); + return; } -- cgit v0.10.2 From 7d6fb7bd1919517937ec390f6ca2d7bcf4f89fb6 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Tue, 11 May 2010 10:21:38 -0600 Subject: ACPI: sleep: eliminate duplicate entries in acpisleep_dmi_table[] Duplicate entries ended up acpisleep_dmi_table[] by accident. They don't hurt functionality, but they are ugly, so let's get rid of them. Cc: stable@kernel.org Signed-off-by: Alex Chiang Signed-off-by: Linus Torvalds diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index e2e9925..baa76bb 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -475,101 +475,13 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { }, { .callback = init_set_sci_en_on_resume, - .ident = "Lenovo ThinkPad X201", + .ident = "Lenovo ThinkPad X201[s]", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201"), }, }, { - .callback = init_set_sci_en_on_resume, - .ident = "Lenovo ThinkPad X201", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201s"), - }, - }, - { - .callback = init_set_sci_en_on_resume, - .ident = "Lenovo ThinkPad T410", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T410"), - }, - }, - { - .callback = init_set_sci_en_on_resume, - .ident = "Lenovo ThinkPad T510", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T510"), - }, - }, - { - .callback = init_set_sci_en_on_resume, - .ident = "Lenovo ThinkPad W510", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W510"), - }, - }, - { - .callback = init_set_sci_en_on_resume, - .ident = "Lenovo ThinkPad X201", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201"), - }, - }, - { - .callback = init_set_sci_en_on_resume, - .ident = "Lenovo ThinkPad X201", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201s"), - }, - }, - { - .callback = init_set_sci_en_on_resume, - .ident = "Lenovo ThinkPad T410", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T410"), - }, - }, - { - .callback = init_set_sci_en_on_resume, - .ident = "Lenovo ThinkPad T510", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T510"), - }, - }, - { - .callback = init_set_sci_en_on_resume, - .ident = "Lenovo ThinkPad W510", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W510"), - }, - }, - { - .callback = init_set_sci_en_on_resume, - .ident = "Lenovo ThinkPad X201", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201"), - }, - }, - { - .callback = init_set_sci_en_on_resume, - .ident = "Lenovo ThinkPad X201", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201s"), - }, - }, - { .callback = init_old_suspend_ordering, .ident = "Panasonic CF51-2L", .matches = { -- cgit v0.10.2 From c61ea31dac0319ec64b33725917bda81fc293a25 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 11 May 2010 16:51:39 +0100 Subject: CacheFiles: Fix occasional EIO on call to vfs_unlink() Fix an occasional EIO returned by a call to vfs_unlink(): [ 4868.465413] CacheFiles: I/O Error: Unlink failed [ 4868.465444] FS-Cache: Cache cachefiles stopped due to I/O error [ 4947.320011] CacheFiles: File cache on md3 unregistering [ 4947.320041] FS-Cache: Withdrawing cache "mycache" [ 5127.348683] FS-Cache: Cache "mycache" added (type cachefiles) [ 5127.348716] CacheFiles: File cache on md3 registered [ 7076.871081] CacheFiles: I/O Error: Unlink failed [ 7076.871130] FS-Cache: Cache cachefiles stopped due to I/O error [ 7116.780891] CacheFiles: File cache on md3 unregistering [ 7116.780937] FS-Cache: Withdrawing cache "mycache" [ 7296.813394] FS-Cache: Cache "mycache" added (type cachefiles) [ 7296.813432] CacheFiles: File cache on md3 registered What happens is this: (1) A cached NFS file is seen to have become out of date, so NFS retires the object and immediately acquires a new object with the same key. (2) Retirement of the old object is done asynchronously - so the lookup/create to generate the new object may be done first. This can be a problem as the old object and the new object must exist at the same point in the backing filesystem (i.e. they must have the same pathname). (3) The lookup for the new object sees that a backing file already exists, checks to see whether it is valid and sees that it isn't. It then deletes that file and creates a new one on disk. (4) The retirement phase for the old file is then performed. It tries to delete the dentry it has, but ext4_unlink() returns -EIO because the inode attached to that dentry no longer matches the inode number associated with the filename in the parent directory. The trace below shows this quite well. [md5sum] ==> __fscache_relinquish_cookie(ffff88002d12fb58{NFS.fh,ffff88002ce62100},1) [md5sum] ==> __fscache_acquire_cookie({NFS.server},{NFS.fh},ffff88002ce62100) NFS has retired the old cookie and asked for a new one. [kslowd] ==> fscache_object_state_machine({OBJ52,OBJECT_ACTIVE,24}) [kslowd] <== fscache_object_state_machine() [->OBJECT_DYING] [kslowd] ==> fscache_object_state_machine({OBJ53,OBJECT_INIT,0}) [kslowd] <== fscache_object_state_machine() [->OBJECT_LOOKING_UP] [kslowd] ==> fscache_object_state_machine({OBJ52,OBJECT_DYING,24}) [kslowd] <== fscache_object_state_machine() [->OBJECT_RECYCLING] The old object (OBJ52) is going through the terminal states to get rid of it, whilst the new object - (OBJ53) - is coming into being. [kslowd] ==> fscache_object_state_machine({OBJ53,OBJECT_LOOKING_UP,0}) [kslowd] ==> cachefiles_walk_to_object({ffff88003029d8b8},OBJ53,@68,) [kslowd] lookup '@68' [kslowd] next -> ffff88002ce41bd0 positive [kslowd] advance [kslowd] lookup 'Es0g00og0_Nd_XCYe3BOzvXrsBLMlN6aw16M1htaA' [kslowd] next -> ffff8800369faac8 positive The new object has looked up the subdir in which the file would be in (getting dentry ffff88002ce41bd0) and then looked up the file itself (getting dentry ffff8800369faac8). [kslowd] validate 'Es0g00og0_Nd_XCYe3BOzvXrsBLMlN6aw16M1htaA' [kslowd] ==> cachefiles_bury_object(,'@68','Es0g00og0_Nd_XCYe3BOzvXrsBLMlN6aw16M1htaA') [kslowd] remove ffff8800369faac8 from ffff88002ce41bd0 [kslowd] unlink stale object [kslowd] <== cachefiles_bury_object() = 0 It then checks the file's xattrs to see if it's valid. NFS says that the auxiliary data indicate the file is out of date (obvious to us - that's why NFS ditched the old version and got a new one). CacheFiles then deletes the old file (dentry ffff8800369faac8). [kslowd] redo lookup [kslowd] lookup 'Es0g00og0_Nd_XCYe3BOzvXrsBLMlN6aw16M1htaA' [kslowd] next -> ffff88002cd94288 negative [kslowd] create -> ffff88002cd94288{ffff88002cdaf238{ino=148247}} CacheFiles then redoes the lookup and gets a negative result in a new dentry (ffff88002cd94288) which it then creates a file for. [kslowd] ==> cachefiles_mark_object_active(,OBJ53) [kslowd] <== cachefiles_mark_object_active() = 0 [kslowd] === OBTAINED_OBJECT === [kslowd] <== cachefiles_walk_to_object() = 0 [148247] [kslowd] <== fscache_object_state_machine() [->OBJECT_AVAILABLE] The new object is then marked active and the state machine moves to the available state - at which point NFS can start filling the object. [kslowd] ==> fscache_object_state_machine({OBJ52,OBJECT_RECYCLING,20}) [kslowd] ==> fscache_release_object() [kslowd] ==> cachefiles_drop_object({OBJ52,2}) [kslowd] ==> cachefiles_delete_object(,OBJ52{ffff8800369faac8}) The old object, meanwhile, goes on with being retired. If allocation occurs first, cachefiles_delete_object() has to wait for dir->d_inode->i_mutex to become available before it can continue. [kslowd] ==> cachefiles_bury_object(,'@68','Es0g00og0_Nd_XCYe3BOzvXrsBLMlN6aw16M1htaA') [kslowd] remove ffff8800369faac8 from ffff88002ce41bd0 [kslowd] unlink stale object EXT4-fs warning (device sda6): ext4_unlink: Inode number mismatch in unlink (148247!=148193) CacheFiles: I/O Error: Unlink failed FS-Cache: Cache cachefiles stopped due to I/O error CacheFiles then tries to delete the file for the old object, but the dentry it has (ffff8800369faac8) no longer points to a valid inode for that directory entry, and so ext4_unlink() returns -EIO when de->inode does not match i_ino. [kslowd] <== cachefiles_bury_object() = -5 [kslowd] <== cachefiles_delete_object() = -5 [kslowd] <== fscache_object_state_machine() [->OBJECT_DEAD] [kslowd] ==> fscache_object_state_machine({OBJ53,OBJECT_AVAILABLE,0}) [kslowd] <== fscache_object_state_machine() [->OBJECT_ACTIVE] (Note that the above trace includes extra information beyond that produced by the upstream code). The fix is to note when an object that is being retired has had its object deleted preemptively by a replacement object that is being created, and to skip the second removal attempt in such a case. Reported-by: Greg M Reported-by: Mark Moseley Reported-by: Romain DEGEZ Signed-off-by: David Howells Signed-off-by: Linus Torvalds diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h index f7c255f..a8cd821 100644 --- a/fs/cachefiles/internal.h +++ b/fs/cachefiles/internal.h @@ -34,6 +34,7 @@ struct cachefiles_object { loff_t i_size; /* object size */ unsigned long flags; #define CACHEFILES_OBJECT_ACTIVE 0 /* T if marked active */ +#define CACHEFILES_OBJECT_BURIED 1 /* T if preemptively buried */ atomic_t usage; /* object usage count */ uint8_t type; /* object type */ uint8_t new; /* T if object new */ diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c index d5db84a1e..f4a7840 100644 --- a/fs/cachefiles/namei.c +++ b/fs/cachefiles/namei.c @@ -93,6 +93,59 @@ static noinline void cachefiles_printk_object(struct cachefiles_object *object, } /* + * mark the owner of a dentry, if there is one, to indicate that that dentry + * has been preemptively deleted + * - the caller must hold the i_mutex on the dentry's parent as required to + * call vfs_unlink(), vfs_rmdir() or vfs_rename() + */ +static void cachefiles_mark_object_buried(struct cachefiles_cache *cache, + struct dentry *dentry) +{ + struct cachefiles_object *object; + struct rb_node *p; + + _enter(",'%*.*s'", + dentry->d_name.len, dentry->d_name.len, dentry->d_name.name); + + write_lock(&cache->active_lock); + + p = cache->active_nodes.rb_node; + while (p) { + object = rb_entry(p, struct cachefiles_object, active_node); + if (object->dentry > dentry) + p = p->rb_left; + else if (object->dentry < dentry) + p = p->rb_right; + else + goto found_dentry; + } + + write_unlock(&cache->active_lock); + _leave(" [no owner]"); + return; + + /* found the dentry for */ +found_dentry: + kdebug("preemptive burial: OBJ%x [%s] %p", + object->fscache.debug_id, + fscache_object_states[object->fscache.state], + dentry); + + if (object->fscache.state < FSCACHE_OBJECT_DYING) { + printk(KERN_ERR "\n"); + printk(KERN_ERR "CacheFiles: Error:" + " Can't preemptively bury live object\n"); + cachefiles_printk_object(object, NULL); + } else if (test_and_set_bit(CACHEFILES_OBJECT_BURIED, &object->flags)) { + printk(KERN_ERR "CacheFiles: Error:" + " Object already preemptively buried\n"); + } + + write_unlock(&cache->active_lock); + _leave(" [owner marked]"); +} + +/* * record the fact that an object is now active */ static int cachefiles_mark_object_active(struct cachefiles_cache *cache, @@ -219,7 +272,8 @@ requeue: */ static int cachefiles_bury_object(struct cachefiles_cache *cache, struct dentry *dir, - struct dentry *rep) + struct dentry *rep, + bool preemptive) { struct dentry *grave, *trap; char nbuffer[8 + 8 + 1]; @@ -229,11 +283,16 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache, dir->d_name.len, dir->d_name.len, dir->d_name.name, rep->d_name.len, rep->d_name.len, rep->d_name.name); + _debug("remove %p from %p", rep, dir); + /* non-directories can just be unlinked */ if (!S_ISDIR(rep->d_inode->i_mode)) { _debug("unlink stale object"); ret = vfs_unlink(dir->d_inode, rep); + if (preemptive) + cachefiles_mark_object_buried(cache, rep); + mutex_unlock(&dir->d_inode->i_mutex); if (ret == -EIO) @@ -325,6 +384,9 @@ try_again: if (ret != 0 && ret != -ENOMEM) cachefiles_io_error(cache, "Rename failed with error %d", ret); + if (preemptive) + cachefiles_mark_object_buried(cache, rep); + unlock_rename(cache->graveyard, dir); dput(grave); _leave(" = 0"); @@ -340,7 +402,7 @@ int cachefiles_delete_object(struct cachefiles_cache *cache, struct dentry *dir; int ret; - _enter(",{%p}", object->dentry); + _enter(",OBJ%x{%p}", object->fscache.debug_id, object->dentry); ASSERT(object->dentry); ASSERT(object->dentry->d_inode); @@ -350,15 +412,25 @@ int cachefiles_delete_object(struct cachefiles_cache *cache, mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); - /* we need to check that our parent is _still_ our parent - it may have - * been renamed */ - if (dir == object->dentry->d_parent) { - ret = cachefiles_bury_object(cache, dir, object->dentry); - } else { - /* it got moved, presumably by cachefilesd culling it, so it's - * no longer in the key path and we can ignore it */ + if (test_bit(CACHEFILES_OBJECT_BURIED, &object->flags)) { + /* object allocation for the same key preemptively deleted this + * object's file so that it could create its own file */ + _debug("object preemptively buried"); mutex_unlock(&dir->d_inode->i_mutex); ret = 0; + } else { + /* we need to check that our parent is _still_ our parent - it + * may have been renamed */ + if (dir == object->dentry->d_parent) { + ret = cachefiles_bury_object(cache, dir, + object->dentry, false); + } else { + /* it got moved, presumably by cachefilesd culling it, + * so it's no longer in the key path and we can ignore + * it */ + mutex_unlock(&dir->d_inode->i_mutex); + ret = 0; + } } dput(dir); @@ -381,7 +453,9 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent, const char *name; int ret, nlen; - _enter("{%p},,%s,", parent->dentry, key); + _enter("OBJ%x{%p},OBJ%x,%s,", + parent->fscache.debug_id, parent->dentry, + object->fscache.debug_id, key); cache = container_of(parent->fscache.cache, struct cachefiles_cache, cache); @@ -509,7 +583,7 @@ lookup_again: * mutex) */ object->dentry = NULL; - ret = cachefiles_bury_object(cache, dir, next); + ret = cachefiles_bury_object(cache, dir, next, true); dput(next); next = NULL; @@ -828,7 +902,7 @@ int cachefiles_cull(struct cachefiles_cache *cache, struct dentry *dir, /* actually remove the victim (drops the dir mutex) */ _debug("bury"); - ret = cachefiles_bury_object(cache, dir, victim); + ret = cachefiles_bury_object(cache, dir, victim, false); if (ret < 0) goto error; -- cgit v0.10.2 From 3d69438031b00c601c991ab447cafb7d5c3c59a6 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Tue, 11 May 2010 14:59:55 -0400 Subject: cifs: guard against hardlinking directories When we made serverino the default, we trusted that the field sent by the server in the "uniqueid" field was actually unique. It turns out that it isn't reliably so. Samba, in particular, will just put the st_ino in the uniqueid field when unix extensions are enabled. When a share spans multiple filesystems, it's quite possible that there will be collisions. This is a server bug, but when the inodes in question are a directory (as is often the case) and there is a collision with the root inode of the mount, the result is a kernel panic on umount. Fix this by checking explicitly for directory inodes with the same uniqueid. If that is the case, then we can assume that using server inode numbers will be a problem and that they should be disabled. Fixes Samba bugzilla 7407 Signed-off-by: Jeff Layton CC: Stable Reviewed-and-Tested-by: Suresh Jayaraman Signed-off-by: Steve French diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index ecf0ffb..0c2fd17 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -502,6 +502,7 @@ struct dfs_info3_param { #define CIFS_FATTR_DFS_REFERRAL 0x1 #define CIFS_FATTR_DELETE_PENDING 0x2 #define CIFS_FATTR_NEED_REVAL 0x4 +#define CIFS_FATTR_INO_COLLISION 0x8 struct cifs_fattr { u32 cf_flags; diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 35ec117..29b9ea2 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -715,6 +715,16 @@ cifs_find_inode(struct inode *inode, void *opaque) if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid) return 0; + /* + * uh oh -- it's a directory. We can't use it since hardlinked dirs are + * verboten. Disable serverino and return it as if it were found, the + * caller can discard it, generate a uniqueid and retry the find + */ + if (S_ISDIR(inode->i_mode) && !list_empty(&inode->i_dentry)) { + fattr->cf_flags |= CIFS_FATTR_INO_COLLISION; + cifs_autodisable_serverino(CIFS_SB(inode->i_sb)); + } + return 1; } @@ -734,15 +744,22 @@ cifs_iget(struct super_block *sb, struct cifs_fattr *fattr) unsigned long hash; struct inode *inode; +retry_iget5_locked: cFYI(1, ("looking for uniqueid=%llu", fattr->cf_uniqueid)); /* hash down to 32-bits on 32-bit arch */ hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid); inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr); - - /* we have fattrs in hand, update the inode */ if (inode) { + /* was there a problematic inode number collision? */ + if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) { + iput(inode); + fattr->cf_uniqueid = iunique(sb, ROOT_I); + fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION; + goto retry_iget5_locked; + } + cifs_fattr_to_inode(inode, fattr); if (sb->s_flags & MS_NOATIME) inode->i_flags |= S_NOATIME | S_NOCMTIME; -- cgit v0.10.2 From 3798ed7bc7ade26d3f59506cd06288615dfc7585 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 11 May 2010 18:01:23 -0300 Subject: perf ui: Add ui_helpline methods MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Initially this was just to be able to have a printf like method to prepare the formatted string and then pass to newtPushHelpLine, but as we already have for ui_progress, etc, its a step in identifying a restricted, highlevel set of widgets we can then have implementations for multiple widget sets (GTK, etc). Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index 638b519..daa86ef 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -57,6 +57,43 @@ void ui_progress__delete(struct ui_progress *self) free(self); } +static void ui_helpline__pop(void) +{ + newtPopHelpLine(); +} + +static void ui_helpline__push(const char *msg) +{ + newtPushHelpLine(msg); +} + +static void ui_helpline__vpush(const char *fmt, va_list ap) +{ + char *s; + + if (vasprintf(&s, fmt, ap) < 0) + vfprintf(stderr, fmt, ap); + else { + ui_helpline__push(s); + free(s); + } +} + +static void ui_helpline__fpush(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + ui_helpline__vpush(fmt, ap); + va_end(ap); +} + +static void ui_helpline__puts(const char *msg) +{ + ui_helpline__pop(); + ui_helpline__push(msg); +} + static char browser__last_msg[1024]; int browser__show_help(const char *format, va_list ap) @@ -69,8 +106,7 @@ int browser__show_help(const char *format, va_list ap) backlog += ret; if (browser__last_msg[backlog - 1] == '\n') { - newtPopHelpLine(); - newtPushHelpLine(browser__last_msg); + ui_helpline__puts(browser__last_msg); newtRefresh(); backlog = 0; } @@ -340,7 +376,7 @@ static void map_symbol__annotate_browser(const struct map_symbol *self, if (fp == NULL) goto out_free_str; - newtPushHelpLine("Press ESC to exit"); + ui_helpline__push("Press ESC to exit"); newtGetScreenSize(&cols, &rows); tree = newtListbox(0, 0, rows - 5, NEWT_FLAG_SCROLL); @@ -370,7 +406,7 @@ static void map_symbol__annotate_browser(const struct map_symbol *self, newtFormRun(form, &es); newtFormDestroy(form); newtPopWindow(); - newtPopHelpLine(); + ui_helpline__pop(); out_free_str: free(str); } @@ -539,7 +575,7 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na if (browser == NULL) return -1; - newtPushHelpLine(helpline); + ui_helpline__push(helpline); hist_browser__title(msg, sizeof(msg), input_name, dso_filter, thread_filter); @@ -602,8 +638,7 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na do_annotate: if (choice == annotate) { if (browser->selection->map->dso->origin == DSO__ORIG_KERNEL) { - newtPopHelpLine(); - newtPushHelpLine("No vmlinux file found, can't " + ui_helpline__puts("No vmlinux file found, can't " "annotate with just a " "kallsyms file"); continue; @@ -611,13 +646,11 @@ do_annotate: map_symbol__annotate_browser(browser->selection, input_name); } else if (choice == zoom_dso) { if (dso_filter) { - newtPopHelpLine(); + ui_helpline__pop(); dso_filter = NULL; } else { - snprintf(msg, sizeof(msg), - "To zoom out press -> + \"Zoom out of %s DSO\"", - dso->kernel ? "the Kernel" : dso->short_name); - newtPushHelpLine(msg); + ui_helpline__fpush("To zoom out press -> + \"Zoom out of %s DSO\"", + dso->kernel ? "the Kernel" : dso->short_name); dso_filter = dso; } hists__filter_by_dso(self, dso_filter); @@ -627,14 +660,12 @@ do_annotate: goto out; } else if (choice == zoom_thread) { if (thread_filter) { - newtPopHelpLine(); + ui_helpline__pop(); thread_filter = NULL; } else { - snprintf(msg, sizeof(msg), - "To zoom out press -> + \"Zoom out of %s(%d) thread\"", - (thread->comm_set ? thread->comm : ""), - thread->pid); - newtPushHelpLine(msg); + ui_helpline__fpush("To zoom out press -> + \"Zoom out of %s(%d) thread\"", + thread->comm_set ? thread->comm : "", + thread->pid); thread_filter = thread; } hists__filter_by_thread(self, thread_filter); @@ -658,7 +689,7 @@ void setup_browser(void) use_browser = true; newtInit(); newtCls(); - newtPushHelpLine(" "); + ui_helpline__puts(" "); } void exit_browser(bool wait_for_ok) -- cgit v0.10.2 From 45c6ceb547ad2d98215351974a4686bf8cb13e14 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 11 May 2010 15:01:51 -0700 Subject: ceph: zero unused message header, footer fields We shouldn't leak any prior memory contents to other parties. And random data, particularly in the 'version' field, can cause problems down the line. Signed-off-by: Sage Weil diff --git a/fs/ceph/messenger.c b/fs/ceph/messenger.c index 509f57d..a3a8f36 100644 --- a/fs/ceph/messenger.c +++ b/fs/ceph/messenger.c @@ -2085,15 +2085,19 @@ struct ceph_msg *ceph_msg_new(int type, int front_len, kref_init(&m->kref); INIT_LIST_HEAD(&m->list_head); + m->hdr.tid = 0; m->hdr.type = cpu_to_le16(type); + m->hdr.priority = cpu_to_le16(CEPH_MSG_PRIO_DEFAULT); + m->hdr.version = 0; m->hdr.front_len = cpu_to_le32(front_len); m->hdr.middle_len = 0; m->hdr.data_len = cpu_to_le32(page_len); m->hdr.data_off = cpu_to_le16(page_off); - m->hdr.priority = cpu_to_le16(CEPH_MSG_PRIO_DEFAULT); + m->hdr.reserved = 0; m->footer.front_crc = 0; m->footer.middle_crc = 0; m->footer.data_crc = 0; + m->footer.flags = 0; m->front_max = front_len; m->front_is_vmalloc = false; m->more_to_follow = false; -- cgit v0.10.2 From 72d5a9f7a9542f88397558c65bcfc3b115a65e34 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Mon, 10 May 2010 17:12:17 -0700 Subject: rcu: remove all rcu head initializations, except on_stack initializations Remove all rcu head inits. We don't care about the RCU head state before passing it to call_rcu() anyway. Only leave the "on_stack" variants so debugobjects can keep track of objects on stack. Signed-off-by: Mathieu Desnoyers Signed-off-by: Paul E. McKenney diff --git a/include/linux/init_task.h b/include/linux/init_task.h index b1ed1cd..7996fc2 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h @@ -49,7 +49,6 @@ extern struct group_info init_groups; { .first = &init_task.pids[PIDTYPE_PGID].node }, \ { .first = &init_task.pids[PIDTYPE_SID].node }, \ }, \ - .rcu = RCU_HEAD_INIT, \ .level = 0, \ .numbers = { { \ .nr = 0, \ diff --git a/kernel/rcutiny.c b/kernel/rcutiny.c index b1804ff..38729d3 100644 --- a/kernel/rcutiny.c +++ b/kernel/rcutiny.c @@ -245,11 +245,13 @@ void rcu_barrier(void) { struct rcu_synchronize rcu; + init_rcu_head_on_stack(&rcu.head); init_completion(&rcu.completion); /* Will wake me after RCU finished. */ call_rcu(&rcu.head, wakeme_after_rcu); /* Wait for it. */ wait_for_completion(&rcu.completion); + destroy_rcu_head_on_stack(&rcu.head); } EXPORT_SYMBOL_GPL(rcu_barrier); @@ -257,11 +259,13 @@ void rcu_barrier_bh(void) { struct rcu_synchronize rcu; + init_rcu_head_on_stack(&rcu.head); init_completion(&rcu.completion); /* Will wake me after RCU finished. */ call_rcu_bh(&rcu.head, wakeme_after_rcu); /* Wait for it. */ wait_for_completion(&rcu.completion); + destroy_rcu_head_on_stack(&rcu.head); } EXPORT_SYMBOL_GPL(rcu_barrier_bh); @@ -269,11 +273,13 @@ void rcu_barrier_sched(void) { struct rcu_synchronize rcu; + init_rcu_head_on_stack(&rcu.head); init_completion(&rcu.completion); /* Will wake me after RCU finished. */ call_rcu_sched(&rcu.head, wakeme_after_rcu); /* Wait for it. */ wait_for_completion(&rcu.completion); + destroy_rcu_head_on_stack(&rcu.head); } EXPORT_SYMBOL_GPL(rcu_barrier_sched); diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c index 58df55b..077defb 100644 --- a/kernel/rcutorture.c +++ b/kernel/rcutorture.c @@ -464,9 +464,11 @@ static void rcu_bh_torture_synchronize(void) { struct rcu_bh_torture_synchronize rcu; + init_rcu_head_on_stack(&rcu.head); init_completion(&rcu.completion); call_rcu_bh(&rcu.head, rcu_bh_torture_wakeme_after_cb); wait_for_completion(&rcu.completion); + destroy_rcu_head_on_stack(&rcu.head); } static struct rcu_torture_ops rcu_bh_ops = { diff --git a/kernel/rcutree.c b/kernel/rcutree.c index ba69969..d443734 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -1484,11 +1484,13 @@ void synchronize_sched(void) if (rcu_blocking_is_gp()) return; + init_rcu_head_on_stack(&rcu.head); init_completion(&rcu.completion); /* Will wake me after RCU finished. */ call_rcu_sched(&rcu.head, wakeme_after_rcu); /* Wait for it. */ wait_for_completion(&rcu.completion); + destroy_rcu_head_on_stack(&rcu.head); } EXPORT_SYMBOL_GPL(synchronize_sched); @@ -1508,11 +1510,13 @@ void synchronize_rcu_bh(void) if (rcu_blocking_is_gp()) return; + init_rcu_head_on_stack(&rcu.head); init_completion(&rcu.completion); /* Will wake me after RCU finished. */ call_rcu_bh(&rcu.head, wakeme_after_rcu); /* Wait for it. */ wait_for_completion(&rcu.completion); + destroy_rcu_head_on_stack(&rcu.head); } EXPORT_SYMBOL_GPL(synchronize_rcu_bh); diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index ac7d80f..0e4f420 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h @@ -557,11 +557,13 @@ void synchronize_rcu(void) if (!rcu_scheduler_active) return; + init_rcu_head_on_stack(&rcu.head); init_completion(&rcu.completion); /* Will wake me after RCU finished. */ call_rcu(&rcu.head, wakeme_after_rcu); /* Wait for it. */ wait_for_completion(&rcu.completion); + destroy_rcu_head_on_stack(&rcu.head); } EXPORT_SYMBOL_GPL(synchronize_rcu); -- cgit v0.10.2 From c394f17799523fe4bc92d173b3d9ac2d240c76a2 Mon Sep 17 00:00:00 2001 From: Vasily Khoruzhick Date: Tue, 11 May 2010 09:55:07 +0300 Subject: ARM: S3C2440: Add HP iPAQ RX1950 machine support Signed-off-by: Vasily Khoruzhick Signed-off-by: Denis Grigoriev Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2440/Kconfig b/arch/arm/mach-s3c2440/Kconfig index 7f46526..a6c5df6 100644 --- a/arch/arm/mach-s3c2440/Kconfig +++ b/arch/arm/mach-s3c2440/Kconfig @@ -187,4 +187,17 @@ config MACH_MINI2440 Say Y here to select support for the MINI2440. Is a 10cm x 10cm board available via various sources. It can come with a 3.5" or 7" touch LCD. +config MACH_RX1950 + bool "HP iPAQ rx1950" + select CPU_S3C2442 + select S3C24XX_DCLK + select PM_H1940 if PM + select I2C + select S3C2410_PWM + select S3C_DEV_NAND + select S3C2410_IOTIMING if S3C2440_CPUFREQ + select S3C2440_XTAL_16934400 + help + Say Y here if you're using HP iPAQ rx1950 + endmenu diff --git a/arch/arm/mach-s3c2440/Makefile b/arch/arm/mach-s3c2440/Makefile index c85ba32..d5440fa 100644 --- a/arch/arm/mach-s3c2440/Makefile +++ b/arch/arm/mach-s3c2440/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o obj-$(CONFIG_MACH_AT2440EVB) += mach-at2440evb.o obj-$(CONFIG_MACH_MINI2440) += mach-mini2440.o obj-$(CONFIG_MACH_NEO1973_GTA02) += mach-gta02.o +obj-$(CONFIG_MACH_RX1950) += mach-rx1950.o # extra machine support diff --git a/arch/arm/mach-s3c2440/mach-rx1950.c b/arch/arm/mach-s3c2440/mach-rx1950.c new file mode 100644 index 0000000..8603b57 --- /dev/null +++ b/arch/arm/mach-s3c2440/mach-rx1950.c @@ -0,0 +1,582 @@ +/* linux/arch/arm/mach-s3c2440/mach-rx1950.c + * + * Copyright (c) 2006-2009 Victor Chukhantsev, Denis Grigoriev, + * Copyright (c) 2007-2010 Vasily Khoruzhick + * + * based on smdk2440 written by Ben Dooks + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LCD_PWM_PERIOD 192960 +#define LCD_PWM_DUTY 127353 + +static struct map_desc rx1950_iodesc[] __initdata = { +}; + +static struct s3c24xx_uart_clksrc rx1950_serial_clocks[] = { + [0] = { + .name = "fclk", + .divisor = 0x0a, + .min_baud = 0, + .max_baud = 0, + }, +}; + +static struct s3c2410_uartcfg rx1950_uartcfgs[] __initdata = { + [0] = { + .hwport = 0, + .flags = 0, + .ucon = 0x3c5, + .ulcon = 0x03, + .ufcon = 0x51, + .clocks = rx1950_serial_clocks, + .clocks_size = ARRAY_SIZE(rx1950_serial_clocks), + }, + [1] = { + .hwport = 1, + .flags = 0, + .ucon = 0x3c5, + .ulcon = 0x03, + .ufcon = 0x51, + .clocks = rx1950_serial_clocks, + .clocks_size = ARRAY_SIZE(rx1950_serial_clocks), + }, + /* IR port */ + [2] = { + .hwport = 2, + .flags = 0, + .ucon = 0x3c5, + .ulcon = 0x43, + .ufcon = 0xf1, + .clocks = rx1950_serial_clocks, + .clocks_size = ARRAY_SIZE(rx1950_serial_clocks), + }, +}; + +static struct s3c2410fb_display rx1950_display = { + .type = S3C2410_LCDCON1_TFT, + .width = 240, + .height = 320, + .xres = 240, + .yres = 320, + .bpp = 16, + + .pixclock = 260000, + .left_margin = 10, + .right_margin = 20, + .hsync_len = 10, + .upper_margin = 2, + .lower_margin = 2, + .vsync_len = 2, + + .lcdcon5 = S3C2410_LCDCON5_FRM565 | + S3C2410_LCDCON5_INVVCLK | + S3C2410_LCDCON5_INVVLINE | + S3C2410_LCDCON5_INVVFRAME | + S3C2410_LCDCON5_HWSWP | + (0x02 << 13) | + (0x02 << 15), + +}; + +static struct s3c2410fb_mach_info rx1950_lcd_cfg = { + .displays = &rx1950_display, + .num_displays = 1, + .default_display = 0, + + .lpcsel = 0x02, + .gpccon = 0xaa9556a9, + .gpccon_mask = 0xffc003fc, + .gpcup = 0x0000ffff, + .gpcup_mask = 0xffffffff, + + .gpdcon = 0xaa90aaa1, + .gpdcon_mask = 0xffc0fff0, + .gpdup = 0x0000fcfd, + .gpdup_mask = 0xffffffff, + +}; + +static struct pwm_device *lcd_pwm; + +void rx1950_lcd_power(int enable) +{ + int i; + static int enabled; + if (enabled == enable) + return; + if (!enable) { + + /* GPC11-GPC15->OUTPUT */ + for (i = 11; i < 16; i++) + gpio_direction_output(S3C2410_GPC(i), 1); + + /* Wait a bit here... */ + mdelay(100); + + /* GPD2-GPD7->OUTPUT */ + /* GPD11-GPD15->OUTPUT */ + /* GPD2-GPD7->1, GPD11-GPD15->1 */ + for (i = 2; i < 8; i++) + gpio_direction_output(S3C2410_GPD(i), 1); + for (i = 11; i < 16; i++) + gpio_direction_output(S3C2410_GPD(i), 1); + + /* Wait a bit here...*/ + mdelay(100); + + /* GPB0->OUTPUT, GPB0->0 */ + gpio_direction_output(S3C2410_GPB(0), 0); + + /* GPC1-GPC4->OUTPUT, GPC1-4->0 */ + for (i = 1; i < 5; i++) + gpio_direction_output(S3C2410_GPC(i), 0); + + /* GPC15-GPC11->0 */ + for (i = 11; i < 16; i++) + gpio_direction_output(S3C2410_GPC(i), 0); + + /* GPD15-GPD11->0, GPD2->GPD7->0 */ + for (i = 11; i < 16; i++) + gpio_direction_output(S3C2410_GPD(i), 0); + + for (i = 2; i < 8; i++) + gpio_direction_output(S3C2410_GPD(i), 0); + + /* GPC6->0, GPC7->0, GPC5->0 */ + gpio_direction_output(S3C2410_GPC(6), 0); + gpio_direction_output(S3C2410_GPC(7), 0); + gpio_direction_output(S3C2410_GPC(5), 0); + + /* GPB1->OUTPUT, GPB1->0 */ + gpio_direction_output(S3C2410_GPB(1), 0); + pwm_config(lcd_pwm, 0, LCD_PWM_PERIOD); + pwm_disable(lcd_pwm); + + /* GPC0->0, GPC10->0 */ + gpio_direction_output(S3C2410_GPC(0), 0); + gpio_direction_output(S3C2410_GPC(10), 0); + } else { + pwm_config(lcd_pwm, LCD_PWM_DUTY, LCD_PWM_PERIOD); + pwm_enable(lcd_pwm); + + gpio_direction_output(S3C2410_GPC(0), 1); + gpio_direction_output(S3C2410_GPC(5), 1); + + s3c_gpio_cfgpin(S3C2410_GPB(1), S3C2410_GPB1_TOUT1); + gpio_direction_output(S3C2410_GPC(7), 1); + + for (i = 1; i < 5; i++) + s3c_gpio_cfgpin(S3C2410_GPC(i), S3C_GPIO_SFN(2)); + + for (i = 11; i < 16; i++) + s3c_gpio_cfgpin(S3C2410_GPC(i), S3C_GPIO_SFN(2)); + + for (i = 2; i < 8; i++) + s3c_gpio_cfgpin(S3C2410_GPD(i), S3C_GPIO_SFN(2)); + + for (i = 11; i < 16; i++) + s3c_gpio_cfgpin(S3C2410_GPD(i), S3C_GPIO_SFN(2)); + + gpio_direction_output(S3C2410_GPC(10), 1); + gpio_direction_output(S3C2410_GPC(6), 1); + } + enabled = enable; +} + +static void rx1950_bl_power(int enable) +{ + static int enabled; + if (enabled == enable) + return; + if (!enable) { + gpio_direction_output(S3C2410_GPB(0), 0); + } else { + /* LED driver need a "push" to power on */ + gpio_direction_output(S3C2410_GPB(0), 1); + /* Warm up backlight for one period of PWM. + * Without this trick its almost impossible to + * enable backlight with low brightness value + */ + ndelay(48000); + s3c_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPB0_TOUT0); + } + enabled = enable; +} + +static int rx1950_backlight_init(struct device *dev) +{ + WARN_ON(gpio_request(S3C2410_GPB(0), "Backlight")); + lcd_pwm = pwm_request(1, "RX1950 LCD"); + if (IS_ERR(lcd_pwm)) { + dev_err(dev, "Unable to request PWM for LCD power!\n"); + return PTR_ERR(lcd_pwm); + } + + rx1950_lcd_power(1); + rx1950_bl_power(1); + + return 0; +} + +static void rx1950_backlight_exit(struct device *dev) +{ + rx1950_bl_power(0); + rx1950_lcd_power(0); + + pwm_free(lcd_pwm); + gpio_free(S3C2410_GPB(0)); +} + + +static int rx1950_backlight_notify(struct device *dev, int brightness) +{ + if (!brightness) { + rx1950_bl_power(0); + rx1950_lcd_power(0); + } else { + rx1950_lcd_power(1); + rx1950_bl_power(1); + } + return brightness; +} + +static struct platform_pwm_backlight_data rx1950_backlight_data = { + .pwm_id = 0, + .max_brightness = 24, + .dft_brightness = 4, + .pwm_period_ns = 48000, + .init = rx1950_backlight_init, + .notify = rx1950_backlight_notify, + .exit = rx1950_backlight_exit, +}; + +static struct platform_device rx1950_backlight = { + .name = "pwm-backlight", + .dev = { + .parent = &s3c_device_timer[0].dev, + .platform_data = &rx1950_backlight_data, + }, +}; + +static void rx1950_set_mmc_power(unsigned char power_mode, unsigned short vdd) +{ + switch (power_mode) { + case MMC_POWER_OFF: + gpio_direction_output(S3C2410_GPJ(1), 0); + break; + case MMC_POWER_UP: + case MMC_POWER_ON: + gpio_direction_output(S3C2410_GPJ(1), 1); + break; + default: + break; + } +} + +static struct s3c24xx_mci_pdata rx1950_mmc_cfg __initdata = { + .gpio_detect = S3C2410_GPF(5), + .gpio_wprotect = S3C2410_GPH(8), + .set_power = rx1950_set_mmc_power, + .ocr_avail = MMC_VDD_32_33, +}; + +static struct mtd_partition rx1950_nand_part[] = { + [0] = { + .name = "Boot0", + .offset = 0, + .size = 0x4000, + .mask_flags = MTD_WRITEABLE, + }, + [1] = { + .name = "Boot1", + .offset = MTDPART_OFS_APPEND, + .size = 0x40000, + .mask_flags = MTD_WRITEABLE, + }, + [2] = { + .name = "Kernel", + .offset = MTDPART_OFS_APPEND, + .size = 0x300000, + .mask_flags = 0, + }, + [3] = { + .name = "Filesystem", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + .mask_flags = 0, + }, +}; + +static struct s3c2410_nand_set rx1950_nand_sets[] = { + [0] = { + .name = "Internal", + .nr_chips = 1, + .nr_partitions = ARRAY_SIZE(rx1950_nand_part), + .partitions = rx1950_nand_part, + }, +}; + +static struct s3c2410_platform_nand rx1950_nand_info = { + .tacls = 25, + .twrph0 = 50, + .twrph1 = 15, + .nr_sets = ARRAY_SIZE(rx1950_nand_sets), + .sets = rx1950_nand_sets, +}; + +static void rx1950_udc_pullup(enum s3c2410_udc_cmd_e cmd) +{ + switch (cmd) { + case S3C2410_UDC_P_ENABLE: + gpio_direction_output(S3C2410_GPJ(5), 1); + break; + case S3C2410_UDC_P_DISABLE: + gpio_direction_output(S3C2410_GPJ(5), 0); + break; + case S3C2410_UDC_P_RESET: + break; + default: + break; + } +} + +static struct s3c2410_udc_mach_info rx1950_udc_cfg __initdata = { + .udc_command = rx1950_udc_pullup, + .vbus_pin = S3C2410_GPG(5), + .vbus_pin_inverted = 1, +}; + +static struct s3c2410_ts_mach_info rx1950_ts_cfg __initdata = { + .delay = 10000, + .presc = 49, + .oversampling_shift = 3, +}; + +static struct gpio_keys_button rx1950_gpio_keys_table[] = { + { + .code = KEY_POWER, + .gpio = S3C2410_GPF(0), + .active_low = 1, + .desc = "Power button", + .wakeup = 1, + }, + { + .code = KEY_F5, + .gpio = S3C2410_GPF(7), + .active_low = 1, + .desc = "Record button", + }, + { + .code = KEY_F1, + .gpio = S3C2410_GPG(0), + .active_low = 1, + .desc = "Calendar button", + }, + { + .code = KEY_F2, + .gpio = S3C2410_GPG(2), + .active_low = 1, + .desc = "Contacts button", + }, + { + .code = KEY_F3, + .gpio = S3C2410_GPG(3), + .active_low = 1, + .desc = "Mail button", + }, + { + .code = KEY_F4, + .gpio = S3C2410_GPG(7), + .active_low = 1, + .desc = "WLAN button", + }, + { + .code = KEY_LEFT, + .gpio = S3C2410_GPG(10), + .active_low = 1, + .desc = "Left button", + }, + { + .code = KEY_RIGHT, + .gpio = S3C2410_GPG(11), + .active_low = 1, + .desc = "Right button", + }, + { + .code = KEY_UP, + .gpio = S3C2410_GPG(4), + .active_low = 1, + .desc = "Up button", + }, + { + .code = KEY_DOWN, + .gpio = S3C2410_GPG(6), + .active_low = 1, + .desc = "Down button", + }, + { + .code = KEY_ENTER, + .gpio = S3C2410_GPG(9), + .active_low = 1, + .desc = "Ok button" + }, +}; + +static struct gpio_keys_platform_data rx1950_gpio_keys_data = { + .buttons = rx1950_gpio_keys_table, + .nbuttons = ARRAY_SIZE(rx1950_gpio_keys_table), +}; + +static struct platform_device rx1950_device_gpiokeys = { + .name = "gpio-keys", + .dev.platform_data = &rx1950_gpio_keys_data, +}; + +static struct s3c2410_platform_i2c rx1950_i2c_data = { + .flags = 0, + .slave_addr = 0x42, + .frequency = 400 * 1000, + .sda_delay = S3C2410_IICLC_SDA_DELAY5 | S3C2410_IICLC_FILTER_ON, +}; + +static struct platform_device *rx1950_devices[] __initdata = { + &s3c_device_lcd, + &s3c_device_wdt, + &s3c_device_i2c0, + &s3c_device_iis, + &s3c_device_usbgadget, + &s3c_device_rtc, + &s3c_device_nand, + &s3c_device_sdi, + &s3c_device_adc, + &s3c_device_ts, + &s3c_device_timer[0], + &s3c_device_timer[1], + &rx1950_backlight, + &rx1950_device_gpiokeys, +}; + +static struct clk *rx1950_clocks[] __initdata = { + &s3c24xx_clkout0, + &s3c24xx_clkout1, +}; + +static void __init rx1950_map_io(void) +{ + s3c24xx_clkout0.parent = &clk_h; + s3c24xx_clkout1.parent = &clk_f; + + s3c24xx_register_clocks(rx1950_clocks, ARRAY_SIZE(rx1950_clocks)); + + s3c24xx_init_io(rx1950_iodesc, ARRAY_SIZE(rx1950_iodesc)); + s3c24xx_init_clocks(16934000); + s3c24xx_init_uarts(rx1950_uartcfgs, ARRAY_SIZE(rx1950_uartcfgs)); + + /* setup PM */ + +#ifdef CONFIG_PM_H1940 + memcpy(phys_to_virt(H1940_SUSPEND_RESUMEAT), h1940_pm_return, 8); +#endif + + s3c_pm_init(); +} + +static void __init rx1950_init_machine(void) +{ + int i; + + s3c24xx_fb_set_platdata(&rx1950_lcd_cfg); + s3c24xx_udc_set_platdata(&rx1950_udc_cfg); + s3c24xx_ts_set_platdata(&rx1950_ts_cfg); + s3c24xx_mci_set_platdata(&rx1950_mmc_cfg); + s3c_i2c0_set_platdata(&rx1950_i2c_data); + s3c_nand_set_platdata(&rx1950_nand_info); + + /* Turn off suspend on both USB ports, and switch the + * selectable USB port to USB device mode. */ + s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST | + S3C2410_MISCCR_USBSUSPND0 | + S3C2410_MISCCR_USBSUSPND1, 0x0); + + WARN_ON(gpio_request(S3C2410_GPJ(5), "UDC pullup")); + gpio_direction_output(S3C2410_GPJ(5), 0); + + /* mmc power is disabled by default */ + WARN_ON(gpio_request(S3C2410_GPJ(1), "MMC power")); + gpio_direction_output(S3C2410_GPJ(1), 0); + + for (i = 0; i < 8; i++) + WARN_ON(gpio_request(S3C2410_GPC(i), "LCD power")); + + for (i = 10; i < 16; i++) + WARN_ON(gpio_request(S3C2410_GPC(i), "LCD power")); + + for (i = 2; i < 8; i++) + WARN_ON(gpio_request(S3C2410_GPD(i), "LCD power")); + + for (i = 11; i < 16; i++) + WARN_ON(gpio_request(S3C2410_GPD(i), "LCD power")); + + WARN_ON(gpio_request(S3C2410_GPB(1), "LCD power")); + + platform_add_devices(rx1950_devices, ARRAY_SIZE(rx1950_devices)); +} + +MACHINE_START(RX1950, "HP iPAQ RX1950") + /* Maintainers: Vasily Khoruzhick */ + .phys_io = S3C2410_PA_UART, + .io_pg_offst = (((u32) S3C24XX_VA_UART) >> 18) & 0xfffc, + .boot_params = S3C2410_SDRAM_PA + 0x100, + .map_io = rx1950_map_io, + .init_irq = s3c24xx_init_irq, + .init_machine = rx1950_init_machine, + .timer = &s3c24xx_timer, +MACHINE_END -- cgit v0.10.2 From c4761b69f4c3bd2f6e62d9cba6d78b5fd4b24203 Mon Sep 17 00:00:00 2001 From: Vasily Khoruzhick Date: Tue, 11 May 2010 09:55:09 +0300 Subject: ARM: S3C24XX: Locate kernel at 0x30108000 if PM_H1940 is enabled If PM_H1940 is enabled, kernel _must_ be located upper then 0x30008000, because this area (0x30000000-0x30100000) can be used by bootloader. If kernel is located at 0x30008000, bootloader will corrupt kernel's code during resume. Signed-off-by: Vasily Khoruzhick Signed-off-by: Ben Dooks diff --git a/arch/arm/Makefile b/arch/arm/Makefile index ed820e7..eddcbba 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -110,6 +110,8 @@ CHECKFLAGS += -D__arm__ head-y := arch/arm/kernel/head$(MMUEXT).o arch/arm/kernel/init_task.o textofs-y := 0x00008000 textofs-$(CONFIG_ARCH_CLPS711X) := 0x00028000 +# We don't want the htc bootloader to corrupt kernel during resume +textofs-$(CONFIG_PM_H1940) := 0x00108000 # SA1111 DMA bug: we don't want the kernel to live in precious DMA-able memory ifeq ($(CONFIG_ARCH_SA1100),y) textofs-$(CONFIG_SA1111) := 0x00208000 diff --git a/arch/arm/mach-s3c2410/Makefile.boot b/arch/arm/mach-s3c2410/Makefile.boot index 7dab2a0..58c1dd7 100644 --- a/arch/arm/mach-s3c2410/Makefile.boot +++ b/arch/arm/mach-s3c2410/Makefile.boot @@ -1,3 +1,7 @@ - zreladdr-y := 0x30008000 -params_phys-y := 0x30000100 - +ifeq ($(CONFIG_PM_H1940),y) + zreladdr-y := 0x30108000 + params_phys-y := 0x30100100 +else + zreladdr-y := 0x30008000 + params_phys-y := 0x30000100 +endif -- cgit v0.10.2 From 0741b7d2699d1e7b4ceab27522c9e5518b2dbd2c Mon Sep 17 00:00:00 2001 From: Vasily Khoruzhick Date: Tue, 11 May 2010 09:55:10 +0300 Subject: ARM: RX1950: Add suspend/resume support for RX1950 Signed-off-by: Vasily Khoruzhick Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/pm.c b/arch/arm/mach-s3c2410/pm.c index 966119c..6a61486 100644 --- a/arch/arm/mach-s3c2410/pm.c +++ b/arch/arm/mach-s3c2410/pm.c @@ -60,10 +60,10 @@ static void s3c2410_pm_prepare(void) __raw_writel(calc, phys_to_virt(H1940_SUSPEND_CHECKSUM)); } - /* the RX3715 uses similar code and the same H1940 and the + /* RX3715 and RX1950 use similar to H1940 code and the * same offsets for resume and checksum pointers */ - if (machine_is_rx3715()) { + if (machine_is_rx3715() || machine_is_rx1950()) { void *base = phys_to_virt(H1940_SUSPEND_CHECK); unsigned long ptr; unsigned long calc = 0; diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 241c24a..45a1bc2 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -869,9 +869,10 @@ void __init reserve_node_zero(pg_data_t *pgdat) if (machine_is_p720t()) res_size = 0x00014000; - /* H1940 and RX3715 need to reserve this for suspend */ + /* H1940, RX3715 and RX1950 need to reserve this for suspend */ - if (machine_is_h1940() || machine_is_rx3715()) { + if (machine_is_h1940() || machine_is_rx3715() + || machine_is_rx1950()) { reserve_bootmem_node(pgdat, 0x30003000, 0x1000, BOOTMEM_DEFAULT); reserve_bootmem_node(pgdat, 0x30081000, 0x1000, -- cgit v0.10.2 From 192ff91fc84e067a3babfddb96114a51c939548e Mon Sep 17 00:00:00 2001 From: Vasily Khoruzhick Date: Tue, 11 May 2010 09:55:11 +0300 Subject: ARM: RX1950: configure GPG13-15 as input before suspend According to datasheet GPG13-15 must be configured as input in NAND boot mode, otherwise device will not be able to wake up Signed-off-by: Vasily Khoruzhick Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/pm.c b/arch/arm/mach-s3c2410/pm.c index 6a61486..725636f 100644 --- a/arch/arm/mach-s3c2410/pm.c +++ b/arch/arm/mach-s3c2410/pm.c @@ -79,6 +79,17 @@ static void s3c2410_pm_prepare(void) if ( machine_is_aml_m5900() ) s3c2410_gpio_setpin(S3C2410_GPF(2), 1); + if (machine_is_rx1950()) { + /* According to S3C2442 user's manual, page 7-17, + * when the system is operating in NAND boot mode, + * the hardware pin configuration - EINT[23:21] – + * must be set as input for starting up after + * wakeup from sleep mode + */ + s3c_gpio_cfgpin(S3C2410_GPG(13), S3C2410_GPIO_INPUT); + s3c_gpio_cfgpin(S3C2410_GPG(14), S3C2410_GPIO_INPUT); + s3c_gpio_cfgpin(S3C2410_GPG(15), S3C2410_GPIO_INPUT); + } } static int s3c2410_pm_resume(struct sys_device *dev) -- cgit v0.10.2 From f33d7e2d2d113a63772bbc993cdec3b5327f0ef1 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Tue, 11 May 2010 14:06:43 -0700 Subject: dma-mapping: fix dma_sync_single_range_* dma_sync_single_range_for_cpu() and dma_sync_single_range_for_device() use a wrong address with a partial synchronization. Signed-off-by: FUJITA Tomonori Reviewed-by: Konrad Rzeszutek Wilk Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/include/asm-generic/dma-mapping-common.h b/include/asm-generic/dma-mapping-common.h index e694263..6920695 100644 --- a/include/asm-generic/dma-mapping-common.h +++ b/include/asm-generic/dma-mapping-common.h @@ -131,7 +131,7 @@ static inline void dma_sync_single_range_for_cpu(struct device *dev, debug_dma_sync_single_range_for_cpu(dev, addr, offset, size, dir); } else - dma_sync_single_for_cpu(dev, addr, size, dir); + dma_sync_single_for_cpu(dev, addr + offset, size, dir); } static inline void dma_sync_single_range_for_device(struct device *dev, @@ -148,7 +148,7 @@ static inline void dma_sync_single_range_for_device(struct device *dev, debug_dma_sync_single_range_for_device(dev, addr, offset, size, dir); } else - dma_sync_single_for_device(dev, addr, size, dir); + dma_sync_single_for_device(dev, addr + offset, size, dir); } static inline void -- cgit v0.10.2 From 3c904afd7358e9ef515eb5df36b6f25c2b7fc2da Mon Sep 17 00:00:00 2001 From: Denis Turischev Date: Tue, 11 May 2010 14:06:44 -0700 Subject: it8761e_gpio: fix bug in gpio numbering The SIO chip contains 16 possible gpio lines, not 14. The schematic was not read carefully. Signed-off-by: Denis Turischev Cc: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/gpio/it8761e_gpio.c b/drivers/gpio/it8761e_gpio.c index 753219c..41a9388 100644 --- a/drivers/gpio/it8761e_gpio.c +++ b/drivers/gpio/it8761e_gpio.c @@ -80,8 +80,8 @@ static int it8761e_gpio_get(struct gpio_chip *gc, unsigned gpio_num) u16 reg; u8 bit; - bit = gpio_num % 7; - reg = (gpio_num >= 7) ? gpio_ba + 1 : gpio_ba; + bit = gpio_num % 8; + reg = (gpio_num >= 8) ? gpio_ba + 1 : gpio_ba; return !!(inb(reg) & (1 << bit)); } @@ -91,8 +91,8 @@ static int it8761e_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num) u8 curr_dirs; u8 io_reg, bit; - bit = gpio_num % 7; - io_reg = (gpio_num >= 7) ? GPIO2X_IO : GPIO1X_IO; + bit = gpio_num % 8; + io_reg = (gpio_num >= 8) ? GPIO2X_IO : GPIO1X_IO; spin_lock(&sio_lock); @@ -116,8 +116,8 @@ static void it8761e_gpio_set(struct gpio_chip *gc, u8 curr_vals, bit; u16 reg; - bit = gpio_num % 7; - reg = (gpio_num >= 7) ? gpio_ba + 1 : gpio_ba; + bit = gpio_num % 8; + reg = (gpio_num >= 8) ? gpio_ba + 1 : gpio_ba; spin_lock(&sio_lock); @@ -135,8 +135,8 @@ static int it8761e_gpio_direction_out(struct gpio_chip *gc, { u8 curr_dirs, io_reg, bit; - bit = gpio_num % 7; - io_reg = (gpio_num >= 7) ? GPIO2X_IO : GPIO1X_IO; + bit = gpio_num % 8; + io_reg = (gpio_num >= 8) ? GPIO2X_IO : GPIO1X_IO; it8761e_gpio_set(gc, gpio_num, val); @@ -200,7 +200,7 @@ static int __init it8761e_gpio_init(void) return -EBUSY; it8761e_gpio_chip.base = -1; - it8761e_gpio_chip.ngpio = 14; + it8761e_gpio_chip.ngpio = 16; err = gpiochip_add(&it8761e_gpio_chip); if (err < 0) -- cgit v0.10.2 From 34441427aab4bdb3069a4ffcda69a99357abcb2e Mon Sep 17 00:00:00 2001 From: Robin Holt Date: Tue, 11 May 2010 14:06:46 -0700 Subject: revert "procfs: provide stack information for threads" and its fixup commits Originally, commit d899bf7b ("procfs: provide stack information for threads") attempted to introduce a new feature for showing where the threadstack was located and how many pages are being utilized by the stack. Commit c44972f1 ("procfs: disable per-task stack usage on NOMMU") was applied to fix the NO_MMU case. Commit 89240ba0 ("x86, fs: Fix x86 procfs stack information for threads on 64-bit") was applied to fix a bug in ia32 executables being loaded. Commit 9ebd4eba7 ("procfs: fix /proc//stat stack pointer for kernel threads") was applied to fix a bug which had kernel threads printing a userland stack address. Commit 1306d603f ('proc: partially revert "procfs: provide stack information for threads"') was then applied to revert the stack pages being used to solve a significant performance regression. This patch nearly undoes the effect of all these patches. The reason for reverting these is it provides an unusable value in field 28. For x86_64, a fork will result in the task->stack_start value being updated to the current user top of stack and not the stack start address. This unpredictability of the stack_start value makes it worthless. That includes the intended use of showing how much stack space a thread has. Other architectures will get different values. As an example, ia64 gets 0. The do_fork() and copy_process() functions appear to treat the stack_start and stack_size parameters as architecture specific. I only partially reverted c44972f1 ("procfs: disable per-task stack usage on NOMMU") . If I had completely reverted it, I would have had to change mm/Makefile only build pagewalk.o when CONFIG_PROC_PAGE_MONITOR is configured. Since I could not test the builds without significant effort, I decided to not change mm/Makefile. I only partially reverted 89240ba0 ("x86, fs: Fix x86 procfs stack information for threads on 64-bit") . I left the KSTK_ESP() change in place as that seemed worthwhile. Signed-off-by: Robin Holt Cc: Stefani Seibold Cc: KOSAKI Motohiro Cc: Michal Simek Cc: Ingo Molnar Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index a4f30fa..1e359b6 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt @@ -316,7 +316,7 @@ address perms offset dev inode pathname 08049000-0804a000 rw-p 00001000 03:00 8312 /opt/test 0804a000-0806b000 rw-p 00000000 00:00 0 [heap] a7cb1000-a7cb2000 ---p 00000000 00:00 0 -a7cb2000-a7eb2000 rw-p 00000000 00:00 0 [threadstack:001ff4b4] +a7cb2000-a7eb2000 rw-p 00000000 00:00 0 a7eb2000-a7eb3000 ---p 00000000 00:00 0 a7eb3000-a7ed5000 rw-p 00000000 00:00 0 a7ed5000-a8008000 r-xp 00000000 03:00 4222 /lib/libc.so.6 @@ -352,7 +352,6 @@ is not associated with a file: [stack] = the stack of the main process [vdso] = the "virtual dynamic shared object", the kernel system call handler - [threadstack:xxxxxxxx] = the stack of the thread, xxxxxxxx is the stack size or if empty, the mapping is anonymous. diff --git a/fs/compat.c b/fs/compat.c index 4b6ed03..0544873 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -1531,8 +1531,6 @@ int compat_do_execve(char * filename, if (retval < 0) goto out; - current->stack_start = current->mm->start_stack; - /* execve succeeded */ current->fs->in_exec = 0; current->in_execve = 0; diff --git a/fs/exec.c b/fs/exec.c index 49cdaa1..e6e94c6 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1387,8 +1387,6 @@ int do_execve(char * filename, if (retval < 0) goto out; - current->stack_start = current->mm->start_stack; - /* execve succeeded */ current->fs->in_exec = 0; current->in_execve = 0; diff --git a/fs/proc/array.c b/fs/proc/array.c index e51f2ec..885ab55 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -81,7 +81,6 @@ #include #include #include -#include #include #include @@ -495,7 +494,7 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns, rsslim, mm ? mm->start_code : 0, mm ? mm->end_code : 0, - (permitted && mm) ? task->stack_start : 0, + (permitted && mm) ? mm->start_stack : 0, esp, eip, /* The signal information here is obsolete. diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 0705534..47f5b14 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -247,25 +247,6 @@ static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma) } else if (vma->vm_start <= mm->start_stack && vma->vm_end >= mm->start_stack) { name = "[stack]"; - } else { - unsigned long stack_start; - struct proc_maps_private *pmp; - - pmp = m->private; - stack_start = pmp->task->stack_start; - - if (vma->vm_start <= stack_start && - vma->vm_end >= stack_start) { - pad_len_spaces(m, len); - seq_printf(m, - "[threadstack:%08lx]", -#ifdef CONFIG_STACK_GROWSUP - vma->vm_end - stack_start -#else - stack_start - vma->vm_start -#endif - ); - } } } else { name = "[vdso]"; diff --git a/include/linux/sched.h b/include/linux/sched.h index dad7f66..2b7b81d 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1497,7 +1497,6 @@ struct task_struct { /* bitmask of trace recursion */ unsigned long trace_recursion; #endif /* CONFIG_TRACING */ - unsigned long stack_start; #ifdef CONFIG_CGROUP_MEM_RES_CTLR /* memcg uses this to do batch job */ struct memcg_batch_info { int do_batch; /* incremented when batch uncharge started */ diff --git a/kernel/fork.c b/kernel/fork.c index 44b0791..4c14942 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1114,8 +1114,6 @@ static struct task_struct *copy_process(unsigned long clone_flags, p->bts = NULL; - p->stack_start = stack_start; - /* Perform scheduler related setup. Assign this task to a CPU. */ sched_fork(p, clone_flags); -- cgit v0.10.2 From ebb1fea9b3adf25d7e2f643c614163af4f93a17f Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 11 May 2010 14:06:48 -0700 Subject: mmc: atmel-mci: fix two parameters swapped Two parameters were swapped in the calls to atmci_init_slot(). Signed-off-by: Nicolas Ferre Reported-by: Anders Grahn Cc: Haavard Skinnemoen Cc: Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 88be37d..57d3cb2d 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -1751,13 +1751,13 @@ static int __init atmci_probe(struct platform_device *pdev) ret = -ENODEV; if (pdata->slot[0].bus_width) { ret = atmci_init_slot(host, &pdata->slot[0], - MCI_SDCSEL_SLOT_A, 0); + 0, MCI_SDCSEL_SLOT_A); if (!ret) nr_slots++; } if (pdata->slot[1].bus_width) { ret = atmci_init_slot(host, &pdata->slot[1], - MCI_SDCSEL_SLOT_B, 1); + 1, MCI_SDCSEL_SLOT_B); if (!ret) nr_slots++; } -- cgit v0.10.2 From 009a891b22395fc86e5f34057d79fffee4509ab5 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 11 May 2010 14:06:49 -0700 Subject: mmc: atmel-mci: prevent kernel oops while removing card The removing of an SD card in certain circumstances can lead to a kernel oops if we do not make sure that the "data" field of the host structure is valid. This patch adds a test in atmci_dma_cleanup() function and also calls atmci_stop_dma() before throwing away the reference to data. Signed-off-by: Nicolas Ferre Cc: Haavard Skinnemoen Cc: Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 57d3cb2d..2a5d5ca 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -569,9 +569,10 @@ static void atmci_dma_cleanup(struct atmel_mci *host) { struct mmc_data *data = host->data; - dma_unmap_sg(&host->pdev->dev, data->sg, data->sg_len, - ((data->flags & MMC_DATA_WRITE) - ? DMA_TO_DEVICE : DMA_FROM_DEVICE)); + if (data) + dma_unmap_sg(&host->pdev->dev, data->sg, data->sg_len, + ((data->flags & MMC_DATA_WRITE) + ? DMA_TO_DEVICE : DMA_FROM_DEVICE)); } static void atmci_stop_dma(struct atmel_mci *host) @@ -1099,8 +1100,8 @@ static void atmci_command_complete(struct atmel_mci *host, "command error: status=0x%08x\n", status); if (cmd->data) { - host->data = NULL; atmci_stop_dma(host); + host->data = NULL; mci_writel(host, IDR, MCI_NOTBUSY | MCI_TXRDY | MCI_RXRDY | ATMCI_DATA_ERROR_FLAGS); -- cgit v0.10.2 From abc2c9fdf636c4335a8d72ac3c5ae152bca44b68 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 11 May 2010 14:06:50 -0700 Subject: mmc: atmel-mci: remove data error interrupt after xfer Disable data error interrupts while we are actually recording that there is not such errors. This will prevent, in some cases, the warning message printed at new request queuing (in atmci_start_request()). Signed-off-by: Nicolas Ferre Cc: Haavard Skinnemoen Cc: Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 2a5d5ca..b77b9b0 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -1294,6 +1294,7 @@ static void atmci_tasklet_func(unsigned long priv) } else { data->bytes_xfered = data->blocks * data->blksz; data->error = 0; + mci_writel(host, IDR, ATMCI_DATA_ERROR_FLAGS); } if (!data->stop) { -- cgit v0.10.2 From d586ebbb8814e039545d38f69029533f3f17748d Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 11 May 2010 14:06:50 -0700 Subject: mmc: atmel-mci: fix in debugfs: response value printing In debugfs, printing of command response reports resp[2] twice: fix it to resp[3]. Signed-off-by: Nicolas Ferre Haavard Skinnemoen Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index b77b9b0..fb279f4 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -266,7 +266,7 @@ static int atmci_req_show(struct seq_file *s, void *v) "CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n", cmd->opcode, cmd->arg, cmd->flags, cmd->resp[0], cmd->resp[1], cmd->resp[2], - cmd->resp[2], cmd->error); + cmd->resp[3], cmd->error); if (data) seq_printf(s, "DATA %u / %u * %u flg %x err %d\n", data->bytes_xfered, data->blocks, @@ -276,7 +276,7 @@ static int atmci_req_show(struct seq_file *s, void *v) "CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n", stop->opcode, stop->arg, stop->flags, stop->resp[0], stop->resp[1], stop->resp[2], - stop->resp[2], stop->error); + stop->resp[3], stop->error); } spin_unlock_bh(&slot->host->lock); -- cgit v0.10.2 From 475f9aa6aa538befcbd0fa95bdebada600f247cd Mon Sep 17 00:00:00 2001 From: Vitaly Mayatskikh Date: Tue, 11 May 2010 14:06:51 -0700 Subject: kexec: fix OOPS in crash_kernel_shrink Two "echo 0 > /sys/kernel/kexec_crash_size" OOPSes kernel. Also content of this file is invalid after first shrink to zero: it shows 1 instead of 0. This scenario is unlikely to happen often (root privs, valid crashkernel= in cmdline, dump-capture kernel not loaded), I hit it only by chance. This patch fixes it. Signed-off-by: Vitaly Mayatskikh Cc: Cong Wang Cc: Neil Horman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/kexec.c b/kernel/kexec.c index 87ebe8a..474a847 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c @@ -1134,11 +1134,9 @@ int crash_shrink_memory(unsigned long new_size) free_reserved_phys_range(end, crashk_res.end); - if (start == end) { - crashk_res.end = end; + if (start == end) release_resource(&crashk_res); - } else - crashk_res.end = end - 1; + crashk_res.end = end - 1; unlock: mutex_unlock(&kexec_mutex); -- cgit v0.10.2 From 4a6018f7f4f1075c1a5403b5ec0ee7262187b86c Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Tue, 11 May 2010 14:06:53 -0700 Subject: hugetlbfs: kill applications that use MAP_NORESERVE with SIGBUS instead of OOM-killer Ordinarily, application using hugetlbfs will create mappings with reserves. For shared mappings, these pages are reserved before mmap() returns success and for private mappings, the caller process is guaranteed and a child process that cannot get the pages gets killed with sigbus. An application that uses MAP_NORESERVE gets no reservations and mmap() will always succeed at the risk the page will not be available at fault time. This might be used for example on very large sparse mappings where the developer is confident the necessary huge pages exist to satisfy all faults even though the whole mapping cannot be backed by huge pages. Unfortunately, if an allocation does fail, VM_FAULT_OOM is returned to the fault handler which proceeds to trigger the OOM-killer. This is unhelpful. Even without hugetlbfs mounted, a user using mmap() can trivially trigger the OOM-killer because VM_FAULT_OOM is returned (will provide example program if desired - it's a whopping 24 lines long). It could be considered a DOS available to an unprivileged user. This patch alters hugetlbfs to kill a process that uses MAP_NORESERVE where huge pages were not available with SIGBUS instead of triggering the OOM killer. This change affects hugetlb_cow() as well. I feel there is a failure case in there, but I didn't create one. It would need a fairly specific target in terms of the faulting application and the hugepage pool size. The hugetlb_no_page() path is much easier to hit but both might as well be closed. Signed-off-by: Mel Gorman Cc: Lee Schermerhorn Cc: David Rientjes Cc: Andi Kleen Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/hugetlb.c b/mm/hugetlb.c index ffbdfc8..4c9e6bb 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -1039,7 +1039,7 @@ static struct page *alloc_huge_page(struct vm_area_struct *vma, page = alloc_buddy_huge_page(h, vma, addr); if (!page) { hugetlb_put_quota(inode->i_mapping, chg); - return ERR_PTR(-VM_FAULT_OOM); + return ERR_PTR(-VM_FAULT_SIGBUS); } } -- cgit v0.10.2 From ab941e0fff3947b6dcc9c578d918d1bba54a6874 Mon Sep 17 00:00:00 2001 From: Naoya Horiguchi Date: Tue, 11 May 2010 14:06:55 -0700 Subject: rmap: remove anon_vma check in page_address_in_vma() Currently page_address_in_vma() compares vma->anon_vma and page_anon_vma(page) for parameter check, but in 2.6.34 a vma can have multiple anon_vmas with anon_vma_chain, so current check does not work. (For anonymous page shared by multiple processes, some verified (page,vma) pairs return -EFAULT wrongly.) We can go to checking all anon_vmas in the "same_vma" chain, but it needs to meet lock requirement. Instead, we can remove anon_vma check safely because page_address_in_vma() assumes that page and vma are already checked to belong to the identical process. Signed-off-by: Naoya Horiguchi Reviewed-by: Rik van Riel Cc: Andi Kleen Cc: Andrea Arcangeli Cc: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/mm/rmap.c b/mm/rmap.c index 07fc947..0feeef8 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -336,14 +336,13 @@ vma_address(struct page *page, struct vm_area_struct *vma) /* * At what user virtual address is page expected in vma? - * checking that the page matches the vma. + * Caller should check the page is actually part of the vma. */ unsigned long page_address_in_vma(struct page *page, struct vm_area_struct *vma) { - if (PageAnon(page)) { - if (vma->anon_vma != page_anon_vma(page)) - return -EFAULT; - } else if (page->mapping && !(vma->vm_flags & VM_NONLINEAR)) { + if (PageAnon(page)) + ; + else if (page->mapping && !(vma->vm_flags & VM_NONLINEAR)) { if (!vma->vm_file || vma->vm_file->f_mapping != page->mapping) return -EFAULT; -- cgit v0.10.2 From 11cad320a4f4bc53d3585c85600c782faa12b99e Mon Sep 17 00:00:00 2001 From: Vitaliy Gusev Date: Tue, 11 May 2010 14:06:56 -0700 Subject: bsdacct: use del_timer_sync() in acct_exit_ns() acct_exit_ns --> acct_file_reopen deletes timer without check timer execution on other CPUs. So acct_timeout() can change an unmapped memory. Signed-off-by: Vitaliy Gusev Cc: Pavel Emelyanov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/acct.c b/kernel/acct.c index 24f8c81..e4c0e1f 100644 --- a/kernel/acct.c +++ b/kernel/acct.c @@ -353,17 +353,18 @@ restart: void acct_exit_ns(struct pid_namespace *ns) { - struct bsd_acct_struct *acct; + struct bsd_acct_struct *acct = ns->bacct; - spin_lock(&acct_lock); - acct = ns->bacct; - if (acct != NULL) { - if (acct->file != NULL) - acct_file_reopen(acct, NULL, NULL); + if (acct == NULL) + return; - kfree(acct); - } + del_timer_sync(&acct->timer); + spin_lock(&acct_lock); + if (acct->file != NULL) + acct_file_reopen(acct, NULL, NULL); spin_unlock(&acct_lock); + + kfree(acct); } /* -- cgit v0.10.2 From 7f0f15464185a92f9d8791ad231bcd7bf6df54e4 Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Tue, 11 May 2010 14:06:58 -0700 Subject: memcg: fix css_id() RCU locking for real Commit ad4ba375373937817404fd92239ef4cadbded23b ("memcg: css_id() must be called under rcu_read_lock()") modifies memcontol.c for fixing RCU check message. But Andrew Morton pointed out that the fix doesn't seems sane and it was just for hidining lockdep messages. This is a patch for do proper things. Checking again, all places, accessing without rcu_read_lock, that commit fixies was intentional.... all callers of css_id() has reference count on it. So, it's not necessary to be under rcu_read_lock(). Considering again, we can use rcu_dereference_check for css_id(). We know css->id is valid if css->refcnt > 0. (css->id never changes and freed after css->refcnt going to be 0.) This patch makes use of rcu_dereference_check() in css_id/depth and remove unnecessary rcu-read-lock added by the commit. Signed-off-by: KAMEZAWA Hiroyuki Cc: "Paul E. McKenney" Cc: Daisuke Nishimura Cc: Balbir Singh Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 3a53c77..6db8b7f 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -4435,7 +4435,15 @@ __setup("cgroup_disable=", cgroup_disable); */ unsigned short css_id(struct cgroup_subsys_state *css) { - struct css_id *cssid = rcu_dereference(css->id); + struct css_id *cssid; + + /* + * This css_id() can return correct value when somone has refcnt + * on this or this is under rcu_read_lock(). Once css->id is allocated, + * it's unchanged until freed. + */ + cssid = rcu_dereference_check(css->id, + rcu_read_lock_held() || atomic_read(&css->refcnt)); if (cssid) return cssid->id; @@ -4445,7 +4453,10 @@ EXPORT_SYMBOL_GPL(css_id); unsigned short css_depth(struct cgroup_subsys_state *css) { - struct css_id *cssid = rcu_dereference(css->id); + struct css_id *cssid; + + cssid = rcu_dereference_check(css->id, + rcu_read_lock_held() || atomic_read(&css->refcnt)); if (cssid) return cssid->depth; diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 0f711c2..595d03f 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -2314,9 +2314,7 @@ mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout) /* record memcg information */ if (do_swap_account && swapout && memcg) { - rcu_read_lock(); swap_cgroup_record(ent, css_id(&memcg->css)); - rcu_read_unlock(); mem_cgroup_get(memcg); } if (swapout && memcg) @@ -2373,10 +2371,8 @@ static int mem_cgroup_move_swap_account(swp_entry_t entry, { unsigned short old_id, new_id; - rcu_read_lock(); old_id = css_id(&from->css); new_id = css_id(&to->css); - rcu_read_unlock(); if (swap_cgroup_cmpxchg(entry, old_id, new_id) == old_id) { mem_cgroup_swap_statistics(from, false); @@ -4044,16 +4040,11 @@ static int is_target_pte_for_mc(struct vm_area_struct *vma, put_page(page); } /* throught */ - if (ent.val && do_swap_account && !ret) { - unsigned short id; - rcu_read_lock(); - id = css_id(&mc.from->css); - rcu_read_unlock(); - if (id == lookup_swap_cgroup(ent)) { - ret = MC_TARGET_SWAP; - if (target) - target->ent = ent; - } + if (ent.val && do_swap_account && !ret && + css_id(&mc.from->css) == lookup_swap_cgroup(ent)) { + ret = MC_TARGET_SWAP; + if (target) + target->ent = ent; } return ret; } -- cgit v0.10.2 From 747388d78a0ae768fd82b55c4ed38aa646a72364 Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Tue, 11 May 2010 14:06:59 -0700 Subject: memcg: fix css_is_ancestor() RCU locking Some callers (in memcontrol.c) calls css_is_ancestor() without rcu_read_lock. Because css_is_ancestor() has to access RCU protected data, it should be under rcu_read_lock(). This makes css_is_ancestor() itself does safe access to RCU protected area. (At least, "root" can have refcnt==0 if it's not an ancestor of "child". So, we need rcu_read_lock().) Signed-off-by: KAMEZAWA Hiroyuki Cc: "Paul E. McKenney" Cc: Daisuke Nishimura Cc: Balbir Singh Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 6db8b7f..6d870f2 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -4464,15 +4464,36 @@ unsigned short css_depth(struct cgroup_subsys_state *css) } EXPORT_SYMBOL_GPL(css_depth); +/** + * css_is_ancestor - test "root" css is an ancestor of "child" + * @child: the css to be tested. + * @root: the css supporsed to be an ancestor of the child. + * + * Returns true if "root" is an ancestor of "child" in its hierarchy. Because + * this function reads css->id, this use rcu_dereference() and rcu_read_lock(). + * But, considering usual usage, the csses should be valid objects after test. + * Assuming that the caller will do some action to the child if this returns + * returns true, the caller must take "child";s reference count. + * If "child" is valid object and this returns true, "root" is valid, too. + */ + bool css_is_ancestor(struct cgroup_subsys_state *child, const struct cgroup_subsys_state *root) { - struct css_id *child_id = rcu_dereference(child->id); - struct css_id *root_id = rcu_dereference(root->id); + struct css_id *child_id; + struct css_id *root_id; + bool ret = true; - if (!child_id || !root_id || (child_id->depth < root_id->depth)) - return false; - return child_id->stack[root_id->depth] == root_id->id; + rcu_read_lock(); + child_id = rcu_dereference(child->id); + root_id = rcu_dereference(root->id); + if (!child_id + || !root_id + || (child_id->depth < root_id->depth) + || (child_id->stack[root_id->depth] != root_id->id)) + ret = false; + rcu_read_unlock(); + return ret; } static void __free_css_id_cb(struct rcu_head *head) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 595d03f..8a79a6f 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -811,12 +811,10 @@ int task_in_mem_cgroup(struct task_struct *task, const struct mem_cgroup *mem) * enabled in "curr" and "curr" is a child of "mem" in *cgroup* * hierarchy(even if use_hierarchy is disabled in "mem"). */ - rcu_read_lock(); if (mem->use_hierarchy) ret = css_is_ancestor(&curr->css, &mem->css); else ret = (curr == mem); - rcu_read_unlock(); css_put(&curr->css); return ret; } @@ -1603,7 +1601,6 @@ static int __mem_cgroup_try_charge(struct mm_struct *mm, * There is a small race that "from" or "to" can be * freed by rmdir, so we use css_tryget(). */ - rcu_read_lock(); from = mc.from; to = mc.to; if (from && css_tryget(&from->css)) { @@ -1624,7 +1621,6 @@ static int __mem_cgroup_try_charge(struct mm_struct *mm, do_continue = (to == mem_over_limit); css_put(&to->css); } - rcu_read_unlock(); if (do_continue) { DEFINE_WAIT(wait); prepare_to_wait(&mc.waitq, &wait, -- cgit v0.10.2 From de145b44b95b9d3212a82d1c0f29b09778ef33c5 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 11 May 2010 14:07:00 -0700 Subject: fbdev: bfin-t350mcqb-fb: fix fbmem allocation with blanking lines The current allocation does not include the memory required for blanking lines. So avoid memory corruption when multiple devices are using the DMA memory near each other. Signed-off-by: Michael Hennerich Signed-off-by: Mike Frysinger Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c index 44e49c2..c2ec3dcd 100644 --- a/drivers/video/bfin-t350mcqb-fb.c +++ b/drivers/video/bfin-t350mcqb-fb.c @@ -488,9 +488,9 @@ static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev) fbinfo->fbops = &bfin_t350mcqb_fb_ops; fbinfo->flags = FBINFO_FLAG_DEFAULT; - info->fb_buffer = - dma_alloc_coherent(NULL, fbinfo->fix.smem_len, &info->dma_handle, - GFP_KERNEL); + info->fb_buffer = dma_alloc_coherent(NULL, fbinfo->fix.smem_len + + ACTIVE_VIDEO_MEM_OFFSET, + &info->dma_handle, GFP_KERNEL); if (NULL == info->fb_buffer) { printk(KERN_ERR DRIVER_NAME @@ -568,8 +568,8 @@ out7: out6: fb_dealloc_cmap(&fbinfo->cmap); out4: - dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer, - info->dma_handle); + dma_free_coherent(NULL, fbinfo->fix.smem_len + ACTIVE_VIDEO_MEM_OFFSET, + info->fb_buffer, info->dma_handle); out3: framebuffer_release(fbinfo); out2: @@ -592,8 +592,9 @@ static int __devexit bfin_t350mcqb_remove(struct platform_device *pdev) free_irq(info->irq, info); if (info->fb_buffer != NULL) - dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer, - info->dma_handle); + dma_free_coherent(NULL, fbinfo->fix.smem_len + + ACTIVE_VIDEO_MEM_OFFSET, info->fb_buffer, + info->dma_handle); fb_dealloc_cmap(&fbinfo->cmap); -- cgit v0.10.2 From a3ed2a15719219769bb095b28009c1d654a419e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Goddard=20Rosa?= Date: Tue, 11 May 2010 14:07:03 -0700 Subject: mqueue: fix kernel BUG caused by double free() on mq_open() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In case of aborting because we reach the maximum amount of memory which can be allocated to message queues per user (RLIMIT_MSGQUEUE), we would try to free the message area twice when bailing out: first by the error handling code itself, and then later when cleaning up the inode through delete_inode(). Signed-off-by: André Goddard Rosa Cc: Alexey Dobriyan Cc: Al Viro Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 722b013..59a009d 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -158,7 +158,7 @@ static struct inode *mqueue_get_inode(struct super_block *sb, u->mq_bytes + mq_bytes > task_rlimit(p, RLIMIT_MSGQUEUE)) { spin_unlock(&mq_lock); - kfree(info->messages); + /* mqueue_delete_inode() releases info->messages */ goto out_inode; } u->mq_bytes += mq_bytes; -- cgit v0.10.2 From 06efbeb4a47b6f865e1c9d175ab9d6e90b69ae9e Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Tue, 11 May 2010 14:07:03 -0700 Subject: hp_accel: fix race in device removal The work queue has to be flushed after the device has been made inaccessible. The patch closes a window during which a work queue might remain active after the device is removed and would then lead to ACPI calls with undefined behavior. Signed-off-by: Oliver Neukum Acked-by: Eric Piel Acked-by: Pavel Machek Cc: Pavel Herrmann Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/hwmon/hp_accel.c b/drivers/hwmon/hp_accel.c index c8ab505..7580f55 100644 --- a/drivers/hwmon/hp_accel.c +++ b/drivers/hwmon/hp_accel.c @@ -328,8 +328,8 @@ static int lis3lv02d_remove(struct acpi_device *device, int type) lis3lv02d_joystick_disable(); lis3lv02d_poweroff(&lis3_dev); - flush_work(&hpled_led.work); led_classdev_unregister(&hpled_led.led_classdev); + flush_work(&hpled_led.work); return lis3lv02d_remove_fs(&lis3_dev); } -- cgit v0.10.2 From 788885ae7a298dec73ba999c2fc5d46d42072ddf Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 11 May 2010 14:07:05 -0700 Subject: drivers/gpu/drm/i915/i915_irq.c:i915_error_object_create(): use correct kmap-atomic slot i915_error_object_create() is called from the timer interrupt and hence can corrupt the KM_USER0 slot. Use KM_IRQ0 instead. Reported-by: Jaswinder Singh Rajput Tested-by: Jaswinder Singh Rajput Acked-by: Chris Wilson Cc: Dave Airlie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 2b8b969..df6a9cd 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -456,11 +456,15 @@ i915_error_object_create(struct drm_device *dev, for (page = 0; page < page_count; page++) { void *s, *d = kmalloc(PAGE_SIZE, GFP_ATOMIC); + unsigned long flags; + if (d == NULL) goto unwind; - s = kmap_atomic(src_priv->pages[page], KM_USER0); + local_irq_save(flags); + s = kmap_atomic(src_priv->pages[page], KM_IRQ0); memcpy(d, s, PAGE_SIZE); - kunmap_atomic(s, KM_USER0); + kunmap_atomic(s, KM_IRQ0); + local_irq_restore(flags); dst->pages[page] = d; } dst->page_count = page_count; -- cgit v0.10.2 From a3c8acd04376d604370dcb6cd2143c9c14078a50 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 11 May 2010 17:47:07 -0700 Subject: x86: Add new static_cpu_has() function using alternatives For CPU-feature-specific code that touches performance-critical paths, introduce a static patching version of [boot_]cpu_has(). This is run at alternatives time and is therefore not appropriate for most initialization code, but on the other hand initialization code is generally not performance critical. On gcc 4.5+ this uses the new "asm goto" feature. Signed-off-by: H. Peter Anvin Cc: Avi Kivity Cc: Suresh Siddha LKML-Reference: <1273135546-29690-2-git-send-email-avi@redhat.com> diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 0cd82d0..9b11a5c 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -175,6 +175,7 @@ #if defined(__KERNEL__) && !defined(__ASSEMBLY__) +#include #include extern const char * const x86_cap_flags[NCAPINTS*32]; @@ -283,6 +284,62 @@ extern const char * const x86_power_flags[32]; #endif /* CONFIG_X86_64 */ +/* + * Static testing of CPU features. Used the same as boot_cpu_has(). + * These are only valid after alternatives have run, but will statically + * patch the target code for additional performance. + * + */ +static __always_inline __pure bool __static_cpu_has(u8 bit) +{ +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) + asm goto("1: jmp %l[t_no]\n" + "2:\n" + ".section .altinstructions,\"a\"\n" + _ASM_ALIGN "\n" + _ASM_PTR "1b\n" + _ASM_PTR "0\n" /* no replacement */ + " .byte %P0\n" /* feature bit */ + " .byte 2b - 1b\n" /* source len */ + " .byte 0\n" /* replacement len */ + " .byte 0xff + 0 - (2b-1b)\n" /* padding */ + ".previous\n" + : : "i" (bit) : : t_no); + return true; + t_no: + return false; +#else + u8 flag; + /* Open-coded due to __stringify() in ALTERNATIVE() */ + asm volatile("1: movb $0,%0\n" + "2:\n" + ".section .altinstructions,\"a\"\n" + _ASM_ALIGN "\n" + _ASM_PTR "1b\n" + _ASM_PTR "3f\n" + " .byte %P1\n" /* feature bit */ + " .byte 2b - 1b\n" /* source len */ + " .byte 4f - 3f\n" /* replacement len */ + " .byte 0xff + (4f-3f) - (2b-1b)\n" /* padding */ + ".previous\n" + ".section .altinstr_replacement,\"ax\"\n" + "3: movb $1,%0\n" + "4:\n" + ".previous\n" + : "=qm" (flag) : "i" (bit)); + return flag; +#endif +} + +#define static_cpu_has(bit) \ +( \ + __builtin_constant_p(boot_cpu_has(bit)) ? \ + boot_cpu_has(bit) : \ + (__builtin_constant_p(bit) && !((bit) & ~0xff)) ? \ + __static_cpu_has(bit) : \ + boot_cpu_has(bit) \ +) + #endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */ #endif /* _ASM_X86_CPUFEATURE_H */ -- cgit v0.10.2 From c9775b4cc522e5f1b40b1366a993f0f05f600f39 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 11 May 2010 17:49:54 -0700 Subject: x86, fpu: Use static_cpu_has() to implement use_xsave() use_xsave() is now just a special case of static_cpu_has(), so use static_cpu_has(). Signed-off-by: H. Peter Anvin Cc: Avi Kivity Cc: Suresh Siddha LKML-Reference: <1273135546-29690-2-git-send-email-avi@redhat.com> diff --git a/arch/x86/include/asm/i387.h b/arch/x86/include/asm/i387.h index 8002e9c..c991b3a 100644 --- a/arch/x86/include/asm/i387.h +++ b/arch/x86/include/asm/i387.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -57,16 +58,9 @@ extern int restore_i387_xstate_ia32(void __user *buf); #define X87_FSW_ES (1 << 7) /* Exception Summary */ -static inline bool use_xsave(void) +static __always_inline __pure bool use_xsave(void) { - u8 has_xsave; - - alternative_io("mov $0, %0", - "mov $1, %0", - X86_FEATURE_XSAVE, - "=qm" (has_xsave)); - - return has_xsave; + return static_cpu_has(X86_FEATURE_XSAVE); } #ifdef CONFIG_X86_64 -- cgit v0.10.2 From afdd225d0feea07f7fe6501771dbfddfda07b632 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 7 May 2010 09:24:05 +0900 Subject: ARM: SAMSUNG: Remove old email address for ben-linux@fluff.org The address ben@fluff.org is old, ben-linux@fluff.org has been in use for a long time, and we should fixup all the occasions of the older address to avoid confusion. Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c index bd4ced5..b212561 100644 --- a/arch/arm/mach-s3c2410/mach-h1940.c +++ b/arch/arm/mach-s3c2410/mach-h1940.c @@ -338,7 +338,7 @@ static void __init h1940_init(void) } MACHINE_START(H1940, "IPAQ-H1940") - /* Maintainer: Ben Dooks */ + /* Maintainer: Ben Dooks */ .phys_io = S3C2410_PA_UART, .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, diff --git a/arch/arm/mach-s3c2412/mach-jive.c b/arch/arm/mach-s3c2412/mach-jive.c index 14f4798..20647f0 100644 --- a/arch/arm/mach-s3c2412/mach-jive.c +++ b/arch/arm/mach-s3c2412/mach-jive.c @@ -674,7 +674,7 @@ static void __init jive_machine_init(void) } MACHINE_START(JIVE, "JIVE") - /* Maintainer: Ben Dooks */ + /* Maintainer: Ben Dooks */ .phys_io = S3C2410_PA_UART, .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, diff --git a/arch/arm/mach-s3c2412/mach-smdk2413.c b/arch/arm/mach-s3c2412/mach-smdk2413.c index 0392065..3d41aa7 100644 --- a/arch/arm/mach-s3c2412/mach-smdk2413.c +++ b/arch/arm/mach-s3c2412/mach-smdk2413.c @@ -150,7 +150,7 @@ static void __init smdk2413_machine_init(void) } MACHINE_START(S3C2413, "S3C2413") - /* Maintainer: Ben Dooks */ + /* Maintainer: Ben Dooks */ .phys_io = S3C2410_PA_UART, .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, @@ -163,7 +163,7 @@ MACHINE_START(S3C2413, "S3C2413") MACHINE_END MACHINE_START(SMDK2412, "SMDK2412") - /* Maintainer: Ben Dooks */ + /* Maintainer: Ben Dooks */ .phys_io = S3C2410_PA_UART, .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, @@ -176,7 +176,7 @@ MACHINE_START(SMDK2412, "SMDK2412") MACHINE_END MACHINE_START(SMDK2413, "SMDK2413") - /* Maintainer: Ben Dooks */ + /* Maintainer: Ben Dooks */ .phys_io = S3C2410_PA_UART, .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, diff --git a/arch/arm/mach-s3c2440/mach-rx3715.c b/arch/arm/mach-s3c2440/mach-rx3715.c index 1e836e5..d2946de 100644 --- a/arch/arm/mach-s3c2440/mach-rx3715.c +++ b/arch/arm/mach-s3c2440/mach-rx3715.c @@ -209,7 +209,7 @@ static void __init rx3715_init_machine(void) } MACHINE_START(RX3715, "IPAQ-RX3715") - /* Maintainer: Ben Dooks */ + /* Maintainer: Ben Dooks */ .phys_io = S3C2410_PA_UART, .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, diff --git a/arch/arm/mach-s3c2440/mach-smdk2440.c b/arch/arm/mach-s3c2440/mach-smdk2440.c index 3ac3d63..df83276 100644 --- a/arch/arm/mach-s3c2440/mach-smdk2440.c +++ b/arch/arm/mach-s3c2440/mach-smdk2440.c @@ -174,7 +174,7 @@ static void __init smdk2440_machine_init(void) } MACHINE_START(S3C2440, "SMDK2440") - /* Maintainer: Ben Dooks */ + /* Maintainer: Ben Dooks */ .phys_io = S3C2410_PA_UART, .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, diff --git a/arch/arm/mach-s3c2443/mach-smdk2443.c b/arch/arm/mach-s3c2443/mach-smdk2443.c index e2e362b..4c863d3 100644 --- a/arch/arm/mach-s3c2443/mach-smdk2443.c +++ b/arch/arm/mach-s3c2443/mach-smdk2443.c @@ -131,7 +131,7 @@ static void __init smdk2443_machine_init(void) } MACHINE_START(SMDK2443, "SMDK2443") - /* Maintainer: Ben Dooks */ + /* Maintainer: Ben Dooks */ .phys_io = S3C2410_PA_UART, .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, .boot_params = S3C2410_SDRAM_PA + 0x100, diff --git a/arch/arm/mach-s3c64xx/mach-smdk6400.c b/arch/arm/mach-s3c64xx/mach-smdk6400.c index f7b1898..5991667 100644 --- a/arch/arm/mach-s3c64xx/mach-smdk6400.c +++ b/arch/arm/mach-s3c64xx/mach-smdk6400.c @@ -84,7 +84,7 @@ static void __init smdk6400_machine_init(void) } MACHINE_START(SMDK6400, "SMDK6400") - /* Maintainer: Ben Dooks */ + /* Maintainer: Ben Dooks */ .phys_io = S3C_PA_UART & 0xfff00000, .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc, .boot_params = S3C64XX_PA_SDRAM + 0x100, diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c index 2d5afd2..9d51455 100644 --- a/arch/arm/mach-s3c64xx/mach-smdk6410.c +++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c @@ -656,7 +656,7 @@ static void __init smdk6410_machine_init(void) } MACHINE_START(SMDK6410, "SMDK6410") - /* Maintainer: Ben Dooks */ + /* Maintainer: Ben Dooks */ .phys_io = S3C_PA_UART & 0xfff00000, .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc, .boot_params = S3C64XX_PA_SDRAM + 0x100, -- cgit v0.10.2 From 0ad73cefa2ec509126af466718e0c3cb1ad8ae9b Mon Sep 17 00:00:00 2001 From: Kukjin Kim Date: Tue, 11 May 2010 09:56:37 +0900 Subject: ARM: SAMSUNG: Remove static of S5P SoCs sysclass This patch removes static of s5p6440_sysclass, s5p6442_sysclass, and s5pv210_sysclass for defintion as extern. Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5p6440/cpu.c b/arch/arm/mach-s5p6440/cpu.c index 1794131a..ca3b320 100644 --- a/arch/arm/mach-s5p6440/cpu.c +++ b/arch/arm/mach-s5p6440/cpu.c @@ -88,7 +88,7 @@ void __init s5p6440_init_irq(void) s5p_init_irq(vic, ARRAY_SIZE(vic)); } -static struct sysdev_class s5p6440_sysclass = { +struct sysdev_class s5p6440_sysclass = { .name = "s5p6440-core", }; diff --git a/arch/arm/mach-s5p6442/cpu.c b/arch/arm/mach-s5p6442/cpu.c index bc2524d..a48fb55 100644 --- a/arch/arm/mach-s5p6442/cpu.c +++ b/arch/arm/mach-s5p6442/cpu.c @@ -95,7 +95,7 @@ void __init s5p6442_init_irq(void) s5p_init_irq(vic, ARRAY_SIZE(vic)); } -static struct sysdev_class s5p6442_sysclass = { +struct sysdev_class s5p6442_sysclass = { .name = "s5p6442-core", }; diff --git a/arch/arm/mach-s5pv210/cpu.c b/arch/arm/mach-s5pv210/cpu.c index 0e0f8fd..2b776eb 100644 --- a/arch/arm/mach-s5pv210/cpu.c +++ b/arch/arm/mach-s5pv210/cpu.c @@ -100,7 +100,7 @@ void __init s5pv210_init_irq(void) s5p_init_irq(vic, ARRAY_SIZE(vic)); } -static struct sysdev_class s5pv210_sysclass = { +struct sysdev_class s5pv210_sysclass = { .name = "s5pv210-core", }; diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h index d316b4a..c54f318 100644 --- a/arch/arm/plat-samsung/include/plat/cpu.h +++ b/arch/arm/plat-samsung/include/plat/cpu.h @@ -78,6 +78,9 @@ extern struct sysdev_class s3c2442_sysclass; extern struct sysdev_class s3c2443_sysclass; extern struct sysdev_class s3c6410_sysclass; extern struct sysdev_class s3c64xx_sysclass; +extern struct sysdev_class s5p6440_sysclass; +extern struct sysdev_class s5p6442_sysclass; +extern struct sysdev_class s5pv210_sysclass; extern void (*s5pc1xx_idle)(void); -- cgit v0.10.2 From ef7b93a11904c6ba10604233d318d9e8ec88cddc Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 11 May 2010 23:18:06 -0300 Subject: perf report: Librarize the annotation code and use it in the newt browser MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now we don't anymore use popen to run 'perf annotate' for the selected symbol, instead we collect per address samplings when processing samples in 'perf report' if we're using the newt browser, then we use this data directly to do annotation. Done this way we can actually traverse the objdump_line objects directly, matching the addresses to the collected samples and colouring them appropriately using lower level slang routines. The new ui_browser class will be reused for the main, callchain aware, histogram browser, when it will be made generic and don't assume that the objects are always instances of the objdump_line class maintained using list_heads. Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 0797786..9c4dc30 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -560,6 +560,8 @@ ifneq ($(shell sh -c "(echo '\#include '; echo 'int main(void) { newtIni msg := $(warning newt not found, disables TUI support. Please install newt-devel or libnewt-dev); BASIC_CFLAGS += -DNO_NEWT_SUPPORT else + # Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h + BASIC_CFLAGS += -I/usr/include/slang EXTLIBS += -lnewt LIB_OBJS += $(OUTPUT)util/newt.o endif @@ -948,6 +950,9 @@ $(OUTPUT)builtin-init-db.o: builtin-init-db.c $(OUTPUT)PERF-CFLAGS $(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< +$(OUTPUT)util/newt.o: util/newt.c $(OUTPUT)PERF-CFLAGS + $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $< + $(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 3940964..fd1b786 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -34,68 +34,8 @@ static bool full_paths; static bool print_line; -struct sym_hist { - u64 sum; - u64 ip[0]; -}; - -struct sym_ext { - struct rb_node node; - double percent; - char *path; -}; - -struct sym_priv { - struct sym_hist *hist; - struct sym_ext *ext; -}; - static const char *sym_hist_filter; -static int sym__alloc_hist(struct symbol *self) -{ - struct sym_priv *priv = symbol__priv(self); - const int size = (sizeof(*priv->hist) + - (self->end - self->start) * sizeof(u64)); - - priv->hist = zalloc(size); - return priv->hist == NULL ? -1 : 0; -} - -/* - * collect histogram counts - */ -static int annotate__hist_hit(struct hist_entry *he, u64 ip) -{ - unsigned int sym_size, offset; - struct symbol *sym = he->ms.sym; - struct sym_priv *priv; - struct sym_hist *h; - - if (!sym || !he->ms.map) - return 0; - - priv = symbol__priv(sym); - if (priv->hist == NULL && sym__alloc_hist(sym) < 0) - return -ENOMEM; - - sym_size = sym->end - sym->start; - offset = ip - sym->start; - - pr_debug3("%s: ip=%#Lx\n", __func__, he->ms.map->unmap_ip(he->ms.map, ip)); - - if (offset >= sym_size) - return 0; - - h = priv->hist; - h->sum++; - h->ip[offset]++; - - pr_debug3("%#Lx %s: count++ [ip: %#Lx, %#Lx] => %Ld\n", he->ms.sym->start, - he->ms.sym->name, ip, ip - he->ms.sym->start, h->ip[offset]); - return 0; -} - static int hists__add_entry(struct hists *self, struct addr_location *al) { struct hist_entry *he; @@ -115,7 +55,7 @@ static int hists__add_entry(struct hists *self, struct addr_location *al) if (he == NULL) return -ENOMEM; - return annotate__hist_hit(he, al->addr); + return hist_entry__inc_addr_samples(he, al->addr); } static int process_sample_event(event_t *event, struct perf_session *session) @@ -140,101 +80,6 @@ static int process_sample_event(event_t *event, struct perf_session *session) return 0; } -struct objdump_line { - struct list_head node; - s64 offset; - char *line; -}; - -static struct objdump_line *objdump_line__new(s64 offset, char *line) -{ - struct objdump_line *self = malloc(sizeof(*self)); - - if (self != NULL) { - self->offset = offset; - self->line = line; - } - - return self; -} - -static void objdump_line__free(struct objdump_line *self) -{ - free(self->line); - free(self); -} - -static void objdump__add_line(struct list_head *head, struct objdump_line *line) -{ - list_add_tail(&line->node, head); -} - -static struct objdump_line *objdump__get_next_ip_line(struct list_head *head, - struct objdump_line *pos) -{ - list_for_each_entry_continue(pos, head, node) - if (pos->offset >= 0) - return pos; - - return NULL; -} - -static int parse_line(FILE *file, struct hist_entry *he, - struct list_head *head) -{ - struct symbol *sym = he->ms.sym; - struct objdump_line *objdump_line; - char *line = NULL, *tmp, *tmp2; - size_t line_len; - s64 line_ip, offset = -1; - char *c; - - if (getline(&line, &line_len, file) < 0) - return -1; - - if (!line) - return -1; - - c = strchr(line, '\n'); - if (c) - *c = 0; - - line_ip = -1; - - /* - * Strip leading spaces: - */ - tmp = line; - while (*tmp) { - if (*tmp != ' ') - break; - tmp++; - } - - if (*tmp) { - /* - * Parse hexa addresses followed by ':' - */ - line_ip = strtoull(tmp, &tmp2, 16); - if (*tmp2 != ':') - line_ip = -1; - } - - if (line_ip != -1) { - u64 start = map__rip_2objdump(he->ms.map, sym->start); - offset = line_ip - start; - } - - objdump_line = objdump_line__new(offset, line); - if (objdump_line == NULL) { - free(line); - return -1; - } - objdump__add_line(head, objdump_line); - - return 0; -} - static int objdump_line__print(struct objdump_line *self, struct list_head *head, struct hist_entry *he, u64 len) @@ -439,27 +284,11 @@ static void annotate_sym(struct hist_entry *he) struct symbol *sym = he->ms.sym; const char *filename = dso->long_name, *d_filename; u64 len; - char command[PATH_MAX*2]; - FILE *file; LIST_HEAD(head); struct objdump_line *pos, *n; - if (!filename) - return; - - if (dso->origin == DSO__ORIG_KERNEL) { - if (dso->annotate_warned) - return; - dso->annotate_warned = 1; - pr_err("Can't annotate %s: No vmlinux file was found in the " - "path:\n", sym->name); - vmlinux_path__fprintf(stderr); + if (hist_entry__annotate(he, &head) < 0) return; - } - - pr_debug("%s: filename=%s, sym=%s, start=%#Lx, end=%#Lx\n", __func__, - filename, sym->name, map->unmap_ip(map, sym->start), - map->unmap_ip(map, sym->end)); if (full_paths) d_filename = filename; @@ -477,29 +306,6 @@ static void annotate_sym(struct hist_entry *he) printf(" Percent | Source code & Disassembly of %s\n", d_filename); printf("------------------------------------------------\n"); - if (verbose >= 2) - printf("annotating [%p] %30s : [%p] %30s\n", - dso, dso->long_name, sym, sym->name); - - sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s", - map__rip_2objdump(map, sym->start), - map__rip_2objdump(map, sym->end), - filename, filename); - - if (verbose >= 3) - printf("doing: %s\n", command); - - file = popen(command, "r"); - if (!file) - return; - - while (!feof(file)) { - if (parse_line(file, he, &head) < 0) - break; - } - - pclose(file); - if (verbose) hist_entry__print_hits(he); diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 3d67d6b..04de338 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -106,8 +106,18 @@ static int perf_session__add_hist_entry(struct perf_session *self, if (he == NULL) goto out_free_syms; err = 0; - if (symbol_conf.use_callchain) + if (symbol_conf.use_callchain) { err = append_chain(he->callchain, data->callchain, syms); + if (err) + goto out_free_syms; + } + /* + * Only in the newt browser we are doing integrated annotation, + * so we don't allocated the extra space needed because the stdio + * code will not use it. + */ + if (use_browser) + err = hist_entry__inc_addr_samples(he, al->addr); out_free_syms: free(syms); return err; @@ -458,6 +468,13 @@ int cmd_report(int argc, const char **argv, const char *prefix __used) if (strcmp(input_name, "-") != 0) setup_browser(); + /* + * Only in the newt browser we are doing integrated annotation, + * so don't allocate extra space that won't be used in the stdio + * implementation. + */ + if (use_browser) + symbol_conf.priv_size = sizeof(struct sym_priv); if (symbol__init() < 0) return -1; diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index baa55be..451d2e4 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -843,3 +843,187 @@ void hists__filter_by_thread(struct hists *self, const struct thread *thread) } } } + +static int symbol__alloc_hist(struct symbol *self) +{ + struct sym_priv *priv = symbol__priv(self); + const int size = (sizeof(*priv->hist) + + (self->end - self->start) * sizeof(u64)); + + priv->hist = zalloc(size); + return priv->hist == NULL ? -1 : 0; +} + +int hist_entry__inc_addr_samples(struct hist_entry *self, u64 ip) +{ + unsigned int sym_size, offset; + struct symbol *sym = self->ms.sym; + struct sym_priv *priv; + struct sym_hist *h; + + if (!sym || !self->ms.map) + return 0; + + priv = symbol__priv(sym); + if (priv->hist == NULL && symbol__alloc_hist(sym) < 0) + return -ENOMEM; + + sym_size = sym->end - sym->start; + offset = ip - sym->start; + + pr_debug3("%s: ip=%#Lx\n", __func__, self->ms.map->unmap_ip(self->ms.map, ip)); + + if (offset >= sym_size) + return 0; + + h = priv->hist; + h->sum++; + h->ip[offset]++; + + pr_debug3("%#Lx %s: count++ [ip: %#Lx, %#Lx] => %Ld\n", self->ms.sym->start, + self->ms.sym->name, ip, ip - self->ms.sym->start, h->ip[offset]); + return 0; +} + +static struct objdump_line *objdump_line__new(s64 offset, char *line) +{ + struct objdump_line *self = malloc(sizeof(*self)); + + if (self != NULL) { + self->offset = offset; + self->line = line; + } + + return self; +} + +void objdump_line__free(struct objdump_line *self) +{ + free(self->line); + free(self); +} + +static void objdump__add_line(struct list_head *head, struct objdump_line *line) +{ + list_add_tail(&line->node, head); +} + +struct objdump_line *objdump__get_next_ip_line(struct list_head *head, + struct objdump_line *pos) +{ + list_for_each_entry_continue(pos, head, node) + if (pos->offset >= 0) + return pos; + + return NULL; +} + +static int hist_entry__parse_objdump_line(struct hist_entry *self, FILE *file, + struct list_head *head) +{ + struct symbol *sym = self->ms.sym; + struct objdump_line *objdump_line; + char *line = NULL, *tmp, *tmp2, *c; + size_t line_len; + s64 line_ip, offset = -1; + + if (getline(&line, &line_len, file) < 0) + return -1; + + if (!line) + return -1; + + while (line_len != 0 && isspace(line[line_len - 1])) + line[--line_len] = '\0'; + + c = strchr(line, '\n'); + if (c) + *c = 0; + + line_ip = -1; + + /* + * Strip leading spaces: + */ + tmp = line; + while (*tmp) { + if (*tmp != ' ') + break; + tmp++; + } + + if (*tmp) { + /* + * Parse hexa addresses followed by ':' + */ + line_ip = strtoull(tmp, &tmp2, 16); + if (*tmp2 != ':') + line_ip = -1; + } + + if (line_ip != -1) { + u64 start = map__rip_2objdump(self->ms.map, sym->start); + offset = line_ip - start; + } + + objdump_line = objdump_line__new(offset, line); + if (objdump_line == NULL) { + free(line); + return -1; + } + objdump__add_line(head, objdump_line); + + return 0; +} + +int hist_entry__annotate(struct hist_entry *self, struct list_head *head) +{ + struct symbol *sym = self->ms.sym; + struct map *map = self->ms.map; + struct dso *dso = map->dso; + const char *filename = dso->long_name; + char command[PATH_MAX * 2]; + FILE *file; + u64 len; + + if (!filename) + return -1; + + if (dso->origin == DSO__ORIG_KERNEL) { + if (dso->annotate_warned) + return 0; + dso->annotate_warned = 1; + pr_err("Can't annotate %s: No vmlinux file was found in the " + "path:\n", sym->name); + vmlinux_path__fprintf(stderr); + return -1; + } + + pr_debug("%s: filename=%s, sym=%s, start=%#Lx, end=%#Lx\n", __func__, + filename, sym->name, map->unmap_ip(map, sym->start), + map->unmap_ip(map, sym->end)); + + len = sym->end - sym->start; + + pr_debug("annotating [%p] %30s : [%p] %30s\n", + dso, dso->long_name, sym, sym->name); + + snprintf(command, sizeof(command), + "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s|expand", + map__rip_2objdump(map, sym->start), + map__rip_2objdump(map, sym->end), + filename, filename); + + pr_debug("Executing: %s\n", command); + + file = popen(command, "r"); + if (!file) + return -1; + + while (!feof(file)) + if (hist_entry__parse_objdump_line(self, file, head) < 0) + break; + + pclose(file); + return 0; +} diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 1c5f93a..ed9c067 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -11,6 +11,32 @@ struct addr_location; struct symbol; struct rb_root; +struct objdump_line { + struct list_head node; + s64 offset; + char *line; +}; + +void objdump_line__free(struct objdump_line *self); +struct objdump_line *objdump__get_next_ip_line(struct list_head *head, + struct objdump_line *pos); + +struct sym_hist { + u64 sum; + u64 ip[0]; +}; + +struct sym_ext { + struct rb_node node; + double percent; + char *path; +}; + +struct sym_priv { + struct sym_hist *hist; + struct sym_ext *ext; +}; + struct events_stats { u64 total; u64 lost; @@ -45,6 +71,9 @@ void hists__collapse_resort(struct hists *self); size_t hists__fprintf(struct hists *self, struct hists *pair, bool show_displacement, FILE *fp); +int hist_entry__inc_addr_samples(struct hist_entry *self, u64 ip); +int hist_entry__annotate(struct hist_entry *self, struct list_head *head); + void hists__filter_by_dso(struct hists *self, const struct dso *dso); void hists__filter_by_thread(struct hists *self, const struct thread *thread); diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index daa86ef..ba6acd0 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -2,6 +2,7 @@ #include #undef _GNU_SOURCE +#include #include #include #include @@ -171,6 +172,254 @@ static bool dialog_yesno(const char *msg) return newtWinChoice(NULL, yes, no, (char *)msg) == 1; } +#define HE_COLORSET_TOP 50 +#define HE_COLORSET_MEDIUM 51 +#define HE_COLORSET_NORMAL 52 +#define HE_COLORSET_SELECTED 53 +#define HE_COLORSET_CODE 54 + +static int ui_browser__percent_color(double percent, bool current) +{ + if (current) + return HE_COLORSET_SELECTED; + if (percent >= MIN_RED) + return HE_COLORSET_TOP; + if (percent >= MIN_GREEN) + return HE_COLORSET_MEDIUM; + return HE_COLORSET_NORMAL; +} + +struct ui_browser { + newtComponent form, sb; + u64 index, first_visible_entry_idx; + void *first_visible_entry, *entries; + u16 top, left, width, height; + void *priv; + u32 nr_entries; +}; + +static void ui_browser__refresh_dimensions(struct ui_browser *self) +{ + int cols, rows; + newtGetScreenSize(&cols, &rows); + + if (self->width > cols - 4) + self->width = cols - 4; + self->height = rows - 5; + if (self->height > self->nr_entries) + self->height = self->nr_entries; + self->top = (rows - self->height) / 2; + self->left = (cols - self->width) / 2; +} + +static void ui_browser__reset_index(struct ui_browser *self) +{ + self->index = self->first_visible_entry_idx = 0; + self->first_visible_entry = NULL; +} + +static int objdump_line__show(struct objdump_line *self, struct list_head *head, + int width, struct hist_entry *he, int len, + bool current_entry) +{ + if (self->offset != -1) { + struct symbol *sym = he->ms.sym; + unsigned int hits = 0; + double percent = 0.0; + int color; + struct sym_priv *priv = symbol__priv(sym); + struct sym_ext *sym_ext = priv->ext; + struct sym_hist *h = priv->hist; + s64 offset = self->offset; + struct objdump_line *next = objdump__get_next_ip_line(head, self); + + while (offset < (s64)len && + (next == NULL || offset < next->offset)) { + if (sym_ext) { + percent += sym_ext[offset].percent; + } else + hits += h->ip[offset]; + + ++offset; + } + + if (sym_ext == NULL && h->sum) + percent = 100.0 * hits / h->sum; + + color = ui_browser__percent_color(percent, current_entry); + SLsmg_set_color(color); + SLsmg_printf(" %7.2f ", percent); + if (!current_entry) + SLsmg_set_color(HE_COLORSET_CODE); + } else { + int color = ui_browser__percent_color(0, current_entry); + SLsmg_set_color(color); + SLsmg_write_nstring(" ", 9); + } + + SLsmg_write_char(':'); + SLsmg_write_nstring(" ", 8); + if (!*self->line) + SLsmg_write_nstring(" ", width - 18); + else + SLsmg_write_nstring(self->line, width - 18); + + return 0; +} + +static int ui_browser__refresh_entries(struct ui_browser *self) +{ + struct objdump_line *pos; + struct list_head *head = self->entries; + struct hist_entry *he = self->priv; + int row = 0; + int len = he->ms.sym->end - he->ms.sym->start; + + if (self->first_visible_entry == NULL || self->first_visible_entry == self->entries) + self->first_visible_entry = head->next; + + pos = list_entry(self->first_visible_entry, struct objdump_line, node); + + list_for_each_entry_from(pos, head, node) { + bool current_entry = (self->first_visible_entry_idx + row) == self->index; + SLsmg_gotorc(self->top + row, self->left); + objdump_line__show(pos, head, self->width, + he, len, current_entry); + if (++row == self->height) + break; + } + + SLsmg_set_color(HE_COLORSET_NORMAL); + SLsmg_fill_region(self->top + row, self->left, + self->height - row, self->width, ' '); + + return 0; +} + +static int ui_browser__run(struct ui_browser *self, const char *title, + struct newtExitStruct *es) +{ + if (self->form) { + newtFormDestroy(self->form); + newtPopWindow(); + } + + ui_browser__refresh_dimensions(self); + newtCenteredWindow(self->width + 2, self->height, title); + self->form = newt_form__new(); + if (self->form == NULL) + return -1; + + self->sb = newtVerticalScrollbar(self->width + 1, 0, self->height, + HE_COLORSET_NORMAL, + HE_COLORSET_SELECTED); + if (self->sb == NULL) + return -1; + + newtFormAddHotKey(self->form, NEWT_KEY_UP); + newtFormAddHotKey(self->form, NEWT_KEY_DOWN); + newtFormAddHotKey(self->form, NEWT_KEY_PGUP); + newtFormAddHotKey(self->form, NEWT_KEY_PGDN); + newtFormAddHotKey(self->form, NEWT_KEY_HOME); + newtFormAddHotKey(self->form, NEWT_KEY_END); + + if (ui_browser__refresh_entries(self) < 0) + return -1; + newtFormAddComponent(self->form, self->sb); + + while (1) { + unsigned int offset; + + newtFormRun(self->form, es); + + if (es->reason != NEWT_EXIT_HOTKEY) + break; + switch (es->u.key) { + case NEWT_KEY_DOWN: + if (self->index == self->nr_entries - 1) + break; + ++self->index; + if (self->index == self->first_visible_entry_idx + self->height) { + struct list_head *pos = self->first_visible_entry; + ++self->first_visible_entry_idx; + self->first_visible_entry = pos->next; + } + break; + case NEWT_KEY_UP: + if (self->index == 0) + break; + --self->index; + if (self->index < self->first_visible_entry_idx) { + struct list_head *pos = self->first_visible_entry; + --self->first_visible_entry_idx; + self->first_visible_entry = pos->prev; + } + break; + case NEWT_KEY_PGDN: + if (self->first_visible_entry_idx + self->height > self->nr_entries - 1) + break; + + offset = self->height; + if (self->index + offset > self->nr_entries - 1) + offset = self->nr_entries - 1 - self->index; + self->index += offset; + self->first_visible_entry_idx += offset; + + while (offset--) { + struct list_head *pos = self->first_visible_entry; + self->first_visible_entry = pos->next; + } + + break; + case NEWT_KEY_PGUP: + if (self->first_visible_entry_idx == 0) + break; + + if (self->first_visible_entry_idx < self->height) + offset = self->first_visible_entry_idx; + else + offset = self->height; + + self->index -= offset; + self->first_visible_entry_idx -= offset; + + while (offset--) { + struct list_head *pos = self->first_visible_entry; + self->first_visible_entry = pos->prev; + } + break; + case NEWT_KEY_HOME: + ui_browser__reset_index(self); + break; + case NEWT_KEY_END: { + struct list_head *head = self->entries; + offset = self->height - 1; + + if (offset > self->nr_entries) + offset = self->nr_entries; + + self->index = self->first_visible_entry_idx = self->nr_entries - 1 - offset; + self->first_visible_entry = head->prev; + while (offset-- != 0) { + struct list_head *pos = self->first_visible_entry; + self->first_visible_entry = pos->prev; + } + } + break; + case NEWT_KEY_ESCAPE: + case CTRL('c'): + case 'Q': + case 'q': + return 0; + default: + continue; + } + if (ui_browser__refresh_entries(self) < 0) + return -1; + } + return 0; +} + /* * When debugging newt problems it was useful to be able to "unroll" * the calls to newtCheckBoxTreeAdd{Array,Item}, so that we can generate @@ -353,62 +602,40 @@ static size_t hist_entry__append_browser(struct hist_entry *self, return ret; } -static void map_symbol__annotate_browser(const struct map_symbol *self, - const char *input_name) +static void hist_entry__annotate_browser(struct hist_entry *self) { - FILE *fp; - int cols, rows; - newtComponent form, tree; + struct ui_browser browser; struct newtExitStruct es; - char *str; - size_t line_len, max_line_len = 0; - size_t max_usable_width; - char *line = NULL; + struct objdump_line *pos, *n; + LIST_HEAD(head); - if (self->sym == NULL) + if (self->ms.sym == NULL) return; - if (asprintf(&str, "perf annotate -i \"%s\" -d \"%s\" %s 2>&1 | expand", - input_name, self->map->dso->name, self->sym->name) < 0) + if (hist_entry__annotate(self, &head) < 0) return; - fp = popen(str, "r"); - if (fp == NULL) - goto out_free_str; - ui_helpline__push("Press ESC to exit"); - newtGetScreenSize(&cols, &rows); - tree = newtListbox(0, 0, rows - 5, NEWT_FLAG_SCROLL); - - while (!feof(fp)) { - if (getline(&line, &line_len, fp) < 0 || !line_len) - break; - while (line_len != 0 && isspace(line[line_len - 1])) - line[--line_len] = '\0'; - if (line_len > max_line_len) - max_line_len = line_len; - newtListboxAppendEntry(tree, line, NULL); + memset(&browser, 0, sizeof(browser)); + browser.entries = &head; + browser.priv = self; + list_for_each_entry(pos, &head, node) { + size_t line_len = strlen(pos->line); + if (browser.width < line_len) + browser.width = line_len; + ++browser.nr_entries; } - fclose(fp); - free(line); - - max_usable_width = cols - 22; - if (max_line_len > max_usable_width) - max_line_len = max_usable_width; - - newtListboxSetWidth(tree, max_line_len); - newtCenteredWindow(max_line_len + 2, rows - 5, self->sym->name); - form = newt_form__new(); - newtFormAddComponent(form, tree); - - newtFormRun(form, &es); - newtFormDestroy(form); + browser.width += 18; /* Percentage */ + ui_browser__run(&browser, self->ms.sym->name, &es); + newtFormDestroy(browser.form); newtPopWindow(); + list_for_each_entry_safe(pos, n, &head, node) { + list_del(&pos->node); + objdump_line__free(pos); + } ui_helpline__pop(); -out_free_str: - free(str); } static const void *newt__symbol_tree_get_current(newtComponent self) @@ -527,7 +754,7 @@ static int hist_browser__populate(struct hist_browser *self, struct hists *hists return 0; } -static struct thread *hist_browser__selected_thread(struct hist_browser *self) +static struct hist_entry *hist_browser__selected_entry(struct hist_browser *self) { int *indexes; @@ -543,7 +770,13 @@ static struct thread *hist_browser__selected_thread(struct hist_browser *self) } return NULL; out: - return *(struct thread **)(self->selection + 1); + return container_of(self->selection, struct hist_entry, ms); +} + +static struct thread *hist_browser__selected_thread(struct hist_browser *self) +{ + struct hist_entry *he = hist_browser__selected_entry(self); + return he ? he->thread : NULL; } static int hist_browser__title(char *bf, size_t size, const char *input_name, @@ -637,13 +870,20 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na continue; do_annotate: if (choice == annotate) { + struct hist_entry *he; + if (browser->selection->map->dso->origin == DSO__ORIG_KERNEL) { ui_helpline__puts("No vmlinux file found, can't " "annotate with just a " "kallsyms file"); continue; } - map_symbol__annotate_browser(browser->selection, input_name); + + he = hist_browser__selected_entry(browser); + if (he == NULL) + continue; + + hist_entry__annotate_browser(he); } else if (choice == zoom_dso) { if (dso_filter) { ui_helpline__pop(); @@ -681,8 +921,23 @@ out: return err; } +static struct newtPercentTreeColors { + const char *topColorFg, *topColorBg; + const char *mediumColorFg, *mediumColorBg; + const char *normalColorFg, *normalColorBg; + const char *selColorFg, *selColorBg; + const char *codeColorFg, *codeColorBg; +} defaultPercentTreeColors = { + "red", "lightgray", + "green", "lightgray", + "black", "lightgray", + "lightgray", "magenta", + "blue", "lightgray", +}; + void setup_browser(void) { + struct newtPercentTreeColors *c = &defaultPercentTreeColors; if (!isatty(1)) return; @@ -690,6 +945,11 @@ void setup_browser(void) newtInit(); newtCls(); ui_helpline__puts(" "); + SLtt_set_color(HE_COLORSET_TOP, NULL, c->topColorFg, c->topColorBg); + SLtt_set_color(HE_COLORSET_MEDIUM, NULL, c->mediumColorFg, c->mediumColorBg); + SLtt_set_color(HE_COLORSET_NORMAL, NULL, c->normalColorFg, c->normalColorBg); + SLtt_set_color(HE_COLORSET_SELECTED, NULL, c->selColorFg, c->selColorBg); + SLtt_set_color(HE_COLORSET_CODE, NULL, c->codeColorFg, c->codeColorBg); } void exit_browser(bool wait_for_ok) diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index b7c54ee..af301ac 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h @@ -48,12 +48,6 @@ struct hist_entry { u64 count_us; u64 count_guest_sys; u64 count_guest_us; - - /* - * XXX WARNING! - * thread _has_ to come after ms, see - * hist_browser__selected_thread in util/newt.c - */ struct map_symbol ms; struct thread *thread; u64 ip; -- cgit v0.10.2 From aa3e5572c538d753dce11bf93532a75f95d22b40 Mon Sep 17 00:00:00 2001 From: Steve French Date: Wed, 12 May 2010 02:24:12 +0000 Subject: [CIFS] drop quota operation stubs CIFS has stubs for XFS-style quotas without an actual implementation backing them, hidden behind a config option not visible in Kconfig. Remove these stubs for now as the quota operations will see some major changes and this code simply gets in the way. Signed-off-by: Christoph Hellwig Reviewed-by: Jeff Layton Signed-off-by: Jan Kara Signed-off-by: Steve French diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 09842d3..8331663 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -49,10 +49,6 @@ #include "cifs_spnego.h" #define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */ -#ifdef CONFIG_CIFS_QUOTA -static const struct quotactl_ops cifs_quotactl_ops; -#endif /* QUOTA */ - int cifsFYI = 0; int cifsERROR = 1; int traceSMB = 0; @@ -135,9 +131,6 @@ cifs_read_super(struct super_block *sb, void *data, /* if (cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512) sb->s_blocksize = cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */ -#ifdef CONFIG_CIFS_QUOTA - sb->s_qcop = &cifs_quotactl_ops; -#endif sb->s_blocksize = CIFS_MAX_MSGSIZE; sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */ inode = cifs_root_iget(sb, ROOT_I); @@ -418,106 +411,6 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) return 0; } -#ifdef CONFIG_CIFS_QUOTA -int cifs_xquota_set(struct super_block *sb, int quota_type, qid_t qid, - struct fs_disk_quota *pdquota) -{ - int xid; - int rc = 0; - struct cifs_sb_info *cifs_sb = CIFS_SB(sb); - struct cifsTconInfo *pTcon; - - if (cifs_sb) - pTcon = cifs_sb->tcon; - else - return -EIO; - - - xid = GetXid(); - if (pTcon) { - cFYI(1, "set type: 0x%x id: %d", quota_type, qid); - } else - rc = -EIO; - - FreeXid(xid); - return rc; -} - -int cifs_xquota_get(struct super_block *sb, int quota_type, qid_t qid, - struct fs_disk_quota *pdquota) -{ - int xid; - int rc = 0; - struct cifs_sb_info *cifs_sb = CIFS_SB(sb); - struct cifsTconInfo *pTcon; - - if (cifs_sb) - pTcon = cifs_sb->tcon; - else - return -EIO; - - xid = GetXid(); - if (pTcon) { - cFYI(1, "set type: 0x%x id: %d", quota_type, qid); - } else - rc = -EIO; - - FreeXid(xid); - return rc; -} - -int cifs_xstate_set(struct super_block *sb, unsigned int flags, int operation) -{ - int xid; - int rc = 0; - struct cifs_sb_info *cifs_sb = CIFS_SB(sb); - struct cifsTconInfo *pTcon; - - if (cifs_sb) - pTcon = cifs_sb->tcon; - else - return -EIO; - - xid = GetXid(); - if (pTcon) { - cFYI(1, "flags: 0x%x operation: 0x%x", flags, operation); - } else - rc = -EIO; - - FreeXid(xid); - return rc; -} - -int cifs_xstate_get(struct super_block *sb, struct fs_quota_stat *qstats) -{ - int xid; - int rc = 0; - struct cifs_sb_info *cifs_sb = CIFS_SB(sb); - struct cifsTconInfo *pTcon; - - if (cifs_sb) - pTcon = cifs_sb->tcon; - else - return -EIO; - - xid = GetXid(); - if (pTcon) { - cFYI(1, "pqstats %p", qstats); - } else - rc = -EIO; - - FreeXid(xid); - return rc; -} - -static const struct quotactl_ops cifs_quotactl_ops = { - .set_xquota = cifs_xquota_set, - .get_xquota = cifs_xquota_get, - .set_xstate = cifs_xstate_set, - .get_xstate = cifs_xstate_get, -}; -#endif - static void cifs_umount_begin(struct super_block *sb) { struct cifs_sb_info *cifs_sb = CIFS_SB(sb); -- cgit v0.10.2 From f818a73674c5d197f66b636a46d7d578d7258129 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 11 May 2010 20:56:31 -0700 Subject: ceph: fix cap removal races The iterate_session_caps helper traverses the session caps list and tries to grab an inode reference. However, the __ceph_remove_cap was clearing the inode backpointer _before_ removing itself from the session list, causing a null pointer dereference. Clear cap->ci under protection of s_cap_lock to avoid the race, and to tightly couple the list and backpointer state. Use a local flag to indicate whether we are releasing the cap, as cap->session may be modified by a racing thread in iterate_session_caps. Signed-off-by: Sage Weil diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 0c16818..d940053 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -858,6 +858,8 @@ static int __ceph_is_any_caps(struct ceph_inode_info *ci) } /* + * Remove a cap. Take steps to deal with a racing iterate_session_caps. + * * caller should hold i_lock. * caller will not hold session s_mutex if called from destroy_inode. */ @@ -866,15 +868,10 @@ void __ceph_remove_cap(struct ceph_cap *cap) struct ceph_mds_session *session = cap->session; struct ceph_inode_info *ci = cap->ci; struct ceph_mds_client *mdsc = &ceph_client(ci->vfs_inode.i_sb)->mdsc; + int removed = 0; dout("__ceph_remove_cap %p from %p\n", cap, &ci->vfs_inode); - /* remove from inode list */ - rb_erase(&cap->ci_node, &ci->i_caps); - cap->ci = NULL; - if (ci->i_auth_cap == cap) - ci->i_auth_cap = NULL; - /* remove from session list */ spin_lock(&session->s_cap_lock); if (session->s_cap_iterator == cap) { @@ -885,10 +882,18 @@ void __ceph_remove_cap(struct ceph_cap *cap) list_del_init(&cap->session_caps); session->s_nr_caps--; cap->session = NULL; + removed = 1; } + /* protect backpointer with s_cap_lock: see iterate_session_caps */ + cap->ci = NULL; spin_unlock(&session->s_cap_lock); - if (cap->session == NULL) + /* remove from inode list */ + rb_erase(&cap->ci_node, &ci->i_caps); + if (ci->i_auth_cap == cap) + ci->i_auth_cap = NULL; + + if (removed) ceph_put_cap(cap); if (!__ceph_is_any_caps(ci) && ci->i_snap_realm) { diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index eccc0ec..24561a5 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -736,9 +736,10 @@ static void cleanup_cap_releases(struct ceph_mds_session *session) } /* - * Helper to safely iterate over all caps associated with a session. + * Helper to safely iterate over all caps associated with a session, with + * special care taken to handle a racing __ceph_remove_cap(). * - * caller must hold session s_mutex + * Caller must hold session s_mutex. */ static int iterate_session_caps(struct ceph_mds_session *session, int (*cb)(struct inode *, struct ceph_cap *, -- cgit v0.10.2 From e84346b726ea90a8ed470bc81c4136a7b8710ea5 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 11 May 2010 21:20:38 -0700 Subject: ceph: preserve seq # on requeued messages after transient transport errors If the tcp connection drops and we reconnect to reestablish a stateful session (with the mds), we need to resend previously sent (and possibly received) messages with the _same_ seq # so that they can be dropped on the other end if needed. Only assign a new seq once after the message is queued. Signed-off-by: Sage Weil diff --git a/fs/ceph/messenger.c b/fs/ceph/messenger.c index a3a8f36..cd4fadb 100644 --- a/fs/ceph/messenger.c +++ b/fs/ceph/messenger.c @@ -492,7 +492,14 @@ static void prepare_write_message(struct ceph_connection *con) list_move_tail(&m->list_head, &con->out_sent); } - m->hdr.seq = cpu_to_le64(++con->out_seq); + /* + * only assign outgoing seq # if we haven't sent this message + * yet. if it is requeued, resend with it's original seq. + */ + if (m->needs_out_seq) { + m->hdr.seq = cpu_to_le64(++con->out_seq); + m->needs_out_seq = false; + } dout("prepare_write_message %p seq %lld type %d len %d+%d+%d %d pgs\n", m, con->out_seq, le16_to_cpu(m->hdr.type), @@ -1986,6 +1993,8 @@ void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg) BUG_ON(msg->front.iov_len != le32_to_cpu(msg->hdr.front_len)); + msg->needs_out_seq = true; + /* queue */ mutex_lock(&con->mutex); BUG_ON(!list_empty(&msg->list_head)); diff --git a/fs/ceph/messenger.h b/fs/ceph/messenger.h index a343dae..a5caf91 100644 --- a/fs/ceph/messenger.h +++ b/fs/ceph/messenger.h @@ -86,6 +86,7 @@ struct ceph_msg { struct kref kref; bool front_is_vmalloc; bool more_to_follow; + bool needs_out_seq; int front_max; struct ceph_msgpool *pool; -- cgit v0.10.2 From 0fe1ac48bef018bed896307cd12f6ca9b5e704ab Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 13 Apr 2010 20:46:04 +0000 Subject: powerpc/perf_event: Fix oops due to perf_event_do_pending call Anton Blanchard found that large POWER systems would occasionally crash in the exception exit path when profiling with perf_events. The symptom was that an interrupt would occur late in the exit path when the MSR[RI] (recoverable interrupt) bit was clear. Interrupts should be hard-disabled at this point but they were enabled. Because the interrupt was not recoverable the system panicked. The reason is that the exception exit path was calling perf_event_do_pending after hard-disabling interrupts, and perf_event_do_pending will re-enable interrupts. The simplest and cleanest fix for this is to use the same mechanism that 32-bit powerpc does, namely to cause a self-IPI by setting the decrementer to 1. This means we can remove the tests in the exception exit path and raw_local_irq_restore. This also makes sure that the call to perf_event_do_pending from timer_interrupt() happens within irq_enter/irq_exit. (Note that calling perf_event_do_pending from timer_interrupt does not mean that there is a possible 1/HZ latency; setting the decrementer to 1 ensures that the timer interrupt will happen immediately, i.e. within one timebase tick, which is a few nanoseconds or 10s of nanoseconds.) Signed-off-by: Paul Mackerras Cc: stable@kernel.org Signed-off-by: Benjamin Herrenschmidt diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h index 9f4c9d4f..bd100fc 100644 --- a/arch/powerpc/include/asm/hw_irq.h +++ b/arch/powerpc/include/asm/hw_irq.h @@ -130,43 +130,5 @@ static inline int irqs_disabled_flags(unsigned long flags) */ struct irq_chip; -#ifdef CONFIG_PERF_EVENTS - -#ifdef CONFIG_PPC64 -static inline unsigned long test_perf_event_pending(void) -{ - unsigned long x; - - asm volatile("lbz %0,%1(13)" - : "=r" (x) - : "i" (offsetof(struct paca_struct, perf_event_pending))); - return x; -} - -static inline void set_perf_event_pending(void) -{ - asm volatile("stb %0,%1(13)" : : - "r" (1), - "i" (offsetof(struct paca_struct, perf_event_pending))); -} - -static inline void clear_perf_event_pending(void) -{ - asm volatile("stb %0,%1(13)" : : - "r" (0), - "i" (offsetof(struct paca_struct, perf_event_pending))); -} -#endif /* CONFIG_PPC64 */ - -#else /* CONFIG_PERF_EVENTS */ - -static inline unsigned long test_perf_event_pending(void) -{ - return 0; -} - -static inline void clear_perf_event_pending(void) {} -#endif /* CONFIG_PERF_EVENTS */ - #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_HW_IRQ_H */ diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 957ceb7..c09138d 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -133,7 +133,6 @@ int main(void) DEFINE(PACAKMSR, offsetof(struct paca_struct, kernel_msr)); DEFINE(PACASOFTIRQEN, offsetof(struct paca_struct, soft_enabled)); DEFINE(PACAHARDIRQEN, offsetof(struct paca_struct, hard_enabled)); - DEFINE(PACAPERFPEND, offsetof(struct paca_struct, perf_event_pending)); DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id)); #ifdef CONFIG_PPC_MM_SLICES DEFINE(PACALOWSLICESPSIZE, offsetof(struct paca_struct, diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 07109d8..42e9d90 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -556,15 +556,6 @@ ALT_FW_FTR_SECTION_END_IFCLR(FW_FEATURE_ISERIES) 2: TRACE_AND_RESTORE_IRQ(r5); -#ifdef CONFIG_PERF_EVENTS - /* check paca->perf_event_pending if we're enabling ints */ - lbz r3,PACAPERFPEND(r13) - and. r3,r3,r5 - beq 27f - bl .perf_event_do_pending -27: -#endif /* CONFIG_PERF_EVENTS */ - /* extract EE bit and use it to restore paca->hard_enabled */ ld r3,_MSR(r1) rldicl r4,r3,49,63 /* r0 = (r3 >> 15) & 1 */ diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 64f6f20..066bd31 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -53,7 +53,6 @@ #include #include #include -#include #include #include @@ -145,11 +144,6 @@ notrace void raw_local_irq_restore(unsigned long en) } #endif /* CONFIG_PPC_STD_MMU_64 */ - if (test_perf_event_pending()) { - clear_perf_event_pending(); - perf_event_do_pending(); - } - /* * if (get_paca()->hard_enabled) return; * But again we need to take care that gcc gets hard_enabled directly diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 1b16b9a..0441bbd 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -532,25 +532,60 @@ void __init iSeries_time_init_early(void) } #endif /* CONFIG_PPC_ISERIES */ -#if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_PPC32) -DEFINE_PER_CPU(u8, perf_event_pending); +#ifdef CONFIG_PERF_EVENTS -void set_perf_event_pending(void) +/* + * 64-bit uses a byte in the PACA, 32-bit uses a per-cpu variable... + */ +#ifdef CONFIG_PPC64 +static inline unsigned long test_perf_event_pending(void) { - get_cpu_var(perf_event_pending) = 1; - set_dec(1); - put_cpu_var(perf_event_pending); + unsigned long x; + + asm volatile("lbz %0,%1(13)" + : "=r" (x) + : "i" (offsetof(struct paca_struct, perf_event_pending))); + return x; } +static inline void set_perf_event_pending_flag(void) +{ + asm volatile("stb %0,%1(13)" : : + "r" (1), + "i" (offsetof(struct paca_struct, perf_event_pending))); +} + +static inline void clear_perf_event_pending(void) +{ + asm volatile("stb %0,%1(13)" : : + "r" (0), + "i" (offsetof(struct paca_struct, perf_event_pending))); +} + +#else /* 32-bit */ + +DEFINE_PER_CPU(u8, perf_event_pending); + +#define set_perf_event_pending_flag() __get_cpu_var(perf_event_pending) = 1 #define test_perf_event_pending() __get_cpu_var(perf_event_pending) #define clear_perf_event_pending() __get_cpu_var(perf_event_pending) = 0 -#else /* CONFIG_PERF_EVENTS && CONFIG_PPC32 */ +#endif /* 32 vs 64 bit */ + +void set_perf_event_pending(void) +{ + preempt_disable(); + set_perf_event_pending_flag(); + set_dec(1); + preempt_enable(); +} + +#else /* CONFIG_PERF_EVENTS */ #define test_perf_event_pending() 0 #define clear_perf_event_pending() -#endif /* CONFIG_PERF_EVENTS && CONFIG_PPC32 */ +#endif /* CONFIG_PERF_EVENTS */ /* * For iSeries shared processors, we have to let the hypervisor @@ -582,10 +617,6 @@ void timer_interrupt(struct pt_regs * regs) set_dec(DECREMENTER_MAX); #ifdef CONFIG_PPC32 - if (test_perf_event_pending()) { - clear_perf_event_pending(); - perf_event_do_pending(); - } if (atomic_read(&ppc_n_lost_interrupts) != 0) do_IRQ(regs); #endif @@ -604,6 +635,11 @@ void timer_interrupt(struct pt_regs * regs) calculate_steal_time(); + if (test_perf_event_pending()) { + clear_perf_event_pending(); + perf_event_do_pending(); + } + #ifdef CONFIG_PPC_ISERIES if (firmware_has_feature(FW_FEATURE_ISERIES)) get_lppaca()->int_dword.fields.decr_int = 0; -- cgit v0.10.2 From 1c1e093cbf6d3a7576ba0bd10363362a1c5c74ee Mon Sep 17 00:00:00 2001 From: Stefan Weinhuber Date: Wed, 12 May 2010 09:32:11 +0200 Subject: [S390] dasd: fix race between tasklet and dasd_sleep_on The various dasd_sleep_on functions use a global wait queue when waiting for a cqr. The wait condition checks the status and devlist fields of the cqr to determine if it is safe to continue. This evaluation may return true, although the tasklet has not finished processing of the cqr and the callback function has not been called yet. When the callback is finally called, the data in the cqr may already be invalid. The sleep_on wait condition needs a safe way to determine if the tasklet has finished processing. Use the callback_data field of the cqr to store a token, which is set by the callback function itself. Cc: Signed-off-by: Stefan Weinhuber Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index acf222f..fa2339c 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -37,6 +37,9 @@ */ #define DASD_CHANQ_MAX_SIZE 4 +#define DASD_SLEEPON_START_TAG (void *) 1 +#define DASD_SLEEPON_END_TAG (void *) 2 + /* * SECTION: exported variables of dasd.c */ @@ -1472,7 +1475,10 @@ void dasd_add_request_tail(struct dasd_ccw_req *cqr) */ static void dasd_wakeup_cb(struct dasd_ccw_req *cqr, void *data) { - wake_up((wait_queue_head_t *) data); + spin_lock_irq(get_ccwdev_lock(cqr->startdev->cdev)); + cqr->callback_data = DASD_SLEEPON_END_TAG; + spin_unlock_irq(get_ccwdev_lock(cqr->startdev->cdev)); + wake_up(&generic_waitq); } static inline int _wait_for_wakeup(struct dasd_ccw_req *cqr) @@ -1482,10 +1488,7 @@ static inline int _wait_for_wakeup(struct dasd_ccw_req *cqr) device = cqr->startdev; spin_lock_irq(get_ccwdev_lock(device->cdev)); - rc = ((cqr->status == DASD_CQR_DONE || - cqr->status == DASD_CQR_NEED_ERP || - cqr->status == DASD_CQR_TERMINATED) && - list_empty(&cqr->devlist)); + rc = (cqr->callback_data == DASD_SLEEPON_END_TAG); spin_unlock_irq(get_ccwdev_lock(device->cdev)); return rc; } @@ -1573,7 +1576,7 @@ static int _dasd_sleep_on(struct dasd_ccw_req *maincqr, int interruptible) wait_event(generic_waitq, !(device->stopped)); cqr->callback = dasd_wakeup_cb; - cqr->callback_data = (void *) &generic_waitq; + cqr->callback_data = DASD_SLEEPON_START_TAG; dasd_add_request_tail(cqr); if (interruptible) { rc = wait_event_interruptible( @@ -1652,7 +1655,7 @@ int dasd_sleep_on_immediatly(struct dasd_ccw_req *cqr) } cqr->callback = dasd_wakeup_cb; - cqr->callback_data = (void *) &generic_waitq; + cqr->callback_data = DASD_SLEEPON_START_TAG; cqr->status = DASD_CQR_QUEUED; list_add(&cqr->devlist, &device->ccw_queue); -- cgit v0.10.2 From 545c174d1f093a462b4bb9131b23d5ea72a600e1 Mon Sep 17 00:00:00 2001 From: Gerald Schaefer Date: Wed, 12 May 2010 09:32:12 +0200 Subject: [S390] ptrace: fix return value of do_syscall_trace_enter() strace may change the system call number, so regs->gprs[2] must not be read before tracehook_report_syscall_entry(). This fixes a bug where "strace -f" will hang after a vfork(). Cc: Signed-off-by: Gerald Schaefer Signed-off-by: Martin Schwidefsky diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index 33fdc5a..9f654da 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -640,7 +640,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, asmlinkage long do_syscall_trace_enter(struct pt_regs *regs) { - long ret; + long ret = 0; /* Do the secure computing check first. */ secure_computing(regs->gprs[2]); @@ -649,7 +649,6 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs) * The sysc_tracesys code in entry.S stored the system * call number to gprs[2]. */ - ret = regs->gprs[2]; if (test_thread_flag(TIF_SYSCALL_TRACE) && (tracehook_report_syscall_entry(regs) || regs->gprs[2] >= NR_syscalls)) { @@ -671,7 +670,7 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs) regs->gprs[2], regs->orig_gpr2, regs->gprs[3], regs->gprs[4], regs->gprs[5]); - return ret; + return ret ?: regs->gprs[2]; } asmlinkage void do_syscall_trace_exit(struct pt_regs *regs) -- cgit v0.10.2 From 57d84906f0f3005d4d22e13a3f5102a16a7fc4a2 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Wed, 12 May 2010 09:32:13 +0200 Subject: [S390] correct address of _stext with CONFIG_SHARED_KERNEL=y As of git commit 1844c9bc0b2fed3023551c1affe033ab38e90b9a head64.S/head31.S are not included in head.S anymore but build as an extra object. This breaks shared kernel support because the .org statement in head64.S/head31.S for CONFIG_SHARED_KERNEL=y will have a different effect. The end address of the head.text section in head.o will be added to the .org value, to compensate for this subtract 0x11000 to get the required value of 0x100000 again. Signed-off-by: Martin Schwidefsky diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S index 1bbcc49..b8f8dc1 100644 --- a/arch/s390/kernel/head31.S +++ b/arch/s390/kernel/head31.S @@ -82,7 +82,7 @@ startup_continue: _ehead: #ifdef CONFIG_SHARED_KERNEL - .org 0x100000 + .org 0x100000 - 0x11000 # head.o ends at 0x11000 #endif # diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S index 1f70970..cdef687 100644 --- a/arch/s390/kernel/head64.S +++ b/arch/s390/kernel/head64.S @@ -80,7 +80,7 @@ startup_continue: _ehead: #ifdef CONFIG_SHARED_KERNEL - .org 0x100000 + .org 0x100000 - 0x11000 # head.o ends at 0x11000 #endif # -- cgit v0.10.2 From 2a6ce6e5fda4721b35f309acedf4cac61ecbfb04 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 12 May 2010 10:16:20 +0200 Subject: ALSA: hda - Add hp-dv4 model for IDT 92HD71bx It turned out that HP dv series have inconsistent the mute-LED GPIO mapping among various models. dv4/7 seem to use GPIO 0 while dv 5/6 seem to use GPIO 3. The previous commit 26ebe0a28986f4845b2c5bea43ac5cc0b9f27f0a ALSA: hda - Fix mute-LED GPIO pin for HP dv series breaks dv5/6. This patch adds the new quirk model, hp-dv4, to handle HP dv4/7 separately from HP dv5/6. Tested-by: Kunal Gangakhedkar (for dv6-1110ax) Acked-by: Kunal Gangakhedkar Signed-off-by: Takashi Iwai diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index eb4ea3d..a0e06d8 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -104,6 +104,7 @@ enum { STAC_DELL_M4_2, STAC_DELL_M4_3, STAC_HP_M4, + STAC_HP_DV4, STAC_HP_DV5, STAC_HP_HDX, STAC_HP_DV4_1222NR, @@ -1691,6 +1692,7 @@ static unsigned int *stac92hd71bxx_brd_tbl[STAC_92HD71BXX_MODELS] = { [STAC_DELL_M4_2] = dell_m4_2_pin_configs, [STAC_DELL_M4_3] = dell_m4_3_pin_configs, [STAC_HP_M4] = NULL, + [STAC_HP_DV4] = NULL, [STAC_HP_DV5] = NULL, [STAC_HP_HDX] = NULL, [STAC_HP_DV4_1222NR] = NULL, @@ -1703,6 +1705,7 @@ static const char *stac92hd71bxx_models[STAC_92HD71BXX_MODELS] = { [STAC_DELL_M4_2] = "dell-m4-2", [STAC_DELL_M4_3] = "dell-m4-3", [STAC_HP_M4] = "hp-m4", + [STAC_HP_DV4] = "hp-dv4", [STAC_HP_DV5] = "hp-dv5", [STAC_HP_HDX] = "hp-hdx", [STAC_HP_DV4_1222NR] = "hp-dv4-1222nr", @@ -1721,7 +1724,7 @@ static struct snd_pci_quirk stac92hd71bxx_cfg_tbl[] = { SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3080, "HP", STAC_HP_DV5), SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x30f0, - "HP dv4-7", STAC_HP_DV5), + "HP dv4-7", STAC_HP_DV4), SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xfff0, 0x3600, "HP dv4-7", STAC_HP_DV5), SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3610, @@ -5678,6 +5681,9 @@ again: spec->num_smuxes = 1; spec->num_dmuxes = 1; /* fallthrough */ + case STAC_HP_DV4: + spec->gpio_led = 0x01; + /* fallthrough */ case STAC_HP_DV5: snd_hda_codec_set_pincfg(codec, 0x0d, 0x90170010); stac92xx_auto_set_pinctl(codec, 0x0d, AC_PINCTL_OUT_EN); @@ -5686,7 +5692,6 @@ again: * detection. */ spec->hp_detect = 1; - spec->gpio_led = 0x01; break; case STAC_HP_HDX: spec->num_dmics = 1; @@ -5749,7 +5754,8 @@ again: } /* enable bass on HP dv7 */ - if (spec->board_config == STAC_HP_DV5) { + if (spec->board_config == STAC_HP_DV4 || + spec->board_config == STAC_HP_DV5) { unsigned int cap; cap = snd_hda_param_read(codec, 0x1, AC_PAR_GPIO_CAP); cap &= AC_GPIO_IO_COUNT; -- cgit v0.10.2 From 6a45f7822544c54a2cf070d84f4e85f2fb32ec02 Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Tue, 11 May 2010 16:34:39 +0200 Subject: ALSA: virtuoso: fix Xonar D1/DX front panel microphone Commit 65c3ac885ce9852852b895a4a62212f62cb5f2e9 in 2.6.33 accidentally left out the initialization of the AC97 codec FMIC2MIC bit, which broke recording from the front panel microphone. Signed-off-by: Clemens Ladisch Cc: Signed-off-by: Jaroslav Kysela Signed-off-by: Takashi Iwai diff --git a/sound/pci/oxygen/xonar_cs43xx.c b/sound/pci/oxygen/xonar_cs43xx.c index 16c226b..7c4986b 100644 --- a/sound/pci/oxygen/xonar_cs43xx.c +++ b/sound/pci/oxygen/xonar_cs43xx.c @@ -56,6 +56,7 @@ #include #include #include "xonar.h" +#include "cm9780.h" #include "cs4398.h" #include "cs4362a.h" @@ -172,6 +173,8 @@ static void xonar_d1_init(struct oxygen *chip) oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_D1_FRONT_PANEL | GPIO_D1_INPUT_ROUTE); + oxygen_ac97_set_bits(chip, 0, CM9780_JACK, CM9780_FMIC2MIC); + xonar_init_cs53x1(chip); xonar_enable_output(chip); -- cgit v0.10.2 From 9fe17b5d47d3d3c85b35623dea8f571a184134c0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 12 May 2010 10:32:42 +0200 Subject: ALSA: pcm - Use pgprot_noncached() for MIPS non-coherent archs MIPS non-coherent archs need the noncached pgprot in mmap of PCM buffers. But, since the coherency needs to be checked dynamically via plat_device_is_coherent(), we need an ugly check dependent on MIPS in ALSA core code. This should be cleaned up in MIPS arch side (e.g. creating dma_mmap_coherent()) in near future. Tested-by: Wu Zhangjin Signed-off-by: Takashi Iwai diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 8728876..20b5982 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -36,6 +36,9 @@ #include #include #include +#if defined(CONFIG_MIPS) && defined(CONFIG_DMA_NONCOHERENT) +#include +#endif /* * Compatibility @@ -3184,6 +3187,10 @@ static int snd_pcm_default_mmap(struct snd_pcm_substream *substream, substream->runtime->dma_area, substream->runtime->dma_addr, area->vm_end - area->vm_start); +#elif defined(CONFIG_MIPS) && defined(CONFIG_DMA_NONCOHERENT) + if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV && + !plat_device_is_coherent(substream->dma_buffer.dev.dev)) + area->vm_page_prot = pgprot_noncached(area->vm_page_prot); #endif /* ARCH_HAS_DMA_MMAP_COHERENT */ /* mmap with fault handler */ area->vm_ops = &snd_pcm_vm_ops_data_fault; -- cgit v0.10.2 From 6cd82ffe0cd3836b32b29bd1436e5fd551957d54 Mon Sep 17 00:00:00 2001 From: Maurus Cuelenaere Date: Tue, 4 May 2010 13:12:32 +0200 Subject: ARM: SAMSUNG: Move HWMON from plat-s3c24xx to plat-samsung Move HWMON platform definition from plat-s3c24xx to plat-samsung and adjust mach-bast to use the new s3c_hwmon_set_platdata(). This allows usage of dev-hwmon by other Samsung SoCs. Signed-off-by: Maurus Cuelenaere Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig index 5547318..ca5c3c6 100644 --- a/arch/arm/mach-s3c2410/Kconfig +++ b/arch/arm/mach-s3c2410/Kconfig @@ -110,6 +110,7 @@ config ARCH_BAST select MACH_BAST_IDE select S3C24XX_DCLK select ISA + select S3C_DEV_HWMON select S3C_DEV_USB_HOST select S3C_DEV_NAND help diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c index 02b1b622..c8786df 100644 --- a/arch/arm/mach-s3c2410/mach-bast.c +++ b/arch/arm/mach-s3c2410/mach-bast.c @@ -634,7 +634,7 @@ static void __init bast_map_io(void) s3c24xx_register_clocks(bast_clocks, ARRAY_SIZE(bast_clocks)); - s3c_device_hwmon.dev.platform_data = &bast_hwmon_info; + s3c_hwmon_set_platdata(&bast_hwmon_info); s3c24xx_init_io(bast_iodesc, ARRAY_SIZE(bast_iodesc)); s3c24xx_init_clocks(0); diff --git a/arch/arm/plat-s3c24xx/devs.c b/arch/arm/plat-s3c24xx/devs.c index 9265f09..3166f32 100644 --- a/arch/arm/plat-s3c24xx/devs.c +++ b/arch/arm/plat-s3c24xx/devs.c @@ -338,14 +338,6 @@ struct platform_device s3c_device_adc = { .resource = s3c_adc_resource, }; -/* HWMON */ - -struct platform_device s3c_device_hwmon = { - .name = "s3c-hwmon", - .id = -1, - .dev.parent = &s3c_device_adc.dev, -}; - /* SDI */ static struct resource s3c_sdi_resource[] = { diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig index d552c65..7a36cf8 100644 --- a/arch/arm/plat-samsung/Kconfig +++ b/arch/arm/plat-samsung/Kconfig @@ -160,6 +160,11 @@ config S3C_DEV_HSMMC2 help Compile in platform device definitions for HSMMC channel 2 +config S3C_DEV_HWMON + bool + help + Compile in platform device definitions for HWMON + config S3C_DEV_I2C1 bool help diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile index 22c89d0..0ad820a 100644 --- a/arch/arm/plat-samsung/Makefile +++ b/arch/arm/plat-samsung/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_S3C_ADC) += adc.o obj-$(CONFIG_S3C_DEV_HSMMC) += dev-hsmmc.o obj-$(CONFIG_S3C_DEV_HSMMC1) += dev-hsmmc1.o obj-$(CONFIG_S3C_DEV_HSMMC2) += dev-hsmmc2.o +obj-$(CONFIG_S3C_DEV_HWMON) += dev-hwmon.o obj-y += dev-i2c0.o obj-$(CONFIG_S3C_DEV_I2C1) += dev-i2c1.o obj-$(CONFIG_S3C_DEV_FB) += dev-fb.o diff --git a/arch/arm/plat-samsung/dev-hwmon.c b/arch/arm/plat-samsung/dev-hwmon.c new file mode 100644 index 0000000..b3ffb95 --- /dev/null +++ b/arch/arm/plat-samsung/dev-hwmon.c @@ -0,0 +1,42 @@ +/* linux/arch/arm/plat-samsung/dev-hwmon.c + * + * Copyright 2008 Simtec Electronics + * Ben Dooks + * http://armlinux.simtec.co.uk/ + * + * Adapted for HWMON by Maurus Cuelenaere + * + * Samsung series device definition for HWMON + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include + +#include +#include + +struct platform_device s3c_device_hwmon = { + .name = "s3c-hwmon", + .id = -1, + .dev.parent = &s3c_device_adc.dev, +}; + +void __init s3c_hwmon_set_platdata(struct s3c_hwmon_pdata *pd) +{ + struct s3c_hwmon_pdata *npd; + + if (!pd) { + printk(KERN_ERR "%s: no platform data\n", __func__); + return; + } + + npd = kmemdup(pd, sizeof(struct s3c_hwmon_pdata), GFP_KERNEL); + if (!npd) + printk(KERN_ERR "%s: no memory for platform data\n", __func__); + + s3c_device_hwmon.dev.platform_data = npd; +} diff --git a/arch/arm/plat-samsung/include/plat/hwmon.h b/arch/arm/plat-samsung/include/plat/hwmon.h index 1ba88ea..c167e44 100644 --- a/arch/arm/plat-samsung/include/plat/hwmon.h +++ b/arch/arm/plat-samsung/include/plat/hwmon.h @@ -37,5 +37,15 @@ struct s3c_hwmon_pdata { struct s3c_hwmon_chcfg *in[8]; }; +/** + * s3c_hwmon_set_platdata - Set platform data for S3C HWMON device + * @pd: Platform data to register to device. + * + * Register the given platform data for use with the S3C HWMON device. + * The call will copy the platform data, so the board definitions can + * make the structure itself __initdata. + */ +extern void __init s3c_hwmon_set_platdata(struct s3c_hwmon_pdata *pd); + #endif /* __ASM_ARCH_ADC_HWMON_H */ -- cgit v0.10.2 From f4a27aed48584b9e4699e9ee76288618a8574d77 Mon Sep 17 00:00:00 2001 From: Srinidhi Kasagar Date: Wed, 12 May 2010 05:52:18 +0100 Subject: ARM: 6125/1: ARM TWD: move TWD registers to common header This moves the TWD register set of MPcore to a common existing file so that watchdog driver can access it Signed-off-by: srinidhi kasagar Acked-by: Linus Walleij Signed-off-by: Russell King diff --git a/arch/arm/include/asm/smp_twd.h b/arch/arm/include/asm/smp_twd.h index 7be0978..634f357 100644 --- a/arch/arm/include/asm/smp_twd.h +++ b/arch/arm/include/asm/smp_twd.h @@ -1,6 +1,23 @@ #ifndef __ASMARM_SMP_TWD_H #define __ASMARM_SMP_TWD_H +#define TWD_TIMER_LOAD 0x00 +#define TWD_TIMER_COUNTER 0x04 +#define TWD_TIMER_CONTROL 0x08 +#define TWD_TIMER_INTSTAT 0x0C + +#define TWD_WDOG_LOAD 0x20 +#define TWD_WDOG_COUNTER 0x24 +#define TWD_WDOG_CONTROL 0x28 +#define TWD_WDOG_INTSTAT 0x2C +#define TWD_WDOG_RESETSTAT 0x30 +#define TWD_WDOG_DISABLE 0x34 + +#define TWD_TIMER_CONTROL_ENABLE (1 << 0) +#define TWD_TIMER_CONTROL_ONESHOT (0 << 1) +#define TWD_TIMER_CONTROL_PERIODIC (1 << 1) +#define TWD_TIMER_CONTROL_IT_ENABLE (1 << 2) + struct clock_event_device; extern void __iomem *twd_base; diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index ea02a7b..7c5f0c0 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c @@ -21,23 +21,6 @@ #include #include -#define TWD_TIMER_LOAD 0x00 -#define TWD_TIMER_COUNTER 0x04 -#define TWD_TIMER_CONTROL 0x08 -#define TWD_TIMER_INTSTAT 0x0C - -#define TWD_WDOG_LOAD 0x20 -#define TWD_WDOG_COUNTER 0x24 -#define TWD_WDOG_CONTROL 0x28 -#define TWD_WDOG_INTSTAT 0x2C -#define TWD_WDOG_RESETSTAT 0x30 -#define TWD_WDOG_DISABLE 0x34 - -#define TWD_TIMER_CONTROL_ENABLE (1 << 0) -#define TWD_TIMER_CONTROL_ONESHOT (0 << 1) -#define TWD_TIMER_CONTROL_PERIODIC (1 << 1) -#define TWD_TIMER_CONTROL_IT_ENABLE (1 << 2) - /* set up by the platform code */ void __iomem *twd_base; -- cgit v0.10.2 From 98af057092f8f0dabe63c5df08adc2bbfbddb1d2 Mon Sep 17 00:00:00 2001 From: Srinidhi Kasagar Date: Wed, 12 May 2010 05:53:26 +0100 Subject: ARM: 6126/1: ARM mpcore_wdt: fix build failure and other fixes This fixes the build failures seen when building mpcore_wdt and it also removes the nonexistent ARM_MPCORE_PLATFORM dependency, instead make it dependent on HAVE_ARM_TWD. Also this fixes spinlock usage appropriately. Signed-off-by: srinidhi kasagar Acked-by: Linus Walleij Signed-off-by: Russell King diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 0bf5020..b87ba23 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -175,7 +175,7 @@ config SA1100_WATCHDOG config MPCORE_WATCHDOG tristate "MPcore watchdog" - depends on ARM_MPCORE_PLATFORM && LOCAL_TIMERS + depends on HAVE_ARM_TWD help Watchdog timer embedded into the MPcore system. diff --git a/drivers/watchdog/mpcore_wdt.c b/drivers/watchdog/mpcore_wdt.c index 016c6a7..b8ec7ac 100644 --- a/drivers/watchdog/mpcore_wdt.c +++ b/drivers/watchdog/mpcore_wdt.c @@ -31,8 +31,9 @@ #include #include #include +#include -#include +#include struct mpcore_wdt { unsigned long timer_alive; @@ -44,7 +45,7 @@ struct mpcore_wdt { }; static struct platform_device *mpcore_wdt_dev; -extern unsigned int mpcore_timer_rate; +static DEFINE_SPINLOCK(wdt_lock); #define TIMER_MARGIN 60 static int mpcore_margin = TIMER_MARGIN; @@ -94,13 +95,15 @@ static irqreturn_t mpcore_wdt_fire(int irq, void *arg) */ static void mpcore_wdt_keepalive(struct mpcore_wdt *wdt) { - unsigned int count; + unsigned long count; + spin_lock(&wdt_lock); /* Assume prescale is set to 256 */ - count = (mpcore_timer_rate / 256) * mpcore_margin; + count = __raw_readl(wdt->base + TWD_WDOG_COUNTER); + count = (0xFFFFFFFFU - count) * (HZ / 5); + count = (count / 256) * mpcore_margin; /* Reload the counter */ - spin_lock(&wdt_lock); writel(count + wdt->perturb, wdt->base + TWD_WDOG_LOAD); wdt->perturb = wdt->perturb ? 0 : 1; spin_unlock(&wdt_lock); @@ -119,7 +122,6 @@ static void mpcore_wdt_start(struct mpcore_wdt *wdt) { dev_printk(KERN_INFO, wdt->dev, "enabling watchdog.\n"); - spin_lock(&wdt_lock); /* This loads the count register but does NOT start the count yet */ mpcore_wdt_keepalive(wdt); @@ -130,7 +132,6 @@ static void mpcore_wdt_start(struct mpcore_wdt *wdt) /* Enable watchdog - prescale=256, watchdog mode=1, enable=1 */ writel(0x0000FF09, wdt->base + TWD_WDOG_CONTROL); } - spin_unlock(&wdt_lock); } static int mpcore_wdt_set_heartbeat(int t) @@ -360,7 +361,7 @@ static int __devinit mpcore_wdt_probe(struct platform_device *dev) mpcore_wdt_miscdev.parent = &dev->dev; ret = misc_register(&mpcore_wdt_miscdev); if (ret) { - dev_printk(KERN_ERR, _dev, + dev_printk(KERN_ERR, wdt->dev, "cannot register miscdev on minor=%d (err=%d)\n", WATCHDOG_MINOR, ret); goto err_misc; @@ -369,13 +370,13 @@ static int __devinit mpcore_wdt_probe(struct platform_device *dev) ret = request_irq(wdt->irq, mpcore_wdt_fire, IRQF_DISABLED, "mpcore_wdt", wdt); if (ret) { - dev_printk(KERN_ERR, _dev, + dev_printk(KERN_ERR, wdt->dev, "cannot register IRQ%d for watchdog\n", wdt->irq); goto err_irq; } mpcore_wdt_stop(wdt); - platform_set_drvdata(&dev->dev, wdt); + platform_set_drvdata(dev, wdt); mpcore_wdt_dev = dev; return 0; -- cgit v0.10.2 From 8213466596bf10b75887754773ee13c10cf86f5c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 12 May 2010 16:43:32 +0200 Subject: ALSA: ice1724 - Fix ESI Maya44 capture source control The capture source control of maya44 was wrongly coded with the bit shift instead of the bit mask. Also, the slot for line-in was wrongly assigned (slot 5 instead of 4). Reported-by: Alex Chernyshoff Cc: Signed-off-by: Takashi Iwai diff --git a/sound/pci/ice1712/maya44.c b/sound/pci/ice1712/maya44.c index 3e1c20a..726fd4b 100644 --- a/sound/pci/ice1712/maya44.c +++ b/sound/pci/ice1712/maya44.c @@ -347,7 +347,7 @@ static int maya_gpio_sw_put(struct snd_kcontrol *kcontrol, /* known working input slots (0-4) */ #define MAYA_LINE_IN 1 /* in-2 */ -#define MAYA_MIC_IN 4 /* in-5 */ +#define MAYA_MIC_IN 3 /* in-4 */ static void wm8776_select_input(struct snd_maya44 *chip, int idx, int line) { @@ -393,8 +393,8 @@ static int maya_rec_src_put(struct snd_kcontrol *kcontrol, int changed; mutex_lock(&chip->mutex); - changed = maya_set_gpio_bits(chip->ice, GPIO_MIC_RELAY, - sel ? GPIO_MIC_RELAY : 0); + changed = maya_set_gpio_bits(chip->ice, 1 << GPIO_MIC_RELAY, + sel ? (1 << GPIO_MIC_RELAY) : 0); wm8776_select_input(chip, 0, sel ? MAYA_MIC_IN : MAYA_LINE_IN); mutex_unlock(&chip->mutex); return changed; -- cgit v0.10.2 From e7b702b1a8f2a6961367da903217e669be0f099f Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 18 Apr 2010 21:25:11 +0100 Subject: Inotify: undefined reference to `anon_inode_getfd' Fix: fs/built-in.o: In function `sys_inotify_init1': summary.c:(.text+0x347a4): undefined reference to `anon_inode_getfd' found by kautobuild with arms bcmring_defconfig, which ends up with INOTIFY_USER enabled (through the 'default y') but leaves ANON_INODES unset. However, inotify_user.c uses anon_inode_getfd(). Signed-off-by: Russell King Signed-off-by: Eric Paris diff --git a/fs/notify/inotify/Kconfig b/fs/notify/inotify/Kconfig index b3a159b..4427f8c 100644 --- a/fs/notify/inotify/Kconfig +++ b/fs/notify/inotify/Kconfig @@ -17,6 +17,7 @@ config INOTIFY_USER bool "Inotify support for userspace" select ANON_INODES select FSNOTIFY + select ANON_INODES default y ---help--- Say Y here to enable inotify support for userspace, including the -- cgit v0.10.2 From 0d4993563bde70bc7c7718686bc5c5c089733001 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 11 May 2010 19:44:17 +0300 Subject: vhost: fix barrier pairing According to memory-barriers.txt, an smp memory barrier in guest should always be paired with an smp memory barrier in host, and I quote "a lack of appropriate pairing is almost certainly an error". In case of vhost, failure to flush out used index update before looking at the interrupt disable flag could result in missed interrupts, resulting in networking hang under stress. This might happen when flags read bypasses used index write. So we see interrupts disabled and do not interrupt, at the same time guest writes flags value to enable interrupt, reads an old used index value, thinks that used ring is empty and waits for interrupt. Note: the barrier we pair with here is in drivers/virtio/virtio_ring.c, function vring_enable_cb. Signed-off-by: Michael S. Tsirkin Acked-by: Juan Quintela diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index e69d238..49fa953 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -1035,7 +1035,12 @@ int vhost_add_used(struct vhost_virtqueue *vq, unsigned int head, int len) /* This actually signals the guest, using eventfd. */ void vhost_signal(struct vhost_dev *dev, struct vhost_virtqueue *vq) { - __u16 flags = 0; + __u16 flags; + /* Flush out used index updates. This is paired + * with the barrier that the Guest executes when enabling + * interrupts. */ + smp_mb(); + if (get_user(flags, &vq->avail->flags)) { vq_err(vq, "Failed to get flags"); return; -- cgit v0.10.2 From fb0491146518c24b8ded5f9afa59b1df3749dea9 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Thu, 13 May 2010 09:26:49 +0900 Subject: ARM: S5P6440: Register apll/mpll/epll mout clocks. This patch modifies the following. 1. Registers the mout_apll clksrc_clk clock. 2. The mout_mpll and mout_epll were registered as 'struct clk' types and then their parents were setup using the s3c_set_clksrc function. This patch reduces the two steps into one by registering the mout_mpll and mout_epll clocks using the s3c_register_clksrc function. 3. As per point 2 above, the init_parents array is no longer required. So the mout clocks are now put together in a new array named 'sysclks'. The sysclks array will list the system level clocks and more clocks will be added to it in the subsequent patches. Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5p6440/clock.c b/arch/arm/mach-s5p6440/clock.c index b2672e1..3ad63f4 100644 --- a/arch/arm/mach-s5p6440/clock.c +++ b/arch/arm/mach-s5p6440/clock.c @@ -574,7 +574,7 @@ static struct clksrc_clk clksrcs[] = { }; /* Clock initialisation code */ -static struct clksrc_clk *init_parents[] = { +static struct clksrc_clk *sysclks[] = { &clk_mout_apll, &clk_mout_epll, &clk_mout_mpll, @@ -652,17 +652,12 @@ void __init_or_cpufreq s5p6440_setup_clocks(void) clk_h_low.rate = hclk_low; clk_p_low.rate = pclk_low; - for (ptr = 0; ptr < ARRAY_SIZE(init_parents); ptr++) - s3c_set_clksrc(init_parents[ptr], true); - for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) s3c_set_clksrc(&clksrcs[ptr], true); } static struct clk *clks[] __initdata = { &clk_ext, - &clk_mout_epll.clk, - &clk_mout_mpll.clk, &clk_dout_mpll, &clk_iis_cd_v40, &clk_pcm_cd, @@ -680,6 +675,9 @@ void __init s5p6440_register_clocks(void) if (ret > 0) printk(KERN_ERR "Failed to register %u clocks\n", ret); + for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++) + s3c_register_clksrc(sysclks[ptr], 1); + s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs)); s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks)); -- cgit v0.10.2 From 30d58349608c3a31dbea0cc9238f6d8edc21e299 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Thu, 13 May 2010 09:26:58 +0900 Subject: ARM: S5P6440: Change dout_mpll clock type to clksrc_clk clock type. This patch modifies the following. 1. Modifies the dout_mpll clock type as clksrc_clk clock type. This modification allows the use of common clock code in managing the dout_mpll clock (which otherwise would need custom defined functions such as s5p6440_clk_doutmpll_get_rate). 2. s5p6440_clk_doutmpll_get_rate function is removed as it is no longer needed. Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5p6440/clock.c b/arch/arm/mach-s5p6440/clock.c index 3ad63f4..8bd6f15 100644 --- a/arch/arm/mach-s5p6440/clock.c +++ b/arch/arm/mach-s5p6440/clock.c @@ -247,23 +247,13 @@ static struct clk_ops s5p6440_clkarm_ops = { .round_rate = s5p6440_armclk_round_rate, }; -static unsigned long s5p6440_clk_doutmpll_get_rate(struct clk *clk) -{ - unsigned long rate = clk_get_rate(clk->parent); - - if (__raw_readl(S5P_CLK_DIV0) & S5P_CLKDIV0_MPLL_MASK) - rate /= 2; - - return rate; -} - -static struct clk clk_dout_mpll = { - .name = "dout_mpll", - .id = -1, - .parent = &clk_mout_mpll.clk, - .ops = &(struct clk_ops) { - .get_rate = s5p6440_clk_doutmpll_get_rate, +static struct clksrc_clk clk_dout_mpll = { + .clk = { + .name = "dout_mpll", + .id = -1, + .parent = &clk_mout_mpll.clk, }, + .reg_div = { .reg = S5P_CLK_DIV0, .shift = 4, .size = 1 }, }; int s5p6440_clk48m_ctrl(struct clk *clk, int enable) @@ -490,7 +480,7 @@ static struct clk clk_pcm_cd = { static struct clk *clkset_spi_mmc_list[] = { &clk_mout_epll.clk, - &clk_dout_mpll, + &clk_dout_mpll.clk, &clk_fin_epll, }; @@ -501,7 +491,7 @@ static struct clksrc_sources clkset_spi_mmc = { static struct clk *clkset_uart_list[] = { &clk_mout_epll.clk, - &clk_dout_mpll + &clk_dout_mpll.clk, }; static struct clksrc_sources clkset_uart = { @@ -578,6 +568,7 @@ static struct clksrc_clk *sysclks[] = { &clk_mout_apll, &clk_mout_epll, &clk_mout_mpll, + &clk_dout_mpll, }; void __init_or_cpufreq s5p6440_setup_clocks(void) @@ -658,7 +649,6 @@ void __init_or_cpufreq s5p6440_setup_clocks(void) static struct clk *clks[] __initdata = { &clk_ext, - &clk_dout_mpll, &clk_iis_cd_v40, &clk_pcm_cd, &clk_p_low, -- cgit v0.10.2 From 9c72d016e2b556e7d8f739b21404f32333fbc5e4 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Thu, 13 May 2010 09:27:04 +0900 Subject: ARM: S5P6440: Remove usage of clk_arm and add clk_armclk clock The clk_arm clock is of type 'struct clk' whereas on S5P6440, the arm clock is more suitable to be of type 'struct clksrc_clk' (since arm clock is divided version of apll clock). This patch modifies the following. 1. Removes the usage of clk_arm clock (defined in plat-s5p) and defines the new clock 'clk_armclk' of type 'struct clksrc_clk'. 2. Rearranges the assignment of clock rate for the fout_a/m/epll clocks. This will help in calculating the clock rate of fclk from clk_armclk clock and setup the clock rate for fout_m/epll for subsequent patches which depend on it. 3. Modifies the clock rate calculation of fclk to be based on the newly added clk_armclk clock. Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5p6440/clock.c b/arch/arm/mach-s5p6440/clock.c index 8bd6f15..2c6dd54 100644 --- a/arch/arm/mach-s5p6440/clock.c +++ b/arch/arm/mach-s5p6440/clock.c @@ -247,6 +247,16 @@ static struct clk_ops s5p6440_clkarm_ops = { .round_rate = s5p6440_armclk_round_rate, }; +static struct clksrc_clk clk_armclk = { + .clk = { + .name = "armclk", + .id = 1, + .parent = &clk_mout_apll.clk, + .ops = &s5p6440_clkarm_ops, + }, + .reg_div = { .reg = S5P_CLK_DIV0, .shift = 0, .size = 4 }, +}; + static struct clksrc_clk clk_dout_mpll = { .clk = { .name = "dout_mpll", @@ -569,6 +579,7 @@ static struct clksrc_clk *sysclks[] = { &clk_mout_epll, &clk_mout_mpll, &clk_dout_mpll, + &clk_armclk, }; void __init_or_cpufreq s5p6440_setup_clocks(void) @@ -592,8 +603,6 @@ void __init_or_cpufreq s5p6440_setup_clocks(void) clk_fout_epll.ops = &s5p6440_epll_ops; /* Set S5P6440 functions for arm clock */ - clk_arm.parent = &clk_mout_apll.clk; - clk_arm.ops = &s5p6440_clkarm_ops; clk_48m.enable = s5p6440_clk48m_ctrl; clkdiv0 = __raw_readl(S5P_CLK_DIV0); @@ -610,11 +619,15 @@ void __init_or_cpufreq s5p6440_setup_clocks(void) mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON), pll_4502); apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4502); + clk_fout_mpll.rate = mpll; + clk_fout_epll.rate = epll; + clk_fout_apll.rate = apll; + printk(KERN_INFO "S5P6440: PLL settings, A=%ld.%ldMHz, M=%ld.%ldMHz," \ " E=%ld.%ldMHz\n", print_mhz(apll), print_mhz(mpll), print_mhz(epll)); - fclk = apll / GET_DIV(clkdiv0, S5P_CLKDIV0_ARM); + fclk = clk_get_rate(&clk_armclk.clk); hclk = fclk / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK); pclk = hclk / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK); @@ -633,10 +646,6 @@ void __init_or_cpufreq s5p6440_setup_clocks(void) print_mhz(hclk), print_mhz(hclk_low), print_mhz(pclk), print_mhz(pclk_low)); - clk_fout_mpll.rate = mpll; - clk_fout_epll.rate = epll; - clk_fout_apll.rate = apll; - clk_f.rate = fclk; clk_h.rate = hclk; clk_p.rate = pclk; -- cgit v0.10.2 From 91af70814105f4c05e6e11b51c3269907b71794b Mon Sep 17 00:00:00 2001 From: Michel Lespinasse Date: Wed, 12 May 2010 11:38:45 +0100 Subject: rwsem: Test for no active locks in __rwsem_do_wake undo code If there are no active threasd using a semaphore, it is always correct to unqueue blocked threads. This seems to be what was intended in the undo code. What was done instead, was to look for a sem count of zero - this is an impossible situation, given that at least one thread is known to be queued on the semaphore. The code might be correct as written, but it's hard to reason about and it's not what was intended (otherwise the goto out would have been unconditional). Go for checking the active count - the alternative is not worth the headache. Signed-off-by: Michel Lespinasse Signed-off-by: David Howells Signed-off-by: Linus Torvalds diff --git a/lib/rwsem.c b/lib/rwsem.c index 3e3365e..ceba8e2 100644 --- a/lib/rwsem.c +++ b/lib/rwsem.c @@ -136,9 +136,10 @@ __rwsem_do_wake(struct rw_semaphore *sem, int downgrading) out: return sem; - /* undo the change to count, but check for a transition 1->0 */ + /* undo the change to the active count, but check for a transition + * 1->0 */ undo: - if (rwsem_atomic_update(-RWSEM_ACTIVE_BIAS, sem) != 0) + if (rwsem_atomic_update(-RWSEM_ACTIVE_BIAS, sem) & RWSEM_ACTIVE_MASK) goto out; goto try_again; } -- cgit v0.10.2 From 7ac512aa8237c43331ffaf77a4fd8b8d684819ba Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 12 May 2010 15:34:03 +0100 Subject: CacheFiles: Fix error handling in cachefiles_determine_cache_security() cachefiles_determine_cache_security() is expected to return with a security override in place. However, if set_create_files_as() fails, we fail to do this. In this case, we should just reinstate the security override that was set by the caller. Furthermore, if set_create_files_as() fails, we should dispose of the new credentials we were in the process of creating. Signed-off-by: David Howells Signed-off-by: Linus Torvalds diff --git a/fs/cachefiles/security.c b/fs/cachefiles/security.c index b5808cd..039b501 100644 --- a/fs/cachefiles/security.c +++ b/fs/cachefiles/security.c @@ -77,6 +77,8 @@ static int cachefiles_check_cache_dir(struct cachefiles_cache *cache, /* * check the security details of the on-disk cache * - must be called with security override in force + * - must return with a security override in force - even in the case of an + * error */ int cachefiles_determine_cache_security(struct cachefiles_cache *cache, struct dentry *root, @@ -99,6 +101,8 @@ int cachefiles_determine_cache_security(struct cachefiles_cache *cache, * which create files */ ret = set_create_files_as(new, root->d_inode); if (ret < 0) { + abort_creds(new); + cachefiles_begin_secure(cache, _saved_cred); _leave(" = %d [cfa]", ret); return ret; } -- cgit v0.10.2 From 769d9968e42c995eaaf61ac5583d998f32e0769a Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 12 May 2010 18:39:45 -0700 Subject: Revert "PCI: update bridge resources to get more big ranges in PCI assign unssigned" This reverts commit 977d17bb1749517b353874ccdc9b85abc7a58c2a, because it can cause problems with some devices not getting any resources at all when the resource tree is re-allocated. For an example of this, see https://bugzilla.kernel.org/show_bug.cgi?id=15960 (originally https://bugtrack.alsa-project.org/alsa-bug/view.php?id=4982) (lkml thread: http://lkml.org/lkml/2010/4/19/20) where Peter Henriksson reported his Xonar DX sound card gone, because the IO port region was no longer allocated. Reported-bisected-and-tested-by: Peter Henriksson Requested-by: Andrew Morton Requested-by: Clemens Ladisch Acked-by: Jesse Barnes Cc: Yinghai Lu Signed-off-by: Linus Torvalds diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 4fe36d2..19b1113 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -838,65 +838,11 @@ static void pci_bus_dump_resources(struct pci_bus *bus) } } -static int __init pci_bus_get_depth(struct pci_bus *bus) -{ - int depth = 0; - struct pci_dev *dev; - - list_for_each_entry(dev, &bus->devices, bus_list) { - int ret; - struct pci_bus *b = dev->subordinate; - if (!b) - continue; - - ret = pci_bus_get_depth(b); - if (ret + 1 > depth) - depth = ret + 1; - } - - return depth; -} -static int __init pci_get_max_depth(void) -{ - int depth = 0; - struct pci_bus *bus; - - list_for_each_entry(bus, &pci_root_buses, node) { - int ret; - - ret = pci_bus_get_depth(bus); - if (ret > depth) - depth = ret; - } - - return depth; -} - -/* - * first try will not touch pci bridge res - * second and later try will clear small leaf bridge res - * will stop till to the max deepth if can not find good one - */ void __init pci_assign_unassigned_resources(void) { struct pci_bus *bus; - int tried_times = 0; - enum release_type rel_type = leaf_only; - struct resource_list_x head, *list; - unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | - IORESOURCE_PREFETCH; - unsigned long failed_type; - int max_depth = pci_get_max_depth(); - int pci_try_num; - head.next = NULL; - - pci_try_num = max_depth + 1; - printk(KERN_DEBUG "PCI: max bus depth: %d pci_try_num: %d\n", - max_depth, pci_try_num); - -again: /* Depth first, calculate sizes and alignments of all subordinate buses. */ list_for_each_entry(bus, &pci_root_buses, node) { @@ -904,65 +850,9 @@ again: } /* Depth last, allocate resources and update the hardware. */ list_for_each_entry(bus, &pci_root_buses, node) { - __pci_bus_assign_resources(bus, &head); - } - tried_times++; - - /* any device complain? */ - if (!head.next) - goto enable_and_dump; - failed_type = 0; - for (list = head.next; list;) { - failed_type |= list->flags; - list = list->next; - } - /* - * io port are tight, don't try extra - * or if reach the limit, don't want to try more - */ - failed_type &= type_mask; - if ((failed_type == IORESOURCE_IO) || (tried_times >= pci_try_num)) { - free_failed_list(&head); - goto enable_and_dump; - } - - printk(KERN_DEBUG "PCI: No. %d try to assign unassigned res\n", - tried_times + 1); - - /* third times and later will not check if it is leaf */ - if ((tried_times + 1) > 2) - rel_type = whole_subtree; - - /* - * Try to release leaf bridge's resources that doesn't fit resource of - * child device under that bridge - */ - for (list = head.next; list;) { - bus = list->dev->bus; - pci_bus_release_bridge_resources(bus, list->flags & type_mask, - rel_type); - list = list->next; - } - /* restore size and flags */ - for (list = head.next; list;) { - struct resource *res = list->res; - - res->start = list->start; - res->end = list->end; - res->flags = list->flags; - if (list->dev->subordinate) - res->flags = 0; - - list = list->next; - } - free_failed_list(&head); - - goto again; - -enable_and_dump: - /* Depth last, update the hardware. */ - list_for_each_entry(bus, &pci_root_buses, node) + pci_bus_assign_resources(bus); pci_enable_bridges(bus); + } /* dump the resource on buses */ list_for_each_entry(bus, &pci_root_buses, node) { -- cgit v0.10.2 From e4f44f82691e927a2f5eb582793454e052b920c7 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Thu, 13 May 2010 09:27:09 +0900 Subject: ARM: S5P6440: Remove usage of clk_h and add clk_hclk clock The clk_h clock is of type 'struct clk' whereas on S5P6440, the hclk is more suitable to be of type 'struct clksrc_clk' (since hclk clock is divided version of armclk) This patch modifies the following. 1. Adds the 'clk_hclk' clock which is of type 'struct clksrc_clk'. 2. Removes all references to the clk_h clock. 3. Addes clk_hclk into the list of sysclks. 4. The clock rate 'hclk' is modified to be derived from clk_hclk. Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5p6440/clock.c b/arch/arm/mach-s5p6440/clock.c index 2c6dd54..bc0458e 100644 --- a/arch/arm/mach-s5p6440/clock.c +++ b/arch/arm/mach-s5p6440/clock.c @@ -266,6 +266,15 @@ static struct clksrc_clk clk_dout_mpll = { .reg_div = { .reg = S5P_CLK_DIV0, .shift = 4, .size = 1 }, }; +static struct clksrc_clk clk_hclk = { + .clk = { + .name = "clk_hclk", + .id = -1, + .parent = &clk_armclk.clk, + }, + .reg_div = { .reg = S5P_CLK_DIV0, .shift = 8, .size = 4 }, +}; + int s5p6440_clk48m_ctrl(struct clk *clk, int enable) { unsigned long flags; @@ -321,7 +330,7 @@ static struct clk init_clocks_disable[] = { { .name = "nand", .id = -1, - .parent = &clk_h, + .parent = &clk_hclk.clk, .enable = s5p6440_mem_ctrl, .ctrlbit = S5P_CLKCON_MEM0_HCLK_NFCON, }, { @@ -580,6 +589,7 @@ static struct clksrc_clk *sysclks[] = { &clk_mout_mpll, &clk_dout_mpll, &clk_armclk, + &clk_hclk, }; void __init_or_cpufreq s5p6440_setup_clocks(void) @@ -628,7 +638,7 @@ void __init_or_cpufreq s5p6440_setup_clocks(void) print_mhz(apll), print_mhz(mpll), print_mhz(epll)); fclk = clk_get_rate(&clk_armclk.clk); - hclk = fclk / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK); + hclk = clk_get_rate(&clk_hclk.clk); pclk = hclk / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK); if (__raw_readl(S5P_OTHERS) & S5P_OTHERS_HCLK_LOW_SEL_MPLL) { -- cgit v0.10.2 From 47051461ab1cc8049e676902bf1972268bed4b9a Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Thu, 13 May 2010 09:27:13 +0900 Subject: ARM: S5P6440: Remove usage of clk_p and add clk_pclk clock The clk_p clock is of type 'struct clk' whereas on S5P6440, the pclk is more suitable to be of type 'struct clksrc_clk' (since pclk clock is divided version of hclk). This patch modifies the following. 1. Adds the 'clk_pclk' clock which is of type 'struct clksrc_clk'. 2. Adds clk_pclk into the list of sysclks. 3. The clock rate 'pclk' is modified to be derived from clk_pclk. Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5p6440/clock.c b/arch/arm/mach-s5p6440/clock.c index bc0458e..61bc85b 100644 --- a/arch/arm/mach-s5p6440/clock.c +++ b/arch/arm/mach-s5p6440/clock.c @@ -275,6 +275,15 @@ static struct clksrc_clk clk_hclk = { .reg_div = { .reg = S5P_CLK_DIV0, .shift = 8, .size = 4 }, }; +static struct clksrc_clk clk_pclk = { + .clk = { + .name = "clk_pclk", + .id = -1, + .parent = &clk_hclk.clk, + }, + .reg_div = { .reg = S5P_CLK_DIV0, .shift = 12, .size = 4 }, +}; + int s5p6440_clk48m_ctrl(struct clk *clk, int enable) { unsigned long flags; @@ -590,6 +599,7 @@ static struct clksrc_clk *sysclks[] = { &clk_dout_mpll, &clk_armclk, &clk_hclk, + &clk_pclk, }; void __init_or_cpufreq s5p6440_setup_clocks(void) @@ -639,7 +649,7 @@ void __init_or_cpufreq s5p6440_setup_clocks(void) fclk = clk_get_rate(&clk_armclk.clk); hclk = clk_get_rate(&clk_hclk.clk); - pclk = hclk / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK); + pclk = clk_get_rate(&clk_pclk.clk); if (__raw_readl(S5P_OTHERS) & S5P_OTHERS_HCLK_LOW_SEL_MPLL) { /* Asynchronous mode */ -- cgit v0.10.2 From 93ad94db5509ccac65a57f6fc599d61a61767efc Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Thu, 13 May 2010 09:27:17 +0900 Subject: ARM: S5P6440: Remove usage of clk_h_low and add clk_hclk_low clock The clk_h_low clock is of type 'struct clk' whereas on S5P6440, the hclk_low clock is more suitable to be of type 'struct clksrc_clk' (since hclk_low clock is derived from a choice of clock sources and then divided by a divisor). This patch modifies the following. 1. Removes the definition and usage of clk_h_clk clock. 2. Adds the clk_hclk_low clock of type 'struct clksrc_clk' clock. 3. Adds clk_hclk_low to the list of system clocks. 4. The clock rate of hclk_low is derived from the clk_hclk_low clock. Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5p6440/clock.c b/arch/arm/mach-s5p6440/clock.c index 61bc85b..c70b3a4 100644 --- a/arch/arm/mach-s5p6440/clock.c +++ b/arch/arm/mach-s5p6440/clock.c @@ -134,15 +134,6 @@ static struct clksrc_clk clk_mout_mpll = { .reg_src = { .reg = S5P_CLK_SRC0, .shift = 1, .size = 1 }, }; -static struct clk clk_h_low = { - .name = "hclk_low", - .id = -1, - .rate = 0, - .parent = NULL, - .ctrlbit = 0, - .ops = &clk_ops_def_setrate, -}; - static struct clk clk_p_low = { .name = "pclk_low", .id = -1, @@ -284,6 +275,26 @@ static struct clksrc_clk clk_pclk = { .reg_div = { .reg = S5P_CLK_DIV0, .shift = 12, .size = 4 }, }; +static struct clk *clkset_hclklow_list[] = { + &clk_mout_apll.clk, + &clk_mout_mpll.clk, +}; + +static struct clksrc_sources clkset_hclklow = { + .sources = clkset_hclklow_list, + .nr_sources = ARRAY_SIZE(clkset_hclklow_list), +}; + +static struct clksrc_clk clk_hclk_low = { + .clk = { + .name = "hclk_low", + .id = -1, + }, + .sources = &clkset_hclklow, + .reg_src = { .reg = S5P_SYS_OTHERS, .shift = 6, .size = 1 }, + .reg_div = { .reg = S5P_CLK_DIV3, .shift = 8, .size = 4 }, +}; + int s5p6440_clk48m_ctrl(struct clk *clk, int enable) { unsigned long flags; @@ -405,37 +416,37 @@ static struct clk init_clocks_disable[] = { }, { .name = "otg", .id = -1, - .parent = &clk_h_low, + .parent = &clk_hclk_low.clk, .enable = s5p6440_hclk0_ctrl, .ctrlbit = S5P_CLKCON_HCLK0_USB }, { .name = "post", .id = -1, - .parent = &clk_h_low, + .parent = &clk_hclk_low.clk, .enable = s5p6440_hclk0_ctrl, .ctrlbit = S5P_CLKCON_HCLK0_POST0 }, { .name = "lcd", .id = -1, - .parent = &clk_h_low, + .parent = &clk_hclk_low.clk, .enable = s5p6440_hclk1_ctrl, .ctrlbit = S5P_CLKCON_HCLK1_DISPCON, }, { .name = "hsmmc", .id = 0, - .parent = &clk_h_low, + .parent = &clk_hclk_low.clk, .enable = s5p6440_hclk0_ctrl, .ctrlbit = S5P_CLKCON_HCLK0_HSMMC0, }, { .name = "hsmmc", .id = 1, - .parent = &clk_h_low, + .parent = &clk_hclk_low.clk, .enable = s5p6440_hclk0_ctrl, .ctrlbit = S5P_CLKCON_HCLK0_HSMMC1, }, { .name = "hsmmc", .id = 2, - .parent = &clk_h_low, + .parent = &clk_hclk_low.clk, .enable = s5p6440_hclk0_ctrl, .ctrlbit = S5P_CLKCON_HCLK0_HSMMC2, }, { @@ -600,6 +611,7 @@ static struct clksrc_clk *sysclks[] = { &clk_armclk, &clk_hclk, &clk_pclk, + &clk_hclk_low, }; void __init_or_cpufreq s5p6440_setup_clocks(void) @@ -650,15 +662,7 @@ void __init_or_cpufreq s5p6440_setup_clocks(void) fclk = clk_get_rate(&clk_armclk.clk); hclk = clk_get_rate(&clk_hclk.clk); pclk = clk_get_rate(&clk_pclk.clk); - - if (__raw_readl(S5P_OTHERS) & S5P_OTHERS_HCLK_LOW_SEL_MPLL) { - /* Asynchronous mode */ - hclk_low = mpll / GET_DIV(clkdiv3, S5P_CLKDIV3_HCLK_LOW); - } else { - /* Synchronous mode */ - hclk_low = apll / GET_DIV(clkdiv3, S5P_CLKDIV3_HCLK_LOW); - } - + hclk_low = clk_get_rate(&clk_hclk_low.clk); pclk_low = hclk_low / GET_DIV(clkdiv3, S5P_CLKDIV3_PCLK_LOW); printk(KERN_INFO "S5P6440: HCLK=%ld.%ldMHz, HCLK_LOW=%ld.%ldMHz," \ @@ -669,7 +673,6 @@ void __init_or_cpufreq s5p6440_setup_clocks(void) clk_f.rate = fclk; clk_h.rate = hclk; clk_p.rate = pclk; - clk_h_low.rate = hclk_low; clk_p_low.rate = pclk_low; for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) @@ -681,7 +684,6 @@ static struct clk *clks[] __initdata = { &clk_iis_cd_v40, &clk_pcm_cd, &clk_p_low, - &clk_h_low, }; void __init s5p6440_register_clocks(void) -- cgit v0.10.2 From 697f8a9fe7835ba24f2da855c5de4ddbe27aa554 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Thu, 13 May 2010 09:27:29 +0900 Subject: ARM: S5P6440: Remove usage of clk_p_low and add clk_pclk_low clock The pclk_low clock is of type 'struct clk' whereas on S5P6440, the pclk_low clock is more suitable to be of type 'struct clksrc_clk' (since pclk_low clock is a divided clock of hclk_low clock). This patch modifies the following. 1. Removes the definition and usage of clk_p_clk clock. 2. Adds the clk_pclk_low clock of type 'struct clksrc_clk' clock. 3. Adds clk_pclk_low to the list of system clocks. 4. The clock rate of pclk_low is derived from the clk_pclk_low clock. Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5p6440/clock.c b/arch/arm/mach-s5p6440/clock.c index c70b3a4..80d18f5 100644 --- a/arch/arm/mach-s5p6440/clock.c +++ b/arch/arm/mach-s5p6440/clock.c @@ -134,15 +134,6 @@ static struct clksrc_clk clk_mout_mpll = { .reg_src = { .reg = S5P_CLK_SRC0, .shift = 1, .size = 1 }, }; -static struct clk clk_p_low = { - .name = "pclk_low", - .id = -1, - .rate = 0, - .parent = NULL, - .ctrlbit = 0, - .ops = &clk_ops_def_setrate, -}; - enum perf_level { L0 = 532*1000, L1 = 266*1000, @@ -295,6 +286,15 @@ static struct clksrc_clk clk_hclk_low = { .reg_div = { .reg = S5P_CLK_DIV3, .shift = 8, .size = 4 }, }; +static struct clksrc_clk clk_pclk_low = { + .clk = { + .name = "pclk_low", + .id = -1, + .parent = &clk_hclk_low.clk, + }, + .reg_div = { .reg = S5P_CLK_DIV3, .shift = 12, .size = 4 }, +}; + int s5p6440_clk48m_ctrl(struct clk *clk, int enable) { unsigned long flags; @@ -356,31 +356,31 @@ static struct clk init_clocks_disable[] = { }, { .name = "adc", .id = -1, - .parent = &clk_p_low, + .parent = &clk_pclk_low.clk, .enable = s5p6440_pclk_ctrl, .ctrlbit = S5P_CLKCON_PCLK_TSADC, }, { .name = "i2c", .id = -1, - .parent = &clk_p_low, + .parent = &clk_pclk_low.clk, .enable = s5p6440_pclk_ctrl, .ctrlbit = S5P_CLKCON_PCLK_IIC0, }, { .name = "i2s_v40", .id = 0, - .parent = &clk_p_low, + .parent = &clk_pclk_low.clk, .enable = s5p6440_pclk_ctrl, .ctrlbit = S5P_CLKCON_PCLK_IIS2, }, { .name = "spi", .id = 0, - .parent = &clk_p_low, + .parent = &clk_pclk_low.clk, .enable = s5p6440_pclk_ctrl, .ctrlbit = S5P_CLKCON_PCLK_SPI0, }, { .name = "spi", .id = 1, - .parent = &clk_p_low, + .parent = &clk_pclk_low.clk, .enable = s5p6440_pclk_ctrl, .ctrlbit = S5P_CLKCON_PCLK_SPI1, }, { @@ -452,19 +452,19 @@ static struct clk init_clocks_disable[] = { }, { .name = "rtc", .id = -1, - .parent = &clk_p_low, + .parent = &clk_pclk_low.clk, .enable = s5p6440_pclk_ctrl, .ctrlbit = S5P_CLKCON_PCLK_RTC, }, { .name = "watchdog", .id = -1, - .parent = &clk_p_low, + .parent = &clk_pclk_low.clk, .enable = s5p6440_pclk_ctrl, .ctrlbit = S5P_CLKCON_PCLK_WDT, }, { .name = "timers", .id = -1, - .parent = &clk_p_low, + .parent = &clk_pclk_low.clk, .enable = s5p6440_pclk_ctrl, .ctrlbit = S5P_CLKCON_PCLK_PWM, } @@ -477,31 +477,31 @@ static struct clk init_clocks[] = { { .name = "gpio", .id = -1, - .parent = &clk_p_low, + .parent = &clk_pclk_low.clk, .enable = s5p6440_pclk_ctrl, .ctrlbit = S5P_CLKCON_PCLK_GPIO, }, { .name = "uart", .id = 0, - .parent = &clk_p_low, + .parent = &clk_pclk_low.clk, .enable = s5p6440_pclk_ctrl, .ctrlbit = S5P_CLKCON_PCLK_UART0, }, { .name = "uart", .id = 1, - .parent = &clk_p_low, + .parent = &clk_pclk_low.clk, .enable = s5p6440_pclk_ctrl, .ctrlbit = S5P_CLKCON_PCLK_UART1, }, { .name = "uart", .id = 2, - .parent = &clk_p_low, + .parent = &clk_pclk_low.clk, .enable = s5p6440_pclk_ctrl, .ctrlbit = S5P_CLKCON_PCLK_UART2, }, { .name = "uart", .id = 3, - .parent = &clk_p_low, + .parent = &clk_pclk_low.clk, .enable = s5p6440_pclk_ctrl, .ctrlbit = S5P_CLKCON_PCLK_UART3, } @@ -612,6 +612,7 @@ static struct clksrc_clk *sysclks[] = { &clk_hclk, &clk_pclk, &clk_hclk_low, + &clk_pclk_low, }; void __init_or_cpufreq s5p6440_setup_clocks(void) @@ -627,19 +628,13 @@ void __init_or_cpufreq s5p6440_setup_clocks(void) unsigned long apll; unsigned long mpll; unsigned int ptr; - u32 clkdiv0; - u32 clkdiv3; /* Set S5P6440 functions for clk_fout_epll */ clk_fout_epll.enable = s5p6440_epll_enable; clk_fout_epll.ops = &s5p6440_epll_ops; - /* Set S5P6440 functions for arm clock */ clk_48m.enable = s5p6440_clk48m_ctrl; - clkdiv0 = __raw_readl(S5P_CLK_DIV0); - clkdiv3 = __raw_readl(S5P_CLK_DIV3); - xtal_clk = clk_get(NULL, "ext_xtal"); BUG_ON(IS_ERR(xtal_clk)); @@ -663,7 +658,7 @@ void __init_or_cpufreq s5p6440_setup_clocks(void) hclk = clk_get_rate(&clk_hclk.clk); pclk = clk_get_rate(&clk_pclk.clk); hclk_low = clk_get_rate(&clk_hclk_low.clk); - pclk_low = hclk_low / GET_DIV(clkdiv3, S5P_CLKDIV3_PCLK_LOW); + pclk_low = clk_get_rate(&clk_pclk_low.clk); printk(KERN_INFO "S5P6440: HCLK=%ld.%ldMHz, HCLK_LOW=%ld.%ldMHz," \ " PCLK=%ld.%ldMHz, PCLK_LOW=%ld.%ldMHz\n", @@ -673,7 +668,6 @@ void __init_or_cpufreq s5p6440_setup_clocks(void) clk_f.rate = fclk; clk_h.rate = hclk; clk_p.rate = pclk; - clk_p_low.rate = pclk_low; for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) s3c_set_clksrc(&clksrcs[ptr], true); @@ -683,7 +677,6 @@ static struct clk *clks[] __initdata = { &clk_ext, &clk_iis_cd_v40, &clk_pcm_cd, - &clk_p_low, }; void __init s5p6440_register_clocks(void) -- cgit v0.10.2 From 213907dc1b974019f5eb9c94a1c62b11a515564c Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Thu, 13 May 2010 09:27:47 +0900 Subject: ARM: S5P6440: Add clocks of type 'struct clk'. Add definitions of clocks of type 'struct clk'. Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5p6440/clock.c b/arch/arm/mach-s5p6440/clock.c index 80d18f5..26b02d4 100644 --- a/arch/arm/mach-s5p6440/clock.c +++ b/arch/arm/mach-s5p6440/clock.c @@ -467,7 +467,73 @@ static struct clk init_clocks_disable[] = { .parent = &clk_pclk_low.clk, .enable = s5p6440_pclk_ctrl, .ctrlbit = S5P_CLKCON_PCLK_PWM, - } + }, { + .name = "hclk_fimgvg", + .id = -1, + .parent = &clk_hclk.clk, + .enable = s5p6440_hclk1_ctrl, + .ctrlbit = (1 << 2), + }, { + .name = "tsi", + .id = -1, + .parent = &clk_hclk_low.clk, + .enable = s5p6440_hclk1_ctrl, + .ctrlbit = (1 << 0), + }, { + .name = "pclk_fimgvg", + .id = -1, + .parent = &clk_pclk.clk, + .enable = s5p6440_pclk_ctrl, + .ctrlbit = (1 << 31), + }, { + .name = "dmc0", + .id = -1, + .parent = &clk_pclk.clk, + .enable = s5p6440_pclk_ctrl, + .ctrlbit = (1 << 30), + }, { + .name = "etm", + .id = -1, + .parent = &clk_pclk.clk, + .enable = s5p6440_pclk_ctrl, + .ctrlbit = (1 << 29), + }, { + .name = "dsim", + .id = -1, + .parent = &clk_pclk_low.clk, + .enable = s5p6440_pclk_ctrl, + .ctrlbit = (1 << 28), + }, { + .name = "gps", + .id = -1, + .parent = &clk_pclk_low.clk, + .enable = s5p6440_pclk_ctrl, + .ctrlbit = (1 << 25), + }, { + .name = "pcm", + .id = -1, + .parent = &clk_pclk_low.clk, + .enable = s5p6440_pclk_ctrl, + .ctrlbit = (1 << 8), + }, { + .name = "irom", + .id = -1, + .parent = &clk_hclk.clk, + .enable = s5p6440_hclk0_ctrl, + .ctrlbit = (1 << 25), + }, { + .name = "dma", + .id = -1, + .parent = &clk_hclk_low.clk, + .enable = s5p6440_hclk0_ctrl, + .ctrlbit = (1 << 12), + }, { + .name = "2d", + .id = -1, + .parent = &clk_hclk.clk, + .enable = s5p6440_hclk0_ctrl, + .ctrlbit = (1 << 8), + }, }; /* @@ -504,7 +570,19 @@ static struct clk init_clocks[] = { .parent = &clk_pclk_low.clk, .enable = s5p6440_pclk_ctrl, .ctrlbit = S5P_CLKCON_PCLK_UART3, - } + }, { + .name = "mem", + .id = -1, + .parent = &clk_hclk.clk, + .enable = s5p6440_hclk0_ctrl, + .ctrlbit = (1 << 21), + }, { + .name = "intc", + .id = -1, + .parent = &clk_hclk.clk, + .enable = s5p6440_hclk0_ctrl, + .ctrlbit = (1 << 1), + }, }; static struct clk clk_iis_cd_v40 = { -- cgit v0.10.2 From 39b7781b16614c65a53f275ff63440ea806230e2 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Thu, 13 May 2010 09:27:49 +0900 Subject: ARM: S5P6440: Rename clkset_mmc_spi to clkset_group1 The clock source options avaialable in the clkset_mmc_spi are applicable to clocks such as sclk_post, sclk_dispcon and sclk_fimgvg. So this set is renamed as clkset_group1 to indicate that it can be used as clock sources for other clocks and not just for sclk_spi and sclk_mmc clocks. Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5p6440/clock.c b/arch/arm/mach-s5p6440/clock.c index 26b02d4..b47f77d 100644 --- a/arch/arm/mach-s5p6440/clock.c +++ b/arch/arm/mach-s5p6440/clock.c @@ -595,15 +595,15 @@ static struct clk clk_pcm_cd = { .id = -1, }; -static struct clk *clkset_spi_mmc_list[] = { +static struct clk *clkset_group1_list[] = { &clk_mout_epll.clk, &clk_dout_mpll.clk, &clk_fin_epll, }; -static struct clksrc_sources clkset_spi_mmc = { - .sources = clkset_spi_mmc_list, - .nr_sources = ARRAY_SIZE(clkset_spi_mmc_list), +static struct clksrc_sources clkset_group1 = { + .sources = clkset_group1_list, + .nr_sources = ARRAY_SIZE(clkset_group1_list), }; static struct clk *clkset_uart_list[] = { @@ -624,7 +624,7 @@ static struct clksrc_clk clksrcs[] = { .ctrlbit = S5P_CLKCON_SCLK0_MMC0, .enable = s5p6440_sclk_ctrl, }, - .sources = &clkset_spi_mmc, + .sources = &clkset_group1, .reg_src = { .reg = S5P_CLK_SRC0, .shift = 18, .size = 2 }, .reg_div = { .reg = S5P_CLK_DIV1, .shift = 0, .size = 4 }, }, { @@ -634,7 +634,7 @@ static struct clksrc_clk clksrcs[] = { .ctrlbit = S5P_CLKCON_SCLK0_MMC1, .enable = s5p6440_sclk_ctrl, }, - .sources = &clkset_spi_mmc, + .sources = &clkset_group1, .reg_src = { .reg = S5P_CLK_SRC0, .shift = 20, .size = 2 }, .reg_div = { .reg = S5P_CLK_DIV1, .shift = 4, .size = 4 }, }, { @@ -644,7 +644,7 @@ static struct clksrc_clk clksrcs[] = { .ctrlbit = S5P_CLKCON_SCLK0_MMC2, .enable = s5p6440_sclk_ctrl, }, - .sources = &clkset_spi_mmc, + .sources = &clkset_group1, .reg_src = { .reg = S5P_CLK_SRC0, .shift = 22, .size = 2 }, .reg_div = { .reg = S5P_CLK_DIV1, .shift = 8, .size = 4 }, }, { @@ -664,7 +664,7 @@ static struct clksrc_clk clksrcs[] = { .ctrlbit = S5P_CLKCON_SCLK0_SPI0, .enable = s5p6440_sclk_ctrl, }, - .sources = &clkset_spi_mmc, + .sources = &clkset_group1, .reg_src = { .reg = S5P_CLK_SRC0, .shift = 14, .size = 2 }, .reg_div = { .reg = S5P_CLK_DIV2, .shift = 0, .size = 4 }, }, { @@ -674,7 +674,7 @@ static struct clksrc_clk clksrcs[] = { .ctrlbit = S5P_CLKCON_SCLK0_SPI1, .enable = s5p6440_sclk_ctrl, }, - .sources = &clkset_spi_mmc, + .sources = &clkset_group1, .reg_src = { .reg = S5P_CLK_SRC0, .shift = 16, .size = 2 }, .reg_div = { .reg = S5P_CLK_DIV2, .shift = 4, .size = 4 }, } -- cgit v0.10.2 From b3b84d652da3aba06ec26c0570ca138d8c7f1b65 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Thu, 13 May 2010 09:27:54 +0900 Subject: ARM: S5P6440: Add clocks of type 'struct clksrc_clk'. This patch adds the following. 1. Add new definitions of clock of type 'struct clksrc_clk'. 2. Add gate control function for GATE_SCLK1 which is required for new clock additions. Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5p6440/clock.c b/arch/arm/mach-s5p6440/clock.c index b47f77d..ca6e48d 100644 --- a/arch/arm/mach-s5p6440/clock.c +++ b/arch/arm/mach-s5p6440/clock.c @@ -336,6 +336,11 @@ static int s5p6440_sclk_ctrl(struct clk *clk, int enable) return s5p_gatectrl(S5P_CLK_GATE_SCLK0, clk, enable); } +static int s5p6440_sclk1_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P_CLK_GATE_SCLK1, clk, enable); +} + static int s5p6440_mem_ctrl(struct clk *clk, int enable) { return s5p_gatectrl(S5P_CLK_GATE_MEM0, clk, enable); @@ -616,6 +621,19 @@ static struct clksrc_sources clkset_uart = { .nr_sources = ARRAY_SIZE(clkset_uart_list), }; +static struct clk *clkset_audio_list[] = { + &clk_mout_epll.clk, + &clk_dout_mpll.clk, + &clk_fin_epll, + &clk_iis_cd_v40, + &clk_pcm_cd, +}; + +static struct clksrc_sources clkset_audio = { + .sources = clkset_audio_list, + .nr_sources = ARRAY_SIZE(clkset_audio_list), +}; + static struct clksrc_clk clksrcs[] = { { .clk = { @@ -677,7 +695,47 @@ static struct clksrc_clk clksrcs[] = { .sources = &clkset_group1, .reg_src = { .reg = S5P_CLK_SRC0, .shift = 16, .size = 2 }, .reg_div = { .reg = S5P_CLK_DIV2, .shift = 4, .size = 4 }, - } + }, { + .clk = { + .name = "sclk_post", + .id = -1, + .ctrlbit = (1 << 10), + .enable = s5p6440_sclk_ctrl, + }, + .sources = &clkset_group1, + .reg_src = { .reg = S5P_CLK_SRC0, .shift = 26, .size = 2 }, + .reg_div = { .reg = S5P_CLK_DIV1, .shift = 12, .size = 4 }, + }, { + .clk = { + .name = "sclk_dispcon", + .id = -1, + .ctrlbit = (1 << 1), + .enable = s5p6440_sclk1_ctrl, + }, + .sources = &clkset_group1, + .reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 2 }, + .reg_div = { .reg = S5P_CLK_DIV3, .shift = 0, .size = 4 }, + }, { + .clk = { + .name = "sclk_fimgvg", + .id = -1, + .ctrlbit = (1 << 2), + .enable = s5p6440_sclk1_ctrl, + }, + .sources = &clkset_group1, + .reg_src = { .reg = S5P_CLK_SRC1, .shift = 8, .size = 2 }, + .reg_div = { .reg = S5P_CLK_DIV3, .shift = 4, .size = 4 }, + }, { + .clk = { + .name = "sclk_audio2", + .id = -1, + .ctrlbit = (1 << 11), + .enable = s5p6440_sclk_ctrl, + }, + .sources = &clkset_audio, + .reg_src = { .reg = S5P_CLK_SRC1, .shift = 0, .size = 3 }, + .reg_div = { .reg = S5P_CLK_DIV2, .shift = 24, .size = 4 }, + }, }; /* Clock initialisation code */ -- cgit v0.10.2 From 46a47b1ed118cda1a08b7f6077b837a00fbc112b Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Fri, 23 Apr 2010 14:03:38 -0300 Subject: KVM: convert ioapic lock to spinlock kvm_set_irq is used from non sleepable contexes, so convert ioapic from mutex to spinlock. KVM-Stable-Tag. Tested-by: Ralf Bonenkamp Signed-off-by: Marcelo Tosatti diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c index 03a5eb2..7c79c1d 100644 --- a/virt/kvm/ioapic.c +++ b/virt/kvm/ioapic.c @@ -197,7 +197,7 @@ int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level) union kvm_ioapic_redirect_entry entry; int ret = 1; - mutex_lock(&ioapic->lock); + spin_lock(&ioapic->lock); if (irq >= 0 && irq < IOAPIC_NUM_PINS) { entry = ioapic->redirtbl[irq]; level ^= entry.fields.polarity; @@ -214,7 +214,7 @@ int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level) } trace_kvm_ioapic_set_irq(entry.bits, irq, ret == 0); } - mutex_unlock(&ioapic->lock); + spin_unlock(&ioapic->lock); return ret; } @@ -238,9 +238,9 @@ static void __kvm_ioapic_update_eoi(struct kvm_ioapic *ioapic, int vector, * is dropped it will be put into irr and will be delivered * after ack notifier returns. */ - mutex_unlock(&ioapic->lock); + spin_unlock(&ioapic->lock); kvm_notify_acked_irq(ioapic->kvm, KVM_IRQCHIP_IOAPIC, i); - mutex_lock(&ioapic->lock); + spin_lock(&ioapic->lock); if (trigger_mode != IOAPIC_LEVEL_TRIG) continue; @@ -259,9 +259,9 @@ void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode) smp_rmb(); if (!test_bit(vector, ioapic->handled_vectors)) return; - mutex_lock(&ioapic->lock); + spin_lock(&ioapic->lock); __kvm_ioapic_update_eoi(ioapic, vector, trigger_mode); - mutex_unlock(&ioapic->lock); + spin_unlock(&ioapic->lock); } static inline struct kvm_ioapic *to_ioapic(struct kvm_io_device *dev) @@ -287,7 +287,7 @@ static int ioapic_mmio_read(struct kvm_io_device *this, gpa_t addr, int len, ASSERT(!(addr & 0xf)); /* check alignment */ addr &= 0xff; - mutex_lock(&ioapic->lock); + spin_lock(&ioapic->lock); switch (addr) { case IOAPIC_REG_SELECT: result = ioapic->ioregsel; @@ -301,7 +301,7 @@ static int ioapic_mmio_read(struct kvm_io_device *this, gpa_t addr, int len, result = 0; break; } - mutex_unlock(&ioapic->lock); + spin_unlock(&ioapic->lock); switch (len) { case 8: @@ -338,7 +338,7 @@ static int ioapic_mmio_write(struct kvm_io_device *this, gpa_t addr, int len, } addr &= 0xff; - mutex_lock(&ioapic->lock); + spin_lock(&ioapic->lock); switch (addr) { case IOAPIC_REG_SELECT: ioapic->ioregsel = data; @@ -356,7 +356,7 @@ static int ioapic_mmio_write(struct kvm_io_device *this, gpa_t addr, int len, default: break; } - mutex_unlock(&ioapic->lock); + spin_unlock(&ioapic->lock); return 0; } @@ -386,7 +386,7 @@ int kvm_ioapic_init(struct kvm *kvm) ioapic = kzalloc(sizeof(struct kvm_ioapic), GFP_KERNEL); if (!ioapic) return -ENOMEM; - mutex_init(&ioapic->lock); + spin_lock_init(&ioapic->lock); kvm->arch.vioapic = ioapic; kvm_ioapic_reset(ioapic); kvm_iodevice_init(&ioapic->dev, &ioapic_mmio_ops); @@ -419,9 +419,9 @@ int kvm_get_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state) if (!ioapic) return -EINVAL; - mutex_lock(&ioapic->lock); + spin_lock(&ioapic->lock); memcpy(state, ioapic, sizeof(struct kvm_ioapic_state)); - mutex_unlock(&ioapic->lock); + spin_unlock(&ioapic->lock); return 0; } @@ -431,9 +431,9 @@ int kvm_set_ioapic(struct kvm *kvm, struct kvm_ioapic_state *state) if (!ioapic) return -EINVAL; - mutex_lock(&ioapic->lock); + spin_lock(&ioapic->lock); memcpy(ioapic, state, sizeof(struct kvm_ioapic_state)); update_handled_vectors(ioapic); - mutex_unlock(&ioapic->lock); + spin_unlock(&ioapic->lock); return 0; } diff --git a/virt/kvm/ioapic.h b/virt/kvm/ioapic.h index 8a751b7..0b190c3 100644 --- a/virt/kvm/ioapic.h +++ b/virt/kvm/ioapic.h @@ -45,7 +45,7 @@ struct kvm_ioapic { struct kvm_io_device dev; struct kvm *kvm; void (*ack_notifier)(void *opaque, int irq); - struct mutex lock; + spinlock_t lock; DECLARE_BITMAP(handled_vectors, 256); }; -- cgit v0.10.2 From 061e2fd16863009c8005b4b5fdfb75c7215c0b99 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 5 May 2010 16:04:43 +0200 Subject: KVM: SVM: Fix wrong intercept masks on 32 bit This patch makes KVM on 32 bit SVM working again by correcting the masks used for iret interception. With the wrong masks the upper 32 bits of the intercepts are masked out which leaves vmrun unintercepted. This is not legal on svm and the vmrun fails. Bug was introduced by commits 95ba827313 and 3cfc3092. Cc: Jan Kiszka Cc: Gleb Natapov Cc: stable@kernel.org Signed-off-by: Joerg Roedel Signed-off-by: Avi Kivity diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 2ba5820..737361f 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -2067,7 +2067,7 @@ static int cpuid_interception(struct vcpu_svm *svm) static int iret_interception(struct vcpu_svm *svm) { ++svm->vcpu.stat.nmi_window_exits; - svm->vmcb->control.intercept &= ~(1UL << INTERCEPT_IRET); + svm->vmcb->control.intercept &= ~(1ULL << INTERCEPT_IRET); svm->vcpu.arch.hflags |= HF_IRET_MASK; return 1; } @@ -2479,7 +2479,7 @@ static void svm_inject_nmi(struct kvm_vcpu *vcpu) svm->vmcb->control.event_inj = SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_NMI; vcpu->arch.hflags |= HF_NMI_MASK; - svm->vmcb->control.intercept |= (1UL << INTERCEPT_IRET); + svm->vmcb->control.intercept |= (1ULL << INTERCEPT_IRET); ++vcpu->stat.nmi_injections; } @@ -2539,10 +2539,10 @@ static void svm_set_nmi_mask(struct kvm_vcpu *vcpu, bool masked) if (masked) { svm->vcpu.arch.hflags |= HF_NMI_MASK; - svm->vmcb->control.intercept |= (1UL << INTERCEPT_IRET); + svm->vmcb->control.intercept |= (1ULL << INTERCEPT_IRET); } else { svm->vcpu.arch.hflags &= ~HF_NMI_MASK; - svm->vmcb->control.intercept &= ~(1UL << INTERCEPT_IRET); + svm->vmcb->control.intercept &= ~(1ULL << INTERCEPT_IRET); } } -- cgit v0.10.2 From fe19c5a46b4c519153fddd4d5efe32a3e4cfa694 Mon Sep 17 00:00:00 2001 From: Dongxiao Xu Date: Tue, 11 May 2010 18:21:33 +0800 Subject: KVM: x86: Call vcpu_load and vcpu_put in cpuid_update cpuid_update may operate VMCS, so vcpu_load() and vcpu_put() should be called to ensure correctness. Signed-off-by: Dongxiao Xu Signed-off-by: Marcelo Tosatti diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 3c4ca98..c4f35b5 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1712,6 +1712,7 @@ static int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu, if (copy_from_user(cpuid_entries, entries, cpuid->nent * sizeof(struct kvm_cpuid_entry))) goto out_free; + vcpu_load(vcpu); for (i = 0; i < cpuid->nent; i++) { vcpu->arch.cpuid_entries[i].function = cpuid_entries[i].function; vcpu->arch.cpuid_entries[i].eax = cpuid_entries[i].eax; @@ -1729,6 +1730,7 @@ static int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu, r = 0; kvm_apic_set_version(vcpu); kvm_x86_ops->cpuid_update(vcpu); + vcpu_put(vcpu); out_free: vfree(cpuid_entries); @@ -1749,9 +1751,11 @@ static int kvm_vcpu_ioctl_set_cpuid2(struct kvm_vcpu *vcpu, if (copy_from_user(&vcpu->arch.cpuid_entries, entries, cpuid->nent * sizeof(struct kvm_cpuid_entry2))) goto out; + vcpu_load(vcpu); vcpu->arch.cpuid_nent = cpuid->nent; kvm_apic_set_version(vcpu); kvm_x86_ops->cpuid_update(vcpu); + vcpu_put(vcpu); return 0; out: -- cgit v0.10.2 From f8c5fae16649445e15656667f72bd51d777f7766 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 11 May 2010 15:16:46 +0200 Subject: KVM: VMX: blocked-by-sti must not defer NMI injections As the processor may not consider GUEST_INTR_STATE_STI as a reason for blocking NMI, it could return immediately with EXIT_REASON_NMI_WINDOW when we asked for it. But as we consider this state as NMI-blocking, we can run into an endless loop. Resolve this by allowing NMI injection if just GUEST_INTR_STATE_STI is active (originally suggested by Gleb). Intel confirmed that this is safe, the processor will never complain about NMI injection in this state. Signed-off-by: Jan Kiszka KVM-Stable-Tag Acked-by: Gleb Natapov Signed-off-by: Marcelo Tosatti diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index bc933cf..2f8db0e 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -2703,8 +2703,7 @@ static int vmx_nmi_allowed(struct kvm_vcpu *vcpu) return 0; return !(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & - (GUEST_INTR_STATE_STI | GUEST_INTR_STATE_MOV_SS | - GUEST_INTR_STATE_NMI)); + (GUEST_INTR_STATE_MOV_SS | GUEST_INTR_STATE_NMI)); } static bool vmx_get_nmi_mask(struct kvm_vcpu *vcpu) -- cgit v0.10.2 From 4f018c513a81ba243165bfc4fcf44254986ad002 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Sun, 9 May 2010 17:26:47 +0200 Subject: KVM: PPC: Keep index within boundaries in kvmppc_44x_emul_tlbwe() An index of KVM44x_GUEST_TLB_SIZE is already one too large. Signed-off-by: Roel Kluin Acked-by: Hollis Blanchard Acked-by: Alexander Graf Signed-off-by: Marcelo Tosatti diff --git a/arch/powerpc/kvm/44x_tlb.c b/arch/powerpc/kvm/44x_tlb.c index 2570fcc..8123125 100644 --- a/arch/powerpc/kvm/44x_tlb.c +++ b/arch/powerpc/kvm/44x_tlb.c @@ -440,7 +440,7 @@ int kvmppc_44x_emul_tlbwe(struct kvm_vcpu *vcpu, u8 ra, u8 rs, u8 ws) unsigned int gtlb_index; gtlb_index = kvmppc_get_gpr(vcpu, ra); - if (gtlb_index > KVM44x_GUEST_TLB_SIZE) { + if (gtlb_index >= KVM44x_GUEST_TLB_SIZE) { printk("%s: index %d\n", __func__, gtlb_index); kvmppc_dump_vcpu(vcpu); return EMULATE_FAIL; -- cgit v0.10.2 From 46db2c3205ca6e24adbb9b038441bc8f65360535 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 30 Mar 2010 18:27:39 -0300 Subject: perf record: Add a fallback to the reference relocation symbol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Usually "_text" is enough, but I received reports that its not always available, so fallback to "_stext" for the symbol we use to check if we need to apply any relocation to all the symbols in the kernel symtab, for when, for instance, kexec is being used. Reported-by: Darren Hart Reported-by: Steven Rostedt Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Ingo Molnar diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 3b8b638..f1411e9 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -563,6 +563,9 @@ static int __cmd_record(int argc, const char **argv) err = event__synthesize_kernel_mmap(process_synthesized_event, session, "_text"); + if (err < 0) + err = event__synthesize_kernel_mmap(process_synthesized_event, + session, "_stext"); if (err < 0) { pr_err("Couldn't record kernel reference relocation symbol.\n"); return err; -- cgit v0.10.2 From 720019908fd5a1bb442bb0a35a6027ba21864d25 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Wed, 12 May 2010 21:42:42 +0400 Subject: x86, perf: P4 PMU -- use hash for p4_get_escr_idx() Linear search over all p4 MSRs should be fine if only we would not use it in events scheduling routine which is pretty time critical. Lets use hashes. It should speed scheduling up significantly. v2: Steven proposed to use more gentle approach than issue BUG on error, so we use WARN_ONCE now Signed-off-by: Cyrill Gorcunov Cc: Peter Zijlstra Cc: Steven Rostedt Cc: Frederic Weisbecker Cc: Lin Ming LKML-Reference: <20100512174242.GA5190@lenovo> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index a603930..cb875b1 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c @@ -668,66 +668,80 @@ static void p4_pmu_swap_config_ts(struct hw_perf_event *hwc, int cpu) } } -/* ESCRs are not sequential in memory so we need a map */ -static const unsigned int p4_escr_map[ARCH_P4_TOTAL_ESCR] = { - MSR_P4_ALF_ESCR0, /* 0 */ - MSR_P4_ALF_ESCR1, /* 1 */ - MSR_P4_BPU_ESCR0, /* 2 */ - MSR_P4_BPU_ESCR1, /* 3 */ - MSR_P4_BSU_ESCR0, /* 4 */ - MSR_P4_BSU_ESCR1, /* 5 */ - MSR_P4_CRU_ESCR0, /* 6 */ - MSR_P4_CRU_ESCR1, /* 7 */ - MSR_P4_CRU_ESCR2, /* 8 */ - MSR_P4_CRU_ESCR3, /* 9 */ - MSR_P4_CRU_ESCR4, /* 10 */ - MSR_P4_CRU_ESCR5, /* 11 */ - MSR_P4_DAC_ESCR0, /* 12 */ - MSR_P4_DAC_ESCR1, /* 13 */ - MSR_P4_FIRM_ESCR0, /* 14 */ - MSR_P4_FIRM_ESCR1, /* 15 */ - MSR_P4_FLAME_ESCR0, /* 16 */ - MSR_P4_FLAME_ESCR1, /* 17 */ - MSR_P4_FSB_ESCR0, /* 18 */ - MSR_P4_FSB_ESCR1, /* 19 */ - MSR_P4_IQ_ESCR0, /* 20 */ - MSR_P4_IQ_ESCR1, /* 21 */ - MSR_P4_IS_ESCR0, /* 22 */ - MSR_P4_IS_ESCR1, /* 23 */ - MSR_P4_ITLB_ESCR0, /* 24 */ - MSR_P4_ITLB_ESCR1, /* 25 */ - MSR_P4_IX_ESCR0, /* 26 */ - MSR_P4_IX_ESCR1, /* 27 */ - MSR_P4_MOB_ESCR0, /* 28 */ - MSR_P4_MOB_ESCR1, /* 29 */ - MSR_P4_MS_ESCR0, /* 30 */ - MSR_P4_MS_ESCR1, /* 31 */ - MSR_P4_PMH_ESCR0, /* 32 */ - MSR_P4_PMH_ESCR1, /* 33 */ - MSR_P4_RAT_ESCR0, /* 34 */ - MSR_P4_RAT_ESCR1, /* 35 */ - MSR_P4_SAAT_ESCR0, /* 36 */ - MSR_P4_SAAT_ESCR1, /* 37 */ - MSR_P4_SSU_ESCR0, /* 38 */ - MSR_P4_SSU_ESCR1, /* 39 */ - MSR_P4_TBPU_ESCR0, /* 40 */ - MSR_P4_TBPU_ESCR1, /* 41 */ - MSR_P4_TC_ESCR0, /* 42 */ - MSR_P4_TC_ESCR1, /* 43 */ - MSR_P4_U2L_ESCR0, /* 44 */ - MSR_P4_U2L_ESCR1, /* 45 */ +/* + * ESCR address hashing is tricky, ESCRs are not sequential + * in memory but all starts from MSR_P4_BSU_ESCR0 (0x03e0) and + * the metric between any ESCRs is laid in range [0xa0,0xe1] + * + * so we make ~70% filled hashtable + */ + +#define P4_ESCR_MSR_BASE 0x000003a0 +#define P4_ESCR_MSR_MAX 0x000003e1 +#define P4_ESCR_MSR_TABLE_SIZE (P4_ESCR_MSR_MAX - P4_ESCR_MSR_BASE + 1) +#define P4_ESCR_MSR_IDX(msr) (msr - P4_ESCR_MSR_BASE) +#define P4_ESCR_MSR_TABLE_ENTRY(msr) [P4_ESCR_MSR_IDX(msr)] = msr + +static const unsigned int p4_escr_table[P4_ESCR_MSR_TABLE_SIZE] = { + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_ALF_ESCR0), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_ALF_ESCR1), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_BPU_ESCR0), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_BPU_ESCR1), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_BSU_ESCR0), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_BSU_ESCR1), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_CRU_ESCR0), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_CRU_ESCR1), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_CRU_ESCR2), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_CRU_ESCR3), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_CRU_ESCR4), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_CRU_ESCR5), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_DAC_ESCR0), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_DAC_ESCR1), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_FIRM_ESCR0), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_FIRM_ESCR1), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_FLAME_ESCR0), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_FLAME_ESCR1), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_FSB_ESCR0), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_FSB_ESCR1), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_IQ_ESCR0), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_IQ_ESCR1), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_IS_ESCR0), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_IS_ESCR1), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_ITLB_ESCR0), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_ITLB_ESCR1), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_IX_ESCR0), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_IX_ESCR1), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_MOB_ESCR0), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_MOB_ESCR1), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_MS_ESCR0), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_MS_ESCR1), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_PMH_ESCR0), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_PMH_ESCR1), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_RAT_ESCR0), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_RAT_ESCR1), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_SAAT_ESCR0), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_SAAT_ESCR1), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_SSU_ESCR0), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_SSU_ESCR1), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_TBPU_ESCR0), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_TBPU_ESCR1), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_TC_ESCR0), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_TC_ESCR1), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_U2L_ESCR0), + P4_ESCR_MSR_TABLE_ENTRY(MSR_P4_U2L_ESCR1), }; static int p4_get_escr_idx(unsigned int addr) { - unsigned int i; + unsigned int idx = P4_ESCR_MSR_IDX(addr); - for (i = 0; i < ARRAY_SIZE(p4_escr_map); i++) { - if (addr == p4_escr_map[i]) - return i; + if (unlikely(idx >= P4_ESCR_MSR_TABLE_SIZE || + !p4_escr_table[idx])) { + WARN_ONCE(1, "P4 PMU: Wrong address passed: %x\n", addr); + return -1; } - return -1; + return idx; } static int p4_next_cntr(int thread, unsigned long *used_mask, @@ -747,7 +761,7 @@ static int p4_next_cntr(int thread, unsigned long *used_mask, static int p4_pmu_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign) { unsigned long used_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; - unsigned long escr_mask[BITS_TO_LONGS(ARCH_P4_TOTAL_ESCR)]; + unsigned long escr_mask[BITS_TO_LONGS(P4_ESCR_MSR_TABLE_SIZE)]; int cpu = raw_smp_processor_id(); struct hw_perf_event *hwc; struct p4_event_bind *bind; @@ -755,7 +769,7 @@ static int p4_pmu_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign int cntr_idx, escr_idx; bitmap_zero(used_mask, X86_PMC_IDX_MAX); - bitmap_zero(escr_mask, ARCH_P4_TOTAL_ESCR); + bitmap_zero(escr_mask, P4_ESCR_MSR_TABLE_SIZE); for (i = 0, num = n; i < n; i++, num--) { @@ -763,6 +777,8 @@ static int p4_pmu_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign thread = p4_ht_thread(cpu); bind = p4_config_get_bind(hwc->config); escr_idx = p4_get_escr_idx(bind->escr_msr[thread]); + if (unlikely(escr_idx == -1)) + goto done; if (hwc->idx != -1 && !p4_should_swap_ts(hwc->config, cpu)) { cntr_idx = hwc->idx; -- cgit v0.10.2 From 0d5961b7f612f8f54fd6fbe1942cdfb141cddfb9 Mon Sep 17 00:00:00 2001 From: "Steven J. Magnani" Date: Tue, 27 Apr 2010 13:00:23 -0500 Subject: microblaze: re-enable interrupts before calling schedule schedule() should not be called with interrupts disabled. Signed-off-by: Steven J. Magnani Signed-off-by: Michal Simek diff --git a/arch/microblaze/kernel/entry-nommu.S b/arch/microblaze/kernel/entry-nommu.S index 391d619..8cc18cd 100644 --- a/arch/microblaze/kernel/entry-nommu.S +++ b/arch/microblaze/kernel/entry-nommu.S @@ -476,6 +476,8 @@ ENTRY(ret_from_fork) nop work_pending: + enable_irq + andi r11, r19, _TIF_NEED_RESCHED beqi r11, 1f bralid r15, schedule -- cgit v0.10.2 From 538722ca3b762023ac65cec214901a1ebff8b575 Mon Sep 17 00:00:00 2001 From: "Steven J. Magnani" Date: Thu, 6 May 2010 16:38:33 -0500 Subject: microblaze: fix get_user/put_user side-effects The Microblaze implementations of get_user() and (MMU) put_user() evaluate the address argument more than once. This causes unexpected side-effects for invocations that include increment operators, i.e. get_user(foo, bar++). This patch also removes the distinction between MMU and noMMU put_user(). Without the patch: $ echo 1234567890 > /proc/sys/kernel/core_pattern $ cat /proc/sys/kernel/core_pattern 12345 Signed-off-by: Steven J. Magnani diff --git a/arch/microblaze/include/asm/uaccess.h b/arch/microblaze/include/asm/uaccess.h index 446bec2..26460d1 100644 --- a/arch/microblaze/include/asm/uaccess.h +++ b/arch/microblaze/include/asm/uaccess.h @@ -182,6 +182,39 @@ extern long __user_bad(void); * Returns zero on success, or -EFAULT on error. * On error, the variable @x is set to zero. */ +#define get_user(x, ptr) \ + __get_user_check((x), (ptr), sizeof(*(ptr))) + +#define __get_user_check(x, ptr, size) \ +({ \ + unsigned long __gu_val = 0; \ + const typeof(*(ptr)) __user *__gu_addr = (ptr); \ + int __gu_err = 0; \ + \ + if (access_ok(VERIFY_READ, __gu_addr, size)) { \ + switch (size) { \ + case 1: \ + __get_user_asm("lbu", __gu_addr, __gu_val, \ + __gu_err); \ + break; \ + case 2: \ + __get_user_asm("lhu", __gu_addr, __gu_val, \ + __gu_err); \ + break; \ + case 4: \ + __get_user_asm("lw", __gu_addr, __gu_val, \ + __gu_err); \ + break; \ + default: \ + __gu_err = __user_bad(); \ + break; \ + } \ + } else { \ + __gu_err = -EFAULT; \ + } \ + x = (typeof(*(ptr)))__gu_val; \ + __gu_err; \ +}) #define __get_user(x, ptr) \ ({ \ @@ -206,12 +239,6 @@ extern long __user_bad(void); }) -#define get_user(x, ptr) \ -({ \ - access_ok(VERIFY_READ, (ptr), sizeof(*(ptr))) \ - ? __get_user((x), (ptr)) : -EFAULT; \ -}) - #define __put_user_asm(insn, __gu_ptr, __gu_val, __gu_err) \ ({ \ __asm__ __volatile__ ( \ @@ -266,6 +293,42 @@ extern long __user_bad(void); * * Returns zero on success, or -EFAULT on error. */ +#define put_user(x, ptr) \ + __put_user_check((x), (ptr), sizeof(*(ptr))) + +#define __put_user_check(x, ptr, size) \ +({ \ + typeof(*(ptr)) __pu_val; \ + typeof(*(ptr)) __user *__pu_addr = (ptr); \ + int __pu_err = 0; \ + \ + __pu_val = (x); \ + if (access_ok(VERIFY_WRITE, __pu_addr, size)) { \ + switch (size) { \ + case 1: \ + __put_user_asm("sb", __pu_addr, __pu_val, \ + __pu_err); \ + break; \ + case 2: \ + __put_user_asm("sh", __pu_addr, __pu_val, \ + __pu_err); \ + break; \ + case 4: \ + __put_user_asm("sw", __pu_addr, __pu_val, \ + __pu_err); \ + break; \ + case 8: \ + __put_user_asm_8(__pu_addr, __pu_val, __pu_err);\ + break; \ + default: \ + __pu_err = __user_bad(); \ + break; \ + } \ + } else { \ + __pu_err = -EFAULT; \ + } \ + __pu_err; \ +}) #define __put_user(x, ptr) \ ({ \ @@ -290,18 +353,6 @@ extern long __user_bad(void); __gu_err; \ }) -#ifndef CONFIG_MMU - -#define put_user(x, ptr) __put_user((x), (ptr)) - -#else /* CONFIG_MMU */ - -#define put_user(x, ptr) \ -({ \ - access_ok(VERIFY_WRITE, (ptr), sizeof(*(ptr))) \ - ? __put_user((x), (ptr)) : -EFAULT; \ -}) -#endif /* CONFIG_MMU */ /* copy_to_from_user */ #define __copy_from_user(to, from, n) \ -- cgit v0.10.2 From 504e8beed161bd11a2c6cbb8aaf352c14d39b5bb Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 13 May 2010 00:41:15 -0700 Subject: Input: elantech - use all 3 bytes when checking version Apparently all 3 bytes returned by ETP_FW_VERSION_QUERY are significant and should be taken into account when matching hardware version/features. Tested-by: Eric Piel Signed-off-by: Dmitry Torokhov diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 2cbf3fc..1ac12f7 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -184,7 +184,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) int fingers; static int old_fingers; - if (etd->fw_version_maj == 0x01) { + if (etd->fw_version < 0x020000) { /* * byte 0: D U p1 p2 1 p3 R L * byte 1: f 0 th tw x9 x8 y9 y8 @@ -226,7 +226,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) input_report_key(dev, BTN_LEFT, packet[0] & 0x01); input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); - if ((etd->fw_version_maj == 0x01) && + if (etd->fw_version < 0x020000 && (etd->capabilities & ETP_CAP_HAS_ROCKER)) { /* rocker up */ input_report_key(dev, BTN_FORWARD, packet[0] & 0x40); @@ -320,7 +320,7 @@ static int elantech_check_parity_v1(struct psmouse *psmouse) unsigned char p1, p2, p3; /* Parity bits are placed differently */ - if (etd->fw_version_maj == 0x01) { + if (etd->fw_version < 0x020000) { /* byte 0: D U p1 p2 1 p3 R L */ p1 = (packet[0] & 0x20) >> 5; p2 = (packet[0] & 0x10) >> 4; @@ -456,7 +456,7 @@ static void elantech_set_input_params(struct psmouse *psmouse) switch (etd->hw_version) { case 1: /* Rocker button */ - if ((etd->fw_version_maj == 0x01) && + if (etd->fw_version < 0x020000 && (etd->capabilities & ETP_CAP_HAS_ROCKER)) { __set_bit(BTN_FORWARD, dev->keybit); __set_bit(BTN_BACK, dev->keybit); @@ -685,15 +685,14 @@ int elantech_init(struct psmouse *psmouse) pr_err("elantech.c: failed to query firmware version.\n"); goto init_fail; } - etd->fw_version_maj = param[0]; - etd->fw_version_min = param[2]; + + etd->fw_version = (param[0] << 16) | (param[1] << 8) | param[2]; /* * Assume every version greater than this is new EeePC style * hardware with 6 byte packets */ - if ((etd->fw_version_maj == 0x02 && etd->fw_version_min >= 0x30) || - etd->fw_version_maj > 0x02) { + if (etd->fw_version >= 0x020030) { etd->hw_version = 2; /* For now show extra debug information */ etd->debug = 1; @@ -703,8 +702,9 @@ int elantech_init(struct psmouse *psmouse) etd->hw_version = 1; etd->paritycheck = 1; } - pr_info("elantech.c: assuming hardware version %d, firmware version %d.%d\n", - etd->hw_version, etd->fw_version_maj, etd->fw_version_min); + + pr_info("elantech.c: assuming hardware version %d, firmware version %d.%d.%d\n", + etd->hw_version, param[0], param[1], param[2]); if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY, param)) { pr_err("elantech.c: failed to query capabilities.\n"); @@ -719,8 +719,8 @@ int elantech_init(struct psmouse *psmouse) * a touch action starts causing the mouse cursor or scrolled page * to jump. Enable a workaround. */ - if (etd->fw_version_maj == 0x02 && etd->fw_version_min == 0x22) { - pr_info("elantech.c: firmware version 2.34 detected, " + if (etd->fw_version == 0x020022) { + pr_info("elantech.c: firmware version 2.0.34 detected, " "enabling jumpy cursor workaround\n"); etd->jumpy_cursor = 1; } diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h index feac5f7..ac57bde 100644 --- a/drivers/input/mouse/elantech.h +++ b/drivers/input/mouse/elantech.h @@ -100,11 +100,10 @@ struct elantech_data { unsigned char reg_26; unsigned char debug; unsigned char capabilities; - unsigned char fw_version_maj; - unsigned char fw_version_min; - unsigned char hw_version; unsigned char paritycheck; unsigned char jumpy_cursor; + unsigned char hw_version; + unsigned int fw_version; unsigned char parity[256]; }; -- cgit v0.10.2 From ef110b24e28f36620f63dab94708a17c7e267358 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 13 May 2010 00:42:23 -0700 Subject: Input: psmouse - reset all types of mice before reconnecting Synaptics hardware requires resetting device after suspend to ram in order for the device to be operational. The reset lives in synaptics-specific reconnect handler, but it is not being invoked if synaptics support is disabled and the device is handled as a standard PS/2 device (bare or IntelliMouse protocol). Let's add reset into generic reconnect handler as well. Signed-off-by: Dmitry Torokhov diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index cbc8072..a3c9731 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -1394,6 +1394,7 @@ static int psmouse_reconnect(struct serio *serio) struct psmouse *psmouse = serio_get_drvdata(serio); struct psmouse *parent = NULL; struct serio_driver *drv = serio->drv; + unsigned char type; int rc = -1; if (!drv || !psmouse) { @@ -1413,10 +1414,15 @@ static int psmouse_reconnect(struct serio *serio) if (psmouse->reconnect) { if (psmouse->reconnect(psmouse)) goto out; - } else if (psmouse_probe(psmouse) < 0 || - psmouse->type != psmouse_extensions(psmouse, - psmouse_max_proto, false)) { - goto out; + } else { + psmouse_reset(psmouse); + + if (psmouse_probe(psmouse) < 0) + goto out; + + type = psmouse_extensions(psmouse, psmouse_max_proto, false); + if (psmouse->type != type) + goto out; } /* ok, the device type (and capabilities) match the old one, -- cgit v0.10.2 From 3843384a055496dfed3c93ae883d964d8290fdab Mon Sep 17 00:00:00 2001 From: Oskar Schirmer Date: Thu, 13 May 2010 00:42:23 -0700 Subject: Input: ad7877 - keep dma rx buffers in seperate cache lines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With dma based spi transmission, data corruption is observed occasionally. With dma buffers located right next to msg and xfer fields, cache lines correctly flushed in preparation for dma usage may be polluted again when writing to fields in the same cache line. Make sure cache fields used with dma do not share cache lines with fields changed during dma handling. As both fields are part of a struct that is allocated via kzalloc, thus cache aligned, moving the fields to the 1st position and insert padding for alignment does the job. Signed-off-by: Oskar Schirmer Signed-off-by: Daniel Glöckner Signed-off-by: Oliver Schneidewind Signed-off-by: Johannes Weiner Acked-by: Mike Frysinger [dtor@mail.ru - changed to use ___cacheline_aligned as suggested by akpm] Signed-off-by: Dmitry Torokhov diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c index e019d53..0d2d7e5 100644 --- a/drivers/input/touchscreen/ad7877.c +++ b/drivers/input/touchscreen/ad7877.c @@ -156,9 +156,14 @@ struct ser_req { u16 reset; u16 ref_on; u16 command; - u16 sample; struct spi_message msg; struct spi_transfer xfer[6]; + + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + u16 sample ____cacheline_aligned; }; struct ad7877 { @@ -182,8 +187,6 @@ struct ad7877 { u8 averaging; u8 pen_down_acc_interval; - u16 conversion_data[AD7877_NR_SENSE]; - struct spi_transfer xfer[AD7877_NR_SENSE + 2]; struct spi_message msg; @@ -195,6 +198,12 @@ struct ad7877 { spinlock_t lock; struct timer_list timer; /* P: lock */ unsigned pending:1; /* P: lock */ + + /* + * DMA (thus cache coherency maintenance) requires the + * transfer buffers to live in their own cache lines. + */ + u16 conversion_data[AD7877_NR_SENSE] ____cacheline_aligned; }; static int gpio3; -- cgit v0.10.2 From e8b96918a45732551b33764b0b526beac3866d58 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 04:59:43 +0000 Subject: sh: sh7343 mstp32 index rework This patch adds sh7343 MSTP enums for mstp_clks[] index. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c index a066c43..72acbe4 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c @@ -145,51 +145,61 @@ struct clk div6_clks[DIV6_NR] = { #define MSTP(_str, _parent, _reg, _bit, _flags) \ SH_CLK_MSTP32(_str, -1, _parent, _reg, _bit, _flags) -static struct clk mstp_clks[] = { - MSTP("tlb0", &div4_clks[DIV4_I], MSTPCR0, 31, CLK_ENABLE_ON_INIT), - MSTP("ic0", &div4_clks[DIV4_I], MSTPCR0, 30, CLK_ENABLE_ON_INIT), - MSTP("oc0", &div4_clks[DIV4_I], MSTPCR0, 29, CLK_ENABLE_ON_INIT), - MSTP("uram0", &div4_clks[DIV4_U], MSTPCR0, 28, CLK_ENABLE_ON_INIT), - MSTP("xymem0", &div4_clks[DIV4_B], MSTPCR0, 26, CLK_ENABLE_ON_INIT), - MSTP("intc3", &div4_clks[DIV4_P], MSTPCR0, 23, 0), - MSTP("intc0", &div4_clks[DIV4_P], MSTPCR0, 22, 0), - MSTP("dmac0", &div4_clks[DIV4_P], MSTPCR0, 21, 0), - MSTP("sh0", &div4_clks[DIV4_P], MSTPCR0, 20, 0), - MSTP("hudi0", &div4_clks[DIV4_P], MSTPCR0, 19, 0), - MSTP("ubc0", &div4_clks[DIV4_P], MSTPCR0, 17, 0), - MSTP("tmu_fck", &div4_clks[DIV4_P], MSTPCR0, 15, 0), - MSTP("cmt_fck", &r_clk, MSTPCR0, 14, 0), - MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0), - MSTP("mfi0", &div4_clks[DIV4_P], MSTPCR0, 11, 0), - MSTP("flctl0", &div4_clks[DIV4_P], MSTPCR0, 10, 0), - SH_CLK_MSTP32("sci_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 7, 0), - SH_CLK_MSTP32("sci_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 6, 0), - SH_CLK_MSTP32("sci_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 5, 0), - SH_CLK_MSTP32("sci_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 4, 0), - MSTP("sio0", &div4_clks[DIV4_P], MSTPCR0, 3, 0), - MSTP("siof0", &div4_clks[DIV4_P], MSTPCR0, 2, 0), - MSTP("siof1", &div4_clks[DIV4_P], MSTPCR0, 1, 0), - - MSTP("i2c0", &div4_clks[DIV4_P], MSTPCR1, 9, 0), - MSTP("i2c1", &div4_clks[DIV4_P], MSTPCR1, 8, 0), - - MSTP("tpu0", &div4_clks[DIV4_P], MSTPCR2, 25, 0), - MSTP("irda0", &div4_clks[DIV4_P], MSTPCR2, 24, 0), - MSTP("sdhi0", &div4_clks[DIV4_P], MSTPCR2, 18, 0), - MSTP("mmcif0", &div4_clks[DIV4_P], MSTPCR2, 17, 0), - MSTP("sim0", &div4_clks[DIV4_P], MSTPCR2, 16, 0), - MSTP("keysc0", &r_clk, MSTPCR2, 14, 0), - MSTP("tsif0", &div4_clks[DIV4_P], MSTPCR2, 13, 0), - MSTP("s3d40", &div4_clks[DIV4_P], MSTPCR2, 12, 0), - MSTP("usbf0", &div4_clks[DIV4_P], MSTPCR2, 11, 0), - MSTP("siu0", &div4_clks[DIV4_B], MSTPCR2, 8, 0), - MSTP("jpu0", &div4_clks[DIV4_B], MSTPCR2, 6, CLK_ENABLE_ON_INIT), - MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0), - MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0), - MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0), - MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, CLK_ENABLE_ON_INIT), - MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, CLK_ENABLE_ON_INIT), - MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0), +enum { MSTP031, MSTP030, MSTP029, MSTP028, MSTP026, + MSTP023, MSTP022, MSTP021, MSTP020, MSTP019, MSTP018, MSTP017, MSTP016, + MSTP015, MSTP014, MSTP013, MSTP012, MSTP011, MSTP010, + MSTP007, MSTP006, MSTP005, MSTP004, MSTP003, MSTP002, MSTP001, + MSTP109, MSTP108, MSTP100, + MSTP225, MSTP224, MSTP218, MSTP217, MSTP216, + MSTP214, MSTP213, MSTP212, MSTP211, MSTP208, + MSTP206, MSTP205, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200, + MSTP_NR }; + +static struct clk mstp_clks[MSTP_NR] = { + [MSTP031] = MSTP("tlb0", &div4_clks[DIV4_I], MSTPCR0, 31, CLK_ENABLE_ON_INIT), + [MSTP030] = MSTP("ic0", &div4_clks[DIV4_I], MSTPCR0, 30, CLK_ENABLE_ON_INIT), + [MSTP029] = MSTP("oc0", &div4_clks[DIV4_I], MSTPCR0, 29, CLK_ENABLE_ON_INIT), + [MSTP028] = MSTP("uram0", &div4_clks[DIV4_U], MSTPCR0, 28, CLK_ENABLE_ON_INIT), + [MSTP026] = MSTP("xymem0", &div4_clks[DIV4_B], MSTPCR0, 26, CLK_ENABLE_ON_INIT), + [MSTP023] = MSTP("intc3", &div4_clks[DIV4_P], MSTPCR0, 23, 0), + [MSTP022] = MSTP("intc0", &div4_clks[DIV4_P], MSTPCR0, 22, 0), + [MSTP021] = MSTP("dmac0", &div4_clks[DIV4_P], MSTPCR0, 21, 0), + [MSTP020] = MSTP("sh0", &div4_clks[DIV4_P], MSTPCR0, 20, 0), + [MSTP019] = MSTP("hudi0", &div4_clks[DIV4_P], MSTPCR0, 19, 0), + [MSTP017] = MSTP("ubc0", &div4_clks[DIV4_P], MSTPCR0, 17, 0), + [MSTP015] = MSTP("tmu_fck", &div4_clks[DIV4_P], MSTPCR0, 15, 0), + [MSTP014] = MSTP("cmt_fck", &r_clk, MSTPCR0, 14, 0), + [MSTP013] = MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0), + [MSTP011] = MSTP("mfi0", &div4_clks[DIV4_P], MSTPCR0, 11, 0), + [MSTP010] = MSTP("flctl0", &div4_clks[DIV4_P], MSTPCR0, 10, 0), + [MSTP007] = SH_CLK_MSTP32("sci_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 7, 0), + [MSTP006] = SH_CLK_MSTP32("sci_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 6, 0), + [MSTP005] = SH_CLK_MSTP32("sci_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 5, 0), + [MSTP004] = SH_CLK_MSTP32("sci_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 4, 0), + [MSTP003] = MSTP("sio0", &div4_clks[DIV4_P], MSTPCR0, 3, 0), + [MSTP002] = MSTP("siof0", &div4_clks[DIV4_P], MSTPCR0, 2, 0), + [MSTP001] = MSTP("siof1", &div4_clks[DIV4_P], MSTPCR0, 1, 0), + + [MSTP109] = MSTP("i2c0", &div4_clks[DIV4_P], MSTPCR1, 9, 0), + [MSTP108] = MSTP("i2c1", &div4_clks[DIV4_P], MSTPCR1, 8, 0), + + [MSTP225] = MSTP("tpu0", &div4_clks[DIV4_P], MSTPCR2, 25, 0), + [MSTP224] = MSTP("irda0", &div4_clks[DIV4_P], MSTPCR2, 24, 0), + [MSTP218] = MSTP("sdhi0", &div4_clks[DIV4_P], MSTPCR2, 18, 0), + [MSTP217] = MSTP("mmcif0", &div4_clks[DIV4_P], MSTPCR2, 17, 0), + [MSTP216] = MSTP("sim0", &div4_clks[DIV4_P], MSTPCR2, 16, 0), + [MSTP214] = MSTP("keysc0", &r_clk, MSTPCR2, 14, 0), + [MSTP213] = MSTP("tsif0", &div4_clks[DIV4_P], MSTPCR2, 13, 0), + [MSTP212] = MSTP("s3d40", &div4_clks[DIV4_P], MSTPCR2, 12, 0), + [MSTP211] = MSTP("usbf0", &div4_clks[DIV4_P], MSTPCR2, 11, 0), + [MSTP208] = MSTP("siu0", &div4_clks[DIV4_B], MSTPCR2, 8, 0), + [MSTP206] = MSTP("jpu0", &div4_clks[DIV4_B], MSTPCR2, 6, CLK_ENABLE_ON_INIT), + [MSTP205] = MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0), + [MSTP204] = MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0), + [MSTP203] = MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0), + [MSTP202] = MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, CLK_ENABLE_ON_INIT), + [MSTP201] = MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, CLK_ENABLE_ON_INIT), + [MSTP200] = MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0), }; #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } @@ -221,7 +231,7 @@ int __init arch_clk_init(void) ret = sh_clk_div6_register(div6_clks, DIV6_NR); if (!ret) - ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks)); + ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); return ret; } -- cgit v0.10.2 From 25637f7ae0324c636bde172d9e92bc00d4f0121d Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 04:59:50 +0000 Subject: sh: sh7343 mstp32 clkdev lookup Add sh7343 MSTP clocks to the clkdev lookup table. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c index 72acbe4..f661d46 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c @@ -207,6 +207,68 @@ static struct clk mstp_clks[MSTP_NR] = { static struct clk_lookup lookups[] = { /* DIV6 clocks */ CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]), + + /* MSTP32 clocks */ + CLKDEV_CON_ID("tlb0", &mstp_clks[MSTP031]), + CLKDEV_CON_ID("ic0", &mstp_clks[MSTP030]), + CLKDEV_CON_ID("oc0", &mstp_clks[MSTP029]), + CLKDEV_CON_ID("uram0", &mstp_clks[MSTP028]), + CLKDEV_CON_ID("xymem0", &mstp_clks[MSTP026]), + CLKDEV_CON_ID("intc3", &mstp_clks[MSTP023]), + CLKDEV_CON_ID("intc0", &mstp_clks[MSTP022]), + + CLKDEV_CON_ID("dmac0", &mstp_clks[MSTP021]), + CLKDEV_CON_ID("sh0", &mstp_clks[MSTP020]), + CLKDEV_CON_ID("hudi0", &mstp_clks[MSTP019]), + CLKDEV_CON_ID("ubc0", &mstp_clks[MSTP017]), + CLKDEV_CON_ID("tmu_fck", &mstp_clks[MSTP015]), + CLKDEV_CON_ID("cmt_fck", &mstp_clks[MSTP014]), + CLKDEV_CON_ID("rwdt0", &mstp_clks[MSTP013]), + CLKDEV_CON_ID("mfi0", &mstp_clks[MSTP011]), + CLKDEV_CON_ID("flctl0", &mstp_clks[MSTP010]), + { + /* SCIF0 */ + .dev_id = "sh-sci.0", + .con_id = "sci_fck", + .clk = &mstp_clks[MSTP007], + }, { + /* SCIF1 */ + .dev_id = "sh-sci.1", + .con_id = "sci_fck", + .clk = &mstp_clks[MSTP006], + }, { + /* SCIF2 */ + .dev_id = "sh-sci.2", + .con_id = "sci_fck", + .clk = &mstp_clks[MSTP005], + }, { + /* SCIF3 */ + .dev_id = "sh-sci.3", + .con_id = "sci_fck", + .clk = &mstp_clks[MSTP004], + }, + CLKDEV_CON_ID("sio0", &mstp_clks[MSTP003]), + CLKDEV_CON_ID("siof0", &mstp_clks[MSTP002]), + CLKDEV_CON_ID("siof1", &mstp_clks[MSTP001]), + CLKDEV_CON_ID("i2c0", &mstp_clks[MSTP109]), + CLKDEV_CON_ID("i2c1", &mstp_clks[MSTP108]), + CLKDEV_CON_ID("tpu0", &mstp_clks[MSTP225]), + CLKDEV_CON_ID("irda0", &mstp_clks[MSTP224]), + CLKDEV_CON_ID("sdhi0", &mstp_clks[MSTP218]), + CLKDEV_CON_ID("mmcif0", &mstp_clks[MSTP217]), + CLKDEV_CON_ID("sim0", &mstp_clks[MSTP216]), + CLKDEV_CON_ID("keysc0", &mstp_clks[MSTP214]), + CLKDEV_CON_ID("tsif0", &mstp_clks[MSTP213]), + CLKDEV_CON_ID("s3d40", &mstp_clks[MSTP212]), + CLKDEV_CON_ID("usbf0", &mstp_clks[MSTP211]), + CLKDEV_CON_ID("siu0", &mstp_clks[MSTP208]), + CLKDEV_CON_ID("jpu0", &mstp_clks[MSTP206]), + CLKDEV_CON_ID("vou0", &mstp_clks[MSTP205]), + CLKDEV_CON_ID("beu0", &mstp_clks[MSTP204]), + CLKDEV_CON_ID("ceu0", &mstp_clks[MSTP203]), + CLKDEV_CON_ID("veu0", &mstp_clks[MSTP202]), + CLKDEV_CON_ID("vpu0", &mstp_clks[MSTP201]), + CLKDEV_CON_ID("lcdc0", &mstp_clks[MSTP200]), }; int __init arch_clk_init(void) -- cgit v0.10.2 From 4780683a135abbe17f7867d295cd542cde5678b6 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 04:59:58 +0000 Subject: sh: sh7366 mstp32 index rework This patch adds sh7366 MSTP enums for mstp_clks[] index. The MSTP bit for the SIU is removed as well since it is not included in the documentation. Most likely an old copy paste error from sh7722. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c index 44cc5a0..8b9cd31 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c @@ -148,48 +148,56 @@ struct clk div6_clks[DIV6_NR] = { #define MSTP(_str, _parent, _reg, _bit, _flags) \ SH_CLK_MSTP32(_str, -1, _parent, _reg, _bit, _flags) -static struct clk mstp_clks[] = { +enum { MSTP031, MSTP030, MSTP029, MSTP028, MSTP026, + MSTP023, MSTP022, MSTP021, MSTP020, MSTP019, MSTP018, MSTP017, MSTP016, + MSTP015, MSTP014, MSTP013, MSTP012, MSTP011, MSTP010, + MSTP007, MSTP006, MSTP005, MSTP002, MSTP001, + MSTP109, MSTP100, + MSTP227, MSTP226, MSTP224, MSTP223, MSTP222, MSTP218, MSTP217, + MSTP211, MSTP207, MSTP205, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200, + MSTP_NR }; + +static struct clk mstp_clks[MSTP_NR] = { /* See page 52 of Datasheet V0.40: Overview -> Block Diagram */ - MSTP("tlb0", &div4_clks[DIV4_I], MSTPCR0, 31, CLK_ENABLE_ON_INIT), - MSTP("ic0", &div4_clks[DIV4_I], MSTPCR0, 30, CLK_ENABLE_ON_INIT), - MSTP("oc0", &div4_clks[DIV4_I], MSTPCR0, 29, CLK_ENABLE_ON_INIT), - MSTP("rsmem0", &div4_clks[DIV4_SH], MSTPCR0, 28, CLK_ENABLE_ON_INIT), - MSTP("xymem0", &div4_clks[DIV4_B], MSTPCR0, 26, CLK_ENABLE_ON_INIT), - MSTP("intc3", &div4_clks[DIV4_P], MSTPCR0, 23, 0), - MSTP("intc0", &div4_clks[DIV4_P], MSTPCR0, 22, 0), - MSTP("dmac0", &div4_clks[DIV4_P], MSTPCR0, 21, 0), - MSTP("sh0", &div4_clks[DIV4_P], MSTPCR0, 20, 0), - MSTP("hudi0", &div4_clks[DIV4_P], MSTPCR0, 19, 0), - MSTP("ubc0", &div4_clks[DIV4_P], MSTPCR0, 17, 0), - MSTP("tmu_fck", &div4_clks[DIV4_P], MSTPCR0, 15, 0), - MSTP("cmt_fck", &r_clk, MSTPCR0, 14, 0), - MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0), - MSTP("mfi0", &div4_clks[DIV4_P], MSTPCR0, 11, 0), - MSTP("flctl0", &div4_clks[DIV4_P], MSTPCR0, 10, 0), - SH_CLK_MSTP32("sci_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 7, 0), - SH_CLK_MSTP32("sci_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 6, 0), - SH_CLK_MSTP32("sci_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 5, 0), - MSTP("msiof0", &div4_clks[DIV4_P], MSTPCR0, 2, 0), - MSTP("sbr0", &div4_clks[DIV4_P], MSTPCR0, 1, 0), - - MSTP("i2c0", &div4_clks[DIV4_P], MSTPCR1, 9, 0), - - MSTP("icb0", &div4_clks[DIV4_P], MSTPCR2, 27, 0), - MSTP("meram0", &div4_clks[DIV4_P], MSTPCR2, 26, 0), - MSTP("dacy1", &div4_clks[DIV4_P], MSTPCR2, 24, 0), - MSTP("dacy0", &div4_clks[DIV4_P], MSTPCR2, 23, 0), - MSTP("tsif0", &div4_clks[DIV4_P], MSTPCR2, 22, 0), - MSTP("sdhi0", &div4_clks[DIV4_P], MSTPCR2, 18, 0), - MSTP("mmcif0", &div4_clks[DIV4_P], MSTPCR2, 17, 0), - MSTP("usbf0", &div4_clks[DIV4_P], MSTPCR2, 11, 0), - MSTP("siu0", &div4_clks[DIV4_B], MSTPCR2, 9, 0), - MSTP("veu1", &div4_clks[DIV4_B], MSTPCR2, 7, CLK_ENABLE_ON_INIT), - MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0), - MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0), - MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0), - MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, CLK_ENABLE_ON_INIT), - MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, CLK_ENABLE_ON_INIT), - MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0), + [MSTP031] = MSTP("tlb0", &div4_clks[DIV4_I], MSTPCR0, 31, CLK_ENABLE_ON_INIT), + [MSTP030] = MSTP("ic0", &div4_clks[DIV4_I], MSTPCR0, 30, CLK_ENABLE_ON_INIT), + [MSTP029] = MSTP("oc0", &div4_clks[DIV4_I], MSTPCR0, 29, CLK_ENABLE_ON_INIT), + [MSTP028] = MSTP("rsmem0", &div4_clks[DIV4_SH], MSTPCR0, 28, CLK_ENABLE_ON_INIT), + [MSTP026] = MSTP("xymem0", &div4_clks[DIV4_B], MSTPCR0, 26, CLK_ENABLE_ON_INIT), + [MSTP023] = MSTP("intc3", &div4_clks[DIV4_P], MSTPCR0, 23, 0), + [MSTP022] = MSTP("intc0", &div4_clks[DIV4_P], MSTPCR0, 22, 0), + [MSTP021] = MSTP("dmac0", &div4_clks[DIV4_P], MSTPCR0, 21, 0), + [MSTP020] = MSTP("sh0", &div4_clks[DIV4_P], MSTPCR0, 20, 0), + [MSTP019] = MSTP("hudi0", &div4_clks[DIV4_P], MSTPCR0, 19, 0), + [MSTP017] = MSTP("ubc0", &div4_clks[DIV4_P], MSTPCR0, 17, 0), + [MSTP015] = MSTP("tmu_fck", &div4_clks[DIV4_P], MSTPCR0, 15, 0), + [MSTP014] = MSTP("cmt_fck", &r_clk, MSTPCR0, 14, 0), + [MSTP013] = MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0), + [MSTP011] = MSTP("mfi0", &div4_clks[DIV4_P], MSTPCR0, 11, 0), + [MSTP010] = MSTP("flctl0", &div4_clks[DIV4_P], MSTPCR0, 10, 0), + [MSTP007] = SH_CLK_MSTP32("sci_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 7, 0), + [MSTP006] = SH_CLK_MSTP32("sci_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 6, 0), + [MSTP005] = SH_CLK_MSTP32("sci_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 5, 0), + [MSTP002] = MSTP("msiof0", &div4_clks[DIV4_P], MSTPCR0, 2, 0), + [MSTP001] = MSTP("sbr0", &div4_clks[DIV4_P], MSTPCR0, 1, 0), + + [MSTP109] = MSTP("i2c0", &div4_clks[DIV4_P], MSTPCR1, 9, 0), + + [MSTP227] = MSTP("icb0", &div4_clks[DIV4_P], MSTPCR2, 27, 0), + [MSTP226] = MSTP("meram0", &div4_clks[DIV4_P], MSTPCR2, 26, 0), + [MSTP224] = MSTP("dacy1", &div4_clks[DIV4_P], MSTPCR2, 24, 0), + [MSTP223] = MSTP("dacy0", &div4_clks[DIV4_P], MSTPCR2, 23, 0), + [MSTP222] = MSTP("tsif0", &div4_clks[DIV4_P], MSTPCR2, 22, 0), + [MSTP218] = MSTP("sdhi0", &div4_clks[DIV4_P], MSTPCR2, 18, 0), + [MSTP217] = MSTP("mmcif0", &div4_clks[DIV4_P], MSTPCR2, 17, 0), + [MSTP211] = MSTP("usbf0", &div4_clks[DIV4_P], MSTPCR2, 11, 0), + [MSTP207] = MSTP("veu1", &div4_clks[DIV4_B], MSTPCR2, 7, CLK_ENABLE_ON_INIT), + [MSTP205] = MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0), + [MSTP204] = MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0), + [MSTP203] = MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0), + [MSTP202] = MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, CLK_ENABLE_ON_INIT), + [MSTP201] = MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, CLK_ENABLE_ON_INIT), + [MSTP200] = MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0), }; #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } @@ -221,7 +229,7 @@ int __init arch_clk_init(void) ret = sh_clk_div6_register(div6_clks, DIV6_NR); if (!ret) - ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks)); + ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); return ret; } -- cgit v0.10.2 From b87cecef4ce4250c9bc44af04e60d71000d44581 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 05:00:06 +0000 Subject: sh: sh7366 mstp32 clkdev lookup Add sh7366 MSTP clocks to the clkdev lookup table. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c index 8b9cd31..5649bfc 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c @@ -205,6 +205,58 @@ static struct clk mstp_clks[MSTP_NR] = { static struct clk_lookup lookups[] = { /* DIV6 clocks */ CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]), + + /* MSTP32 clocks */ + CLKDEV_CON_ID("tlb0", &mstp_clks[MSTP031]), + CLKDEV_CON_ID("ic0", &mstp_clks[MSTP030]), + CLKDEV_CON_ID("oc0", &mstp_clks[MSTP029]), + CLKDEV_CON_ID("rsmem0", &mstp_clks[MSTP028]), + CLKDEV_CON_ID("xymem0", &mstp_clks[MSTP026]), + CLKDEV_CON_ID("intc3", &mstp_clks[MSTP023]), + CLKDEV_CON_ID("intc0", &mstp_clks[MSTP022]), + CLKDEV_CON_ID("dmac0", &mstp_clks[MSTP021]), + CLKDEV_CON_ID("sh0", &mstp_clks[MSTP020]), + CLKDEV_CON_ID("hudi0", &mstp_clks[MSTP019]), + CLKDEV_CON_ID("ubc0", &mstp_clks[MSTP017]), + CLKDEV_CON_ID("tmu_fck", &mstp_clks[MSTP015]), + CLKDEV_CON_ID("cmt_fck", &mstp_clks[MSTP014]), + CLKDEV_CON_ID("rwdt0", &mstp_clks[MSTP013]), + CLKDEV_CON_ID("mfi0", &mstp_clks[MSTP011]), + CLKDEV_CON_ID("flctl0", &mstp_clks[MSTP010]), + { + /* SCIF0 */ + .dev_id = "sh-sci.0", + .con_id = "sci_fck", + .clk = &mstp_clks[MSTP007], + }, { + /* SCIF1 */ + .dev_id = "sh-sci.1", + .con_id = "sci_fck", + .clk = &mstp_clks[MSTP006], + }, { + /* SCIF2 */ + .dev_id = "sh-sci.2", + .con_id = "sci_fck", + .clk = &mstp_clks[MSTP005], + }, + CLKDEV_CON_ID("msiof0", &mstp_clks[MSTP002]), + CLKDEV_CON_ID("sbr0", &mstp_clks[MSTP001]), + CLKDEV_CON_ID("i2c0", &mstp_clks[MSTP109]), + CLKDEV_CON_ID("icb0", &mstp_clks[MSTP227]), + CLKDEV_CON_ID("meram0", &mstp_clks[MSTP226]), + CLKDEV_CON_ID("dacy1", &mstp_clks[MSTP224]), + CLKDEV_CON_ID("dacy0", &mstp_clks[MSTP223]), + CLKDEV_CON_ID("tsif0", &mstp_clks[MSTP222]), + CLKDEV_CON_ID("sdhi0", &mstp_clks[MSTP218]), + CLKDEV_CON_ID("mmcif0", &mstp_clks[MSTP217]), + CLKDEV_CON_ID("usbf0", &mstp_clks[MSTP211]), + CLKDEV_CON_ID("veu1", &mstp_clks[MSTP207]), + CLKDEV_CON_ID("vou0", &mstp_clks[MSTP205]), + CLKDEV_CON_ID("beu0", &mstp_clks[MSTP204]), + CLKDEV_CON_ID("ceu0", &mstp_clks[MSTP203]), + CLKDEV_CON_ID("veu0", &mstp_clks[MSTP202]), + CLKDEV_CON_ID("vpu0", &mstp_clks[MSTP201]), + CLKDEV_CON_ID("lcdc0", &mstp_clks[MSTP200]), }; int __init arch_clk_init(void) -- cgit v0.10.2 From 5b10a27e9f0aa7282e3b8fd470e71201d6f5764c Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 05:00:14 +0000 Subject: sh: sh7785 mstp32 index rework This patch adds sh7785 MSTP enums for mstp_clks[] index. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c index 28de049..cc34ec3 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c @@ -87,31 +87,37 @@ struct clk div4_clks[DIV4_NR] = { #define MSTPCR0 0xffc80030 #define MSTPCR1 0xffc80034 -static struct clk mstp_clks[] = { +enum { MSTP029, MSTP028, MSTP027, MSTP026, MSTP025, MSTP024, + MSTP021, MSTP020, MSTP017, MSTP016, + MSTP013, MSTP012, MSTP009, MSTP008, MSTP003, MSTP002, + MSTP119, MSTP117, MSTP105, MSTP104, MSTP100, + MSTP_NR }; + +static struct clk mstp_clks[MSTP_NR] = { /* MSTPCR0 */ - SH_CLK_MSTP32("sci_fck", 5, &div4_clks[DIV4_P], MSTPCR0, 29, 0), - SH_CLK_MSTP32("sci_fck", 4, &div4_clks[DIV4_P], MSTPCR0, 28, 0), - SH_CLK_MSTP32("sci_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 27, 0), - SH_CLK_MSTP32("sci_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 26, 0), - SH_CLK_MSTP32("sci_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 25, 0), - SH_CLK_MSTP32("sci_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 24, 0), - SH_CLK_MSTP32("ssi_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 21, 0), - SH_CLK_MSTP32("ssi_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 20, 0), - SH_CLK_MSTP32("hac_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 17, 0), - SH_CLK_MSTP32("hac_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 16, 0), - SH_CLK_MSTP32("mmcif_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 13, 0), - SH_CLK_MSTP32("flctl_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 12, 0), - SH_CLK_MSTP32("tmu345_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 9, 0), - SH_CLK_MSTP32("tmu012_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 8, 0), - SH_CLK_MSTP32("siof_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 3, 0), - SH_CLK_MSTP32("hspi_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 2, 0), + [MSTP029] = SH_CLK_MSTP32("sci_fck", 5, &div4_clks[DIV4_P], MSTPCR0, 29, 0), + [MSTP028] = SH_CLK_MSTP32("sci_fck", 4, &div4_clks[DIV4_P], MSTPCR0, 28, 0), + [MSTP027] = SH_CLK_MSTP32("sci_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 27, 0), + [MSTP026] = SH_CLK_MSTP32("sci_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 26, 0), + [MSTP025] = SH_CLK_MSTP32("sci_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 25, 0), + [MSTP024] = SH_CLK_MSTP32("sci_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 24, 0), + [MSTP021] = SH_CLK_MSTP32("ssi_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 21, 0), + [MSTP020] = SH_CLK_MSTP32("ssi_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 20, 0), + [MSTP017] = SH_CLK_MSTP32("hac_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 17, 0), + [MSTP016] = SH_CLK_MSTP32("hac_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 16, 0), + [MSTP013] = SH_CLK_MSTP32("mmcif_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 13, 0), + [MSTP012] = SH_CLK_MSTP32("flctl_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 12, 0), + [MSTP009] = SH_CLK_MSTP32("tmu345_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 9, 0), + [MSTP008] = SH_CLK_MSTP32("tmu012_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 8, 0), + [MSTP003] = SH_CLK_MSTP32("siof_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 3, 0), + [MSTP002] = SH_CLK_MSTP32("hspi_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 2, 0), /* MSTPCR1 */ - SH_CLK_MSTP32("hudi_fck", -1, NULL, MSTPCR1, 19, 0), - SH_CLK_MSTP32("ubc_fck", -1, NULL, MSTPCR1, 17, 0), - SH_CLK_MSTP32("dmac_11_6_fck", -1, NULL, MSTPCR1, 5, 0), - SH_CLK_MSTP32("dmac_5_0_fck", -1, NULL, MSTPCR1, 4, 0), - SH_CLK_MSTP32("gdta_fck", -1, NULL, MSTPCR1, 0, 0), + [MSTP119] = SH_CLK_MSTP32("hudi_fck", -1, NULL, MSTPCR1, 19, 0), + [MSTP117] = SH_CLK_MSTP32("ubc_fck", -1, NULL, MSTPCR1, 17, 0), + [MSTP105] = SH_CLK_MSTP32("dmac_11_6_fck", -1, NULL, MSTPCR1, 5, 0), + [MSTP104] = SH_CLK_MSTP32("dmac_5_0_fck", -1, NULL, MSTPCR1, 4, 0), + [MSTP100] = SH_CLK_MSTP32("gdta_fck", -1, NULL, MSTPCR1, 0, 0), }; static struct clk_lookup lookups[] = { @@ -119,32 +125,32 @@ static struct clk_lookup lookups[] = { /* TMU0 */ .dev_id = "sh_tmu.0", .con_id = "tmu_fck", - .clk = &mstp_clks[13], /* tmu012_fck */ + .clk = &mstp_clks[MSTP008], }, { /* TMU1 */ .dev_id = "sh_tmu.1", .con_id = "tmu_fck", - .clk = &mstp_clks[13], + .clk = &mstp_clks[MSTP008], }, { /* TMU2 */ .dev_id = "sh_tmu.2", .con_id = "tmu_fck", - .clk = &mstp_clks[13], + .clk = &mstp_clks[MSTP008], }, { /* TMU3 */ .dev_id = "sh_tmu.3", .con_id = "tmu_fck", - .clk = &mstp_clks[12], /* tmu345_fck */ + .clk = &mstp_clks[MSTP009], }, { /* TMU4 */ .dev_id = "sh_tmu.4", .con_id = "tmu_fck", - .clk = &mstp_clks[12], + .clk = &mstp_clks[MSTP009], }, { /* TMU5 */ .dev_id = "sh_tmu.5", .con_id = "tmu_fck", - .clk = &mstp_clks[12], + .clk = &mstp_clks[MSTP009], }, }; @@ -161,7 +167,7 @@ int __init arch_clk_init(void) ret = sh_clk_div4_register(div4_clks, ARRAY_SIZE(div4_clks), &div4_table); if (!ret) - ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks)); + ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); return ret; } -- cgit v0.10.2 From eb85dcaa3e386eb5f1b9b48f707088538a789d58 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 05:00:22 +0000 Subject: sh: sh7785 mstp32 clkdev lookup Add sh7785 MSTP clocks to the clkdev lookup table. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c index cc34ec3..24d7208 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c @@ -120,7 +120,47 @@ static struct clk mstp_clks[MSTP_NR] = { [MSTP100] = SH_CLK_MSTP32("gdta_fck", -1, NULL, MSTPCR1, 0, 0), }; +#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } + static struct clk_lookup lookups[] = { + /* MSTP32 clocks */ + { + /* SCIF5 */ + .dev_id = "sh-sci.5", + .con_id = "sci_fck", + .clk = &mstp_clks[MSTP029], + }, { + /* SCIF4 */ + .dev_id = "sh-sci.4", + .con_id = "sci_fck", + .clk = &mstp_clks[MSTP028], + }, { + /* SCIF3 */ + .dev_id = "sh-sci.3", + .con_id = "sci_fck", + .clk = &mstp_clks[MSTP027], + }, { + /* SCIF2 */ + .dev_id = "sh-sci.2", + .con_id = "sci_fck", + .clk = &mstp_clks[MSTP026], + }, { + /* SCIF1 */ + .dev_id = "sh-sci.1", + .con_id = "sci_fck", + .clk = &mstp_clks[MSTP025], + }, { + /* SCIF0 */ + .dev_id = "sh-sci.0", + .con_id = "sci_fck", + .clk = &mstp_clks[MSTP024], + }, + CLKDEV_CON_ID("ssi1_fck", &mstp_clks[MSTP021]), + CLKDEV_CON_ID("ssi0_fck", &mstp_clks[MSTP020]), + CLKDEV_CON_ID("hac1_fck", &mstp_clks[MSTP017]), + CLKDEV_CON_ID("hac0_fck", &mstp_clks[MSTP016]), + CLKDEV_CON_ID("mmcif_fck", &mstp_clks[MSTP013]), + CLKDEV_CON_ID("flctl_fck", &mstp_clks[MSTP012]), { /* TMU0 */ .dev_id = "sh_tmu.0", @@ -152,6 +192,13 @@ static struct clk_lookup lookups[] = { .con_id = "tmu_fck", .clk = &mstp_clks[MSTP009], }, + CLKDEV_CON_ID("siof_fck", &mstp_clks[MSTP003]), + CLKDEV_CON_ID("hspi_fck", &mstp_clks[MSTP002]), + CLKDEV_CON_ID("hudi_fck", &mstp_clks[MSTP119]), + CLKDEV_CON_ID("ubc_fck", &mstp_clks[MSTP117]), + CLKDEV_CON_ID("dmac_11_6_fck", &mstp_clks[MSTP105]), + CLKDEV_CON_ID("dmac_5_0_fck", &mstp_clks[MSTP104]), + CLKDEV_CON_ID("gdta_fck", &mstp_clks[MSTP100]), }; int __init arch_clk_init(void) -- cgit v0.10.2 From 8bc23d95a0cd639e8766e522e5b9cfd5345bd3e2 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 05:00:30 +0000 Subject: sh: sh7786 mstp32 index rework This patch adds sh7786 MSTP enums for mstp_clks[] index. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c index c4a84bb..57c13ba 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c @@ -87,39 +87,47 @@ struct clk div4_clks[DIV4_NR] = { #define MSTPCR0 0xffc40030 #define MSTPCR1 0xffc40034 -static struct clk mstp_clks[] = { +enum { MSTP029, MSTP028, MSTP027, MSTP026, MSTP025, MSTP024, + MSTP023, MSTP022, MSTP021, MSTP020, MSTP017, MSTP016, + MSTP015, MSTP014, MSTP011, MSTP010, MSTP009, MSTP008, + MSTP005, MSTP004, MSTP002, + MSTP112, MSTP110, MSTP109, MSTP108, + MSTP105, MSTP104, MSTP103, MSTP102, + MSTP_NR }; + +static struct clk mstp_clks[MSTP_NR] = { /* MSTPCR0 */ - SH_CLK_MSTP32("sci_fck", 5, &div4_clks[DIV4_P], MSTPCR0, 29, 0), - SH_CLK_MSTP32("sci_fck", 4, &div4_clks[DIV4_P], MSTPCR0, 28, 0), - SH_CLK_MSTP32("sci_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 27, 0), - SH_CLK_MSTP32("sci_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 26, 0), - SH_CLK_MSTP32("sci_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 25, 0), - SH_CLK_MSTP32("sci_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 24, 0), - SH_CLK_MSTP32("ssi_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 23, 0), - SH_CLK_MSTP32("ssi_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 22, 0), - SH_CLK_MSTP32("ssi_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 21, 0), - SH_CLK_MSTP32("ssi_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 20, 0), - SH_CLK_MSTP32("hac_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 17, 0), - SH_CLK_MSTP32("hac_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 16, 0), - SH_CLK_MSTP32("i2c_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 15, 0), - SH_CLK_MSTP32("i2c_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 14, 0), - SH_CLK_MSTP32("tmu9_11_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 11, 0), - SH_CLK_MSTP32("tmu678_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 10, 0), - SH_CLK_MSTP32("tmu345_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 9, 0), - SH_CLK_MSTP32("tmu012_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 8, 0), - SH_CLK_MSTP32("sdif_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 5, 0), - SH_CLK_MSTP32("sdif_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 4, 0), - SH_CLK_MSTP32("hspi_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 2, 0), + [MSTP029] = SH_CLK_MSTP32("sci_fck", 5, &div4_clks[DIV4_P], MSTPCR0, 29, 0), + [MSTP028] = SH_CLK_MSTP32("sci_fck", 4, &div4_clks[DIV4_P], MSTPCR0, 28, 0), + [MSTP027] = SH_CLK_MSTP32("sci_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 27, 0), + [MSTP026] = SH_CLK_MSTP32("sci_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 26, 0), + [MSTP025] = SH_CLK_MSTP32("sci_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 25, 0), + [MSTP024] = SH_CLK_MSTP32("sci_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 24, 0), + [MSTP023] = SH_CLK_MSTP32("ssi_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 23, 0), + [MSTP022] = SH_CLK_MSTP32("ssi_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 22, 0), + [MSTP021] = SH_CLK_MSTP32("ssi_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 21, 0), + [MSTP020] = SH_CLK_MSTP32("ssi_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 20, 0), + [MSTP017] = SH_CLK_MSTP32("hac_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 17, 0), + [MSTP016] = SH_CLK_MSTP32("hac_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 16, 0), + [MSTP015] = SH_CLK_MSTP32("i2c_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 15, 0), + [MSTP014] = SH_CLK_MSTP32("i2c_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 14, 0), + [MSTP011] = SH_CLK_MSTP32("tmu9_11_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 11, 0), + [MSTP010] = SH_CLK_MSTP32("tmu678_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 10, 0), + [MSTP009] = SH_CLK_MSTP32("tmu345_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 9, 0), + [MSTP008] = SH_CLK_MSTP32("tmu012_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 8, 0), + [MSTP005] = SH_CLK_MSTP32("sdif_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 5, 0), + [MSTP004] = SH_CLK_MSTP32("sdif_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 4, 0), + [MSTP002] = SH_CLK_MSTP32("hspi_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 2, 0), /* MSTPCR1 */ - SH_CLK_MSTP32("usb_fck", -1, NULL, MSTPCR1, 12, 0), - SH_CLK_MSTP32("pcie_fck", 2, NULL, MSTPCR1, 10, 0), - SH_CLK_MSTP32("pcie_fck", 1, NULL, MSTPCR1, 9, 0), - SH_CLK_MSTP32("pcie_fck", 0, NULL, MSTPCR1, 8, 0), - SH_CLK_MSTP32("dmac_11_6_fck", -1, NULL, MSTPCR1, 5, 0), - SH_CLK_MSTP32("dmac_5_0_fck", -1, NULL, MSTPCR1, 4, 0), - SH_CLK_MSTP32("du_fck", -1, NULL, MSTPCR1, 3, 0), - SH_CLK_MSTP32("ether_fck", -1, NULL, MSTPCR1, 2, 0), + [MSTP112] = SH_CLK_MSTP32("usb_fck", -1, NULL, MSTPCR1, 12, 0), + [MSTP110] = SH_CLK_MSTP32("pcie_fck", 2, NULL, MSTPCR1, 10, 0), + [MSTP109] = SH_CLK_MSTP32("pcie_fck", 1, NULL, MSTPCR1, 9, 0), + [MSTP108] = SH_CLK_MSTP32("pcie_fck", 0, NULL, MSTPCR1, 8, 0), + [MSTP105] = SH_CLK_MSTP32("dmac_11_6_fck", -1, NULL, MSTPCR1, 5, 0), + [MSTP104] = SH_CLK_MSTP32("dmac_5_0_fck", -1, NULL, MSTPCR1, 4, 0), + [MSTP103] = SH_CLK_MSTP32("du_fck", -1, NULL, MSTPCR1, 3, 0), + [MSTP102] = SH_CLK_MSTP32("ether_fck", -1, NULL, MSTPCR1, 2, 0), }; static struct clk_lookup lookups[] = { @@ -127,62 +135,62 @@ static struct clk_lookup lookups[] = { /* TMU0 */ .dev_id = "sh_tmu.0", .con_id = "tmu_fck", - .clk = &mstp_clks[17], /* tmu012_fck */ + .clk = &mstp_clks[MSTP008], }, { /* TMU1 */ .dev_id = "sh_tmu.1", .con_id = "tmu_fck", - .clk = &mstp_clks[17], + .clk = &mstp_clks[MSTP008], }, { /* TMU2 */ .dev_id = "sh_tmu.2", .con_id = "tmu_fck", - .clk = &mstp_clks[17], + .clk = &mstp_clks[MSTP008], }, { /* TMU3 */ .dev_id = "sh_tmu.3", .con_id = "tmu_fck", - .clk = &mstp_clks[16], /* tmu345_fck */ + .clk = &mstp_clks[MSTP009], }, { /* TMU4 */ .dev_id = "sh_tmu.4", .con_id = "tmu_fck", - .clk = &mstp_clks[16], + .clk = &mstp_clks[MSTP009], }, { /* TMU5 */ .dev_id = "sh_tmu.5", .con_id = "tmu_fck", - .clk = &mstp_clks[16], + .clk = &mstp_clks[MSTP009], }, { /* TMU6 */ .dev_id = "sh_tmu.6", .con_id = "tmu_fck", - .clk = &mstp_clks[15], /* tmu678_fck */ + .clk = &mstp_clks[MSTP010], }, { /* TMU7 */ .dev_id = "sh_tmu.7", .con_id = "tmu_fck", - .clk = &mstp_clks[15], + .clk = &mstp_clks[MSTP010], }, { /* TMU8 */ .dev_id = "sh_tmu.8", .con_id = "tmu_fck", - .clk = &mstp_clks[15], + .clk = &mstp_clks[MSTP010], }, { /* TMU9 */ .dev_id = "sh_tmu.9", .con_id = "tmu_fck", - .clk = &mstp_clks[14], /* tmu9_11_fck */ + .clk = &mstp_clks[MSTP011], }, { /* TMU10 */ .dev_id = "sh_tmu.10", .con_id = "tmu_fck", - .clk = &mstp_clks[14], + .clk = &mstp_clks[MSTP011], }, { /* TMU11 */ .dev_id = "sh_tmu.11", .con_id = "tmu_fck", - .clk = &mstp_clks[14], + .clk = &mstp_clks[MSTP011], } }; @@ -199,7 +207,7 @@ int __init arch_clk_init(void) ret = sh_clk_div4_register(div4_clks, ARRAY_SIZE(div4_clks), &div4_table); if (!ret) - ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks)); + ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR); return ret; } -- cgit v0.10.2 From d8ef3ccc1c99ae51128b28aaed6e8afc43af71ff Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 05:00:38 +0000 Subject: sh: sh7786 mstp32 clkdev lookup Add sh7786 MSTP clocks to the clkdev lookup table. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c index 57c13ba..d4f5f46 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c @@ -130,7 +130,49 @@ static struct clk mstp_clks[MSTP_NR] = { [MSTP102] = SH_CLK_MSTP32("ether_fck", -1, NULL, MSTPCR1, 2, 0), }; +#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } + static struct clk_lookup lookups[] = { + /* MSTP32 clocks */ + { + /* SCIF5 */ + .dev_id = "sh-sci.5", + .con_id = "sci_fck", + .clk = &mstp_clks[MSTP029], + }, { + /* SCIF4 */ + .dev_id = "sh-sci.4", + .con_id = "sci_fck", + .clk = &mstp_clks[MSTP028], + }, { + /* SCIF3 */ + .dev_id = "sh-sci.3", + .con_id = "sci_fck", + .clk = &mstp_clks[MSTP027], + }, { + /* SCIF2 */ + .dev_id = "sh-sci.2", + .con_id = "sci_fck", + .clk = &mstp_clks[MSTP026], + }, { + /* SCIF1 */ + .dev_id = "sh-sci.1", + .con_id = "sci_fck", + .clk = &mstp_clks[MSTP025], + }, { + /* SCIF0 */ + .dev_id = "sh-sci.0", + .con_id = "sci_fck", + .clk = &mstp_clks[MSTP024], + }, + CLKDEV_CON_ID("ssi3_fck", &mstp_clks[MSTP023]), + CLKDEV_CON_ID("ssi2_fck", &mstp_clks[MSTP022]), + CLKDEV_CON_ID("ssi1_fck", &mstp_clks[MSTP021]), + CLKDEV_CON_ID("ssi0_fck", &mstp_clks[MSTP020]), + CLKDEV_CON_ID("hac1_fck", &mstp_clks[MSTP017]), + CLKDEV_CON_ID("hac0_fck", &mstp_clks[MSTP016]), + CLKDEV_CON_ID("i2c1_fck", &mstp_clks[MSTP015]), + CLKDEV_CON_ID("i2c0_fck", &mstp_clks[MSTP014]), { /* TMU0 */ .dev_id = "sh_tmu.0", @@ -191,7 +233,18 @@ static struct clk_lookup lookups[] = { .dev_id = "sh_tmu.11", .con_id = "tmu_fck", .clk = &mstp_clks[MSTP011], - } + }, + CLKDEV_CON_ID("sdif1_fck", &mstp_clks[MSTP005]), + CLKDEV_CON_ID("sdif0_fck", &mstp_clks[MSTP004]), + CLKDEV_CON_ID("hspi_fck", &mstp_clks[MSTP002]), + CLKDEV_CON_ID("usb_fck", &mstp_clks[MSTP112]), + CLKDEV_CON_ID("pcie2_fck", &mstp_clks[MSTP110]), + CLKDEV_CON_ID("pcie1_fck", &mstp_clks[MSTP109]), + CLKDEV_CON_ID("pcie0_fck", &mstp_clks[MSTP108]), + CLKDEV_CON_ID("dmac_11_6_fck", &mstp_clks[MSTP105]), + CLKDEV_CON_ID("dmac_5_0_fck", &mstp_clks[MSTP104]), + CLKDEV_CON_ID("du_fck", &mstp_clks[MSTP103]), + CLKDEV_CON_ID("ether_fck", &mstp_clks[MSTP102]), }; int __init arch_clk_init(void) -- cgit v0.10.2 From c77a9c3edee079fe0411d98cfb9d872bc336ee32 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 05:00:47 +0000 Subject: sh: get rid of mstp32 clock name and id Remove the name and the id from SH_CLK_MSTP32(). Now when lookups are handled by clkdev they are not needed anymore. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/include/asm/clock.h b/arch/sh/include/asm/clock.h index 405a12c..c52882c 100644 --- a/arch/sh/include/asm/clock.h +++ b/arch/sh/include/asm/clock.h @@ -116,15 +116,12 @@ int clk_rate_table_find(struct clk *clk, struct cpufreq_frequency_table *freq_table, unsigned long rate); -#define SH_CLK_MSTP32(_name, _id, _parent, _enable_reg, \ - _enable_bit, _flags) \ -{ \ - .name = _name, \ - .id = _id, \ - .parent = _parent, \ - .enable_reg = (void __iomem *)_enable_reg, \ - .enable_bit = _enable_bit, \ - .flags = _flags, \ +#define SH_CLK_MSTP32(_parent, _enable_reg, _enable_bit, _flags) \ +{ \ + .parent = _parent, \ + .enable_reg = (void __iomem *)_enable_reg, \ + .enable_bit = _enable_bit, \ + .flags = _flags, \ } int sh_clk_mstp32_register(struct clk *clks, int nr); diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c index f661d46..0aabb5d 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c @@ -142,8 +142,8 @@ struct clk div6_clks[DIV6_NR] = { [DIV6_V] = SH_CLK_DIV6(&pll_clk, VCLKCR, 0), }; -#define MSTP(_str, _parent, _reg, _bit, _flags) \ - SH_CLK_MSTP32(_str, -1, _parent, _reg, _bit, _flags) +#define MSTP(_parent, _reg, _bit, _flags) \ + SH_CLK_MSTP32(_parent, _reg, _bit, _flags) enum { MSTP031, MSTP030, MSTP029, MSTP028, MSTP026, MSTP023, MSTP022, MSTP021, MSTP020, MSTP019, MSTP018, MSTP017, MSTP016, @@ -156,50 +156,50 @@ enum { MSTP031, MSTP030, MSTP029, MSTP028, MSTP026, MSTP_NR }; static struct clk mstp_clks[MSTP_NR] = { - [MSTP031] = MSTP("tlb0", &div4_clks[DIV4_I], MSTPCR0, 31, CLK_ENABLE_ON_INIT), - [MSTP030] = MSTP("ic0", &div4_clks[DIV4_I], MSTPCR0, 30, CLK_ENABLE_ON_INIT), - [MSTP029] = MSTP("oc0", &div4_clks[DIV4_I], MSTPCR0, 29, CLK_ENABLE_ON_INIT), - [MSTP028] = MSTP("uram0", &div4_clks[DIV4_U], MSTPCR0, 28, CLK_ENABLE_ON_INIT), - [MSTP026] = MSTP("xymem0", &div4_clks[DIV4_B], MSTPCR0, 26, CLK_ENABLE_ON_INIT), - [MSTP023] = MSTP("intc3", &div4_clks[DIV4_P], MSTPCR0, 23, 0), - [MSTP022] = MSTP("intc0", &div4_clks[DIV4_P], MSTPCR0, 22, 0), - [MSTP021] = MSTP("dmac0", &div4_clks[DIV4_P], MSTPCR0, 21, 0), - [MSTP020] = MSTP("sh0", &div4_clks[DIV4_P], MSTPCR0, 20, 0), - [MSTP019] = MSTP("hudi0", &div4_clks[DIV4_P], MSTPCR0, 19, 0), - [MSTP017] = MSTP("ubc0", &div4_clks[DIV4_P], MSTPCR0, 17, 0), - [MSTP015] = MSTP("tmu_fck", &div4_clks[DIV4_P], MSTPCR0, 15, 0), - [MSTP014] = MSTP("cmt_fck", &r_clk, MSTPCR0, 14, 0), - [MSTP013] = MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0), - [MSTP011] = MSTP("mfi0", &div4_clks[DIV4_P], MSTPCR0, 11, 0), - [MSTP010] = MSTP("flctl0", &div4_clks[DIV4_P], MSTPCR0, 10, 0), - [MSTP007] = SH_CLK_MSTP32("sci_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 7, 0), - [MSTP006] = SH_CLK_MSTP32("sci_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 6, 0), - [MSTP005] = SH_CLK_MSTP32("sci_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 5, 0), - [MSTP004] = SH_CLK_MSTP32("sci_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 4, 0), - [MSTP003] = MSTP("sio0", &div4_clks[DIV4_P], MSTPCR0, 3, 0), - [MSTP002] = MSTP("siof0", &div4_clks[DIV4_P], MSTPCR0, 2, 0), - [MSTP001] = MSTP("siof1", &div4_clks[DIV4_P], MSTPCR0, 1, 0), - - [MSTP109] = MSTP("i2c0", &div4_clks[DIV4_P], MSTPCR1, 9, 0), - [MSTP108] = MSTP("i2c1", &div4_clks[DIV4_P], MSTPCR1, 8, 0), - - [MSTP225] = MSTP("tpu0", &div4_clks[DIV4_P], MSTPCR2, 25, 0), - [MSTP224] = MSTP("irda0", &div4_clks[DIV4_P], MSTPCR2, 24, 0), - [MSTP218] = MSTP("sdhi0", &div4_clks[DIV4_P], MSTPCR2, 18, 0), - [MSTP217] = MSTP("mmcif0", &div4_clks[DIV4_P], MSTPCR2, 17, 0), - [MSTP216] = MSTP("sim0", &div4_clks[DIV4_P], MSTPCR2, 16, 0), - [MSTP214] = MSTP("keysc0", &r_clk, MSTPCR2, 14, 0), - [MSTP213] = MSTP("tsif0", &div4_clks[DIV4_P], MSTPCR2, 13, 0), - [MSTP212] = MSTP("s3d40", &div4_clks[DIV4_P], MSTPCR2, 12, 0), - [MSTP211] = MSTP("usbf0", &div4_clks[DIV4_P], MSTPCR2, 11, 0), - [MSTP208] = MSTP("siu0", &div4_clks[DIV4_B], MSTPCR2, 8, 0), - [MSTP206] = MSTP("jpu0", &div4_clks[DIV4_B], MSTPCR2, 6, CLK_ENABLE_ON_INIT), - [MSTP205] = MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0), - [MSTP204] = MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0), - [MSTP203] = MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0), - [MSTP202] = MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, CLK_ENABLE_ON_INIT), - [MSTP201] = MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, CLK_ENABLE_ON_INIT), - [MSTP200] = MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0), + [MSTP031] = MSTP(&div4_clks[DIV4_I], MSTPCR0, 31, CLK_ENABLE_ON_INIT), + [MSTP030] = MSTP(&div4_clks[DIV4_I], MSTPCR0, 30, CLK_ENABLE_ON_INIT), + [MSTP029] = MSTP(&div4_clks[DIV4_I], MSTPCR0, 29, CLK_ENABLE_ON_INIT), + [MSTP028] = MSTP(&div4_clks[DIV4_U], MSTPCR0, 28, CLK_ENABLE_ON_INIT), + [MSTP026] = MSTP(&div4_clks[DIV4_B], MSTPCR0, 26, CLK_ENABLE_ON_INIT), + [MSTP023] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 23, 0), + [MSTP022] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 22, 0), + [MSTP021] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 21, 0), + [MSTP020] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 20, 0), + [MSTP019] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 19, 0), + [MSTP017] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 17, 0), + [MSTP015] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 15, 0), + [MSTP014] = MSTP(&r_clk, MSTPCR0, 14, 0), + [MSTP013] = MSTP(&r_clk, MSTPCR0, 13, 0), + [MSTP011] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 11, 0), + [MSTP010] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 10, 0), + [MSTP007] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 7, 0), + [MSTP006] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 6, 0), + [MSTP005] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 5, 0), + [MSTP004] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 4, 0), + [MSTP003] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 3, 0), + [MSTP002] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 2, 0), + [MSTP001] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 1, 0), + + [MSTP109] = MSTP(&div4_clks[DIV4_P], MSTPCR1, 9, 0), + [MSTP108] = MSTP(&div4_clks[DIV4_P], MSTPCR1, 8, 0), + + [MSTP225] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 25, 0), + [MSTP224] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 24, 0), + [MSTP218] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 18, 0), + [MSTP217] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 17, 0), + [MSTP216] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 16, 0), + [MSTP214] = MSTP(&r_clk, MSTPCR2, 14, 0), + [MSTP213] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 13, 0), + [MSTP212] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 12, 0), + [MSTP211] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 11, 0), + [MSTP208] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 8, 0), + [MSTP206] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 6, CLK_ENABLE_ON_INIT), + [MSTP205] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 5, 0), + [MSTP204] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 4, 0), + [MSTP203] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 3, 0), + [MSTP202] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 2, CLK_ENABLE_ON_INIT), + [MSTP201] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 1, CLK_ENABLE_ON_INIT), + [MSTP200] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 0, 0), }; #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } @@ -216,7 +216,6 @@ static struct clk_lookup lookups[] = { CLKDEV_CON_ID("xymem0", &mstp_clks[MSTP026]), CLKDEV_CON_ID("intc3", &mstp_clks[MSTP023]), CLKDEV_CON_ID("intc0", &mstp_clks[MSTP022]), - CLKDEV_CON_ID("dmac0", &mstp_clks[MSTP021]), CLKDEV_CON_ID("sh0", &mstp_clks[MSTP020]), CLKDEV_CON_ID("hudi0", &mstp_clks[MSTP019]), diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c index 5649bfc..a3ef183 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c @@ -145,8 +145,8 @@ struct clk div6_clks[DIV6_NR] = { [DIV6_V] = SH_CLK_DIV6(&pll_clk, VCLKCR, 0), }; -#define MSTP(_str, _parent, _reg, _bit, _flags) \ - SH_CLK_MSTP32(_str, -1, _parent, _reg, _bit, _flags) +#define MSTP(_parent, _reg, _bit, _flags) \ + SH_CLK_MSTP32(_parent, _reg, _bit, _flags) enum { MSTP031, MSTP030, MSTP029, MSTP028, MSTP026, MSTP023, MSTP022, MSTP021, MSTP020, MSTP019, MSTP018, MSTP017, MSTP016, @@ -159,45 +159,45 @@ enum { MSTP031, MSTP030, MSTP029, MSTP028, MSTP026, static struct clk mstp_clks[MSTP_NR] = { /* See page 52 of Datasheet V0.40: Overview -> Block Diagram */ - [MSTP031] = MSTP("tlb0", &div4_clks[DIV4_I], MSTPCR0, 31, CLK_ENABLE_ON_INIT), - [MSTP030] = MSTP("ic0", &div4_clks[DIV4_I], MSTPCR0, 30, CLK_ENABLE_ON_INIT), - [MSTP029] = MSTP("oc0", &div4_clks[DIV4_I], MSTPCR0, 29, CLK_ENABLE_ON_INIT), - [MSTP028] = MSTP("rsmem0", &div4_clks[DIV4_SH], MSTPCR0, 28, CLK_ENABLE_ON_INIT), - [MSTP026] = MSTP("xymem0", &div4_clks[DIV4_B], MSTPCR0, 26, CLK_ENABLE_ON_INIT), - [MSTP023] = MSTP("intc3", &div4_clks[DIV4_P], MSTPCR0, 23, 0), - [MSTP022] = MSTP("intc0", &div4_clks[DIV4_P], MSTPCR0, 22, 0), - [MSTP021] = MSTP("dmac0", &div4_clks[DIV4_P], MSTPCR0, 21, 0), - [MSTP020] = MSTP("sh0", &div4_clks[DIV4_P], MSTPCR0, 20, 0), - [MSTP019] = MSTP("hudi0", &div4_clks[DIV4_P], MSTPCR0, 19, 0), - [MSTP017] = MSTP("ubc0", &div4_clks[DIV4_P], MSTPCR0, 17, 0), - [MSTP015] = MSTP("tmu_fck", &div4_clks[DIV4_P], MSTPCR0, 15, 0), - [MSTP014] = MSTP("cmt_fck", &r_clk, MSTPCR0, 14, 0), - [MSTP013] = MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0), - [MSTP011] = MSTP("mfi0", &div4_clks[DIV4_P], MSTPCR0, 11, 0), - [MSTP010] = MSTP("flctl0", &div4_clks[DIV4_P], MSTPCR0, 10, 0), - [MSTP007] = SH_CLK_MSTP32("sci_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 7, 0), - [MSTP006] = SH_CLK_MSTP32("sci_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 6, 0), - [MSTP005] = SH_CLK_MSTP32("sci_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 5, 0), - [MSTP002] = MSTP("msiof0", &div4_clks[DIV4_P], MSTPCR0, 2, 0), - [MSTP001] = MSTP("sbr0", &div4_clks[DIV4_P], MSTPCR0, 1, 0), - - [MSTP109] = MSTP("i2c0", &div4_clks[DIV4_P], MSTPCR1, 9, 0), - - [MSTP227] = MSTP("icb0", &div4_clks[DIV4_P], MSTPCR2, 27, 0), - [MSTP226] = MSTP("meram0", &div4_clks[DIV4_P], MSTPCR2, 26, 0), - [MSTP224] = MSTP("dacy1", &div4_clks[DIV4_P], MSTPCR2, 24, 0), - [MSTP223] = MSTP("dacy0", &div4_clks[DIV4_P], MSTPCR2, 23, 0), - [MSTP222] = MSTP("tsif0", &div4_clks[DIV4_P], MSTPCR2, 22, 0), - [MSTP218] = MSTP("sdhi0", &div4_clks[DIV4_P], MSTPCR2, 18, 0), - [MSTP217] = MSTP("mmcif0", &div4_clks[DIV4_P], MSTPCR2, 17, 0), - [MSTP211] = MSTP("usbf0", &div4_clks[DIV4_P], MSTPCR2, 11, 0), - [MSTP207] = MSTP("veu1", &div4_clks[DIV4_B], MSTPCR2, 7, CLK_ENABLE_ON_INIT), - [MSTP205] = MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0), - [MSTP204] = MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0), - [MSTP203] = MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0), - [MSTP202] = MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, CLK_ENABLE_ON_INIT), - [MSTP201] = MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, CLK_ENABLE_ON_INIT), - [MSTP200] = MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0), + [MSTP031] = MSTP(&div4_clks[DIV4_I], MSTPCR0, 31, CLK_ENABLE_ON_INIT), + [MSTP030] = MSTP(&div4_clks[DIV4_I], MSTPCR0, 30, CLK_ENABLE_ON_INIT), + [MSTP029] = MSTP(&div4_clks[DIV4_I], MSTPCR0, 29, CLK_ENABLE_ON_INIT), + [MSTP028] = MSTP(&div4_clks[DIV4_SH], MSTPCR0, 28, CLK_ENABLE_ON_INIT), + [MSTP026] = MSTP(&div4_clks[DIV4_B], MSTPCR0, 26, CLK_ENABLE_ON_INIT), + [MSTP023] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 23, 0), + [MSTP022] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 22, 0), + [MSTP021] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 21, 0), + [MSTP020] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 20, 0), + [MSTP019] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 19, 0), + [MSTP017] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 17, 0), + [MSTP015] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 15, 0), + [MSTP014] = MSTP(&r_clk, MSTPCR0, 14, 0), + [MSTP013] = MSTP(&r_clk, MSTPCR0, 13, 0), + [MSTP011] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 11, 0), + [MSTP010] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 10, 0), + [MSTP007] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 7, 0), + [MSTP006] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 6, 0), + [MSTP005] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 5, 0), + [MSTP002] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 2, 0), + [MSTP001] = MSTP(&div4_clks[DIV4_P], MSTPCR0, 1, 0), + + [MSTP109] = MSTP(&div4_clks[DIV4_P], MSTPCR1, 9, 0), + + [MSTP227] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 27, 0), + [MSTP226] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 26, 0), + [MSTP224] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 24, 0), + [MSTP223] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 23, 0), + [MSTP222] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 22, 0), + [MSTP218] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 18, 0), + [MSTP217] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 17, 0), + [MSTP211] = MSTP(&div4_clks[DIV4_P], MSTPCR2, 11, 0), + [MSTP207] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 7, CLK_ENABLE_ON_INIT), + [MSTP205] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 5, 0), + [MSTP204] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 4, 0), + [MSTP203] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 3, 0), + [MSTP202] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 2, CLK_ENABLE_ON_INIT), + [MSTP201] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 1, CLK_ENABLE_ON_INIT), + [MSTP200] = MSTP(&div4_clks[DIV4_B], MSTPCR2, 0, 0), }; #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c index 24d7208..4625b72 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c @@ -95,29 +95,29 @@ enum { MSTP029, MSTP028, MSTP027, MSTP026, MSTP025, MSTP024, static struct clk mstp_clks[MSTP_NR] = { /* MSTPCR0 */ - [MSTP029] = SH_CLK_MSTP32("sci_fck", 5, &div4_clks[DIV4_P], MSTPCR0, 29, 0), - [MSTP028] = SH_CLK_MSTP32("sci_fck", 4, &div4_clks[DIV4_P], MSTPCR0, 28, 0), - [MSTP027] = SH_CLK_MSTP32("sci_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 27, 0), - [MSTP026] = SH_CLK_MSTP32("sci_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 26, 0), - [MSTP025] = SH_CLK_MSTP32("sci_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 25, 0), - [MSTP024] = SH_CLK_MSTP32("sci_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 24, 0), - [MSTP021] = SH_CLK_MSTP32("ssi_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 21, 0), - [MSTP020] = SH_CLK_MSTP32("ssi_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 20, 0), - [MSTP017] = SH_CLK_MSTP32("hac_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 17, 0), - [MSTP016] = SH_CLK_MSTP32("hac_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 16, 0), - [MSTP013] = SH_CLK_MSTP32("mmcif_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 13, 0), - [MSTP012] = SH_CLK_MSTP32("flctl_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 12, 0), - [MSTP009] = SH_CLK_MSTP32("tmu345_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 9, 0), - [MSTP008] = SH_CLK_MSTP32("tmu012_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 8, 0), - [MSTP003] = SH_CLK_MSTP32("siof_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 3, 0), - [MSTP002] = SH_CLK_MSTP32("hspi_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 2, 0), + [MSTP029] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 29, 0), + [MSTP028] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 28, 0), + [MSTP027] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 27, 0), + [MSTP026] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 26, 0), + [MSTP025] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 25, 0), + [MSTP024] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 24, 0), + [MSTP021] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 21, 0), + [MSTP020] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 20, 0), + [MSTP017] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 17, 0), + [MSTP016] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 16, 0), + [MSTP013] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 13, 0), + [MSTP012] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 12, 0), + [MSTP009] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 9, 0), + [MSTP008] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 8, 0), + [MSTP003] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 3, 0), + [MSTP002] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 2, 0), /* MSTPCR1 */ - [MSTP119] = SH_CLK_MSTP32("hudi_fck", -1, NULL, MSTPCR1, 19, 0), - [MSTP117] = SH_CLK_MSTP32("ubc_fck", -1, NULL, MSTPCR1, 17, 0), - [MSTP105] = SH_CLK_MSTP32("dmac_11_6_fck", -1, NULL, MSTPCR1, 5, 0), - [MSTP104] = SH_CLK_MSTP32("dmac_5_0_fck", -1, NULL, MSTPCR1, 4, 0), - [MSTP100] = SH_CLK_MSTP32("gdta_fck", -1, NULL, MSTPCR1, 0, 0), + [MSTP119] = SH_CLK_MSTP32(NULL, MSTPCR1, 19, 0), + [MSTP117] = SH_CLK_MSTP32(NULL, MSTPCR1, 17, 0), + [MSTP105] = SH_CLK_MSTP32(NULL, MSTPCR1, 5, 0), + [MSTP104] = SH_CLK_MSTP32(NULL, MSTPCR1, 4, 0), + [MSTP100] = SH_CLK_MSTP32(NULL, MSTPCR1, 0, 0), }; #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c index d4f5f46..653d966 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c @@ -97,37 +97,37 @@ enum { MSTP029, MSTP028, MSTP027, MSTP026, MSTP025, MSTP024, static struct clk mstp_clks[MSTP_NR] = { /* MSTPCR0 */ - [MSTP029] = SH_CLK_MSTP32("sci_fck", 5, &div4_clks[DIV4_P], MSTPCR0, 29, 0), - [MSTP028] = SH_CLK_MSTP32("sci_fck", 4, &div4_clks[DIV4_P], MSTPCR0, 28, 0), - [MSTP027] = SH_CLK_MSTP32("sci_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 27, 0), - [MSTP026] = SH_CLK_MSTP32("sci_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 26, 0), - [MSTP025] = SH_CLK_MSTP32("sci_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 25, 0), - [MSTP024] = SH_CLK_MSTP32("sci_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 24, 0), - [MSTP023] = SH_CLK_MSTP32("ssi_fck", 3, &div4_clks[DIV4_P], MSTPCR0, 23, 0), - [MSTP022] = SH_CLK_MSTP32("ssi_fck", 2, &div4_clks[DIV4_P], MSTPCR0, 22, 0), - [MSTP021] = SH_CLK_MSTP32("ssi_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 21, 0), - [MSTP020] = SH_CLK_MSTP32("ssi_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 20, 0), - [MSTP017] = SH_CLK_MSTP32("hac_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 17, 0), - [MSTP016] = SH_CLK_MSTP32("hac_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 16, 0), - [MSTP015] = SH_CLK_MSTP32("i2c_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 15, 0), - [MSTP014] = SH_CLK_MSTP32("i2c_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 14, 0), - [MSTP011] = SH_CLK_MSTP32("tmu9_11_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 11, 0), - [MSTP010] = SH_CLK_MSTP32("tmu678_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 10, 0), - [MSTP009] = SH_CLK_MSTP32("tmu345_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 9, 0), - [MSTP008] = SH_CLK_MSTP32("tmu012_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 8, 0), - [MSTP005] = SH_CLK_MSTP32("sdif_fck", 1, &div4_clks[DIV4_P], MSTPCR0, 5, 0), - [MSTP004] = SH_CLK_MSTP32("sdif_fck", 0, &div4_clks[DIV4_P], MSTPCR0, 4, 0), - [MSTP002] = SH_CLK_MSTP32("hspi_fck", -1, &div4_clks[DIV4_P], MSTPCR0, 2, 0), + [MSTP029] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 29, 0), + [MSTP028] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 28, 0), + [MSTP027] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 27, 0), + [MSTP026] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 26, 0), + [MSTP025] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 25, 0), + [MSTP024] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 24, 0), + [MSTP023] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 23, 0), + [MSTP022] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 22, 0), + [MSTP021] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 21, 0), + [MSTP020] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 20, 0), + [MSTP017] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 17, 0), + [MSTP016] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 16, 0), + [MSTP015] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 15, 0), + [MSTP014] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 14, 0), + [MSTP011] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 11, 0), + [MSTP010] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 10, 0), + [MSTP009] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 9, 0), + [MSTP008] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 8, 0), + [MSTP005] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 5, 0), + [MSTP004] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 4, 0), + [MSTP002] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 2, 0), /* MSTPCR1 */ - [MSTP112] = SH_CLK_MSTP32("usb_fck", -1, NULL, MSTPCR1, 12, 0), - [MSTP110] = SH_CLK_MSTP32("pcie_fck", 2, NULL, MSTPCR1, 10, 0), - [MSTP109] = SH_CLK_MSTP32("pcie_fck", 1, NULL, MSTPCR1, 9, 0), - [MSTP108] = SH_CLK_MSTP32("pcie_fck", 0, NULL, MSTPCR1, 8, 0), - [MSTP105] = SH_CLK_MSTP32("dmac_11_6_fck", -1, NULL, MSTPCR1, 5, 0), - [MSTP104] = SH_CLK_MSTP32("dmac_5_0_fck", -1, NULL, MSTPCR1, 4, 0), - [MSTP103] = SH_CLK_MSTP32("du_fck", -1, NULL, MSTPCR1, 3, 0), - [MSTP102] = SH_CLK_MSTP32("ether_fck", -1, NULL, MSTPCR1, 2, 0), + [MSTP112] = SH_CLK_MSTP32(NULL, MSTPCR1, 12, 0), + [MSTP110] = SH_CLK_MSTP32(NULL, MSTPCR1, 10, 0), + [MSTP109] = SH_CLK_MSTP32(NULL, MSTPCR1, 9, 0), + [MSTP108] = SH_CLK_MSTP32(NULL, MSTPCR1, 8, 0), + [MSTP105] = SH_CLK_MSTP32(NULL, MSTPCR1, 5, 0), + [MSTP104] = SH_CLK_MSTP32(NULL, MSTPCR1, 4, 0), + [MSTP103] = SH_CLK_MSTP32(NULL, MSTPCR1, 3, 0), + [MSTP102] = SH_CLK_MSTP32(NULL, MSTPCR1, 2, 0), }; #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } -- cgit v0.10.2 From d40db0c4a63c3af44fd31a7c47cc4a11a44befc7 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 07:05:09 +0000 Subject: sh: div4 reparent workaround Update the div4 set_parent() callback to use the flags instead of name to determine parent index. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/clock-cpg.c b/arch/sh/kernel/cpu/clock-cpg.c index 17a73ad..0b165f6 100644 --- a/arch/sh/kernel/cpu/clock-cpg.c +++ b/arch/sh/kernel/cpu/clock-cpg.c @@ -168,7 +168,12 @@ static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent) u32 value; int ret; - if (!strcmp("pll_clk", parent->name)) + /* we really need a better way to determine parent index, but for + * now assume internal parent comes with CLK_ENABLE_ON_INIT set, + * no CLK_ENABLE_ON_INIT means external clock... + */ + + if (parent->flags & CLK_ENABLE_ON_INIT) value = __raw_readl(clk->enable_reg) & ~(1 << 7); else value = __raw_readl(clk->enable_reg) | (1 << 7); -- cgit v0.10.2 From a3e9f2b72fbcb7c4266f4b7ef1814bb8806c1fac Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 07:05:17 +0000 Subject: sh: sh7722 div4 clkdev lookup Add sh7722 DIV4 clocks to the clkdev lookup list. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c index 2798cea..6ad3bc2 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c @@ -186,6 +186,17 @@ static struct clk mstp_clks[HWBLK_NR] = { #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } static struct clk_lookup lookups[] = { + /* DIV4 clocks */ + CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]), + CLKDEV_CON_ID("umem_clk", &div4_clks[DIV4_U]), + CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_SH]), + CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]), + CLKDEV_CON_ID("b3_clk", &div4_clks[DIV4_B3]), + CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]), + CLKDEV_CON_ID("irda_clk", &div4_enable_clks[DIV4_IRDA]), + CLKDEV_CON_ID("siua_clk", &div4_reparent_clks[DIV4_SIUA]), + CLKDEV_CON_ID("siub_clk", &div4_reparent_clks[DIV4_SIUB]), + /* DIV6 clocks */ CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]), -- cgit v0.10.2 From 3f6623497eee32161b0558c02963fa793988b6a0 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 07:05:25 +0000 Subject: sh: sh7723 div4 clkdev lookup Add sh7723 DIV4 clocks to the clkdev lookup list. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c index 500715f..05b112d 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c @@ -211,6 +211,17 @@ static struct clk mstp_clks[] = { #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } static struct clk_lookup lookups[] = { + /* DIV4 clocks */ + CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]), + CLKDEV_CON_ID("umem_clk", &div4_clks[DIV4_U]), + CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_SH]), + CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]), + CLKDEV_CON_ID("b3_clk", &div4_clks[DIV4_B3]), + CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]), + CLKDEV_CON_ID("irda_clk", &div4_enable_clks[DIV4_IRDA]), + CLKDEV_CON_ID("siua_clk", &div4_reparent_clks[DIV4_SIUA]), + CLKDEV_CON_ID("siub_clk", &div4_reparent_clks[DIV4_SIUB]), + /* DIV6 clocks */ CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]), -- cgit v0.10.2 From 1c4cde2e6d3bcd48635f2f68ca8f03290b5cf2e7 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 07:05:32 +0000 Subject: sh: sh7724 div4 clkdev lookup Add sh7724 DIV4 clocks to the clkdev lookup list. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c index 2bbff53..b9ed211 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c @@ -234,6 +234,13 @@ static struct clk mstp_clks[HWBLK_NR] = { #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } static struct clk_lookup lookups[] = { + /* DIV4 clocks */ + CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]), + CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_SH]), + CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]), + CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]), + CLKDEV_CON_ID("vpu_clk", &div4_clks[DIV4_M1]), + /* DIV6 clocks */ CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]), CLKDEV_CON_ID("fsia_clk", &div6_clks[DIV6_FA]), -- cgit v0.10.2 From f8ef178c88cc21b16e81dab09d1def220e9eb49e Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 07:05:42 +0000 Subject: sh: sh7343 div4 clkdev lookup Add sh7343 DIV4 clocks to the clkdev lookup list. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c index 0aabb5d..c123b55 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c @@ -205,6 +205,16 @@ static struct clk mstp_clks[MSTP_NR] = { #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } static struct clk_lookup lookups[] = { + /* DIV4 clocks */ + CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]), + CLKDEV_CON_ID("umem_clk", &div4_clks[DIV4_U]), + CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_SH]), + CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]), + CLKDEV_CON_ID("b3_clk", &div4_clks[DIV4_B3]), + CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]), + CLKDEV_CON_ID("siua_clk", &div4_clks[DIV4_SIUA]), + CLKDEV_CON_ID("siub_clk", &div4_clks[DIV4_SIUB]), + /* DIV6 clocks */ CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]), -- cgit v0.10.2 From 40956e7569c4d03da69748e333dded74a608af56 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 07:05:50 +0000 Subject: sh: sh7366 div4 clkdev lookup Add sh7366 DIV4 clocks to the clkdev lookup list. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c index a3ef183..35290b8 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c @@ -203,6 +203,16 @@ static struct clk mstp_clks[MSTP_NR] = { #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } static struct clk_lookup lookups[] = { + /* DIV4 clocks */ + CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]), + CLKDEV_CON_ID("umem_clk", &div4_clks[DIV4_U]), + CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_SH]), + CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]), + CLKDEV_CON_ID("b3_clk", &div4_clks[DIV4_B3]), + CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]), + CLKDEV_CON_ID("siua_clk", &div4_clks[DIV4_SIUA]), + CLKDEV_CON_ID("siub_clk", &div4_clks[DIV4_SIUB]), + /* DIV6 clocks */ CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]), -- cgit v0.10.2 From 956f7f442afce6df3fa2b3e77a40ecdb7fc4c9fc Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 07:05:58 +0000 Subject: sh: sh7785 div4 clkdev lookup Add sh7785 DIV4 clocks to the clkdev lookup list. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c index 4625b72..0a44be9 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c @@ -123,6 +123,16 @@ static struct clk mstp_clks[MSTP_NR] = { #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } static struct clk_lookup lookups[] = { + /* DIV4 clocks */ + CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]), + CLKDEV_CON_ID("du_clk", &div4_clks[DIV4_DU]), + CLKDEV_CON_ID("ga_clk", &div4_clks[DIV4_GA]), + CLKDEV_CON_ID("ddr_clk", &div4_clks[DIV4_DDR]), + CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]), + CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_SH]), + CLKDEV_CON_ID("umem_clk", &div4_clks[DIV4_U]), + CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]), + /* MSTP32 clocks */ { /* SCIF5 */ -- cgit v0.10.2 From 1fe3d19883b1f6a243b03456a47e0fdc9629bea6 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 07:06:05 +0000 Subject: sh: sh7786 div4 clkdev lookup Add sh7786 DIV4 clocks to the clkdev lookup list. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c index 653d966..f00b89f 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c @@ -133,6 +133,14 @@ static struct clk mstp_clks[MSTP_NR] = { #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } static struct clk_lookup lookups[] = { + /* DIV4 clocks */ + CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]), + CLKDEV_CON_ID("du_clk", &div4_clks[DIV4_DU]), + CLKDEV_CON_ID("ddr_clk", &div4_clks[DIV4_DDR]), + CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]), + CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_SH]), + CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]), + /* MSTP32 clocks */ { /* SCIF5 */ -- cgit v0.10.2 From 914ebf0bbb24696cd7eecee8942efecca5653126 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 07:06:13 +0000 Subject: sh: get rid of div4 clock name Remove the name parameter from SH_CLK_DIV4() and adjust the processor specific code. The lookup happens using clkdev so the name is unused. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/include/asm/clock.h b/arch/sh/include/asm/clock.h index c52882c..f6b0bfd 100644 --- a/arch/sh/include/asm/clock.h +++ b/arch/sh/include/asm/clock.h @@ -126,14 +126,13 @@ int clk_rate_table_find(struct clk *clk, int sh_clk_mstp32_register(struct clk *clks, int nr); -#define SH_CLK_DIV4(_name, _parent, _reg, _shift, _div_bitmap, _flags) \ -{ \ - .name = _name, \ - .parent = _parent, \ - .enable_reg = (void __iomem *)_reg, \ - .enable_bit = _shift, \ - .arch_flags = _div_bitmap, \ - .flags = _flags, \ +#define SH_CLK_DIV4(_parent, _reg, _shift, _div_bitmap, _flags) \ +{ \ + .parent = _parent, \ + .enable_reg = (void __iomem *)_reg, \ + .enable_bit = _shift, \ + .arch_flags = _div_bitmap, \ + .flags = _flags, \ } struct clk_div4_table { diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c index c123b55..e2e8cc2 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c @@ -122,18 +122,18 @@ static struct clk_div4_table div4_table = { enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P, DIV4_SIUA, DIV4_SIUB, DIV4_NR }; -#define DIV4(_str, _reg, _bit, _mask, _flags) \ - SH_CLK_DIV4(_str, &pll_clk, _reg, _bit, _mask, _flags) +#define DIV4(_reg, _bit, _mask, _flags) \ + SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags) struct clk div4_clks[DIV4_NR] = { - [DIV4_I] = DIV4("cpu_clk", FRQCR, 20, 0x1fff, CLK_ENABLE_ON_INIT), - [DIV4_U] = DIV4("umem_clk", FRQCR, 16, 0x1fff, CLK_ENABLE_ON_INIT), - [DIV4_SH] = DIV4("shyway_clk", FRQCR, 12, 0x1fff, CLK_ENABLE_ON_INIT), - [DIV4_B] = DIV4("bus_clk", FRQCR, 8, 0x1fff, CLK_ENABLE_ON_INIT), - [DIV4_B3] = DIV4("b3_clk", FRQCR, 4, 0x1fff, CLK_ENABLE_ON_INIT), - [DIV4_P] = DIV4("peripheral_clk", FRQCR, 0, 0x1fff, 0), - [DIV4_SIUA] = DIV4("siua_clk", SCLKACR, 0, 0x1fff, 0), - [DIV4_SIUB] = DIV4("siub_clk", SCLKBCR, 0, 0x1fff, 0), + [DIV4_I] = DIV4(FRQCR, 20, 0x1fff, CLK_ENABLE_ON_INIT), + [DIV4_U] = DIV4(FRQCR, 16, 0x1fff, CLK_ENABLE_ON_INIT), + [DIV4_SH] = DIV4(FRQCR, 12, 0x1fff, CLK_ENABLE_ON_INIT), + [DIV4_B] = DIV4(FRQCR, 8, 0x1fff, CLK_ENABLE_ON_INIT), + [DIV4_B3] = DIV4(FRQCR, 4, 0x1fff, CLK_ENABLE_ON_INIT), + [DIV4_P] = DIV4(FRQCR, 0, 0x1fff, 0), + [DIV4_SIUA] = DIV4(SCLKACR, 0, 0x1fff, 0), + [DIV4_SIUB] = DIV4(SCLKBCR, 0, 0x1fff, 0), }; enum { DIV6_V, DIV6_NR }; diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c index 35290b8..4c3a5a5 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c @@ -125,18 +125,18 @@ static struct clk_div4_table div4_table = { enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P, DIV4_SIUA, DIV4_SIUB, DIV4_NR }; -#define DIV4(_str, _reg, _bit, _mask, _flags) \ - SH_CLK_DIV4(_str, &pll_clk, _reg, _bit, _mask, _flags) +#define DIV4(_reg, _bit, _mask, _flags) \ + SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags) struct clk div4_clks[DIV4_NR] = { - [DIV4_I] = DIV4("cpu_clk", FRQCR, 20, 0x1fef, CLK_ENABLE_ON_INIT), - [DIV4_U] = DIV4("umem_clk", FRQCR, 16, 0x1fff, CLK_ENABLE_ON_INIT), - [DIV4_SH] = DIV4("shyway_clk", FRQCR, 12, 0x1fff, CLK_ENABLE_ON_INIT), - [DIV4_B] = DIV4("bus_clk", FRQCR, 8, 0x1fff, CLK_ENABLE_ON_INIT), - [DIV4_B3] = DIV4("b3_clk", FRQCR, 4, 0x1fff, CLK_ENABLE_ON_INIT), - [DIV4_P] = DIV4("peripheral_clk", FRQCR, 0, 0x1fff, 0), - [DIV4_SIUA] = DIV4("siua_clk", SCLKACR, 0, 0x1fff, 0), - [DIV4_SIUB] = DIV4("siub_clk", SCLKBCR, 0, 0x1fff, 0), + [DIV4_I] = DIV4(FRQCR, 20, 0x1fef, CLK_ENABLE_ON_INIT), + [DIV4_U] = DIV4(FRQCR, 16, 0x1fff, CLK_ENABLE_ON_INIT), + [DIV4_SH] = DIV4(FRQCR, 12, 0x1fff, CLK_ENABLE_ON_INIT), + [DIV4_B] = DIV4(FRQCR, 8, 0x1fff, CLK_ENABLE_ON_INIT), + [DIV4_B3] = DIV4(FRQCR, 4, 0x1fff, CLK_ENABLE_ON_INIT), + [DIV4_P] = DIV4(FRQCR, 0, 0x1fff, 0), + [DIV4_SIUA] = DIV4(SCLKACR, 0, 0x1fff, 0), + [DIV4_SIUB] = DIV4(SCLKBCR, 0, 0x1fff, 0), }; enum { DIV6_V, DIV6_NR }; diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c index 6ad3bc2..2d811d9 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c @@ -122,31 +122,31 @@ static struct clk_div4_table div4_table = { .div_mult_table = &div4_div_mult_table, }; -#define DIV4(_str, _reg, _bit, _mask, _flags) \ - SH_CLK_DIV4(_str, &pll_clk, _reg, _bit, _mask, _flags) +#define DIV4(_reg, _bit, _mask, _flags) \ + SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags) enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P, DIV4_NR }; struct clk div4_clks[DIV4_NR] = { - [DIV4_I] = DIV4("cpu_clk", FRQCR, 20, 0x1fef, CLK_ENABLE_ON_INIT), - [DIV4_U] = DIV4("umem_clk", FRQCR, 16, 0x1fff, CLK_ENABLE_ON_INIT), - [DIV4_SH] = DIV4("shyway_clk", FRQCR, 12, 0x1fff, CLK_ENABLE_ON_INIT), - [DIV4_B] = DIV4("bus_clk", FRQCR, 8, 0x1fff, CLK_ENABLE_ON_INIT), - [DIV4_B3] = DIV4("b3_clk", FRQCR, 4, 0x1fff, CLK_ENABLE_ON_INIT), - [DIV4_P] = DIV4("peripheral_clk", FRQCR, 0, 0x1fff, 0), + [DIV4_I] = DIV4(FRQCR, 20, 0x1fef, CLK_ENABLE_ON_INIT), + [DIV4_U] = DIV4(FRQCR, 16, 0x1fff, CLK_ENABLE_ON_INIT), + [DIV4_SH] = DIV4(FRQCR, 12, 0x1fff, CLK_ENABLE_ON_INIT), + [DIV4_B] = DIV4(FRQCR, 8, 0x1fff, CLK_ENABLE_ON_INIT), + [DIV4_B3] = DIV4(FRQCR, 4, 0x1fff, CLK_ENABLE_ON_INIT), + [DIV4_P] = DIV4(FRQCR, 0, 0x1fff, 0), }; enum { DIV4_IRDA, DIV4_ENABLE_NR }; struct clk div4_enable_clks[DIV4_ENABLE_NR] = { - [DIV4_IRDA] = DIV4("irda_clk", IRDACLKCR, 0, 0x1fff, 0), + [DIV4_IRDA] = DIV4(IRDACLKCR, 0, 0x1fff, 0), }; enum { DIV4_SIUA, DIV4_SIUB, DIV4_REPARENT_NR }; struct clk div4_reparent_clks[DIV4_REPARENT_NR] = { - [DIV4_SIUA] = DIV4("siua_clk", SCLKACR, 0, 0x1fff, 0), - [DIV4_SIUB] = DIV4("siub_clk", SCLKBCR, 0, 0x1fff, 0), + [DIV4_SIUA] = DIV4(SCLKACR, 0, 0x1fff, 0), + [DIV4_SIUB] = DIV4(SCLKBCR, 0, 0x1fff, 0), }; enum { DIV6_V, DIV6_NR }; diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c index 05b112d..7685504 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c @@ -125,29 +125,29 @@ static struct clk_div4_table div4_table = { enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P, DIV4_NR }; -#define DIV4(_str, _reg, _bit, _mask, _flags) \ - SH_CLK_DIV4(_str, &pll_clk, _reg, _bit, _mask, _flags) +#define DIV4(_reg, _bit, _mask, _flags) \ + SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags) struct clk div4_clks[DIV4_NR] = { - [DIV4_I] = DIV4("cpu_clk", FRQCR, 20, 0x0dbf, CLK_ENABLE_ON_INIT), - [DIV4_U] = DIV4("umem_clk", FRQCR, 16, 0x0dbf, CLK_ENABLE_ON_INIT), - [DIV4_SH] = DIV4("shyway_clk", FRQCR, 12, 0x0dbf, CLK_ENABLE_ON_INIT), - [DIV4_B] = DIV4("bus_clk", FRQCR, 8, 0x0dbf, CLK_ENABLE_ON_INIT), - [DIV4_B3] = DIV4("b3_clk", FRQCR, 4, 0x0db4, CLK_ENABLE_ON_INIT), - [DIV4_P] = DIV4("peripheral_clk", FRQCR, 0, 0x0dbf, 0), + [DIV4_I] = DIV4(FRQCR, 20, 0x0dbf, CLK_ENABLE_ON_INIT), + [DIV4_U] = DIV4(FRQCR, 16, 0x0dbf, CLK_ENABLE_ON_INIT), + [DIV4_SH] = DIV4(FRQCR, 12, 0x0dbf, CLK_ENABLE_ON_INIT), + [DIV4_B] = DIV4(FRQCR, 8, 0x0dbf, CLK_ENABLE_ON_INIT), + [DIV4_B3] = DIV4(FRQCR, 4, 0x0db4, CLK_ENABLE_ON_INIT), + [DIV4_P] = DIV4(FRQCR, 0, 0x0dbf, 0), }; enum { DIV4_IRDA, DIV4_ENABLE_NR }; struct clk div4_enable_clks[DIV4_ENABLE_NR] = { - [DIV4_IRDA] = DIV4("irda_clk", IRDACLKCR, 0, 0x0dbf, 0), + [DIV4_IRDA] = DIV4(IRDACLKCR, 0, 0x0dbf, 0), }; enum { DIV4_SIUA, DIV4_SIUB, DIV4_REPARENT_NR }; struct clk div4_reparent_clks[DIV4_REPARENT_NR] = { - [DIV4_SIUA] = DIV4("siua_clk", SCLKACR, 0, 0x0dbf, 0), - [DIV4_SIUB] = DIV4("siub_clk", SCLKBCR, 0, 0x0dbf, 0), + [DIV4_SIUA] = DIV4(SCLKACR, 0, 0x0dbf, 0), + [DIV4_SIUB] = DIV4(SCLKBCR, 0, 0x0dbf, 0), }; enum { DIV6_V, DIV6_NR }; diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c index b9ed211..6095f50 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c @@ -153,15 +153,15 @@ static struct clk_div4_table div4_table = { enum { DIV4_I, DIV4_SH, DIV4_B, DIV4_P, DIV4_M1, DIV4_NR }; -#define DIV4(_str, _reg, _bit, _mask, _flags) \ - SH_CLK_DIV4(_str, &pll_clk, _reg, _bit, _mask, _flags) +#define DIV4(_reg, _bit, _mask, _flags) \ + SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags) struct clk div4_clks[DIV4_NR] = { - [DIV4_I] = DIV4("cpu_clk", FRQCRA, 20, 0x2f7d, CLK_ENABLE_ON_INIT), - [DIV4_SH] = DIV4("shyway_clk", FRQCRA, 12, 0x2f7c, CLK_ENABLE_ON_INIT), - [DIV4_B] = DIV4("bus_clk", FRQCRA, 8, 0x2f7c, CLK_ENABLE_ON_INIT), - [DIV4_P] = DIV4("peripheral_clk", FRQCRA, 0, 0x2f7c, 0), - [DIV4_M1] = DIV4("vpu_clk", FRQCRB, 4, 0x2f7c, CLK_ENABLE_ON_INIT), + [DIV4_I] = DIV4(FRQCRA, 20, 0x2f7d, CLK_ENABLE_ON_INIT), + [DIV4_SH] = DIV4(FRQCRA, 12, 0x2f7c, CLK_ENABLE_ON_INIT), + [DIV4_B] = DIV4(FRQCRA, 8, 0x2f7c, CLK_ENABLE_ON_INIT), + [DIV4_P] = DIV4(FRQCRA, 0, 0x2f7c, 0), + [DIV4_M1] = DIV4(FRQCRB, 4, 0x2f7c, CLK_ENABLE_ON_INIT), }; enum { DIV6_V, DIV6_FA, DIV6_FB, DIV6_I, DIV6_S, DIV6_NR }; diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c index 0a44be9..a7a8eec 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c @@ -70,18 +70,18 @@ static struct clk_div4_table div4_table = { enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_DDR, DIV4_GA, DIV4_DU, DIV4_P, DIV4_NR }; -#define DIV4(_str, _bit, _mask, _flags) \ - SH_CLK_DIV4(_str, &pll_clk, FRQMR1, _bit, _mask, _flags) +#define DIV4(_bit, _mask, _flags) \ + SH_CLK_DIV4(&pll_clk, FRQMR1, _bit, _mask, _flags) struct clk div4_clks[DIV4_NR] = { - [DIV4_P] = DIV4("peripheral_clk", 0, 0x0f80, 0), - [DIV4_DU] = DIV4("du_clk", 4, 0x0ff0, 0), - [DIV4_GA] = DIV4("ga_clk", 8, 0x0030, 0), - [DIV4_DDR] = DIV4("ddr_clk", 12, 0x000c, CLK_ENABLE_ON_INIT), - [DIV4_B] = DIV4("bus_clk", 16, 0x0fe0, CLK_ENABLE_ON_INIT), - [DIV4_SH] = DIV4("shyway_clk", 20, 0x000c, CLK_ENABLE_ON_INIT), - [DIV4_U] = DIV4("umem_clk", 24, 0x000c, CLK_ENABLE_ON_INIT), - [DIV4_I] = DIV4("cpu_clk", 28, 0x000e, CLK_ENABLE_ON_INIT), + [DIV4_P] = DIV4(0, 0x0f80, 0), + [DIV4_DU] = DIV4(4, 0x0ff0, 0), + [DIV4_GA] = DIV4(8, 0x0030, 0), + [DIV4_DDR] = DIV4(12, 0x000c, CLK_ENABLE_ON_INIT), + [DIV4_B] = DIV4(16, 0x0fe0, CLK_ENABLE_ON_INIT), + [DIV4_SH] = DIV4(20, 0x000c, CLK_ENABLE_ON_INIT), + [DIV4_U] = DIV4(24, 0x000c, CLK_ENABLE_ON_INIT), + [DIV4_I] = DIV4(28, 0x000e, CLK_ENABLE_ON_INIT), }; #define MSTPCR0 0xffc80030 diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c index f00b89f..3ce3b5a 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c @@ -72,16 +72,16 @@ static struct clk_div4_table div4_table = { enum { DIV4_I, DIV4_SH, DIV4_B, DIV4_DDR, DIV4_DU, DIV4_P, DIV4_NR }; -#define DIV4(_str, _bit, _mask, _flags) \ - SH_CLK_DIV4(_str, &pll_clk, FRQMR1, _bit, _mask, _flags) +#define DIV4(_bit, _mask, _flags) \ + SH_CLK_DIV4(&pll_clk, FRQMR1, _bit, _mask, _flags) struct clk div4_clks[DIV4_NR] = { - [DIV4_P] = DIV4("peripheral_clk", 0, 0x0b40, 0), - [DIV4_DU] = DIV4("du_clk", 4, 0x0010, 0), - [DIV4_DDR] = DIV4("ddr_clk", 12, 0x0002, CLK_ENABLE_ON_INIT), - [DIV4_B] = DIV4("bus_clk", 16, 0x0360, CLK_ENABLE_ON_INIT), - [DIV4_SH] = DIV4("shyway_clk", 20, 0x0002, CLK_ENABLE_ON_INIT), - [DIV4_I] = DIV4("cpu_clk", 28, 0x0006, CLK_ENABLE_ON_INIT), + [DIV4_P] = DIV4(0, 0x0b40, 0), + [DIV4_DU] = DIV4(4, 0x0010, 0), + [DIV4_DDR] = DIV4(12, 0x0002, CLK_ENABLE_ON_INIT), + [DIV4_B] = DIV4(16, 0x0360, CLK_ENABLE_ON_INIT), + [DIV4_SH] = DIV4(20, 0x0002, CLK_ENABLE_ON_INIT), + [DIV4_I] = DIV4(28, 0x0006, CLK_ENABLE_ON_INIT), }; #define MSTPCR0 0xffc40030 -- cgit v0.10.2 From 53041f020b31dd83aa4d0bdc78015bee58b1afe8 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 09:35:11 +0000 Subject: sh: switch legacy clocks to clkdev This patch converts the legacy clocks to register using clkdev. Also the clock name is removed. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/clock-cpg.c b/arch/sh/kernel/cpu/clock-cpg.c index 0b165f6..69c6472 100644 --- a/arch/sh/kernel/cpu/clock-cpg.c +++ b/arch/sh/kernel/cpu/clock-cpg.c @@ -2,6 +2,7 @@ #include #include #include +#include #include static int sh_clk_mstp32_enable(struct clk *clk) @@ -299,25 +300,21 @@ int __init sh_clk_div4_reparent_register(struct clk *clks, int nr, #ifdef CONFIG_SH_CLK_CPG_LEGACY static struct clk master_clk = { - .name = "master_clk", .flags = CLK_ENABLE_ON_INIT, .rate = CONFIG_SH_PCLK_FREQ, }; static struct clk peripheral_clk = { - .name = "peripheral_clk", .parent = &master_clk, .flags = CLK_ENABLE_ON_INIT, }; static struct clk bus_clk = { - .name = "bus_clk", .parent = &master_clk, .flags = CLK_ENABLE_ON_INIT, }; static struct clk cpu_clk = { - .name = "cpu_clk", .parent = &master_clk, .flags = CLK_ENABLE_ON_INIT, }; @@ -332,6 +329,16 @@ static struct clk *onchip_clocks[] = { &cpu_clk, }; +#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } + +static struct clk_lookup lookups[] = { + /* main clocks */ + CLKDEV_CON_ID("master_clk", &master_clk), + CLKDEV_CON_ID("peripheral_clk", &peripheral_clk), + CLKDEV_CON_ID("bus_clk", &bus_clk), + CLKDEV_CON_ID("cpu_clk", &cpu_clk), +}; + int __init __deprecated cpg_clk_init(void) { int i, ret = 0; @@ -343,6 +350,8 @@ int __init __deprecated cpg_clk_init(void) ret |= clk_register(clk); } + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); + clk_add_alias("tmu_fck", NULL, "peripheral_clk", NULL); clk_add_alias("mtu2_fck", NULL, "peripheral_clk", NULL); clk_add_alias("cmt_fck", NULL, "peripheral_clk", NULL); -- cgit v0.10.2 From b3f9f630d35f7eeec49221690991e834d7b27e05 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 09:35:19 +0000 Subject: sh: switch sh7724 to clkdev This patch converts the remaining sh7724 clocks to use clkdev for lookup. The now unused name and id from struct clk are also removed. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c index 6095f50..2d9700c 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c @@ -41,8 +41,6 @@ /* Fixed 32 KHz root clock for RTC and Power Management purposes */ static struct clk r_clk = { - .name = "rclk", - .id = -1, .rate = 32768, }; @@ -51,8 +49,6 @@ static struct clk r_clk = { * from the platform code. */ struct clk extal_clk = { - .name = "extal", - .id = -1, .rate = 33333333, }; @@ -76,8 +72,6 @@ static struct clk_ops fll_clk_ops = { }; static struct clk fll_clk = { - .name = "fll_clk", - .id = -1, .ops = &fll_clk_ops, .parent = &r_clk, .flags = CLK_ENABLE_ON_INIT, @@ -98,8 +92,6 @@ static struct clk_ops pll_clk_ops = { }; static struct clk pll_clk = { - .name = "pll_clk", - .id = -1, .ops = &pll_clk_ops, .flags = CLK_ENABLE_ON_INIT, }; @@ -115,8 +107,6 @@ static struct clk_ops div3_clk_ops = { }; static struct clk div3_clk = { - .name = "div3_clk", - .id = -1, .ops = &div3_clk_ops, .parent = &pll_clk, }; @@ -234,6 +224,13 @@ static struct clk mstp_clks[HWBLK_NR] = { #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } static struct clk_lookup lookups[] = { + /* main clocks */ + CLKDEV_CON_ID("rclk", &r_clk), + CLKDEV_CON_ID("extal", &extal_clk), + CLKDEV_CON_ID("fll_clk", &fll_clk), + CLKDEV_CON_ID("pll_clk", &pll_clk), + CLKDEV_CON_ID("div3_clk", &div3_clk), + /* DIV4 clocks */ CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]), CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_SH]), -- cgit v0.10.2 From 00522ac3b11f52cce6358516dd8695a588082a73 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 09:35:27 +0000 Subject: sh: switch sh7723 to clkdev This patch converts the remaining sh7723 clocks to use clkdev for lookup. The now unused name and id from struct clk are also removed. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c index 7685504..d3938f0 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c @@ -38,8 +38,6 @@ /* Fixed 32 KHz root clock for RTC and Power Management purposes */ static struct clk r_clk = { - .name = "rclk", - .id = -1, .rate = 32768, }; @@ -48,8 +46,6 @@ static struct clk r_clk = { * from the platform code. */ struct clk extal_clk = { - .name = "extal", - .id = -1, .rate = 33333333, }; @@ -71,8 +67,6 @@ static struct clk_ops dll_clk_ops = { }; static struct clk dll_clk = { - .name = "dll_clk", - .id = -1, .ops = &dll_clk_ops, .parent = &r_clk, .flags = CLK_ENABLE_ON_INIT, @@ -96,8 +90,6 @@ static struct clk_ops pll_clk_ops = { }; static struct clk pll_clk = { - .name = "pll_clk", - .id = -1, .ops = &pll_clk_ops, .flags = CLK_ENABLE_ON_INIT, }; @@ -211,6 +203,12 @@ static struct clk mstp_clks[] = { #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } static struct clk_lookup lookups[] = { + /* main clocks */ + CLKDEV_CON_ID("rclk", &r_clk), + CLKDEV_CON_ID("extal", &extal_clk), + CLKDEV_CON_ID("dll_clk", &dll_clk), + CLKDEV_CON_ID("pll_clk", &pll_clk), + /* DIV4 clocks */ CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]), CLKDEV_CON_ID("umem_clk", &div4_clks[DIV4_U]), -- cgit v0.10.2 From 925bb17b725ba84159bac9defebac0cb46e01e4f Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 09:35:38 +0000 Subject: sh: switch sh7722 to clkdev This patch converts the remaining sh7722 clocks to use clkdev for lookup. The now unused name and id from struct clk are also removed. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c index 2d811d9..2030f3d 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c @@ -37,8 +37,6 @@ /* Fixed 32 KHz root clock for RTC and Power Management purposes */ static struct clk r_clk = { - .name = "rclk", - .id = -1, .rate = 32768, }; @@ -47,8 +45,6 @@ static struct clk r_clk = { * from the platform code. */ struct clk extal_clk = { - .name = "extal", - .id = -1, .rate = 33333333, }; @@ -70,8 +66,6 @@ static struct clk_ops dll_clk_ops = { }; static struct clk dll_clk = { - .name = "dll_clk", - .id = -1, .ops = &dll_clk_ops, .parent = &r_clk, .flags = CLK_ENABLE_ON_INIT, @@ -95,8 +89,6 @@ static struct clk_ops pll_clk_ops = { }; static struct clk pll_clk = { - .name = "pll_clk", - .id = -1, .ops = &pll_clk_ops, .flags = CLK_ENABLE_ON_INIT, }; @@ -186,6 +178,12 @@ static struct clk mstp_clks[HWBLK_NR] = { #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } static struct clk_lookup lookups[] = { + /* main clocks */ + CLKDEV_CON_ID("rclk", &r_clk), + CLKDEV_CON_ID("extal", &extal_clk), + CLKDEV_CON_ID("dll_clk", &dll_clk), + CLKDEV_CON_ID("pll_clk", &pll_clk), + /* DIV4 clocks */ CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]), CLKDEV_CON_ID("umem_clk", &div4_clks[DIV4_U]), -- cgit v0.10.2 From 8249a3113094b826c5010d27c8cf07a395be2abc Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 09:35:45 +0000 Subject: sh: switch sh7343 to clkdev This patch converts the remaining sh7343 clocks to use clkdev for lookup. The now unused name and id from struct clk are also removed. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c index e2e8cc2..71291ae 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c @@ -37,8 +37,6 @@ /* Fixed 32 KHz root clock for RTC and Power Management purposes */ static struct clk r_clk = { - .name = "rclk", - .id = -1, .rate = 32768, }; @@ -47,8 +45,6 @@ static struct clk r_clk = { * from the platform code. */ struct clk extal_clk = { - .name = "extal", - .id = -1, .rate = 33333333, }; @@ -70,8 +66,6 @@ static struct clk_ops dll_clk_ops = { }; static struct clk dll_clk = { - .name = "dll_clk", - .id = -1, .ops = &dll_clk_ops, .parent = &r_clk, .flags = CLK_ENABLE_ON_INIT, @@ -92,8 +86,6 @@ static struct clk_ops pll_clk_ops = { }; static struct clk pll_clk = { - .name = "pll_clk", - .id = -1, .ops = &pll_clk_ops, .flags = CLK_ENABLE_ON_INIT, }; @@ -205,6 +197,12 @@ static struct clk mstp_clks[MSTP_NR] = { #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } static struct clk_lookup lookups[] = { + /* main clocks */ + CLKDEV_CON_ID("rclk", &r_clk), + CLKDEV_CON_ID("extal", &extal_clk), + CLKDEV_CON_ID("dll_clk", &dll_clk), + CLKDEV_CON_ID("pll_clk", &pll_clk), + /* DIV4 clocks */ CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]), CLKDEV_CON_ID("umem_clk", &div4_clks[DIV4_U]), -- cgit v0.10.2 From 59aa69d9c20b1ee15fa26aa6631b555aaef91323 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 09:35:55 +0000 Subject: sh: switch sh7366 to clkdev This patch converts the remaining sh7366 clocks to use clkdev for lookup. The now unused name and id from struct clk are also removed. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c index 4c3a5a5..7ce5bbc 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7366.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7366.c @@ -37,8 +37,6 @@ /* Fixed 32 KHz root clock for RTC and Power Management purposes */ static struct clk r_clk = { - .name = "rclk", - .id = -1, .rate = 32768, }; @@ -47,8 +45,6 @@ static struct clk r_clk = { * from the platform code. */ struct clk extal_clk = { - .name = "extal", - .id = -1, .rate = 33333333, }; @@ -70,8 +66,6 @@ static struct clk_ops dll_clk_ops = { }; static struct clk dll_clk = { - .name = "dll_clk", - .id = -1, .ops = &dll_clk_ops, .parent = &r_clk, .flags = CLK_ENABLE_ON_INIT, @@ -95,8 +89,6 @@ static struct clk_ops pll_clk_ops = { }; static struct clk pll_clk = { - .name = "pll_clk", - .id = -1, .ops = &pll_clk_ops, .flags = CLK_ENABLE_ON_INIT, }; @@ -203,6 +195,12 @@ static struct clk mstp_clks[MSTP_NR] = { #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } static struct clk_lookup lookups[] = { + /* main clocks */ + CLKDEV_CON_ID("rclk", &r_clk), + CLKDEV_CON_ID("extal", &extal_clk), + CLKDEV_CON_ID("dll_clk", &dll_clk), + CLKDEV_CON_ID("pll_clk", &pll_clk), + /* DIV4 clocks */ CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]), CLKDEV_CON_ID("umem_clk", &div4_clks[DIV4_U]), -- cgit v0.10.2 From 4a81fe625efc8b9122eb4473dab31fa90e07a381 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 09:36:03 +0000 Subject: sh: switch sh7785 to clkdev This patch converts the remaining sh7785 clocks to use clkdev for lookup. The now unused name and id from struct clk are also removed. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c index a7a8eec..c3e458a 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7785.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7785.c @@ -24,8 +24,6 @@ * from the platform code. */ static struct clk extal_clk = { - .name = "extal", - .id = -1, .rate = 33333333, }; @@ -43,8 +41,6 @@ static struct clk_ops pll_clk_ops = { }; static struct clk pll_clk = { - .name = "pll_clk", - .id = -1, .ops = &pll_clk_ops, .parent = &extal_clk, .flags = CLK_ENABLE_ON_INIT, @@ -123,6 +119,10 @@ static struct clk mstp_clks[MSTP_NR] = { #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } static struct clk_lookup lookups[] = { + /* main clocks */ + CLKDEV_CON_ID("extal", &extal_clk), + CLKDEV_CON_ID("pll_clk", &pll_clk), + /* DIV4 clocks */ CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]), CLKDEV_CON_ID("du_clk", &div4_clks[DIV4_DU]), -- cgit v0.10.2 From 2cf79bea43491722a23b63a6f4e54d3804c10ed6 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 09:36:16 +0000 Subject: sh: switch sh7786 to clkdev This patch converts the remaining sh7786 clocks to use clkdev for lookup. The now unused name and id from struct clk are also removed. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c index 3ce3b5a..105a6d4 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7786.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7786.c @@ -23,8 +23,6 @@ * from the platform code. */ static struct clk extal_clk = { - .name = "extal", - .id = -1, .rate = 33333333, }; @@ -46,8 +44,6 @@ static struct clk_ops pll_clk_ops = { }; static struct clk pll_clk = { - .name = "pll_clk", - .id = -1, .ops = &pll_clk_ops, .parent = &extal_clk, .flags = CLK_ENABLE_ON_INIT, @@ -133,6 +129,10 @@ static struct clk mstp_clks[MSTP_NR] = { #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } static struct clk_lookup lookups[] = { + /* main clocks */ + CLKDEV_CON_ID("extal", &extal_clk), + CLKDEV_CON_ID("pll_clk", &pll_clk), + /* DIV4 clocks */ CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]), CLKDEV_CON_ID("du_clk", &div4_clks[DIV4_DU]), -- cgit v0.10.2 From 29497ec42c7c3a42682e5538ca7f96cd9a00fcbb Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 09:36:24 +0000 Subject: sh: switch sh7780 to clkdev This patch converts the remaining sh7780 clocks to use clkdev for lookup. The now unused name and id from struct clk are also removed. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7780.c b/arch/sh/kernel/cpu/sh4a/clock-sh7780.c index 150963a..62d7063 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7780.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7780.c @@ -11,6 +11,8 @@ */ #include #include +#include +#include #include #include #include @@ -83,7 +85,6 @@ static struct clk_ops sh7780_shyway_clk_ops = { }; static struct clk sh7780_shyway_clk = { - .name = "shyway_clk", .flags = CLK_ENABLE_ON_INIT, .ops = &sh7780_shyway_clk_ops, }; @@ -96,6 +97,13 @@ static struct clk *sh7780_onchip_clocks[] = { &sh7780_shyway_clk, }; +#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } + +static struct clk_lookup lookups[] = { + /* main clocks */ + CLKDEV_CON_ID("shyway_clk", &sh7780_shyway_clk), +}; + int __init arch_clk_init(void) { struct clk *clk; @@ -113,5 +121,7 @@ int __init arch_clk_init(void) clk_put(clk); + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); + return ret; } -- cgit v0.10.2 From d6a94217fb4b4d193d6064c524df22f97bd49136 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 09:36:32 +0000 Subject: sh: switch sh7763 to clkdev This patch converts the remaining sh7763 clocks to use clkdev for lookup. The now unused name and id from struct clk are also removed. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7763.c b/arch/sh/kernel/cpu/sh4a/clock-sh7763.c index 9f40116..1f1df48 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7763.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7763.c @@ -12,6 +12,8 @@ */ #include #include +#include +#include #include #include #include @@ -77,7 +79,6 @@ static struct clk_ops sh7763_shyway_clk_ops = { }; static struct clk sh7763_shyway_clk = { - .name = "shyway_clk", .flags = CLK_ENABLE_ON_INIT, .ops = &sh7763_shyway_clk_ops, }; @@ -90,6 +91,13 @@ static struct clk *sh7763_onchip_clocks[] = { &sh7763_shyway_clk, }; +#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } + +static struct clk_lookup lookups[] = { + /* main clocks */ + CLKDEV_CON_ID("shyway_clk", &sh7763_shyway_clk), +}; + int __init arch_clk_init(void) { struct clk *clk; @@ -107,5 +115,7 @@ int __init arch_clk_init(void) clk_put(clk); + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); + return ret; } -- cgit v0.10.2 From f0e7f90223108e32f6b28393e4ab892209922e0b Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 09:36:40 +0000 Subject: sh: switch sh7757 to clkdev This patch converts the remaining sh7757 clocks to use clkdev for lookup. The now unused name and id from struct clk are also removed. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7757.c b/arch/sh/kernel/cpu/sh4a/clock-sh7757.c index 86aae60..0a752bd 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7757.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7757.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -87,7 +88,6 @@ static struct clk_ops sh7757_shyway_clk_ops = { }; static struct clk sh7757_shyway_clk = { - .name = "shyway_clk", .flags = CLK_ENABLE_ON_INIT, .ops = &sh7757_shyway_clk_ops, }; @@ -100,6 +100,13 @@ static struct clk *sh7757_onchip_clocks[] = { &sh7757_shyway_clk, }; +#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } + +static struct clk_lookup lookups[] = { + /* main clocks */ + CLKDEV_CON_ID("shyway_clk", &sh7757_shyway_clk), +}; + static int __init sh7757_clk_init(void) { struct clk *clk = clk_get(NULL, "master_clk"); @@ -123,6 +130,8 @@ static int __init sh7757_clk_init(void) clk_put(clk); + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); + return 0; } -- cgit v0.10.2 From 38803d7626c3903dea98d23dfe012e98975503f3 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 09:36:48 +0000 Subject: sh: switch shx3 to clkdev This patch converts the remaining shx3 clocks to use clkdev for lookup. The now unused name and id from struct clk are also removed. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4a/clock-shx3.c b/arch/sh/kernel/cpu/sh4a/clock-shx3.c index e75c57b..236a628 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-shx3.c +++ b/arch/sh/kernel/cpu/sh4a/clock-shx3.c @@ -13,9 +13,10 @@ */ #include #include +#include +#include #include #include -#include static int ifc_divisors[] = { 1, 2, 4 ,6 }; static int bfc_divisors[] = { 1, 1, 1, 1, 1, 12, 16, 18, 24, 32, 36, 48 }; @@ -94,7 +95,6 @@ static struct clk_ops shx3_shyway_clk_ops = { }; static struct clk shx3_shyway_clk = { - .name = "shyway_clk", .flags = CLK_ENABLE_ON_INIT, .ops = &shx3_shyway_clk_ops, }; @@ -107,6 +107,13 @@ static struct clk *shx3_onchip_clocks[] = { &shx3_shyway_clk, }; +#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } + +static struct clk_lookup lookups[] = { + /* main clocks */ + CLKDEV_CON_ID("shyway_clk", &shx3_shyway_clk), +}; + int __init arch_clk_init(void) { struct clk *clk; @@ -124,5 +131,7 @@ int __init arch_clk_init(void) clk_put(clk); + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); + return ret; } -- cgit v0.10.2 From 9c352bcab7f28e472b06c91d57210b93e08f0fbb Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 09:36:57 +0000 Subject: sh: switch sh4-202 to clkdev This patch converts the remaining sh4-202 clocks to use clkdev for lookup. The now unused name and id from struct clk are also removed. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c index 6b80850..4eabc68c 100644 --- a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c +++ b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c @@ -12,9 +12,10 @@ #include #include #include +#include +#include #include #include -#include #define CPG2_FRQCR3 0xfe0a0018 @@ -45,7 +46,6 @@ static struct clk_ops sh4202_emi_clk_ops = { }; static struct clk sh4202_emi_clk = { - .name = "emi_clk", .flags = CLK_ENABLE_ON_INIT, .ops = &sh4202_emi_clk_ops, }; @@ -61,7 +61,6 @@ static struct clk_ops sh4202_femi_clk_ops = { }; static struct clk sh4202_femi_clk = { - .name = "femi_clk", .flags = CLK_ENABLE_ON_INIT, .ops = &sh4202_femi_clk_ops, }; @@ -139,7 +138,6 @@ static struct clk_ops sh4202_shoc_clk_ops = { }; static struct clk sh4202_shoc_clk = { - .name = "shoc_clk", .flags = CLK_ENABLE_ON_INIT, .ops = &sh4202_shoc_clk_ops, }; @@ -150,6 +148,15 @@ static struct clk *sh4202_onchip_clocks[] = { &sh4202_shoc_clk, }; +#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } + +static struct clk_lookup lookups[] = { + /* main clocks */ + CLKDEV_CON_ID("emi_clk", &sh4202_emi_clk), + CLKDEV_CON_ID("femi_clk", &sh4202_femi_clk), + CLKDEV_CON_ID("shoc_clk", &sh4202_shoc_clk), +}; + int __init arch_clk_init(void) { struct clk *clk; @@ -167,5 +174,7 @@ int __init arch_clk_init(void) clk_put(clk); + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); + return ret; } -- cgit v0.10.2 From 67bbabbc8680f53c7b8780d991f655c5cbb88700 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 09:37:05 +0000 Subject: sh: switch boards to clkdev This patch converts the remaining board clocks to use clkdev for lookup if needed. The unused name and id from struct clk are also removed. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c index 6c13b92..1850c08 100644 --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c @@ -710,8 +710,6 @@ static struct clk_ops fsimck_clk_ops = { }; static struct clk fsimckb_clk = { - .name = "fsimckb_clk", - .id = -1, .ops = &fsimck_clk_ops, .enable_reg = (void __iomem *)FCLKBCR, .rate = 0, /* unknown */ diff --git a/arch/sh/boards/mach-highlander/setup.c b/arch/sh/boards/mach-highlander/setup.c index affd667..a5ecfba 100644 --- a/arch/sh/boards/mach-highlander/setup.c +++ b/arch/sh/boards/mach-highlander/setup.c @@ -14,6 +14,7 @@ * for more details. */ #include +#include #include #include #include @@ -26,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -326,7 +328,6 @@ static struct clk_ops ivdr_clk_ops = { }; static struct clk ivdr_clk = { - .name = "ivdr_clk", .ops = &ivdr_clk_ops, }; @@ -334,6 +335,13 @@ static struct clk *r7780rp_clocks[] = { &ivdr_clk, }; +#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } + +static struct clk_lookup lookups[] = { + /* main clocks */ + CLKDEV_CON_ID("ivdr_clk", &ivdr_clk), +}; + static void r7780rp_power_off(void) { if (mach_is_r7780mp() || mach_is_r7785rp()) @@ -370,6 +378,8 @@ static void __init highlander_setup(char **cmdline_p) clk_enable(clk); } + clkdev_add_table(lookups, ARRAY_SIZE(lookups)); + __raw_writew(0x0000, PA_OBLED); /* Clear LED. */ if (mach_is_r7780rp()) diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c index ccaa290..20b6053 100644 --- a/arch/sh/boards/mach-se/7724/setup.c +++ b/arch/sh/boards/mach-se/7724/setup.c @@ -276,8 +276,6 @@ static struct clk_ops fsimck_clk_ops = { }; static struct clk fsimcka_clk = { - .name = "fsimcka_clk", - .id = -1, .ops = &fsimck_clk_ops, .enable_reg = (void __iomem *)FCLKACR, .rate = 0, /* unknown */ -- cgit v0.10.2 From 441c2440aba2efd8d0f48a5e3357deec92283d62 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 09:37:12 +0000 Subject: sh: remove unused clock lookup Now when all clocks are registered using clkdev, get rid of the special SH-specific clock lookup. Also ditch the unused module ref counting code. This patch syncs the SH behaviour with ARM. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/include/asm/clock.h b/arch/sh/include/asm/clock.h index f6b0bfd..35d2196 100644 --- a/arch/sh/include/asm/clock.h +++ b/arch/sh/include/asm/clock.h @@ -23,7 +23,6 @@ struct clk { struct list_head node; const char *name; int id; - struct module *owner; struct clk *parent; struct clk_ops *ops; diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c index a725c7f..8cc6935 100644 --- a/arch/sh/kernel/cpu/clock.c +++ b/arch/sh/kernel/cpu/clock.c @@ -398,49 +398,16 @@ EXPORT_SYMBOL_GPL(clk_round_rate); * Returns a clock. Note that we first try to use device id on the bus * and clock name. If this fails, we try to use clock name only. */ -struct clk *clk_get(struct device *dev, const char *id) +struct clk *clk_get(struct device *dev, const char *con_id) { const char *dev_id = dev ? dev_name(dev) : NULL; - struct clk *p, *clk = ERR_PTR(-ENOENT); - int idno; - clk = clk_get_sys(dev_id, id); - if (clk && !IS_ERR(clk)) - return clk; - - if (dev == NULL || dev->bus != &platform_bus_type) - idno = -1; - else - idno = to_platform_device(dev)->id; - - mutex_lock(&clock_list_sem); - list_for_each_entry(p, &clock_list, node) { - if (p->name && p->id == idno && - strcmp(id, p->name) == 0 && try_module_get(p->owner)) { - clk = p; - goto found; - } - } - - list_for_each_entry(p, &clock_list, node) { - if (p->name && - strcmp(id, p->name) == 0 && try_module_get(p->owner)) { - clk = p; - break; - } - } - -found: - mutex_unlock(&clock_list_sem); - - return clk; + return clk_get_sys(dev_id, con_id); } EXPORT_SYMBOL_GPL(clk_get); void clk_put(struct clk *clk) { - if (clk && !IS_ERR(clk)) - module_put(clk->owner); } EXPORT_SYMBOL_GPL(clk_put); -- cgit v0.10.2 From d28bdf05f72238d626c8d06b61049f6df8d78e70 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 13:29:17 +0000 Subject: sh: move sh asm/clock.h contents to linux/sh_clk.h V2 This patch is V2 of the clock framework move from arch/sh/include/asm/clock.h to include/linux/sh_clk.h and updates the include paths for files that will be shared between SH and SH-Mobile ARM. The file asm/clock.h is still kept in this version, this to depend on as few files as possible at this point. We keep SH specific stuff in there. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/include/asm/clock.h b/arch/sh/include/asm/clock.h index 35d2196..f387e5c 100644 --- a/arch/sh/include/asm/clock.h +++ b/arch/sh/include/asm/clock.h @@ -1,158 +1,13 @@ #ifndef __ASM_SH_CLOCK_H #define __ASM_SH_CLOCK_H -#include -#include -#include -#include -#include - -struct clk; - -struct clk_ops { - void (*init)(struct clk *clk); - int (*enable)(struct clk *clk); - void (*disable)(struct clk *clk); - unsigned long (*recalc)(struct clk *clk); - int (*set_rate)(struct clk *clk, unsigned long rate, int algo_id); - int (*set_parent)(struct clk *clk, struct clk *parent); - long (*round_rate)(struct clk *clk, unsigned long rate); -}; - -struct clk { - struct list_head node; - const char *name; - int id; - - struct clk *parent; - struct clk_ops *ops; - - struct list_head children; - struct list_head sibling; /* node for children */ - - int usecount; - - unsigned long rate; - unsigned long flags; - - void __iomem *enable_reg; - unsigned int enable_bit; - - unsigned long arch_flags; - void *priv; - struct dentry *dentry; - struct cpufreq_frequency_table *freq_table; -}; - -#define CLK_ENABLE_ON_INIT (1 << 0) +#include /* Should be defined by processor-specific code */ void __deprecated arch_init_clk_ops(struct clk_ops **, int type); int __init arch_clk_init(void); -/* arch/sh/kernel/cpu/clock.c */ -int clk_init(void); -unsigned long followparent_recalc(struct clk *); -void recalculate_root_clocks(void); -void propagate_rate(struct clk *); -int clk_reparent(struct clk *child, struct clk *parent); -int clk_register(struct clk *); -void clk_unregister(struct clk *); - /* arch/sh/kernel/cpu/clock-cpg.c */ int __init __deprecated cpg_clk_init(void); -/* the exported API, in addition to clk_set_rate */ -/** - * clk_set_rate_ex - set the clock rate for a clock source, with additional parameter - * @clk: clock source - * @rate: desired clock rate in Hz - * @algo_id: algorithm id to be passed down to ops->set_rate - * - * Returns success (0) or negative errno. - */ -int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id); - -enum clk_sh_algo_id { - NO_CHANGE = 0, - - IUS_N1_N1, - IUS_322, - IUS_522, - IUS_N11, - - SB_N1, - - SB3_N1, - SB3_32, - SB3_43, - SB3_54, - - BP_N1, - - IP_N1, -}; - -struct clk_div_mult_table { - unsigned int *divisors; - unsigned int nr_divisors; - unsigned int *multipliers; - unsigned int nr_multipliers; -}; - -struct cpufreq_frequency_table; -void clk_rate_table_build(struct clk *clk, - struct cpufreq_frequency_table *freq_table, - int nr_freqs, - struct clk_div_mult_table *src_table, - unsigned long *bitmap); - -long clk_rate_table_round(struct clk *clk, - struct cpufreq_frequency_table *freq_table, - unsigned long rate); - -int clk_rate_table_find(struct clk *clk, - struct cpufreq_frequency_table *freq_table, - unsigned long rate); - -#define SH_CLK_MSTP32(_parent, _enable_reg, _enable_bit, _flags) \ -{ \ - .parent = _parent, \ - .enable_reg = (void __iomem *)_enable_reg, \ - .enable_bit = _enable_bit, \ - .flags = _flags, \ -} - -int sh_clk_mstp32_register(struct clk *clks, int nr); - -#define SH_CLK_DIV4(_parent, _reg, _shift, _div_bitmap, _flags) \ -{ \ - .parent = _parent, \ - .enable_reg = (void __iomem *)_reg, \ - .enable_bit = _shift, \ - .arch_flags = _div_bitmap, \ - .flags = _flags, \ -} - -struct clk_div4_table { - struct clk_div_mult_table *div_mult_table; - void (*kick)(struct clk *clk); -}; - -int sh_clk_div4_register(struct clk *clks, int nr, - struct clk_div4_table *table); -int sh_clk_div4_enable_register(struct clk *clks, int nr, - struct clk_div4_table *table); -int sh_clk_div4_reparent_register(struct clk *clks, int nr, - struct clk_div4_table *table); - -#define SH_CLK_DIV6(_parent, _reg, _flags) \ -{ \ - .parent = _parent, \ - .enable_reg = (void __iomem *)_reg, \ - .flags = _flags, \ -} - -int sh_clk_div6_register(struct clk *clks, int nr); - #endif /* __ASM_SH_CLOCK_H */ diff --git a/include/linux/sh_clk.h b/include/linux/sh_clk.h new file mode 100644 index 0000000..de91145 --- /dev/null +++ b/include/linux/sh_clk.h @@ -0,0 +1,151 @@ +#ifndef __SH_CLOCK_H +#define __SH_CLOCK_H + +#include +#include +#include +#include +#include + +struct clk; + +struct clk_ops { + void (*init)(struct clk *clk); + int (*enable)(struct clk *clk); + void (*disable)(struct clk *clk); + unsigned long (*recalc)(struct clk *clk); + int (*set_rate)(struct clk *clk, unsigned long rate, int algo_id); + int (*set_parent)(struct clk *clk, struct clk *parent); + long (*round_rate)(struct clk *clk, unsigned long rate); +}; + +struct clk { + struct list_head node; + const char *name; + int id; + + struct clk *parent; + struct clk_ops *ops; + + struct list_head children; + struct list_head sibling; /* node for children */ + + int usecount; + + unsigned long rate; + unsigned long flags; + + void __iomem *enable_reg; + unsigned int enable_bit; + + unsigned long arch_flags; + void *priv; + struct dentry *dentry; + struct cpufreq_frequency_table *freq_table; +}; + +#define CLK_ENABLE_ON_INIT (1 << 0) + +/* arch/sh/kernel/cpu/clock.c */ +int clk_init(void); +unsigned long followparent_recalc(struct clk *); +void recalculate_root_clocks(void); +void propagate_rate(struct clk *); +int clk_reparent(struct clk *child, struct clk *parent); +int clk_register(struct clk *); +void clk_unregister(struct clk *); + +/* the exported API, in addition to clk_set_rate */ +/** + * clk_set_rate_ex - set the clock rate for a clock source, with additional parameter + * @clk: clock source + * @rate: desired clock rate in Hz + * @algo_id: algorithm id to be passed down to ops->set_rate + * + * Returns success (0) or negative errno. + */ +int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id); + +enum clk_sh_algo_id { + NO_CHANGE = 0, + + IUS_N1_N1, + IUS_322, + IUS_522, + IUS_N11, + + SB_N1, + + SB3_N1, + SB3_32, + SB3_43, + SB3_54, + + BP_N1, + + IP_N1, +}; + +struct clk_div_mult_table { + unsigned int *divisors; + unsigned int nr_divisors; + unsigned int *multipliers; + unsigned int nr_multipliers; +}; + +struct cpufreq_frequency_table; +void clk_rate_table_build(struct clk *clk, + struct cpufreq_frequency_table *freq_table, + int nr_freqs, + struct clk_div_mult_table *src_table, + unsigned long *bitmap); + +long clk_rate_table_round(struct clk *clk, + struct cpufreq_frequency_table *freq_table, + unsigned long rate); + +int clk_rate_table_find(struct clk *clk, + struct cpufreq_frequency_table *freq_table, + unsigned long rate); + +#define SH_CLK_MSTP32(_parent, _enable_reg, _enable_bit, _flags) \ +{ \ + .parent = _parent, \ + .enable_reg = (void __iomem *)_enable_reg, \ + .enable_bit = _enable_bit, \ + .flags = _flags, \ +} + +int sh_clk_mstp32_register(struct clk *clks, int nr); + +#define SH_CLK_DIV4(_parent, _reg, _shift, _div_bitmap, _flags) \ +{ \ + .parent = _parent, \ + .enable_reg = (void __iomem *)_reg, \ + .enable_bit = _shift, \ + .arch_flags = _div_bitmap, \ + .flags = _flags, \ +} + +struct clk_div4_table { + struct clk_div_mult_table *div_mult_table; + void (*kick)(struct clk *clk); +}; + +int sh_clk_div4_register(struct clk *clks, int nr, + struct clk_div4_table *table); +int sh_clk_div4_enable_register(struct clk *clks, int nr, + struct clk_div4_table *table); +int sh_clk_div4_reparent_register(struct clk *clks, int nr, + struct clk_div4_table *table); + +#define SH_CLK_DIV6(_parent, _reg, _flags) \ +{ \ + .parent = _parent, \ + .enable_reg = (void __iomem *)_reg, \ + .flags = _flags, \ +} + +int sh_clk_div6_register(struct clk *clks, int nr); + +#endif /* __SH_CLOCK_H */ -- cgit v0.10.2 From 8b5ee113e1b97097e992a0301d0cac2530b31fc2 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 13:29:25 +0000 Subject: sh: move sh clock.c contents to drivers/sh/clk. This patch is V2 of the SH clock framework move from arch/sh/kernel/cpu/clock.c to drivers/sh/clk.c. All code except the following functions are moved: clk_init(), clk_get() and clk_put(). The init function is still kept in clock.c since it depends on the SH-specific machvec implementation. The symbols clk_get() and clk_put() already exist in the common ARM clkdev code, those symbols are left in the SH tree to avoid duplicating them for SH-Mobile ARM. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/include/asm/clock.h b/arch/sh/include/asm/clock.h index f387e5c..803d4c7 100644 --- a/arch/sh/include/asm/clock.h +++ b/arch/sh/include/asm/clock.h @@ -10,4 +10,7 @@ int __init arch_clk_init(void); /* arch/sh/kernel/cpu/clock-cpg.c */ int __init __deprecated cpg_clk_init(void); +/* arch/sh/kernel/cpu/clock.c */ +int clk_init(void); + #endif /* __ASM_SH_CLOCK_H */ diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c index 8cc6935..50f887d 100644 --- a/arch/sh/kernel/cpu/clock.c +++ b/arch/sh/kernel/cpu/clock.c @@ -16,467 +16,10 @@ */ #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include #include -static LIST_HEAD(clock_list); -static DEFINE_SPINLOCK(clock_lock); -static DEFINE_MUTEX(clock_list_sem); - -void clk_rate_table_build(struct clk *clk, - struct cpufreq_frequency_table *freq_table, - int nr_freqs, - struct clk_div_mult_table *src_table, - unsigned long *bitmap) -{ - unsigned long mult, div; - unsigned long freq; - int i; - - for (i = 0; i < nr_freqs; i++) { - div = 1; - mult = 1; - - if (src_table->divisors && i < src_table->nr_divisors) - div = src_table->divisors[i]; - - if (src_table->multipliers && i < src_table->nr_multipliers) - mult = src_table->multipliers[i]; - - if (!div || !mult || (bitmap && !test_bit(i, bitmap))) - freq = CPUFREQ_ENTRY_INVALID; - else - freq = clk->parent->rate * mult / div; - - freq_table[i].index = i; - freq_table[i].frequency = freq; - } - - /* Termination entry */ - freq_table[i].index = i; - freq_table[i].frequency = CPUFREQ_TABLE_END; -} - -long clk_rate_table_round(struct clk *clk, - struct cpufreq_frequency_table *freq_table, - unsigned long rate) -{ - unsigned long rate_error, rate_error_prev = ~0UL; - unsigned long rate_best_fit = rate; - unsigned long highest, lowest; - int i; - - highest = lowest = 0; - - for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { - unsigned long freq = freq_table[i].frequency; - - if (freq == CPUFREQ_ENTRY_INVALID) - continue; - - if (freq > highest) - highest = freq; - if (freq < lowest) - lowest = freq; - - rate_error = abs(freq - rate); - if (rate_error < rate_error_prev) { - rate_best_fit = freq; - rate_error_prev = rate_error; - } - - if (rate_error == 0) - break; - } - - if (rate >= highest) - rate_best_fit = highest; - if (rate <= lowest) - rate_best_fit = lowest; - - return rate_best_fit; -} - -int clk_rate_table_find(struct clk *clk, - struct cpufreq_frequency_table *freq_table, - unsigned long rate) -{ - int i; - - for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { - unsigned long freq = freq_table[i].frequency; - - if (freq == CPUFREQ_ENTRY_INVALID) - continue; - - if (freq == rate) - return i; - } - - return -ENOENT; -} - -/* Used for clocks that always have same value as the parent clock */ -unsigned long followparent_recalc(struct clk *clk) -{ - return clk->parent ? clk->parent->rate : 0; -} - -int clk_reparent(struct clk *child, struct clk *parent) -{ - list_del_init(&child->sibling); - if (parent) - list_add(&child->sibling, &parent->children); - child->parent = parent; - - /* now do the debugfs renaming to reattach the child - to the proper parent */ - - return 0; -} - -/* Propagate rate to children */ -void propagate_rate(struct clk *tclk) -{ - struct clk *clkp; - - list_for_each_entry(clkp, &tclk->children, sibling) { - if (clkp->ops && clkp->ops->recalc) - clkp->rate = clkp->ops->recalc(clkp); - - propagate_rate(clkp); - } -} - -static void __clk_disable(struct clk *clk) -{ - if (clk->usecount == 0) { - printk(KERN_ERR "Trying disable clock %s with 0 usecount\n", - clk->name); - WARN_ON(1); - return; - } - - if (!(--clk->usecount)) { - if (likely(clk->ops && clk->ops->disable)) - clk->ops->disable(clk); - if (likely(clk->parent)) - __clk_disable(clk->parent); - } -} - -void clk_disable(struct clk *clk) -{ - unsigned long flags; - - if (!clk) - return; - - spin_lock_irqsave(&clock_lock, flags); - __clk_disable(clk); - spin_unlock_irqrestore(&clock_lock, flags); -} -EXPORT_SYMBOL_GPL(clk_disable); - -static int __clk_enable(struct clk *clk) -{ - int ret = 0; - - if (clk->usecount++ == 0) { - if (clk->parent) { - ret = __clk_enable(clk->parent); - if (unlikely(ret)) - goto err; - } - - if (clk->ops && clk->ops->enable) { - ret = clk->ops->enable(clk); - if (ret) { - if (clk->parent) - __clk_disable(clk->parent); - goto err; - } - } - } - - return ret; -err: - clk->usecount--; - return ret; -} - -int clk_enable(struct clk *clk) -{ - unsigned long flags; - int ret; - - if (!clk) - return -EINVAL; - - spin_lock_irqsave(&clock_lock, flags); - ret = __clk_enable(clk); - spin_unlock_irqrestore(&clock_lock, flags); - - return ret; -} -EXPORT_SYMBOL_GPL(clk_enable); - -static LIST_HEAD(root_clks); - -/** - * recalculate_root_clocks - recalculate and propagate all root clocks - * - * Recalculates all root clocks (clocks with no parent), which if the - * clock's .recalc is set correctly, should also propagate their rates. - * Called at init. - */ -void recalculate_root_clocks(void) -{ - struct clk *clkp; - - list_for_each_entry(clkp, &root_clks, sibling) { - if (clkp->ops && clkp->ops->recalc) - clkp->rate = clkp->ops->recalc(clkp); - propagate_rate(clkp); - } -} - -int clk_register(struct clk *clk) -{ - if (clk == NULL || IS_ERR(clk)) - return -EINVAL; - - /* - * trap out already registered clocks - */ - if (clk->node.next || clk->node.prev) - return 0; - - mutex_lock(&clock_list_sem); - - INIT_LIST_HEAD(&clk->children); - clk->usecount = 0; - - if (clk->parent) - list_add(&clk->sibling, &clk->parent->children); - else - list_add(&clk->sibling, &root_clks); - - list_add(&clk->node, &clock_list); - if (clk->ops && clk->ops->init) - clk->ops->init(clk); - mutex_unlock(&clock_list_sem); - - return 0; -} -EXPORT_SYMBOL_GPL(clk_register); - -void clk_unregister(struct clk *clk) -{ - mutex_lock(&clock_list_sem); - list_del(&clk->sibling); - list_del(&clk->node); - mutex_unlock(&clock_list_sem); -} -EXPORT_SYMBOL_GPL(clk_unregister); - -static void clk_enable_init_clocks(void) -{ - struct clk *clkp; - - list_for_each_entry(clkp, &clock_list, node) - if (clkp->flags & CLK_ENABLE_ON_INIT) - clk_enable(clkp); -} - -unsigned long clk_get_rate(struct clk *clk) -{ - return clk->rate; -} -EXPORT_SYMBOL_GPL(clk_get_rate); - -int clk_set_rate(struct clk *clk, unsigned long rate) -{ - return clk_set_rate_ex(clk, rate, 0); -} -EXPORT_SYMBOL_GPL(clk_set_rate); - -int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id) -{ - int ret = -EOPNOTSUPP; - unsigned long flags; - - spin_lock_irqsave(&clock_lock, flags); - - if (likely(clk->ops && clk->ops->set_rate)) { - ret = clk->ops->set_rate(clk, rate, algo_id); - if (ret != 0) - goto out_unlock; - } else { - clk->rate = rate; - ret = 0; - } - - if (clk->ops && clk->ops->recalc) - clk->rate = clk->ops->recalc(clk); - - propagate_rate(clk); - -out_unlock: - spin_unlock_irqrestore(&clock_lock, flags); - - return ret; -} -EXPORT_SYMBOL_GPL(clk_set_rate_ex); - -int clk_set_parent(struct clk *clk, struct clk *parent) -{ - unsigned long flags; - int ret = -EINVAL; - - if (!parent || !clk) - return ret; - if (clk->parent == parent) - return 0; - - spin_lock_irqsave(&clock_lock, flags); - if (clk->usecount == 0) { - if (clk->ops->set_parent) - ret = clk->ops->set_parent(clk, parent); - else - ret = clk_reparent(clk, parent); - - if (ret == 0) { - pr_debug("clock: set parent of %s to %s (new rate %ld)\n", - clk->name, clk->parent->name, clk->rate); - if (clk->ops->recalc) - clk->rate = clk->ops->recalc(clk); - propagate_rate(clk); - } - } else - ret = -EBUSY; - spin_unlock_irqrestore(&clock_lock, flags); - - return ret; -} -EXPORT_SYMBOL_GPL(clk_set_parent); - -struct clk *clk_get_parent(struct clk *clk) -{ - return clk->parent; -} -EXPORT_SYMBOL_GPL(clk_get_parent); - -long clk_round_rate(struct clk *clk, unsigned long rate) -{ - if (likely(clk->ops && clk->ops->round_rate)) { - unsigned long flags, rounded; - - spin_lock_irqsave(&clock_lock, flags); - rounded = clk->ops->round_rate(clk, rate); - spin_unlock_irqrestore(&clock_lock, flags); - - return rounded; - } - - return clk_get_rate(clk); -} -EXPORT_SYMBOL_GPL(clk_round_rate); - -/* - * Returns a clock. Note that we first try to use device id on the bus - * and clock name. If this fails, we try to use clock name only. - */ -struct clk *clk_get(struct device *dev, const char *con_id) -{ - const char *dev_id = dev ? dev_name(dev) : NULL; - - return clk_get_sys(dev_id, con_id); -} -EXPORT_SYMBOL_GPL(clk_get); - -void clk_put(struct clk *clk) -{ -} -EXPORT_SYMBOL_GPL(clk_put); - -#ifdef CONFIG_PM -static int clks_sysdev_suspend(struct sys_device *dev, pm_message_t state) -{ - static pm_message_t prev_state; - struct clk *clkp; - - switch (state.event) { - case PM_EVENT_ON: - /* Resumeing from hibernation */ - if (prev_state.event != PM_EVENT_FREEZE) - break; - - list_for_each_entry(clkp, &clock_list, node) { - if (likely(clkp->ops)) { - unsigned long rate = clkp->rate; - - if (likely(clkp->ops->set_parent)) - clkp->ops->set_parent(clkp, - clkp->parent); - if (likely(clkp->ops->set_rate)) - clkp->ops->set_rate(clkp, - rate, NO_CHANGE); - else if (likely(clkp->ops->recalc)) - clkp->rate = clkp->ops->recalc(clkp); - } - } - break; - case PM_EVENT_FREEZE: - break; - case PM_EVENT_SUSPEND: - break; - } - - prev_state = state; - return 0; -} - -static int clks_sysdev_resume(struct sys_device *dev) -{ - return clks_sysdev_suspend(dev, PMSG_ON); -} - -static struct sysdev_class clks_sysdev_class = { - .name = "clks", -}; - -static struct sysdev_driver clks_sysdev_driver = { - .suspend = clks_sysdev_suspend, - .resume = clks_sysdev_resume, -}; - -static struct sys_device clks_sysdev_dev = { - .cls = &clks_sysdev_class, -}; - -static int __init clk_sysdev_init(void) -{ - sysdev_class_register(&clks_sysdev_class); - sysdev_driver_register(&clks_sysdev_class, &clks_sysdev_driver); - sysdev_register(&clks_sysdev_dev); - - return 0; -} -subsys_initcall(clk_sysdev_init); -#endif - int __init clk_init(void) { int ret; @@ -506,89 +49,19 @@ int __init clk_init(void) } /* - * debugfs support to trace clock tree hierarchy and attributes + * Returns a clock. Note that we first try to use device id on the bus + * and clock name. If this fails, we try to use clock name only. */ -static struct dentry *clk_debugfs_root; - -static int clk_debugfs_register_one(struct clk *c) +struct clk *clk_get(struct device *dev, const char *con_id) { - int err; - struct dentry *d, *child, *child_tmp; - struct clk *pa = c->parent; - char s[255]; - char *p = s; - - p += sprintf(p, "%s", c->name); - if (c->id >= 0) - sprintf(p, ":%d", c->id); - d = debugfs_create_dir(s, pa ? pa->dentry : clk_debugfs_root); - if (!d) - return -ENOMEM; - c->dentry = d; - - d = debugfs_create_u8("usecount", S_IRUGO, c->dentry, (u8 *)&c->usecount); - if (!d) { - err = -ENOMEM; - goto err_out; - } - d = debugfs_create_u32("rate", S_IRUGO, c->dentry, (u32 *)&c->rate); - if (!d) { - err = -ENOMEM; - goto err_out; - } - d = debugfs_create_x32("flags", S_IRUGO, c->dentry, (u32 *)&c->flags); - if (!d) { - err = -ENOMEM; - goto err_out; - } - return 0; + const char *dev_id = dev ? dev_name(dev) : NULL; -err_out: - d = c->dentry; - list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child) - debugfs_remove(child); - debugfs_remove(c->dentry); - return err; + return clk_get_sys(dev_id, con_id); } +EXPORT_SYMBOL_GPL(clk_get); -static int clk_debugfs_register(struct clk *c) +void clk_put(struct clk *clk) { - int err; - struct clk *pa = c->parent; - - if (pa && !pa->dentry) { - err = clk_debugfs_register(pa); - if (err) - return err; - } - - if (!c->dentry && c->name) { - err = clk_debugfs_register_one(c); - if (err) - return err; - } - return 0; } +EXPORT_SYMBOL_GPL(clk_put); -static int __init clk_debugfs_init(void) -{ - struct clk *c; - struct dentry *d; - int err; - - d = debugfs_create_dir("clock", NULL); - if (!d) - return -ENOMEM; - clk_debugfs_root = d; - - list_for_each_entry(c, &clock_list, node) { - err = clk_debugfs_register(c); - if (err) - goto err_out; - } - return 0; -err_out: - debugfs_remove_recursive(clk_debugfs_root); - return err; -} -late_initcall(clk_debugfs_init); diff --git a/drivers/sh/Makefile b/drivers/sh/Makefile index 4956bf1..033a949 100644 --- a/drivers/sh/Makefile +++ b/drivers/sh/Makefile @@ -4,4 +4,5 @@ obj-$(CONFIG_SUPERHYWAY) += superhyway/ obj-$(CONFIG_MAPLE) += maple/ obj-$(CONFIG_GENERIC_GPIO) += pfc.o +obj-$(CONFIG_SUPERH) += clk.o obj-y += intc.o diff --git a/drivers/sh/clk.c b/drivers/sh/clk.c new file mode 100644 index 0000000..c90a3e1 --- /dev/null +++ b/drivers/sh/clk.c @@ -0,0 +1,548 @@ +/* + * drivers/sh/clk.c - SuperH clock framework + * + * Copyright (C) 2005 - 2009 Paul Mundt + * + * This clock framework is derived from the OMAP version by: + * + * Copyright (C) 2004 - 2008 Nokia Corporation + * Written by Tuukka Tikkanen + * + * Modified for omap shared clock framework by Tony Lindgren + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static LIST_HEAD(clock_list); +static DEFINE_SPINLOCK(clock_lock); +static DEFINE_MUTEX(clock_list_sem); + +void clk_rate_table_build(struct clk *clk, + struct cpufreq_frequency_table *freq_table, + int nr_freqs, + struct clk_div_mult_table *src_table, + unsigned long *bitmap) +{ + unsigned long mult, div; + unsigned long freq; + int i; + + for (i = 0; i < nr_freqs; i++) { + div = 1; + mult = 1; + + if (src_table->divisors && i < src_table->nr_divisors) + div = src_table->divisors[i]; + + if (src_table->multipliers && i < src_table->nr_multipliers) + mult = src_table->multipliers[i]; + + if (!div || !mult || (bitmap && !test_bit(i, bitmap))) + freq = CPUFREQ_ENTRY_INVALID; + else + freq = clk->parent->rate * mult / div; + + freq_table[i].index = i; + freq_table[i].frequency = freq; + } + + /* Termination entry */ + freq_table[i].index = i; + freq_table[i].frequency = CPUFREQ_TABLE_END; +} + +long clk_rate_table_round(struct clk *clk, + struct cpufreq_frequency_table *freq_table, + unsigned long rate) +{ + unsigned long rate_error, rate_error_prev = ~0UL; + unsigned long rate_best_fit = rate; + unsigned long highest, lowest; + int i; + + highest = lowest = 0; + + for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { + unsigned long freq = freq_table[i].frequency; + + if (freq == CPUFREQ_ENTRY_INVALID) + continue; + + if (freq > highest) + highest = freq; + if (freq < lowest) + lowest = freq; + + rate_error = abs(freq - rate); + if (rate_error < rate_error_prev) { + rate_best_fit = freq; + rate_error_prev = rate_error; + } + + if (rate_error == 0) + break; + } + + if (rate >= highest) + rate_best_fit = highest; + if (rate <= lowest) + rate_best_fit = lowest; + + return rate_best_fit; +} + +int clk_rate_table_find(struct clk *clk, + struct cpufreq_frequency_table *freq_table, + unsigned long rate) +{ + int i; + + for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { + unsigned long freq = freq_table[i].frequency; + + if (freq == CPUFREQ_ENTRY_INVALID) + continue; + + if (freq == rate) + return i; + } + + return -ENOENT; +} + +/* Used for clocks that always have same value as the parent clock */ +unsigned long followparent_recalc(struct clk *clk) +{ + return clk->parent ? clk->parent->rate : 0; +} + +int clk_reparent(struct clk *child, struct clk *parent) +{ + list_del_init(&child->sibling); + if (parent) + list_add(&child->sibling, &parent->children); + child->parent = parent; + + /* now do the debugfs renaming to reattach the child + to the proper parent */ + + return 0; +} + +/* Propagate rate to children */ +void propagate_rate(struct clk *tclk) +{ + struct clk *clkp; + + list_for_each_entry(clkp, &tclk->children, sibling) { + if (clkp->ops && clkp->ops->recalc) + clkp->rate = clkp->ops->recalc(clkp); + + propagate_rate(clkp); + } +} + +static void __clk_disable(struct clk *clk) +{ + if (clk->usecount == 0) { + printk(KERN_ERR "Trying disable clock %s with 0 usecount\n", + clk->name); + WARN_ON(1); + return; + } + + if (!(--clk->usecount)) { + if (likely(clk->ops && clk->ops->disable)) + clk->ops->disable(clk); + if (likely(clk->parent)) + __clk_disable(clk->parent); + } +} + +void clk_disable(struct clk *clk) +{ + unsigned long flags; + + if (!clk) + return; + + spin_lock_irqsave(&clock_lock, flags); + __clk_disable(clk); + spin_unlock_irqrestore(&clock_lock, flags); +} +EXPORT_SYMBOL_GPL(clk_disable); + +static int __clk_enable(struct clk *clk) +{ + int ret = 0; + + if (clk->usecount++ == 0) { + if (clk->parent) { + ret = __clk_enable(clk->parent); + if (unlikely(ret)) + goto err; + } + + if (clk->ops && clk->ops->enable) { + ret = clk->ops->enable(clk); + if (ret) { + if (clk->parent) + __clk_disable(clk->parent); + goto err; + } + } + } + + return ret; +err: + clk->usecount--; + return ret; +} + +int clk_enable(struct clk *clk) +{ + unsigned long flags; + int ret; + + if (!clk) + return -EINVAL; + + spin_lock_irqsave(&clock_lock, flags); + ret = __clk_enable(clk); + spin_unlock_irqrestore(&clock_lock, flags); + + return ret; +} +EXPORT_SYMBOL_GPL(clk_enable); + +static LIST_HEAD(root_clks); + +/** + * recalculate_root_clocks - recalculate and propagate all root clocks + * + * Recalculates all root clocks (clocks with no parent), which if the + * clock's .recalc is set correctly, should also propagate their rates. + * Called at init. + */ +void recalculate_root_clocks(void) +{ + struct clk *clkp; + + list_for_each_entry(clkp, &root_clks, sibling) { + if (clkp->ops && clkp->ops->recalc) + clkp->rate = clkp->ops->recalc(clkp); + propagate_rate(clkp); + } +} + +int clk_register(struct clk *clk) +{ + if (clk == NULL || IS_ERR(clk)) + return -EINVAL; + + /* + * trap out already registered clocks + */ + if (clk->node.next || clk->node.prev) + return 0; + + mutex_lock(&clock_list_sem); + + INIT_LIST_HEAD(&clk->children); + clk->usecount = 0; + + if (clk->parent) + list_add(&clk->sibling, &clk->parent->children); + else + list_add(&clk->sibling, &root_clks); + + list_add(&clk->node, &clock_list); + if (clk->ops && clk->ops->init) + clk->ops->init(clk); + mutex_unlock(&clock_list_sem); + + return 0; +} +EXPORT_SYMBOL_GPL(clk_register); + +void clk_unregister(struct clk *clk) +{ + mutex_lock(&clock_list_sem); + list_del(&clk->sibling); + list_del(&clk->node); + mutex_unlock(&clock_list_sem); +} +EXPORT_SYMBOL_GPL(clk_unregister); + +void clk_enable_init_clocks(void) +{ + struct clk *clkp; + + list_for_each_entry(clkp, &clock_list, node) + if (clkp->flags & CLK_ENABLE_ON_INIT) + clk_enable(clkp); +} + +unsigned long clk_get_rate(struct clk *clk) +{ + return clk->rate; +} +EXPORT_SYMBOL_GPL(clk_get_rate); + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + return clk_set_rate_ex(clk, rate, 0); +} +EXPORT_SYMBOL_GPL(clk_set_rate); + +int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id) +{ + int ret = -EOPNOTSUPP; + unsigned long flags; + + spin_lock_irqsave(&clock_lock, flags); + + if (likely(clk->ops && clk->ops->set_rate)) { + ret = clk->ops->set_rate(clk, rate, algo_id); + if (ret != 0) + goto out_unlock; + } else { + clk->rate = rate; + ret = 0; + } + + if (clk->ops && clk->ops->recalc) + clk->rate = clk->ops->recalc(clk); + + propagate_rate(clk); + +out_unlock: + spin_unlock_irqrestore(&clock_lock, flags); + + return ret; +} +EXPORT_SYMBOL_GPL(clk_set_rate_ex); + +int clk_set_parent(struct clk *clk, struct clk *parent) +{ + unsigned long flags; + int ret = -EINVAL; + + if (!parent || !clk) + return ret; + if (clk->parent == parent) + return 0; + + spin_lock_irqsave(&clock_lock, flags); + if (clk->usecount == 0) { + if (clk->ops->set_parent) + ret = clk->ops->set_parent(clk, parent); + else + ret = clk_reparent(clk, parent); + + if (ret == 0) { + pr_debug("clock: set parent of %s to %s (new rate %ld)\n", + clk->name, clk->parent->name, clk->rate); + if (clk->ops->recalc) + clk->rate = clk->ops->recalc(clk); + propagate_rate(clk); + } + } else + ret = -EBUSY; + spin_unlock_irqrestore(&clock_lock, flags); + + return ret; +} +EXPORT_SYMBOL_GPL(clk_set_parent); + +struct clk *clk_get_parent(struct clk *clk) +{ + return clk->parent; +} +EXPORT_SYMBOL_GPL(clk_get_parent); + +long clk_round_rate(struct clk *clk, unsigned long rate) +{ + if (likely(clk->ops && clk->ops->round_rate)) { + unsigned long flags, rounded; + + spin_lock_irqsave(&clock_lock, flags); + rounded = clk->ops->round_rate(clk, rate); + spin_unlock_irqrestore(&clock_lock, flags); + + return rounded; + } + + return clk_get_rate(clk); +} +EXPORT_SYMBOL_GPL(clk_round_rate); + +#ifdef CONFIG_PM +static int clks_sysdev_suspend(struct sys_device *dev, pm_message_t state) +{ + static pm_message_t prev_state; + struct clk *clkp; + + switch (state.event) { + case PM_EVENT_ON: + /* Resumeing from hibernation */ + if (prev_state.event != PM_EVENT_FREEZE) + break; + + list_for_each_entry(clkp, &clock_list, node) { + if (likely(clkp->ops)) { + unsigned long rate = clkp->rate; + + if (likely(clkp->ops->set_parent)) + clkp->ops->set_parent(clkp, + clkp->parent); + if (likely(clkp->ops->set_rate)) + clkp->ops->set_rate(clkp, + rate, NO_CHANGE); + else if (likely(clkp->ops->recalc)) + clkp->rate = clkp->ops->recalc(clkp); + } + } + break; + case PM_EVENT_FREEZE: + break; + case PM_EVENT_SUSPEND: + break; + } + + prev_state = state; + return 0; +} + +static int clks_sysdev_resume(struct sys_device *dev) +{ + return clks_sysdev_suspend(dev, PMSG_ON); +} + +static struct sysdev_class clks_sysdev_class = { + .name = "clks", +}; + +static struct sysdev_driver clks_sysdev_driver = { + .suspend = clks_sysdev_suspend, + .resume = clks_sysdev_resume, +}; + +static struct sys_device clks_sysdev_dev = { + .cls = &clks_sysdev_class, +}; + +static int __init clk_sysdev_init(void) +{ + sysdev_class_register(&clks_sysdev_class); + sysdev_driver_register(&clks_sysdev_class, &clks_sysdev_driver); + sysdev_register(&clks_sysdev_dev); + + return 0; +} +subsys_initcall(clk_sysdev_init); +#endif + +/* + * debugfs support to trace clock tree hierarchy and attributes + */ +static struct dentry *clk_debugfs_root; + +static int clk_debugfs_register_one(struct clk *c) +{ + int err; + struct dentry *d, *child, *child_tmp; + struct clk *pa = c->parent; + char s[255]; + char *p = s; + + p += sprintf(p, "%s", c->name); + if (c->id >= 0) + sprintf(p, ":%d", c->id); + d = debugfs_create_dir(s, pa ? pa->dentry : clk_debugfs_root); + if (!d) + return -ENOMEM; + c->dentry = d; + + d = debugfs_create_u8("usecount", S_IRUGO, c->dentry, (u8 *)&c->usecount); + if (!d) { + err = -ENOMEM; + goto err_out; + } + d = debugfs_create_u32("rate", S_IRUGO, c->dentry, (u32 *)&c->rate); + if (!d) { + err = -ENOMEM; + goto err_out; + } + d = debugfs_create_x32("flags", S_IRUGO, c->dentry, (u32 *)&c->flags); + if (!d) { + err = -ENOMEM; + goto err_out; + } + return 0; + +err_out: + d = c->dentry; + list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child) + debugfs_remove(child); + debugfs_remove(c->dentry); + return err; +} + +static int clk_debugfs_register(struct clk *c) +{ + int err; + struct clk *pa = c->parent; + + if (pa && !pa->dentry) { + err = clk_debugfs_register(pa); + if (err) + return err; + } + + if (!c->dentry && c->name) { + err = clk_debugfs_register_one(c); + if (err) + return err; + } + return 0; +} + +static int __init clk_debugfs_init(void) +{ + struct clk *c; + struct dentry *d; + int err; + + d = debugfs_create_dir("clock", NULL); + if (!d) + return -ENOMEM; + clk_debugfs_root = d; + + list_for_each_entry(c, &clock_list, node) { + err = clk_debugfs_register(c); + if (err) + goto err_out; + } + return 0; +err_out: + debugfs_remove_recursive(clk_debugfs_root); + return err; +} +late_initcall(clk_debugfs_init); diff --git a/include/linux/sh_clk.h b/include/linux/sh_clk.h index de91145..6d7de242 100644 --- a/include/linux/sh_clk.h +++ b/include/linux/sh_clk.h @@ -47,13 +47,13 @@ struct clk { #define CLK_ENABLE_ON_INIT (1 << 0) /* arch/sh/kernel/cpu/clock.c */ -int clk_init(void); unsigned long followparent_recalc(struct clk *); void recalculate_root_clocks(void); void propagate_rate(struct clk *); int clk_reparent(struct clk *child, struct clk *parent); int clk_register(struct clk *); void clk_unregister(struct clk *); +void clk_enable_init_clocks(void); /* the exported API, in addition to clk_set_rate */ /** -- cgit v0.10.2 From fa676ca3944e4459ea3d133eabc923c8ab5d2576 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 11 May 2010 13:29:34 +0000 Subject: sh: move sh clock-cpg.c contents to drivers/sh/clk-cpg.c Move the CPG helpers to drivers/sh/clk-cpg.c V2. This to allow SH-Mobile ARM to share the code with SH. All functions except the legacy CPG stuff is moved. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile index 0e48bc6..4edcb60 100644 --- a/arch/sh/kernel/cpu/Makefile +++ b/arch/sh/kernel/cpu/Makefile @@ -16,7 +16,7 @@ obj-$(CONFIG_ARCH_SHMOBILE) += shmobile/ # Common interfaces. obj-$(CONFIG_SH_ADC) += adc.o -obj-$(CONFIG_SH_CLK_CPG) += clock-cpg.o +obj-$(CONFIG_SH_CLK_CPG_LEGACY) += clock-cpg.o obj-$(CONFIG_SH_FPU) += fpu.o obj-$(CONFIG_SH_FPU_EMU) += fpu.o diff --git a/arch/sh/kernel/cpu/clock-cpg.c b/arch/sh/kernel/cpu/clock-cpg.c index 69c6472..e2f63d6 100644 --- a/arch/sh/kernel/cpu/clock-cpg.c +++ b/arch/sh/kernel/cpu/clock-cpg.c @@ -5,300 +5,6 @@ #include #include -static int sh_clk_mstp32_enable(struct clk *clk) -{ - __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << clk->enable_bit), - clk->enable_reg); - return 0; -} - -static void sh_clk_mstp32_disable(struct clk *clk) -{ - __raw_writel(__raw_readl(clk->enable_reg) | (1 << clk->enable_bit), - clk->enable_reg); -} - -static struct clk_ops sh_clk_mstp32_clk_ops = { - .enable = sh_clk_mstp32_enable, - .disable = sh_clk_mstp32_disable, - .recalc = followparent_recalc, -}; - -int __init sh_clk_mstp32_register(struct clk *clks, int nr) -{ - struct clk *clkp; - int ret = 0; - int k; - - for (k = 0; !ret && (k < nr); k++) { - clkp = clks + k; - clkp->ops = &sh_clk_mstp32_clk_ops; - ret |= clk_register(clkp); - } - - return ret; -} - -static long sh_clk_div_round_rate(struct clk *clk, unsigned long rate) -{ - return clk_rate_table_round(clk, clk->freq_table, rate); -} - -static int sh_clk_div6_divisors[64] = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64 -}; - -static struct clk_div_mult_table sh_clk_div6_table = { - .divisors = sh_clk_div6_divisors, - .nr_divisors = ARRAY_SIZE(sh_clk_div6_divisors), -}; - -static unsigned long sh_clk_div6_recalc(struct clk *clk) -{ - struct clk_div_mult_table *table = &sh_clk_div6_table; - unsigned int idx; - - clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, - table, NULL); - - idx = __raw_readl(clk->enable_reg) & 0x003f; - - return clk->freq_table[idx].frequency; -} - -static int sh_clk_div6_set_rate(struct clk *clk, - unsigned long rate, int algo_id) -{ - unsigned long value; - int idx; - - idx = clk_rate_table_find(clk, clk->freq_table, rate); - if (idx < 0) - return idx; - - value = __raw_readl(clk->enable_reg); - value &= ~0x3f; - value |= idx; - __raw_writel(value, clk->enable_reg); - return 0; -} - -static int sh_clk_div6_enable(struct clk *clk) -{ - unsigned long value; - int ret; - - ret = sh_clk_div6_set_rate(clk, clk->rate, 0); - if (ret == 0) { - value = __raw_readl(clk->enable_reg); - value &= ~0x100; /* clear stop bit to enable clock */ - __raw_writel(value, clk->enable_reg); - } - return ret; -} - -static void sh_clk_div6_disable(struct clk *clk) -{ - unsigned long value; - - value = __raw_readl(clk->enable_reg); - value |= 0x100; /* stop clock */ - value |= 0x3f; /* VDIV bits must be non-zero, overwrite divider */ - __raw_writel(value, clk->enable_reg); -} - -static struct clk_ops sh_clk_div6_clk_ops = { - .recalc = sh_clk_div6_recalc, - .round_rate = sh_clk_div_round_rate, - .set_rate = sh_clk_div6_set_rate, - .enable = sh_clk_div6_enable, - .disable = sh_clk_div6_disable, -}; - -int __init sh_clk_div6_register(struct clk *clks, int nr) -{ - struct clk *clkp; - void *freq_table; - int nr_divs = sh_clk_div6_table.nr_divisors; - int freq_table_size = sizeof(struct cpufreq_frequency_table); - int ret = 0; - int k; - - freq_table_size *= (nr_divs + 1); - freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL); - if (!freq_table) { - pr_err("sh_clk_div6_register: unable to alloc memory\n"); - return -ENOMEM; - } - - for (k = 0; !ret && (k < nr); k++) { - clkp = clks + k; - - clkp->ops = &sh_clk_div6_clk_ops; - clkp->id = -1; - clkp->freq_table = freq_table + (k * freq_table_size); - clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END; - - ret = clk_register(clkp); - } - - return ret; -} - -static unsigned long sh_clk_div4_recalc(struct clk *clk) -{ - struct clk_div4_table *d4t = clk->priv; - struct clk_div_mult_table *table = d4t->div_mult_table; - unsigned int idx; - - clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, - table, &clk->arch_flags); - - idx = (__raw_readl(clk->enable_reg) >> clk->enable_bit) & 0x000f; - - return clk->freq_table[idx].frequency; -} - -static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent) -{ - struct clk_div4_table *d4t = clk->priv; - struct clk_div_mult_table *table = d4t->div_mult_table; - u32 value; - int ret; - - /* we really need a better way to determine parent index, but for - * now assume internal parent comes with CLK_ENABLE_ON_INIT set, - * no CLK_ENABLE_ON_INIT means external clock... - */ - - if (parent->flags & CLK_ENABLE_ON_INIT) - value = __raw_readl(clk->enable_reg) & ~(1 << 7); - else - value = __raw_readl(clk->enable_reg) | (1 << 7); - - ret = clk_reparent(clk, parent); - if (ret < 0) - return ret; - - __raw_writel(value, clk->enable_reg); - - /* Rebiuld the frequency table */ - clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, - table, &clk->arch_flags); - - return 0; -} - -static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate, int algo_id) -{ - struct clk_div4_table *d4t = clk->priv; - unsigned long value; - int idx = clk_rate_table_find(clk, clk->freq_table, rate); - if (idx < 0) - return idx; - - value = __raw_readl(clk->enable_reg); - value &= ~(0xf << clk->enable_bit); - value |= (idx << clk->enable_bit); - __raw_writel(value, clk->enable_reg); - - if (d4t->kick) - d4t->kick(clk); - - return 0; -} - -static int sh_clk_div4_enable(struct clk *clk) -{ - __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << 8), clk->enable_reg); - return 0; -} - -static void sh_clk_div4_disable(struct clk *clk) -{ - __raw_writel(__raw_readl(clk->enable_reg) | (1 << 8), clk->enable_reg); -} - -static struct clk_ops sh_clk_div4_clk_ops = { - .recalc = sh_clk_div4_recalc, - .set_rate = sh_clk_div4_set_rate, - .round_rate = sh_clk_div_round_rate, -}; - -static struct clk_ops sh_clk_div4_enable_clk_ops = { - .recalc = sh_clk_div4_recalc, - .set_rate = sh_clk_div4_set_rate, - .round_rate = sh_clk_div_round_rate, - .enable = sh_clk_div4_enable, - .disable = sh_clk_div4_disable, -}; - -static struct clk_ops sh_clk_div4_reparent_clk_ops = { - .recalc = sh_clk_div4_recalc, - .set_rate = sh_clk_div4_set_rate, - .round_rate = sh_clk_div_round_rate, - .enable = sh_clk_div4_enable, - .disable = sh_clk_div4_disable, - .set_parent = sh_clk_div4_set_parent, -}; - -static int __init sh_clk_div4_register_ops(struct clk *clks, int nr, - struct clk_div4_table *table, struct clk_ops *ops) -{ - struct clk *clkp; - void *freq_table; - int nr_divs = table->div_mult_table->nr_divisors; - int freq_table_size = sizeof(struct cpufreq_frequency_table); - int ret = 0; - int k; - - freq_table_size *= (nr_divs + 1); - freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL); - if (!freq_table) { - pr_err("sh_clk_div4_register: unable to alloc memory\n"); - return -ENOMEM; - } - - for (k = 0; !ret && (k < nr); k++) { - clkp = clks + k; - - clkp->ops = ops; - clkp->id = -1; - clkp->priv = table; - - clkp->freq_table = freq_table + (k * freq_table_size); - clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END; - - ret = clk_register(clkp); - } - - return ret; -} - -int __init sh_clk_div4_register(struct clk *clks, int nr, - struct clk_div4_table *table) -{ - return sh_clk_div4_register_ops(clks, nr, table, &sh_clk_div4_clk_ops); -} - -int __init sh_clk_div4_enable_register(struct clk *clks, int nr, - struct clk_div4_table *table) -{ - return sh_clk_div4_register_ops(clks, nr, table, - &sh_clk_div4_enable_clk_ops); -} - -int __init sh_clk_div4_reparent_register(struct clk *clks, int nr, - struct clk_div4_table *table) -{ - return sh_clk_div4_register_ops(clks, nr, table, - &sh_clk_div4_reparent_clk_ops); -} - -#ifdef CONFIG_SH_CLK_CPG_LEGACY static struct clk master_clk = { .flags = CLK_ENABLE_ON_INIT, .rate = CONFIG_SH_PCLK_FREQ, @@ -368,4 +74,3 @@ int __init __weak arch_clk_init(void) { return cpg_clk_init(); } -#endif /* CONFIG_SH_CPG_CLK_LEGACY */ diff --git a/drivers/sh/Makefile b/drivers/sh/Makefile index 033a949..78bb512 100644 --- a/drivers/sh/Makefile +++ b/drivers/sh/Makefile @@ -5,4 +5,5 @@ obj-$(CONFIG_SUPERHYWAY) += superhyway/ obj-$(CONFIG_MAPLE) += maple/ obj-$(CONFIG_GENERIC_GPIO) += pfc.o obj-$(CONFIG_SUPERH) += clk.o +obj-$(CONFIG_SH_CLK_CPG) += clk-cpg.o obj-y += intc.o diff --git a/drivers/sh/clk-cpg.c b/drivers/sh/clk-cpg.c new file mode 100644 index 0000000..f5c80ba --- /dev/null +++ b/drivers/sh/clk-cpg.c @@ -0,0 +1,298 @@ +#include +#include +#include +#include +#include + +static int sh_clk_mstp32_enable(struct clk *clk) +{ + __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << clk->enable_bit), + clk->enable_reg); + return 0; +} + +static void sh_clk_mstp32_disable(struct clk *clk) +{ + __raw_writel(__raw_readl(clk->enable_reg) | (1 << clk->enable_bit), + clk->enable_reg); +} + +static struct clk_ops sh_clk_mstp32_clk_ops = { + .enable = sh_clk_mstp32_enable, + .disable = sh_clk_mstp32_disable, + .recalc = followparent_recalc, +}; + +int __init sh_clk_mstp32_register(struct clk *clks, int nr) +{ + struct clk *clkp; + int ret = 0; + int k; + + for (k = 0; !ret && (k < nr); k++) { + clkp = clks + k; + clkp->ops = &sh_clk_mstp32_clk_ops; + ret |= clk_register(clkp); + } + + return ret; +} + +static long sh_clk_div_round_rate(struct clk *clk, unsigned long rate) +{ + return clk_rate_table_round(clk, clk->freq_table, rate); +} + +static int sh_clk_div6_divisors[64] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64 +}; + +static struct clk_div_mult_table sh_clk_div6_table = { + .divisors = sh_clk_div6_divisors, + .nr_divisors = ARRAY_SIZE(sh_clk_div6_divisors), +}; + +static unsigned long sh_clk_div6_recalc(struct clk *clk) +{ + struct clk_div_mult_table *table = &sh_clk_div6_table; + unsigned int idx; + + clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, + table, NULL); + + idx = __raw_readl(clk->enable_reg) & 0x003f; + + return clk->freq_table[idx].frequency; +} + +static int sh_clk_div6_set_rate(struct clk *clk, + unsigned long rate, int algo_id) +{ + unsigned long value; + int idx; + + idx = clk_rate_table_find(clk, clk->freq_table, rate); + if (idx < 0) + return idx; + + value = __raw_readl(clk->enable_reg); + value &= ~0x3f; + value |= idx; + __raw_writel(value, clk->enable_reg); + return 0; +} + +static int sh_clk_div6_enable(struct clk *clk) +{ + unsigned long value; + int ret; + + ret = sh_clk_div6_set_rate(clk, clk->rate, 0); + if (ret == 0) { + value = __raw_readl(clk->enable_reg); + value &= ~0x100; /* clear stop bit to enable clock */ + __raw_writel(value, clk->enable_reg); + } + return ret; +} + +static void sh_clk_div6_disable(struct clk *clk) +{ + unsigned long value; + + value = __raw_readl(clk->enable_reg); + value |= 0x100; /* stop clock */ + value |= 0x3f; /* VDIV bits must be non-zero, overwrite divider */ + __raw_writel(value, clk->enable_reg); +} + +static struct clk_ops sh_clk_div6_clk_ops = { + .recalc = sh_clk_div6_recalc, + .round_rate = sh_clk_div_round_rate, + .set_rate = sh_clk_div6_set_rate, + .enable = sh_clk_div6_enable, + .disable = sh_clk_div6_disable, +}; + +int __init sh_clk_div6_register(struct clk *clks, int nr) +{ + struct clk *clkp; + void *freq_table; + int nr_divs = sh_clk_div6_table.nr_divisors; + int freq_table_size = sizeof(struct cpufreq_frequency_table); + int ret = 0; + int k; + + freq_table_size *= (nr_divs + 1); + freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL); + if (!freq_table) { + pr_err("sh_clk_div6_register: unable to alloc memory\n"); + return -ENOMEM; + } + + for (k = 0; !ret && (k < nr); k++) { + clkp = clks + k; + + clkp->ops = &sh_clk_div6_clk_ops; + clkp->id = -1; + clkp->freq_table = freq_table + (k * freq_table_size); + clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END; + + ret = clk_register(clkp); + } + + return ret; +} + +static unsigned long sh_clk_div4_recalc(struct clk *clk) +{ + struct clk_div4_table *d4t = clk->priv; + struct clk_div_mult_table *table = d4t->div_mult_table; + unsigned int idx; + + clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, + table, &clk->arch_flags); + + idx = (__raw_readl(clk->enable_reg) >> clk->enable_bit) & 0x000f; + + return clk->freq_table[idx].frequency; +} + +static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent) +{ + struct clk_div4_table *d4t = clk->priv; + struct clk_div_mult_table *table = d4t->div_mult_table; + u32 value; + int ret; + + /* we really need a better way to determine parent index, but for + * now assume internal parent comes with CLK_ENABLE_ON_INIT set, + * no CLK_ENABLE_ON_INIT means external clock... + */ + + if (parent->flags & CLK_ENABLE_ON_INIT) + value = __raw_readl(clk->enable_reg) & ~(1 << 7); + else + value = __raw_readl(clk->enable_reg) | (1 << 7); + + ret = clk_reparent(clk, parent); + if (ret < 0) + return ret; + + __raw_writel(value, clk->enable_reg); + + /* Rebiuld the frequency table */ + clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, + table, &clk->arch_flags); + + return 0; +} + +static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate, int algo_id) +{ + struct clk_div4_table *d4t = clk->priv; + unsigned long value; + int idx = clk_rate_table_find(clk, clk->freq_table, rate); + if (idx < 0) + return idx; + + value = __raw_readl(clk->enable_reg); + value &= ~(0xf << clk->enable_bit); + value |= (idx << clk->enable_bit); + __raw_writel(value, clk->enable_reg); + + if (d4t->kick) + d4t->kick(clk); + + return 0; +} + +static int sh_clk_div4_enable(struct clk *clk) +{ + __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << 8), clk->enable_reg); + return 0; +} + +static void sh_clk_div4_disable(struct clk *clk) +{ + __raw_writel(__raw_readl(clk->enable_reg) | (1 << 8), clk->enable_reg); +} + +static struct clk_ops sh_clk_div4_clk_ops = { + .recalc = sh_clk_div4_recalc, + .set_rate = sh_clk_div4_set_rate, + .round_rate = sh_clk_div_round_rate, +}; + +static struct clk_ops sh_clk_div4_enable_clk_ops = { + .recalc = sh_clk_div4_recalc, + .set_rate = sh_clk_div4_set_rate, + .round_rate = sh_clk_div_round_rate, + .enable = sh_clk_div4_enable, + .disable = sh_clk_div4_disable, +}; + +static struct clk_ops sh_clk_div4_reparent_clk_ops = { + .recalc = sh_clk_div4_recalc, + .set_rate = sh_clk_div4_set_rate, + .round_rate = sh_clk_div_round_rate, + .enable = sh_clk_div4_enable, + .disable = sh_clk_div4_disable, + .set_parent = sh_clk_div4_set_parent, +}; + +static int __init sh_clk_div4_register_ops(struct clk *clks, int nr, + struct clk_div4_table *table, struct clk_ops *ops) +{ + struct clk *clkp; + void *freq_table; + int nr_divs = table->div_mult_table->nr_divisors; + int freq_table_size = sizeof(struct cpufreq_frequency_table); + int ret = 0; + int k; + + freq_table_size *= (nr_divs + 1); + freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL); + if (!freq_table) { + pr_err("sh_clk_div4_register: unable to alloc memory\n"); + return -ENOMEM; + } + + for (k = 0; !ret && (k < nr); k++) { + clkp = clks + k; + + clkp->ops = ops; + clkp->id = -1; + clkp->priv = table; + + clkp->freq_table = freq_table + (k * freq_table_size); + clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END; + + ret = clk_register(clkp); + } + + return ret; +} + +int __init sh_clk_div4_register(struct clk *clks, int nr, + struct clk_div4_table *table) +{ + return sh_clk_div4_register_ops(clks, nr, table, &sh_clk_div4_clk_ops); +} + +int __init sh_clk_div4_enable_register(struct clk *clks, int nr, + struct clk_div4_table *table) +{ + return sh_clk_div4_register_ops(clks, nr, table, + &sh_clk_div4_enable_clk_ops); +} + +int __init sh_clk_div4_reparent_register(struct clk *clks, int nr, + struct clk_div4_table *table) +{ + return sh_clk_div4_register_ops(clks, nr, table, + &sh_clk_div4_reparent_clk_ops); +} -- cgit v0.10.2 From 103058536300f80ec54f2a8c9209d066925416fd Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 13 May 2010 01:08:33 +0000 Subject: sh: Check return value of clk_get on ecovec24 Signed-off-by: Kuninori Morimoto Signed-off-by: Paul Mundt diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c index 1850c08..62123885 100644 --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c @@ -1136,16 +1136,20 @@ static int __init arch_setup(void) /* set SPU2 clock to 83.4 MHz */ clk = clk_get(NULL, "spu_clk"); - clk_set_rate(clk, clk_round_rate(clk, 83333333)); - clk_put(clk); + if (clk) { + clk_set_rate(clk, clk_round_rate(clk, 83333333)); + clk_put(clk); + } /* change parent of FSI B */ clk = clk_get(NULL, "fsib_clk"); - clk_register(&fsimckb_clk); - clk_set_parent(clk, &fsimckb_clk); - clk_set_rate(clk, 11000); - clk_set_rate(&fsimckb_clk, 11000); - clk_put(clk); + if (clk) { + clk_register(&fsimckb_clk); + clk_set_parent(clk, &fsimckb_clk); + clk_set_rate(clk, 11000); + clk_set_rate(&fsimckb_clk, 11000); + clk_put(clk); + } gpio_request(GPIO_PTU0, NULL); gpio_direction_output(GPIO_PTU0, 0); @@ -1157,8 +1161,10 @@ static int __init arch_setup(void) /* set VPU clock to 166 MHz */ clk = clk_get(NULL, "vpu_clk"); - clk_set_rate(clk, clk_round_rate(clk, 166000000)); - clk_put(clk); + if (clk) { + clk_set_rate(clk, clk_round_rate(clk, 166000000)); + clk_put(clk); + } /* enable IrDA */ gpio_request(GPIO_FN_IRDA_OUT, NULL); -- cgit v0.10.2 From 03c5ecd13cfe308a521e40e6dec6059314f3341b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 13 May 2010 01:08:37 +0000 Subject: sh: Check return value of clk_get on ms7724 Signed-off-by: Kuninori Morimoto Signed-off-by: Paul Mundt diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c index 20b6053..e74ae7b 100644 --- a/arch/sh/boards/mach-se/7724/setup.c +++ b/arch/sh/boards/mach-se/7724/setup.c @@ -769,16 +769,20 @@ static int __init devices_setup(void) /* set SPU2 clock to 83.4 MHz */ clk = clk_get(NULL, "spu_clk"); - clk_set_rate(clk, clk_round_rate(clk, 83333333)); - clk_put(clk); + if (clk) { + clk_set_rate(clk, clk_round_rate(clk, 83333333)); + clk_put(clk); + } /* change parent of FSI A */ clk = clk_get(NULL, "fsia_clk"); - clk_register(&fsimcka_clk); - clk_set_parent(clk, &fsimcka_clk); - clk_set_rate(clk, 11000); - clk_set_rate(&fsimcka_clk, 11000); - clk_put(clk); + if (clk) { + clk_register(&fsimcka_clk); + clk_set_parent(clk, &fsimcka_clk); + clk_set_rate(clk, 11000); + clk_set_rate(&fsimcka_clk, 11000); + clk_put(clk); + } /* SDHI0 connected to cn7 */ gpio_request(GPIO_FN_SDHI0CD, NULL); -- cgit v0.10.2 From f5ca6d4cbd49dbb6e179a71fa610eb321a3e9951 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 4 May 2010 14:15:09 +0000 Subject: sh: simplify WARN usage in SH clock driver Signed-off-by: Guennadi Liakhovetski Signed-off-by: Paul Mundt diff --git a/drivers/sh/clk.c b/drivers/sh/clk.c index c90a3e1..5d84ada 100644 --- a/drivers/sh/clk.c +++ b/drivers/sh/clk.c @@ -160,12 +160,9 @@ void propagate_rate(struct clk *tclk) static void __clk_disable(struct clk *clk) { - if (clk->usecount == 0) { - printk(KERN_ERR "Trying disable clock %s with 0 usecount\n", - clk->name); - WARN_ON(1); + if (WARN(!clk->usecount, "Trying to disable clock %s with 0 usecount\n", + clk->name)) return; - } if (!(--clk->usecount)) { if (likely(clk->ops && clk->ops->disable)) -- cgit v0.10.2 From e1733d2c397476c245a681ba0b54c88858b7a0be Mon Sep 17 00:00:00 2001 From: "Steven J. Magnani" Date: Tue, 27 Apr 2010 13:00:35 -0500 Subject: microblaze: export assembly functions used by modules Modules that use copy_{to,from}_user(), memcpy(), and memset() fail to build in certain circumstances. Signed-off-by: Steven J. Magnani Signed-off-by: Michal Simek diff --git a/arch/microblaze/kernel/microblaze_ksyms.c b/arch/microblaze/kernel/microblaze_ksyms.c index bc4dcb7..ecfb852 100644 --- a/arch/microblaze/kernel/microblaze_ksyms.c +++ b/arch/microblaze/kernel/microblaze_ksyms.c @@ -52,3 +52,13 @@ EXPORT_SYMBOL_GPL(_ebss); extern void _mcount(void); EXPORT_SYMBOL(_mcount); #endif + +/* + * Assembly functions that may be used (directly or indirectly) by modules + */ +EXPORT_SYMBOL(__copy_tofrom_user); + +#ifdef CONFIG_OPT_LIB_ASM +EXPORT_SYMBOL(memcpy); +EXPORT_SYMBOL(memmove); +#endif -- cgit v0.10.2 From ddfbc935eae68294834dc29998f93147a5422a0d Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 13 May 2010 10:55:47 +0200 Subject: microblaze: Remove compilation warnings in cache macro CC arch/microblaze/kernel/cpu/cache.o arch/microblaze/kernel/cpu/cache.c: In function '__invalidate_dcache_range_wb': arch/microblaze/kernel/cpu/cache.c:398: warning: ISO C90 forbids mixed declarations and code arch/microblaze/kernel/cpu/cache.c: In function '__flush_dcache_range_wb': arch/microblaze/kernel/cpu/cache.c:509: warning: ISO C90 forbids mixed declara Signed-off-by: Michal Simek diff --git a/arch/microblaze/kernel/cpu/cache.c b/arch/microblaze/kernel/cpu/cache.c index 21c3a92..109876e 100644 --- a/arch/microblaze/kernel/cpu/cache.c +++ b/arch/microblaze/kernel/cpu/cache.c @@ -137,8 +137,9 @@ do { \ do { \ int step = -line_length; \ int align = ~(line_length - 1); \ + int count; \ end = ((end & align) == end) ? end - line_length : end & align; \ - int count = end - start; \ + count = end - start; \ WARN_ON(count < 0); \ \ __asm__ __volatile__ (" 1: " #op " %0, %1; \ -- cgit v0.10.2 From 06fe53beb636294587d8e94ef83c06cef07c21fd Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 13 May 2010 17:56:56 +0900 Subject: driver core: Early dev_name() depends on slab_is_available(). The early dev_name() setup needs to do an allocation which can only be satisfied under slab_is_available() conditions. Some of the early platform drivers may be initialized before this point, and those still need to contend themselves with an empty dev_name. This fixes up a regression with the SH earlyprintk which was bailing out prior to hitting the early probe path due to not being able to satisfy the early allocation. Other early platform drivers (such as the early timers) that need to match the dev name are sufficiently late that allocations are already possible. Signed-off-by: Paul Mundt diff --git a/drivers/base/platform.c b/drivers/base/platform.c index f2377f3..ef51b00 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -1244,7 +1244,7 @@ static int __init early_platform_driver_probe_id(char *class_str, * dev_name() and others to be used before the * rest of the driver core is initialized. */ - if (!match->dev.init_name) { + if (!match->dev.init_name && slab_is_available()) { if (match->id != -1) match->dev.init_name = kasprintf(GFP_KERNEL, "%s.%d", -- cgit v0.10.2 From a71ba09655d197f22938fffa6f5d210ff5134f98 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 13 May 2010 18:42:25 +0900 Subject: sh: fixup the docbook paths for clock framework shuffling. Now that the definitions have been consolidated in an alternate header, update the template accordingly. Signed-off-by: Paul Mundt diff --git a/Documentation/DocBook/sh.tmpl b/Documentation/DocBook/sh.tmpl index 0c3dc4c..d858d92 100644 --- a/Documentation/DocBook/sh.tmpl +++ b/Documentation/DocBook/sh.tmpl @@ -19,13 +19,17 @@ - 2008 + 2008-2010 Paul Mundt - 2008 + 2008-2010 Renesas Technology Corp. + + 2010 + Renesas Electronics Corp. + @@ -77,7 +81,7 @@ Clock Framework Extensions -!Iarch/sh/include/asm/clock.h +!Iinclude/linux/sh_clk.h Machine Specific Interfaces diff --git a/include/linux/sh_clk.h b/include/linux/sh_clk.h index 6d7de242..1636d1e 100644 --- a/include/linux/sh_clk.h +++ b/include/linux/sh_clk.h @@ -46,7 +46,7 @@ struct clk { #define CLK_ENABLE_ON_INIT (1 << 0) -/* arch/sh/kernel/cpu/clock.c */ +/* drivers/sh/clk.c */ unsigned long followparent_recalc(struct clk *); void recalculate_root_clocks(void); void propagate_rate(struct clk *); @@ -55,7 +55,6 @@ int clk_register(struct clk *); void clk_unregister(struct clk *); void clk_enable_init_clocks(void); -/* the exported API, in addition to clk_set_rate */ /** * clk_set_rate_ex - set the clock rate for a clock source, with additional parameter * @clk: clock source -- cgit v0.10.2 From 1ce2470aa544a0aa37b575c45cba366770860af7 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 13 May 2010 12:09:54 +0200 Subject: microblaze: Remove powerpc code from Microblaze port Remove eeh_add_device_tree_late which is powerpc specific code. Signed-off-by: Michal Simek diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c index 01c8c97..9cb782b 100644 --- a/arch/microblaze/pci/pci-common.c +++ b/arch/microblaze/pci/pci-common.c @@ -1507,7 +1507,7 @@ void pcibios_finish_adding_to_bus(struct pci_bus *bus) pci_bus_add_devices(bus); /* Fixup EEH */ - eeh_add_device_tree_late(bus); + /* eeh_add_device_tree_late(bus); */ } EXPORT_SYMBOL_GPL(pcibios_finish_adding_to_bus); -- cgit v0.10.2 From ee4bcdf1d248c4ebe5f73e11631c3bd3f76d777b Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Thu, 13 May 2010 12:11:42 +0200 Subject: microblaze: export assembly functions used by modules Export __strncpy_user, memory_size, ioremap_bot for modules. Signed-off-by: Michal Simek diff --git a/arch/microblaze/kernel/microblaze_ksyms.c b/arch/microblaze/kernel/microblaze_ksyms.c index ecfb852..ff85f77 100644 --- a/arch/microblaze/kernel/microblaze_ksyms.c +++ b/arch/microblaze/kernel/microblaze_ksyms.c @@ -57,6 +57,7 @@ EXPORT_SYMBOL(_mcount); * Assembly functions that may be used (directly or indirectly) by modules */ EXPORT_SYMBOL(__copy_tofrom_user); +EXPORT_SYMBOL(__strncpy_user); #ifdef CONFIG_OPT_LIB_ASM EXPORT_SYMBOL(memcpy); diff --git a/arch/microblaze/mm/init.c b/arch/microblaze/mm/init.c index f42c2dd..cca3579 100644 --- a/arch/microblaze/mm/init.c +++ b/arch/microblaze/mm/init.c @@ -47,6 +47,7 @@ unsigned long memory_start; EXPORT_SYMBOL(memory_start); unsigned long memory_end; /* due to mm/nommu.c */ unsigned long memory_size; +EXPORT_SYMBOL(memory_size); /* * paging_init() sets up the page tables - in fact we've already done this. diff --git a/arch/microblaze/mm/pgtable.c b/arch/microblaze/mm/pgtable.c index 784557f..59bf233 100644 --- a/arch/microblaze/mm/pgtable.c +++ b/arch/microblaze/mm/pgtable.c @@ -42,6 +42,7 @@ unsigned long ioremap_base; unsigned long ioremap_bot; +EXPORT_SYMBOL(ioremap_bot); /* The maximum lowmem defaults to 768Mb, but this can be configured to * another value. -- cgit v0.10.2 From 5051d411ec87381693433d24c4488b2fa4a6306c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 2 Apr 2010 13:08:39 +0100 Subject: mfd: Clean up after WM83xx AUXADC interrupt if it arrives late In certain circumstances, especially under heavy load, the AUXADC completion interrupt may be detected after we've timed out waiting for it. That conversion would still succeed but the next conversion will see the completion that was signalled by the interrupt for the previous conversion and therefore not wait for the AUXADC conversion to run, causing it to report failure. Provide a simple, non-invasive cleanup by using try_wait_for_completion() to ensure that the completion is not signalled before we wait. Since the AUXADC is run within a mutex we know there can only have been at most one AUXADC interrupt outstanding. A more involved change should follow for the next merge window. Signed-off-by: Mark Brown Signed-off-by: Samuel Ortiz diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index a3d5728..f2ab025 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c @@ -349,6 +349,9 @@ int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input) goto disable; } + /* If an interrupt arrived late clean up after it */ + try_wait_for_completion(&wm831x->auxadc_done); + /* Ignore the result to allow us to soldier on without IRQ hookup */ wait_for_completion_timeout(&wm831x->auxadc_done, msecs_to_jiffies(5)); diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c index e400a3b..b580748 100644 --- a/drivers/mfd/wm8350-core.c +++ b/drivers/mfd/wm8350-core.c @@ -363,6 +363,10 @@ int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref) reg |= 1 << channel | WM8350_AUXADC_POLL; wm8350_reg_write(wm8350, WM8350_DIGITISER_CONTROL_1, reg); + /* If a late IRQ left the completion signalled then consume + * the completion. */ + try_wait_for_completion(&wm8350->auxadc_done); + /* We ignore the result of the completion and just check for a * conversion result, allowing us to soldier on if the IRQ * infrastructure is not set up for the chip. */ -- cgit v0.10.2 From 4fec9978822a66b25f5645eb20c115034a18cfd1 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Tue, 11 May 2010 15:34:54 +0100 Subject: ARM: 6124/1: ep93xx: SPI driver platform support code This patch adds platform side support code for the EP93xx SPI driver. This includes clock, resources and muxing. There is a new function: ep93xx_register_spi() which can be used by board support code to register new SPI devices for the board. This patch depends on patch 5998/1 ep93xx: added chip revision reading function Cc: Ryan Mallon Cc: David Brownell Cc: Grant Likely Signed-off-by: Mika Westerberg Acked-by: H Hartley Sweeten Acked-by: Martin Guy Signed-off-by: Russell King diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c index 5f80092..e29bdef 100644 --- a/arch/arm/mach-ep93xx/clock.c +++ b/arch/arm/mach-ep93xx/clock.c @@ -96,6 +96,10 @@ static struct clk clk_keypad = { .enable_mask = EP93XX_SYSCON_KEYTCHCLKDIV_KEN, .set_rate = set_keytchclk_rate, }; +static struct clk clk_spi = { + .parent = &clk_xtali, + .rate = EP93XX_EXT_CLK_RATE, +}; static struct clk clk_pwm = { .parent = &clk_xtali, .rate = EP93XX_EXT_CLK_RATE, @@ -186,6 +190,7 @@ static struct clk_lookup clocks[] = { INIT_CK("ep93xx-ohci", NULL, &clk_usb_host), INIT_CK("ep93xx-keypad", NULL, &clk_keypad), INIT_CK("ep93xx-fb", NULL, &clk_video), + INIT_CK("ep93xx-spi.0", NULL, &clk_spi), INIT_CK(NULL, "pwm_clk", &clk_pwm), INIT_CK(NULL, "m2p0", &clk_m2p0), INIT_CK(NULL, "m2p1", &clk_m2p1), @@ -473,6 +478,14 @@ static int __init ep93xx_clock_init(void) /* Initialize the pll2 derived clocks */ clk_usb_host.rate = clk_pll2.rate / (((value >> 28) & 0xf) + 1); + /* + * EP93xx SSP clock rate was doubled in version E2. For more information + * see: + * http://www.cirrus.com/en/pubs/appNote/AN273REV4.pdf + */ + if (ep93xx_chip_revision() < EP93XX_CHIP_REV_E2) + clk_spi.rate /= 2; + pr_info("PLL1 running at %ld MHz, PLL2 at %ld MHz\n", clk_pll1.rate / 1000000, clk_pll2.rate / 1000000); pr_info("FCLK %ld MHz, HCLK %ld MHz, PCLK %ld MHz\n", diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 8d3f77e..9092677 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -31,10 +31,12 @@ #include #include #include +#include #include #include #include +#include #include #include @@ -430,6 +432,56 @@ void __init ep93xx_register_i2c(struct i2c_gpio_platform_data *data, platform_device_register(&ep93xx_i2c_device); } +/************************************************************************* + * EP93xx SPI peripheral handling + *************************************************************************/ +static struct ep93xx_spi_info ep93xx_spi_master_data; + +static struct resource ep93xx_spi_resources[] = { + { + .start = EP93XX_SPI_PHYS_BASE, + .end = EP93XX_SPI_PHYS_BASE + 0x18 - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_EP93XX_SSP, + .end = IRQ_EP93XX_SSP, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device ep93xx_spi_device = { + .name = "ep93xx-spi", + .id = 0, + .dev = { + .platform_data = &ep93xx_spi_master_data, + }, + .num_resources = ARRAY_SIZE(ep93xx_spi_resources), + .resource = ep93xx_spi_resources, +}; + +/** + * ep93xx_register_spi() - registers spi platform device + * @info: ep93xx board specific spi master info (__initdata) + * @devices: SPI devices to register (__initdata) + * @num: number of SPI devices to register + * + * This function registers platform device for the EP93xx SPI controller and + * also makes sure that SPI pins are muxed so that I2S is not using those pins. + */ +void __init ep93xx_register_spi(struct ep93xx_spi_info *info, + struct spi_board_info *devices, int num) +{ + /* + * When SPI is used, we need to make sure that I2S is muxed off from + * SPI pins. + */ + ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2SONSSP); + + ep93xx_spi_master_data = *info; + spi_register_board_info(devices, num); + platform_device_register(&ep93xx_spi_device); +} /************************************************************************* * EP93xx LEDs diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h index 93e2ecc..b1e096f 100644 --- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h +++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h @@ -106,6 +106,7 @@ #define EP93XX_AAC_BASE EP93XX_APB_IOMEM(0x00080000) +#define EP93XX_SPI_PHYS_BASE EP93XX_APB_PHYS(0x000a0000) #define EP93XX_SPI_BASE EP93XX_APB_IOMEM(0x000a0000) #define EP93XX_IRDA_BASE EP93XX_APB_IOMEM(0x000b0000) diff --git a/arch/arm/mach-ep93xx/include/mach/platform.h b/arch/arm/mach-ep93xx/include/mach/platform.h index b663390..9a4413d 100644 --- a/arch/arm/mach-ep93xx/include/mach/platform.h +++ b/arch/arm/mach-ep93xx/include/mach/platform.h @@ -6,9 +6,11 @@ struct i2c_gpio_platform_data; struct i2c_board_info; +struct spi_board_info; struct platform_device; struct ep93xxfb_mach_info; struct ep93xx_keypad_platform_data; +struct ep93xx_spi_info; struct ep93xx_eth_data { @@ -44,6 +46,8 @@ unsigned int ep93xx_chip_revision(void); void ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr); void ep93xx_register_i2c(struct i2c_gpio_platform_data *data, struct i2c_board_info *devices, int num); +void ep93xx_register_spi(struct ep93xx_spi_info *info, + struct spi_board_info *devices, int num); void ep93xx_register_fb(struct ep93xxfb_mach_info *data); void ep93xx_register_pwm(int pwm0, int pwm1); int ep93xx_pwm_acquire_gpio(struct platform_device *pdev); -- cgit v0.10.2 From 2a847513cdecd517f7efc06296c539c3a936cf98 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 7 May 2010 10:03:02 +0100 Subject: ARM: 6107/1: plat-nomadik: use the MTU clocksrc for sched_clock This provides some serious scheduling for the Nomadik family by introducing a sched_clock() using the MTU clock source in the same manner as e.g. OMAP or U300. This type of solutions has been discussed at no end in the past, however we need this resolution for making measurements and using HRTimers. Signed-off-by: Linus Walleij Signed-off-by: Russell King diff --git a/arch/arm/plat-nomadik/timer.c b/arch/arm/plat-nomadik/timer.c index db67402..0ff3798 100644 --- a/arch/arm/plat-nomadik/timer.c +++ b/arch/arm/plat-nomadik/timer.c @@ -20,6 +20,15 @@ void __iomem *mtu_base; /* ssigned by machine code */ +/* + * Kernel assumes that sched_clock can be called early + * but the MTU may not yet be initialized. + */ +static cycle_t nmdk_read_timer_dummy(struct clocksource *cs) +{ + return 0; +} + /* clocksource: MTU decrements, so we negate the value being read. */ static cycle_t nmdk_read_timer(struct clocksource *cs) { @@ -29,12 +38,27 @@ static cycle_t nmdk_read_timer(struct clocksource *cs) static struct clocksource nmdk_clksrc = { .name = "mtu_0", .rating = 200, - .read = nmdk_read_timer, + .read = nmdk_read_timer_dummy, .mask = CLOCKSOURCE_MASK(32), .shift = 20, .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; +/* + * Override the global weak sched_clock symbol with this + * local implementation which uses the clocksource to get some + * better resolution when scheduling the kernel. We accept that + * this wraps around for now, since it is just a relative time + * stamp. (Inspired by OMAP implementation.) + */ +unsigned long long notrace sched_clock(void) +{ + return clocksource_cyc2ns(nmdk_clksrc.read( + &nmdk_clksrc), + nmdk_clksrc.mult, + nmdk_clksrc.shift); +} + /* Clockevent device: use one-shot mode */ static void nmdk_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev) @@ -121,6 +145,8 @@ void __init nmdk_timer_init(void) writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(0)); nmdk_clksrc.mult = clocksource_hz2mult(rate, nmdk_clksrc.shift); + /* Now the scheduling clock is ready */ + nmdk_clksrc.read = nmdk_read_timer; if (clocksource_register(&nmdk_clksrc)) pr_err("timer: failed to initialize clock source %s\n", -- cgit v0.10.2 From 002baeecf53677d2034113e34197ec221f42e037 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Thu, 13 May 2010 12:52:57 +0200 Subject: vfs: Fix O_NOFOLLOW behavior for paths with trailing slashes According to specification mkdir d; ln -s d a; open("a/", O_NOFOLLOW | O_RDONLY) should return success but currently it returns ELOOP. This is a regression caused by path lookup cleanup patch series. Fix the code to ignore O_NOFOLLOW in case the provided path has trailing slashes. Cc: Andrew Morton Cc: Al Viro Reported-by: Marius Tolzmann Acked-by: Miklos Szeredi Signed-off-by: Jan Kara Signed-off-by: Linus Torvalds diff --git a/fs/namei.c b/fs/namei.c index a7dce91..16df7277 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1641,7 +1641,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path, if (nd->last.name[nd->last.len]) { if (open_flag & O_CREAT) goto exit; - nd->flags |= LOOKUP_DIRECTORY; + nd->flags |= LOOKUP_DIRECTORY | LOOKUP_FOLLOW; } /* just plain open? */ @@ -1830,6 +1830,8 @@ reval: } if (open_flag & O_DIRECTORY) nd.flags |= LOOKUP_DIRECTORY; + if (!(open_flag & O_NOFOLLOW)) + nd.flags |= LOOKUP_FOLLOW; filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname); while (unlikely(!filp)) { /* trailing symlink */ struct path holder; @@ -1837,7 +1839,7 @@ reval: void *cookie; error = -ELOOP; /* S_ISDIR part is a temporary automount kludge */ - if ((open_flag & O_NOFOLLOW) && !S_ISDIR(inode->i_mode)) + if (!(nd.flags & LOOKUP_FOLLOW) && !S_ISDIR(inode->i_mode)) goto exit_dput; if (count++ == 32) goto exit_dput; -- cgit v0.10.2 From d78a9494fe8b63e2ec1e2284e45a8d709c4d02c0 Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Mon, 10 May 2010 12:41:18 +0530 Subject: davinci: edma: use BIT() wherever possible This patch replaces occurences of (1 << x) with BIT(x) as it makes for much better reading. Signed-off-by: Sekhar Nori Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/dma.c b/arch/arm/mach-davinci/dma.c index cc5fcda..1922d46 100644 --- a/arch/arm/mach-davinci/dma.c +++ b/arch/arm/mach-davinci/dma.c @@ -312,16 +312,16 @@ setup_dma_interrupt(unsigned lch, if (!callback) edma_shadow0_write_array(ctlr, SH_IECR, lch >> 5, - (1 << (lch & 0x1f))); + BIT(lch & 0x1f)); edma_cc[ctlr]->intr_data[lch].callback = callback; edma_cc[ctlr]->intr_data[lch].data = data; if (callback) { edma_shadow0_write_array(ctlr, SH_ICR, lch >> 5, - (1 << (lch & 0x1f))); + BIT(lch & 0x1f)); edma_shadow0_write_array(ctlr, SH_IESR, lch >> 5, - (1 << (lch & 0x1f))); + BIT(lch & 0x1f)); } } @@ -374,7 +374,7 @@ static irqreturn_t dma_irq_handler(int irq, void *data) SH_IER, j) & BIT(i))) { /* Clear the corresponding IPR bits */ edma_shadow0_write_array(ctlr, SH_ICR, j, - (1 << i)); + BIT(i)); if (edma_cc[ctlr]->intr_data[k].callback) edma_cc[ctlr]->intr_data[k].callback( k, DMA_COMPLETE, @@ -423,13 +423,13 @@ static irqreturn_t dma_ccerr_handler(int irq, void *data) for (i = 0; i < 32; i++) { int k = (j << 5) + i; if (edma_read_array(ctlr, EDMA_EMR, j) & - (1 << i)) { + BIT(i)) { /* Clear the corresponding EMR bits */ edma_write_array(ctlr, EDMA_EMCR, j, - 1 << i); + BIT(i)); /* Clear any SER */ edma_shadow0_write_array(ctlr, SH_SECR, - j, (1 << i)); + j, BIT(i)); if (edma_cc[ctlr]->intr_data[k]. callback) { edma_cc[ctlr]->intr_data[k]. @@ -444,11 +444,11 @@ static irqreturn_t dma_ccerr_handler(int irq, void *data) dev_dbg(data, "QEMR %02x\n", edma_read(ctlr, EDMA_QEMR)); for (i = 0; i < 8; i++) { - if (edma_read(ctlr, EDMA_QEMR) & (1 << i)) { + if (edma_read(ctlr, EDMA_QEMR) & BIT(i)) { /* Clear the corresponding IPR bits */ - edma_write(ctlr, EDMA_QEMCR, 1 << i); + edma_write(ctlr, EDMA_QEMCR, BIT(i)); edma_shadow0_write(ctlr, SH_QSECR, - (1 << i)); + BIT(i)); /* NOTE: not reported!! */ } @@ -460,9 +460,9 @@ static irqreturn_t dma_ccerr_handler(int irq, void *data) * to just write CCERRCLR with CCERR value... */ for (i = 0; i < 8; i++) { - if (edma_read(ctlr, EDMA_CCERR) & (1 << i)) { + if (edma_read(ctlr, EDMA_CCERR) & BIT(i)) { /* Clear the corresponding IPR bits */ - edma_write(ctlr, EDMA_CCERRCLR, 1 << i); + edma_write(ctlr, EDMA_CCERRCLR, BIT(i)); /* NOTE: not reported!! */ } @@ -666,7 +666,7 @@ int edma_alloc_channel(int channel, } /* ensure access through shadow region 0 */ - edma_or_array2(ctlr, EDMA_DRAE, 0, channel >> 5, 1 << (channel & 0x1f)); + edma_or_array2(ctlr, EDMA_DRAE, 0, channel >> 5, BIT(channel & 0x1f)); /* ensure no events are pending */ edma_stop(EDMA_CTLR_CHAN(ctlr, channel)); @@ -1204,7 +1204,7 @@ void edma_pause(unsigned channel) channel = EDMA_CHAN_SLOT(channel); if (channel < edma_cc[ctlr]->num_channels) { - unsigned int mask = (1 << (channel & 0x1f)); + unsigned int mask = BIT(channel & 0x1f); edma_shadow0_write_array(ctlr, SH_EECR, channel >> 5, mask); } @@ -1225,7 +1225,7 @@ void edma_resume(unsigned channel) channel = EDMA_CHAN_SLOT(channel); if (channel < edma_cc[ctlr]->num_channels) { - unsigned int mask = (1 << (channel & 0x1f)); + unsigned int mask = BIT(channel & 0x1f); edma_shadow0_write_array(ctlr, SH_EESR, channel >> 5, mask); } @@ -1252,7 +1252,7 @@ int edma_start(unsigned channel) if (channel < edma_cc[ctlr]->num_channels) { int j = channel >> 5; - unsigned int mask = (1 << (channel & 0x1f)); + unsigned int mask = BIT(channel & 0x1f); /* EDMA channels without event association */ if (test_bit(channel, edma_cc[ctlr]->edma_unused)) { @@ -1298,7 +1298,7 @@ void edma_stop(unsigned channel) if (channel < edma_cc[ctlr]->num_channels) { int j = channel >> 5; - unsigned int mask = (1 << (channel & 0x1f)); + unsigned int mask = BIT(channel & 0x1f); edma_shadow0_write_array(ctlr, SH_EECR, j, mask); edma_shadow0_write_array(ctlr, SH_ECR, j, mask); @@ -1337,7 +1337,7 @@ void edma_clean_channel(unsigned channel) if (channel < edma_cc[ctlr]->num_channels) { int j = (channel >> 5); - unsigned int mask = 1 << (channel & 0x1f); + unsigned int mask = BIT(channel & 0x1f); pr_debug("EDMA: EMR%d %08x\n", j, edma_read_array(ctlr, EDMA_EMR, j)); @@ -1346,7 +1346,7 @@ void edma_clean_channel(unsigned channel) edma_write_array(ctlr, EDMA_EMCR, j, mask); /* Clear any SER */ edma_shadow0_write_array(ctlr, SH_SECR, j, mask); - edma_write(ctlr, EDMA_CCERRCLR, (1 << 16) | 0x3); + edma_write(ctlr, EDMA_CCERRCLR, BIT(16) | BIT(1) | BIT(0)); } } EXPORT_SYMBOL(edma_clean_channel); @@ -1366,9 +1366,9 @@ void edma_clear_event(unsigned channel) if (channel >= edma_cc[ctlr]->num_channels) return; if (channel < 32) - edma_write(ctlr, EDMA_ECR, 1 << channel); + edma_write(ctlr, EDMA_ECR, BIT(channel)); else - edma_write(ctlr, EDMA_ECRH, 1 << (channel - 32)); + edma_write(ctlr, EDMA_ECRH, BIT(channel - 32)); } EXPORT_SYMBOL(edma_clear_event); -- cgit v0.10.2 From a6374f53405b719c767c6318fe052a6d8f32cd89 Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Mon, 10 May 2010 12:41:19 +0530 Subject: davinci: edma: fix coding style issue related to breaking lines In the edma driver, most of the long lines in 'if condition' are broken after the logical operator '&&' except two instances. This patch fixes that to bring consistency across the file. Signed-off-by: Sekhar Nori Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/dma.c b/arch/arm/mach-davinci/dma.c index 1922d46..d33827a 100644 --- a/arch/arm/mach-davinci/dma.c +++ b/arch/arm/mach-davinci/dma.c @@ -351,8 +351,8 @@ static irqreturn_t dma_irq_handler(int irq, void *data) dev_dbg(data, "dma_irq_handler\n"); - if ((edma_shadow0_read_array(ctlr, SH_IPR, 0) == 0) - && (edma_shadow0_read_array(ctlr, SH_IPR, 1) == 0)) + if ((edma_shadow0_read_array(ctlr, SH_IPR, 0) == 0) && + (edma_shadow0_read_array(ctlr, SH_IPR, 1) == 0)) return IRQ_NONE; while (1) { @@ -468,10 +468,10 @@ static irqreturn_t dma_ccerr_handler(int irq, void *data) } } } - if ((edma_read_array(ctlr, EDMA_EMR, 0) == 0) - && (edma_read_array(ctlr, EDMA_EMR, 1) == 0) - && (edma_read(ctlr, EDMA_QEMR) == 0) - && (edma_read(ctlr, EDMA_CCERR) == 0)) + if ((edma_read_array(ctlr, EDMA_EMR, 0) == 0) && + (edma_read_array(ctlr, EDMA_EMR, 1) == 0) && + (edma_read(ctlr, EDMA_QEMR) == 0) && + (edma_read(ctlr, EDMA_CCERR) == 0)) break; cnt++; if (cnt > 10) -- cgit v0.10.2 From b8d44293952e4b32b8595d924a377351f3cd1565 Mon Sep 17 00:00:00 2001 From: Cyril Chemparathy Date: Fri, 7 May 2010 17:06:32 -0400 Subject: Davinci: gpio - use ioremap() This patch modifies the gpio_base definition in davinci_soc_info to be a physical address, which is then ioremap()ed by the gpio initialization function. Signed-off-by: Cyril Chemparathy Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c index 83879f8..4f5727f 100644 --- a/arch/arm/mach-davinci/da830.c +++ b/arch/arm/mach-davinci/da830.c @@ -1201,7 +1201,7 @@ static struct davinci_soc_info davinci_soc_info_da830 = { .intc_irq_num = DA830_N_CP_INTC_IRQ, .timer_info = &da830_timer_info, .gpio_type = GPIO_TYPE_DAVINCI, - .gpio_base = IO_ADDRESS(DA8XX_GPIO_BASE), + .gpio_base = DA8XX_GPIO_BASE, .gpio_num = 128, .gpio_irq = IRQ_DA8XX_GPIO0, .serial_dev = &da8xx_serial_device, diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c index 2b6dd59..cb7f663 100644 --- a/arch/arm/mach-davinci/da850.c +++ b/arch/arm/mach-davinci/da850.c @@ -1086,7 +1086,7 @@ static struct davinci_soc_info davinci_soc_info_da850 = { .intc_irq_num = DA850_N_CP_INTC_IRQ, .timer_info = &da850_timer_info, .gpio_type = GPIO_TYPE_DAVINCI, - .gpio_base = IO_ADDRESS(DA8XX_GPIO_BASE), + .gpio_base = DA8XX_GPIO_BASE, .gpio_num = 144, .gpio_irq = IRQ_DA8XX_GPIO0, .serial_dev = &da8xx_serial_device, diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c index 0c62a68..277041d 100644 --- a/arch/arm/mach-davinci/dm355.c +++ b/arch/arm/mach-davinci/dm355.c @@ -855,7 +855,7 @@ static struct davinci_soc_info davinci_soc_info_dm355 = { .intc_irq_num = DAVINCI_N_AINTC_IRQ, .timer_info = &dm355_timer_info, .gpio_type = GPIO_TYPE_DAVINCI, - .gpio_base = IO_ADDRESS(DAVINCI_GPIO_BASE), + .gpio_base = DAVINCI_GPIO_BASE, .gpio_num = 104, .gpio_irq = IRQ_DM355_GPIOBNK0, .serial_dev = &dm355_serial_device, diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index ed76450..ecdbc67 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -1060,7 +1060,7 @@ static struct davinci_soc_info davinci_soc_info_dm365 = { .intc_irq_num = DAVINCI_N_AINTC_IRQ, .timer_info = &dm365_timer_info, .gpio_type = GPIO_TYPE_DAVINCI, - .gpio_base = IO_ADDRESS(DAVINCI_GPIO_BASE), + .gpio_base = DAVINCI_GPIO_BASE, .gpio_num = 104, .gpio_irq = IRQ_DM365_GPIO0, .gpio_unbanked = 8, /* really 16 ... skip muxed GPIOs */ diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index 7f36c22..beb315c 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c @@ -746,7 +746,7 @@ static struct davinci_soc_info davinci_soc_info_dm644x = { .intc_irq_num = DAVINCI_N_AINTC_IRQ, .timer_info = &dm644x_timer_info, .gpio_type = GPIO_TYPE_DAVINCI, - .gpio_base = IO_ADDRESS(DAVINCI_GPIO_BASE), + .gpio_base = DAVINCI_GPIO_BASE, .gpio_num = 71, .gpio_irq = IRQ_GPIOBNK0, .serial_dev = &dm644x_serial_device, diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index 8dd0afe..95fc981e 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -830,7 +830,7 @@ static struct davinci_soc_info davinci_soc_info_dm646x = { .intc_irq_num = DAVINCI_N_AINTC_IRQ, .timer_info = &dm646x_timer_info, .gpio_type = GPIO_TYPE_DAVINCI, - .gpio_base = IO_ADDRESS(DAVINCI_GPIO_BASE), + .gpio_base = DAVINCI_GPIO_BASE, .gpio_num = 43, /* Only 33 usable */ .gpio_irq = IRQ_DM646X_GPIOBNK0, .serial_dev = &dm646x_serial_device, diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c index 2efb446..bf0ff58 100644 --- a/arch/arm/mach-davinci/gpio.c +++ b/arch/arm/mach-davinci/gpio.c @@ -37,22 +37,22 @@ struct davinci_gpio_regs { container_of(chip, struct davinci_gpio_controller, chip) static struct davinci_gpio_controller chips[DIV_ROUND_UP(DAVINCI_N_GPIO, 32)]; +static void __iomem *gpio_base; static struct davinci_gpio_regs __iomem __init *gpio2regs(unsigned gpio) { void __iomem *ptr; - void __iomem *base = davinci_soc_info.gpio_base; if (gpio < 32 * 1) - ptr = base + 0x10; + ptr = gpio_base + 0x10; else if (gpio < 32 * 2) - ptr = base + 0x38; + ptr = gpio_base + 0x38; else if (gpio < 32 * 3) - ptr = base + 0x60; + ptr = gpio_base + 0x60; else if (gpio < 32 * 4) - ptr = base + 0x88; + ptr = gpio_base + 0x88; else if (gpio < 32 * 5) - ptr = base + 0xb0; + ptr = gpio_base + 0xb0; else ptr = NULL; return ptr; @@ -157,6 +157,10 @@ static int __init davinci_gpio_setup(void) if (WARN_ON(DAVINCI_N_GPIO < ngpio)) ngpio = DAVINCI_N_GPIO; + gpio_base = ioremap(soc_info->gpio_base, SZ_4K); + if (WARN_ON(!gpio_base)) + return -ENOMEM; + for (i = 0, base = 0; base < ngpio; i++, base += 32) { chips[i].chip.label = "DaVinci"; @@ -445,7 +449,7 @@ done: /* BINTEN -- per-bank interrupt enable. genirq would also let these * bits be set/cleared dynamically. */ - __raw_writel(binten, soc_info->gpio_base + 0x08); + __raw_writel(binten, gpio_base + 0x08); printk(KERN_INFO "DaVinci: %d gpio irqs\n", irq - gpio_to_irq(0)); diff --git a/arch/arm/mach-davinci/include/mach/common.h b/arch/arm/mach-davinci/include/mach/common.h index a58bd88..2dd2226 100644 --- a/arch/arm/mach-davinci/include/mach/common.h +++ b/arch/arm/mach-davinci/include/mach/common.h @@ -60,7 +60,7 @@ struct davinci_soc_info { unsigned long intc_irq_num; struct davinci_timer_info *timer_info; int gpio_type; - void __iomem *gpio_base; + u32 gpio_base; unsigned gpio_num; unsigned gpio_irq; unsigned gpio_unbanked; -- cgit v0.10.2 From db6db5d8474b16811566e0e919d060e2856d5ad9 Mon Sep 17 00:00:00 2001 From: Cyril Chemparathy Date: Fri, 7 May 2010 17:06:33 -0400 Subject: Davinci: da8xx: rtc - use ioremap This patch modifies the RTC unlock code to use ioremap() maps instead of IO_ADDRESS() translation. Signed-off-by: Cyril Chemparathy Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c index 67a6fbc..8cda729 100644 --- a/arch/arm/mach-davinci/devices-da8xx.c +++ b/arch/arm/mach-davinci/devices-da8xx.c @@ -584,10 +584,17 @@ static struct platform_device da8xx_rtc_device = { int da8xx_register_rtc(void) { int ret; + void __iomem *base; + + base = ioremap(DA8XX_RTC_BASE, SZ_4K); + if (WARN_ON(!base)) + return -ENOMEM; /* Unlock the rtc's registers */ - __raw_writel(0x83e70b13, IO_ADDRESS(DA8XX_RTC_BASE + 0x6c)); - __raw_writel(0x95a4f1e0, IO_ADDRESS(DA8XX_RTC_BASE + 0x70)); + __raw_writel(0x83e70b13, base + 0x6c); + __raw_writel(0x95a4f1e0, base + 0x70); + + iounmap(base); ret = platform_device_register(&da8xx_rtc_device); if (!ret) -- cgit v0.10.2 From 3347db8392486a1b52aab980cc445cf505c36d45 Mon Sep 17 00:00:00 2001 From: Cyril Chemparathy Date: Fri, 7 May 2010 17:06:34 -0400 Subject: Davinci: jtag_id - use ioremap() This patch replaces the jtag id base info in davinci_soc_info with a physical address which is then ioremap()ed within common code. This patch (in combination with a similar change for PSC) will allow us to eliminate the SYSCFG nastiness in DA8xx code. Signed-off-by: Cyril Chemparathy Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/common.c b/arch/arm/mach-davinci/common.c index f8221c5..65e073d 100644 --- a/arch/arm/mach-davinci/common.c +++ b/arch/arm/mach-davinci/common.c @@ -37,26 +37,43 @@ void davinci_get_mac_addr(struct memory_accessor *mem_acc, void *context) pr_info("Read MAC addr from EEPROM: %pM\n", mac_addr); } -static struct davinci_id * __init davinci_get_id(u32 jtag_id) +static int __init davinci_init_id(struct davinci_soc_info *soc_info) { - int i; - struct davinci_id *dip; - u8 variant = (jtag_id & 0xf0000000) >> 28; - u16 part_no = (jtag_id & 0x0ffff000) >> 12; + int i; + struct davinci_id *dip; + u8 variant; + u16 part_no; + void __iomem *base; + + base = ioremap(soc_info->jtag_id_reg, SZ_4K); + if (!base) { + pr_err("Unable to map JTAG ID register\n"); + return -ENOMEM; + } + + soc_info->jtag_id = __raw_readl(base); + iounmap(base); - for (i = 0, dip = davinci_soc_info.ids; i < davinci_soc_info.ids_num; + variant = (soc_info->jtag_id & 0xf0000000) >> 28; + part_no = (soc_info->jtag_id & 0x0ffff000) >> 12; + + for (i = 0, dip = soc_info->ids; i < soc_info->ids_num; i++, dip++) /* Don't care about the manufacturer right now */ - if ((dip->part_no == part_no) && (dip->variant == variant)) - return dip; - - return NULL; + if ((dip->part_no == part_no) && (dip->variant == variant)) { + soc_info->cpu_id = dip->cpu_id; + pr_info("DaVinci %s variant 0x%x\n", dip->name, + dip->variant); + return 0; + } + + pr_err("Unknown DaVinci JTAG ID 0x%x\n", soc_info->jtag_id); + return -EINVAL; } void __init davinci_common_init(struct davinci_soc_info *soc_info) { int ret; - struct davinci_id *dip; if (!soc_info) { ret = -EINVAL; @@ -84,18 +101,9 @@ void __init davinci_common_init(struct davinci_soc_info *soc_info) * We want to check CPU revision early for cpu_is_xxxx() macros. * IO space mapping must be initialized before we can do that. */ - davinci_soc_info.jtag_id = __raw_readl(davinci_soc_info.jtag_id_base); - - dip = davinci_get_id(davinci_soc_info.jtag_id); - if (!dip) { - ret = -EINVAL; - pr_err("Unknown DaVinci JTAG ID 0x%x\n", - davinci_soc_info.jtag_id); + ret = davinci_init_id(&davinci_soc_info); + if (ret < 0) goto err; - } - - davinci_soc_info.cpu_id = dip->cpu_id; - pr_info("DaVinci %s variant 0x%x\n", dip->name, dip->variant); if (davinci_soc_info.cpu_clks) { ret = davinci_clk_init(davinci_soc_info.cpu_clks); diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c index 4f5727f..c5600b8 100644 --- a/arch/arm/mach-davinci/da830.c +++ b/arch/arm/mach-davinci/da830.c @@ -1188,6 +1188,7 @@ static struct davinci_timer_info da830_timer_info = { static struct davinci_soc_info davinci_soc_info_da830 = { .io_desc = da830_io_desc, .io_desc_num = ARRAY_SIZE(da830_io_desc), + .jtag_id_reg = DA8XX_SYSCFG0_BASE + DA8XX_JTAG_ID_REG, .ids = da830_ids, .ids_num = ARRAY_SIZE(da830_ids), .cpu_clks = da830_clks, @@ -1215,8 +1216,6 @@ void __init da830_init(void) if (WARN(!da8xx_syscfg0_base, "Unable to map syscfg0 module")) return; - davinci_soc_info_da830.jtag_id_base = - DA8XX_SYSCFG0_VIRT(DA8XX_JTAG_ID_REG); davinci_soc_info_da830.pinmux_base = DA8XX_SYSCFG0_VIRT(0x120); davinci_common_init(&davinci_soc_info_da830); diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c index cb7f663..fcf7016 100644 --- a/arch/arm/mach-davinci/da850.c +++ b/arch/arm/mach-davinci/da850.c @@ -1073,6 +1073,7 @@ no_ddrpll_mem: static struct davinci_soc_info davinci_soc_info_da850 = { .io_desc = da850_io_desc, .io_desc_num = ARRAY_SIZE(da850_io_desc), + .jtag_id_reg = DA8XX_SYSCFG0_BASE + DA8XX_JTAG_ID_REG, .ids = da850_ids, .ids_num = ARRAY_SIZE(da850_ids), .cpu_clks = da850_clks, @@ -1108,8 +1109,6 @@ void __init da850_init(void) if (WARN(!da8xx_syscfg1_base, "Unable to map syscfg1 module")) return; - davinci_soc_info_da850.jtag_id_base = - DA8XX_SYSCFG0_VIRT(DA8XX_JTAG_ID_REG); davinci_soc_info_da850.pinmux_base = DA8XX_SYSCFG0_VIRT(0x120); davinci_common_init(&davinci_soc_info_da850); diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c index 277041d..228b6d1 100644 --- a/arch/arm/mach-davinci/dm355.c +++ b/arch/arm/mach-davinci/dm355.c @@ -840,7 +840,7 @@ static struct platform_device dm355_serial_device = { static struct davinci_soc_info davinci_soc_info_dm355 = { .io_desc = dm355_io_desc, .io_desc_num = ARRAY_SIZE(dm355_io_desc), - .jtag_id_base = IO_ADDRESS(0x01c40028), + .jtag_id_reg = 0x01c40028, .ids = dm355_ids, .ids_num = ARRAY_SIZE(dm355_ids), .cpu_clks = dm355_clks, diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index ecdbc67..b396d58 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -1045,7 +1045,7 @@ static struct platform_device dm365_serial_device = { static struct davinci_soc_info davinci_soc_info_dm365 = { .io_desc = dm365_io_desc, .io_desc_num = ARRAY_SIZE(dm365_io_desc), - .jtag_id_base = IO_ADDRESS(0x01c40028), + .jtag_id_reg = 0x01c40028, .ids = dm365_ids, .ids_num = ARRAY_SIZE(dm365_ids), .cpu_clks = dm365_clks, diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index beb315c..9859567 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c @@ -731,7 +731,7 @@ static struct platform_device dm644x_serial_device = { static struct davinci_soc_info davinci_soc_info_dm644x = { .io_desc = dm644x_io_desc, .io_desc_num = ARRAY_SIZE(dm644x_io_desc), - .jtag_id_base = IO_ADDRESS(0x01c40028), + .jtag_id_reg = 0x01c40028, .ids = dm644x_ids, .ids_num = ARRAY_SIZE(dm644x_ids), .cpu_clks = dm644x_clks, diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index 95fc981e..f9a8cc4 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -815,7 +815,7 @@ static struct platform_device dm646x_serial_device = { static struct davinci_soc_info davinci_soc_info_dm646x = { .io_desc = dm646x_io_desc, .io_desc_num = ARRAY_SIZE(dm646x_io_desc), - .jtag_id_base = IO_ADDRESS(0x01c40028), + .jtag_id_reg = 0x01c40028, .ids = dm646x_ids, .ids_num = ARRAY_SIZE(dm646x_ids), .cpu_clks = dm646x_clks, diff --git a/arch/arm/mach-davinci/include/mach/common.h b/arch/arm/mach-davinci/include/mach/common.h index 2dd2226..1078458 100644 --- a/arch/arm/mach-davinci/include/mach/common.h +++ b/arch/arm/mach-davinci/include/mach/common.h @@ -45,7 +45,7 @@ struct davinci_soc_info { unsigned long io_desc_num; u32 cpu_id; u32 jtag_id; - void __iomem *jtag_id_base; + u32 jtag_id_reg; struct davinci_id *ids; unsigned long ids_num; struct clk_lookup *cpu_clks; -- cgit v0.10.2 From 1bcd38ad2de4c1cd30387c588dfb28d637d4111d Mon Sep 17 00:00:00 2001 From: Cyril Chemparathy Date: Fri, 7 May 2010 17:06:35 -0400 Subject: Davinci: timer - use ioremap() This patch eliminates IO_ADDRESS() usage for Davinci timer definitions. The timer code has correspondingly been modified to ioremap() MMRs instead. Signed-off-by: Cyril Chemparathy Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c index c5600b8..8a2510c 100644 --- a/arch/arm/mach-davinci/da830.c +++ b/arch/arm/mach-davinci/da830.c @@ -1159,14 +1159,14 @@ static struct davinci_id da830_ids[] = { static struct davinci_timer_instance da830_timer_instance[2] = { { - .base = IO_ADDRESS(DA8XX_TIMER64P0_BASE), + .base = DA8XX_TIMER64P0_BASE, .bottom_irq = IRQ_DA8XX_TINT12_0, .top_irq = IRQ_DA8XX_TINT34_0, .cmp_off = DA830_CMP12_0, .cmp_irq = IRQ_DA830_T12CMPINT0_0, }, { - .base = IO_ADDRESS(DA8XX_TIMER64P1_BASE), + .base = DA8XX_TIMER64P1_BASE, .bottom_irq = IRQ_DA8XX_TINT12_1, .top_irq = IRQ_DA8XX_TINT34_1, .cmp_off = DA830_CMP12_0, diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c index fcf7016..ebfa5ca 100644 --- a/arch/arm/mach-davinci/da850.c +++ b/arch/arm/mach-davinci/da850.c @@ -800,22 +800,22 @@ static struct davinci_id da850_ids[] = { static struct davinci_timer_instance da850_timer_instance[4] = { { - .base = IO_ADDRESS(DA8XX_TIMER64P0_BASE), + .base = DA8XX_TIMER64P0_BASE, .bottom_irq = IRQ_DA8XX_TINT12_0, .top_irq = IRQ_DA8XX_TINT34_0, }, { - .base = IO_ADDRESS(DA8XX_TIMER64P1_BASE), + .base = DA8XX_TIMER64P1_BASE, .bottom_irq = IRQ_DA8XX_TINT12_1, .top_irq = IRQ_DA8XX_TINT34_1, }, { - .base = IO_ADDRESS(DA850_TIMER64P2_BASE), + .base = DA850_TIMER64P2_BASE, .bottom_irq = IRQ_DA850_TINT12_2, .top_irq = IRQ_DA850_TINT34_2, }, { - .base = IO_ADDRESS(DA850_TIMER64P3_BASE), + .base = DA850_TIMER64P3_BASE, .bottom_irq = IRQ_DA850_TINT12_3, .top_irq = IRQ_DA850_TINT34_3, }, diff --git a/arch/arm/mach-davinci/devices.c b/arch/arm/mach-davinci/devices.c index d9c82ee..8b7201e 100644 --- a/arch/arm/mach-davinci/devices.c +++ b/arch/arm/mach-davinci/devices.c @@ -297,12 +297,12 @@ static void davinci_init_wdt(void) struct davinci_timer_instance davinci_timer_instance[2] = { { - .base = IO_ADDRESS(DAVINCI_TIMER0_BASE), + .base = DAVINCI_TIMER0_BASE, .bottom_irq = IRQ_TINT0_TINT12, .top_irq = IRQ_TINT0_TINT34, }, { - .base = IO_ADDRESS(DAVINCI_TIMER1_BASE), + .base = DAVINCI_TIMER1_BASE, .bottom_irq = IRQ_TINT1_TINT12, .top_irq = IRQ_TINT1_TINT34, }, diff --git a/arch/arm/mach-davinci/include/mach/common.h b/arch/arm/mach-davinci/include/mach/common.h index 1078458..2e15464 100644 --- a/arch/arm/mach-davinci/include/mach/common.h +++ b/arch/arm/mach-davinci/include/mach/common.h @@ -24,7 +24,7 @@ extern void __iomem *davinci_intc_base; extern int davinci_intc_type; struct davinci_timer_instance { - void __iomem *base; + u32 base; u32 bottom_irq; u32 top_irq; unsigned long cmp_off; diff --git a/arch/arm/mach-davinci/time.c b/arch/arm/mach-davinci/time.c index e5c598a..0f21c36 100644 --- a/arch/arm/mach-davinci/time.c +++ b/arch/arm/mach-davinci/time.c @@ -197,32 +197,36 @@ static void __init timer_init(void) { struct davinci_soc_info *soc_info = &davinci_soc_info; struct davinci_timer_instance *dtip = soc_info->timer_info->timers; + void __iomem *base[2]; int i; /* Global init of each 64-bit timer as a whole */ for(i=0; i<2; i++) { u32 tgcr; - void __iomem *base = dtip[i].base; + + base[i] = ioremap(dtip[i].base, SZ_4K); + if (WARN_ON(!base[i])) + continue; /* Disabled, Internal clock source */ - __raw_writel(0, base + TCR); + __raw_writel(0, base[i] + TCR); /* reset both timers, no pre-scaler for timer34 */ tgcr = 0; - __raw_writel(tgcr, base + TGCR); + __raw_writel(tgcr, base[i] + TGCR); /* Set both timers to unchained 32-bit */ tgcr = TGCR_TIMMODE_32BIT_UNCHAINED << TGCR_TIMMODE_SHIFT; - __raw_writel(tgcr, base + TGCR); + __raw_writel(tgcr, base[i] + TGCR); /* Unreset timers */ tgcr |= (TGCR_UNRESET << TGCR_TIM12RS_SHIFT) | (TGCR_UNRESET << TGCR_TIM34RS_SHIFT); - __raw_writel(tgcr, base + TGCR); + __raw_writel(tgcr, base[i] + TGCR); /* Init both counters to zero */ - __raw_writel(0, base + TIM12); - __raw_writel(0, base + TIM34); + __raw_writel(0, base[i] + TIM12); + __raw_writel(0, base[i] + TIM34); } /* Init of each timer as a 32-bit timer */ @@ -231,7 +235,9 @@ static void __init timer_init(void) int timer = ID_TO_TIMER(t->id); u32 irq; - t->base = dtip[timer].base; + t->base = base[timer]; + if (!t->base) + continue; if (IS_TIMER_BOT(t->id)) { t->enamode_shift = 6; -- cgit v0.10.2 From e4c822c7e98cdda78b10a696b030fc20b22dcab4 Mon Sep 17 00:00:00 2001 From: Cyril Chemparathy Date: Fri, 7 May 2010 17:06:36 -0400 Subject: Davinci: psc - use ioremap() This patch modifies the psc and clock control code to use ioremap()ed registers. Signed-off-by: Cyril Chemparathy Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c index 868cb76..054c303 100644 --- a/arch/arm/mach-davinci/clock.c +++ b/arch/arm/mach-davinci/clock.c @@ -302,7 +302,6 @@ static unsigned long clk_pllclk_recalc(struct clk *clk) struct pll_data *pll = clk->pll_data; unsigned long rate = clk->rate; - pll->base = IO_ADDRESS(pll->phys_base); ctrl = __raw_readl(pll->base + PLLCTL); rate = pll->input_rate = clk->parent->rate; @@ -458,8 +457,17 @@ int __init davinci_clk_init(struct clk_lookup *clocks) clk->recalc = clk_leafclk_recalc; } - if (clk->pll_data && !clk->pll_data->div_ratio_mask) - clk->pll_data->div_ratio_mask = PLLDIV_RATIO_MASK; + if (clk->pll_data) { + struct pll_data *pll = clk->pll_data; + + if (!pll->div_ratio_mask) + pll->div_ratio_mask = PLLDIV_RATIO_MASK; + + if (pll->phys_base && !pll->base) { + pll->base = ioremap(pll->phys_base, SZ_4K); + WARN_ON(!pll->base); + } + } if (clk->recalc) clk->rate = clk->recalc(clk); diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c index 8a2510c..47a7f49 100644 --- a/arch/arm/mach-davinci/da830.c +++ b/arch/arm/mach-davinci/da830.c @@ -1127,10 +1127,7 @@ static struct map_desc da830_io_desc[] = { }, }; -static void __iomem *da830_psc_bases[] = { - IO_ADDRESS(DA8XX_PSC0_BASE), - IO_ADDRESS(DA8XX_PSC1_BASE), -}; +static u32 da830_psc_bases[] = { DA8XX_PSC0_BASE, DA8XX_PSC1_BASE }; /* Contents of JTAG ID register used to identify exact cpu type */ static struct davinci_id da830_ids[] = { diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c index ebfa5ca..2a430bb 100644 --- a/arch/arm/mach-davinci/da850.c +++ b/arch/arm/mach-davinci/da850.c @@ -782,10 +782,7 @@ static struct map_desc da850_io_desc[] = { }, }; -static void __iomem *da850_psc_bases[] = { - IO_ADDRESS(DA8XX_PSC0_BASE), - IO_ADDRESS(DA8XX_PSC1_BASE), -}; +static u32 da850_psc_bases[] = { DA8XX_PSC0_BASE, DA8XX_PSC1_BASE }; /* Contents of JTAG ID register used to identify exact cpu type */ static struct davinci_id da850_ids[] = { diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c index 228b6d1..70a1827 100644 --- a/arch/arm/mach-davinci/dm355.c +++ b/arch/arm/mach-davinci/dm355.c @@ -783,9 +783,7 @@ static struct davinci_id dm355_ids[] = { }, }; -static void __iomem *dm355_psc_bases[] = { - IO_ADDRESS(DAVINCI_PWR_SLEEP_CNTRL_BASE), -}; +static u32 dm355_psc_bases[] = { DAVINCI_PWR_SLEEP_CNTRL_BASE }; /* * T0_BOT: Timer 0, bottom: clockevent source for hrtimers diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index b396d58..451a4ef 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -1002,9 +1002,7 @@ static struct davinci_id dm365_ids[] = { }, }; -static void __iomem *dm365_psc_bases[] = { - IO_ADDRESS(DAVINCI_PWR_SLEEP_CNTRL_BASE), -}; +static u32 dm365_psc_bases[] = { DAVINCI_PWR_SLEEP_CNTRL_BASE }; static struct davinci_timer_info dm365_timer_info = { .timers = davinci_timer_instance, diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index 9859567..ee654de 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c @@ -674,9 +674,7 @@ static struct davinci_id dm644x_ids[] = { }, }; -static void __iomem *dm644x_psc_bases[] = { - IO_ADDRESS(DAVINCI_PWR_SLEEP_CNTRL_BASE), -}; +static u32 dm644x_psc_bases[] = { DAVINCI_PWR_SLEEP_CNTRL_BASE }; /* * T0_BOT: Timer 0, bottom: clockevent source for hrtimers diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index f9a8cc4..4c98ef0 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -758,9 +758,7 @@ static struct davinci_id dm646x_ids[] = { }, }; -static void __iomem *dm646x_psc_bases[] = { - IO_ADDRESS(DAVINCI_PWR_SLEEP_CNTRL_BASE), -}; +static u32 dm646x_psc_bases[] = { DAVINCI_PWR_SLEEP_CNTRL_BASE }; /* * T0_BOT: Timer 0, bottom: clockevent source for hrtimers diff --git a/arch/arm/mach-davinci/include/mach/common.h b/arch/arm/mach-davinci/include/mach/common.h index 2e15464..4c8dfcb4d 100644 --- a/arch/arm/mach-davinci/include/mach/common.h +++ b/arch/arm/mach-davinci/include/mach/common.h @@ -49,7 +49,7 @@ struct davinci_soc_info { struct davinci_id *ids; unsigned long ids_num; struct clk_lookup *cpu_clks; - void __iomem **psc_bases; + u32 *psc_bases; unsigned long psc_bases_num; void __iomem *pinmux_base; const struct mux_config *pinmux_pins; diff --git a/arch/arm/mach-davinci/psc.c b/arch/arm/mach-davinci/psc.c index d7cb438..1b15dbd 100644 --- a/arch/arm/mach-davinci/psc.c +++ b/arch/arm/mach-davinci/psc.c @@ -38,8 +38,9 @@ int __init davinci_psc_is_clk_active(unsigned int ctlr, unsigned int id) return 0; } - psc_base = soc_info->psc_bases[ctlr]; + psc_base = ioremap(soc_info->psc_bases[ctlr], SZ_4K); mdstat = __raw_readl(psc_base + MDSTAT + 4 * id); + iounmap(psc_base); /* if clocked, state can be "Enable" or "SyncReset" */ return mdstat & BIT(12); @@ -59,7 +60,7 @@ void davinci_psc_config(unsigned int domain, unsigned int ctlr, return; } - psc_base = soc_info->psc_bases[ctlr]; + psc_base = ioremap(soc_info->psc_bases[ctlr], SZ_4K); mdctl = __raw_readl(psc_base + MDCTL + 4 * id); mdctl &= ~MDSTAT_STATE_MASK; @@ -99,4 +100,6 @@ void davinci_psc_config(unsigned int domain, unsigned int ctlr, do { mdstat = __raw_readl(psc_base + MDSTAT + 4 * id); } while (!((mdstat & MDSTAT_STATE_MASK) == next_state)); + + iounmap(psc_base); } -- cgit v0.10.2 From bd808947040ba53b2b0e52dde598a9414fb27bba Mon Sep 17 00:00:00 2001 From: Cyril Chemparathy Date: Fri, 7 May 2010 17:06:37 -0400 Subject: Davinci: aintc/cpintc - use ioremap() This patch implements the following: - interrupt initialization uses ioremap() instead of passing a virtual address via davinci_soc_info. - machine definitions directly point to cp_intc_init() or davinci_irq_init() - davinci_intc_type and davinci_intc_base now get initialized in controller specific init functions instead of davinci_common_init() - minor fix in davinci_irq_init() to use intc_irq_num instead of DAVINCI_N_AINTC_IRQ Signed-off-by: Cyril Chemparathy Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c index 8f079d2..212d970 100644 --- a/arch/arm/mach-davinci/board-da830-evm.c +++ b/arch/arm/mach-davinci/board-da830-evm.c @@ -561,14 +561,6 @@ static int __init da830_evm_console_init(void) console_initcall(da830_evm_console_init); #endif -static __init void da830_evm_irq_init(void) -{ - struct davinci_soc_info *soc_info = &davinci_soc_info; - - cp_intc_init((void __iomem *)DA8XX_CP_INTC_VIRT, DA830_N_CP_INTC_IRQ, - soc_info->intc_irq_prios, NULL); -} - static void __init da830_evm_map_io(void) { da830_init(); @@ -579,7 +571,7 @@ MACHINE_START(DAVINCI_DA830_EVM, "DaVinci DA830/OMAP-L137 EVM") .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, .boot_params = (DA8XX_DDR_BASE + 0x100), .map_io = da830_evm_map_io, - .init_irq = da830_evm_irq_init, + .init_irq = cp_intc_init, .timer = &davinci_timer, .init_machine = da830_evm_init, MACHINE_END diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c index 6c137e0..abd0493 100644 --- a/arch/arm/mach-davinci/board-da850-evm.c +++ b/arch/arm/mach-davinci/board-da850-evm.c @@ -736,14 +736,6 @@ static int __init da850_evm_console_init(void) console_initcall(da850_evm_console_init); #endif -static __init void da850_evm_irq_init(void) -{ - struct davinci_soc_info *soc_info = &davinci_soc_info; - - cp_intc_init((void __iomem *)DA8XX_CP_INTC_VIRT, DA850_N_CP_INTC_IRQ, - soc_info->intc_irq_prios, NULL); -} - static void __init da850_evm_map_io(void) { da850_init(); @@ -754,7 +746,7 @@ MACHINE_START(DAVINCI_DA850_EVM, "DaVinci DA850/OMAP-L138 EVM") .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, .boot_params = (DA8XX_DDR_BASE + 0x100), .map_io = da850_evm_map_io, - .init_irq = da850_evm_irq_init, + .init_irq = cp_intc_init, .timer = &davinci_timer, .init_machine = da850_evm_init, MACHINE_END diff --git a/arch/arm/mach-davinci/board-dm355-evm.c b/arch/arm/mach-davinci/board-dm355-evm.c index a0ad7d9..a319101 100644 --- a/arch/arm/mach-davinci/board-dm355-evm.c +++ b/arch/arm/mach-davinci/board-dm355-evm.c @@ -350,17 +350,12 @@ static __init void dm355_evm_init(void) dm355_init_asp1(ASP1_TX_EVT_EN | ASP1_RX_EVT_EN, &dm355_evm_snd_data); } -static __init void dm355_evm_irq_init(void) -{ - davinci_irq_init(); -} - MACHINE_START(DAVINCI_DM355_EVM, "DaVinci DM355 EVM") .phys_io = IO_PHYS, .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, .boot_params = (0x80000100), .map_io = dm355_evm_map_io, - .init_irq = dm355_evm_irq_init, + .init_irq = davinci_irq_init, .timer = &davinci_timer, .init_machine = dm355_evm_init, MACHINE_END diff --git a/arch/arm/mach-davinci/board-dm355-leopard.c b/arch/arm/mach-davinci/board-dm355-leopard.c index c3d5a70..f1d8132 100644 --- a/arch/arm/mach-davinci/board-dm355-leopard.c +++ b/arch/arm/mach-davinci/board-dm355-leopard.c @@ -269,17 +269,12 @@ static __init void dm355_leopard_init(void) ARRAY_SIZE(dm355_leopard_spi_info)); } -static __init void dm355_leopard_irq_init(void) -{ - davinci_irq_init(); -} - MACHINE_START(DM355_LEOPARD, "DaVinci DM355 leopard") .phys_io = IO_PHYS, .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, .boot_params = (0x80000100), .map_io = dm355_leopard_map_io, - .init_irq = dm355_leopard_irq_init, + .init_irq = davinci_irq_init, .timer = &davinci_timer, .init_machine = dm355_leopard_init, MACHINE_END diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c index b98b35c..98814e6 100644 --- a/arch/arm/mach-davinci/board-dm365-evm.c +++ b/arch/arm/mach-davinci/board-dm365-evm.c @@ -608,17 +608,12 @@ static __init void dm365_evm_init(void) ARRAY_SIZE(dm365_evm_spi_info)); } -static __init void dm365_evm_irq_init(void) -{ - davinci_irq_init(); -} - MACHINE_START(DAVINCI_DM365_EVM, "DaVinci DM365 EVM") .phys_io = IO_PHYS, .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, .boot_params = (0x80000100), .map_io = dm365_evm_map_io, - .init_irq = dm365_evm_irq_init, + .init_irq = davinci_irq_init, .timer = &davinci_timer, .init_machine = dm365_evm_init, MACHINE_END diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c index 73c0b04..34c8b41 100644 --- a/arch/arm/mach-davinci/board-dm644x-evm.c +++ b/arch/arm/mach-davinci/board-dm644x-evm.c @@ -704,18 +704,13 @@ static __init void davinci_evm_init(void) } -static __init void davinci_evm_irq_init(void) -{ - davinci_irq_init(); -} - MACHINE_START(DAVINCI_EVM, "DaVinci DM644x EVM") /* Maintainer: MontaVista Software */ .phys_io = IO_PHYS, .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, .boot_params = (DAVINCI_DDR_BASE + 0x100), .map_io = davinci_evm_map_io, - .init_irq = davinci_evm_irq_init, + .init_irq = davinci_irq_init, .timer = &davinci_timer, .init_machine = davinci_evm_init, MACHINE_END diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c index e2ac06f..6d88893 100644 --- a/arch/arm/mach-davinci/board-dm646x-evm.c +++ b/arch/arm/mach-davinci/board-dm646x-evm.c @@ -739,11 +739,6 @@ static __init void evm_init(void) soc_info->emac_pdata->mdio_max_freq = DM646X_EVM_MDIO_FREQUENCY; } -static __init void davinci_dm646x_evm_irq_init(void) -{ - davinci_irq_init(); -} - #define DM646X_EVM_REF_FREQ 27000000 #define DM6467T_EVM_REF_FREQ 33000000 @@ -760,7 +755,7 @@ MACHINE_START(DAVINCI_DM6467_EVM, "DaVinci DM646x EVM") .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, .boot_params = (0x80000100), .map_io = davinci_map_io, - .init_irq = davinci_dm646x_evm_irq_init, + .init_irq = davinci_irq_init, .timer = &davinci_timer, .init_machine = evm_init, MACHINE_END @@ -770,7 +765,7 @@ MACHINE_START(DAVINCI_DM6467TEVM, "DaVinci DM6467T EVM") .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, .boot_params = (0x80000100), .map_io = davinci_map_io, - .init_irq = davinci_dm646x_evm_irq_init, + .init_irq = davinci_irq_init, .timer = &davinci_timer, .init_machine = evm_init, MACHINE_END diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c index 875770c..4c30e92 100644 --- a/arch/arm/mach-davinci/board-neuros-osd2.c +++ b/arch/arm/mach-davinci/board-neuros-osd2.c @@ -273,18 +273,13 @@ static __init void davinci_ntosd2_init(void) davinci_setup_mmc(0, &davinci_ntosd2_mmc_config); } -static __init void davinci_ntosd2_irq_init(void) -{ - davinci_irq_init(); -} - MACHINE_START(NEUROS_OSD2, "Neuros OSD2") /* Maintainer: Neuros Technologies */ .phys_io = IO_PHYS, .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, .boot_params = (DAVINCI_DDR_BASE + 0x100), .map_io = davinci_ntosd2_map_io, - .init_irq = davinci_ntosd2_irq_init, + .init_irq = davinci_irq_init, .timer = &davinci_timer, .init_machine = davinci_ntosd2_init, MACHINE_END diff --git a/arch/arm/mach-davinci/board-sffsdr.c b/arch/arm/mach-davinci/board-sffsdr.c index 1ed0662..23e664a 100644 --- a/arch/arm/mach-davinci/board-sffsdr.c +++ b/arch/arm/mach-davinci/board-sffsdr.c @@ -152,18 +152,13 @@ static __init void davinci_sffsdr_init(void) davinci_cfg_reg(DM644X_VLYNQWD); } -static __init void davinci_sffsdr_irq_init(void) -{ - davinci_irq_init(); -} - MACHINE_START(SFFSDR, "Lyrtech SFFSDR") /* Maintainer: Hugo Villeneuve hugo.villeneuve@lyrtech.com */ .phys_io = IO_PHYS, .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc, .boot_params = (DAVINCI_DDR_BASE + 0x100), .map_io = davinci_sffsdr_map_io, - .init_irq = davinci_sffsdr_irq_init, + .init_irq = davinci_irq_init, .timer = &davinci_timer, .init_machine = davinci_sffsdr_init, MACHINE_END diff --git a/arch/arm/mach-davinci/common.c b/arch/arm/mach-davinci/common.c index 65e073d..1d25573 100644 --- a/arch/arm/mach-davinci/common.c +++ b/arch/arm/mach-davinci/common.c @@ -112,8 +112,6 @@ void __init davinci_common_init(struct davinci_soc_info *soc_info) goto err; } - davinci_intc_base = davinci_soc_info.intc_base; - davinci_intc_type = davinci_soc_info.intc_type; return; err: diff --git a/arch/arm/mach-davinci/cp_intc.c b/arch/arm/mach-davinci/cp_intc.c index 2a8d26e..bb4c40e 100644 --- a/arch/arm/mach-davinci/cp_intc.c +++ b/arch/arm/mach-davinci/cp_intc.c @@ -13,18 +13,17 @@ #include #include +#include #include -static void __iomem *cp_intc_base; - static inline unsigned int cp_intc_read(unsigned offset) { - return __raw_readl(cp_intc_base + offset); + return __raw_readl(davinci_intc_base + offset); } static inline void cp_intc_write(unsigned long value, unsigned offset) { - __raw_writel(value, cp_intc_base + offset); + __raw_writel(value, davinci_intc_base + offset); } static void cp_intc_ack_irq(unsigned int irq) @@ -100,13 +99,18 @@ static struct irq_chip cp_intc_irq_chip = { .set_wake = cp_intc_set_wake, }; -void __init cp_intc_init(void __iomem *base, unsigned short num_irq, - u8 *irq_prio, u32 *host_map) +void __init cp_intc_init(void) { + unsigned long num_irq = davinci_soc_info.intc_irq_num; + u8 *irq_prio = davinci_soc_info.intc_irq_prios; + u32 *host_map = davinci_soc_info.intc_host_map; unsigned num_reg = BITS_TO_LONGS(num_irq); int i; - cp_intc_base = base; + davinci_intc_type = DAVINCI_INTC_TYPE_CP_INTC; + davinci_intc_base = ioremap(davinci_soc_info.intc_base, SZ_8K); + if (WARN_ON(!davinci_intc_base)) + return; cp_intc_write(0, CP_INTC_GLOBAL_ENABLE); diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c index 47a7f49..2c84f07 100644 --- a/arch/arm/mach-davinci/da830.c +++ b/arch/arm/mach-davinci/da830.c @@ -1193,7 +1193,7 @@ static struct davinci_soc_info davinci_soc_info_da830 = { .psc_bases_num = ARRAY_SIZE(da830_psc_bases), .pinmux_pins = da830_pins, .pinmux_pins_num = ARRAY_SIZE(da830_pins), - .intc_base = (void __iomem *)DA8XX_CP_INTC_VIRT, + .intc_base = DA8XX_CP_INTC_BASE, .intc_type = DAVINCI_INTC_TYPE_CP_INTC, .intc_irq_prios = da830_default_priorities, .intc_irq_num = DA830_N_CP_INTC_IRQ, diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c index 2a430bb..6f5ea2a 100644 --- a/arch/arm/mach-davinci/da850.c +++ b/arch/arm/mach-davinci/da850.c @@ -1078,7 +1078,7 @@ static struct davinci_soc_info davinci_soc_info_da850 = { .psc_bases_num = ARRAY_SIZE(da850_psc_bases), .pinmux_pins = da850_pins, .pinmux_pins_num = ARRAY_SIZE(da850_pins), - .intc_base = (void __iomem *)DA8XX_CP_INTC_VIRT, + .intc_base = DA8XX_CP_INTC_BASE, .intc_type = DAVINCI_INTC_TYPE_CP_INTC, .intc_irq_prios = da850_default_priorities, .intc_irq_num = DA850_N_CP_INTC_IRQ, diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c index 70a1827..5ab39f6 100644 --- a/arch/arm/mach-davinci/dm355.c +++ b/arch/arm/mach-davinci/dm355.c @@ -847,7 +847,7 @@ static struct davinci_soc_info davinci_soc_info_dm355 = { .pinmux_base = IO_ADDRESS(DAVINCI_SYSTEM_MODULE_BASE), .pinmux_pins = dm355_pins, .pinmux_pins_num = ARRAY_SIZE(dm355_pins), - .intc_base = IO_ADDRESS(DAVINCI_ARM_INTC_BASE), + .intc_base = DAVINCI_ARM_INTC_BASE, .intc_type = DAVINCI_INTC_TYPE_AINTC, .intc_irq_prios = dm355_default_priorities, .intc_irq_num = DAVINCI_N_AINTC_IRQ, diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index 451a4ef..be340ed 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -1052,7 +1052,7 @@ static struct davinci_soc_info davinci_soc_info_dm365 = { .pinmux_base = IO_ADDRESS(DAVINCI_SYSTEM_MODULE_BASE), .pinmux_pins = dm365_pins, .pinmux_pins_num = ARRAY_SIZE(dm365_pins), - .intc_base = IO_ADDRESS(DAVINCI_ARM_INTC_BASE), + .intc_base = DAVINCI_ARM_INTC_BASE, .intc_type = DAVINCI_INTC_TYPE_AINTC, .intc_irq_prios = dm365_default_priorities, .intc_irq_num = DAVINCI_N_AINTC_IRQ, diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index ee654de..d3aa1f7 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c @@ -738,7 +738,7 @@ static struct davinci_soc_info davinci_soc_info_dm644x = { .pinmux_base = IO_ADDRESS(DAVINCI_SYSTEM_MODULE_BASE), .pinmux_pins = dm644x_pins, .pinmux_pins_num = ARRAY_SIZE(dm644x_pins), - .intc_base = IO_ADDRESS(DAVINCI_ARM_INTC_BASE), + .intc_base = DAVINCI_ARM_INTC_BASE, .intc_type = DAVINCI_INTC_TYPE_AINTC, .intc_irq_prios = dm644x_default_priorities, .intc_irq_num = DAVINCI_N_AINTC_IRQ, diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index 4c98ef0..e0153b3 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -822,7 +822,7 @@ static struct davinci_soc_info davinci_soc_info_dm646x = { .pinmux_base = IO_ADDRESS(DAVINCI_SYSTEM_MODULE_BASE), .pinmux_pins = dm646x_pins, .pinmux_pins_num = ARRAY_SIZE(dm646x_pins), - .intc_base = IO_ADDRESS(DAVINCI_ARM_INTC_BASE), + .intc_base = DAVINCI_ARM_INTC_BASE, .intc_type = DAVINCI_INTC_TYPE_AINTC, .intc_irq_prios = dm646x_default_priorities, .intc_irq_num = DAVINCI_N_AINTC_IRQ, diff --git a/arch/arm/mach-davinci/include/mach/common.h b/arch/arm/mach-davinci/include/mach/common.h index 4c8dfcb4d..005f624 100644 --- a/arch/arm/mach-davinci/include/mach/common.h +++ b/arch/arm/mach-davinci/include/mach/common.h @@ -54,10 +54,11 @@ struct davinci_soc_info { void __iomem *pinmux_base; const struct mux_config *pinmux_pins; unsigned long pinmux_pins_num; - void __iomem *intc_base; + u32 intc_base; int intc_type; u8 *intc_irq_prios; unsigned long intc_irq_num; + u32 *intc_host_map; struct davinci_timer_info *timer_info; int gpio_type; u32 gpio_base; diff --git a/arch/arm/mach-davinci/include/mach/cp_intc.h b/arch/arm/mach-davinci/include/mach/cp_intc.h index 121b114..4e8190e 100644 --- a/arch/arm/mach-davinci/include/mach/cp_intc.h +++ b/arch/arm/mach-davinci/include/mach/cp_intc.h @@ -51,7 +51,6 @@ #define CP_INTC_HOST_PRIO_VECTOR(n) (0x1600 + (n << 2)) #define CP_INTC_VECTOR_ADDR(n) (0x2000 + (n << 2)) -void __init cp_intc_init(void __iomem *base, unsigned short num_irq, - u8 *irq_prio, u32 *host_map); +void __init cp_intc_init(void); #endif /* __ASM_HARDWARE_CP_INTC_H */ diff --git a/arch/arm/mach-davinci/irq.c b/arch/arm/mach-davinci/irq.c index af92ffe..784ddf3 100644 --- a/arch/arm/mach-davinci/irq.c +++ b/arch/arm/mach-davinci/irq.c @@ -116,6 +116,11 @@ void __init davinci_irq_init(void) unsigned i; const u8 *davinci_def_priorities = davinci_soc_info.intc_irq_prios; + davinci_intc_type = DAVINCI_INTC_TYPE_AINTC; + davinci_intc_base = ioremap(davinci_soc_info.intc_base, SZ_4K); + if (WARN_ON(!davinci_intc_base)) + return; + /* Clear all interrupt requests */ davinci_irq_writel(~0x0, FIQ_REG0_OFFSET); davinci_irq_writel(~0x0, FIQ_REG1_OFFSET); @@ -148,7 +153,7 @@ void __init davinci_irq_init(void) } /* set up genirq dispatch for ARM INTC */ - for (i = 0; i < DAVINCI_N_AINTC_IRQ; i++) { + for (i = 0; i < davinci_soc_info.intc_irq_num; i++) { set_irq_chip(i, &davinci_irq_chip_0); set_irq_flags(i, IRQF_VALID | IRQF_PROBE); if (i != IRQ_TINT1_TINT34) -- cgit v0.10.2 From 779b0d53ca41873d59225eb776c5d4493a0abd0f Mon Sep 17 00:00:00 2001 From: Cyril Chemparathy Date: Fri, 7 May 2010 17:06:38 -0400 Subject: Davinci: pinmux - use ioremap() This patch modifies the pinmux implementation so as to ioremap() the pinmux register area on first use. Signed-off-by: Cyril Chemparathy Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c index 2c84f07..94fe971 100644 --- a/arch/arm/mach-davinci/da830.c +++ b/arch/arm/mach-davinci/da830.c @@ -1191,6 +1191,7 @@ static struct davinci_soc_info davinci_soc_info_da830 = { .cpu_clks = da830_clks, .psc_bases = da830_psc_bases, .psc_bases_num = ARRAY_SIZE(da830_psc_bases), + .pinmux_base = DA8XX_SYSCFG0_BASE + 0x120, .pinmux_pins = da830_pins, .pinmux_pins_num = ARRAY_SIZE(da830_pins), .intc_base = DA8XX_CP_INTC_BASE, @@ -1213,7 +1214,5 @@ void __init da830_init(void) if (WARN(!da8xx_syscfg0_base, "Unable to map syscfg0 module")) return; - davinci_soc_info_da830.pinmux_base = DA8XX_SYSCFG0_VIRT(0x120); - davinci_common_init(&davinci_soc_info_da830); } diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c index 6f5ea2a..74d4e49 100644 --- a/arch/arm/mach-davinci/da850.c +++ b/arch/arm/mach-davinci/da850.c @@ -1076,6 +1076,7 @@ static struct davinci_soc_info davinci_soc_info_da850 = { .cpu_clks = da850_clks, .psc_bases = da850_psc_bases, .psc_bases_num = ARRAY_SIZE(da850_psc_bases), + .pinmux_base = DA8XX_SYSCFG0_BASE + 0x120, .pinmux_pins = da850_pins, .pinmux_pins_num = ARRAY_SIZE(da850_pins), .intc_base = DA8XX_CP_INTC_BASE, @@ -1106,8 +1107,6 @@ void __init da850_init(void) if (WARN(!da8xx_syscfg1_base, "Unable to map syscfg1 module")) return; - davinci_soc_info_da850.pinmux_base = DA8XX_SYSCFG0_VIRT(0x120); - davinci_common_init(&davinci_soc_info_da850); /* diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c index 5ab39f6..3834781 100644 --- a/arch/arm/mach-davinci/dm355.c +++ b/arch/arm/mach-davinci/dm355.c @@ -844,7 +844,7 @@ static struct davinci_soc_info davinci_soc_info_dm355 = { .cpu_clks = dm355_clks, .psc_bases = dm355_psc_bases, .psc_bases_num = ARRAY_SIZE(dm355_psc_bases), - .pinmux_base = IO_ADDRESS(DAVINCI_SYSTEM_MODULE_BASE), + .pinmux_base = DAVINCI_SYSTEM_MODULE_BASE, .pinmux_pins = dm355_pins, .pinmux_pins_num = ARRAY_SIZE(dm355_pins), .intc_base = DAVINCI_ARM_INTC_BASE, diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index be340ed..e5e3dce4 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -1049,7 +1049,7 @@ static struct davinci_soc_info davinci_soc_info_dm365 = { .cpu_clks = dm365_clks, .psc_bases = dm365_psc_bases, .psc_bases_num = ARRAY_SIZE(dm365_psc_bases), - .pinmux_base = IO_ADDRESS(DAVINCI_SYSTEM_MODULE_BASE), + .pinmux_base = DAVINCI_SYSTEM_MODULE_BASE, .pinmux_pins = dm365_pins, .pinmux_pins_num = ARRAY_SIZE(dm365_pins), .intc_base = DAVINCI_ARM_INTC_BASE, diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index d3aa1f7..7ad1520 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c @@ -735,7 +735,7 @@ static struct davinci_soc_info davinci_soc_info_dm644x = { .cpu_clks = dm644x_clks, .psc_bases = dm644x_psc_bases, .psc_bases_num = ARRAY_SIZE(dm644x_psc_bases), - .pinmux_base = IO_ADDRESS(DAVINCI_SYSTEM_MODULE_BASE), + .pinmux_base = DAVINCI_SYSTEM_MODULE_BASE, .pinmux_pins = dm644x_pins, .pinmux_pins_num = ARRAY_SIZE(dm644x_pins), .intc_base = DAVINCI_ARM_INTC_BASE, diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index e0153b3..9404565 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c @@ -819,7 +819,7 @@ static struct davinci_soc_info davinci_soc_info_dm646x = { .cpu_clks = dm646x_clks, .psc_bases = dm646x_psc_bases, .psc_bases_num = ARRAY_SIZE(dm646x_psc_bases), - .pinmux_base = IO_ADDRESS(DAVINCI_SYSTEM_MODULE_BASE), + .pinmux_base = DAVINCI_SYSTEM_MODULE_BASE, .pinmux_pins = dm646x_pins, .pinmux_pins_num = ARRAY_SIZE(dm646x_pins), .intc_base = DAVINCI_ARM_INTC_BASE, diff --git a/arch/arm/mach-davinci/include/mach/common.h b/arch/arm/mach-davinci/include/mach/common.h index 005f624..2e07248 100644 --- a/arch/arm/mach-davinci/include/mach/common.h +++ b/arch/arm/mach-davinci/include/mach/common.h @@ -51,7 +51,7 @@ struct davinci_soc_info { struct clk_lookup *cpu_clks; u32 *psc_bases; unsigned long psc_bases_num; - void __iomem *pinmux_base; + u32 pinmux_base; const struct mux_config *pinmux_pins; unsigned long pinmux_pins_num; u32 intc_base; diff --git a/arch/arm/mach-davinci/mux.c b/arch/arm/mach-davinci/mux.c index e9d530a..f34a8dc 100644 --- a/arch/arm/mach-davinci/mux.c +++ b/arch/arm/mach-davinci/mux.c @@ -22,6 +22,8 @@ #include #include +static void __iomem *pinmux_base; + /* * Sets the DAVINCI MUX register based on the table */ @@ -29,14 +31,19 @@ int __init_or_module davinci_cfg_reg(const unsigned long index) { static DEFINE_SPINLOCK(mux_spin_lock); struct davinci_soc_info *soc_info = &davinci_soc_info; - void __iomem *base = soc_info->pinmux_base; unsigned long flags; const struct mux_config *cfg; unsigned int reg_orig = 0, reg = 0; unsigned int mask, warn = 0; - if (!soc_info->pinmux_pins) - BUG(); + if (WARN_ON(!soc_info->pinmux_pins)) + return -ENODEV; + + if (!pinmux_base) { + pinmux_base = ioremap(soc_info->pinmux_base, SZ_4K); + if (WARN_ON(!pinmux_base)) + return -ENOMEM; + } if (index >= soc_info->pinmux_pins_num) { printk(KERN_ERR "Invalid pin mux index: %lu (%lu)\n", @@ -57,7 +64,7 @@ int __init_or_module davinci_cfg_reg(const unsigned long index) unsigned tmp1, tmp2; spin_lock_irqsave(&mux_spin_lock, flags); - reg_orig = __raw_readl(base + cfg->mux_reg); + reg_orig = __raw_readl(pinmux_base + cfg->mux_reg); mask = (cfg->mask << cfg->mask_offset); tmp1 = reg_orig & mask; @@ -69,7 +76,7 @@ int __init_or_module davinci_cfg_reg(const unsigned long index) if (tmp1 != tmp2) warn = 1; - __raw_writel(reg, base + cfg->mux_reg); + __raw_writel(reg, pinmux_base + cfg->mux_reg); spin_unlock_irqrestore(&mux_spin_lock, flags); } -- cgit v0.10.2 From bcd6a1c695c8b404bfde22b276186ac52a20291b Mon Sep 17 00:00:00 2001 From: Cyril Chemparathy Date: Fri, 7 May 2010 17:06:39 -0400 Subject: Davinci: iotable based ioremap() interception This patch allows for a more flexible ioremap() interception based on iotable contents. With this patch, the ioremap() interception code can properly translate addresses only after davinci_soc_info has been initialized. Consequently, in soc-specific init functions, davinci_common_init() has to happen before any ioremap() attempts. The da8xx init sequence has been suitably modified to meet this restriction. Signed-off-by: Cyril Chemparathy Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c index 94fe971..3a7a96f 100644 --- a/arch/arm/mach-davinci/da830.c +++ b/arch/arm/mach-davinci/da830.c @@ -1210,9 +1210,8 @@ static struct davinci_soc_info davinci_soc_info_da830 = { void __init da830_init(void) { - da8xx_syscfg0_base = ioremap(DA8XX_SYSCFG0_BASE, SZ_4K); - if (WARN(!da8xx_syscfg0_base, "Unable to map syscfg0 module")) - return; - davinci_common_init(&davinci_soc_info_da830); + + da8xx_syscfg0_base = ioremap(DA8XX_SYSCFG0_BASE, SZ_4K); + WARN(!da8xx_syscfg0_base, "Unable to map syscfg0 module"); } diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c index 74d4e49..6b8331b 100644 --- a/arch/arm/mach-davinci/da850.c +++ b/arch/arm/mach-davinci/da850.c @@ -1099,6 +1099,8 @@ void __init da850_init(void) { unsigned int v; + davinci_common_init(&davinci_soc_info_da850); + da8xx_syscfg0_base = ioremap(DA8XX_SYSCFG0_BASE, SZ_4K); if (WARN(!da8xx_syscfg0_base, "Unable to map syscfg0 module")) return; @@ -1107,8 +1109,6 @@ void __init da850_init(void) if (WARN(!da8xx_syscfg1_base, "Unable to map syscfg1 module")) return; - davinci_common_init(&davinci_soc_info_da850); - /* * Move the clock source of Async3 domain to PLL1 SYSCLK2. * This helps keeping the peripherals on this domain insulated diff --git a/arch/arm/mach-davinci/include/mach/common.h b/arch/arm/mach-davinci/include/mach/common.h index 2e07248..a57cba2 100644 --- a/arch/arm/mach-davinci/include/mach/common.h +++ b/arch/arm/mach-davinci/include/mach/common.h @@ -39,7 +39,13 @@ struct davinci_timer_info { struct davinci_gpio_controller; -/* SoC specific init support */ +/* + * SoC info passed into common davinci modules. + * + * Base addresses in this structure should be physical and not virtual. + * Modules that take such base addresses, should internally ioremap() them to + * use. + */ struct davinci_soc_info { struct map_desc *io_desc; unsigned long io_desc_num; diff --git a/arch/arm/mach-davinci/io.c b/arch/arm/mach-davinci/io.c index a1c0b6b..8ea60a8b 100644 --- a/arch/arm/mach-davinci/io.c +++ b/arch/arm/mach-davinci/io.c @@ -12,19 +12,29 @@ #include #include +#include -#define BETWEEN(p, st, sz) ((p) >= (st) && (p) < ((st) + (sz))) -#define XLATE(p, pst, vst) ((void __iomem *)((p) - (pst) + (vst))) +#include /* * Intercept ioremap() requests for addresses in our fixed mapping regions. */ void __iomem *davinci_ioremap(unsigned long p, size_t size, unsigned int type) { - if (BETWEEN(p, IO_PHYS, IO_SIZE)) - return XLATE(p, IO_PHYS, IO_VIRT); + struct map_desc *desc = davinci_soc_info.io_desc; + int desc_num = davinci_soc_info.io_desc_num; + int i; - return __arm_ioremap_caller(p, size, type, __builtin_return_address(0)); + for (i = 0; i < desc_num; i++, desc++) { + unsigned long iophys = __pfn_to_phys(desc->pfn); + unsigned long iosize = desc->length; + + if (p >= iophys && (p + size) <= (iophys + iosize)) + return __io(desc->virtual + p - iophys); + } + + return __arm_ioremap_caller(p, size, type, + __builtin_return_address(0)); } EXPORT_SYMBOL(davinci_ioremap); -- cgit v0.10.2 From 2168e76d6ba061fcc95095a3f54ceef8588cbb90 Mon Sep 17 00:00:00 2001 From: Thomas Koeller Date: Tue, 11 May 2010 17:06:47 +0200 Subject: DM365: Added PINMUX definitions for GPIO30..32 Board code may want to use them. Signed-off-by: Thomas Koeller Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index e5e3dce4..dd7c204 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -569,6 +569,9 @@ MUX_CFG(DM365, SPI4_SDENA0, 4, 20, 3, 1, false) MUX_CFG(DM365, SPI4_SDENA1, 4, 16, 3, 2, false) MUX_CFG(DM365, GPIO20, 3, 21, 3, 0, false) +MUX_CFG(DM365, GPIO30, 4, 6, 3, 0, false) +MUX_CFG(DM365, GPIO31, 4, 8, 3, 0, false) +MUX_CFG(DM365, GPIO32, 4, 10, 3, 0, false) MUX_CFG(DM365, GPIO33, 4, 12, 3, 0, false) MUX_CFG(DM365, GPIO40, 4, 26, 3, 0, false) MUX_CFG(DM365, GPIO64_57, 2, 6, 1, 0, false) diff --git a/arch/arm/mach-davinci/include/mach/mux.h b/arch/arm/mach-davinci/include/mach/mux.h index 743dbd2..4a1fdd3 100644 --- a/arch/arm/mach-davinci/include/mach/mux.h +++ b/arch/arm/mach-davinci/include/mach/mux.h @@ -289,6 +289,9 @@ enum davinci_dm365_index { /* GPIO */ DM365_GPIO20, + DM365_GPIO30, + DM365_GPIO31, + DM365_GPIO32, DM365_GPIO33, DM365_GPIO40, DM365_GPIO64_57, -- cgit v0.10.2 From 0efe2b7442caaf087e56ae9b68fa5f61f4761fa8 Mon Sep 17 00:00:00 2001 From: Thomas Koeller Date: Tue, 11 May 2010 17:06:48 +0200 Subject: DM365: Make CLKOUTx available Added PINMUX configurations for the CLKOUT0 .. CLKOUT2 functions, for boards that want to use these clocks. Signed-off-by: Thomas Koeller Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index dd7c204..d0d24d4 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -568,6 +568,10 @@ MUX_CFG(DM365, SPI4_SDO, 4, 16, 3, 1, false) MUX_CFG(DM365, SPI4_SDENA0, 4, 20, 3, 1, false) MUX_CFG(DM365, SPI4_SDENA1, 4, 16, 3, 2, false) +MUX_CFG(DM365, CLKOUT0, 4, 20, 3, 3, false) +MUX_CFG(DM365, CLKOUT1, 4, 16, 3, 3, false) +MUX_CFG(DM365, CLKOUT2, 4, 8, 3, 3, false) + MUX_CFG(DM365, GPIO20, 3, 21, 3, 0, false) MUX_CFG(DM365, GPIO30, 4, 6, 3, 0, false) MUX_CFG(DM365, GPIO31, 4, 8, 3, 0, false) diff --git a/arch/arm/mach-davinci/include/mach/mux.h b/arch/arm/mach-davinci/include/mach/mux.h index 4a1fdd3..07ef83b 100644 --- a/arch/arm/mach-davinci/include/mach/mux.h +++ b/arch/arm/mach-davinci/include/mach/mux.h @@ -287,6 +287,11 @@ enum davinci_dm365_index { DM365_SPI4_SDENA0, DM365_SPI4_SDENA1, + /* Clock */ + DM365_CLKOUT0, + DM365_CLKOUT1, + DM365_CLKOUT2, + /* GPIO */ DM365_GPIO20, DM365_GPIO30, -- cgit v0.10.2 From 7735227e76e1660e448ec66c30e7bfd06f7cd9b7 Mon Sep 17 00:00:00 2001 From: Thomas Koeller Date: Tue, 11 May 2010 17:06:49 +0200 Subject: DM365: Added more PINMUX configurations for AEMIF More complete AEMIF support for boards. Signed-off-by: Thomas Koeller Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index d0d24d4..a146849 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -485,11 +485,14 @@ MUX_CFG(DM365, SD1_DATA0, 4, 22, 3, 1, false) MUX_CFG(DM365, I2C_SDA, 3, 23, 3, 2, false) MUX_CFG(DM365, I2C_SCL, 3, 21, 3, 2, false) -MUX_CFG(DM365, AEMIF_AR, 2, 0, 3, 1, false) +MUX_CFG(DM365, AEMIF_AR_A14, 2, 0, 3, 1, false) +MUX_CFG(DM365, AEMIF_AR_BA0, 2, 0, 3, 2, false) MUX_CFG(DM365, AEMIF_A3, 2, 2, 3, 1, false) MUX_CFG(DM365, AEMIF_A7, 2, 4, 3, 1, false) MUX_CFG(DM365, AEMIF_D15_8, 2, 6, 1, 1, false) MUX_CFG(DM365, AEMIF_CE0, 2, 7, 1, 0, false) +MUX_CFG(DM365, AEMIF_CE1, 2, 8, 1, 0, false) +MUX_CFG(DM365, AEMIF_WE_OE, 2, 9, 1, 0, false) MUX_CFG(DM365, MCBSP0_BDX, 0, 23, 1, 1, false) MUX_CFG(DM365, MCBSP0_X, 0, 22, 1, 1, false) diff --git a/arch/arm/mach-davinci/include/mach/mux.h b/arch/arm/mach-davinci/include/mach/mux.h index 07ef83b..de11aac 100644 --- a/arch/arm/mach-davinci/include/mach/mux.h +++ b/arch/arm/mach-davinci/include/mach/mux.h @@ -194,11 +194,14 @@ enum davinci_dm365_index { DM365_I2C_SCL, /* AEMIF */ - DM365_AEMIF_AR, + DM365_AEMIF_AR_A14, + DM365_AEMIF_AR_BA0, DM365_AEMIF_A3, DM365_AEMIF_A7, DM365_AEMIF_D15_8, DM365_AEMIF_CE0, + DM365_AEMIF_CE1, + DM365_AEMIF_WE_OE, /* ASP0 function */ DM365_MCBSP0_BDX, -- cgit v0.10.2 From e6114fa1d1d6a588766f28081b971047dd3e5def Mon Sep 17 00:00:00 2001 From: Anatolij Gustschin Date: Wed, 5 May 2010 00:18:59 +0200 Subject: serial: mpc52xx_uart: fix null pointer dereference Commit 6acc6833510db8f72b5ef343296d97480555fda9 introduced NULL pointer dereference and kernel crash on ppc32 machines while booting. Fix this bug now. Reported-by: Leonardo Chiquitto Tested-by: Leonardo Chiquitto Signed-off-by: Anatolij Gustschin Acked-by: Grant Likely Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index a176ab4..02469c3 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c @@ -1467,7 +1467,7 @@ mpc52xx_uart_init(void) /* * Map the PSC FIFO Controller and init if on MPC512x. */ - if (psc_ops->fifoc_init) { + if (psc_ops && psc_ops->fifoc_init) { ret = psc_ops->fifoc_init(); if (ret) return ret; -- cgit v0.10.2 From 77945febbe60a69e9dcab7f49d33a1aa1e436973 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 4 May 2010 20:42:36 +0100 Subject: tty: Fix unbalanced BKL handling in error path Arnd noted: After the "retry_open:" label, we first get the tty_mutex and then the BKL. However a the end of tty_open, we jump back to retry_open with the BKL still held. If we run into this case, the tty_open function will be left with the BKL still held. Signed-off-by: Alan Cox Acked-by: Arnd Bergmann Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 6da962c..d71f0fc 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -1875,6 +1875,7 @@ got_driver: */ if (filp->f_op == &hung_up_tty_fops) filp->f_op = &tty_fops; + unlock_kernel(); goto retry_open; } unlock_kernel(); -- cgit v0.10.2 From 1c5250d6163dac28be3afabdfb6c723f107051b7 Mon Sep 17 00:00:00 2001 From: Valentin Longchamp Date: Wed, 5 May 2010 11:47:07 +0200 Subject: serial: imx.c: fix CTS trigger level lower to avoid lost chars MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The imx CTS trigger level is left at its reset value that is 32 chars. Since the RX FIFO has 32 entries, when CTS is raised, the FIFO already is full. However, some serial port devices first empty their TX FIFO before stopping when CTS is raised, resulting in lost chars. This patch sets the trigger level lower so that other chars arrive after CTS is raised, there is still room for 16 of them. Signed-off-by: Valentin Longchamp Tested-by: Philippe Rétornaz Acked-by: Wolfram Sang Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 4315b23..eacb588 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -120,7 +120,8 @@ #define MX2_UCR3_RXDMUXSEL (1<<2) /* RXD Muxed Input Select, on mx2/mx3 */ #define UCR3_INVT (1<<1) /* Inverted Infrared transmission */ #define UCR3_BPEN (1<<0) /* Preset registers enable */ -#define UCR4_CTSTL_32 (32<<10) /* CTS trigger level (32 chars) */ +#define UCR4_CTSTL_SHF 10 /* CTS trigger level shift */ +#define UCR4_CTSTL_MASK 0x3F /* CTS trigger is 6 bits wide */ #define UCR4_INVR (1<<9) /* Inverted infrared reception */ #define UCR4_ENIRI (1<<8) /* Serial infrared interrupt enable */ #define UCR4_WKEN (1<<7) /* Wake interrupt enable */ @@ -591,6 +592,9 @@ static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode) return 0; } +/* half the RX buffer size */ +#define CTSTL 16 + static int imx_startup(struct uart_port *port) { struct imx_port *sport = (struct imx_port *)port; @@ -607,6 +611,10 @@ static int imx_startup(struct uart_port *port) if (USE_IRDA(sport)) temp |= UCR4_IRSC; + /* set the trigger level for CTS */ + temp &= ~(UCR4_CTSTL_MASK<< UCR4_CTSTL_SHF); + temp |= CTSTL<< UCR4_CTSTL_SHF; + writel(temp & ~UCR4_DREN, sport->port.membase + UCR4); if (USE_IRDA(sport)) { -- cgit v0.10.2 From 8769e1c7177fd9f6981042bcc6c2851c99a4a7e7 Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Thu, 13 May 2010 19:22:58 +0200 Subject: perf hist: Fix hists__browse no-newt case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix mistake in a parameter type of the no-newt hists__browse() version. Fixes: builtin-report.c: In function ‘__cmd_report’: builtin-report.c:314: erreur: incompatible type for argument 1 of ‘hists__browse’ Signed-off-by: Frederic Weisbecker Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras LKML-Reference: <1273771378-8577-1-git-send-regression-fweisbec@gmail.com> Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index ed9c067..0b4c8df 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -78,7 +78,7 @@ void hists__filter_by_dso(struct hists *self, const struct dso *dso); void hists__filter_by_thread(struct hists *self, const struct thread *thread); #ifdef NO_NEWT_SUPPORT -static inline int hists__browse(struct hists self __used, +static inline int hists__browse(struct hists *self __used, const char *helpline __used, const char *input_name __used) { -- cgit v0.10.2 From 8a0ecfb8b47dc765fdf460913231876bbc95385e Mon Sep 17 00:00:00 2001 From: Frederic Weisbecker Date: Thu, 13 May 2010 19:47:16 +0200 Subject: perf hist: Fix missing getline declaration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit hist.c needs to include util.h so that it gets stdio.h inclusion with __GNU_SOURCE defined. Fixes: util/hist.c: In function ‘hist_entry__parse_objdump_line’: util/hist.c:931: erreur: implicit declaration of function ‘getline’ util/hist.c:931: erreur: nested extern declaration of ‘getline’ Signed-off-by: Frederic Weisbecker Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Paul Mackerras LKML-Reference: <1273772836-11533-1-git-send-regression-fweisbec@gmail.com> Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 451d2e4..5dc4f84 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -1,3 +1,4 @@ +#include "util.h" #include "hist.h" #include "session.h" #include "sort.h" -- cgit v0.10.2 From 2e6cdf996ba43ce0b090ffbf754f83e17362cd69 Mon Sep 17 00:00:00 2001 From: Stephane Eranian Date: Wed, 12 May 2010 10:40:01 +0200 Subject: perf tools: change event inheritance logic in stat and record MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit By default, event inheritance across fork and pthread_create was on but the -i option of stat and record, which enabled inheritance, led to believe it was off by default. This patch fixes this logic by inverting the meaning of the -i option. By default inheritance is on whether you attach to a process (-p), a thread (-t) or start a process. If you pass -i, then you turn off inheritance. Turning off inheritance if you don't need it, helps limit perf resource usage as well. The patch also fixes perf stat -t xxxx and perf record -t xxxx which did not start the counters. Acked-by: Frederic Weisbecker Cc: David S. Miller Cc: Frédéric Weisbecker Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra LKML-Reference: <4bea9d2f.d60ce30a.0b5b.08e1@mx.google.com> Signed-off-by: Stephane Eranian Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt index 020d871..34e255f 100644 --- a/tools/perf/Documentation/perf-record.txt +++ b/tools/perf/Documentation/perf-record.txt @@ -69,8 +69,8 @@ OPTIONS Output file name. -i:: ---inherit:: - Child tasks inherit counters. +--no-inherit:: + Child tasks do not inherit counters. -F:: --freq=:: Profile at this frequency. diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt index 484080d..2cab8e8 100644 --- a/tools/perf/Documentation/perf-stat.txt +++ b/tools/perf/Documentation/perf-stat.txt @@ -31,8 +31,8 @@ OPTIONS hexadecimal event descriptor. -i:: ---inherit:: - child tasks inherit counters +--no-inherit:: + child tasks do not inherit counters -p:: --pid=:: stat events on existing pid diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 6b77b28..0f467cf 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -54,7 +54,7 @@ static pid_t target_tid = -1; static pid_t *all_tids = NULL; static int thread_num = 0; static pid_t child_pid = -1; -static bool inherit = true; +static bool no_inherit = false; static enum write_mode_t write_mode = WRITE_FORCE; static bool call_graph = false; static bool inherit_stat = false; @@ -298,8 +298,8 @@ static void create_counter(int counter, int cpu) attr->mmap = track; attr->comm = track; - attr->inherit = inherit; - if (target_pid == -1 && !system_wide) { + attr->inherit = !no_inherit; + if (target_pid == -1 && target_tid == -1 && !system_wide) { attr->disabled = 1; attr->enable_on_exec = 1; } @@ -641,7 +641,7 @@ static int __cmd_record(int argc, const char **argv) close(child_ready_pipe[0]); } - if ((!system_wide && !inherit) || profile_cpu != -1) { + if ((!system_wide && no_inherit) || profile_cpu != -1) { open_counters(profile_cpu); } else { nr_cpus = read_cpu_map(); @@ -821,8 +821,8 @@ static const struct option options[] = { "event period to sample"), OPT_STRING('o', "output", &output_name, "file", "output file name"), - OPT_BOOLEAN('i', "inherit", &inherit, - "child tasks inherit counters"), + OPT_BOOLEAN('i', "no-inherit", &no_inherit, + "child tasks do not inherit counters"), OPT_INTEGER('F', "freq", &user_freq, "profile at this frequency"), OPT_INTEGER('m', "mmap-pages", &mmap_pages, diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index e619ac8..ff8c413 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -72,7 +72,7 @@ static unsigned int nr_cpus = 0; static int run_idx = 0; static int run_count = 1; -static bool inherit = true; +static bool no_inherit = false; static bool scale = true; static pid_t target_pid = -1; static pid_t target_tid = -1; @@ -167,8 +167,8 @@ static int create_perf_stat_counter(int counter) ++ncreated; } } else { - attr->inherit = inherit; - if (target_pid == -1) { + attr->inherit = !no_inherit; + if (target_pid == -1 && target_tid == -1) { attr->disabled = 1; attr->enable_on_exec = 1; } @@ -518,8 +518,8 @@ static const struct option options[] = { OPT_CALLBACK('e', "event", NULL, "event", "event selector. use 'perf list' to list available events", parse_events), - OPT_BOOLEAN('i', "inherit", &inherit, - "child tasks inherit counters"), + OPT_BOOLEAN('i', "no-inherit", &no_inherit, + "child tasks do not inherit counters"), OPT_INTEGER('p', "pid", &target_pid, "stat events on existing process id"), OPT_INTEGER('t', "tid", &target_tid, -- cgit v0.10.2 From 5d2be7cb198a0a6bc6088d3806fb7261b184ad89 Mon Sep 17 00:00:00 2001 From: Kirill Smelkov Date: Thu, 13 May 2010 14:39:25 +0400 Subject: perf trace scripts: Fix typos in perf-trace-python.txt option option -> option special special -> special Signed-off-by: Kirill Smelkov Cc: Tom Zanussi LKML-Reference: <1273747165-17242-1-git-send-email-kirr@mns.spb.ru> Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Documentation/perf-trace-python.txt b/tools/perf/Documentation/perf-trace-python.txt index 864aac2..693be80 100644 --- a/tools/perf/Documentation/perf-trace-python.txt +++ b/tools/perf/Documentation/perf-trace-python.txt @@ -182,7 +182,7 @@ mean either that the record step recorded event types that it wasn't really interested in, or the script was run against a trace file that doesn't correspond to the script. -The script generated by -g option option simply prints a line for each +The script generated by -g option simply prints a line for each event found in the trace stream i.e. it basically just dumps the event and its parameter values to stdout. The print_header() function is simply a utility function used for that purpose. Let's rename the @@ -582,7 +582,7 @@ files: flag_str(event_name, field_name, field_value) - returns the string represention corresponding to field_value for the flag field field_name of event event_name symbol_str(event_name, field_name, field_value) - returns the string represention corresponding to field_value for the symbolic field field_name of event event_name -The *autodict* function returns a special special kind of Python +The *autodict* function returns a special kind of Python dictionary that implements Perl's 'autovivifying' hashes in Python i.e. with autovivifying hashes, you can assign nested hash values without having to go to the trouble of creating intermediate levels if -- cgit v0.10.2 From f01487119dda3d9f58c9729c7361ecc50a61c188 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Tue, 27 Apr 2010 12:13:48 +0200 Subject: x86, amd: Check X86_FEATURE_OSVW bit before accessing OSVW MSRs If host CPU is exposed to a guest the OSVW MSRs are not guaranteed to be present and a GP fault occurs. Thus checking the feature flag is essential. Cc: # .32.x .33.x Signed-off-by: Andreas Herrmann LKML-Reference: <20100427101348.GC4489@alberich.amd.com> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 28ad9f4..0415c3e 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -546,11 +546,13 @@ static int __cpuinit check_c1e_idle(const struct cpuinfo_x86 *c) * check OSVW bit for CPUs that are not affected * by erratum #400 */ - rdmsrl(MSR_AMD64_OSVW_ID_LENGTH, val); - if (val >= 2) { - rdmsrl(MSR_AMD64_OSVW_STATUS, val); - if (!(val & BIT(1))) - goto no_c1e_idle; + if (cpu_has(c, X86_FEATURE_OSVW)) { + rdmsrl(MSR_AMD64_OSVW_ID_LENGTH, val); + if (val >= 2) { + rdmsrl(MSR_AMD64_OSVW_STATUS, val); + if (!(val & BIT(1))) + goto no_c1e_idle; + } } return 1; } -- cgit v0.10.2 From df3c6b08d01581052040611f2dced989b83244c9 Mon Sep 17 00:00:00 2001 From: Jassi Brar Date: Tue, 9 Mar 2010 15:10:31 +0900 Subject: ARM: S3C6410: Define clk_src2 register Define S3C6410 specific register - CLK_SRC2 Signed-off-by: Jassi Brar Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c64xx/include/mach/regs-clock.h b/arch/arm/mach-s3c64xx/include/mach/regs-clock.h index 3ef6274..0114eb0 100644 --- a/arch/arm/mach-s3c64xx/include/mach/regs-clock.h +++ b/arch/arm/mach-s3c64xx/include/mach/regs-clock.h @@ -33,6 +33,7 @@ #define S3C_PCLK_GATE S3C_CLKREG(0x34) #define S3C_SCLK_GATE S3C_CLKREG(0x38) #define S3C_MEM0_GATE S3C_CLKREG(0x3C) +#define S3C6410_CLK_SRC2 S3C_CLKREG(0x10C) /* CLKDIV0 */ #define S3C6400_CLKDIV0_PCLK_MASK (0xf << 12) -- cgit v0.10.2 From bc8eb1e2fa23ff433531c8b631f76302843f52e6 Mon Sep 17 00:00:00 2001 From: Jassi Brar Date: Tue, 9 Mar 2010 15:10:32 +0900 Subject: ARM: S3C6410: Declare IISCDCLK_V4 Clock Declare the source of clock provided at Xi2sCDCLK2 pin for IISv4 controller. Signed-off-by: Jassi Brar Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c64xx/clock.c b/arch/arm/mach-s3c64xx/clock.c index 2ac2e7d..c0041eb 100644 --- a/arch/arm/mach-s3c64xx/clock.c +++ b/arch/arm/mach-s3c64xx/clock.c @@ -518,6 +518,11 @@ static struct clk clk_iis_cd1 = { .id = -1, }; +static struct clk clk_iisv4_cd = { + .name = "iis_cdclk_v4", + .id = -1, +}; + static struct clk clk_pcm_cd = { .name = "pcm_cdclk", .id = -1, @@ -749,6 +754,7 @@ static struct clk *clks1[] __initdata = { &clk_ext_xtal_mux, &clk_iis_cd0, &clk_iis_cd1, + &clk_iisv4_cd, &clk_pcm_cd, &clk_mout_epll.clk, &clk_mout_mpll.clk, -- cgit v0.10.2 From 1aede2ea50a56a83dd95e7d1139a948212be2446 Mon Sep 17 00:00:00 2001 From: Jassi Brar Date: Tue, 9 Mar 2010 15:10:33 +0900 Subject: ARM: S3C6410: Declare possible sources of audio-bus2 Declare possible sources of CLKAUDIO[2]/audio-bus for IISv4 controller. Signed-off-by: Jassi Brar Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c64xx/clock.c b/arch/arm/mach-s3c64xx/clock.c index c0041eb..6c286d5 100644 --- a/arch/arm/mach-s3c64xx/clock.c +++ b/arch/arm/mach-s3c64xx/clock.c @@ -554,6 +554,19 @@ static struct clksrc_sources clkset_audio1 = { .nr_sources = ARRAY_SIZE(clkset_audio1_list), }; +static struct clk *clkset_audio2_list[] = { + [0] = &clk_mout_epll.clk, + [1] = &clk_dout_mpll, + [2] = &clk_fin_epll, + [3] = &clk_iisv4_cd, + [4] = &clk_pcm_cd, +}; + +static struct clksrc_sources clkset_audio2 = { + .sources = clkset_audio2_list, + .nr_sources = ARRAY_SIZE(clkset_audio2_list), +}; + static struct clk *clkset_camif_list[] = { &clk_h2, }; -- cgit v0.10.2 From 835879a8848e9de93d38cdae99bda18d08545586 Mon Sep 17 00:00:00 2001 From: Jassi Brar Date: Tue, 9 Mar 2010 15:10:34 +0900 Subject: ARM: S3C6410: Declare IISv4 audio-bus clock Declare 'audio-bus' clock for IISv4 controller of S3C6410. Even though the name is same as that for IISv3, the id is set to -1(just one instance of the controller is available) which helps always fetch the correct clock. Signed-off-by: Jassi Brar Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c64xx/clock.c b/arch/arm/mach-s3c64xx/clock.c index 6c286d5..da83595 100644 --- a/arch/arm/mach-s3c64xx/clock.c +++ b/arch/arm/mach-s3c64xx/clock.c @@ -670,6 +670,16 @@ static struct clksrc_clk clksrcs[] = { .sources = &clkset_audio1, }, { .clk = { + .name = "audio-bus", + .id = -1, /* There's only one IISv4 port */ + .ctrlbit = S3C6410_CLKCON_SCLK_AUDIO2, + .enable = s3c64xx_sclk_ctrl, + }, + .reg_src = { .reg = S3C6410_CLK_SRC2, .shift = 0, .size = 3 }, + .reg_div = { .reg = S3C_CLK_DIV2, .shift = 24, .size = 4 }, + .sources = &clkset_audio2, + }, { + .clk = { .name = "irda-bus", .id = 0, .ctrlbit = S3C_CLKCON_SCLK_IRDA, -- cgit v0.10.2 From 9e565292270a2d55524be38835104c564ac8f795 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Thu, 13 May 2010 21:43:03 -0700 Subject: x86: Use .cfi_sections for assembly code The newer assemblers support the .cfi_sections directive so we can put the CFI from .S files into the .debug_frame section that is preserved in unstripped vmlinux and in separate debuginfo, rather than the .eh_frame section that is now discarded by vmlinux.lds.S. Signed-off-by: Roland McGrath LKML-Reference: <20100514044303.A6FE7400BE@magilla.sf.frob.com> Signed-off-by: H. Peter Anvin diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 0a43dc5..8aa1b59 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -95,8 +95,9 @@ sp-$(CONFIG_X86_64) := rsp cfi := $(call as-instr,.cfi_startproc\n.cfi_rel_offset $(sp-y)$(comma)0\n.cfi_endproc,-DCONFIG_AS_CFI=1) # is .cfi_signal_frame supported too? cfi-sigframe := $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1) -KBUILD_AFLAGS += $(cfi) $(cfi-sigframe) -KBUILD_CFLAGS += $(cfi) $(cfi-sigframe) +cfi-sections := $(call as-instr,.cfi_sections .debug_frame,-DCONFIG_AS_CFI_SECTIONS=1) +KBUILD_AFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) +KBUILD_CFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) LDFLAGS := -m elf_$(UTS_MACHINE) diff --git a/arch/x86/include/asm/dwarf2.h b/arch/x86/include/asm/dwarf2.h index ae6253a..733f7e9 100644 --- a/arch/x86/include/asm/dwarf2.h +++ b/arch/x86/include/asm/dwarf2.h @@ -34,6 +34,18 @@ #define CFI_SIGNAL_FRAME #endif +#if defined(CONFIG_AS_CFI_SECTIONS) && defined(__ASSEMBLY__) + /* + * Emit CFI data in .debug_frame sections, not .eh_frame sections. + * The latter we currently just discard since we don't do DWARF + * unwinding at runtime. So only the offline DWARF information is + * useful to anyone. Note we should not use this directive if this + * file is used in the vDSO assembly, or if vmlinux.lds.S gets + * changed so it doesn't discard .eh_frame. + */ + .cfi_sections .debug_frame +#endif + #else /* -- cgit v0.10.2 From a5e48b88da225580394f825ffe67e444b050074b Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Fri, 14 May 2010 07:40:46 +0200 Subject: microblaze: Fix module loading on system with WB cache There is necessary to flush whole dcache. Icache work should be done in kernel/module.c. Signed-off-by: Michal Simek diff --git a/arch/microblaze/kernel/module.c b/arch/microblaze/kernel/module.c index cbecf11..0e73f66 100644 --- a/arch/microblaze/kernel/module.c +++ b/arch/microblaze/kernel/module.c @@ -16,6 +16,7 @@ #include #include +#include void *module_alloc(unsigned long size) { @@ -151,6 +152,7 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab, int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *module) { + flush_dcache(); return 0; } -- cgit v0.10.2 From 4ae69e6b718589abe97c9625ccbb1e0bc95a8c0e Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Thu, 22 Apr 2010 12:19:17 -0700 Subject: mmap_min_addr check CAP_SYS_RAWIO only for write Redirecting directly to lsm, here's the patch discussed on lkml: http://lkml.org/lkml/2010/4/22/219 The mmap_min_addr value is useful information for an admin to see without being root ("is my system vulnerable to kernel NULL pointer attacks?") and its setting is trivially easy for an attacker to determine by calling mmap() in PAGE_SIZE increments starting at 0, so trying to keep it private has no value. Only require CAP_SYS_RAWIO if changing the value, not reading it. Comment from Serge : Me, I like to write my passwords with light blue pen on dark blue paper, pasted on my window - if you're going to get my password, you're gonna get a headache. Signed-off-by: Kees Cook Acked-by: Serge Hallyn Signed-off-by: James Morris (cherry picked from commit 822cceec7248013821d655545ea45d1c6a9d15b3) diff --git a/security/min_addr.c b/security/min_addr.c index e86f297..f728728 100644 --- a/security/min_addr.c +++ b/security/min_addr.c @@ -33,7 +33,7 @@ int mmap_min_addr_handler(struct ctl_table *table, int write, { int ret; - if (!capable(CAP_SYS_RAWIO)) + if (write && !capable(CAP_SYS_RAWIO)) return -EPERM; ret = proc_doulongvec_minmax(table, write, buffer, lenp, ppos); -- cgit v0.10.2 From c8446b9bdabcb0caa61bb341bd73c58f7104b503 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 14 May 2010 10:36:42 -0300 Subject: perf hist: Make event__totals per hists MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is one more thing that started global but are more useful per hist or per session. Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index fd1b786..77bcc9b 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -365,7 +365,7 @@ static int __cmd_annotate(void) goto out_delete; if (dump_trace) { - event__print_totals(); + perf_session__fprintf_nr_events(session, stdout); goto out_delete; } diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 04de338..f13cda1 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -139,6 +139,12 @@ static int add_event_total(struct perf_session *session, return -ENOMEM; hists->stats.total += data->period; + /* + * FIXME: add_event_total should be moved from here to + * perf_session__process_event so that the proper hist is passed to + * the event_op methods. + */ + hists__inc_nr_events(hists, PERF_RECORD_SAMPLE); session->hists.stats.total += data->period; return 0; } @@ -293,7 +299,7 @@ static int __cmd_report(void) goto out_delete; if (dump_trace) { - event__print_totals(); + perf_session__fprintf_nr_events(session, stdout); goto out_delete; } diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index cce006e..3e8fec1 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -7,6 +7,23 @@ #include "strlist.h" #include "thread.h" +const char *event__name[] = { + [0] = "TOTAL", + [PERF_RECORD_MMAP] = "MMAP", + [PERF_RECORD_LOST] = "LOST", + [PERF_RECORD_COMM] = "COMM", + [PERF_RECORD_EXIT] = "EXIT", + [PERF_RECORD_THROTTLE] = "THROTTLE", + [PERF_RECORD_UNTHROTTLE] = "UNTHROTTLE", + [PERF_RECORD_FORK] = "FORK", + [PERF_RECORD_READ] = "READ", + [PERF_RECORD_SAMPLE] = "SAMPLE", + [PERF_RECORD_HEADER_ATTR] = "ATTR", + [PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE", + [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA", + [PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID", +}; + static pid_t event__synthesize_comm(pid_t pid, int full, event__handler_t process, struct perf_session *session) diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 48c2cc9..8577085 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -160,4 +160,6 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session, struct addr_location *al, symbol_filter_t filter); int event__parse_sample(event_t *event, u64 type, struct sample_data *data); +extern const char *event__name[]; + #endif /* __PERF_RECORD_H */ diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 5dc4f84..1614ad7 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -1028,3 +1028,24 @@ int hist_entry__annotate(struct hist_entry *self, struct list_head *head) pclose(file); return 0; } + +void hists__inc_nr_events(struct hists *self, u32 type) +{ + ++self->hists.stats.nr_events[0]; + ++self->hists.stats.nr_events[type]; +} + +size_t hists__fprintf_nr_events(struct hists *self, FILE *fp) +{ + int i; + size_t ret = 0; + + for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) { + if (!event__name[i]) + continue; + ret += fprintf(fp, "%10s events: %10d\n", + event__name[i], self->stats.nr_events[i]); + } + + return ret; +} diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 0b4c8df..97b8962 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -40,6 +40,8 @@ struct sym_priv { struct events_stats { u64 total; u64 lost; + u32 nr_events[PERF_RECORD_HEADER_MAX]; + u32 nr_unknown_events; }; struct hists { @@ -68,6 +70,10 @@ void hist_entry__free(struct hist_entry *); void hists__output_resort(struct hists *self); void hists__collapse_resort(struct hists *self); + +void hists__inc_nr_events(struct hists *self, u32 type); +size_t hists__fprintf_nr_events(struct hists *self, FILE *fp); + size_t hists__fprintf(struct hists *self, struct hists *pair, bool show_displacement, FILE *fp); diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 72a7f6a..7231f6b 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -94,7 +94,6 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc self->mmap_window = 32; self->cwd = NULL; self->cwdlen = 0; - self->unknown_events = 0; self->machines = RB_ROOT; self->repipe = repipe; INIT_LIST_HEAD(&self->ordered_samples.samples_head); @@ -241,36 +240,6 @@ static void perf_event_ops__fill_defaults(struct perf_event_ops *handler) } } -static const char *event__name[] = { - [0] = "TOTAL", - [PERF_RECORD_MMAP] = "MMAP", - [PERF_RECORD_LOST] = "LOST", - [PERF_RECORD_COMM] = "COMM", - [PERF_RECORD_EXIT] = "EXIT", - [PERF_RECORD_THROTTLE] = "THROTTLE", - [PERF_RECORD_UNTHROTTLE] = "UNTHROTTLE", - [PERF_RECORD_FORK] = "FORK", - [PERF_RECORD_READ] = "READ", - [PERF_RECORD_SAMPLE] = "SAMPLE", - [PERF_RECORD_HEADER_ATTR] = "ATTR", - [PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE", - [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA", - [PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID", -}; - -unsigned long event__total[PERF_RECORD_HEADER_MAX]; - -void event__print_totals(void) -{ - int i; - for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) { - if (!event__name[i]) - continue; - pr_info("%10s events: %10ld\n", - event__name[i], event__total[i]); - } -} - void mem_bswap_64(void *src, int byte_size) { u64 *m = src; @@ -580,8 +549,7 @@ static int perf_session__process_event(struct perf_session *self, dump_printf("%#Lx [%#x]: PERF_RECORD_%s", offset + head, event->header.size, event__name[event->header.type]); - ++event__total[0]; - ++event__total[event->header.type]; + hists__inc_nr_events(self, event->header.type); } if (self->header.needs_swap && event__swap_ops[event->header.type]) @@ -619,7 +587,7 @@ static int perf_session__process_event(struct perf_session *self, case PERF_RECORD_FINISHED_ROUND: return ops->finished_round(event, self, ops); default: - self->unknown_events++; + ++self->hists.stats.nr_unknown_events; return -1; } } diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index ce00fa6..e7fce48 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h @@ -30,8 +30,6 @@ struct perf_session { struct machine host_machine; struct rb_root machines; struct rb_root hists_tree; - unsigned long event_total[PERF_RECORD_MAX]; - unsigned long unknown_events; /* * FIXME: should point to the first entry in hists_tree and * be a hists instance. Right now its only 'report' @@ -140,4 +138,10 @@ size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, FILE *fp, { return machines__fprintf_dsos_buildid(&self->machines, fp, with_hits); } + +static inline +size_t perf_session__fprintf_nr_events(struct perf_session *self, FILE *fp) +{ + return hists__fprintf_nr_events(&self->hists, fp); +} #endif /* __PERF_SESSION_H */ -- cgit v0.10.2 From 3dbc6fb6a3c8a7dc164ae330ab024a3fe65ae53e Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Tue, 11 May 2010 17:16:23 -0400 Subject: inotify: clean up the inotify_add_watch out path inotify_add_watch explictly frees the unused inode mark, but it can just use the generic code. Just do that. Signed-off-by: Eric Paris diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index 472cdf2..40da732 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -578,16 +578,13 @@ retry: /* return the watch descriptor for this new entry */ ret = tmp_ientry->wd; - /* match the ref from fsnotify_init_markentry() */ - fsnotify_put_mark(&tmp_ientry->fsn_entry); - /* if this mark added a new event update the group mask */ if (mask & ~group->mask) fsnotify_recalc_group_mask(group); out_err: - if (ret < 0) - kmem_cache_free(inotify_inode_mark_cachep, tmp_ientry); + /* match the ref from fsnotify_init_markentry() */ + fsnotify_put_mark(&tmp_ientry->fsn_entry); return ret; } -- cgit v0.10.2 From e08733446e72b983fed850fc5d8bd21b386feb29 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Tue, 11 May 2010 17:17:40 -0400 Subject: inotify: race use after free/double free in inotify inode marks There is a race in the inotify add/rm watch code. A task can find and remove a mark which doesn't have all of it's references. This can result in a use after free/double free situation. Task A Task B ------------ ----------- inotify_new_watch() allocate a mark (refcnt == 1) add it to the idr inotify_rm_watch() inotify_remove_from_idr() fsnotify_put_mark() refcnt hits 0, free take reference because we are on idr [at this point it is a use after free] [time goes on] refcnt may hit 0 again, double free The fix is to take the reference BEFORE the object can be found in the idr. Signed-off-by: Eric Paris Cc: diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index 40da732..e46ca68 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -546,21 +546,24 @@ retry: if (unlikely(!idr_pre_get(&group->inotify_data.idr, GFP_KERNEL))) goto out_err; + /* we are putting the mark on the idr, take a reference */ + fsnotify_get_mark(&tmp_ientry->fsn_entry); + spin_lock(&group->inotify_data.idr_lock); ret = idr_get_new_above(&group->inotify_data.idr, &tmp_ientry->fsn_entry, group->inotify_data.last_wd+1, &tmp_ientry->wd); spin_unlock(&group->inotify_data.idr_lock); if (ret) { + /* we didn't get on the idr, drop the idr reference */ + fsnotify_put_mark(&tmp_ientry->fsn_entry); + /* idr was out of memory allocate and try again */ if (ret == -EAGAIN) goto retry; goto out_err; } - /* we put the mark on the idr, take a reference */ - fsnotify_get_mark(&tmp_ientry->fsn_entry); - /* we are on the idr, now get on the inode */ ret = fsnotify_add_mark(&tmp_ientry->fsn_entry, group, inode); if (ret) { -- cgit v0.10.2 From b3b38d842fa367d862b83e7670af4e0fd6a80fc0 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Wed, 12 May 2010 15:34:07 -0700 Subject: inotify: don't leak user struct on inotify release inotify_new_group() receives a get_uid-ed user_struct and saves the reference on group->inotify_data.user. The problem is that free_uid() is never called on it. Issue seem to be introduced by 63c882a0 (inotify: reimplement inotify using fsnotify) after 2.6.30. Signed-off-by: Pavel Emelyanov Eric Paris Cc: Signed-off-by: Andrew Morton Signed-off-by: Eric Paris diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c index 1afb0a1..e27960c 100644 --- a/fs/notify/inotify/inotify_fsnotify.c +++ b/fs/notify/inotify/inotify_fsnotify.c @@ -28,6 +28,7 @@ #include /* struct path */ #include /* kmem_* */ #include +#include #include "inotify.h" @@ -146,6 +147,7 @@ static void inotify_free_group_priv(struct fsnotify_group *group) idr_for_each(&group->inotify_data.idr, idr_callback, group); idr_remove_all(&group->inotify_data.idr); idr_destroy(&group->inotify_data.idr); + free_uid(group->inotify_data.user); } void inotify_free_event_priv(struct fsnotify_event_private_data *fsn_event_priv) -- cgit v0.10.2 From cee75ac7ecc27084accdb9d9d6fde65a09f047ae Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 14 May 2010 13:16:55 -0300 Subject: perf hist: Clarify events_stats fields usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The events_stats.total field is too generic, rename it to .total_period, and also add a comment explaining that it is the sum of all the .period fields in samples, that is needed because we use auto-freq to avoid sampling artifacts. Ditto for events_stats.lost, that is the sum of all lost_event.lost fields, i.e. the number of events the kernel dropped. Looking at the users, builtin-sched.c can make use of these fields and stop doing it again. Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 3a95a02..6dd4bda 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -54,7 +54,7 @@ static int diff__process_sample_event(event_t *event, struct perf_session *sessi return -1; } - session->hists.stats.total += data.period; + session->hists.stats.total_period += data.period; return 0; } diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index f13cda1..b8f47de 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -138,14 +138,14 @@ static int add_event_total(struct perf_session *session, if (!hists) return -ENOMEM; - hists->stats.total += data->period; + hists->stats.total_period += data->period; /* * FIXME: add_event_total should be moved from here to * perf_session__process_event so that the proper hist is passed to * the event_op methods. */ hists__inc_nr_events(hists, PERF_RECORD_SAMPLE); - session->hists.stats.total += data->period; + session->hists.stats.total_period += data->period; return 0; } @@ -322,10 +322,10 @@ static int __cmd_report(void) if (rb_first(&session->hists.entries) == rb_last(&session->hists.entries)) fprintf(stdout, "# Samples: %Ld\n#\n", - hists->stats.total); + hists->stats.total_period); else fprintf(stdout, "# Samples: %Ld %s\n#\n", - hists->stats.total, + hists->stats.total_period, __event_name(hists->type, hists->config)); hists__fprintf(hists, NULL, false, stdout); diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index aef6ed0..be7bc92 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -1641,19 +1641,10 @@ static int process_sample_event(event_t *event, struct perf_session *session) return 0; } -static int process_lost_event(event_t *event __used, - struct perf_session *session __used) -{ - nr_lost_chunks++; - nr_lost_events += event->lost.lost; - - return 0; -} - static struct perf_event_ops event_ops = { .sample = process_sample_event, .comm = event__process_comm, - .lost = process_lost_event, + .lost = event__process_lost, .ordered_samples = true, }; @@ -1664,8 +1655,12 @@ static int read_events(void) if (session == NULL) return -ENOMEM; - if (perf_session__has_traces(session, "record -R")) + if (perf_session__has_traces(session, "record -R")) { err = perf_session__process_events(session, &event_ops); + nr_events = session->hists.stats.nr_events[0]; + nr_lost_events = session->hists.stats.total_lost; + nr_lost_chunks = session->hists.stats.nr_events[PERF_RECORD_LOST]; + } perf_session__delete(session); return err; diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 95fcb05..dddf3f0 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c @@ -109,7 +109,7 @@ static int process_sample_event(event_t *event, struct perf_session *session) data.time, thread->comm); } - session->hists.stats.total += data.period; + session->hists.stats.total_period += data.period; return 0; } diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 3e8fec1..50771b5 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -385,7 +385,7 @@ int event__process_comm(event_t *self, struct perf_session *session) int event__process_lost(event_t *self, struct perf_session *session) { dump_printf(": id:%Ld: lost:%Ld\n", self->lost.id, self->lost.lost); - session->hists.stats.lost += self->lost.lost; + session->hists.stats.total_lost += self->lost.lost; return 0; } diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 1614ad7..c592245 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -239,7 +239,7 @@ void hists__output_resort(struct hists *self) struct hist_entry *n; u64 min_callchain_hits; - min_callchain_hits = self->stats.total * (callchain_param.min_percent / 100); + min_callchain_hits = self->stats.total_period * (callchain_param.min_percent / 100); tmp = RB_ROOT; next = rb_first(&self->entries); @@ -525,7 +525,7 @@ int hist_entry__snprintf(struct hist_entry *self, char *s, size_t size, if (pair_hists) { count = self->pair ? self->pair->count : 0; - total = pair_hists->stats.total; + total = pair_hists->stats.total_period; count_sys = self->pair ? self->pair->count_sys : 0; count_us = self->pair ? self->pair->count_us : 0; count_guest_sys = self->pair ? self->pair->count_guest_sys : 0; @@ -769,10 +769,10 @@ print_entries: ++position; } ret += hist_entry__fprintf(h, pair, show_displacement, - displacement, fp, self->stats.total); + displacement, fp, self->stats.total_period); if (symbol_conf.use_callchain) - ret += hist_entry__fprintf_callchain(h, fp, self->stats.total); + ret += hist_entry__fprintf_callchain(h, fp, self->stats.total_period); if (h->ms.map == NULL && verbose > 1) { __map_groups__fprintf_maps(&h->thread->mg, @@ -795,7 +795,7 @@ void hists__filter_by_dso(struct hists *self, const struct dso *dso) { struct rb_node *nd; - self->nr_entries = self->stats.total = 0; + self->nr_entries = self->stats.total_period = 0; self->max_sym_namelen = 0; for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) { @@ -812,7 +812,7 @@ void hists__filter_by_dso(struct hists *self, const struct dso *dso) h->filtered &= ~(1 << HIST_FILTER__DSO); if (!h->filtered) { ++self->nr_entries; - self->stats.total += h->count; + self->stats.total_period += h->count; if (h->ms.sym && self->max_sym_namelen < h->ms.sym->namelen) self->max_sym_namelen = h->ms.sym->namelen; @@ -824,7 +824,7 @@ void hists__filter_by_thread(struct hists *self, const struct thread *thread) { struct rb_node *nd; - self->nr_entries = self->stats.total = 0; + self->nr_entries = self->stats.total_period = 0; self->max_sym_namelen = 0; for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) { @@ -837,7 +837,7 @@ void hists__filter_by_thread(struct hists *self, const struct thread *thread) h->filtered &= ~(1 << HIST_FILTER__THREAD); if (!h->filtered) { ++self->nr_entries; - self->stats.total += h->count; + self->stats.total_period += h->count; if (h->ms.sym && self->max_sym_namelen < h->ms.sym->namelen) self->max_sym_namelen = h->ms.sym->namelen; @@ -1031,8 +1031,8 @@ int hist_entry__annotate(struct hist_entry *self, struct list_head *head) void hists__inc_nr_events(struct hists *self, u32 type) { - ++self->hists.stats.nr_events[0]; - ++self->hists.stats.nr_events[type]; + ++self->stats.nr_events[0]; + ++self->stats.nr_events[type]; } size_t hists__fprintf_nr_events(struct hists *self, FILE *fp) diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 97b8962..da6b848 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -37,9 +37,21 @@ struct sym_priv { struct sym_ext *ext; }; +/* + * The kernel collects the number of events it couldn't send in a stretch and + * when possible sends this number in a PERF_RECORD_LOST event. The number of + * such "chunks" of lost events is stored in .nr_events[PERF_EVENT_LOST] while + * total_lost tells exactly how many events the kernel in fact lost, i.e. it is + * the sum of all struct lost_event.lost fields reported. + * + * The total_period is needed because by default auto-freq is used, so + * multipling nr_events[PERF_EVENT_SAMPLE] by a frequency isn't possible to get + * the total number of low level events, it is necessary to to sum all struct + * sample_event.period and stash the result in total_period. + */ struct events_stats { - u64 total; - u64 lost; + u64 total_period; + u64 total_lost; u32 nr_events[PERF_RECORD_HEADER_MAX]; u32 nr_unknown_events; }; diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index ba6acd0..010bacf 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -689,7 +689,7 @@ static int hist_browser__populate(struct hist_browser *self, struct hists *hists } snprintf(str, sizeof(str), "Samples: %Ld ", - hists->stats.total); + hists->stats.total_period); newtDrawRootText(0, 0, str); newtGetScreenSize(NULL, &rows); @@ -718,12 +718,12 @@ static int hist_browser__populate(struct hist_browser *self, struct hists *hists if (h->filtered) continue; - len = hist_entry__append_browser(h, self->tree, hists->stats.total); + len = hist_entry__append_browser(h, self->tree, hists->stats.total_period); if (len > max_len) max_len = len; if (symbol_conf.use_callchain) hist_entry__append_callchain_browser(h, self->tree, - hists->stats.total, idx++); + hists->stats.total_period, idx++); ++curr_hist; if (curr_hist % 5) ui_progress__update(progress, curr_hist); diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 7231f6b..25bfca4 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -549,7 +549,7 @@ static int perf_session__process_event(struct perf_session *self, dump_printf("%#Lx [%#x]: PERF_RECORD_%s", offset + head, event->header.size, event__name[event->header.type]); - hists__inc_nr_events(self, event->header.type); + hists__inc_nr_events(&self->hists, event->header.type); } if (self->header.needs_swap && event__swap_ops[event->header.type]) -- cgit v0.10.2 From c82ee828aa20487d254a5225d256cd422acee459 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 14 May 2010 14:19:35 -0300 Subject: perf report: Report number of events, not samples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Number of samples is meaningless after we switched to auto-freq, so report the number of events, i.e. not the sum of the different periods, but the number PERF_RECORD_SAMPLE emitted by the kernel. While doing this I noticed that naming "count" to the sum of all the event periods can be confusing, so rename it to .period, just like in struct sample.data, so that we become more consistent. This helps with the next step, that was to record in struct hist_entry the number of sample events for each instance, we need that because we use it to generate the number of events when applying filters to the tree of hist entries like it is being done in the TUI report browser. Suggested-by: Ingo Molnar Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 6dd4bda..a6e2fdc 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -23,9 +23,9 @@ static bool force; static bool show_displacement; static int hists__add_entry(struct hists *self, - struct addr_location *al, u64 count) + struct addr_location *al, u64 period) { - if (__hists__add_entry(self, al, NULL, count) != NULL) + if (__hists__add_entry(self, al, NULL, period) != NULL) return 0; return -ENOMEM; } @@ -50,7 +50,7 @@ static int diff__process_sample_event(event_t *event, struct perf_session *sessi event__parse_sample(event, session->sample_type, &data); if (hists__add_entry(&session->hists, &al, data.period)) { - pr_warning("problem incrementing symbol count, skipping event\n"); + pr_warning("problem incrementing symbol period, skipping event\n"); return -1; } diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index b8f47de..6826512 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -188,14 +188,14 @@ static int process_sample_event(event_t *event, struct perf_session *session) return 0; if (perf_session__add_hist_entry(session, &al, &data)) { - pr_debug("problem incrementing symbol count, skipping event\n"); + pr_debug("problem incrementing symbol period, skipping event\n"); return -1; } attr = perf_header__find_attr(data.id, &session->header); if (add_event_total(session, &data, attr)) { - pr_debug("problem adding event count\n"); + pr_debug("problem adding event period\n"); return -1; } @@ -269,11 +269,25 @@ static struct perf_event_ops event_ops = { extern volatile int session_done; -static void sig_handler(int sig __attribute__((__unused__))) +static void sig_handler(int sig __used) { session_done = 1; } +static size_t hists__fprintf_nr_sample_events(struct hists *self, + const char *evname, FILE *fp) +{ + size_t ret; + char unit; + unsigned long nr_events = self->stats.nr_events[PERF_RECORD_SAMPLE]; + + nr_events = convert_unit(nr_events, &unit); + ret = fprintf(fp, "# Events: %lu%c", nr_events, unit); + if (evname != NULL) + ret += fprintf(fp, " %s", evname); + return ret + fprintf(fp, "\n#\n"); +} + static int __cmd_report(void) { int ret = -EINVAL; @@ -319,14 +333,12 @@ static int __cmd_report(void) if (use_browser) hists__browse(hists, help, input_name); else { - if (rb_first(&session->hists.entries) == + const char *evname = NULL; + if (rb_first(&session->hists.entries) != rb_last(&session->hists.entries)) - fprintf(stdout, "# Samples: %Ld\n#\n", - hists->stats.total_period); - else - fprintf(stdout, "# Samples: %Ld %s\n#\n", - hists->stats.total_period, - __event_name(hists->type, hists->config)); + evname = __event_name(hists->type, hists->config); + + hists__fprintf_nr_sample_events(hists, evname, stdout); hists__fprintf(hists, NULL, false, stdout); fprintf(stdout, "\n\n"); diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index c592245..f75c5f6 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -9,21 +9,21 @@ struct callchain_param callchain_param = { .min_percent = 0.5 }; -static void hist_entry__add_cpumode_count(struct hist_entry *self, - unsigned int cpumode, u64 count) +static void hist_entry__add_cpumode_period(struct hist_entry *self, + unsigned int cpumode, u64 period) { switch (cpumode) { case PERF_RECORD_MISC_KERNEL: - self->count_sys += count; + self->period_sys += period; break; case PERF_RECORD_MISC_USER: - self->count_us += count; + self->period_us += period; break; case PERF_RECORD_MISC_GUEST_KERNEL: - self->count_guest_sys += count; + self->period_guest_sys += period; break; case PERF_RECORD_MISC_GUEST_USER: - self->count_guest_us += count; + self->period_guest_us += period; break; default: break; @@ -31,7 +31,7 @@ static void hist_entry__add_cpumode_count(struct hist_entry *self, } /* - * histogram, sorted on item, collects counts + * histogram, sorted on item, collects periods */ static struct hist_entry *hist_entry__new(struct hist_entry *template) @@ -41,6 +41,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template) if (self != NULL) { *self = *template; + self->nr_events = 1; if (symbol_conf.use_callchain) callchain_init(self->callchain); } @@ -57,7 +58,7 @@ static void hists__inc_nr_entries(struct hists *self, struct hist_entry *entry) struct hist_entry *__hists__add_entry(struct hists *self, struct addr_location *al, - struct symbol *sym_parent, u64 count) + struct symbol *sym_parent, u64 period) { struct rb_node **p = &self->entries.rb_node; struct rb_node *parent = NULL; @@ -70,7 +71,7 @@ struct hist_entry *__hists__add_entry(struct hists *self, }, .ip = al->addr, .level = al->level, - .count = count, + .period = period, .parent = sym_parent, }; int cmp; @@ -82,7 +83,8 @@ struct hist_entry *__hists__add_entry(struct hists *self, cmp = hist_entry__cmp(&entry, he); if (!cmp) { - he->count += count; + he->period += period; + ++he->nr_events; goto out; } @@ -99,7 +101,7 @@ struct hist_entry *__hists__add_entry(struct hists *self, rb_insert_color(&he->rb_node, &self->entries); hists__inc_nr_entries(self, he); out: - hist_entry__add_cpumode_count(he, al->cpumode, count); + hist_entry__add_cpumode_period(he, al->cpumode, period); return he; } @@ -160,7 +162,7 @@ static bool collapse__insert_entry(struct rb_root *root, struct hist_entry *he) cmp = hist_entry__collapse(iter, he); if (!cmp) { - iter->count += he->count; + iter->period += he->period; hist_entry__free(he); return false; } @@ -203,7 +205,7 @@ void hists__collapse_resort(struct hists *self) } /* - * reverse the map, sort on count. + * reverse the map, sort on period. */ static void __hists__insert_output_entry(struct rb_root *entries, @@ -222,7 +224,7 @@ static void __hists__insert_output_entry(struct rb_root *entries, parent = *p; iter = rb_entry(parent, struct hist_entry, rb_node); - if (he->count > iter->count) + if (he->period > iter->period) p = &(*p)->rb_left; else p = &(*p)->rb_right; @@ -288,7 +290,7 @@ static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask, } static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, - int depth, int depth_mask, int count, + int depth, int depth_mask, int period, u64 total_samples, int hits, int left_margin) { @@ -301,7 +303,7 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain, ret += fprintf(fp, "|"); else ret += fprintf(fp, " "); - if (!count && i == depth - 1) { + if (!period && i == depth - 1) { double percent; percent = hits * 100.0 / total_samples; @@ -516,7 +518,7 @@ int hist_entry__snprintf(struct hist_entry *self, char *s, size_t size, long displacement, bool color, u64 session_total) { struct sort_entry *se; - u64 count, total, count_sys, count_us, count_guest_sys, count_guest_us; + u64 period, total, period_sys, period_us, period_guest_sys, period_guest_us; const char *sep = symbol_conf.field_sep; int ret; @@ -524,57 +526,57 @@ int hist_entry__snprintf(struct hist_entry *self, char *s, size_t size, return 0; if (pair_hists) { - count = self->pair ? self->pair->count : 0; + period = self->pair ? self->pair->period : 0; total = pair_hists->stats.total_period; - count_sys = self->pair ? self->pair->count_sys : 0; - count_us = self->pair ? self->pair->count_us : 0; - count_guest_sys = self->pair ? self->pair->count_guest_sys : 0; - count_guest_us = self->pair ? self->pair->count_guest_us : 0; + period_sys = self->pair ? self->pair->period_sys : 0; + period_us = self->pair ? self->pair->period_us : 0; + period_guest_sys = self->pair ? self->pair->period_guest_sys : 0; + period_guest_us = self->pair ? self->pair->period_guest_us : 0; } else { - count = self->count; + period = self->period; total = session_total; - count_sys = self->count_sys; - count_us = self->count_us; - count_guest_sys = self->count_guest_sys; - count_guest_us = self->count_guest_us; + period_sys = self->period_sys; + period_us = self->period_us; + period_guest_sys = self->period_guest_sys; + period_guest_us = self->period_guest_us; } if (total) { if (color) ret = percent_color_snprintf(s, size, sep ? "%.2f" : " %6.2f%%", - (count * 100.0) / total); + (period * 100.0) / total); else ret = snprintf(s, size, sep ? "%.2f" : " %6.2f%%", - (count * 100.0) / total); + (period * 100.0) / total); if (symbol_conf.show_cpu_utilization) { ret += percent_color_snprintf(s + ret, size - ret, sep ? "%.2f" : " %6.2f%%", - (count_sys * 100.0) / total); + (period_sys * 100.0) / total); ret += percent_color_snprintf(s + ret, size - ret, sep ? "%.2f" : " %6.2f%%", - (count_us * 100.0) / total); + (period_us * 100.0) / total); if (perf_guest) { ret += percent_color_snprintf(s + ret, size - ret, sep ? "%.2f" : " %6.2f%%", - (count_guest_sys * 100.0) / + (period_guest_sys * 100.0) / total); ret += percent_color_snprintf(s + ret, size - ret, sep ? "%.2f" : " %6.2f%%", - (count_guest_us * 100.0) / + (period_guest_us * 100.0) / total); } } } else - ret = snprintf(s, size, sep ? "%lld" : "%12lld ", count); + ret = snprintf(s, size, sep ? "%lld" : "%12lld ", period); if (symbol_conf.show_nr_samples) { if (sep) - ret += snprintf(s + ret, size - ret, "%c%lld", *sep, count); + ret += snprintf(s + ret, size - ret, "%c%lld", *sep, period); else - ret += snprintf(s + ret, size - ret, "%11lld", count); + ret += snprintf(s + ret, size - ret, "%11lld", period); } if (pair_hists) { @@ -582,9 +584,9 @@ int hist_entry__snprintf(struct hist_entry *self, char *s, size_t size, double old_percent = 0, new_percent = 0, diff; if (total > 0) - old_percent = (count * 100.0) / total; + old_percent = (period * 100.0) / total; if (session_total > 0) - new_percent = (self->count * 100.0) / session_total; + new_percent = (self->period * 100.0) / session_total; diff = new_percent - old_percent; @@ -796,6 +798,7 @@ void hists__filter_by_dso(struct hists *self, const struct dso *dso) struct rb_node *nd; self->nr_entries = self->stats.total_period = 0; + self->stats.nr_events[PERF_RECORD_SAMPLE] = 0; self->max_sym_namelen = 0; for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) { @@ -812,7 +815,8 @@ void hists__filter_by_dso(struct hists *self, const struct dso *dso) h->filtered &= ~(1 << HIST_FILTER__DSO); if (!h->filtered) { ++self->nr_entries; - self->stats.total_period += h->count; + self->stats.total_period += h->period; + self->stats.nr_events[PERF_RECORD_SAMPLE] += h->nr_events; if (h->ms.sym && self->max_sym_namelen < h->ms.sym->namelen) self->max_sym_namelen = h->ms.sym->namelen; @@ -825,6 +829,7 @@ void hists__filter_by_thread(struct hists *self, const struct thread *thread) struct rb_node *nd; self->nr_entries = self->stats.total_period = 0; + self->stats.nr_events[PERF_RECORD_SAMPLE] = 0; self->max_sym_namelen = 0; for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) { @@ -837,7 +842,8 @@ void hists__filter_by_thread(struct hists *self, const struct thread *thread) h->filtered &= ~(1 << HIST_FILTER__THREAD); if (!h->filtered) { ++self->nr_entries; - self->stats.total_period += h->count; + self->stats.total_period += h->period; + self->stats.nr_events[PERF_RECORD_SAMPLE] += h->nr_events; if (h->ms.sym && self->max_sym_namelen < h->ms.sym->namelen) self->max_sym_namelen = h->ms.sym->namelen; @@ -881,7 +887,7 @@ int hist_entry__inc_addr_samples(struct hist_entry *self, u64 ip) h->sum++; h->ip[offset]++; - pr_debug3("%#Lx %s: count++ [ip: %#Lx, %#Lx] => %Ld\n", self->ms.sym->start, + pr_debug3("%#Lx %s: period++ [ip: %#Lx, %#Lx] => %Ld\n", self->ms.sym->start, self->ms.sym->name, ip, ip - self->ms.sym->start, h->ip[offset]); return 0; } diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index da6b848..6f17dcd 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -69,7 +69,7 @@ struct hists { struct hist_entry *__hists__add_entry(struct hists *self, struct addr_location *al, - struct symbol *parent, u64 count); + struct symbol *parent, u64 period); extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *); extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *); int hist_entry__fprintf(struct hist_entry *self, struct hists *pair_hists, diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index 010bacf..3402453 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -680,16 +680,18 @@ static int hist_browser__populate(struct hist_browser *self, struct hists *hists struct ui_progress *progress; struct rb_node *nd; u64 curr_hist = 0; - char seq[] = "."; + char seq[] = ".", unit; char str[256]; + unsigned long nr_events = hists->stats.nr_events[PERF_RECORD_SAMPLE]; if (self->form) { newtFormDestroy(self->form); newtPopWindow(); } - snprintf(str, sizeof(str), "Samples: %Ld ", - hists->stats.total_period); + nr_events = convert_unit(nr_events, &unit); + snprintf(str, sizeof(str), "Events: %lu%c ", + nr_events, unit); newtDrawRootText(0, 0, str); newtGetScreenSize(NULL, &rows); diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index af301ac..eab2e0b3 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h @@ -43,14 +43,15 @@ extern enum sort_type sort__first_dimension; struct hist_entry { struct rb_node rb_node; - u64 count; - u64 count_sys; - u64 count_us; - u64 count_guest_sys; - u64 count_guest_us; + u64 period; + u64 period_sys; + u64 period_us; + u64 period_guest_sys; + u64 period_guest_us; struct map_symbol ms; struct thread *thread; u64 ip; + u32 nr_events; char level; u8 filtered; struct symbol *parent; diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c index f9b890f..2142656 100644 --- a/tools/perf/util/util.c +++ b/tools/perf/util/util.c @@ -92,3 +92,25 @@ out_close_from: out: return err; } + +unsigned long convert_unit(unsigned long value, char *unit) +{ + *unit = ' '; + + if (value > 1000) { + value /= 1000; + *unit = 'K'; + } + + if (value > 1000) { + value /= 1000; + *unit = 'M'; + } + + if (value > 1000) { + value /= 1000; + *unit = 'G'; + } + + return value; +} diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index fbf45d1..0795bf30 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -423,6 +423,7 @@ char **argv_split(const char *str, int *argcp); void argv_free(char **argv); bool strglobmatch(const char *str, const char *pat); bool strlazymatch(const char *str, const char *pat); +unsigned long convert_unit(unsigned long value, char *unit); #define _STR(x) #x #define STR(x) _STR(x) -- cgit v0.10.2 From b9af5ddf8a34ff3c911372173c2e51c6f8a6ca8f Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Thu, 13 May 2010 22:51:51 +0400 Subject: DA830: fix USB 2.0 clock entry DA8xx OHCI driver fails to load due to failing clk_get() call for the USB 2.0 clock. Arrange matching USB 2.0 clock by the clock name instead of the device. (Adding another CLK() entry for "ohci.0" device won't do -- in the future I'll also have to enable USB 2.0 clock to configure CPPI 4.1 module, in which case I won't have any device at all.) Signed-off-by: Sergei Shtylyov Signed-off-by: Kevin Hilman diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c index 122e61a..e8cb982 100644 --- a/arch/arm/mach-davinci/da830.c +++ b/arch/arm/mach-davinci/da830.c @@ -410,7 +410,7 @@ static struct clk_lookup da830_clks[] = { CLK("davinci-mcasp.0", NULL, &mcasp0_clk), CLK("davinci-mcasp.1", NULL, &mcasp1_clk), CLK("davinci-mcasp.2", NULL, &mcasp2_clk), - CLK("musb_hdrc", NULL, &usb20_clk), + CLK(NULL, "usb20", &usb20_clk), CLK(NULL, "aemif", &aemif_clk), CLK(NULL, "aintc", &aintc_clk), CLK(NULL, "secu_mgr", &secu_mgr_clk), -- cgit v0.10.2 From ade029e2aaacc8965a548b0b0f80c5bee97ffc68 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Sat, 24 Apr 2010 09:56:53 +0200 Subject: x86, k8: Fix build error when K8_NB is disabled K8_NB depends on PCI and when the last is disabled (allnoconfig) we fail at the final linking stage due to missing exported num_k8_northbridges. Add a header stub for that. Signed-off-by: Borislav Petkov LKML-Reference: <20100503183036.GJ26107@aftab> Signed-off-by: H. Peter Anvin Cc: diff --git a/arch/x86/include/asm/k8.h b/arch/x86/include/asm/k8.h index f70e600..af00bd1 100644 --- a/arch/x86/include/asm/k8.h +++ b/arch/x86/include/asm/k8.h @@ -16,11 +16,16 @@ extern int k8_numa_init(unsigned long start_pfn, unsigned long end_pfn); extern int k8_scan_nodes(void); #ifdef CONFIG_K8_NB +extern int num_k8_northbridges; + static inline struct pci_dev *node_to_k8_nb_misc(int node) { return (node < num_k8_northbridges) ? k8_northbridges[node] : NULL; } + #else +#define num_k8_northbridges 0 + static inline struct pci_dev *node_to_k8_nb_misc(int node) { return NULL; -- cgit v0.10.2 From 7f284d3cc96e02468a42e045f77af11e5ff8b095 Mon Sep 17 00:00:00 2001 From: Frank Arnold Date: Thu, 22 Apr 2010 16:06:59 +0200 Subject: x86, cacheinfo: Turn off L3 cache index disable feature in virtualized environments When running a quest kernel on xen we get: BUG: unable to handle kernel NULL pointer dereference at 0000000000000038 IP: [] cpuid4_cache_lookup_regs+0x2ca/0x3df PGD 0 Oops: 0000 [#1] SMP last sysfs file: CPU 0 Modules linked in: Pid: 0, comm: swapper Tainted: G W 2.6.34-rc3 #1 /HVM domU RIP: 0010:[] [] cpuid4_cache_lookup_regs+0x 2ca/0x3df RSP: 0018:ffff880002203e08 EFLAGS: 00010046 RAX: 0000000000000000 RBX: 0000000000000003 RCX: 0000000000000060 RDX: 0000000000000000 RSI: 0000000000000040 RDI: 0000000000000000 RBP: ffff880002203ed8 R08: 00000000000017c0 R09: ffff880002203e38 R10: ffff8800023d5d40 R11: ffffffff81a01e28 R12: ffff880187e6f5c0 R13: ffff880002203e34 R14: ffff880002203e58 R15: ffff880002203e68 FS: 0000000000000000(0000) GS:ffff880002200000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 0000000000000038 CR3: 0000000001a3c000 CR4: 00000000000006f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process swapper (pid: 0, threadinfo ffffffff81a00000, task ffffffff81a44020) Stack: ffffffff810d7ecb ffff880002203e20 ffffffff81059140 ffff880002203e30 <0> ffffffff810d7ec9 0000000002203e40 000000000050d140 ffff880002203e70 <0> 0000000002008140 0000000000000086 ffff880040020140 ffffffff81068b8b Call Trace: [] ? sync_supers_timer_fn+0x0/0x1c [] ? mod_timer+0x23/0x25 [] ? arm_supers_timer+0x34/0x36 [] ? hrtimer_get_next_event+0xa7/0xc3 [] ? get_next_timer_interrupt+0x19a/0x20d [] get_cpu_leaves+0x5c/0x232 [] ? sched_clock_local+0x1c/0x82 [] ? sched_clock_tick+0x75/0x7a [] generic_smp_call_function_single_interrupt+0xae/0xd0 [] smp_call_function_single_interrupt+0x18/0x27 [] call_function_single_interrupt+0x13/0x20 [] ? notifier_call_chain+0x14/0x63 [] ? native_safe_halt+0xc/0xd [] ? default_idle+0x36/0x53 [] cpu_idle+0xaa/0xe4 [] rest_init+0x7e/0x80 [] start_kernel+0x40e/0x419 [] x86_64_start_reservations+0xb3/0xb7 [] x86_64_start_kernel+0xf8/0x107 Code: 14 d5 40 ff ae 81 8b 14 02 31 c0 3b 15 47 1c 8b 00 7d 0e 48 8b 05 36 1c 8b 00 48 63 d2 48 8b 04 d0 c7 85 5c ff ff ff 00 00 00 00 <8b> 70 38 48 8d 8d 5c ff ff ff 48 8b 78 10 ba c4 01 00 00 e8 eb RIP [] cpuid4_cache_lookup_regs+0x2ca/0x3df RSP CR2: 0000000000000038 ---[ end trace a7919e7f17c0a726 ]--- The L3 cache index disable feature of AMD CPUs has to be disabled if the kernel is running as guest on top of a hypervisor because northbridge devices are not available to the guest. Currently, this fixes a boot crash on top of Xen. In the future this will become an issue on KVM as well. Check if northbridge devices are present and do not enable the feature if there are none. [ hpa: backported to 2.6.34 ] Signed-off-by: Frank Arnold LKML-Reference: <1271945222-5283-3-git-send-email-bp@amd64.org> Acked-by: Borislav Petkov Signed-off-by: H. Peter Anvin Cc: diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index b3eeb66..95962a9 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -340,6 +340,10 @@ amd_check_l3_disable(int index, struct _cpuid4_info_regs *this_leaf) (boot_cpu_data.x86_mask < 0x1))) return; + /* not in virtualized environments */ + if (num_k8_northbridges == 0) + return; + this_leaf->can_disable = true; this_leaf->l3_indices = amd_calc_l3_indices(); } -- cgit v0.10.2 From e9b1d5d0ff4d3ae86050dc4c91b3147361c7af9e Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Fri, 14 May 2010 13:55:57 -0700 Subject: x86, mrst: Don't blindly access extended config space Do not blindly access extended configuration space unless we actively know we're on a Moorestown platform. The fixed-size BAR capability lives in the extended configuration space, and thus is not applicable if the configuration space isn't appropriately sized. This fixes booting certain VMware configurations with CONFIG_MRST=y. Moorestown will add a fake PCI-X 266 capability to advertise the presence of extended configuration space. Reported-and-tested-by: Petr Vandrovec Signed-off-by: H. Peter Anvin Acked-by: Jacob Pan Acked-by: Jesse Barnes LKML-Reference: diff --git a/arch/x86/pci/mrst.c b/arch/x86/pci/mrst.c index 8bf2fcb..1cdc02c 100644 --- a/arch/x86/pci/mrst.c +++ b/arch/x86/pci/mrst.c @@ -247,6 +247,10 @@ static void __devinit pci_fixed_bar_fixup(struct pci_dev *dev) u32 size; int i; + /* Must have extended configuration space */ + if (dev->cfg_size < PCIE_CAP_OFFSET + 4) + return; + /* Fixup the BAR sizes for fixed BAR devices and make them unmoveable */ offset = fixed_bar_cap(dev->bus, dev->devfn); if (!offset || PCI_DEVFN(2, 0) == dev->devfn || -- cgit v0.10.2 From 3e1bbdc3a721f4b1ed44f4554402a8dbc60fa97f Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 14 May 2010 20:05:21 -0300 Subject: perf newt: Make <- zoom out filters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After we use the filters to zoom into DSOs or threads, we can use <- (left arrow) to zoom out from the last filter applied. It is still possible to zoom out of order by using the popup menu. With this we now have the zoom out operation on the browsing fast path, by allowing fast navigation using just the four arrors and the enter key to expand collapse callchains. Suggested-by: Ingo Molnar Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 9c4dc30..a9281cc 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -416,6 +416,7 @@ LIB_H += util/thread.h LIB_H += util/trace-event.h LIB_H += util/probe-finder.h LIB_H += util/probe-event.h +LIB_H += util/pstack.h LIB_H += util/cpumap.h LIB_OBJS += $(OUTPUT)util/abspath.o @@ -451,6 +452,7 @@ LIB_OBJS += $(OUTPUT)util/callchain.o LIB_OBJS += $(OUTPUT)util/values.o LIB_OBJS += $(OUTPUT)util/debug.o LIB_OBJS += $(OUTPUT)util/map.o +LIB_OBJS += $(OUTPUT)util/pstack.o LIB_OBJS += $(OUTPUT)util/session.o LIB_OBJS += $(OUTPUT)util/thread.o LIB_OBJS += $(OUTPUT)util/trace-event-parse.o diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index 3402453..e74df12 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -9,6 +9,7 @@ #include "cache.h" #include "hist.h" +#include "pstack.h" #include "session.h" #include "sort.h" #include "symbol.h" @@ -750,6 +751,7 @@ static int hist_browser__populate(struct hist_browser *self, struct hists *hists newtFormAddHotKey(self->form, 'A'); newtFormAddHotKey(self->form, 'a'); newtFormAddHotKey(self->form, NEWT_KEY_RIGHT); + newtFormAddHotKey(self->form, NEWT_KEY_LEFT); newtFormAddComponents(self->form, self->tree, NULL); self->selection = newt__symbol_tree_get_current(self->tree); @@ -801,6 +803,7 @@ static int hist_browser__title(char *bf, size_t size, const char *input_name, int hists__browse(struct hists *self, const char *helpline, const char *input_name) { struct hist_browser *browser = hist_browser__new(); + struct pstack *fstack = pstack__new(2); const struct thread *thread_filter = NULL; const struct dso *dso_filter = NULL; struct newtExitStruct es; @@ -810,12 +813,16 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na if (browser == NULL) return -1; + fstack = pstack__new(2); + if (fstack == NULL) + goto out; + ui_helpline__push(helpline); hist_browser__title(msg, sizeof(msg), input_name, dso_filter, thread_filter); if (hist_browser__populate(browser, self, msg) < 0) - goto out; + goto out_free_stack; while (1) { const struct thread *thread; @@ -836,6 +843,19 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na else continue; } + + if (es.u.key == NEWT_KEY_LEFT) { + const void *top; + + if (pstack__empty(fstack)) + continue; + top = pstack__pop(fstack); + if (top == &dso_filter) + goto zoom_out_dso; + if (top == &thread_filter) + goto zoom_out_thread; + continue; + } } if (browser->selection->sym != NULL && @@ -888,12 +908,15 @@ do_annotate: hist_entry__annotate_browser(he); } else if (choice == zoom_dso) { if (dso_filter) { + pstack__remove(fstack, &dso_filter); +zoom_out_dso: ui_helpline__pop(); dso_filter = NULL; } else { - ui_helpline__fpush("To zoom out press -> + \"Zoom out of %s DSO\"", + ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s DSO\"", dso->kernel ? "the Kernel" : dso->short_name); dso_filter = dso; + pstack__push(fstack, &dso_filter); } hists__filter_by_dso(self, dso_filter); hist_browser__title(msg, sizeof(msg), input_name, @@ -902,13 +925,16 @@ do_annotate: goto out; } else if (choice == zoom_thread) { if (thread_filter) { + pstack__remove(fstack, &thread_filter); +zoom_out_thread: ui_helpline__pop(); thread_filter = NULL; } else { - ui_helpline__fpush("To zoom out press -> + \"Zoom out of %s(%d) thread\"", + ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"", thread->comm_set ? thread->comm : "", thread->pid); thread_filter = thread; + pstack__push(fstack, &thread_filter); } hists__filter_by_thread(self, thread_filter); hist_browser__title(msg, sizeof(msg), input_name, @@ -918,6 +944,8 @@ do_annotate: } } err = 0; +out_free_stack: + pstack__delete(fstack); out: hist_browser__delete(browser); return err; diff --git a/tools/perf/util/pstack.c b/tools/perf/util/pstack.c new file mode 100644 index 0000000..13d36fa --- /dev/null +++ b/tools/perf/util/pstack.c @@ -0,0 +1,75 @@ +/* + * Simple pointer stack + * + * (c) 2010 Arnaldo Carvalho de Melo + */ + +#include "util.h" +#include "pstack.h" +#include +#include + +struct pstack { + unsigned short top; + unsigned short max_nr_entries; + void *entries[0]; +}; + +struct pstack *pstack__new(unsigned short max_nr_entries) +{ + struct pstack *self = zalloc((sizeof(*self) + + max_nr_entries * sizeof(void *))); + if (self != NULL) + self->max_nr_entries = max_nr_entries; + return self; +} + +void pstack__delete(struct pstack *self) +{ + free(self); +} + +bool pstack__empty(const struct pstack *self) +{ + return self->top == 0; +} + +void pstack__remove(struct pstack *self, void *key) +{ + unsigned short i = self->top, last_index = self->top - 1; + + while (i-- != 0) { + if (self->entries[i] == key) { + if (i < last_index) + memmove(self->entries + i, + self->entries + i + 1, + (last_index - i) * sizeof(void *)); + --self->top; + return; + } + } + pr_err("%s: %p not on the pstack!\n", __func__, key); +} + +void pstack__push(struct pstack *self, void *key) +{ + if (self->top == self->max_nr_entries) { + pr_err("%s: top=%d, overflow!\n", __func__, self->top); + return; + } + self->entries[self->top++] = key; +} + +void *pstack__pop(struct pstack *self) +{ + void *ret; + + if (self->top == 0) { + pr_err("%s: underflow!\n", __func__); + return NULL; + } + + ret = self->entries[--self->top]; + self->entries[self->top] = NULL; + return ret; +} diff --git a/tools/perf/util/pstack.h b/tools/perf/util/pstack.h new file mode 100644 index 0000000..5ad0702 --- /dev/null +++ b/tools/perf/util/pstack.h @@ -0,0 +1,12 @@ +#ifndef _PERF_PSTACK_ +#define _PERF_PSTACK_ + +struct pstack; +struct pstack *pstack__new(unsigned short max_nr_entries); +void pstack__delete(struct pstack *self); +bool pstack__empty(const struct pstack *self); +void pstack__remove(struct pstack *self, void *key); +void pstack__push(struct pstack *self, void *key); +void *pstack__pop(struct pstack *self); + +#endif /* _PERF_PSTACK_ */ -- cgit v0.10.2 From bfcc6e2eca507819e297a4c758ebd6b26e625330 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Fri, 14 May 2010 19:40:35 -0700 Subject: hughd: update email address My old address will shut down in a couple of weeks: update the tree. Signed-off-by: Hugh Dickins Signed-off-by: Hugh Dickins Signed-off-by: Linus Torvalds diff --git a/MAINTAINERS b/MAINTAINERS index d5b0b1b..d329b05 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5492,7 +5492,7 @@ S: Maintained F: drivers/mmc/host/tmio_mmc.* TMPFS (SHMEM FILESYSTEM) -M: Hugh Dickins +M: Hugh Dickins L: linux-mm@kvack.org S: Maintained F: include/linux/shmem_fs.h -- cgit v0.10.2 From 16a2164bb03612efe79a76c73da6da44445b9287 Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Fri, 14 May 2010 19:44:10 -0700 Subject: profile: fix stats and data leakage If the kernel is large or the profiling step small, /proc/profile leaks data and readprofile shows silly stats, until readprofile -r has reset the buffer: clear the prof_buffer when it is vmalloc()ed. Signed-off-by: Hugh Dickins Cc: stable@kernel.org Signed-off-by: Linus Torvalds diff --git a/kernel/profile.c b/kernel/profile.c index a55d3a3..dfadc5b 100644 --- a/kernel/profile.c +++ b/kernel/profile.c @@ -127,8 +127,10 @@ int __ref profile_init(void) return 0; prof_buffer = vmalloc(buffer_bytes); - if (prof_buffer) + if (prof_buffer) { + memset(prof_buffer, 0, buffer_bytes); return 0; + } free_cpumask_var(prof_cpu_mask); return -ENOMEM; -- cgit v0.10.2 From 1ff3d7d79204612ebe2e611d2592f8898908ca00 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Fri, 14 May 2010 23:08:15 +0400 Subject: x86, perf: P4 PMU - fix counters management logic Jaswinder reported this #GP: | | Message from syslogd@ht at May 14 09:39:32 ... | kernel:[ 314.908612] EIP: [] | x86_perf_event_set_period+0x19d/0x1b2 SS:ESP 0068:edac3d70 | Ming has narrowed it down to a comparision issue between arguments with different sizes and signs. As result event index reached a wrong value which in turn led to a GP fault. At the same time it was found that p4_next_cntr has broken logic and should return the counter index only if it was not yet borrowed for another event. Reported-by: Jaswinder Singh Rajput Reported-by: Lin Ming Bisected-by: Lin Ming Tested-by: Jaswinder Singh Rajput Signed-off-by: Cyrill Gorcunov CC: Peter Zijlstra CC: Frederic Weisbecker LKML-Reference: <20100514190815.GG13509@lenovo> Signed-off-by: Ingo Molnar diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index cb875b1..424fc8d 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c @@ -18,7 +18,7 @@ struct p4_event_bind { unsigned int opcode; /* Event code and ESCR selector */ unsigned int escr_msr[2]; /* ESCR MSR for this event */ - unsigned char cntr[2][P4_CNTR_LIMIT]; /* counter index (offset), -1 on abscence */ + char cntr[2][P4_CNTR_LIMIT]; /* counter index (offset), -1 on abscence */ }; struct p4_cache_event_bind { @@ -747,11 +747,11 @@ static int p4_get_escr_idx(unsigned int addr) static int p4_next_cntr(int thread, unsigned long *used_mask, struct p4_event_bind *bind) { - int i = 0, j; + int i, j; for (i = 0; i < P4_CNTR_LIMIT; i++) { - j = bind->cntr[thread][i++]; - if (j == -1 || !test_bit(j, used_mask)) + j = bind->cntr[thread][i]; + if (j != -1 && !test_bit(j, used_mask)) return j; } -- cgit v0.10.2 From d83c49f3e36cecd2e8823b6c48ffba083b8a5704 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 30 Apr 2010 17:17:09 -0400 Subject: Fix the regression created by "set S_DEAD on unlink()..." commit 1) i_flags simply doesn't work for mount/unlink race prevention; we may have many links to file and rm on one of those obviously shouldn't prevent bind on top of another later on. To fix it right way we need to mark _dentry_ as unsuitable for mounting upon; new flag (DCACHE_CANT_MOUNT) is protected by d_flags and i_mutex on the inode in question. Set it (with dont_mount(dentry)) in unlink/rmdir/etc., check (with cant_mount(dentry)) in places in namespace.c that used to check for S_DEAD. Setting S_DEAD is still needed in places where we used to set it (for directories getting killed), since we rely on it for readdir/rmdir race prevention. 2) rename()/mount() protection has another bogosity - we unhash the target before we'd checked that it's not a mountpoint. Fixed. 3) ancient bogosity in pivot_root() - we locked i_mutex on the right directory, but checked S_DEAD on the different (and wrong) one. Noticed and fixed. Signed-off-by: Al Viro diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index 4a6366a..111a01a 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c @@ -380,6 +380,7 @@ static int usbfs_rmdir(struct inode *dir, struct dentry *dentry) mutex_lock(&inode->i_mutex); dentry_unhash(dentry); if (usbfs_empty(dentry)) { + dont_mount(dentry); drop_nlink(dentry->d_inode); drop_nlink(dentry->d_inode); dput(dentry); diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index 8e48b52..0b502f8 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c @@ -645,6 +645,7 @@ static void detach_groups(struct config_group *group) configfs_detach_group(sd->s_element); child->d_inode->i_flags |= S_DEAD; + dont_mount(child); mutex_unlock(&child->d_inode->i_mutex); @@ -840,6 +841,7 @@ static int configfs_attach_item(struct config_item *parent_item, mutex_lock(&dentry->d_inode->i_mutex); configfs_remove_dir(item); dentry->d_inode->i_flags |= S_DEAD; + dont_mount(dentry); mutex_unlock(&dentry->d_inode->i_mutex); d_delete(dentry); } @@ -882,6 +884,7 @@ static int configfs_attach_group(struct config_item *parent_item, if (ret) { configfs_detach_item(item); dentry->d_inode->i_flags |= S_DEAD; + dont_mount(dentry); } configfs_adjust_dir_dirent_depth_after_populate(sd); mutex_unlock(&dentry->d_inode->i_mutex); @@ -1725,6 +1728,7 @@ void configfs_unregister_subsystem(struct configfs_subsystem *subsys) mutex_unlock(&configfs_symlink_mutex); configfs_detach_group(&group->cg_item); dentry->d_inode->i_flags |= S_DEAD; + dont_mount(dentry); mutex_unlock(&dentry->d_inode->i_mutex); d_delete(dentry); diff --git a/fs/namei.c b/fs/namei.c index 16df7277..b86b96f 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2176,8 +2176,10 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry) error = security_inode_rmdir(dir, dentry); if (!error) { error = dir->i_op->rmdir(dir, dentry); - if (!error) + if (!error) { dentry->d_inode->i_flags |= S_DEAD; + dont_mount(dentry); + } } } mutex_unlock(&dentry->d_inode->i_mutex); @@ -2261,7 +2263,7 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry) if (!error) { error = dir->i_op->unlink(dir, dentry); if (!error) - dentry->d_inode->i_flags |= S_DEAD; + dont_mount(dentry); } } mutex_unlock(&dentry->d_inode->i_mutex); @@ -2572,17 +2574,20 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, return error; target = new_dentry->d_inode; - if (target) { + if (target) mutex_lock(&target->i_mutex); - dentry_unhash(new_dentry); - } if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry)) error = -EBUSY; - else + else { + if (target) + dentry_unhash(new_dentry); error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry); + } if (target) { - if (!error) + if (!error) { target->i_flags |= S_DEAD; + dont_mount(new_dentry); + } mutex_unlock(&target->i_mutex); if (d_unhashed(new_dentry)) d_rehash(new_dentry); @@ -2614,7 +2619,7 @@ static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry, error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry); if (!error) { if (target) - target->i_flags |= S_DEAD; + dont_mount(new_dentry); if (!(old_dir->i_sb->s_type->fs_flags & FS_RENAME_DOES_D_MOVE)) d_move(old_dentry, new_dentry); } diff --git a/fs/namespace.c b/fs/namespace.c index 8174c8a..f20cb57 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1432,7 +1432,7 @@ static int graft_tree(struct vfsmount *mnt, struct path *path) err = -ENOENT; mutex_lock(&path->dentry->d_inode->i_mutex); - if (IS_DEADDIR(path->dentry->d_inode)) + if (cant_mount(path->dentry)) goto out_unlock; err = security_sb_check_sb(mnt, path); @@ -1623,7 +1623,7 @@ static int do_move_mount(struct path *path, char *old_name) err = -ENOENT; mutex_lock(&path->dentry->d_inode->i_mutex); - if (IS_DEADDIR(path->dentry->d_inode)) + if (cant_mount(path->dentry)) goto out1; if (d_unlinked(path->dentry)) @@ -2234,7 +2234,7 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, if (!check_mnt(root.mnt)) goto out2; error = -ENOENT; - if (IS_DEADDIR(new.dentry->d_inode)) + if (cant_mount(old.dentry)) goto out2; if (d_unlinked(new.dentry)) goto out2; diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 30b93b2..eebb617 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -186,6 +186,8 @@ d_iput: no no no yes #define DCACHE_FSNOTIFY_PARENT_WATCHED 0x0080 /* Parent inode is watched by some fsnotify listener */ +#define DCACHE_CANT_MOUNT 0x0100 + extern spinlock_t dcache_lock; extern seqlock_t rename_lock; @@ -358,6 +360,18 @@ static inline int d_unlinked(struct dentry *dentry) return d_unhashed(dentry) && !IS_ROOT(dentry); } +static inline int cant_mount(struct dentry *dentry) +{ + return (dentry->d_flags & DCACHE_CANT_MOUNT); +} + +static inline void dont_mount(struct dentry *dentry) +{ + spin_lock(&dentry->d_lock); + dentry->d_flags |= DCACHE_CANT_MOUNT; + spin_unlock(&dentry->d_lock); +} + static inline struct dentry *dget_parent(struct dentry *dentry) { struct dentry *ret; -- cgit v0.10.2 From 265624495f5acf6077f8f8d264f8170573d8d752 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 28 Apr 2010 20:57:02 -0400 Subject: Fix double-free in logfs iput() is needed *until* we'd done successful d_alloc_root() Signed-off-by: Al Viro diff --git a/fs/logfs/super.c b/fs/logfs/super.c index 5866ee6..d7c23ed 100644 --- a/fs/logfs/super.c +++ b/fs/logfs/super.c @@ -333,27 +333,27 @@ static int logfs_get_sb_final(struct super_block *sb, struct vfsmount *mnt) goto fail; sb->s_root = d_alloc_root(rootdir); - if (!sb->s_root) - goto fail2; + if (!sb->s_root) { + iput(rootdir); + goto fail; + } super->s_erase_page = alloc_pages(GFP_KERNEL, 0); if (!super->s_erase_page) - goto fail2; + goto fail; memset(page_address(super->s_erase_page), 0xFF, PAGE_SIZE); /* FIXME: check for read-only mounts */ err = logfs_make_writeable(sb); if (err) - goto fail3; + goto fail1; log_super("LogFS: Finished mounting\n"); simple_set_mnt(mnt, sb); return 0; -fail3: +fail1: __free_page(super->s_erase_page); -fail2: - iput(rootdir); fail: iput(logfs_super(sb)->s_master_inode); return -EIO; -- cgit v0.10.2 From 404e781249f003a37a140756fc4aeae463dcb217 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 21 Apr 2010 12:30:32 +0200 Subject: fs/sysv: dereferencing ERR_PTR() I moved the dir_put_page() inside the if condition so we don't dereference "page", if it's an ERR_PTR(). Signed-off-by: Dan Carpenter Signed-off-by: Al Viro diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c index 4e50286..1dabed2 100644 --- a/fs/sysv/dir.c +++ b/fs/sysv/dir.c @@ -164,8 +164,8 @@ struct sysv_dir_entry *sysv_find_entry(struct dentry *dentry, struct page **res_ name, de->name)) goto found; } + dir_put_page(page); } - dir_put_page(page); if (++n >= npages) n = 0; -- cgit v0.10.2 From 684bdc7ff95e0c1d4b0bcf236491840b55a54189 Mon Sep 17 00:00:00 2001 From: Jan Blunck Date: Mon, 12 Apr 2010 16:44:08 -0700 Subject: JFS: Free sbi memory in error path I spotted the missing kfree() while removing the BKL. [akpm@linux-foundation.org: avoid multiple returns so it doesn't happen again] Signed-off-by: Jan Blunck Cc: Dave Kleikamp Signed-off-by: Andrew Morton Signed-off-by: Al Viro diff --git a/fs/jfs/super.c b/fs/jfs/super.c index 157382f..b66832a 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c @@ -446,10 +446,8 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent) /* initialize the mount flag and determine the default error handler */ flag = JFS_ERR_REMOUNT_RO; - if (!parse_options((char *) data, sb, &newLVSize, &flag)) { - kfree(sbi); - return -EINVAL; - } + if (!parse_options((char *) data, sb, &newLVSize, &flag)) + goto out_kfree; sbi->flag = flag; #ifdef CONFIG_JFS_POSIX_ACL @@ -458,7 +456,7 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent) if (newLVSize) { printk(KERN_ERR "resize option for remount only\n"); - return -EINVAL; + goto out_kfree; } /* @@ -478,7 +476,7 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent) inode = new_inode(sb); if (inode == NULL) { ret = -ENOMEM; - goto out_kfree; + goto out_unload; } inode->i_ino = 0; inode->i_nlink = 1; @@ -550,9 +548,10 @@ out_mount_failed: make_bad_inode(sbi->direct_inode); iput(sbi->direct_inode); sbi->direct_inode = NULL; -out_kfree: +out_unload: if (sbi->nls_tab) unload_nls(sbi->nls_tab); +out_kfree: kfree(sbi); return ret; } -- cgit v0.10.2 From 4d736b5e1cffb716bfbad669ce6aedf454779373 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Sun, 4 Apr 2010 23:25:52 +0900 Subject: arm: use asm-generic/scatterlist.h Signed-off-by: FUJITA Tomonori Signed-off-by: Russell King diff --git a/arch/arm/include/asm/scatterlist.h b/arch/arm/include/asm/scatterlist.h index ca0a37d..bcda59f 100644 --- a/arch/arm/include/asm/scatterlist.h +++ b/arch/arm/include/asm/scatterlist.h @@ -4,24 +4,8 @@ #include #include -struct scatterlist { -#ifdef CONFIG_DEBUG_SG - unsigned long sg_magic; -#endif - unsigned long page_link; - unsigned int offset; /* buffer offset */ - dma_addr_t dma_address; /* dma address */ - unsigned int length; /* length */ -}; +#include -/* - * These macros should be used after a pci_map_sg call has been done - * to get bus addresses of each of the SG entries and their lengths. - * You should only work with the number of sg entries pci_map_sg - * returns, or alternatively stop on the first sg_dma_len(sg) which - * is 0. - */ -#define sg_dma_address(sg) ((sg)->dma_address) -#define sg_dma_len(sg) ((sg)->length) +#undef ARCH_HAS_SG_CHAIN #endif /* _ASMARM_SCATTERLIST_H */ -- cgit v0.10.2 From b7072c63c1b0611042ba6ecf0152a33c7b806e67 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sun, 2 May 2010 12:40:35 +0300 Subject: ARM: convert /proc/cpu/aligment to seq_file Convert code away from ->read_proc/->write_proc interfaces. Switch to proc_create()/proc_create_data() which makes addition of proc entries reliable wrt NULL ->proc_fops, NULL ->data and so on. Problem with ->read_proc et al is described here commit 786d7e1612f0b0adb6046f19b906609e4fe8b1ba "Fix rmmod/read/write races in /proc entries" This patch is part of an effort to remove the old simple procfs PAGE_SIZE buffer interface. Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Russell King diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index edddd66..28b7c27 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -94,36 +95,29 @@ static const char *usermode_action[] = { "signal+warn" }; -static int -proc_alignment_read(char *page, char **start, off_t off, int count, int *eof, - void *data) +static int alignment_proc_show(struct seq_file *m, void *v) { - char *p = page; - int len; - - p += sprintf(p, "User:\t\t%lu\n", ai_user); - p += sprintf(p, "System:\t\t%lu\n", ai_sys); - p += sprintf(p, "Skipped:\t%lu\n", ai_skipped); - p += sprintf(p, "Half:\t\t%lu\n", ai_half); - p += sprintf(p, "Word:\t\t%lu\n", ai_word); + seq_printf(m, "User:\t\t%lu\n", ai_user); + seq_printf(m, "System:\t\t%lu\n", ai_sys); + seq_printf(m, "Skipped:\t%lu\n", ai_skipped); + seq_printf(m, "Half:\t\t%lu\n", ai_half); + seq_printf(m, "Word:\t\t%lu\n", ai_word); if (cpu_architecture() >= CPU_ARCH_ARMv5TE) - p += sprintf(p, "DWord:\t\t%lu\n", ai_dword); - p += sprintf(p, "Multi:\t\t%lu\n", ai_multi); - p += sprintf(p, "User faults:\t%i (%s)\n", ai_usermode, + seq_printf(m, "DWord:\t\t%lu\n", ai_dword); + seq_printf(m, "Multi:\t\t%lu\n", ai_multi); + seq_printf(m, "User faults:\t%i (%s)\n", ai_usermode, usermode_action[ai_usermode]); - len = (p - page) - off; - if (len < 0) - len = 0; - - *eof = (len <= count) ? 1 : 0; - *start = page + off; + return 0; +} - return len; +static int alignment_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, alignment_proc_show, NULL); } -static int proc_alignment_write(struct file *file, const char __user *buffer, - unsigned long count, void *data) +static ssize_t alignment_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) { char mode; @@ -136,6 +130,13 @@ static int proc_alignment_write(struct file *file, const char __user *buffer, return count; } +static const struct file_operations alignment_proc_fops = { + .open = alignment_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = alignment_proc_write, +}; #endif /* CONFIG_PROC_FS */ union offset_union { @@ -901,12 +902,10 @@ static int __init alignment_init(void) #ifdef CONFIG_PROC_FS struct proc_dir_entry *res; - res = create_proc_entry("cpu/alignment", S_IWUSR | S_IRUGO, NULL); + res = proc_create("cpu/alignment", S_IWUSR | S_IRUGO, NULL, + &alignment_proc_fops); if (!res) return -ENOMEM; - - res->read_proc = proc_alignment_read; - res->write_proc = proc_alignment_write; #endif /* -- cgit v0.10.2 From 6262c92f51ffb074800d5a340ee16bc06758e037 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 25 Mar 2010 17:06:19 +0000 Subject: ARM: Remove useless linux/bootmem.h includes These files include linux/bootmem.h without using anything from this file; remove the unnecessary include. Acked-by: Tony Lindgren Signed-off-by: Russell King diff --git a/arch/arm/mach-clps711x/mm.c b/arch/arm/mach-clps711x/mm.c index a7b4591..9865921 100644 --- a/arch/arm/mach-clps711x/mm.c +++ b/arch/arm/mach-clps711x/mm.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index 71728d3..0bce097 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/arm/mach-omap1/board-htcherald.c b/arch/arm/mach-omap1/board-htcherald.c index e36639f..8e313b4 100644 --- a/arch/arm/mach-omap1/board-htcherald.c +++ b/arch/arm/mach-omap1/board-htcherald.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index c664947..aa3e209 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -43,7 +43,6 @@ #include #include #include -#include #include #include -- cgit v0.10.2 From ceb683d3bc36f213aeef0c5d79e6fbb1e16bd459 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 25 Mar 2010 18:47:20 +0000 Subject: ARM: Ensure meminfo is sorted prior to sanity_check_meminfo Acked-by: Tony Lindgren Signed-off-by: Russell King diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 7829cb5..8bbb9a9 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include @@ -387,21 +386,12 @@ static void arm_memory_present(struct meminfo *mi, int node) } #endif -static int __init meminfo_cmp(const void *_a, const void *_b) -{ - const struct membank *a = _a, *b = _b; - long cmp = bank_pfn_start(a) - bank_pfn_start(b); - return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; -} - void __init bootmem_init(void) { struct meminfo *mi = &meminfo; unsigned long min, max_low, max_high; int node, initrd_node; - sort(&mi->bank, mi->nr_banks, sizeof(mi->bank[0]), meminfo_cmp, NULL); - /* * Locate which node contains the ramdisk image, if any. */ diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 9d4da6a..9154719 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -1013,6 +1014,13 @@ static void __init kmap_init(void) #endif } +static int __init meminfo_cmp(const void *_a, const void *_b) +{ + const struct membank *a = _a, *b = _b; + long cmp = bank_pfn_start(a) - bank_pfn_start(b); + return cmp < 0 ? -1 : cmp > 0 ? 1 : 0; +} + /* * paging_init() sets up the page tables, initialises the zone memory * maps, and sets up the zero page, bad page and bad page tables. @@ -1021,6 +1029,8 @@ void __init paging_init(struct machine_desc *mdesc) { void *zero_page; + sort(&meminfo.bank, meminfo.nr_banks, sizeof(meminfo.bank[0]), meminfo_cmp, NULL); + build_mem_type_table(); sanity_check_meminfo(); prepare_page_table(); -- cgit v0.10.2 From a2227120eead4ea7d2ea04d8ce0947f1dd23dedf Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 25 Mar 2010 18:56:05 +0000 Subject: ARM: Move memory mapping into mmu.c Acked-by: Tony Lindgren Signed-off-by: Russell King diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 8bbb9a9..105d1d4 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -225,20 +225,6 @@ static int __init check_initrd(struct meminfo *mi) return initrd_node; } -static inline void map_memory_bank(struct membank *bank) -{ -#ifdef CONFIG_MMU - struct map_desc map; - - map.pfn = bank_pfn_start(bank); - map.virtual = __phys_to_virt(bank_phys_start(bank)); - map.length = bank_phys_size(bank); - map.type = MT_MEMORY; - - create_mapping(&map); -#endif -} - static void __init bootmem_init_node(int node, struct meminfo *mi, unsigned long start_pfn, unsigned long end_pfn) { @@ -248,16 +234,6 @@ static void __init bootmem_init_node(int node, struct meminfo *mi, int i; /* - * Map the memory banks for this node. - */ - for_each_nodebank(i, mi, node) { - struct membank *bank = &mi->bank[i]; - - if (!bank->highmem) - map_memory_bank(bank); - } - - /* * Allocate the bootmem bitmap page. */ boot_pages = bootmem_bootmap_pages(end_pfn - start_pfn); diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h index a888363..815d08e 100644 --- a/arch/arm/mm/mm.h +++ b/arch/arm/mm/mm.h @@ -28,10 +28,7 @@ extern void __flush_dcache_page(struct address_space *mapping, struct page *page #endif -struct map_desc; -struct meminfo; struct pglist_data; -void __init create_mapping(struct map_desc *md); void __init bootmem_init(void); void reserve_node_zero(struct pglist_data *pgdat); diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 9154719..6985200 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -600,7 +600,7 @@ static void __init create_36bit_mapping(struct map_desc *md, * offsets, and we take full advantage of sections and * supersections. */ -void __init create_mapping(struct map_desc *md) +static void __init create_mapping(struct map_desc *md) { unsigned long phys, addr, length, end; const struct mem_type *type; @@ -1014,6 +1014,32 @@ static void __init kmap_init(void) #endif } +static inline void map_memory_bank(struct membank *bank) +{ + struct map_desc map; + + map.pfn = bank_pfn_start(bank); + map.virtual = __phys_to_virt(bank_phys_start(bank)); + map.length = bank_phys_size(bank); + map.type = MT_MEMORY; + + create_mapping(&map); +} + +static void __init map_lowmem(void) +{ + struct meminfo *mi = &meminfo; + int i; + + /* Map all the lowmem memory banks. */ + for (i = 0; i < mi->nr_banks; i++) { + struct membank *bank = &mi->bank[i]; + + if (!bank->highmem) + map_memory_bank(bank); + } +} + static int __init meminfo_cmp(const void *_a, const void *_b) { const struct membank *a = _a, *b = _b; @@ -1034,6 +1060,7 @@ void __init paging_init(struct machine_desc *mdesc) build_mem_type_table(); sanity_check_meminfo(); prepare_page_table(); + map_lowmem(); bootmem_init(); devicemaps_init(mdesc); kmap_init(); -- cgit v0.10.2 From 64039be8226b9f6c80c704d94ac9891eee4a274c Mon Sep 17 00:00:00 2001 From: Jason McMullan Date: Wed, 5 May 2010 18:59:37 +0100 Subject: ARM: 6094/1: Extend cache-l2x0 to support the 16-way PL310 The L310 cache controller's interface is almost identical to the L210. One major difference is that the PL310 can have up to 16 ways. This change uses the cache's part ID and the Associativity bits in the AUX_CTRL register to determine the number of ways. Also, this version prints out the CACHE_ID and AUX_CTRL registers. Acked-by: Will Deacon Acked-by: Acked-by: Catalin Marinas Signed-off-by: Jason S. McMullan Signed-off-by: Russell King diff --git a/arch/arm/include/asm/hardware/cache-l2x0.h b/arch/arm/include/asm/hardware/cache-l2x0.h index cdb9022..6bcba48 100644 --- a/arch/arm/include/asm/hardware/cache-l2x0.h +++ b/arch/arm/include/asm/hardware/cache-l2x0.h @@ -21,6 +21,9 @@ #define __ASM_ARM_HARDWARE_L2X0_H #define L2X0_CACHE_ID 0x000 +#define L2X0_CACHE_ID_PART_MASK (0xf << 6) +#define L2X0_CACHE_ID_PART_L210 (1 << 6) +#define L2X0_CACHE_ID_PART_L310 (3 << 6) #define L2X0_CACHE_TYPE 0x004 #define L2X0_CTRL 0x100 #define L2X0_AUX_CTRL 0x104 diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index 0733463..78f0fc8 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -27,6 +27,7 @@ static void __iomem *l2x0_base; static DEFINE_SPINLOCK(l2x0_lock); +static uint32_t l2x0_way_mask; /* Bitmask of active ways */ static inline void cache_wait(void __iomem *reg, unsigned long mask) { @@ -99,8 +100,8 @@ static inline void l2x0_inv_all(void) /* invalidate all ways */ spin_lock_irqsave(&l2x0_lock, flags); - writel(0xff, l2x0_base + L2X0_INV_WAY); - cache_wait(l2x0_base + L2X0_INV_WAY, 0xff); + writel(l2x0_way_mask, l2x0_base + L2X0_INV_WAY); + cache_wait(l2x0_base + L2X0_INV_WAY, l2x0_way_mask); cache_sync(); spin_unlock_irqrestore(&l2x0_lock, flags); } @@ -199,9 +200,37 @@ static void l2x0_flush_range(unsigned long start, unsigned long end) void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) { __u32 aux; + __u32 cache_id; + int ways; + const char *type; l2x0_base = base; + cache_id = readl(l2x0_base + L2X0_CACHE_ID); + aux = readl(l2x0_base + L2X0_AUX_CTRL); + + /* Determine the number of ways */ + switch (cache_id & L2X0_CACHE_ID_PART_MASK) { + case L2X0_CACHE_ID_PART_L310: + if (aux & (1 << 16)) + ways = 16; + else + ways = 8; + type = "L310"; + break; + case L2X0_CACHE_ID_PART_L210: + ways = (aux >> 13) & 0xf; + type = "L210"; + break; + default: + /* Assume unknown chips have 8 ways */ + ways = 8; + type = "L2x0 series"; + break; + } + + l2x0_way_mask = (1 << ways) - 1; + /* * Check if l2x0 controller is already enabled. * If you are booting from non-secure mode @@ -210,8 +239,6 @@ void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) if (!(readl(l2x0_base + L2X0_CTRL) & 1)) { /* l2x0 controller is disabled */ - - aux = readl(l2x0_base + L2X0_AUX_CTRL); aux &= aux_mask; aux |= aux_val; writel(aux, l2x0_base + L2X0_AUX_CTRL); @@ -226,5 +253,7 @@ void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) outer_cache.clean_range = l2x0_clean_range; outer_cache.flush_range = l2x0_flush_range; - printk(KERN_INFO "L2X0 cache controller enabled\n"); + printk(KERN_INFO "%s cache controller enabled\n", type); + printk(KERN_INFO "l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x\n", + ways, cache_id, aux); } -- cgit v0.10.2 From 75070612c49c0bb976bb9221d051b20316ad1bc7 Mon Sep 17 00:00:00 2001 From: Jassi Brar Date: Fri, 14 May 2010 15:18:54 +0100 Subject: ARM: 6132/1: PL330: Add common core driver PL330 is a configurable DMA controller PrimeCell device. The register map of the device is well defined. The configuration of a particular implementation can be read from the six configuration registers CR0-4,Dn. This patch implements a driver for the specification:- http://infocenter.arm.com/help/topic/com.arm.doc.ddi0424a/DDI0424A_dmac_pl330_r0p0_trm.pdf The exported interface should be sufficient to implement a driver for any DMA API. Signed-off-by: Jassi Brar Signed-off-by: Russell King diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig index b64bb78..cf90590 100644 --- a/arch/arm/common/Kconfig +++ b/arch/arm/common/Kconfig @@ -18,6 +18,9 @@ config ICST525 config ICST307 bool +config PL330 + bool + config SA1111 bool select DMABOUNCE if !ARCH_PXA diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile index 76be7ff..df20c26 100644 --- a/arch/arm/common/Makefile +++ b/arch/arm/common/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_ARM_GIC) += gic.o obj-$(CONFIG_ARM_VIC) += vic.o obj-$(CONFIG_ICST525) += icst525.o obj-$(CONFIG_ICST307) += icst307.o +obj-$(CONFIG_PL330) += pl330.o obj-$(CONFIG_SA1111) += sa1111.o obj-$(CONFIG_PCI_HOST_VIA82C505) += via82c505.o obj-$(CONFIG_DMABOUNCE) += dmabounce.o diff --git a/arch/arm/common/pl330.c b/arch/arm/common/pl330.c new file mode 100644 index 0000000..5ebbab6 --- /dev/null +++ b/arch/arm/common/pl330.c @@ -0,0 +1,1966 @@ +/* linux/arch/arm/common/pl330.c + * + * Copyright (C) 2010 Samsung Electronics Co Ltd. + * Jaswinder Singh + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Register and Bit field Definitions */ +#define DS 0x0 +#define DS_ST_STOP 0x0 +#define DS_ST_EXEC 0x1 +#define DS_ST_CMISS 0x2 +#define DS_ST_UPDTPC 0x3 +#define DS_ST_WFE 0x4 +#define DS_ST_ATBRR 0x5 +#define DS_ST_QBUSY 0x6 +#define DS_ST_WFP 0x7 +#define DS_ST_KILL 0x8 +#define DS_ST_CMPLT 0x9 +#define DS_ST_FLTCMP 0xe +#define DS_ST_FAULT 0xf + +#define DPC 0x4 +#define INTEN 0x20 +#define ES 0x24 +#define INTSTATUS 0x28 +#define INTCLR 0x2c +#define FSM 0x30 +#define FSC 0x34 +#define FTM 0x38 + +#define _FTC 0x40 +#define FTC(n) (_FTC + (n)*0x4) + +#define _CS 0x100 +#define CS(n) (_CS + (n)*0x8) +#define CS_CNS (1 << 21) + +#define _CPC 0x104 +#define CPC(n) (_CPC + (n)*0x8) + +#define _SA 0x400 +#define SA(n) (_SA + (n)*0x20) + +#define _DA 0x404 +#define DA(n) (_DA + (n)*0x20) + +#define _CC 0x408 +#define CC(n) (_CC + (n)*0x20) + +#define CC_SRCINC (1 << 0) +#define CC_DSTINC (1 << 14) +#define CC_SRCPRI (1 << 8) +#define CC_DSTPRI (1 << 22) +#define CC_SRCNS (1 << 9) +#define CC_DSTNS (1 << 23) +#define CC_SRCIA (1 << 10) +#define CC_DSTIA (1 << 24) +#define CC_SRCBRSTLEN_SHFT 4 +#define CC_DSTBRSTLEN_SHFT 18 +#define CC_SRCBRSTSIZE_SHFT 1 +#define CC_DSTBRSTSIZE_SHFT 15 +#define CC_SRCCCTRL_SHFT 11 +#define CC_SRCCCTRL_MASK 0x7 +#define CC_DSTCCTRL_SHFT 25 +#define CC_DRCCCTRL_MASK 0x7 +#define CC_SWAP_SHFT 28 + +#define _LC0 0x40c +#define LC0(n) (_LC0 + (n)*0x20) + +#define _LC1 0x410 +#define LC1(n) (_LC1 + (n)*0x20) + +#define DBGSTATUS 0xd00 +#define DBG_BUSY (1 << 0) + +#define DBGCMD 0xd04 +#define DBGINST0 0xd08 +#define DBGINST1 0xd0c + +#define CR0 0xe00 +#define CR1 0xe04 +#define CR2 0xe08 +#define CR3 0xe0c +#define CR4 0xe10 +#define CRD 0xe14 + +#define PERIPH_ID 0xfe0 +#define PCELL_ID 0xff0 + +#define CR0_PERIPH_REQ_SET (1 << 0) +#define CR0_BOOT_EN_SET (1 << 1) +#define CR0_BOOT_MAN_NS (1 << 2) +#define CR0_NUM_CHANS_SHIFT 4 +#define CR0_NUM_CHANS_MASK 0x7 +#define CR0_NUM_PERIPH_SHIFT 12 +#define CR0_NUM_PERIPH_MASK 0x1f +#define CR0_NUM_EVENTS_SHIFT 17 +#define CR0_NUM_EVENTS_MASK 0x1f + +#define CR1_ICACHE_LEN_SHIFT 0 +#define CR1_ICACHE_LEN_MASK 0x7 +#define CR1_NUM_ICACHELINES_SHIFT 4 +#define CR1_NUM_ICACHELINES_MASK 0xf + +#define CRD_DATA_WIDTH_SHIFT 0 +#define CRD_DATA_WIDTH_MASK 0x7 +#define CRD_WR_CAP_SHIFT 4 +#define CRD_WR_CAP_MASK 0x7 +#define CRD_WR_Q_DEP_SHIFT 8 +#define CRD_WR_Q_DEP_MASK 0xf +#define CRD_RD_CAP_SHIFT 12 +#define CRD_RD_CAP_MASK 0x7 +#define CRD_RD_Q_DEP_SHIFT 16 +#define CRD_RD_Q_DEP_MASK 0xf +#define CRD_DATA_BUFF_SHIFT 20 +#define CRD_DATA_BUFF_MASK 0x3ff + +#define PART 0x330 +#define DESIGNER 0x41 +#define REVISION 0x0 +#define INTEG_CFG 0x0 +#define PERIPH_ID_VAL ((PART << 0) | (DESIGNER << 12) \ + | (REVISION << 20) | (INTEG_CFG << 24)) + +#define PCELL_ID_VAL 0xb105f00d + +#define PL330_STATE_STOPPED (1 << 0) +#define PL330_STATE_EXECUTING (1 << 1) +#define PL330_STATE_WFE (1 << 2) +#define PL330_STATE_FAULTING (1 << 3) +#define PL330_STATE_COMPLETING (1 << 4) +#define PL330_STATE_WFP (1 << 5) +#define PL330_STATE_KILLING (1 << 6) +#define PL330_STATE_FAULT_COMPLETING (1 << 7) +#define PL330_STATE_CACHEMISS (1 << 8) +#define PL330_STATE_UPDTPC (1 << 9) +#define PL330_STATE_ATBARRIER (1 << 10) +#define PL330_STATE_QUEUEBUSY (1 << 11) +#define PL330_STATE_INVALID (1 << 15) + +#define PL330_STABLE_STATES (PL330_STATE_STOPPED | PL330_STATE_EXECUTING \ + | PL330_STATE_WFE | PL330_STATE_FAULTING) + +#define CMD_DMAADDH 0x54 +#define CMD_DMAEND 0x00 +#define CMD_DMAFLUSHP 0x35 +#define CMD_DMAGO 0xa0 +#define CMD_DMALD 0x04 +#define CMD_DMALDP 0x25 +#define CMD_DMALP 0x20 +#define CMD_DMALPEND 0x28 +#define CMD_DMAKILL 0x01 +#define CMD_DMAMOV 0xbc +#define CMD_DMANOP 0x18 +#define CMD_DMARMB 0x12 +#define CMD_DMASEV 0x34 +#define CMD_DMAST 0x08 +#define CMD_DMASTP 0x29 +#define CMD_DMASTZ 0x0c +#define CMD_DMAWFE 0x36 +#define CMD_DMAWFP 0x30 +#define CMD_DMAWMB 0x13 + +#define SZ_DMAADDH 3 +#define SZ_DMAEND 1 +#define SZ_DMAFLUSHP 2 +#define SZ_DMALD 1 +#define SZ_DMALDP 2 +#define SZ_DMALP 2 +#define SZ_DMALPEND 2 +#define SZ_DMAKILL 1 +#define SZ_DMAMOV 6 +#define SZ_DMANOP 1 +#define SZ_DMARMB 1 +#define SZ_DMASEV 2 +#define SZ_DMAST 1 +#define SZ_DMASTP 2 +#define SZ_DMASTZ 1 +#define SZ_DMAWFE 2 +#define SZ_DMAWFP 2 +#define SZ_DMAWMB 1 +#define SZ_DMAGO 6 + +#define BRST_LEN(ccr) ((((ccr) >> CC_SRCBRSTLEN_SHFT) & 0xf) + 1) +#define BRST_SIZE(ccr) (1 << (((ccr) >> CC_SRCBRSTSIZE_SHFT) & 0x7)) + +#define BYTE_TO_BURST(b, ccr) ((b) / BRST_SIZE(ccr) / BRST_LEN(ccr)) +#define BURST_TO_BYTE(c, ccr) ((c) * BRST_SIZE(ccr) * BRST_LEN(ccr)) + +/* + * With 256 bytes, we can do more than 2.5MB and 5MB xfers per req + * at 1byte/burst for P<->M and M<->M respectively. + * For typical scenario, at 1word/burst, 10MB and 20MB xfers per req + * should be enough for P<->M and M<->M respectively. + */ +#define MCODE_BUFF_PER_REQ 256 + +/* + * Mark a _pl330_req as free. + * We do it by writing DMAEND as the first instruction + * because no valid request is going to have DMAEND as + * its first instruction to execute. + */ +#define MARK_FREE(req) do { \ + _emit_END(0, (req)->mc_cpu); \ + (req)->mc_len = 0; \ + } while (0) + +/* If the _pl330_req is available to the client */ +#define IS_FREE(req) (*((u8 *)((req)->mc_cpu)) == CMD_DMAEND) + +/* Use this _only_ to wait on transient states */ +#define UNTIL(t, s) while (!(_state(t) & (s))) cpu_relax(); + +#ifdef PL330_DEBUG_MCGEN +static unsigned cmd_line; +#define PL330_DBGCMD_DUMP(off, x...) do { \ + printk("%x:", cmd_line); \ + printk(x); \ + cmd_line += off; \ + } while (0) +#define PL330_DBGMC_START(addr) (cmd_line = addr) +#else +#define PL330_DBGCMD_DUMP(off, x...) do {} while (0) +#define PL330_DBGMC_START(addr) do {} while (0) +#endif + +struct _xfer_spec { + u32 ccr; + struct pl330_req *r; + struct pl330_xfer *x; +}; + +enum dmamov_dst { + SAR = 0, + CCR, + DAR, +}; + +enum pl330_dst { + SRC = 0, + DST, +}; + +enum pl330_cond { + SINGLE, + BURST, + ALWAYS, +}; + +struct _pl330_req { + u32 mc_bus; + void *mc_cpu; + /* Number of bytes taken to setup MC for the req */ + u32 mc_len; + struct pl330_req *r; + /* Hook to attach to DMAC's list of reqs with due callback */ + struct list_head rqd; +}; + +/* ToBeDone for tasklet */ +struct _pl330_tbd { + bool reset_dmac; + bool reset_mngr; + u8 reset_chan; +}; + +/* A DMAC Thread */ +struct pl330_thread { + u8 id; + int ev; + /* If the channel is not yet acquired by any client */ + bool free; + /* Parent DMAC */ + struct pl330_dmac *dmac; + /* Only two at a time */ + struct _pl330_req req[2]; + /* Index of the last submitted request */ + unsigned lstenq; +}; + +enum pl330_dmac_state { + UNINIT, + INIT, + DYING, +}; + +/* A DMAC */ +struct pl330_dmac { + spinlock_t lock; + /* Holds list of reqs with due callbacks */ + struct list_head req_done; + /* Pointer to platform specific stuff */ + struct pl330_info *pinfo; + /* Maximum possible events/irqs */ + int events[32]; + /* BUS address of MicroCode buffer */ + u32 mcode_bus; + /* CPU address of MicroCode buffer */ + void *mcode_cpu; + /* List of all Channel threads */ + struct pl330_thread *channels; + /* Pointer to the MANAGER thread */ + struct pl330_thread *manager; + /* To handle bad news in interrupt */ + struct tasklet_struct tasks; + struct _pl330_tbd dmac_tbd; + /* State of DMAC operation */ + enum pl330_dmac_state state; +}; + +static inline void _callback(struct pl330_req *r, enum pl330_op_err err) +{ + if (r && r->xfer_cb) + r->xfer_cb(r->token, err); +} + +static inline bool _queue_empty(struct pl330_thread *thrd) +{ + return (IS_FREE(&thrd->req[0]) && IS_FREE(&thrd->req[1])) + ? true : false; +} + +static inline bool _queue_full(struct pl330_thread *thrd) +{ + return (IS_FREE(&thrd->req[0]) || IS_FREE(&thrd->req[1])) + ? false : true; +} + +static inline bool is_manager(struct pl330_thread *thrd) +{ + struct pl330_dmac *pl330 = thrd->dmac; + + /* MANAGER is indexed at the end */ + if (thrd->id == pl330->pinfo->pcfg.num_chan) + return true; + else + return false; +} + +/* If manager of the thread is in Non-Secure mode */ +static inline bool _manager_ns(struct pl330_thread *thrd) +{ + struct pl330_dmac *pl330 = thrd->dmac; + + return (pl330->pinfo->pcfg.mode & DMAC_MODE_NS) ? true : false; +} + +static inline u32 get_id(struct pl330_info *pi, u32 off) +{ + void __iomem *regs = pi->base; + u32 id = 0; + + id |= (readb(regs + off + 0x0) << 0); + id |= (readb(regs + off + 0x4) << 8); + id |= (readb(regs + off + 0x8) << 16); + id |= (readb(regs + off + 0xc) << 24); + + return id; +} + +static inline u32 _emit_ADDH(unsigned dry_run, u8 buf[], + enum pl330_dst da, u16 val) +{ + if (dry_run) + return SZ_DMAADDH; + + buf[0] = CMD_DMAADDH; + buf[0] |= (da << 1); + *((u16 *)&buf[1]) = val; + + PL330_DBGCMD_DUMP(SZ_DMAADDH, "\tDMAADDH %s %u\n", + da == 1 ? "DA" : "SA", val); + + return SZ_DMAADDH; +} + +static inline u32 _emit_END(unsigned dry_run, u8 buf[]) +{ + if (dry_run) + return SZ_DMAEND; + + buf[0] = CMD_DMAEND; + + PL330_DBGCMD_DUMP(SZ_DMAEND, "\tDMAEND\n"); + + return SZ_DMAEND; +} + +static inline u32 _emit_FLUSHP(unsigned dry_run, u8 buf[], u8 peri) +{ + if (dry_run) + return SZ_DMAFLUSHP; + + buf[0] = CMD_DMAFLUSHP; + + peri &= 0x1f; + peri <<= 3; + buf[1] = peri; + + PL330_DBGCMD_DUMP(SZ_DMAFLUSHP, "\tDMAFLUSHP %u\n", peri >> 3); + + return SZ_DMAFLUSHP; +} + +static inline u32 _emit_LD(unsigned dry_run, u8 buf[], enum pl330_cond cond) +{ + if (dry_run) + return SZ_DMALD; + + buf[0] = CMD_DMALD; + + if (cond == SINGLE) + buf[0] |= (0 << 1) | (1 << 0); + else if (cond == BURST) + buf[0] |= (1 << 1) | (1 << 0); + + PL330_DBGCMD_DUMP(SZ_DMALD, "\tDMALD%c\n", + cond == SINGLE ? 'S' : (cond == BURST ? 'B' : 'A')); + + return SZ_DMALD; +} + +static inline u32 _emit_LDP(unsigned dry_run, u8 buf[], + enum pl330_cond cond, u8 peri) +{ + if (dry_run) + return SZ_DMALDP; + + buf[0] = CMD_DMALDP; + + if (cond == BURST) + buf[0] |= (1 << 1); + + peri &= 0x1f; + peri <<= 3; + buf[1] = peri; + + PL330_DBGCMD_DUMP(SZ_DMALDP, "\tDMALDP%c %u\n", + cond == SINGLE ? 'S' : 'B', peri >> 3); + + return SZ_DMALDP; +} + +static inline u32 _emit_LP(unsigned dry_run, u8 buf[], + unsigned loop, u8 cnt) +{ + if (dry_run) + return SZ_DMALP; + + buf[0] = CMD_DMALP; + + if (loop) + buf[0] |= (1 << 1); + + cnt--; /* DMAC increments by 1 internally */ + buf[1] = cnt; + + PL330_DBGCMD_DUMP(SZ_DMALP, "\tDMALP_%c %u\n", loop ? '1' : '0', cnt); + + return SZ_DMALP; +} + +struct _arg_LPEND { + enum pl330_cond cond; + bool forever; + unsigned loop; + u8 bjump; +}; + +static inline u32 _emit_LPEND(unsigned dry_run, u8 buf[], + const struct _arg_LPEND *arg) +{ + enum pl330_cond cond = arg->cond; + bool forever = arg->forever; + unsigned loop = arg->loop; + u8 bjump = arg->bjump; + + if (dry_run) + return SZ_DMALPEND; + + buf[0] = CMD_DMALPEND; + + if (loop) + buf[0] |= (1 << 2); + + if (!forever) + buf[0] |= (1 << 4); + + if (cond == SINGLE) + buf[0] |= (0 << 1) | (1 << 0); + else if (cond == BURST) + buf[0] |= (1 << 1) | (1 << 0); + + buf[1] = bjump; + + PL330_DBGCMD_DUMP(SZ_DMALPEND, "\tDMALP%s%c_%c bjmpto_%x\n", + forever ? "FE" : "END", + cond == SINGLE ? 'S' : (cond == BURST ? 'B' : 'A'), + loop ? '1' : '0', + bjump); + + return SZ_DMALPEND; +} + +static inline u32 _emit_KILL(unsigned dry_run, u8 buf[]) +{ + if (dry_run) + return SZ_DMAKILL; + + buf[0] = CMD_DMAKILL; + + return SZ_DMAKILL; +} + +static inline u32 _emit_MOV(unsigned dry_run, u8 buf[], + enum dmamov_dst dst, u32 val) +{ + if (dry_run) + return SZ_DMAMOV; + + buf[0] = CMD_DMAMOV; + buf[1] = dst; + *((u32 *)&buf[2]) = val; + + PL330_DBGCMD_DUMP(SZ_DMAMOV, "\tDMAMOV %s 0x%x\n", + dst == SAR ? "SAR" : (dst == DAR ? "DAR" : "CCR"), val); + + return SZ_DMAMOV; +} + +static inline u32 _emit_NOP(unsigned dry_run, u8 buf[]) +{ + if (dry_run) + return SZ_DMANOP; + + buf[0] = CMD_DMANOP; + + PL330_DBGCMD_DUMP(SZ_DMANOP, "\tDMANOP\n"); + + return SZ_DMANOP; +} + +static inline u32 _emit_RMB(unsigned dry_run, u8 buf[]) +{ + if (dry_run) + return SZ_DMARMB; + + buf[0] = CMD_DMARMB; + + PL330_DBGCMD_DUMP(SZ_DMARMB, "\tDMARMB\n"); + + return SZ_DMARMB; +} + +static inline u32 _emit_SEV(unsigned dry_run, u8 buf[], u8 ev) +{ + if (dry_run) + return SZ_DMASEV; + + buf[0] = CMD_DMASEV; + + ev &= 0x1f; + ev <<= 3; + buf[1] = ev; + + PL330_DBGCMD_DUMP(SZ_DMASEV, "\tDMASEV %u\n", ev >> 3); + + return SZ_DMASEV; +} + +static inline u32 _emit_ST(unsigned dry_run, u8 buf[], enum pl330_cond cond) +{ + if (dry_run) + return SZ_DMAST; + + buf[0] = CMD_DMAST; + + if (cond == SINGLE) + buf[0] |= (0 << 1) | (1 << 0); + else if (cond == BURST) + buf[0] |= (1 << 1) | (1 << 0); + + PL330_DBGCMD_DUMP(SZ_DMAST, "\tDMAST%c\n", + cond == SINGLE ? 'S' : (cond == BURST ? 'B' : 'A')); + + return SZ_DMAST; +} + +static inline u32 _emit_STP(unsigned dry_run, u8 buf[], + enum pl330_cond cond, u8 peri) +{ + if (dry_run) + return SZ_DMASTP; + + buf[0] = CMD_DMASTP; + + if (cond == BURST) + buf[0] |= (1 << 1); + + peri &= 0x1f; + peri <<= 3; + buf[1] = peri; + + PL330_DBGCMD_DUMP(SZ_DMASTP, "\tDMASTP%c %u\n", + cond == SINGLE ? 'S' : 'B', peri >> 3); + + return SZ_DMASTP; +} + +static inline u32 _emit_STZ(unsigned dry_run, u8 buf[]) +{ + if (dry_run) + return SZ_DMASTZ; + + buf[0] = CMD_DMASTZ; + + PL330_DBGCMD_DUMP(SZ_DMASTZ, "\tDMASTZ\n"); + + return SZ_DMASTZ; +} + +static inline u32 _emit_WFE(unsigned dry_run, u8 buf[], u8 ev, + unsigned invalidate) +{ + if (dry_run) + return SZ_DMAWFE; + + buf[0] = CMD_DMAWFE; + + ev &= 0x1f; + ev <<= 3; + buf[1] = ev; + + if (invalidate) + buf[1] |= (1 << 1); + + PL330_DBGCMD_DUMP(SZ_DMAWFE, "\tDMAWFE %u%s\n", + ev >> 3, invalidate ? ", I" : ""); + + return SZ_DMAWFE; +} + +static inline u32 _emit_WFP(unsigned dry_run, u8 buf[], + enum pl330_cond cond, u8 peri) +{ + if (dry_run) + return SZ_DMAWFP; + + buf[0] = CMD_DMAWFP; + + if (cond == SINGLE) + buf[0] |= (0 << 1) | (0 << 0); + else if (cond == BURST) + buf[0] |= (1 << 1) | (0 << 0); + else + buf[0] |= (0 << 1) | (1 << 0); + + peri &= 0x1f; + peri <<= 3; + buf[1] = peri; + + PL330_DBGCMD_DUMP(SZ_DMAWFP, "\tDMAWFP%c %u\n", + cond == SINGLE ? 'S' : (cond == BURST ? 'B' : 'P'), peri >> 3); + + return SZ_DMAWFP; +} + +static inline u32 _emit_WMB(unsigned dry_run, u8 buf[]) +{ + if (dry_run) + return SZ_DMAWMB; + + buf[0] = CMD_DMAWMB; + + PL330_DBGCMD_DUMP(SZ_DMAWMB, "\tDMAWMB\n"); + + return SZ_DMAWMB; +} + +struct _arg_GO { + u8 chan; + u32 addr; + unsigned ns; +}; + +static inline u32 _emit_GO(unsigned dry_run, u8 buf[], + const struct _arg_GO *arg) +{ + u8 chan = arg->chan; + u32 addr = arg->addr; + unsigned ns = arg->ns; + + if (dry_run) + return SZ_DMAGO; + + buf[0] = CMD_DMAGO; + buf[0] |= (ns << 1); + + buf[1] = chan & 0x7; + + *((u32 *)&buf[2]) = addr; + + return SZ_DMAGO; +} + +#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t) + +/* Returns Time-Out */ +static bool _until_dmac_idle(struct pl330_thread *thrd) +{ + void __iomem *regs = thrd->dmac->pinfo->base; + unsigned long loops = msecs_to_loops(5); + + do { + /* Until Manager is Idle */ + if (!(readl(regs + DBGSTATUS) & DBG_BUSY)) + break; + + cpu_relax(); + } while (--loops); + + if (!loops) + return true; + + return false; +} + +static inline void _execute_DBGINSN(struct pl330_thread *thrd, + u8 insn[], bool as_manager) +{ + void __iomem *regs = thrd->dmac->pinfo->base; + u32 val; + + val = (insn[0] << 16) | (insn[1] << 24); + if (!as_manager) { + val |= (1 << 0); + val |= (thrd->id << 8); /* Channel Number */ + } + writel(val, regs + DBGINST0); + + val = *((u32 *)&insn[2]); + writel(val, regs + DBGINST1); + + /* If timed out due to halted state-machine */ + if (_until_dmac_idle(thrd)) { + dev_err(thrd->dmac->pinfo->dev, "DMAC halted!\n"); + return; + } + + /* Get going */ + writel(0, regs + DBGCMD); +} + +static inline u32 _state(struct pl330_thread *thrd) +{ + void __iomem *regs = thrd->dmac->pinfo->base; + u32 val; + + if (is_manager(thrd)) + val = readl(regs + DS) & 0xf; + else + val = readl(regs + CS(thrd->id)) & 0xf; + + switch (val) { + case DS_ST_STOP: + return PL330_STATE_STOPPED; + case DS_ST_EXEC: + return PL330_STATE_EXECUTING; + case DS_ST_CMISS: + return PL330_STATE_CACHEMISS; + case DS_ST_UPDTPC: + return PL330_STATE_UPDTPC; + case DS_ST_WFE: + return PL330_STATE_WFE; + case DS_ST_FAULT: + return PL330_STATE_FAULTING; + case DS_ST_ATBRR: + if (is_manager(thrd)) + return PL330_STATE_INVALID; + else + return PL330_STATE_ATBARRIER; + case DS_ST_QBUSY: + if (is_manager(thrd)) + return PL330_STATE_INVALID; + else + return PL330_STATE_QUEUEBUSY; + case DS_ST_WFP: + if (is_manager(thrd)) + return PL330_STATE_INVALID; + else + return PL330_STATE_WFP; + case DS_ST_KILL: + if (is_manager(thrd)) + return PL330_STATE_INVALID; + else + return PL330_STATE_KILLING; + case DS_ST_CMPLT: + if (is_manager(thrd)) + return PL330_STATE_INVALID; + else + return PL330_STATE_COMPLETING; + case DS_ST_FLTCMP: + if (is_manager(thrd)) + return PL330_STATE_INVALID; + else + return PL330_STATE_FAULT_COMPLETING; + default: + return PL330_STATE_INVALID; + } +} + +/* If the request 'req' of thread 'thrd' is currently active */ +static inline bool _req_active(struct pl330_thread *thrd, + struct _pl330_req *req) +{ + void __iomem *regs = thrd->dmac->pinfo->base; + u32 buf = req->mc_bus, pc = readl(regs + CPC(thrd->id)); + + if (IS_FREE(req)) + return false; + + return (pc >= buf && pc <= buf + req->mc_len) ? true : false; +} + +/* Returns 0 if the thread is inactive, ID of active req + 1 otherwise */ +static inline unsigned _thrd_active(struct pl330_thread *thrd) +{ + if (_req_active(thrd, &thrd->req[0])) + return 1; /* First req active */ + + if (_req_active(thrd, &thrd->req[1])) + return 2; /* Second req active */ + + return 0; +} + +static void _stop(struct pl330_thread *thrd) +{ + void __iomem *regs = thrd->dmac->pinfo->base; + u8 insn[6] = {0, 0, 0, 0, 0, 0}; + + if (_state(thrd) == PL330_STATE_FAULT_COMPLETING) + UNTIL(thrd, PL330_STATE_FAULTING | PL330_STATE_KILLING); + + /* Return if nothing needs to be done */ + if (_state(thrd) == PL330_STATE_COMPLETING + || _state(thrd) == PL330_STATE_KILLING + || _state(thrd) == PL330_STATE_STOPPED) + return; + + _emit_KILL(0, insn); + + /* Stop generating interrupts for SEV */ + writel(readl(regs + INTEN) & ~(1 << thrd->ev), regs + INTEN); + + _execute_DBGINSN(thrd, insn, is_manager(thrd)); +} + +/* Start doing req 'idx' of thread 'thrd' */ +static bool _trigger(struct pl330_thread *thrd) +{ + void __iomem *regs = thrd->dmac->pinfo->base; + struct _pl330_req *req; + struct pl330_req *r; + struct _arg_GO go; + unsigned ns; + u8 insn[6] = {0, 0, 0, 0, 0, 0}; + + /* Return if already ACTIVE */ + if (_state(thrd) != PL330_STATE_STOPPED) + return true; + + if (!IS_FREE(&thrd->req[1 - thrd->lstenq])) + req = &thrd->req[1 - thrd->lstenq]; + else if (!IS_FREE(&thrd->req[thrd->lstenq])) + req = &thrd->req[thrd->lstenq]; + else + req = NULL; + + /* Return if no request */ + if (!req || !req->r) + return true; + + r = req->r; + + if (r->cfg) + ns = r->cfg->nonsecure ? 1 : 0; + else if (readl(regs + CS(thrd->id)) & CS_CNS) + ns = 1; + else + ns = 0; + + /* See 'Abort Sources' point-4 at Page 2-25 */ + if (_manager_ns(thrd) && !ns) + dev_info(thrd->dmac->pinfo->dev, "%s:%d Recipe for ABORT!\n", + __func__, __LINE__); + + go.chan = thrd->id; + go.addr = req->mc_bus; + go.ns = ns; + _emit_GO(0, insn, &go); + + /* Set to generate interrupts for SEV */ + writel(readl(regs + INTEN) | (1 << thrd->ev), regs + INTEN); + + /* Only manager can execute GO */ + _execute_DBGINSN(thrd, insn, true); + + return true; +} + +static bool _start(struct pl330_thread *thrd) +{ + switch (_state(thrd)) { + case PL330_STATE_FAULT_COMPLETING: + UNTIL(thrd, PL330_STATE_FAULTING | PL330_STATE_KILLING); + + if (_state(thrd) == PL330_STATE_KILLING) + UNTIL(thrd, PL330_STATE_STOPPED) + + case PL330_STATE_FAULTING: + _stop(thrd); + + case PL330_STATE_KILLING: + case PL330_STATE_COMPLETING: + UNTIL(thrd, PL330_STATE_STOPPED) + + case PL330_STATE_STOPPED: + return _trigger(thrd); + + case PL330_STATE_WFP: + case PL330_STATE_QUEUEBUSY: + case PL330_STATE_ATBARRIER: + case PL330_STATE_UPDTPC: + case PL330_STATE_CACHEMISS: + case PL330_STATE_EXECUTING: + return true; + + case PL330_STATE_WFE: /* For RESUME, nothing yet */ + default: + return false; + } +} + +static inline int _ldst_memtomem(unsigned dry_run, u8 buf[], + const struct _xfer_spec *pxs, int cyc) +{ + int off = 0; + + while (cyc--) { + off += _emit_LD(dry_run, &buf[off], ALWAYS); + off += _emit_RMB(dry_run, &buf[off]); + off += _emit_ST(dry_run, &buf[off], ALWAYS); + off += _emit_WMB(dry_run, &buf[off]); + } + + return off; +} + +static inline int _ldst_devtomem(unsigned dry_run, u8 buf[], + const struct _xfer_spec *pxs, int cyc) +{ + int off = 0; + + while (cyc--) { + off += _emit_WFP(dry_run, &buf[off], SINGLE, pxs->r->peri); + off += _emit_LDP(dry_run, &buf[off], SINGLE, pxs->r->peri); + off += _emit_ST(dry_run, &buf[off], ALWAYS); + off += _emit_FLUSHP(dry_run, &buf[off], pxs->r->peri); + } + + return off; +} + +static inline int _ldst_memtodev(unsigned dry_run, u8 buf[], + const struct _xfer_spec *pxs, int cyc) +{ + int off = 0; + + while (cyc--) { + off += _emit_WFP(dry_run, &buf[off], SINGLE, pxs->r->peri); + off += _emit_LD(dry_run, &buf[off], ALWAYS); + off += _emit_STP(dry_run, &buf[off], SINGLE, pxs->r->peri); + off += _emit_FLUSHP(dry_run, &buf[off], pxs->r->peri); + } + + return off; +} + +static int _bursts(unsigned dry_run, u8 buf[], + const struct _xfer_spec *pxs, int cyc) +{ + int off = 0; + + switch (pxs->r->rqtype) { + case MEMTODEV: + off += _ldst_memtodev(dry_run, &buf[off], pxs, cyc); + break; + case DEVTOMEM: + off += _ldst_devtomem(dry_run, &buf[off], pxs, cyc); + break; + case MEMTOMEM: + off += _ldst_memtomem(dry_run, &buf[off], pxs, cyc); + break; + default: + off += 0x40000000; /* Scare off the Client */ + break; + } + + return off; +} + +/* Returns bytes consumed and updates bursts */ +static inline int _loop(unsigned dry_run, u8 buf[], + unsigned long *bursts, const struct _xfer_spec *pxs) +{ + int cyc, cycmax, szlp, szlpend, szbrst, off; + unsigned lcnt0, lcnt1, ljmp0, ljmp1; + struct _arg_LPEND lpend; + + /* Max iterations possibile in DMALP is 256 */ + if (*bursts >= 256*256) { + lcnt1 = 256; + lcnt0 = 256; + cyc = *bursts / lcnt1 / lcnt0; + } else if (*bursts > 256) { + lcnt1 = 256; + lcnt0 = *bursts / lcnt1; + cyc = 1; + } else { + lcnt1 = *bursts; + lcnt0 = 0; + cyc = 1; + } + + szlp = _emit_LP(1, buf, 0, 0); + szbrst = _bursts(1, buf, pxs, 1); + + lpend.cond = ALWAYS; + lpend.forever = false; + lpend.loop = 0; + lpend.bjump = 0; + szlpend = _emit_LPEND(1, buf, &lpend); + + if (lcnt0) { + szlp *= 2; + szlpend *= 2; + } + + /* + * Max bursts that we can unroll due to limit on the + * size of backward jump that can be encoded in DMALPEND + * which is 8-bits and hence 255 + */ + cycmax = (255 - (szlp + szlpend)) / szbrst; + + cyc = (cycmax < cyc) ? cycmax : cyc; + + off = 0; + + if (lcnt0) { + off += _emit_LP(dry_run, &buf[off], 0, lcnt0); + ljmp0 = off; + } + + off += _emit_LP(dry_run, &buf[off], 1, lcnt1); + ljmp1 = off; + + off += _bursts(dry_run, &buf[off], pxs, cyc); + + lpend.cond = ALWAYS; + lpend.forever = false; + lpend.loop = 1; + lpend.bjump = off - ljmp1; + off += _emit_LPEND(dry_run, &buf[off], &lpend); + + if (lcnt0) { + lpend.cond = ALWAYS; + lpend.forever = false; + lpend.loop = 0; + lpend.bjump = off - ljmp0; + off += _emit_LPEND(dry_run, &buf[off], &lpend); + } + + *bursts = lcnt1 * cyc; + if (lcnt0) + *bursts *= lcnt0; + + return off; +} + +static inline int _setup_loops(unsigned dry_run, u8 buf[], + const struct _xfer_spec *pxs) +{ + struct pl330_xfer *x = pxs->x; + u32 ccr = pxs->ccr; + unsigned long c, bursts = BYTE_TO_BURST(x->bytes, ccr); + int off = 0; + + while (bursts) { + c = bursts; + off += _loop(dry_run, &buf[off], &c, pxs); + bursts -= c; + } + + return off; +} + +static inline int _setup_xfer(unsigned dry_run, u8 buf[], + const struct _xfer_spec *pxs) +{ + struct pl330_xfer *x = pxs->x; + int off = 0; + + /* DMAMOV SAR, x->src_addr */ + off += _emit_MOV(dry_run, &buf[off], SAR, x->src_addr); + /* DMAMOV DAR, x->dst_addr */ + off += _emit_MOV(dry_run, &buf[off], DAR, x->dst_addr); + + /* Setup Loop(s) */ + off += _setup_loops(dry_run, &buf[off], pxs); + + return off; +} + +/* + * A req is a sequence of one or more xfer units. + * Returns the number of bytes taken to setup the MC for the req. + */ +static int _setup_req(unsigned dry_run, struct pl330_thread *thrd, + unsigned index, struct _xfer_spec *pxs) +{ + struct _pl330_req *req = &thrd->req[index]; + struct pl330_xfer *x; + u8 *buf = req->mc_cpu; + int off = 0; + + PL330_DBGMC_START(req->mc_bus); + + /* DMAMOV CCR, ccr */ + off += _emit_MOV(dry_run, &buf[off], CCR, pxs->ccr); + + x = pxs->r->x; + do { + /* Error if xfer length is not aligned at burst size */ + if (x->bytes % (BRST_SIZE(pxs->ccr) * BRST_LEN(pxs->ccr))) + return -EINVAL; + + pxs->x = x; + off += _setup_xfer(dry_run, &buf[off], pxs); + + x = x->next; + } while (x); + + /* DMASEV peripheral/event */ + off += _emit_SEV(dry_run, &buf[off], thrd->ev); + /* DMAEND */ + off += _emit_END(dry_run, &buf[off]); + + return off; +} + +static inline u32 _prepare_ccr(const struct pl330_reqcfg *rqc) +{ + u32 ccr = 0; + + if (rqc->src_inc) + ccr |= CC_SRCINC; + + if (rqc->dst_inc) + ccr |= CC_DSTINC; + + /* We set same protection levels for Src and DST for now */ + if (rqc->privileged) + ccr |= CC_SRCPRI | CC_DSTPRI; + if (rqc->nonsecure) + ccr |= CC_SRCNS | CC_DSTNS; + if (rqc->insnaccess) + ccr |= CC_SRCIA | CC_DSTIA; + + ccr |= (((rqc->brst_len - 1) & 0xf) << CC_SRCBRSTLEN_SHFT); + ccr |= (((rqc->brst_len - 1) & 0xf) << CC_DSTBRSTLEN_SHFT); + + ccr |= (rqc->brst_size << CC_SRCBRSTSIZE_SHFT); + ccr |= (rqc->brst_size << CC_DSTBRSTSIZE_SHFT); + + ccr |= (rqc->dcctl << CC_SRCCCTRL_SHFT); + ccr |= (rqc->scctl << CC_DSTCCTRL_SHFT); + + ccr |= (rqc->swap << CC_SWAP_SHFT); + + return ccr; +} + +static inline bool _is_valid(u32 ccr) +{ + enum pl330_dstcachectrl dcctl; + enum pl330_srccachectrl scctl; + + dcctl = (ccr >> CC_DSTCCTRL_SHFT) & CC_DRCCCTRL_MASK; + scctl = (ccr >> CC_SRCCCTRL_SHFT) & CC_SRCCCTRL_MASK; + + if (dcctl == DINVALID1 || dcctl == DINVALID2 + || scctl == SINVALID1 || scctl == SINVALID2) + return false; + else + return true; +} + +/* + * Submit a list of xfers after which the client wants notification. + * Client is not notified after each xfer unit, just once after all + * xfer units are done or some error occurs. + */ +int pl330_submit_req(void *ch_id, struct pl330_req *r) +{ + struct pl330_thread *thrd = ch_id; + struct pl330_dmac *pl330; + struct pl330_info *pi; + struct _xfer_spec xs; + unsigned long flags; + void __iomem *regs; + unsigned idx; + u32 ccr; + int ret = 0; + + /* No Req or Unacquired Channel or DMAC */ + if (!r || !thrd || thrd->free) + return -EINVAL; + + pl330 = thrd->dmac; + pi = pl330->pinfo; + regs = pi->base; + + if (pl330->state == DYING + || pl330->dmac_tbd.reset_chan & (1 << thrd->id)) { + dev_info(thrd->dmac->pinfo->dev, "%s:%d\n", + __func__, __LINE__); + return -EAGAIN; + } + + /* If request for non-existing peripheral */ + if (r->rqtype != MEMTOMEM && r->peri >= pi->pcfg.num_peri) { + dev_info(thrd->dmac->pinfo->dev, + "%s:%d Invalid peripheral(%u)!\n", + __func__, __LINE__, r->peri); + return -EINVAL; + } + + spin_lock_irqsave(&pl330->lock, flags); + + if (_queue_full(thrd)) { + ret = -EAGAIN; + goto xfer_exit; + } + + /* Prefer Secure Channel */ + if (!_manager_ns(thrd)) + r->cfg->nonsecure = 0; + else + r->cfg->nonsecure = 1; + + /* Use last settings, if not provided */ + if (r->cfg) + ccr = _prepare_ccr(r->cfg); + else + ccr = readl(regs + CC(thrd->id)); + + /* If this req doesn't have valid xfer settings */ + if (!_is_valid(ccr)) { + ret = -EINVAL; + dev_info(thrd->dmac->pinfo->dev, "%s:%d Invalid CCR(%x)!\n", + __func__, __LINE__, ccr); + goto xfer_exit; + } + + idx = IS_FREE(&thrd->req[0]) ? 0 : 1; + + xs.ccr = ccr; + xs.r = r; + + /* First dry run to check if req is acceptable */ + ret = _setup_req(1, thrd, idx, &xs); + if (ret < 0) + goto xfer_exit; + + if (ret > pi->mcbufsz / 2) { + dev_info(thrd->dmac->pinfo->dev, + "%s:%d Trying increasing mcbufsz\n", + __func__, __LINE__); + ret = -ENOMEM; + goto xfer_exit; + } + + /* Hook the request */ + thrd->lstenq = idx; + thrd->req[idx].mc_len = _setup_req(0, thrd, idx, &xs); + thrd->req[idx].r = r; + + ret = 0; + +xfer_exit: + spin_unlock_irqrestore(&pl330->lock, flags); + + return ret; +} +EXPORT_SYMBOL(pl330_submit_req); + +static void pl330_dotask(unsigned long data) +{ + struct pl330_dmac *pl330 = (struct pl330_dmac *) data; + struct pl330_info *pi = pl330->pinfo; + unsigned long flags; + int i; + + spin_lock_irqsave(&pl330->lock, flags); + + /* The DMAC itself gone nuts */ + if (pl330->dmac_tbd.reset_dmac) { + pl330->state = DYING; + /* Reset the manager too */ + pl330->dmac_tbd.reset_mngr = true; + /* Clear the reset flag */ + pl330->dmac_tbd.reset_dmac = false; + } + + if (pl330->dmac_tbd.reset_mngr) { + _stop(pl330->manager); + /* Reset all channels */ + pl330->dmac_tbd.reset_chan = (1 << pi->pcfg.num_chan) - 1; + /* Clear the reset flag */ + pl330->dmac_tbd.reset_mngr = false; + } + + for (i = 0; i < pi->pcfg.num_chan; i++) { + + if (pl330->dmac_tbd.reset_chan & (1 << i)) { + struct pl330_thread *thrd = &pl330->channels[i]; + void __iomem *regs = pi->base; + enum pl330_op_err err; + + _stop(thrd); + + if (readl(regs + FSC) & (1 << thrd->id)) + err = PL330_ERR_FAIL; + else + err = PL330_ERR_ABORT; + + spin_unlock_irqrestore(&pl330->lock, flags); + + _callback(thrd->req[1 - thrd->lstenq].r, err); + _callback(thrd->req[thrd->lstenq].r, err); + + spin_lock_irqsave(&pl330->lock, flags); + + thrd->req[0].r = NULL; + thrd->req[1].r = NULL; + MARK_FREE(&thrd->req[0]); + MARK_FREE(&thrd->req[1]); + + /* Clear the reset flag */ + pl330->dmac_tbd.reset_chan &= ~(1 << i); + } + } + + spin_unlock_irqrestore(&pl330->lock, flags); + + return; +} + +/* Returns 1 if state was updated, 0 otherwise */ +int pl330_update(const struct pl330_info *pi) +{ + struct _pl330_req *rqdone; + struct pl330_dmac *pl330; + unsigned long flags; + void __iomem *regs; + u32 val; + int id, ev, ret = 0; + + if (!pi || !pi->pl330_data) + return 0; + + regs = pi->base; + pl330 = pi->pl330_data; + + spin_lock_irqsave(&pl330->lock, flags); + + val = readl(regs + FSM) & 0x1; + if (val) + pl330->dmac_tbd.reset_mngr = true; + else + pl330->dmac_tbd.reset_mngr = false; + + val = readl(regs + FSC) & ((1 << pi->pcfg.num_chan) - 1); + pl330->dmac_tbd.reset_chan |= val; + if (val) { + int i = 0; + while (i < pi->pcfg.num_chan) { + if (val & (1 << i)) { + dev_info(pi->dev, + "Reset Channel-%d\t CS-%x FTC-%x\n", + i, readl(regs + CS(i)), + readl(regs + FTC(i))); + _stop(&pl330->channels[i]); + } + i++; + } + } + + /* Check which event happened i.e, thread notified */ + val = readl(regs + ES); + if (pi->pcfg.num_events < 32 + && val & ~((1 << pi->pcfg.num_events) - 1)) { + pl330->dmac_tbd.reset_dmac = true; + dev_err(pi->dev, "%s:%d Unexpected!\n", __func__, __LINE__); + ret = 1; + goto updt_exit; + } + + for (ev = 0; ev < pi->pcfg.num_events; ev++) { + if (val & (1 << ev)) { /* Event occured */ + struct pl330_thread *thrd; + u32 inten = readl(regs + INTEN); + int active; + + /* Clear the event */ + if (inten & (1 << ev)) + writel(1 << ev, regs + INTCLR); + + ret = 1; + + id = pl330->events[ev]; + + thrd = &pl330->channels[id]; + + active = _thrd_active(thrd); + if (!active) /* Aborted */ + continue; + + active -= 1; + + rqdone = &thrd->req[active]; + MARK_FREE(rqdone); + + /* Get going again ASAP */ + _start(thrd); + + /* For now, just make a list of callbacks to be done */ + list_add_tail(&rqdone->rqd, &pl330->req_done); + } + } + + /* Now that we are in no hurry, do the callbacks */ + while (!list_empty(&pl330->req_done)) { + rqdone = container_of(pl330->req_done.next, + struct _pl330_req, rqd); + + list_del_init(&rqdone->rqd); + + spin_unlock_irqrestore(&pl330->lock, flags); + _callback(rqdone->r, PL330_ERR_NONE); + spin_lock_irqsave(&pl330->lock, flags); + } + +updt_exit: + spin_unlock_irqrestore(&pl330->lock, flags); + + if (pl330->dmac_tbd.reset_dmac + || pl330->dmac_tbd.reset_mngr + || pl330->dmac_tbd.reset_chan) { + ret = 1; + tasklet_schedule(&pl330->tasks); + } + + return ret; +} +EXPORT_SYMBOL(pl330_update); + +int pl330_chan_ctrl(void *ch_id, enum pl330_chan_op op) +{ + struct pl330_thread *thrd = ch_id; + struct pl330_dmac *pl330; + unsigned long flags; + int ret = 0, active; + + if (!thrd || thrd->free || thrd->dmac->state == DYING) + return -EINVAL; + + pl330 = thrd->dmac; + + spin_lock_irqsave(&pl330->lock, flags); + + switch (op) { + case PL330_OP_FLUSH: + /* Make sure the channel is stopped */ + _stop(thrd); + + thrd->req[0].r = NULL; + thrd->req[1].r = NULL; + MARK_FREE(&thrd->req[0]); + MARK_FREE(&thrd->req[1]); + break; + + case PL330_OP_ABORT: + active = _thrd_active(thrd); + + /* Make sure the channel is stopped */ + _stop(thrd); + + /* ABORT is only for the active req */ + if (!active) + break; + + active--; + + thrd->req[active].r = NULL; + MARK_FREE(&thrd->req[active]); + + /* Start the next */ + case PL330_OP_START: + if (!_start(thrd)) + ret = -EIO; + break; + + default: + ret = -EINVAL; + } + + spin_unlock_irqrestore(&pl330->lock, flags); + return ret; +} +EXPORT_SYMBOL(pl330_chan_ctrl); + +int pl330_chan_status(void *ch_id, struct pl330_chanstatus *pstatus) +{ + struct pl330_thread *thrd = ch_id; + struct pl330_dmac *pl330; + struct pl330_info *pi; + void __iomem *regs; + int active; + u32 val; + + if (!pstatus || !thrd || thrd->free) + return -EINVAL; + + pl330 = thrd->dmac; + pi = pl330->pinfo; + regs = pi->base; + + /* The client should remove the DMAC and add again */ + if (pl330->state == DYING) + pstatus->dmac_halted = true; + else + pstatus->dmac_halted = false; + + val = readl(regs + FSC); + if (val & (1 << thrd->id)) + pstatus->faulting = true; + else + pstatus->faulting = false; + + active = _thrd_active(thrd); + + if (!active) { + /* Indicate that the thread is not running */ + pstatus->top_req = NULL; + pstatus->wait_req = NULL; + } else { + active--; + pstatus->top_req = thrd->req[active].r; + pstatus->wait_req = !IS_FREE(&thrd->req[1 - active]) + ? thrd->req[1 - active].r : NULL; + } + + pstatus->src_addr = readl(regs + SA(thrd->id)); + pstatus->dst_addr = readl(regs + DA(thrd->id)); + + return 0; +} +EXPORT_SYMBOL(pl330_chan_status); + +/* Reserve an event */ +static inline int _alloc_event(struct pl330_thread *thrd) +{ + struct pl330_dmac *pl330 = thrd->dmac; + struct pl330_info *pi = pl330->pinfo; + int ev; + + for (ev = 0; ev < pi->pcfg.num_events; ev++) + if (pl330->events[ev] == -1) { + pl330->events[ev] = thrd->id; + return ev; + } + + return -1; +} + +/* Upon success, returns IdentityToken for the + * allocated channel, NULL otherwise. + */ +void *pl330_request_channel(const struct pl330_info *pi) +{ + struct pl330_thread *thrd = NULL; + struct pl330_dmac *pl330; + unsigned long flags; + int chans, i; + + if (!pi || !pi->pl330_data) + return NULL; + + pl330 = pi->pl330_data; + + if (pl330->state == DYING) + return NULL; + + chans = pi->pcfg.num_chan; + + spin_lock_irqsave(&pl330->lock, flags); + + for (i = 0; i < chans; i++) { + thrd = &pl330->channels[i]; + if (thrd->free) { + thrd->ev = _alloc_event(thrd); + if (thrd->ev >= 0) { + thrd->free = false; + thrd->lstenq = 1; + thrd->req[0].r = NULL; + MARK_FREE(&thrd->req[0]); + thrd->req[1].r = NULL; + MARK_FREE(&thrd->req[1]); + break; + } + } + thrd = NULL; + } + + spin_unlock_irqrestore(&pl330->lock, flags); + + return thrd; +} +EXPORT_SYMBOL(pl330_request_channel); + +/* Release an event */ +static inline void _free_event(struct pl330_thread *thrd, int ev) +{ + struct pl330_dmac *pl330 = thrd->dmac; + struct pl330_info *pi = pl330->pinfo; + + /* If the event is valid and was held by the thread */ + if (ev >= 0 && ev < pi->pcfg.num_events + && pl330->events[ev] == thrd->id) + pl330->events[ev] = -1; +} + +void pl330_release_channel(void *ch_id) +{ + struct pl330_thread *thrd = ch_id; + struct pl330_dmac *pl330; + unsigned long flags; + + if (!thrd || thrd->free) + return; + + _stop(thrd); + + _callback(thrd->req[1 - thrd->lstenq].r, PL330_ERR_ABORT); + _callback(thrd->req[thrd->lstenq].r, PL330_ERR_ABORT); + + pl330 = thrd->dmac; + + spin_lock_irqsave(&pl330->lock, flags); + _free_event(thrd, thrd->ev); + thrd->free = true; + spin_unlock_irqrestore(&pl330->lock, flags); +} +EXPORT_SYMBOL(pl330_release_channel); + +/* Initialize the structure for PL330 configuration, that can be used + * by the client driver the make best use of the DMAC + */ +static void read_dmac_config(struct pl330_info *pi) +{ + void __iomem *regs = pi->base; + u32 val; + + val = readl(regs + CRD) >> CRD_DATA_WIDTH_SHIFT; + val &= CRD_DATA_WIDTH_MASK; + pi->pcfg.data_bus_width = 8 * (1 << val); + + val = readl(regs + CRD) >> CRD_DATA_BUFF_SHIFT; + val &= CRD_DATA_BUFF_MASK; + pi->pcfg.data_buf_dep = val + 1; + + val = readl(regs + CR0) >> CR0_NUM_CHANS_SHIFT; + val &= CR0_NUM_CHANS_MASK; + val += 1; + pi->pcfg.num_chan = val; + + val = readl(regs + CR0); + if (val & CR0_PERIPH_REQ_SET) { + val = (val >> CR0_NUM_PERIPH_SHIFT) & CR0_NUM_PERIPH_MASK; + val += 1; + pi->pcfg.num_peri = val; + pi->pcfg.peri_ns = readl(regs + CR4); + } else { + pi->pcfg.num_peri = 0; + } + + val = readl(regs + CR0); + if (val & CR0_BOOT_MAN_NS) + pi->pcfg.mode |= DMAC_MODE_NS; + else + pi->pcfg.mode &= ~DMAC_MODE_NS; + + val = readl(regs + CR0) >> CR0_NUM_EVENTS_SHIFT; + val &= CR0_NUM_EVENTS_MASK; + val += 1; + pi->pcfg.num_events = val; + + pi->pcfg.irq_ns = readl(regs + CR3); + + pi->pcfg.periph_id = get_id(pi, PERIPH_ID); + pi->pcfg.pcell_id = get_id(pi, PCELL_ID); +} + +static inline void _reset_thread(struct pl330_thread *thrd) +{ + struct pl330_dmac *pl330 = thrd->dmac; + struct pl330_info *pi = pl330->pinfo; + + thrd->req[0].mc_cpu = pl330->mcode_cpu + + (thrd->id * pi->mcbufsz); + thrd->req[0].mc_bus = pl330->mcode_bus + + (thrd->id * pi->mcbufsz); + thrd->req[0].r = NULL; + MARK_FREE(&thrd->req[0]); + + thrd->req[1].mc_cpu = thrd->req[0].mc_cpu + + pi->mcbufsz / 2; + thrd->req[1].mc_bus = thrd->req[0].mc_bus + + pi->mcbufsz / 2; + thrd->req[1].r = NULL; + MARK_FREE(&thrd->req[1]); +} + +static int dmac_alloc_threads(struct pl330_dmac *pl330) +{ + struct pl330_info *pi = pl330->pinfo; + int chans = pi->pcfg.num_chan; + struct pl330_thread *thrd; + int i; + + /* Allocate 1 Manager and 'chans' Channel threads */ + pl330->channels = kzalloc((1 + chans) * sizeof(*thrd), + GFP_KERNEL); + if (!pl330->channels) + return -ENOMEM; + + /* Init Channel threads */ + for (i = 0; i < chans; i++) { + thrd = &pl330->channels[i]; + thrd->id = i; + thrd->dmac = pl330; + _reset_thread(thrd); + thrd->free = true; + } + + /* MANAGER is indexed at the end */ + thrd = &pl330->channels[chans]; + thrd->id = chans; + thrd->dmac = pl330; + thrd->free = false; + pl330->manager = thrd; + + return 0; +} + +static int dmac_alloc_resources(struct pl330_dmac *pl330) +{ + struct pl330_info *pi = pl330->pinfo; + int chans = pi->pcfg.num_chan; + int ret; + + /* + * Alloc MicroCode buffer for 'chans' Channel threads. + * A channel's buffer offset is (Channel_Id * MCODE_BUFF_PERCHAN) + */ + pl330->mcode_cpu = dma_alloc_coherent(pi->dev, + chans * pi->mcbufsz, + &pl330->mcode_bus, GFP_KERNEL); + if (!pl330->mcode_cpu) { + dev_err(pi->dev, "%s:%d Can't allocate memory!\n", + __func__, __LINE__); + return -ENOMEM; + } + + ret = dmac_alloc_threads(pl330); + if (ret) { + dev_err(pi->dev, "%s:%d Can't to create channels for DMAC!\n", + __func__, __LINE__); + dma_free_coherent(pi->dev, + chans * pi->mcbufsz, + pl330->mcode_cpu, pl330->mcode_bus); + return ret; + } + + return 0; +} + +int pl330_add(struct pl330_info *pi) +{ + struct pl330_dmac *pl330; + void __iomem *regs; + int i, ret; + + if (!pi || !pi->dev) + return -EINVAL; + + /* If already added */ + if (pi->pl330_data) + return -EINVAL; + + /* + * If the SoC can perform reset on the DMAC, then do it + * before reading its configuration. + */ + if (pi->dmac_reset) + pi->dmac_reset(pi); + + regs = pi->base; + + /* Check if we can handle this DMAC */ + if (get_id(pi, PERIPH_ID) != PERIPH_ID_VAL + || get_id(pi, PCELL_ID) != PCELL_ID_VAL) { + dev_err(pi->dev, "PERIPH_ID 0x%x, PCELL_ID 0x%x !\n", + readl(regs + PERIPH_ID), readl(regs + PCELL_ID)); + return -EINVAL; + } + + /* Read the configuration of the DMAC */ + read_dmac_config(pi); + + if (pi->pcfg.num_events == 0) { + dev_err(pi->dev, "%s:%d Can't work without events!\n", + __func__, __LINE__); + return -EINVAL; + } + + pl330 = kzalloc(sizeof(*pl330), GFP_KERNEL); + if (!pl330) { + dev_err(pi->dev, "%s:%d Can't allocate memory!\n", + __func__, __LINE__); + return -ENOMEM; + } + + /* Assign the info structure and private data */ + pl330->pinfo = pi; + pi->pl330_data = pl330; + + spin_lock_init(&pl330->lock); + + INIT_LIST_HEAD(&pl330->req_done); + + /* Use default MC buffer size if not provided */ + if (!pi->mcbufsz) + pi->mcbufsz = MCODE_BUFF_PER_REQ * 2; + + /* Mark all events as free */ + for (i = 0; i < pi->pcfg.num_events; i++) + pl330->events[i] = -1; + + /* Allocate resources needed by the DMAC */ + ret = dmac_alloc_resources(pl330); + if (ret) { + dev_err(pi->dev, "Unable to create channels for DMAC\n"); + kfree(pl330); + return ret; + } + + tasklet_init(&pl330->tasks, pl330_dotask, (unsigned long) pl330); + + pl330->state = INIT; + + return 0; +} +EXPORT_SYMBOL(pl330_add); + +static int dmac_free_threads(struct pl330_dmac *pl330) +{ + struct pl330_info *pi = pl330->pinfo; + int chans = pi->pcfg.num_chan; + struct pl330_thread *thrd; + int i; + + /* Release Channel threads */ + for (i = 0; i < chans; i++) { + thrd = &pl330->channels[i]; + pl330_release_channel((void *)thrd); + } + + /* Free memory */ + kfree(pl330->channels); + + return 0; +} + +static void dmac_free_resources(struct pl330_dmac *pl330) +{ + struct pl330_info *pi = pl330->pinfo; + int chans = pi->pcfg.num_chan; + + dmac_free_threads(pl330); + + dma_free_coherent(pi->dev, chans * pi->mcbufsz, + pl330->mcode_cpu, pl330->mcode_bus); +} + +void pl330_del(struct pl330_info *pi) +{ + struct pl330_dmac *pl330; + + if (!pi || !pi->pl330_data) + return; + + pl330 = pi->pl330_data; + + pl330->state = UNINIT; + + tasklet_kill(&pl330->tasks); + + /* Free DMAC resources */ + dmac_free_resources(pl330); + + kfree(pl330); + pi->pl330_data = NULL; +} +EXPORT_SYMBOL(pl330_del); diff --git a/arch/arm/include/asm/hardware/pl330.h b/arch/arm/include/asm/hardware/pl330.h new file mode 100644 index 0000000..575fa81 --- /dev/null +++ b/arch/arm/include/asm/hardware/pl330.h @@ -0,0 +1,217 @@ +/* linux/include/asm/hardware/pl330.h + * + * Copyright (C) 2010 Samsung Electronics Co. Ltd. + * Jaswinder Singh + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __PL330_CORE_H +#define __PL330_CORE_H + +#define PL330_MAX_CHAN 8 +#define PL330_MAX_IRQS 32 +#define PL330_MAX_PERI 32 + +enum pl330_srccachectrl { + SCCTRL0 = 0, /* Noncacheable and nonbufferable */ + SCCTRL1, /* Bufferable only */ + SCCTRL2, /* Cacheable, but do not allocate */ + SCCTRL3, /* Cacheable and bufferable, but do not allocate */ + SINVALID1, + SINVALID2, + SCCTRL6, /* Cacheable write-through, allocate on reads only */ + SCCTRL7, /* Cacheable write-back, allocate on reads only */ +}; + +enum pl330_dstcachectrl { + DCCTRL0 = 0, /* Noncacheable and nonbufferable */ + DCCTRL1, /* Bufferable only */ + DCCTRL2, /* Cacheable, but do not allocate */ + DCCTRL3, /* Cacheable and bufferable, but do not allocate */ + DINVALID1 = 8, + DINVALID2, + DCCTRL6, /* Cacheable write-through, allocate on writes only */ + DCCTRL7, /* Cacheable write-back, allocate on writes only */ +}; + +/* Populated by the PL330 core driver for DMA API driver's info */ +struct pl330_config { + u32 periph_id; + u32 pcell_id; +#define DMAC_MODE_NS (1 << 0) + unsigned int mode; + unsigned int data_bus_width:10; /* In number of bits */ + unsigned int data_buf_dep:10; + unsigned int num_chan:4; + unsigned int num_peri:6; + u32 peri_ns; + unsigned int num_events:6; + u32 irq_ns; +}; + +/* Handle to the DMAC provided to the PL330 core */ +struct pl330_info { + /* Owning device */ + struct device *dev; + /* Size of MicroCode buffers for each channel. */ + unsigned mcbufsz; + /* ioremap'ed address of PL330 registers. */ + void __iomem *base; + /* Client can freely use it. */ + void *client_data; + /* PL330 core data, Client must not touch it. */ + void *pl330_data; + /* Populated by the PL330 core driver during pl330_add */ + struct pl330_config pcfg; + /* + * If the DMAC has some reset mechanism, then the + * client may want to provide pointer to the method. + */ + void (*dmac_reset)(struct pl330_info *pi); +}; + +enum pl330_byteswap { + SWAP_NO = 0, + SWAP_2, + SWAP_4, + SWAP_8, + SWAP_16, +}; + +/** + * Request Configuration. + * The PL330 core does not modify this and uses the last + * working configuration if the request doesn't provide any. + * + * The Client may want to provide this info only for the + * first request and a request with new settings. + */ +struct pl330_reqcfg { + /* Address Incrementing */ + unsigned dst_inc:1; + unsigned src_inc:1; + + /* + * For now, the SRC & DST protection levels + * and burst size/length are assumed same. + */ + bool nonsecure; + bool privileged; + bool insnaccess; + unsigned brst_len:5; + unsigned brst_size:3; /* in power of 2 */ + + enum pl330_dstcachectrl dcctl; + enum pl330_srccachectrl scctl; + enum pl330_byteswap swap; +}; + +/* + * One cycle of DMAC operation. + * There may be more than one xfer in a request. + */ +struct pl330_xfer { + u32 src_addr; + u32 dst_addr; + /* Size to xfer */ + u32 bytes; + /* + * Pointer to next xfer in the list. + * The last xfer in the req must point to NULL. + */ + struct pl330_xfer *next; +}; + +/* The xfer callbacks are made with one of these arguments. */ +enum pl330_op_err { + /* The all xfers in the request were success. */ + PL330_ERR_NONE, + /* If req aborted due to global error. */ + PL330_ERR_ABORT, + /* If req failed due to problem with Channel. */ + PL330_ERR_FAIL, +}; + +enum pl330_reqtype { + MEMTOMEM, + MEMTODEV, + DEVTOMEM, + DEVTODEV, +}; + +/* A request defining Scatter-Gather List ending with NULL xfer. */ +struct pl330_req { + enum pl330_reqtype rqtype; + /* Index of peripheral for the xfer. */ + unsigned peri:5; + /* Unique token for this xfer, set by the client. */ + void *token; + /* Callback to be called after xfer. */ + void (*xfer_cb)(void *token, enum pl330_op_err err); + /* If NULL, req will be done at last set parameters. */ + struct pl330_reqcfg *cfg; + /* Pointer to first xfer in the request. */ + struct pl330_xfer *x; +}; + +/* + * To know the status of the channel and DMAC, the client + * provides a pointer to this structure. The PL330 core + * fills it with current information. + */ +struct pl330_chanstatus { + /* + * If the DMAC engine halted due to some error, + * the client should remove-add DMAC. + */ + bool dmac_halted; + /* + * If channel is halted due to some error, + * the client should ABORT/FLUSH and START the channel. + */ + bool faulting; + /* Location of last load */ + u32 src_addr; + /* Location of last store */ + u32 dst_addr; + /* + * Pointer to the currently active req, NULL if channel is + * inactive, even though the requests may be present. + */ + struct pl330_req *top_req; + /* Pointer to req waiting second in the queue if any. */ + struct pl330_req *wait_req; +}; + +enum pl330_chan_op { + /* Start the channel */ + PL330_OP_START, + /* Abort the active xfer */ + PL330_OP_ABORT, + /* Stop xfer and flush queue */ + PL330_OP_FLUSH, +}; + +extern int pl330_add(struct pl330_info *); +extern void pl330_del(struct pl330_info *pi); +extern int pl330_update(const struct pl330_info *pi); +extern void pl330_release_channel(void *ch_id); +extern void *pl330_request_channel(const struct pl330_info *pi); +extern int pl330_chan_status(void *ch_id, struct pl330_chanstatus *pstatus); +extern int pl330_chan_ctrl(void *ch_id, enum pl330_chan_op op); +extern int pl330_submit_req(void *ch_id, struct pl330_req *r); + +#endif /* __PL330_CORE_H */ -- cgit v0.10.2 From 8e2a43f5f5e1255879064924917fb1a6e5be7cb3 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 May 2010 10:18:05 +0100 Subject: ARM: rename mach_cpu_disable() to platform_cpu_disable() Consistently name all SMP platform related functions. Signed-off-by: Russell King diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h index e0d763b..3d05190 100644 --- a/arch/arm/include/asm/smp.h +++ b/arch/arm/include/asm/smp.h @@ -82,7 +82,7 @@ struct secondary_data { extern struct secondary_data secondary_data; extern int __cpu_disable(void); -extern int mach_cpu_disable(unsigned int cpu); +extern int platform_cpu_disable(unsigned int cpu); extern void __cpu_die(unsigned int cpu); extern void cpu_die(void); diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 577543f..7a3cc02 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -162,7 +162,7 @@ int __cpu_disable(void) struct task_struct *p; int ret; - ret = mach_cpu_disable(cpu); + ret = platform_cpu_disable(cpu); if (ret) return ret; diff --git a/arch/arm/mach-realview/hotplug.c b/arch/arm/mach-realview/hotplug.c index be048e3..f95521a 100644 --- a/arch/arm/mach-realview/hotplug.c +++ b/arch/arm/mach-realview/hotplug.c @@ -131,7 +131,7 @@ void platform_cpu_die(unsigned int cpu) cpu_leave_lowpower(); } -int mach_cpu_disable(unsigned int cpu) +int platform_cpu_disable(unsigned int cpu) { /* * we don't allow CPU 0 to be shutdown (it is still too special -- cgit v0.10.2 From 49aea0fd95495538230e19f58e217fb06ffdbfeb Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 May 2010 10:40:21 +0100 Subject: ARM: nwfpe: allow debugging output to be configured at runtime Enabling CONFIG_USER_DEBUG allows NWFPE to complain about every FP exception, which with some programs can cause the kernel message log to fill with NWFPE debug, swamping out other messages. This change allows NWFPE debugging to be configured at run time. Signed-off-by: Russell King diff --git a/arch/arm/nwfpe/fpmodule.c b/arch/arm/nwfpe/fpmodule.c index 4c0ab50..cb7658e 100644 --- a/arch/arm/nwfpe/fpmodule.c +++ b/arch/arm/nwfpe/fpmodule.c @@ -24,6 +24,7 @@ #include "fpa11.h" #include +#include /* XXX */ #include @@ -134,13 +135,17 @@ a SIGFPE exception if necessary. If not the relevant bits in the cumulative exceptions flag byte are set and we return. */ +#ifdef CONFIG_DEBUG_USER +/* By default, ignore inexact errors as there are far too many of them to log */ +static int debug = ~BIT_IXC; +#endif + void float_raise(signed char flags) { register unsigned int fpsr, cumulativeTraps; #ifdef CONFIG_DEBUG_USER - /* Ignore inexact errors as there are far too many of them to log */ - if (flags & ~BIT_IXC) + if (flags & debug) printk(KERN_DEBUG "NWFPE: %s[%d] takes exception %08x at %p from %08lx\n", current->comm, current->pid, flags, @@ -179,3 +184,7 @@ module_exit(fpe_exit); MODULE_AUTHOR("Scott Bambrough "); MODULE_DESCRIPTION("NWFPE floating point emulator (" NWFPE_BITS " precision)"); MODULE_LICENSE("GPL"); + +#ifdef CONFIG_DEBUG_USER +module_param(debug, int, 0644); +#endif -- cgit v0.10.2 From 8c0b742ca7a7d21de0ddc87eda6ef0b282e4de18 Mon Sep 17 00:00:00 2001 From: "Kirill A. Shutemov" Date: Sat, 15 May 2010 09:57:06 +0100 Subject: ARM: 6134/1: Handle instruction cache maintenance fault properly Between "clean D line..." and "invalidate I line" operations in v7_coherent_user_range(), the memory page may get swapped out. And the fault on "invalidate I line" could not be properly handled causing the oops. In ARMv6 "external abort on linefetch" replaced by "instruction cache maintenance fault". Let's handle it as translation fault. It fixes the issue. I'm not sure if it's reasonable to check arch version in run-time. Let's do it in compile time for now. Reviewed-by: Catalin Marinas Signed-off-by: Siarhei Siamashka Signed-off-by: Kirill A. Shutemov Signed-off-by: Russell King diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index 9d40c34..92f5801 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c @@ -463,7 +463,12 @@ static struct fsr_info { { do_bad, SIGILL, BUS_ADRALN, "alignment exception" }, { do_bad, SIGKILL, 0, "terminal exception" }, { do_bad, SIGILL, BUS_ADRALN, "alignment exception" }, +/* Do we need runtime check ? */ +#if __LINUX_ARM_ARCH__ < 6 { do_bad, SIGBUS, 0, "external abort on linefetch" }, +#else + { do_translation_fault, SIGSEGV, SEGV_MAPERR, "I-cache maintenance fault" }, +#endif { do_translation_fault, SIGSEGV, SEGV_MAPERR, "section translation fault" }, { do_bad, SIGBUS, 0, "external abort on linefetch" }, { do_page_fault, SIGSEGV, SEGV_MAPERR, "page translation fault" }, -- cgit v0.10.2 From 5dc6416414fb3ec6e2825fd4d20c8bf1d7fe0395 Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Sat, 15 May 2010 11:27:37 -0400 Subject: Btrfs: check for read permission on src file in the clone ioctl The existing code would have allowed you to clone a file that was only open for writing Signed-off-by: Chris Mason diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 2b7dd88..9de6c3a 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -1480,12 +1480,17 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, ret = -EBADF; goto out_drop_write; } + src = src_file->f_dentry->d_inode; ret = -EINVAL; if (src == inode) goto out_fput; + /* the src must be open for reading */ + if (!(src_file->f_mode & FMODE_READ)) + goto out_fput; + ret = -EISDIR; if (S_ISDIR(src->i_mode) || S_ISDIR(inode->i_mode)) goto out_fput; -- cgit v0.10.2 From bdef2fe88b1e4bde7458aedd207929ce3f9d66ee Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Sat, 15 May 2010 12:32:31 -0400 Subject: mmc: at91_mci: modify cache flush routines As we were using an internal dma flushing routine, this patch changes to the DMA API flush_kernel_dcache_page(). Driver is able to compile now. [akpm@linux-foundation.org: flush_kernel_dcache_page() comes before kunmap_atomic()] Signed-off-by: Nicolas Ferre Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c index a6dd7da..336d9f5 100644 --- a/drivers/mmc/host/at91_mci.c +++ b/drivers/mmc/host/at91_mci.c @@ -314,8 +314,8 @@ static void at91_mci_post_dma_read(struct at91mci_host *host) dmabuf = (unsigned *)tmpv; } + flush_kernel_dcache_page(sg_page(sg)); kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ); - dmac_flush_range((void *)sgbuffer, ((void *)sgbuffer) + amount); data->bytes_xfered += amount; if (size == 0) break; -- cgit v0.10.2 From 43aa7ac736a4e21aae4882bd8f7c67403aed45b8 Mon Sep 17 00:00:00 2001 From: "kirjanov@gmail.com" Date: Sat, 15 May 2010 12:32:34 -0400 Subject: lib/btree: fix possible NULL pointer dereference mempool_alloc() can return null in atomic case. Signed-off-by: Denis Kirjanov Cc: Joern Engel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds diff --git a/lib/btree.c b/lib/btree.c index 41859a8..c9c6f03 100644 --- a/lib/btree.c +++ b/lib/btree.c @@ -95,7 +95,8 @@ static unsigned long *btree_node_alloc(struct btree_head *head, gfp_t gfp) unsigned long *node; node = mempool_alloc(head->mempool, gfp); - memset(node, 0, NODESIZE); + if (likely(node)) + memset(node, 0, NODESIZE); return node; } -- cgit v0.10.2 From 95e8f634d7a3ea5af40ec3fa42c8a152fd3a0624 Mon Sep 17 00:00:00 2001 From: Shane McDonald Date: Thu, 6 May 2010 23:26:57 -0600 Subject: MIPS FPU emulator: allow Cause bits of FCSR to be writeable by ctc1 In the FPU emulator code of the MIPS, the Cause bits of the FCSR register are not currently writeable by the ctc1 instruction. In odd corner cases, this can cause problems. For example, a case existed where a divide-by-zero exception was generated by the FPU, and the signal handler attempted to restore the FPU registers to their state before the exception occurred. In this particular setup, writing the old value to the FCSR register would cause another divide-by-zero exception to occur immediately. The solution is to change the ctc1 instruction emulator code to allow the Cause bits of the FCSR register to be writeable. This is the behaviour of the hardware that the code is emulating. This problem was found by Shane McDonald, but the credit for the fix goes to Kevin Kissell. In Kevin's words: I submit that the bug is indeed in that ctc_op: case of the emulator. The Cause bits (17:12) are supposed to be writable by that instruction, but the CTC1 emulation won't let them be updated by the instruction. I think that actually if you just completely removed lines 387-388 [...] things would work a good deal better. At least, it would be a more accurate emulation of the architecturally defined FPU. If I wanted to be really, really pedantic (which I sometimes do), I'd also protect the reserved bits that aren't necessarily writable. Signed-off-by: Shane McDonald To: anemo@mba.ocn.ne.jp To: kevink@paralogos.com To: sshtylyov@mvista.com Patchwork: http://patchwork.linux-mips.org/patch/1205/ Signed-off-by: Ralf Baechle --- diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 49382d5..c6e3c93 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -135,6 +135,12 @@ #define FPU_CSR_COND7 0x80000000 /* $fcc7 */ /* + * Bits 18 - 20 of the FPU Status Register will be read as 0, + * and should be written as zero. + */ +#define FPU_CSR_RSVD 0x001c0000 + +/* * X the exception cause indicator * E the exception enable * S the sticky/flag bit @@ -161,7 +167,8 @@ #define FPU_CSR_UDF_S 0x00000008 #define FPU_CSR_INE_S 0x00000004 -/* rounding mode */ +/* Bits 0 and 1 of FPU Status Register specify the rounding mode */ +#define FPU_CSR_RM 0x00000003 #define FPU_CSR_RN 0x0 /* nearest */ #define FPU_CSR_RZ 0x1 /* towards zero */ #define FPU_CSR_RU 0x2 /* towards +Infinity */ diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index 8f2f8e9..f2338d1 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -78,6 +78,9 @@ DEFINE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats); #define FPCREG_RID 0 /* $0 = revision id */ #define FPCREG_CSR 31 /* $31 = csr */ +/* Determine rounding mode from the RM bits of the FCSR */ +#define modeindex(v) ((v) & FPU_CSR_RM) + /* Convert Mips rounding mode (0..3) to IEEE library modes. */ static const unsigned char ieee_rm[4] = { [FPU_CSR_RN] = IEEE754_RN, @@ -384,10 +387,14 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx) (void *) (xcp->cp0_epc), MIPSInst_RT(ir), value); #endif - value &= (FPU_CSR_FLUSH | FPU_CSR_ALL_E | FPU_CSR_ALL_S | 0x03); - ctx->fcr31 &= ~(FPU_CSR_FLUSH | FPU_CSR_ALL_E | FPU_CSR_ALL_S | 0x03); - /* convert to ieee library modes */ - ctx->fcr31 |= (value & ~0x3) | ieee_rm[value & 0x3]; + + /* + * Don't write reserved bits, + * and convert to ieee library modes + */ + ctx->fcr31 = (value & + ~(FPU_CSR_RSVD | FPU_CSR_RM)) | + ieee_rm[modeindex(value)]; } if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) { return SIGFPE; -- cgit v0.10.2 From 46afb8296c2494bfce17064124b253eb9b176ef9 Mon Sep 17 00:00:00 2001 From: Chandrakala Chavva Date: Mon, 10 May 2010 17:11:54 -0700 Subject: MIPS: N32: Use compat version for sys_ppoll. The sys_ppoll() takes struct 'struct timespec'. This is different for the N32 and N64 ABIs. Use the compat version to do the proper conversions. Signed-off-by: David Daney To: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/1210/ Signed-off-by: Ralf Baechle --- diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index 44337ba..a5297e2 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -385,7 +385,7 @@ EXPORT(sysn32_call_table) PTR sys_fchmodat PTR sys_faccessat PTR compat_sys_pselect6 - PTR sys_ppoll /* 6265 */ + PTR compat_sys_ppoll /* 6265 */ PTR sys_unshare PTR sys_splice PTR sys_sync_file_range -- cgit v0.10.2 From 4e73238d163c6fcf001264832701d2a6d4927672 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Fri, 7 May 2010 00:59:46 +0800 Subject: MIPS: Oprofile: Fix Loongson irq handler The interrupt enable bit for the performance counters is in the Control Register $24, not in the counter register. loongson2_perfcount_handler(), we need to use Reported-by: Xu Hengyang Signed-off-by: Wu Zhangjin Cc: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/1198/ Signed-off-by: Ralf Baechle --- diff --git a/arch/mips/oprofile/op_model_loongson2.c b/arch/mips/oprofile/op_model_loongson2.c index 29e2326..fa3bf66 100644 --- a/arch/mips/oprofile/op_model_loongson2.c +++ b/arch/mips/oprofile/op_model_loongson2.c @@ -122,7 +122,7 @@ static irqreturn_t loongson2_perfcount_handler(int irq, void *dev_id) */ /* Check whether the irq belongs to me */ - enabled = read_c0_perfcnt() & LOONGSON2_PERFCNT_INT_EN; + enabled = read_c0_perfctrl() & LOONGSON2_PERFCNT_INT_EN; if (!enabled) return IRQ_NONE; enabled = reg.cnt1_enabled | reg.cnt2_enabled; -- cgit v0.10.2 From 605539034f208d365f76af8e2152cb25f702367d Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 15 May 2010 20:40:34 -0300 Subject: perf newt: Make <- exit the ui_browser MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Right now that means that pressing the left arrow willl make the symbol annotation window to exit back to the main symbol histogram browser. This is another improvement on the UI fastpath, i.e. just the arrows and enter are enough for most browsing. Suggested-by: Ingo Molnar Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index e74df12..5ded2f0 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -323,6 +323,7 @@ static int ui_browser__run(struct ui_browser *self, const char *title, newtFormAddHotKey(self->form, NEWT_KEY_PGDN); newtFormAddHotKey(self->form, NEWT_KEY_HOME); newtFormAddHotKey(self->form, NEWT_KEY_END); + newtFormAddHotKey(self->form, NEWT_KEY_LEFT); if (ui_browser__refresh_entries(self) < 0) return -1; @@ -408,6 +409,7 @@ static int ui_browser__run(struct ui_browser *self, const char *title, } break; case NEWT_KEY_ESCAPE: + case NEWT_KEY_LEFT: case CTRL('c'): case 'Q': case 'q': @@ -616,7 +618,7 @@ static void hist_entry__annotate_browser(struct hist_entry *self) if (hist_entry__annotate(self, &head) < 0) return; - ui_helpline__push("Press ESC to exit"); + ui_helpline__push("Press <- or ESC to exit"); memset(&browser, 0, sizeof(browser)); browser.entries = &head; -- cgit v0.10.2 From c1ec5fefd9cd9ccb020966a49a3c7f44b25d9e84 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 15 May 2010 20:45:31 -0300 Subject: perf newt: Fix the 'A'/'a' shortcut for annotate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reported-by: Ingo Molnar Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index 5ded2f0..094887f 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -892,10 +892,10 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na if (choice == -1) continue; -do_annotate: + if (choice == annotate) { struct hist_entry *he; - +do_annotate: if (browser->selection->map->dso->origin == DSO__ORIG_KERNEL) { ui_helpline__puts("No vmlinux file found, can't " "annotate with just a " -- cgit v0.10.2 From 29351db6a05e7e42be457569428425520a18beec Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 15 May 2010 21:06:58 -0300 Subject: perf newt: Exit browser unconditionally when CTRL+C, q or Q is pressed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ESC still asks for confirmation. Suggested-by: Ingo Molnar Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index 094887f..139eb1a 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -837,9 +837,10 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na if (es.reason == NEWT_EXIT_HOTKEY) { if (toupper(es.u.key) == 'A') goto do_annotate; - if (es.u.key == NEWT_KEY_ESCAPE || - toupper(es.u.key) == 'Q' || - es.u.key == CTRL('c')) { + if (toupper(es.u.key) == 'Q' || + es.u.key == CTRL('c')) + break; + if (es.u.key == NEWT_KEY_ESCAPE) { if (dialog_yesno("Do you really want to exit?")) break; else -- cgit v0.10.2 From 9d192e118a094087494997ea1c8a2faf39af38c5 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sat, 15 May 2010 21:15:01 -0300 Subject: perf newt: Add single key shortcuts for zoom into DSO and threads MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 'D'/'d' for zooming into the DSO in the current highlighted hist entry, 'T'/'t' for zooming into the current thread. Suggested-by: Ingo Molnar Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index 139eb1a..6974431 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -752,6 +752,10 @@ static int hist_browser__populate(struct hist_browser *self, struct hists *hists newtFormAddHotKey(self->form, 'A'); newtFormAddHotKey(self->form, 'a'); + newtFormAddHotKey(self->form, 'D'); + newtFormAddHotKey(self->form, 'd'); + newtFormAddHotKey(self->form, 'T'); + newtFormAddHotKey(self->form, 't'); newtFormAddHotKey(self->form, NEWT_KEY_RIGHT); newtFormAddHotKey(self->form, NEWT_KEY_LEFT); newtFormAddComponents(self->form, self->tree, NULL); @@ -834,9 +838,20 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na annotate = -2, zoom_dso = -2, zoom_thread = -2; newtFormRun(browser->form, &es); + + thread = hist_browser__selected_thread(browser); + dso = browser->selection->map ? browser->selection->map->dso : NULL; + if (es.reason == NEWT_EXIT_HOTKEY) { - if (toupper(es.u.key) == 'A') + switch (toupper(es.u.key)) { + case 'A': goto do_annotate; + case 'D': + goto zoom_dso; + case 'T': + goto zoom_thread; + default:; + } if (toupper(es.u.key) == 'Q' || es.u.key == CTRL('c')) break; @@ -866,7 +881,6 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na browser->selection->sym->name) > 0) annotate = nr_options++; - thread = hist_browser__selected_thread(browser); if (thread != NULL && asprintf(&options[nr_options], "Zoom %s %s(%d) thread", (thread_filter ? "out of" : "into"), @@ -874,7 +888,6 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na thread->pid) > 0) zoom_thread = nr_options++; - dso = browser->selection->map ? browser->selection->map->dso : NULL; if (dso != NULL && asprintf(&options[nr_options], "Zoom %s %s DSO", (dso_filter ? "out of" : "into"), @@ -910,12 +923,15 @@ do_annotate: hist_entry__annotate_browser(he); } else if (choice == zoom_dso) { +zoom_dso: if (dso_filter) { pstack__remove(fstack, &dso_filter); zoom_out_dso: ui_helpline__pop(); dso_filter = NULL; } else { + if (dso == NULL) + continue; ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s DSO\"", dso->kernel ? "the Kernel" : dso->short_name); dso_filter = dso; @@ -927,6 +943,7 @@ zoom_out_dso: if (hist_browser__populate(browser, self, msg) < 0) goto out; } else if (choice == zoom_thread) { +zoom_thread: if (thread_filter) { pstack__remove(fstack, &thread_filter); zoom_out_thread: -- cgit v0.10.2 From 35790c0421121364883a167bab8a2e37e1f67f78 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 16 May 2010 00:34:04 -0700 Subject: tcp: fix MD5 (RFC2385) support TCP MD5 support uses percpu data for temporary storage. It currently disables preemption so that same storage cannot be reclaimed by another thread on same cpu. We also have to make sure a softirq handler wont try to use also same context. Various bug reports demonstrated corruptions. Fix is to disable preemption and BH. Reported-by: Bhaskar Dutta Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller diff --git a/include/net/tcp.h b/include/net/tcp.h index 75be5a2..aa04b9a 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1197,30 +1197,15 @@ extern int tcp_v4_md5_do_del(struct sock *sk, extern struct tcp_md5sig_pool * __percpu *tcp_alloc_md5sig_pool(struct sock *); extern void tcp_free_md5sig_pool(void); -extern struct tcp_md5sig_pool *__tcp_get_md5sig_pool(int cpu); -extern void __tcp_put_md5sig_pool(void); +extern struct tcp_md5sig_pool *tcp_get_md5sig_pool(void); +extern void tcp_put_md5sig_pool(void); + extern int tcp_md5_hash_header(struct tcp_md5sig_pool *, struct tcphdr *); extern int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *, struct sk_buff *, unsigned header_len); extern int tcp_md5_hash_key(struct tcp_md5sig_pool *hp, struct tcp_md5sig_key *key); -static inline -struct tcp_md5sig_pool *tcp_get_md5sig_pool(void) -{ - int cpu = get_cpu(); - struct tcp_md5sig_pool *ret = __tcp_get_md5sig_pool(cpu); - if (!ret) - put_cpu(); - return ret; -} - -static inline void tcp_put_md5sig_pool(void) -{ - __tcp_put_md5sig_pool(); - put_cpu(); -} - /* write queue abstraction */ static inline void tcp_write_queue_purge(struct sock *sk) { diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 0f8caf6..296150b 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2839,7 +2839,6 @@ static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool * __percpu *pool) if (p->md5_desc.tfm) crypto_free_hash(p->md5_desc.tfm); kfree(p); - p = NULL; } } free_percpu(pool); @@ -2937,25 +2936,40 @@ retry: EXPORT_SYMBOL(tcp_alloc_md5sig_pool); -struct tcp_md5sig_pool *__tcp_get_md5sig_pool(int cpu) + +/** + * tcp_get_md5sig_pool - get md5sig_pool for this user + * + * We use percpu structure, so if we succeed, we exit with preemption + * and BH disabled, to make sure another thread or softirq handling + * wont try to get same context. + */ +struct tcp_md5sig_pool *tcp_get_md5sig_pool(void) { struct tcp_md5sig_pool * __percpu *p; - spin_lock_bh(&tcp_md5sig_pool_lock); + + local_bh_disable(); + + spin_lock(&tcp_md5sig_pool_lock); p = tcp_md5sig_pool; if (p) tcp_md5sig_users++; - spin_unlock_bh(&tcp_md5sig_pool_lock); - return (p ? *per_cpu_ptr(p, cpu) : NULL); -} + spin_unlock(&tcp_md5sig_pool_lock); + + if (p) + return *per_cpu_ptr(p, smp_processor_id()); -EXPORT_SYMBOL(__tcp_get_md5sig_pool); + local_bh_enable(); + return NULL; +} +EXPORT_SYMBOL(tcp_get_md5sig_pool); -void __tcp_put_md5sig_pool(void) +void tcp_put_md5sig_pool(void) { + local_bh_enable(); tcp_free_md5sig_pool(); } - -EXPORT_SYMBOL(__tcp_put_md5sig_pool); +EXPORT_SYMBOL(tcp_put_md5sig_pool); int tcp_md5_hash_header(struct tcp_md5sig_pool *hp, struct tcphdr *th) -- cgit v0.10.2 From 55fa0cfd7c3ac2ae34cac7dca2e3fbcfe661e6c3 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sun, 9 May 2010 16:56:07 +0000 Subject: sctp: delete active ICMP proto unreachable timer when free transport transport may be free before ICMP proto unreachable timer expire, so we should delete active ICMP proto unreachable timer when transport is going away. Signed-off-by: Wei Yongjun Acked-by: Vlad Yasevich Signed-off-by: David S. Miller diff --git a/net/sctp/transport.c b/net/sctp/transport.c index 4a36803..165d54e 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c @@ -173,6 +173,10 @@ void sctp_transport_free(struct sctp_transport *transport) del_timer(&transport->T3_rtx_timer)) sctp_transport_put(transport); + /* Delete the ICMP proto unreachable timer if it's active. */ + if (timer_pending(&transport->proto_unreach_timer) && + del_timer(&transport->proto_unreach_timer)) + sctp_association_put(transport->asoc); sctp_transport_put(transport); } -- cgit v0.10.2 From c02db8c6290bb992442fec1407643c94cc414375 Mon Sep 17 00:00:00 2001 From: Chris Wright Date: Sun, 16 May 2010 01:05:45 -0700 Subject: rtnetlink: make SR-IOV VF interface symmetric Now we have a set of nested attributes: IFLA_VFINFO_LIST (NESTED) IFLA_VF_INFO (NESTED) IFLA_VF_MAC IFLA_VF_VLAN IFLA_VF_TX_RATE This allows a single set to operate on multiple attributes if desired. Among other things, it means a dump can be replayed to set state. The current interface has yet to be released, so this seems like something to consider for 2.6.34. Signed-off-by: Chris Wright Signed-off-by: David S. Miller diff --git a/include/linux/if_link.h b/include/linux/if_link.h index c9bf92c..d94963b 100644 --- a/include/linux/if_link.h +++ b/include/linux/if_link.h @@ -79,10 +79,7 @@ enum { IFLA_NET_NS_PID, IFLA_IFALIAS, IFLA_NUM_VF, /* Number of VFs if device is SR-IOV PF */ - IFLA_VF_MAC, /* Hardware queue specific attributes */ - IFLA_VF_VLAN, - IFLA_VF_TX_RATE, /* TX Bandwidth Allocation */ - IFLA_VFINFO, + IFLA_VFINFO_LIST, __IFLA_MAX }; @@ -203,6 +200,24 @@ enum macvlan_mode { /* SR-IOV virtual function managment section */ +enum { + IFLA_VF_INFO_UNSPEC, + IFLA_VF_INFO, + __IFLA_VF_INFO_MAX, +}; + +#define IFLA_VF_INFO_MAX (__IFLA_VF_INFO_MAX - 1) + +enum { + IFLA_VF_UNSPEC, + IFLA_VF_MAC, /* Hardware queue specific attributes */ + IFLA_VF_VLAN, + IFLA_VF_TX_RATE, /* TX Bandwidth Allocation */ + __IFLA_VF_MAX, +}; + +#define IFLA_VF_MAX (__IFLA_VF_MAX - 1) + struct ifla_vf_mac { __u32 vf; __u8 mac[32]; /* MAX_ADDR_LEN */ diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index fe776c9..31e85d3 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -602,12 +602,19 @@ static void copy_rtnl_link_stats(struct rtnl_link_stats *a, a->tx_compressed = b->tx_compressed; }; +/* All VF info */ static inline int rtnl_vfinfo_size(const struct net_device *dev) { - if (dev->dev.parent && dev_is_pci(dev->dev.parent)) - return dev_num_vf(dev->dev.parent) * - sizeof(struct ifla_vf_info); - else + if (dev->dev.parent && dev_is_pci(dev->dev.parent)) { + + int num_vfs = dev_num_vf(dev->dev.parent); + size_t size = nlmsg_total_size(sizeof(struct nlattr)); + size += nlmsg_total_size(num_vfs * sizeof(struct nlattr)); + size += num_vfs * (sizeof(struct ifla_vf_mac) + + sizeof(struct ifla_vf_vlan) + + sizeof(struct ifla_vf_tx_rate)); + return size; + } else return 0; } @@ -629,7 +636,7 @@ static inline size_t if_nlmsg_size(const struct net_device *dev) + nla_total_size(1) /* IFLA_OPERSTATE */ + nla_total_size(1) /* IFLA_LINKMODE */ + nla_total_size(4) /* IFLA_NUM_VF */ - + nla_total_size(rtnl_vfinfo_size(dev)) /* IFLA_VFINFO */ + + rtnl_vfinfo_size(dev) /* IFLA_VFINFO_LIST */ + rtnl_link_get_size(dev); /* IFLA_LINKINFO */ } @@ -700,14 +707,37 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent) { int i; - struct ifla_vf_info ivi; - NLA_PUT_U32(skb, IFLA_NUM_VF, dev_num_vf(dev->dev.parent)); - for (i = 0; i < dev_num_vf(dev->dev.parent); i++) { + struct nlattr *vfinfo, *vf; + int num_vfs = dev_num_vf(dev->dev.parent); + + NLA_PUT_U32(skb, IFLA_NUM_VF, num_vfs); + vfinfo = nla_nest_start(skb, IFLA_VFINFO_LIST); + if (!vfinfo) + goto nla_put_failure; + for (i = 0; i < num_vfs; i++) { + struct ifla_vf_info ivi; + struct ifla_vf_mac vf_mac; + struct ifla_vf_vlan vf_vlan; + struct ifla_vf_tx_rate vf_tx_rate; if (dev->netdev_ops->ndo_get_vf_config(dev, i, &ivi)) break; - NLA_PUT(skb, IFLA_VFINFO, sizeof(ivi), &ivi); + vf_mac.vf = vf_vlan.vf = vf_tx_rate.vf = ivi.vf; + memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac)); + vf_vlan.vlan = ivi.vlan; + vf_vlan.qos = ivi.qos; + vf_tx_rate.rate = ivi.tx_rate; + vf = nla_nest_start(skb, IFLA_VF_INFO); + if (!vf) { + nla_nest_cancel(skb, vfinfo); + goto nla_put_failure; + } + NLA_PUT(skb, IFLA_VF_MAC, sizeof(vf_mac), &vf_mac); + NLA_PUT(skb, IFLA_VF_VLAN, sizeof(vf_vlan), &vf_vlan); + NLA_PUT(skb, IFLA_VF_TX_RATE, sizeof(vf_tx_rate), &vf_tx_rate); + nla_nest_end(skb, vf); } + nla_nest_end(skb, vfinfo); } if (dev->rtnl_link_ops) { if (rtnl_link_fill(skb, dev) < 0) @@ -769,12 +799,7 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = { [IFLA_LINKINFO] = { .type = NLA_NESTED }, [IFLA_NET_NS_PID] = { .type = NLA_U32 }, [IFLA_IFALIAS] = { .type = NLA_STRING, .len = IFALIASZ-1 }, - [IFLA_VF_MAC] = { .type = NLA_BINARY, - .len = sizeof(struct ifla_vf_mac) }, - [IFLA_VF_VLAN] = { .type = NLA_BINARY, - .len = sizeof(struct ifla_vf_vlan) }, - [IFLA_VF_TX_RATE] = { .type = NLA_BINARY, - .len = sizeof(struct ifla_vf_tx_rate) }, + [IFLA_VFINFO_LIST] = {. type = NLA_NESTED }, }; EXPORT_SYMBOL(ifla_policy); @@ -783,6 +808,19 @@ static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { [IFLA_INFO_DATA] = { .type = NLA_NESTED }, }; +static const struct nla_policy ifla_vfinfo_policy[IFLA_VF_INFO_MAX+1] = { + [IFLA_VF_INFO] = { .type = NLA_NESTED }, +}; + +static const struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = { + [IFLA_VF_MAC] = { .type = NLA_BINARY, + .len = sizeof(struct ifla_vf_mac) }, + [IFLA_VF_VLAN] = { .type = NLA_BINARY, + .len = sizeof(struct ifla_vf_vlan) }, + [IFLA_VF_TX_RATE] = { .type = NLA_BINARY, + .len = sizeof(struct ifla_vf_tx_rate) }, +}; + struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]) { struct net *net; @@ -812,6 +850,52 @@ static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[]) return 0; } +static int do_setvfinfo(struct net_device *dev, struct nlattr *attr) +{ + int rem, err = -EINVAL; + struct nlattr *vf; + const struct net_device_ops *ops = dev->netdev_ops; + + nla_for_each_nested(vf, attr, rem) { + switch (nla_type(vf)) { + case IFLA_VF_MAC: { + struct ifla_vf_mac *ivm; + ivm = nla_data(vf); + err = -EOPNOTSUPP; + if (ops->ndo_set_vf_mac) + err = ops->ndo_set_vf_mac(dev, ivm->vf, + ivm->mac); + break; + } + case IFLA_VF_VLAN: { + struct ifla_vf_vlan *ivv; + ivv = nla_data(vf); + err = -EOPNOTSUPP; + if (ops->ndo_set_vf_vlan) + err = ops->ndo_set_vf_vlan(dev, ivv->vf, + ivv->vlan, + ivv->qos); + break; + } + case IFLA_VF_TX_RATE: { + struct ifla_vf_tx_rate *ivt; + ivt = nla_data(vf); + err = -EOPNOTSUPP; + if (ops->ndo_set_vf_tx_rate) + err = ops->ndo_set_vf_tx_rate(dev, ivt->vf, + ivt->rate); + break; + } + default: + err = -EINVAL; + break; + } + if (err) + break; + } + return err; +} + static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, struct nlattr **tb, char *ifname, int modified) { @@ -942,40 +1026,17 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, write_unlock_bh(&dev_base_lock); } - if (tb[IFLA_VF_MAC]) { - struct ifla_vf_mac *ivm; - ivm = nla_data(tb[IFLA_VF_MAC]); - err = -EOPNOTSUPP; - if (ops->ndo_set_vf_mac) - err = ops->ndo_set_vf_mac(dev, ivm->vf, ivm->mac); - if (err < 0) - goto errout; - modified = 1; - } - - if (tb[IFLA_VF_VLAN]) { - struct ifla_vf_vlan *ivv; - ivv = nla_data(tb[IFLA_VF_VLAN]); - err = -EOPNOTSUPP; - if (ops->ndo_set_vf_vlan) - err = ops->ndo_set_vf_vlan(dev, ivv->vf, - ivv->vlan, - ivv->qos); - if (err < 0) - goto errout; - modified = 1; - } - err = 0; - - if (tb[IFLA_VF_TX_RATE]) { - struct ifla_vf_tx_rate *ivt; - ivt = nla_data(tb[IFLA_VF_TX_RATE]); - err = -EOPNOTSUPP; - if (ops->ndo_set_vf_tx_rate) - err = ops->ndo_set_vf_tx_rate(dev, ivt->vf, ivt->rate); - if (err < 0) - goto errout; - modified = 1; + if (tb[IFLA_VFINFO_LIST]) { + struct nlattr *attr; + int rem; + nla_for_each_nested(attr, tb[IFLA_VFINFO_LIST], rem) { + if (nla_type(attr) != IFLA_VF_INFO) + goto errout; + err = do_setvfinfo(dev, attr); + if (err < 0) + goto errout; + modified = 1; + } } err = 0; -- cgit v0.10.2 From e40152ee1e1c7a63f4777791863215e3faa37a86 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 16 May 2010 14:17:36 -0700 Subject: Linus 2.6.34 diff --git a/Makefile b/Makefile index 701bc65..ebc8225 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 34 -EXTRAVERSION = -rc7 +EXTRAVERSION = NAME = Sheep on Meth # *DOCUMENTATION* -- cgit v0.10.2 From a308f3a868185d4f804fe71d0400e2b058c6d9af Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 16 May 2010 20:29:38 -0300 Subject: perf tui: Make <- exit menus too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In fact it is now added to the hot key list when newt_form__new is used, allowing us to remove the explicit assignment in all its users. The visible change is that <- will exit the menu that pops up when -> is pressed (and Enter when callchains are not being used). Suggested-by: Ingo Molnar Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index 6974431..59a63e4 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -118,6 +118,7 @@ int browser__show_help(const char *format, va_list ap) static void newt_form__set_exit_keys(newtComponent self) { + newtFormAddHotKey(self, NEWT_KEY_LEFT); newtFormAddHotKey(self, NEWT_KEY_ESCAPE); newtFormAddHotKey(self, 'Q'); newtFormAddHotKey(self, 'q'); @@ -323,7 +324,6 @@ static int ui_browser__run(struct ui_browser *self, const char *title, newtFormAddHotKey(self->form, NEWT_KEY_PGDN); newtFormAddHotKey(self->form, NEWT_KEY_HOME); newtFormAddHotKey(self->form, NEWT_KEY_END); - newtFormAddHotKey(self->form, NEWT_KEY_LEFT); if (ui_browser__refresh_entries(self) < 0) return -1; @@ -757,7 +757,6 @@ static int hist_browser__populate(struct hist_browser *self, struct hists *hists newtFormAddHotKey(self->form, 'T'); newtFormAddHotKey(self->form, 't'); newtFormAddHotKey(self->form, NEWT_KEY_RIGHT); - newtFormAddHotKey(self->form, NEWT_KEY_LEFT); newtFormAddComponents(self->form, self->tree, NULL); self->selection = newt__symbol_tree_get_current(self->tree); -- cgit v0.10.2 From a9a4ab747e2d45bf08fddbc1568f080091486af9 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 16 May 2010 21:04:27 -0300 Subject: perf tui: Add help window to show key associations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Suggested-by: Ingo Molnar Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index 59a63e4..2001d26 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -167,6 +167,48 @@ out_destroy_form: return rc; } +static int ui__help_window(const char *text) +{ + struct newtExitStruct es; + newtComponent tb, form = newt_form__new(); + int rc = -1; + int max_len = 0, nr_lines = 0; + const char *t; + + if (form == NULL) + return -1; + + t = text; + while (1) { + const char *sep = strchr(t, '\n'); + int len; + + if (sep == NULL) + sep = strchr(t, '\0'); + len = sep - t; + if (max_len < len) + max_len = len; + ++nr_lines; + if (*sep == '\0') + break; + t = sep + 1; + } + + tb = newtTextbox(0, 0, max_len, nr_lines, 0); + if (tb == NULL) + goto out_destroy_form; + + newtTextboxSetText(tb, text); + newtFormAddComponent(form, tb); + newtCenteredWindow(max_len, nr_lines, NULL); + newtFormRun(form, &es); + newtPopWindow(); + rc = 0; +out_destroy_form: + newtFormDestroy(form); + return rc; +} + static bool dialog_yesno(const char *msg) { /* newtWinChoice should really be accepting const char pointers... */ @@ -756,6 +798,10 @@ static int hist_browser__populate(struct hist_browser *self, struct hists *hists newtFormAddHotKey(self->form, 'd'); newtFormAddHotKey(self->form, 'T'); newtFormAddHotKey(self->form, 't'); + newtFormAddHotKey(self->form, '?'); + newtFormAddHotKey(self->form, 'H'); + newtFormAddHotKey(self->form, 'h'); + newtFormAddHotKey(self->form, NEWT_KEY_F1); newtFormAddHotKey(self->form, NEWT_KEY_RIGHT); newtFormAddComponents(self->form, self->tree, NULL); self->selection = newt__symbol_tree_get_current(self->tree); @@ -842,6 +888,9 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na dso = browser->selection->map ? browser->selection->map->dso : NULL; if (es.reason == NEWT_EXIT_HOTKEY) { + if (es.u.key == NEWT_KEY_F1) + goto do_help; + switch (toupper(es.u.key)) { case 'A': goto do_annotate; @@ -849,6 +898,17 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na goto zoom_dso; case 'T': goto zoom_thread; + case 'H': + case '?': +do_help: + ui__help_window("-> Zoom into DSO/Threads & Annotate current symbol\n" + "<- Zoom out\n" + "a Annotate current symbol\n" + "h/?/F1 Show this window\n" + "d Zoom into current DSO\n" + "t Zoom into current Thread\n" + "q/CTRL+C Exit browser"); + continue; default:; } if (toupper(es.u.key) == 'Q' || -- cgit v0.10.2 From 59cda520881a1caf4332d6b03634c96fba361591 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Mon, 17 May 2010 09:38:01 +0900 Subject: ARM: S5PV210: Rearrange the system clock definitions The system clock definitions are currently defined below the peripheral clock definitions in the V210 clock code. For the V210 clock updates that follow this patch, it is required that the system clock definitions such as the mout_apll and mout_mpll be defined prior to the device clock definitions. This patch re-arranges the system clock defintions for the clock updates that follow this patch. Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index ccccae2..a620cd8 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c @@ -31,6 +31,33 @@ #include #include +static struct clksrc_clk clk_mout_apll = { + .clk = { + .name = "mout_apll", + .id = -1, + }, + .sources = &clk_src_apll, + .reg_src = { .reg = S5P_CLK_SRC0, .shift = 0, .size = 1 }, +}; + +static struct clksrc_clk clk_mout_epll = { + .clk = { + .name = "mout_epll", + .id = -1, + }, + .sources = &clk_src_epll, + .reg_src = { .reg = S5P_CLK_SRC0, .shift = 8, .size = 1 }, +}; + +static struct clksrc_clk clk_mout_mpll = { + .clk = { + .name = "mout_mpll", + .id = -1, + }, + .sources = &clk_src_mpll, + .reg_src = { .reg = S5P_CLK_SRC0, .shift = 4, .size = 1 }, +}; + static int s5pv210_clk_ip0_ctrl(struct clk *clk, int enable) { return s5p_gatectrl(S5P_CLKGATE_IP0, clk, enable); @@ -272,33 +299,6 @@ static struct clk init_clocks[] = { }, }; -static struct clksrc_clk clk_mout_apll = { - .clk = { - .name = "mout_apll", - .id = -1, - }, - .sources = &clk_src_apll, - .reg_src = { .reg = S5P_CLK_SRC0, .shift = 0, .size = 1 }, -}; - -static struct clksrc_clk clk_mout_epll = { - .clk = { - .name = "mout_epll", - .id = -1, - }, - .sources = &clk_src_epll, - .reg_src = { .reg = S5P_CLK_SRC0, .shift = 8, .size = 1 }, -}; - -static struct clksrc_clk clk_mout_mpll = { - .clk = { - .name = "mout_mpll", - .id = -1, - }, - .sources = &clk_src_mpll, - .reg_src = { .reg = S5P_CLK_SRC0, .shift = 4, .size = 1 }, -}; - static struct clk *clkset_uart_list[] = { [6] = &clk_mout_mpll.clk, [7] = &clk_mout_epll.clk, -- cgit v0.10.2 From eb1ef1ed06a168cf548419ba6e99f34c8169cffe Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Mon, 17 May 2010 09:38:12 +0900 Subject: ARM: S5PV210: Register apll/mpll/epll clksrc_clk clocks This patch modifies the following. 1. Registers the mout_apll clksrc_clk clock. 2. The mout_mpll and mout_epll clocks were registered as 'struct clk' types and then their parents were setup using the s3c_set_clksrc function. This patch reduces the two steps into one by registering the mout_mpll and mout_epll clocks using the s3c_register_clksrc function. 3. As per point 2 above, the init_parents array is no longer required. So the mout clocks are now put together in a new array named 'sysclks'. The sysclks array will list the system level clocks and more clocks will be added to it in the subsequent patches. 4. The clks array is left empty because of the movement of mpll and epll clocks into the sysclks array. It is not deleted since subsequent patches will add clocks into this array. Signed-off-by: Thomas Abraham samsung.com> Signed-off-by: Kukjin Kim samsung.com> Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index a620cd8..25b73a3 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c @@ -324,7 +324,7 @@ static struct clksrc_clk clksrcs[] = { }; /* Clock initialisation code */ -static struct clksrc_clk *init_parents[] = { +static struct clksrc_clk *sysclks[] = { &clk_mout_apll, &clk_mout_epll, &clk_mout_mpll, @@ -411,16 +411,11 @@ void __init_or_cpufreq s5pv210_setup_clocks(void) clk_h166.rate = hclk166; clk_h200.rate = hclk200; - for (ptr = 0; ptr < ARRAY_SIZE(init_parents); ptr++) - s3c_set_clksrc(init_parents[ptr], true); - for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) s3c_set_clksrc(&clksrcs[ptr], true); } static struct clk *clks[] __initdata = { - &clk_mout_epll.clk, - &clk_mout_mpll.clk, }; void __init s5pv210_register_clocks(void) @@ -433,6 +428,9 @@ void __init s5pv210_register_clocks(void) if (ret > 0) printk(KERN_ERR "Failed to register %u clocks\n", ret); + for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++) + s3c_register_clksrc(sysclks[ptr], 1); + s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs)); s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks)); -- cgit v0.10.2 From c62ec6a9aaabd5d0512e9d091d82940efefa4fa6 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Mon, 17 May 2010 09:38:28 +0900 Subject: ARM: S5PV210: Rearrange assignment of clock for fout apll/mpll/epll clocks The assignment of clock rates for fout apll/mpll/epll is moved further up in the s5pv210_setup_clocks function because the subsequent patches require the clock rate of fout clocks to be setup. Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index 25b73a3..d782fed 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c @@ -369,6 +369,10 @@ void __init_or_cpufreq s5pv210_setup_clocks(void) mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON), pll_4502); epll = s5p_get_pll45xx(xtal, __raw_readl(S5P_EPLL_CON), pll_4500); + clk_fout_apll.rate = apll; + clk_fout_mpll.rate = mpll; + clk_fout_epll.rate = epll; + printk(KERN_INFO "S5PV210: PLL settings, A=%ld, M=%ld, E=%ld", apll, mpll, epll); @@ -398,10 +402,6 @@ void __init_or_cpufreq s5pv210_setup_clocks(void) HCLKP=%ld, PCLKM=%ld, PCLKD=%ld, PCLKP=%ld\n", armclk, hclk200, hclk166, hclk133, pclk100, pclk83, pclk66); - clk_fout_apll.rate = apll; - clk_fout_mpll.rate = mpll; - clk_fout_epll.rate = epll; - clk_f.rate = armclk; clk_h.rate = hclk133; clk_p.rate = pclk66; -- cgit v0.10.2 From 374e0bf5f9e3b6055a943a838605e411b50c2838 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Mon, 17 May 2010 09:38:31 +0900 Subject: ARM: S5PV210: Add armclk of clksrc_clk clock type This patch modifies the following. 1. Adds arm clock 'clk_armclk' of type clksrc_clk clock type. 2. Adds arm clock to the list of system clocks 'sysclks' for registering it along with other system clocks. 3. Modifies the armclk clock rate calculation procedure to be based on the new clk_armclk clock. Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index d782fed..f57fa1e 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c @@ -58,6 +58,26 @@ static struct clksrc_clk clk_mout_mpll = { .reg_src = { .reg = S5P_CLK_SRC0, .shift = 4, .size = 1 }, }; +static struct clk *clkset_armclk_list[] = { + [0] = &clk_mout_apll.clk, + [1] = &clk_mout_mpll.clk, +}; + +static struct clksrc_sources clkset_armclk = { + .sources = clkset_armclk_list, + .nr_sources = ARRAY_SIZE(clkset_armclk_list), +}; + +static struct clksrc_clk clk_armclk = { + .clk = { + .name = "armclk", + .id = -1, + }, + .sources = &clkset_armclk, + .reg_src = { .reg = S5P_CLK_SRC0, .shift = 16, .size = 1 }, + .reg_div = { .reg = S5P_CLK_DIV0, .shift = 0, .size = 3 }, +}; + static int s5pv210_clk_ip0_ctrl(struct clk *clk, int enable) { return s5p_gatectrl(S5P_CLKGATE_IP0, clk, enable); @@ -328,6 +348,7 @@ static struct clksrc_clk *sysclks[] = { &clk_mout_apll, &clk_mout_epll, &clk_mout_mpll, + &clk_armclk, }; #define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1) @@ -376,7 +397,7 @@ void __init_or_cpufreq s5pv210_setup_clocks(void) printk(KERN_INFO "S5PV210: PLL settings, A=%ld, M=%ld, E=%ld", apll, mpll, epll); - armclk = apll / GET_DIV(clkdiv0, S5P_CLKDIV0_APLL); + armclk = clk_get_rate(&clk_armclk.clk); if (__raw_readl(S5P_CLK_SRC0) & S5P_CLKSRC0_MUX200_MASK) hclk200 = mpll / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK200); else -- cgit v0.10.2 From af76a201c63fd7566bab8892f3b8c82e66a264d0 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Mon, 17 May 2010 09:38:34 +0900 Subject: ARM: S5PV210: Remove usage of clk_h200 clock and add clk_hclk_msys clock The clk_h200 represents the HCLK for the MSYS domain. This clock is of type 'struct clk' but on V210, it is more suitable to be of type 'struct clksrc_clk' (since it is a divided version of the armclk). The replacement clock is renamed as clk_hclk_msys to indicate that it represents the HCLK for MSYS domain. This patch modifies the following. 1. Removes the usage of the clk_h200 clock. 2. Adds the new clock 'clk_hclk_msys'. 3. Adds clk_hclk_msys to the list of sysclks to be registered. 4. Modifies the hclk_msys clock rate calculation procedure to be based on the new clk_hclk_msys clock. Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index f57fa1e..d5acd26 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c @@ -78,6 +78,15 @@ static struct clksrc_clk clk_armclk = { .reg_div = { .reg = S5P_CLK_DIV0, .shift = 0, .size = 3 }, }; +static struct clksrc_clk clk_hclk_msys = { + .clk = { + .name = "hclk_msys", + .id = -1, + .parent = &clk_armclk.clk, + }, + .reg_div = { .reg = S5P_CLK_DIV0, .shift = 8, .size = 3 }, +}; + static int s5pv210_clk_ip0_ctrl(struct clk *clk, int enable) { return s5p_gatectrl(S5P_CLKGATE_IP0, clk, enable); @@ -98,11 +107,6 @@ static int s5pv210_clk_ip3_ctrl(struct clk *clk, int enable) return s5p_gatectrl(S5P_CLKGATE_IP3, clk, enable); } -static struct clk clk_h200 = { - .name = "hclk200", - .id = -1, -}; - static struct clk clk_h100 = { .name = "hclk100", .id = -1, @@ -134,7 +138,6 @@ static struct clk clk_p66 = { }; static struct clk *sys_clks[] = { - &clk_h200, &clk_h100, &clk_h166, &clk_h133, @@ -349,6 +352,7 @@ static struct clksrc_clk *sysclks[] = { &clk_mout_epll, &clk_mout_mpll, &clk_armclk, + &clk_hclk_msys, }; #define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1) @@ -358,7 +362,7 @@ void __init_or_cpufreq s5pv210_setup_clocks(void) struct clk *xtal_clk; unsigned long xtal; unsigned long armclk; - unsigned long hclk200; + unsigned long hclk_msys; unsigned long hclk166; unsigned long hclk133; unsigned long pclk100; @@ -398,10 +402,7 @@ void __init_or_cpufreq s5pv210_setup_clocks(void) apll, mpll, epll); armclk = clk_get_rate(&clk_armclk.clk); - if (__raw_readl(S5P_CLK_SRC0) & S5P_CLKSRC0_MUX200_MASK) - hclk200 = mpll / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK200); - else - hclk200 = armclk / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK200); + hclk_msys = clk_get_rate(&clk_hclk_msys.clk); if (__raw_readl(S5P_CLK_SRC0) & S5P_CLKSRC0_MUX166_MASK) { hclk166 = apll / GET_DIV(clkdiv0, S5P_CLKDIV0_A2M); @@ -415,13 +416,13 @@ void __init_or_cpufreq s5pv210_setup_clocks(void) } else hclk133 = mpll / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK133); - pclk100 = hclk200 / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK100); + pclk100 = hclk_msys / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK100); pclk83 = hclk166 / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK83); pclk66 = hclk133 / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK66); printk(KERN_INFO "S5PV210: ARMCLK=%ld, HCLKM=%ld, HCLKD=%ld, \ HCLKP=%ld, PCLKM=%ld, PCLKD=%ld, PCLKP=%ld\n", - armclk, hclk200, hclk166, hclk133, pclk100, pclk83, pclk66); + armclk, hclk_msys, hclk166, hclk133, pclk100, pclk83, pclk66); clk_f.rate = armclk; clk_h.rate = hclk133; @@ -430,7 +431,6 @@ void __init_or_cpufreq s5pv210_setup_clocks(void) clk_p83.rate = pclk83; clk_h133.rate = hclk133; clk_h166.rate = hclk166; - clk_h200.rate = hclk200; for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) s3c_set_clksrc(&clksrcs[ptr], true); -- cgit v0.10.2 From 0fe967a1ca8845ac227d3cab51e3520ddb310932 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Mon, 17 May 2010 09:38:37 +0900 Subject: ARM: S5PV210: Remove usage of clk_h166 and add clk_hclk_dsys clock The clk_h166 clock, which is the HCLK clock for DSYS domain, is of type 'struct clk' whereas on S5PV210, this clock is suitable to be of type clksrc_clk clock (since it has a choice of clock source and a pre-divider). So this patch replaces the 'struct clk' type clock to 'struct clksrc_clk' type clock for the HCLK DSYS clock. This patch modifies the following. 1. Remove definitions and usage of 'clk_h166' clock. 2. Adds 'clk_sclk_a2m' clock which is one of possible parent clock sources for the DSYS HCLK clock. 3. Adds 'clk_hclk_dsys' clock which is of type 'struct clksrc_clk'. 4. Replace all usage of clk_h166 with clk_hclk_dsys clock. 5. Adds clk_sclk_a2m and clk_hclk_dsys into list of clocks to be registered. 6. Removes the clock rate calculation of hclk166 and replaces it with code that derives the HCLK DSYS clock rate from the clk_hclk_dsys clock. Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index d5acd26..ecffafe 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c @@ -87,6 +87,35 @@ static struct clksrc_clk clk_hclk_msys = { .reg_div = { .reg = S5P_CLK_DIV0, .shift = 8, .size = 3 }, }; +static struct clksrc_clk clk_sclk_a2m = { + .clk = { + .name = "sclk_a2m", + .id = -1, + .parent = &clk_mout_apll.clk, + }, + .reg_div = { .reg = S5P_CLK_DIV0, .shift = 4, .size = 3 }, +}; + +static struct clk *clkset_hclk_sys_list[] = { + [0] = &clk_mout_mpll.clk, + [1] = &clk_sclk_a2m.clk, +}; + +static struct clksrc_sources clkset_hclk_sys = { + .sources = clkset_hclk_sys_list, + .nr_sources = ARRAY_SIZE(clkset_hclk_sys_list), +}; + +static struct clksrc_clk clk_hclk_dsys = { + .clk = { + .name = "hclk_dsys", + .id = -1, + }, + .sources = &clkset_hclk_sys, + .reg_src = { .reg = S5P_CLK_SRC0, .shift = 20, .size = 1 }, + .reg_div = { .reg = S5P_CLK_DIV0, .shift = 16, .size = 4 }, +}; + static int s5pv210_clk_ip0_ctrl(struct clk *clk, int enable) { return s5p_gatectrl(S5P_CLKGATE_IP0, clk, enable); @@ -112,11 +141,6 @@ static struct clk clk_h100 = { .id = -1, }; -static struct clk clk_h166 = { - .name = "hclk166", - .id = -1, -}; - static struct clk clk_h133 = { .name = "hclk133", .id = -1, @@ -139,7 +163,6 @@ static struct clk clk_p66 = { static struct clk *sys_clks[] = { &clk_h100, - &clk_h166, &clk_h133, &clk_p100, &clk_p83, @@ -150,7 +173,7 @@ static struct clk init_clocks_disable[] = { { .name = "rot", .id = -1, - .parent = &clk_h166, + .parent = &clk_hclk_dsys.clk, .enable = s5pv210_clk_ip0_ctrl, .ctrlbit = (1<<29), }, { @@ -168,7 +191,7 @@ static struct clk init_clocks_disable[] = { }, { .name = "lcd", .id = -1, - .parent = &clk_h166, + .parent = &clk_hclk_dsys.clk, .enable = s5pv210_clk_ip1_ctrl, .ctrlbit = (1<<0), }, { @@ -353,6 +376,8 @@ static struct clksrc_clk *sysclks[] = { &clk_mout_mpll, &clk_armclk, &clk_hclk_msys, + &clk_sclk_a2m, + &clk_hclk_dsys, }; #define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1) @@ -363,7 +388,7 @@ void __init_or_cpufreq s5pv210_setup_clocks(void) unsigned long xtal; unsigned long armclk; unsigned long hclk_msys; - unsigned long hclk166; + unsigned long hclk_dsys; unsigned long hclk133; unsigned long pclk100; unsigned long pclk83; @@ -403,12 +428,7 @@ void __init_or_cpufreq s5pv210_setup_clocks(void) armclk = clk_get_rate(&clk_armclk.clk); hclk_msys = clk_get_rate(&clk_hclk_msys.clk); - - if (__raw_readl(S5P_CLK_SRC0) & S5P_CLKSRC0_MUX166_MASK) { - hclk166 = apll / GET_DIV(clkdiv0, S5P_CLKDIV0_A2M); - hclk166 = hclk166 / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK166); - } else - hclk166 = mpll / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK166); + hclk_dsys = clk_get_rate(&clk_hclk_dsys.clk); if (__raw_readl(S5P_CLK_SRC0) & S5P_CLKSRC0_MUX133_MASK) { hclk133 = apll / GET_DIV(clkdiv0, S5P_CLKDIV0_A2M); @@ -417,12 +437,12 @@ void __init_or_cpufreq s5pv210_setup_clocks(void) hclk133 = mpll / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK133); pclk100 = hclk_msys / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK100); - pclk83 = hclk166 / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK83); + pclk83 = hclk_dsys / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK83); pclk66 = hclk133 / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK66); printk(KERN_INFO "S5PV210: ARMCLK=%ld, HCLKM=%ld, HCLKD=%ld, \ HCLKP=%ld, PCLKM=%ld, PCLKD=%ld, PCLKP=%ld\n", - armclk, hclk_msys, hclk166, hclk133, pclk100, pclk83, pclk66); + armclk, hclk_msys, hclk_dsys, hclk133, pclk100, pclk83, pclk66); clk_f.rate = armclk; clk_h.rate = hclk133; @@ -430,7 +450,6 @@ void __init_or_cpufreq s5pv210_setup_clocks(void) clk_p66.rate = pclk66; clk_p83.rate = pclk83; clk_h133.rate = hclk133; - clk_h166.rate = hclk166; for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) s3c_set_clksrc(&clksrcs[ptr], true); -- cgit v0.10.2 From acfa245fc7777bc1935c70a8951ff699952921c5 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Mon, 17 May 2010 09:38:40 +0900 Subject: ARM: S5PV210: Remove usage of clk_h133 and add clk_hclk_psys clock The clk_h133 clock, which is the HCLK clock for PSYS domain, is of type 'struct clk' whereas on S5PV210, this clock is suitable to be of type clksrc_clk clock (since it has a choice of clock source and a pre-divider). So this patch replaces the 'struct clk' type clock to 'struct clksrc_clk' type clock for the HCLK PSYS clock. This patch modifies the following. 1. Remove definitions and usage of 'clk_h133' clock. 2. Adds 'clk_hclk_psys' clock which is of type 'struct clksrc_clk'. 3. Replace all usage of clk_h133 with clk_hclk_psys clock. 4. Adds clk_hclk_psys into list of clocks to be registered. 5. Removes the clock rate calculation of hclk133 and replaces it with code that derives the HCLK PSYS clock rate from the clk_hclk_psys clock. 6. Modify printing of the system clock rates. Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index ecffafe..7ed1d4e 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c @@ -116,6 +116,16 @@ static struct clksrc_clk clk_hclk_dsys = { .reg_div = { .reg = S5P_CLK_DIV0, .shift = 16, .size = 4 }, }; +static struct clksrc_clk clk_hclk_psys = { + .clk = { + .name = "hclk_psys", + .id = -1, + }, + .sources = &clkset_hclk_sys, + .reg_src = { .reg = S5P_CLK_SRC0, .shift = 24, .size = 1 }, + .reg_div = { .reg = S5P_CLK_DIV0, .shift = 24, .size = 4 }, +}; + static int s5pv210_clk_ip0_ctrl(struct clk *clk, int enable) { return s5p_gatectrl(S5P_CLKGATE_IP0, clk, enable); @@ -141,11 +151,6 @@ static struct clk clk_h100 = { .id = -1, }; -static struct clk clk_h133 = { - .name = "hclk133", - .id = -1, -}; - static struct clk clk_p100 = { .name = "pclk100", .id = -1, @@ -163,7 +168,6 @@ static struct clk clk_p66 = { static struct clk *sys_clks[] = { &clk_h100, - &clk_h133, &clk_p100, &clk_p83, &clk_p66 @@ -179,13 +183,13 @@ static struct clk init_clocks_disable[] = { }, { .name = "otg", .id = -1, - .parent = &clk_h133, + .parent = &clk_hclk_psys.clk, .enable = s5pv210_clk_ip1_ctrl, .ctrlbit = (1<<16), }, { .name = "usb-host", .id = -1, - .parent = &clk_h133, + .parent = &clk_hclk_psys.clk, .enable = s5pv210_clk_ip1_ctrl, .ctrlbit = (1<<17), }, { @@ -197,31 +201,31 @@ static struct clk init_clocks_disable[] = { }, { .name = "cfcon", .id = 0, - .parent = &clk_h133, + .parent = &clk_hclk_psys.clk, .enable = s5pv210_clk_ip1_ctrl, .ctrlbit = (1<<25), }, { .name = "hsmmc", .id = 0, - .parent = &clk_h133, + .parent = &clk_hclk_psys.clk, .enable = s5pv210_clk_ip2_ctrl, .ctrlbit = (1<<16), }, { .name = "hsmmc", .id = 1, - .parent = &clk_h133, + .parent = &clk_hclk_psys.clk, .enable = s5pv210_clk_ip2_ctrl, .ctrlbit = (1<<17), }, { .name = "hsmmc", .id = 2, - .parent = &clk_h133, + .parent = &clk_hclk_psys.clk, .enable = s5pv210_clk_ip2_ctrl, .ctrlbit = (1<<18), }, { .name = "hsmmc", .id = 3, - .parent = &clk_h133, + .parent = &clk_hclk_psys.clk, .enable = s5pv210_clk_ip2_ctrl, .ctrlbit = (1<<19), }, { @@ -378,6 +382,7 @@ static struct clksrc_clk *sysclks[] = { &clk_hclk_msys, &clk_sclk_a2m, &clk_hclk_dsys, + &clk_hclk_psys, }; #define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1) @@ -389,7 +394,7 @@ void __init_or_cpufreq s5pv210_setup_clocks(void) unsigned long armclk; unsigned long hclk_msys; unsigned long hclk_dsys; - unsigned long hclk133; + unsigned long hclk_psys; unsigned long pclk100; unsigned long pclk83; unsigned long pclk66; @@ -429,27 +434,22 @@ void __init_or_cpufreq s5pv210_setup_clocks(void) armclk = clk_get_rate(&clk_armclk.clk); hclk_msys = clk_get_rate(&clk_hclk_msys.clk); hclk_dsys = clk_get_rate(&clk_hclk_dsys.clk); - - if (__raw_readl(S5P_CLK_SRC0) & S5P_CLKSRC0_MUX133_MASK) { - hclk133 = apll / GET_DIV(clkdiv0, S5P_CLKDIV0_A2M); - hclk133 = hclk133 / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK133); - } else - hclk133 = mpll / GET_DIV(clkdiv0, S5P_CLKDIV0_HCLK133); + hclk_psys = clk_get_rate(&clk_hclk_psys.clk); pclk100 = hclk_msys / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK100); pclk83 = hclk_dsys / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK83); - pclk66 = hclk133 / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK66); + pclk66 = hclk_psys / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK66); - printk(KERN_INFO "S5PV210: ARMCLK=%ld, HCLKM=%ld, HCLKD=%ld, \ - HCLKP=%ld, PCLKM=%ld, PCLKD=%ld, PCLKP=%ld\n", - armclk, hclk_msys, hclk_dsys, hclk133, pclk100, pclk83, pclk66); + printk(KERN_INFO "S5PV210: ARMCLK=%ld, HCLKM=%ld, HCLKD=%ld\n" + "HCLKP=%ld, PCLKM=%ld, PCLKD=%ld, PCLKP=%ld\n", + armclk, hclk_msys, hclk_dsys, hclk_psys, + pclk100, pclk83, pclk66); clk_f.rate = armclk; - clk_h.rate = hclk133; + clk_h.rate = hclk_psys; clk_p.rate = pclk66; clk_p66.rate = pclk66; clk_p83.rate = pclk83; - clk_h133.rate = hclk133; for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) s3c_set_clksrc(&clksrcs[ptr], true); -- cgit v0.10.2 From 6ed91a202b3843d2fec51f00c31e65313ca00906 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Mon, 17 May 2010 09:38:42 +0900 Subject: ARM: S5PV210: Remove usage of clk_p100 and add clk_pclk_msys clock The clk_p100 clock, which is the PCLK clock for MSYS domain, is of type 'struct clk' whereas on S5PV210, this clock is suitable to be of type clksrc_clk clock (since it has a choice of clock source and a pre-divider). So this patch replaces the 'struct clk' type clock to 'struct clksrc_clk' type clock for the PCLK MSYS clock. This patch modifies the following. 1. Remove definitions and usage of 'clk_p100' clock. 2. Adds 'clk_pclk_msys' clock which is of type 'struct clksrc_clk'. 3. Replace all usage of clk_p100 with clk_pclk_msys clock. 4. Adds clk_pclk_msys into list of clocks to be registered. Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index 7ed1d4e..4791642 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c @@ -87,6 +87,15 @@ static struct clksrc_clk clk_hclk_msys = { .reg_div = { .reg = S5P_CLK_DIV0, .shift = 8, .size = 3 }, }; +static struct clksrc_clk clk_pclk_msys = { + .clk = { + .name = "pclk_msys", + .id = -1, + .parent = &clk_hclk_msys.clk, + }, + .reg_div = { .reg = S5P_CLK_DIV0, .shift = 12, .size = 3 }, +}; + static struct clksrc_clk clk_sclk_a2m = { .clk = { .name = "sclk_a2m", @@ -151,11 +160,6 @@ static struct clk clk_h100 = { .id = -1, }; -static struct clk clk_p100 = { - .name = "pclk100", - .id = -1, -}; - static struct clk clk_p83 = { .name = "pclk83", .id = -1, @@ -168,7 +172,6 @@ static struct clk clk_p66 = { static struct clk *sys_clks[] = { &clk_h100, - &clk_p100, &clk_p83, &clk_p66 }; @@ -383,6 +386,7 @@ static struct clksrc_clk *sysclks[] = { &clk_sclk_a2m, &clk_hclk_dsys, &clk_hclk_psys, + &clk_pclk_msys, }; #define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1) @@ -395,7 +399,7 @@ void __init_or_cpufreq s5pv210_setup_clocks(void) unsigned long hclk_msys; unsigned long hclk_dsys; unsigned long hclk_psys; - unsigned long pclk100; + unsigned long pclk_msys; unsigned long pclk83; unsigned long pclk66; unsigned long apll; @@ -435,15 +439,14 @@ void __init_or_cpufreq s5pv210_setup_clocks(void) hclk_msys = clk_get_rate(&clk_hclk_msys.clk); hclk_dsys = clk_get_rate(&clk_hclk_dsys.clk); hclk_psys = clk_get_rate(&clk_hclk_psys.clk); - - pclk100 = hclk_msys / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK100); + pclk_msys = clk_get_rate(&clk_pclk_msys.clk); pclk83 = hclk_dsys / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK83); pclk66 = hclk_psys / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK66); printk(KERN_INFO "S5PV210: ARMCLK=%ld, HCLKM=%ld, HCLKD=%ld\n" "HCLKP=%ld, PCLKM=%ld, PCLKD=%ld, PCLKP=%ld\n", armclk, hclk_msys, hclk_dsys, hclk_psys, - pclk100, pclk83, pclk66); + pclk_msys, pclk83, pclk66); clk_f.rate = armclk; clk_h.rate = hclk_psys; -- cgit v0.10.2 From 664f5b2065da188821fe5aa998c6351e8c042d98 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Mon, 17 May 2010 09:38:44 +0900 Subject: ARM: S5PV210: Fix clk_get_rate issue with the clk_h100 clock The clk_h100 clock represents the IMEM clock for the MSYS domain. This clock rate of this clock is always half of the hclk_msys clock. There is an issue when getting the clock rate of the clk_h100 clock (clock get_rate hclk_h100 always returns clock rate that is equal to the hclk_msys clock rate). This patch modifies the following. 1. Moves the definition of the clk_h100 clock into the 'init_clocks' list with the appropriate parent, ctrlbit, enable and ops fields. 2. The name of the clock is changed from 'clk_h100' to 'hclk_imem' to represent more clearly that is represents the IMEM clock in the MSYS domain. 3. The function to get the clock rate of the hclk_imem clock is added. Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index 4791642..527c9c4 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c @@ -155,11 +155,6 @@ static int s5pv210_clk_ip3_ctrl(struct clk *clk, int enable) return s5p_gatectrl(S5P_CLKGATE_IP3, clk, enable); } -static struct clk clk_h100 = { - .name = "hclk100", - .id = -1, -}; - static struct clk clk_p83 = { .name = "pclk83", .id = -1, @@ -171,11 +166,19 @@ static struct clk clk_p66 = { }; static struct clk *sys_clks[] = { - &clk_h100, &clk_p83, &clk_p66 }; +static unsigned long s5pv210_clk_imem_get_rate(struct clk *clk) +{ + return clk_get_rate(clk->parent) / 2; +} + +static struct clk_ops clk_hclk_imem_ops = { + .get_rate = s5pv210_clk_imem_get_rate, +}; + static struct clk init_clocks_disable[] = { { .name = "rot", @@ -326,6 +329,13 @@ static struct clk init_clocks_disable[] = { static struct clk init_clocks[] = { { + .name = "hclk_imem", + .id = -1, + .parent = &clk_hclk_msys.clk, + .ctrlbit = (1 << 5), + .enable = s5pv210_clk_ip0_ctrl, + .ops = &clk_hclk_imem_ops, + }, { .name = "uart", .id = 0, .parent = &clk_p66, -- cgit v0.10.2 From 58772cd34479ca50e90eea25288d2021dd2e6ff6 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Mon, 17 May 2010 09:38:48 +0900 Subject: ARM: S5PV210: Remove usage of clk_p83 and add clk_pclk_dsys clock\ The clk_p83 clock, which is the PCLK clock for DSYS domain, is of type 'struct clk' whereas on S5PV210, this clock is suitable to be of type clksrc_clk clock (since it has a clock divider). So this patch replaces the 'struct clk' type clock to 'struct clksrc_clk' type clock for the PCLK DSYS clock. This patch modifies the following. 1. Remove definitions and usage of 'clk_p83' clock. 2. Adds 'clk_pclk_dsys' clock which is of type 'struct clksrc_clk'. 3. Replace all usage of clk_p83 with clk_pclk_dsys clock. 4. Adds clk_pclk_dsys into list of clocks to be registered. Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index 527c9c4..b46d9ec 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c @@ -125,6 +125,15 @@ static struct clksrc_clk clk_hclk_dsys = { .reg_div = { .reg = S5P_CLK_DIV0, .shift = 16, .size = 4 }, }; +static struct clksrc_clk clk_pclk_dsys = { + .clk = { + .name = "pclk_dsys", + .id = -1, + .parent = &clk_hclk_dsys.clk, + }, + .reg_div = { .reg = S5P_CLK_DIV0, .shift = 20, .size = 3 }, +}; + static struct clksrc_clk clk_hclk_psys = { .clk = { .name = "hclk_psys", @@ -155,18 +164,12 @@ static int s5pv210_clk_ip3_ctrl(struct clk *clk, int enable) return s5p_gatectrl(S5P_CLKGATE_IP3, clk, enable); } -static struct clk clk_p83 = { - .name = "pclk83", - .id = -1, -}; - static struct clk clk_p66 = { .name = "pclk66", .id = -1, }; static struct clk *sys_clks[] = { - &clk_p83, &clk_p66 }; @@ -397,6 +400,7 @@ static struct clksrc_clk *sysclks[] = { &clk_hclk_dsys, &clk_hclk_psys, &clk_pclk_msys, + &clk_pclk_dsys, }; #define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1) @@ -410,7 +414,7 @@ void __init_or_cpufreq s5pv210_setup_clocks(void) unsigned long hclk_dsys; unsigned long hclk_psys; unsigned long pclk_msys; - unsigned long pclk83; + unsigned long pclk_dsys; unsigned long pclk66; unsigned long apll; unsigned long mpll; @@ -450,19 +454,18 @@ void __init_or_cpufreq s5pv210_setup_clocks(void) hclk_dsys = clk_get_rate(&clk_hclk_dsys.clk); hclk_psys = clk_get_rate(&clk_hclk_psys.clk); pclk_msys = clk_get_rate(&clk_pclk_msys.clk); - pclk83 = hclk_dsys / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK83); + pclk_dsys = clk_get_rate(&clk_pclk_dsys.clk); pclk66 = hclk_psys / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK66); printk(KERN_INFO "S5PV210: ARMCLK=%ld, HCLKM=%ld, HCLKD=%ld\n" "HCLKP=%ld, PCLKM=%ld, PCLKD=%ld, PCLKP=%ld\n", armclk, hclk_msys, hclk_dsys, hclk_psys, - pclk_msys, pclk83, pclk66); + pclk_msys, pclk_dsys, pclk66); clk_f.rate = armclk; clk_h.rate = hclk_psys; clk_p.rate = pclk66; clk_p66.rate = pclk66; - clk_p83.rate = pclk83; for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) s3c_set_clksrc(&clksrcs[ptr], true); -- cgit v0.10.2 From f44cf78b6b475116a4d3c98576f8697dd4ca7e79 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Mon, 17 May 2010 09:38:50 +0900 Subject: ARM: S5PV210: Remove usage of clk_p66 and add clk_pclk_psys clock The clk_p83 clock, which is the PCLK clock for PSYS domain, is of type 'struct clk' whereas on S5PV210, this clock is suitable to be of type clksrc_clk clock (since it has a clock divider). So this patch replaces the 'struct clk' type clock to 'struct clksrc_clk' type clock for the PCLK PSYS clock. This patch modifies the following. 1. Removes definitions and usage of 'clk_p66' clock. 2. Adds 'clk_pclk_psys' clock which is of type 'struct clksrc_clk'. 3. Replaces all usage of clk_p66 with clk_pclk_psys clock. 4. Adds clk_pclk_psys into list of clocks to be registered. 5. Removes the sys_clks array since it is no longer required. Also the registration of clocks in sys_clks is also removed. 6. Remove the 'GET_DIV' as it is no longer required. Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index b46d9ec..315955da 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c @@ -144,6 +144,15 @@ static struct clksrc_clk clk_hclk_psys = { .reg_div = { .reg = S5P_CLK_DIV0, .shift = 24, .size = 4 }, }; +static struct clksrc_clk clk_pclk_psys = { + .clk = { + .name = "pclk_psys", + .id = -1, + .parent = &clk_hclk_psys.clk, + }, + .reg_div = { .reg = S5P_CLK_DIV0, .shift = 28, .size = 3 }, +}; + static int s5pv210_clk_ip0_ctrl(struct clk *clk, int enable) { return s5p_gatectrl(S5P_CLKGATE_IP0, clk, enable); @@ -164,15 +173,6 @@ static int s5pv210_clk_ip3_ctrl(struct clk *clk, int enable) return s5p_gatectrl(S5P_CLKGATE_IP3, clk, enable); } -static struct clk clk_p66 = { - .name = "pclk66", - .id = -1, -}; - -static struct clk *sys_clks[] = { - &clk_p66 -}; - static unsigned long s5pv210_clk_imem_get_rate(struct clk *clk) { return clk_get_rate(clk->parent) / 2; @@ -240,73 +240,73 @@ static struct clk init_clocks_disable[] = { }, { .name = "systimer", .id = -1, - .parent = &clk_p66, + .parent = &clk_pclk_psys.clk, .enable = s5pv210_clk_ip3_ctrl, .ctrlbit = (1<<16), }, { .name = "watchdog", .id = -1, - .parent = &clk_p66, + .parent = &clk_pclk_psys.clk, .enable = s5pv210_clk_ip3_ctrl, .ctrlbit = (1<<22), }, { .name = "rtc", .id = -1, - .parent = &clk_p66, + .parent = &clk_pclk_psys.clk, .enable = s5pv210_clk_ip3_ctrl, .ctrlbit = (1<<15), }, { .name = "i2c", .id = 0, - .parent = &clk_p66, + .parent = &clk_pclk_psys.clk, .enable = s5pv210_clk_ip3_ctrl, .ctrlbit = (1<<7), }, { .name = "i2c", .id = 1, - .parent = &clk_p66, + .parent = &clk_pclk_psys.clk, .enable = s5pv210_clk_ip3_ctrl, .ctrlbit = (1<<8), }, { .name = "i2c", .id = 2, - .parent = &clk_p66, + .parent = &clk_pclk_psys.clk, .enable = s5pv210_clk_ip3_ctrl, .ctrlbit = (1<<9), }, { .name = "spi", .id = 0, - .parent = &clk_p66, + .parent = &clk_pclk_psys.clk, .enable = s5pv210_clk_ip3_ctrl, .ctrlbit = (1<<12), }, { .name = "spi", .id = 1, - .parent = &clk_p66, + .parent = &clk_pclk_psys.clk, .enable = s5pv210_clk_ip3_ctrl, .ctrlbit = (1<<13), }, { .name = "spi", .id = 2, - .parent = &clk_p66, + .parent = &clk_pclk_psys.clk, .enable = s5pv210_clk_ip3_ctrl, .ctrlbit = (1<<14), }, { .name = "timers", .id = -1, - .parent = &clk_p66, + .parent = &clk_pclk_psys.clk, .enable = s5pv210_clk_ip3_ctrl, .ctrlbit = (1<<23), }, { .name = "adc", .id = -1, - .parent = &clk_p66, + .parent = &clk_pclk_psys.clk, .enable = s5pv210_clk_ip3_ctrl, .ctrlbit = (1<<24), }, { .name = "keypad", .id = -1, - .parent = &clk_p66, + .parent = &clk_pclk_psys.clk, .enable = s5pv210_clk_ip3_ctrl, .ctrlbit = (1<<21), }, { @@ -341,25 +341,25 @@ static struct clk init_clocks[] = { }, { .name = "uart", .id = 0, - .parent = &clk_p66, + .parent = &clk_pclk_psys.clk, .enable = s5pv210_clk_ip3_ctrl, .ctrlbit = (1<<7), }, { .name = "uart", .id = 1, - .parent = &clk_p66, + .parent = &clk_pclk_psys.clk, .enable = s5pv210_clk_ip3_ctrl, .ctrlbit = (1<<8), }, { .name = "uart", .id = 2, - .parent = &clk_p66, + .parent = &clk_pclk_psys.clk, .enable = s5pv210_clk_ip3_ctrl, .ctrlbit = (1<<9), }, { .name = "uart", .id = 3, - .parent = &clk_p66, + .parent = &clk_pclk_psys.clk, .enable = s5pv210_clk_ip3_ctrl, .ctrlbit = (1<<10), }, @@ -401,10 +401,9 @@ static struct clksrc_clk *sysclks[] = { &clk_hclk_psys, &clk_pclk_msys, &clk_pclk_dsys, + &clk_pclk_psys, }; -#define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1) - void __init_or_cpufreq s5pv210_setup_clocks(void) { struct clk *xtal_clk; @@ -415,7 +414,7 @@ void __init_or_cpufreq s5pv210_setup_clocks(void) unsigned long hclk_psys; unsigned long pclk_msys; unsigned long pclk_dsys; - unsigned long pclk66; + unsigned long pclk_psys; unsigned long apll; unsigned long mpll; unsigned long epll; @@ -455,17 +454,16 @@ void __init_or_cpufreq s5pv210_setup_clocks(void) hclk_psys = clk_get_rate(&clk_hclk_psys.clk); pclk_msys = clk_get_rate(&clk_pclk_msys.clk); pclk_dsys = clk_get_rate(&clk_pclk_dsys.clk); - pclk66 = hclk_psys / GET_DIV(clkdiv0, S5P_CLKDIV0_PCLK66); + pclk_psys = clk_get_rate(&clk_pclk_psys.clk); printk(KERN_INFO "S5PV210: ARMCLK=%ld, HCLKM=%ld, HCLKD=%ld\n" "HCLKP=%ld, PCLKM=%ld, PCLKD=%ld, PCLKP=%ld\n", armclk, hclk_msys, hclk_dsys, hclk_psys, - pclk_msys, pclk_dsys, pclk66); + pclk_msys, pclk_dsys, pclk_psys); clk_f.rate = armclk; clk_h.rate = hclk_psys; - clk_p.rate = pclk66; - clk_p66.rate = pclk66; + clk_p.rate = pclk_psys; for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) s3c_set_clksrc(&clksrcs[ptr], true); @@ -490,10 +488,6 @@ void __init s5pv210_register_clocks(void) s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs)); s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks)); - ret = s3c24xx_register_clocks(sys_clks, ARRAY_SIZE(sys_clks)); - if (ret > 0) - printk(KERN_ERR "Failed to register system clocks\n"); - clkp = init_clocks_disable; for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) { ret = s3c24xx_register_clock(clkp); -- cgit v0.10.2 From f445dbd5af7863dd7dce4685e39980419d4144eb Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Mon, 17 May 2010 09:38:52 +0900 Subject: ARM: S5PV210: Add support for VPLL This patch adds the following. 1. Adds 'clk_sclk_hdmi27m' clock to represent the HDMI 27MHz clock. 2. Adds 'clk_vpllsrc; clock of type clksrc_clk to represent the input clock for VPLL. 3. Adds 'clk_sclk_vpll' clock of type clksrc_clk to represent the output of the MUX_VPLL mux. 4. Add clk_sclk_hdmi27m, clk_vpllsrc and clk_sclk_vpll to the list of clocks to be registered. 5. Adds boot time print of 'clk_sclk_vpll' clock rate. 6. Adds 'clk_fout_vpll' clock to plat-s5p such that it is reusable on other s5p platforms. Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index 315955da..c86bff5 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c @@ -173,6 +173,57 @@ static int s5pv210_clk_ip3_ctrl(struct clk *clk, int enable) return s5p_gatectrl(S5P_CLKGATE_IP3, clk, enable); } +static int s5pv210_clk_mask0_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P_CLK_SRC_MASK0, clk, enable); +} + +static struct clk clk_sclk_hdmi27m = { + .name = "sclk_hdmi27m", + .id = -1, + .rate = 27000000, +}; + +static struct clk *clkset_vpllsrc_list[] = { + [0] = &clk_fin_vpll, + [1] = &clk_sclk_hdmi27m, +}; + +static struct clksrc_sources clkset_vpllsrc = { + .sources = clkset_vpllsrc_list, + .nr_sources = ARRAY_SIZE(clkset_vpllsrc_list), +}; + +static struct clksrc_clk clk_vpllsrc = { + .clk = { + .name = "vpll_src", + .id = -1, + .enable = s5pv210_clk_mask0_ctrl, + .ctrlbit = (1 << 7), + }, + .sources = &clkset_vpllsrc, + .reg_src = { .reg = S5P_CLK_SRC1, .shift = 28, .size = 1 }, +}; + +static struct clk *clkset_sclk_vpll_list[] = { + [0] = &clk_vpllsrc.clk, + [1] = &clk_fout_vpll, +}; + +static struct clksrc_sources clkset_sclk_vpll = { + .sources = clkset_sclk_vpll_list, + .nr_sources = ARRAY_SIZE(clkset_sclk_vpll_list), +}; + +static struct clksrc_clk clk_sclk_vpll = { + .clk = { + .name = "sclk_vpll", + .id = -1, + }, + .sources = &clkset_sclk_vpll, + .reg_src = { .reg = S5P_CLK_SRC0, .shift = 12, .size = 1 }, +}; + static unsigned long s5pv210_clk_imem_get_rate(struct clk *clk) { return clk_get_rate(clk->parent) / 2; @@ -402,12 +453,15 @@ static struct clksrc_clk *sysclks[] = { &clk_pclk_msys, &clk_pclk_dsys, &clk_pclk_psys, + &clk_vpllsrc, + &clk_sclk_vpll, }; void __init_or_cpufreq s5pv210_setup_clocks(void) { struct clk *xtal_clk; unsigned long xtal; + unsigned long vpllsrc; unsigned long armclk; unsigned long hclk_msys; unsigned long hclk_dsys; @@ -418,6 +472,7 @@ void __init_or_cpufreq s5pv210_setup_clocks(void) unsigned long apll; unsigned long mpll; unsigned long epll; + unsigned long vpll; unsigned int ptr; u32 clkdiv0, clkdiv1; @@ -440,13 +495,16 @@ void __init_or_cpufreq s5pv210_setup_clocks(void) apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON), pll_4508); mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON), pll_4502); epll = s5p_get_pll45xx(xtal, __raw_readl(S5P_EPLL_CON), pll_4500); + vpllsrc = clk_get_rate(&clk_vpllsrc.clk); + vpll = s5p_get_pll45xx(vpllsrc, __raw_readl(S5P_VPLL_CON), pll_4502); clk_fout_apll.rate = apll; clk_fout_mpll.rate = mpll; clk_fout_epll.rate = epll; + clk_fout_vpll.rate = vpll; - printk(KERN_INFO "S5PV210: PLL settings, A=%ld, M=%ld, E=%ld", - apll, mpll, epll); + printk(KERN_INFO "S5PV210: PLL settings, A=%ld, M=%ld, E=%ld V=%ld", + apll, mpll, epll, vpll); armclk = clk_get_rate(&clk_armclk.clk); hclk_msys = clk_get_rate(&clk_hclk_msys.clk); @@ -470,6 +528,7 @@ void __init_or_cpufreq s5pv210_setup_clocks(void) } static struct clk *clks[] __initdata = { + &clk_sclk_hdmi27m, }; void __init s5pv210_register_clocks(void) diff --git a/arch/arm/plat-s5p/clock.c b/arch/arm/plat-s5p/clock.c index aa96e33..4ca0759 100644 --- a/arch/arm/plat-s5p/clock.c +++ b/arch/arm/plat-s5p/clock.c @@ -69,6 +69,13 @@ struct clk clk_fout_epll = { .ctrlbit = (1 << 31), }; +/* VPLL clock output */ +struct clk clk_fout_vpll = { + .name = "fout_vpll", + .id = -1, + .ctrlbit = (1 << 31), +}; + /* ARM clock */ struct clk clk_arm = { .name = "armclk", @@ -133,6 +140,7 @@ static struct clk *s5p_clks[] __initdata = { &clk_fout_apll, &clk_fout_mpll, &clk_fout_epll, + &clk_fout_vpll, &clk_arm, &clk_vpll, }; diff --git a/arch/arm/plat-s5p/include/plat/s5p-clock.h b/arch/arm/plat-s5p/include/plat/s5p-clock.h index 56fb8b4..5ae8866 100644 --- a/arch/arm/plat-s5p/include/plat/s5p-clock.h +++ b/arch/arm/plat-s5p/include/plat/s5p-clock.h @@ -27,6 +27,7 @@ extern struct clk clk_48m; extern struct clk clk_fout_apll; extern struct clk clk_fout_mpll; extern struct clk clk_fout_epll; +extern struct clk clk_fout_vpll; extern struct clk clk_arm; extern struct clk clk_vpll; -- cgit v0.10.2 From 2cf4c2e6301f19e08b7090c024b312f6e2c0f230 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Mon, 17 May 2010 09:38:55 +0900 Subject: ARM: S5PV210: Add new system clocks This patch adds the following system clocks. 1. clk_sclk_hdmiphy 2. clk_sclk_usbphy0 3. clk_sclk_usbphy1 4. sclk_dmc (dram memory controller clock) 5. sclk_onenand Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index c86bff5..2c7be15 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c @@ -184,6 +184,21 @@ static struct clk clk_sclk_hdmi27m = { .rate = 27000000, }; +static struct clk clk_sclk_hdmiphy = { + .name = "sclk_hdmiphy", + .id = -1, +}; + +static struct clk clk_sclk_usbphy0 = { + .name = "sclk_usbphy0", + .id = -1, +}; + +static struct clk clk_sclk_usbphy1 = { + .name = "sclk_usbphy1", + .id = -1, +}; + static struct clk *clkset_vpllsrc_list[] = { [0] = &clk_fin_vpll, [1] = &clk_sclk_hdmi27m, @@ -426,9 +441,47 @@ static struct clksrc_sources clkset_uart = { .nr_sources = ARRAY_SIZE(clkset_uart_list), }; +static struct clk *clkset_group1_list[] = { + [0] = &clk_sclk_a2m.clk, + [1] = &clk_mout_mpll.clk, + [2] = &clk_mout_epll.clk, + [3] = &clk_sclk_vpll.clk, +}; + +static struct clksrc_sources clkset_group1 = { + .sources = clkset_group1_list, + .nr_sources = ARRAY_SIZE(clkset_group1_list), +}; + +static struct clk *clkset_sclk_onenand_list[] = { + [0] = &clk_hclk_psys.clk, + [1] = &clk_hclk_dsys.clk, +}; + +static struct clksrc_sources clkset_sclk_onenand = { + .sources = clkset_sclk_onenand_list, + .nr_sources = ARRAY_SIZE(clkset_sclk_onenand_list), +}; + static struct clksrc_clk clksrcs[] = { { .clk = { + .name = "sclk_dmc", + .id = -1, + }, + .sources = &clkset_group1, + .reg_src = { .reg = S5P_CLK_SRC6, .shift = 24, .size = 2 }, + .reg_div = { .reg = S5P_CLK_DIV6, .shift = 28, .size = 4 }, + }, { + .clk = { + .name = "sclk_onenand", + .id = -1, + }, + .sources = &clkset_sclk_onenand, + .reg_src = { .reg = S5P_CLK_SRC0, .shift = 28, .size = 1 }, + .reg_div = { .reg = S5P_CLK_DIV6, .shift = 12, .size = 3 }, + }, { + .clk = { .name = "uclk1", .id = -1, .ctrlbit = (1<<17), @@ -529,6 +582,9 @@ void __init_or_cpufreq s5pv210_setup_clocks(void) static struct clk *clks[] __initdata = { &clk_sclk_hdmi27m, + &clk_sclk_hdmiphy, + &clk_sclk_usbphy0, + &clk_sclk_usbphy1, }; void __init s5pv210_register_clocks(void) -- cgit v0.10.2 From 9e20614bb9403102033b60ce7d8fceb5becdb71c Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Mon, 17 May 2010 09:38:57 +0900 Subject: ARM: S5PV210: Add sclk_dac, sclk_mixer and sclk_hdmi clocks Add sclk_dac, sclk_mixer and sclk_hdmi clocks. These clocks are of type 'struct clksrc_clk' and so have a corresponding clock list. These clocks are also added to the list of clocks to be registered at boot time. Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index 2c7be15..c03e288 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c @@ -463,6 +463,67 @@ static struct clksrc_sources clkset_sclk_onenand = { .nr_sources = ARRAY_SIZE(clkset_sclk_onenand_list), }; +static struct clk *clkset_sclk_dac_list[] = { + [0] = &clk_sclk_vpll.clk, + [1] = &clk_sclk_hdmiphy, +}; + +static struct clksrc_sources clkset_sclk_dac = { + .sources = clkset_sclk_dac_list, + .nr_sources = ARRAY_SIZE(clkset_sclk_dac_list), +}; + +static struct clksrc_clk clk_sclk_dac = { + .clk = { + .name = "sclk_dac", + .id = -1, + .ctrlbit = (1 << 10), + .enable = s5pv210_clk_ip1_ctrl, + }, + .sources = &clkset_sclk_dac, + .reg_src = { .reg = S5P_CLK_SRC1, .shift = 8, .size = 1 }, +}; + +static struct clksrc_clk clk_sclk_pixel = { + .clk = { + .name = "sclk_pixel", + .id = -1, + .parent = &clk_sclk_vpll.clk, + }, + .reg_div = { .reg = S5P_CLK_DIV1, .shift = 0, .size = 4}, +}; + +static struct clk *clkset_sclk_hdmi_list[] = { + [0] = &clk_sclk_pixel.clk, + [1] = &clk_sclk_hdmiphy, +}; + +static struct clksrc_sources clkset_sclk_hdmi = { + .sources = clkset_sclk_hdmi_list, + .nr_sources = ARRAY_SIZE(clkset_sclk_hdmi_list), +}; + +static struct clksrc_clk clk_sclk_hdmi = { + .clk = { + .name = "sclk_hdmi", + .id = -1, + .enable = s5pv210_clk_ip1_ctrl, + .ctrlbit = (1 << 11), + }, + .sources = &clkset_sclk_hdmi, + .reg_src = { .reg = S5P_CLK_SRC1, .shift = 0, .size = 1 }, +}; + +static struct clk *clkset_sclk_mixer_list[] = { + [0] = &clk_sclk_dac.clk, + [1] = &clk_sclk_hdmi.clk, +}; + +static struct clksrc_sources clkset_sclk_mixer = { + .sources = clkset_sclk_mixer_list, + .nr_sources = ARRAY_SIZE(clkset_sclk_mixer_list), +}; + static struct clksrc_clk clksrcs[] = { { .clk = { @@ -490,7 +551,16 @@ static struct clksrc_clk clksrcs[] = { .sources = &clkset_uart, .reg_src = { .reg = S5P_CLK_SRC4, .shift = 16, .size = 4 }, .reg_div = { .reg = S5P_CLK_DIV4, .shift = 16, .size = 4 }, - } + }, { + .clk = { + .name = "sclk_mixer", + .id = -1, + .enable = s5pv210_clk_ip1_ctrl, + .ctrlbit = (1 << 9), + }, + .sources = &clkset_sclk_mixer, + .reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 1 }, + }, }; /* Clock initialisation code */ @@ -508,6 +578,9 @@ static struct clksrc_clk *sysclks[] = { &clk_pclk_psys, &clk_vpllsrc, &clk_sclk_vpll, + &clk_sclk_dac, + &clk_sclk_pixel, + &clk_sclk_hdmi, }; void __init_or_cpufreq s5pv210_setup_clocks(void) -- cgit v0.10.2 From 4583487c43358070ef1bd43dd1cbaf2dd42e4db7 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Mon, 17 May 2010 09:39:00 +0900 Subject: ARM: S5PV210: Add sclk_audio and sclk_spdif clocks. Add the sclk_audio(0/1/2) clocks and sclk_spdif clock of type 'struct clksrc_clk' clock. Also, add clk_pcmcdclk(0/1/2) clocks of type 'struct clk' clock. Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index c03e288..0154710 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c @@ -199,6 +199,21 @@ static struct clk clk_sclk_usbphy1 = { .id = -1, }; +static struct clk clk_pcmcdclk0 = { + .name = "pcmcdclk", + .id = -1, +}; + +static struct clk clk_pcmcdclk1 = { + .name = "pcmcdclk", + .id = -1, +}; + +static struct clk clk_pcmcdclk2 = { + .name = "pcmcdclk", + .id = -1, +}; + static struct clk *clkset_vpllsrc_list[] = { [0] = &clk_fin_vpll, [1] = &clk_sclk_hdmi27m, @@ -524,6 +539,104 @@ static struct clksrc_sources clkset_sclk_mixer = { .nr_sources = ARRAY_SIZE(clkset_sclk_mixer_list), }; +static struct clk *clkset_sclk_audio0_list[] = { + [0] = &clk_ext_xtal_mux, + [1] = &clk_pcmcdclk0, + [2] = &clk_sclk_hdmi27m, + [3] = &clk_sclk_usbphy0, + [4] = &clk_sclk_usbphy1, + [5] = &clk_sclk_hdmiphy, + [6] = &clk_mout_mpll.clk, + [7] = &clk_mout_epll.clk, + [8] = &clk_sclk_vpll.clk, +}; + +static struct clksrc_sources clkset_sclk_audio0 = { + .sources = clkset_sclk_audio0_list, + .nr_sources = ARRAY_SIZE(clkset_sclk_audio0_list), +}; + +static struct clksrc_clk clk_sclk_audio0 = { + .clk = { + .name = "sclk_audio", + .id = 0, + .enable = s5pv210_clk_ip3_ctrl, + .ctrlbit = (1 << 4), + }, + .sources = &clkset_sclk_audio0, + .reg_src = { .reg = S5P_CLK_SRC6, .shift = 0, .size = 4 }, + .reg_div = { .reg = S5P_CLK_DIV6, .shift = 0, .size = 4 }, +}; + +static struct clk *clkset_sclk_audio1_list[] = { + [0] = &clk_ext_xtal_mux, + [1] = &clk_pcmcdclk1, + [2] = &clk_sclk_hdmi27m, + [3] = &clk_sclk_usbphy0, + [4] = &clk_sclk_usbphy1, + [5] = &clk_sclk_hdmiphy, + [6] = &clk_mout_mpll.clk, + [7] = &clk_mout_epll.clk, + [8] = &clk_sclk_vpll.clk, +}; + +static struct clksrc_sources clkset_sclk_audio1 = { + .sources = clkset_sclk_audio1_list, + .nr_sources = ARRAY_SIZE(clkset_sclk_audio1_list), +}; + +static struct clksrc_clk clk_sclk_audio1 = { + .clk = { + .name = "sclk_audio", + .id = 1, + .enable = s5pv210_clk_ip3_ctrl, + .ctrlbit = (1 << 5), + }, + .sources = &clkset_sclk_audio1, + .reg_src = { .reg = S5P_CLK_SRC6, .shift = 4, .size = 4 }, + .reg_div = { .reg = S5P_CLK_DIV6, .shift = 4, .size = 4 }, +}; + +static struct clk *clkset_sclk_audio2_list[] = { + [0] = &clk_ext_xtal_mux, + [1] = &clk_pcmcdclk0, + [2] = &clk_sclk_hdmi27m, + [3] = &clk_sclk_usbphy0, + [4] = &clk_sclk_usbphy1, + [5] = &clk_sclk_hdmiphy, + [6] = &clk_mout_mpll.clk, + [7] = &clk_mout_epll.clk, + [8] = &clk_sclk_vpll.clk, +}; + +static struct clksrc_sources clkset_sclk_audio2 = { + .sources = clkset_sclk_audio2_list, + .nr_sources = ARRAY_SIZE(clkset_sclk_audio2_list), +}; + +static struct clksrc_clk clk_sclk_audio2 = { + .clk = { + .name = "sclk_audio", + .id = 2, + .enable = s5pv210_clk_ip3_ctrl, + .ctrlbit = (1 << 6), + }, + .sources = &clkset_sclk_audio2, + .reg_src = { .reg = S5P_CLK_SRC6, .shift = 8, .size = 4 }, + .reg_div = { .reg = S5P_CLK_DIV6, .shift = 8, .size = 4 }, +}; + +static struct clk *clkset_sclk_spdif_list[] = { + [0] = &clk_sclk_audio0.clk, + [1] = &clk_sclk_audio1.clk, + [2] = &clk_sclk_audio2.clk, +}; + +static struct clksrc_sources clkset_sclk_spdif = { + .sources = clkset_sclk_spdif_list, + .nr_sources = ARRAY_SIZE(clkset_sclk_spdif_list), +}; + static struct clksrc_clk clksrcs[] = { { .clk = { @@ -560,6 +673,15 @@ static struct clksrc_clk clksrcs[] = { }, .sources = &clkset_sclk_mixer, .reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 1 }, + }, { + .clk = { + .name = "sclk_spdif", + .id = -1, + .enable = s5pv210_clk_mask0_ctrl, + .ctrlbit = (1 << 27), + }, + .sources = &clkset_sclk_spdif, + .reg_src = { .reg = S5P_CLK_SRC6, .shift = 12, .size = 2 }, }, }; @@ -658,6 +780,9 @@ static struct clk *clks[] __initdata = { &clk_sclk_hdmiphy, &clk_sclk_usbphy0, &clk_sclk_usbphy1, + &clk_pcmcdclk0, + &clk_pcmcdclk1, + &clk_pcmcdclk2, }; void __init s5pv210_register_clocks(void) -- cgit v0.10.2 From f64cacc3194f49c7371e2ce61c22de62b8652dc7 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Mon, 17 May 2010 09:39:03 +0900 Subject: ARM: S5PV210: Add sclk clocks of type 'struct clksrc_clk' clock Add sclk clocks of type 'struct clksrc_clk' clock. The 'group2' of clock clock sources is also added. This patch also changes the the 'id' member value of the uclk1 clock for instance instance 0 since there are 4 instances of the uclk1 clock. Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c index 0154710..154bca4 100644 --- a/arch/arm/mach-s5pv210/clock.c +++ b/arch/arm/mach-s5pv210/clock.c @@ -173,6 +173,11 @@ static int s5pv210_clk_ip3_ctrl(struct clk *clk, int enable) return s5p_gatectrl(S5P_CLKGATE_IP3, clk, enable); } +static int s5pv210_clk_ip4_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P_CLKGATE_IP4, clk, enable); +} + static int s5pv210_clk_mask0_ctrl(struct clk *clk, int enable) { return s5p_gatectrl(S5P_CLK_SRC_MASK0, clk, enable); @@ -637,6 +642,23 @@ static struct clksrc_sources clkset_sclk_spdif = { .nr_sources = ARRAY_SIZE(clkset_sclk_spdif_list), }; +static struct clk *clkset_group2_list[] = { + [0] = &clk_ext_xtal_mux, + [1] = &clk_xusbxti, + [2] = &clk_sclk_hdmi27m, + [3] = &clk_sclk_usbphy0, + [4] = &clk_sclk_usbphy1, + [5] = &clk_sclk_hdmiphy, + [6] = &clk_mout_mpll.clk, + [7] = &clk_mout_epll.clk, + [8] = &clk_sclk_vpll.clk, +}; + +static struct clksrc_sources clkset_group2 = { + .sources = clkset_group2_list, + .nr_sources = ARRAY_SIZE(clkset_group2_list), +}; + static struct clksrc_clk clksrcs[] = { { .clk = { @@ -657,7 +679,7 @@ static struct clksrc_clk clksrcs[] = { }, { .clk = { .name = "uclk1", - .id = -1, + .id = 0, .ctrlbit = (1<<17), .enable = s5pv210_clk_ip3_ctrl, }, @@ -665,6 +687,36 @@ static struct clksrc_clk clksrcs[] = { .reg_src = { .reg = S5P_CLK_SRC4, .shift = 16, .size = 4 }, .reg_div = { .reg = S5P_CLK_DIV4, .shift = 16, .size = 4 }, }, { + .clk = { + .name = "uclk1", + .id = 1, + .enable = s5pv210_clk_ip3_ctrl, + .ctrlbit = (1 << 18), + }, + .sources = &clkset_uart, + .reg_src = { .reg = S5P_CLK_SRC4, .shift = 20, .size = 4 }, + .reg_div = { .reg = S5P_CLK_DIV4, .shift = 20, .size = 4 }, + }, { + .clk = { + .name = "uclk1", + .id = 2, + .enable = s5pv210_clk_ip3_ctrl, + .ctrlbit = (1 << 19), + }, + .sources = &clkset_uart, + .reg_src = { .reg = S5P_CLK_SRC4, .shift = 24, .size = 4 }, + .reg_div = { .reg = S5P_CLK_DIV4, .shift = 24, .size = 4 }, + }, { + .clk = { + .name = "uclk1", + .id = 3, + .enable = s5pv210_clk_ip3_ctrl, + .ctrlbit = (1 << 20), + }, + .sources = &clkset_uart, + .reg_src = { .reg = S5P_CLK_SRC4, .shift = 28, .size = 4 }, + .reg_div = { .reg = S5P_CLK_DIV4, .shift = 28, .size = 4 }, + }, { .clk = { .name = "sclk_mixer", .id = -1, @@ -682,6 +734,182 @@ static struct clksrc_clk clksrcs[] = { }, .sources = &clkset_sclk_spdif, .reg_src = { .reg = S5P_CLK_SRC6, .shift = 12, .size = 2 }, + }, { + .clk = { + .name = "sclk_fimc", + .id = 0, + .enable = s5pv210_clk_ip0_ctrl, + .ctrlbit = (1 << 24), + }, + .sources = &clkset_group2, + .reg_src = { .reg = S5P_CLK_SRC3, .shift = 12, .size = 4 }, + .reg_div = { .reg = S5P_CLK_DIV3, .shift = 12, .size = 4 }, + }, { + .clk = { + .name = "sclk_fimc", + .id = 1, + .enable = s5pv210_clk_ip0_ctrl, + .ctrlbit = (1 << 25), + }, + .sources = &clkset_group2, + .reg_src = { .reg = S5P_CLK_SRC3, .shift = 16, .size = 4 }, + .reg_div = { .reg = S5P_CLK_DIV3, .shift = 16, .size = 4 }, + }, { + .clk = { + .name = "sclk_fimc", + .id = 2, + .enable = s5pv210_clk_ip0_ctrl, + .ctrlbit = (1 << 26), + }, + .sources = &clkset_group2, + .reg_src = { .reg = S5P_CLK_SRC3, .shift = 20, .size = 4 }, + .reg_div = { .reg = S5P_CLK_DIV3, .shift = 20, .size = 4 }, + }, { + .clk = { + .name = "sclk_cam", + .id = 0, + }, + .sources = &clkset_group2, + .reg_src = { .reg = S5P_CLK_SRC1, .shift = 12, .size = 4 }, + .reg_div = { .reg = S5P_CLK_DIV1, .shift = 12, .size = 4 }, + }, { + .clk = { + .name = "sclk_cam", + .id = 1, + }, + .sources = &clkset_group2, + .reg_src = { .reg = S5P_CLK_SRC1, .shift = 16, .size = 4 }, + .reg_div = { .reg = S5P_CLK_DIV1, .shift = 16, .size = 4 }, + }, { + .clk = { + .name = "sclk_fimd", + .id = -1, + .enable = s5pv210_clk_ip1_ctrl, + .ctrlbit = (1 << 0), + }, + .sources = &clkset_group2, + .reg_src = { .reg = S5P_CLK_SRC1, .shift = 20, .size = 4 }, + .reg_div = { .reg = S5P_CLK_DIV1, .shift = 20, .size = 4 }, + }, { + .clk = { + .name = "sclk_mmc", + .id = 0, + .enable = s5pv210_clk_ip2_ctrl, + .ctrlbit = (1 << 16), + }, + .sources = &clkset_group2, + .reg_src = { .reg = S5P_CLK_SRC4, .shift = 0, .size = 4 }, + .reg_div = { .reg = S5P_CLK_DIV4, .shift = 0, .size = 4 }, + }, { + .clk = { + .name = "sclk_mmc", + .id = 1, + .enable = s5pv210_clk_ip2_ctrl, + .ctrlbit = (1 << 17), + }, + .sources = &clkset_group2, + .reg_src = { .reg = S5P_CLK_SRC4, .shift = 4, .size = 4 }, + .reg_div = { .reg = S5P_CLK_DIV4, .shift = 4, .size = 4 }, + }, { + .clk = { + .name = "sclk_mmc", + .id = 2, + .enable = s5pv210_clk_ip2_ctrl, + .ctrlbit = (1 << 18), + }, + .sources = &clkset_group2, + .reg_src = { .reg = S5P_CLK_SRC4, .shift = 8, .size = 4 }, + .reg_div = { .reg = S5P_CLK_DIV4, .shift = 8, .size = 4 }, + }, { + .clk = { + .name = "sclk_mmc", + .id = 3, + .enable = s5pv210_clk_ip2_ctrl, + .ctrlbit = (1 << 19), + }, + .sources = &clkset_group2, + .reg_src = { .reg = S5P_CLK_SRC4, .shift = 12, .size = 4 }, + .reg_div = { .reg = S5P_CLK_DIV4, .shift = 12, .size = 4 }, + }, { + .clk = { + .name = "sclk_mfc", + .id = -1, + .enable = s5pv210_clk_ip0_ctrl, + .ctrlbit = (1 << 16), + }, + .sources = &clkset_group1, + .reg_src = { .reg = S5P_CLK_SRC2, .shift = 4, .size = 2 }, + .reg_div = { .reg = S5P_CLK_DIV2, .shift = 4, .size = 4 }, + }, { + .clk = { + .name = "sclk_g2d", + .id = -1, + .enable = s5pv210_clk_ip0_ctrl, + .ctrlbit = (1 << 12), + }, + .sources = &clkset_group1, + .reg_src = { .reg = S5P_CLK_SRC2, .shift = 8, .size = 2 }, + .reg_div = { .reg = S5P_CLK_DIV2, .shift = 8, .size = 4 }, + }, { + .clk = { + .name = "sclk_g3d", + .id = -1, + .enable = s5pv210_clk_ip0_ctrl, + .ctrlbit = (1 << 8), + }, + .sources = &clkset_group1, + .reg_src = { .reg = S5P_CLK_SRC2, .shift = 0, .size = 2 }, + .reg_div = { .reg = S5P_CLK_DIV2, .shift = 0, .size = 4 }, + }, { + .clk = { + .name = "sclk_csis", + .id = -1, + .enable = s5pv210_clk_ip0_ctrl, + .ctrlbit = (1 << 31), + }, + .sources = &clkset_group2, + .reg_src = { .reg = S5P_CLK_SRC1, .shift = 24, .size = 4 }, + .reg_div = { .reg = S5P_CLK_DIV1, .shift = 28, .size = 4 }, + }, { + .clk = { + .name = "sclk_spi", + .id = 0, + .enable = s5pv210_clk_ip3_ctrl, + .ctrlbit = (1 << 12), + }, + .sources = &clkset_group2, + .reg_src = { .reg = S5P_CLK_SRC5, .shift = 0, .size = 4 }, + .reg_div = { .reg = S5P_CLK_DIV5, .shift = 0, .size = 4 }, + }, { + .clk = { + .name = "sclk_spi", + .id = 1, + .enable = s5pv210_clk_ip3_ctrl, + .ctrlbit = (1 << 13), + }, + .sources = &clkset_group2, + .reg_src = { .reg = S5P_CLK_SRC5, .shift = 4, .size = 4 }, + .reg_div = { .reg = S5P_CLK_DIV5, .shift = 4, .size = 4 }, + }, { + .clk = { + .name = "sclk_pwi", + .id = -1, + .enable = &s5pv210_clk_ip4_ctrl, + .ctrlbit = (1 << 2), + }, + .sources = &clkset_group2, + .reg_src = { .reg = S5P_CLK_SRC6, .shift = 20, .size = 4 }, + .reg_div = { .reg = S5P_CLK_DIV6, .shift = 24, .size = 4 }, + }, { + .clk = { + .name = "sclk_pwm", + .id = -1, + .enable = s5pv210_clk_ip3_ctrl, + .ctrlbit = (1 << 23), + }, + .sources = &clkset_group2, + .reg_src = { .reg = S5P_CLK_SRC5, .shift = 12, .size = 4 }, + .reg_div = { .reg = S5P_CLK_DIV5, .shift = 12, .size = 4 }, }, }; -- cgit v0.10.2 From e4af4268a34d8cd28c46a03161fc017cbd2db887 Mon Sep 17 00:00:00 2001 From: Jacob Pan Date: Fri, 14 May 2010 14:41:14 -0700 Subject: x86, mrst, pci: return 0 for non-present pci bars Moorestown PCI code has special handling of devices with fixed BARs. In case of BAR sizing writes, we need to update the fake PCI MMCFG space with real size decode value. When a BAR is not present, we need to return 0 instead of ~0. ~0 will be treated as device error per bugzilla 12006. Signed-off-by: Jacob Pan LKML-Reference: <1273873281-17489-2-git-send-email-jacob.jun.pan@linux.intel.com> Acked-by: Jesse Barnes Acked-by: Thomas Gleixner Signed-off-by: H. Peter Anvin diff --git a/arch/x86/pci/mrst.c b/arch/x86/pci/mrst.c index 8bf2fcb..d5c7aef 100644 --- a/arch/x86/pci/mrst.c +++ b/arch/x86/pci/mrst.c @@ -109,7 +109,7 @@ static int pci_device_update_fixed(struct pci_bus *bus, unsigned int devfn, decode++; decode = ~(decode - 1); } else { - decode = ~0; + decode = 0; } /* -- cgit v0.10.2 From fea24e28c663e62663097f0ed3b8ff1f9a87f15e Mon Sep 17 00:00:00 2001 From: Jacob Pan Date: Fri, 14 May 2010 14:41:20 -0700 Subject: x86, mrst: add nop functions to x86_init mpparse functions Moorestown does not have BIOS provided MP tables, we can save some time by avoiding scaning of these tables. e.g. [ 0.000000] Scan SMP from c0000000 for 1024 bytes. [ 0.000000] Scan SMP from c009fc00 for 1024 bytes. [ 0.000000] Scan SMP from c00f0000 for 65536 bytes. [ 0.000000] Scan SMP from c00bfff0 for 1024 bytes. Searching EBDA with the base at 0x40E will also result in random pointer deferencing within 1MB. This can be a problem in Lincroft if the pointer hits VGA area and VGA mode is not enabled. Signed-off-by: Jacob Pan LKML-Reference: <1273873281-17489-8-git-send-email-jacob.jun.pan@linux.intel.com> Acked-by: Thomas Gleixner Signed-off-by: H. Peter Anvin diff --git a/arch/x86/kernel/mrst.c b/arch/x86/kernel/mrst.c index 0aad867..e796448 100644 --- a/arch/x86/kernel/mrst.c +++ b/arch/x86/kernel/mrst.c @@ -237,4 +237,9 @@ void __init x86_mrst_early_setup(void) x86_init.pci.fixup_irqs = x86_init_noop; legacy_pic = &null_legacy_pic; + + /* Avoid searching for BIOS MP tables */ + x86_init.mpparse.find_smp_config = x86_init_noop; + x86_init.mpparse.get_smp_config = x86_init_uint_noop; + } -- cgit v0.10.2 From 14894b9b8317d9a337bba55998fdef1c9b2dc63d Mon Sep 17 00:00:00 2001 From: Jassi Brar Date: Mon, 17 May 2010 10:35:29 +0900 Subject: S3C: DMA: Change argument of s3c2410_dma_devconfig All other functions have the channel argument of type 'unsigned int' the s3c2410_dma_devconfig also accept the same value as argument but treat it as type 'int'. Remove this anomaly by make it 'unsigned int'. Signed-off-by: Jassi Brar Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c64xx/dma.c b/arch/arm/mach-s3c64xx/dma.c index 33ccf7b..5567e03 100644 --- a/arch/arm/mach-s3c64xx/dma.c +++ b/arch/arm/mach-s3c64xx/dma.c @@ -414,7 +414,7 @@ err_buff: EXPORT_SYMBOL(s3c2410_dma_enqueue); -int s3c2410_dma_devconfig(int channel, +int s3c2410_dma_devconfig(unsigned int channel, enum s3c2410_dmasrc source, unsigned long devaddr) { diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c index 93827b3..6ad274e 100644 --- a/arch/arm/plat-s3c24xx/dma.c +++ b/arch/arm/plat-s3c24xx/dma.c @@ -1104,7 +1104,7 @@ EXPORT_SYMBOL(s3c2410_dma_config); * devaddr: physical address of the source */ -int s3c2410_dma_devconfig(int channel, +int s3c2410_dma_devconfig(unsigned int channel, enum s3c2410_dmasrc source, unsigned long devaddr) { diff --git a/arch/arm/plat-samsung/include/plat/dma.h b/arch/arm/plat-samsung/include/plat/dma.h index 7584d75..2e8f8c6 100644 --- a/arch/arm/plat-samsung/include/plat/dma.h +++ b/arch/arm/plat-samsung/include/plat/dma.h @@ -110,8 +110,8 @@ extern int s3c2410_dma_config(unsigned int channel, int xferunit); * configure the device we're talking to */ -extern int s3c2410_dma_devconfig(int channel, enum s3c2410_dmasrc source, - unsigned long devaddr); +extern int s3c2410_dma_devconfig(unsigned int channel, + enum s3c2410_dmasrc source, unsigned long devaddr); /* s3c2410_dma_getposition * -- cgit v0.10.2 From 94038a99119c171aea27608f81c7ba359de98c4e Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Mon, 17 May 2010 10:00:00 +0200 Subject: [S390] More cleanup for struct _lowcore Remove cpu_id from lowcore and replace addr_t with __u64. Signed-off-by: Martin Schwidefsky diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index 05527c0..f7e78c7 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h @@ -126,16 +126,15 @@ struct _lowcore { __u32 user_exec_asce; /* 0x02ac */ /* SMP info area */ - struct cpuid cpu_id; /* 0x02b0 */ - __u32 cpu_nr; /* 0x02b8 */ - __u32 softirq_pending; /* 0x02bc */ - __u32 percpu_offset; /* 0x02c0 */ - __u32 ext_call_fast; /* 0x02c4 */ - __u64 int_clock; /* 0x02c8 */ - __u64 clock_comparator; /* 0x02d0 */ - __u32 machine_flags; /* 0x02d8 */ - __u32 ftrace_func; /* 0x02dc */ - __u8 pad_0x02e0[0x0300-0x02e0]; /* 0x02e0 */ + __u32 cpu_nr; /* 0x02b0 */ + __u32 softirq_pending; /* 0x02b4 */ + __u32 percpu_offset; /* 0x02b8 */ + __u32 ext_call_fast; /* 0x02bc */ + __u64 int_clock; /* 0x02c0 */ + __u64 clock_comparator; /* 0x02c8 */ + __u32 machine_flags; /* 0x02d0 */ + __u32 ftrace_func; /* 0x02d4 */ + __u8 pad_0x02d8[0x0300-0x02d8]; /* 0x02d8 */ /* Interrupt response block */ __u8 irb[64]; /* 0x0300 */ @@ -189,14 +188,14 @@ struct _lowcore { __u32 data_exc_code; /* 0x0090 */ __u16 mon_class_num; /* 0x0094 */ __u16 per_perc_atmid; /* 0x0096 */ - addr_t per_address; /* 0x0098 */ + __u64 per_address; /* 0x0098 */ __u8 exc_access_id; /* 0x00a0 */ __u8 per_access_id; /* 0x00a1 */ __u8 op_access_id; /* 0x00a2 */ __u8 ar_access_id; /* 0x00a3 */ __u8 pad_0x00a4[0x00a8-0x00a4]; /* 0x00a4 */ - addr_t trans_exc_code; /* 0x00a8 */ - addr_t monitor_code; /* 0x00b0 */ + __u64 trans_exc_code; /* 0x00a8 */ + __u64 monitor_code; /* 0x00b0 */ __u16 subchannel_id; /* 0x00b8 */ __u16 subchannel_nr; /* 0x00ba */ __u32 io_int_parm; /* 0x00bc */ @@ -207,7 +206,7 @@ struct _lowcore { __u32 mcck_interruption_code[2]; /* 0x00e8 */ __u8 pad_0x00f0[0x00f4-0x00f0]; /* 0x00f0 */ __u32 external_damage_code; /* 0x00f4 */ - addr_t failing_storage_address; /* 0x00f8 */ + __u64 failing_storage_address; /* 0x00f8 */ __u8 pad_0x0100[0x0110-0x0100]; /* 0x0100 */ __u64 breaking_event_addr; /* 0x0110 */ __u8 pad_0x0118[0x0120-0x0118]; /* 0x0118 */ @@ -255,17 +254,16 @@ struct _lowcore { __u64 user_exec_asce; /* 0x0318 */ /* SMP info area */ - struct cpuid cpu_id; /* 0x0320 */ - __u32 cpu_nr; /* 0x0328 */ - __u32 softirq_pending; /* 0x032c */ - __u64 percpu_offset; /* 0x0330 */ - __u64 ext_call_fast; /* 0x0338 */ - __u64 int_clock; /* 0x0340 */ - __u64 clock_comparator; /* 0x0348 */ - __u64 vdso_per_cpu_data; /* 0x0350 */ - __u64 machine_flags; /* 0x0358 */ - __u64 ftrace_func; /* 0x0360 */ - __u8 pad_0x0368[0x0380-0x0368]; /* 0x0368 */ + __u32 cpu_nr; /* 0x0320 */ + __u32 softirq_pending; /* 0x0324 */ + __u64 percpu_offset; /* 0x0328 */ + __u64 ext_call_fast; /* 0x0330 */ + __u64 int_clock; /* 0x0338 */ + __u64 clock_comparator; /* 0x0340 */ + __u64 vdso_per_cpu_data; /* 0x0348 */ + __u64 machine_flags; /* 0x0350 */ + __u64 ftrace_func; /* 0x0358 */ + __u8 pad_0x0368[0x0380-0x0360]; /* 0x0360 */ /* Interrupt response block. */ __u8 irb[64]; /* 0x0380 */ diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index a094089..32b1ede 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c @@ -126,7 +126,6 @@ int main(void) DEFINE(__LC_KERNEL_ASCE, offsetof(struct _lowcore, kernel_asce)); DEFINE(__LC_USER_ASCE, offsetof(struct _lowcore, user_asce)); DEFINE(__LC_USER_EXEC_ASCE, offsetof(struct _lowcore, user_exec_asce)); - DEFINE(__LC_CPUID, offsetof(struct _lowcore, cpu_id)); DEFINE(__LC_INT_CLOCK, offsetof(struct _lowcore, int_clock)); DEFINE(__LC_MACHINE_FLAGS, offsetof(struct _lowcore, machine_flags)); DEFINE(__LC_FTRACE_FUNC, offsetof(struct _lowcore, ftrace_func)); diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S index 9d1f767..51838ad 100644 --- a/arch/s390/kernel/head.S +++ b/arch/s390/kernel/head.S @@ -328,8 +328,8 @@ iplstart: # # reset files in VM reader # - stidp __LC_CPUID # store cpuid - tm __LC_CPUID,0xff # running VM ? + stidp __LC_SAVE_AREA # store cpuid + tm __LC_SAVE_AREA,0xff # running VM ? bno .Lnoreset la %r2,.Lreset lhi %r3,26 diff --git a/arch/s390/kernel/processor.c b/arch/s390/kernel/processor.c index 0729f36..ecb2d02 100644 --- a/arch/s390/kernel/processor.c +++ b/arch/s390/kernel/processor.c @@ -18,24 +18,42 @@ #include #include +static DEFINE_PER_CPU(struct cpuid, cpu_id); + +/* + * cpu_init - initializes state that is per-CPU. + */ +void __cpuinit cpu_init(void) +{ + struct cpuid *id = &per_cpu(cpu_id, smp_processor_id()); + + get_cpu_id(id); + atomic_inc(&init_mm.mm_count); + current->active_mm = &init_mm; + BUG_ON(current->mm); + enter_lazy_tlb(&init_mm, current); +} + +/* + * print_cpu_info - print basic information about a cpu + */ void __cpuinit print_cpu_info(void) { + struct cpuid *id = &per_cpu(cpu_id, smp_processor_id()); + pr_info("Processor %d started, address %d, identification %06X\n", - S390_lowcore.cpu_nr, S390_lowcore.cpu_addr, - S390_lowcore.cpu_id.ident); + S390_lowcore.cpu_nr, S390_lowcore.cpu_addr, id->ident); } /* * show_cpuinfo - Get information on one CPU for use by procfs. */ - static int show_cpuinfo(struct seq_file *m, void *v) { static const char *hwcap_str[10] = { "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp", "edat", "etf3eh", "highgprs" }; - struct _lowcore *lc; unsigned long n = (unsigned long) v - 1; int i; @@ -55,19 +73,12 @@ static int show_cpuinfo(struct seq_file *m, void *v) } if (cpu_online(n)) { -#ifdef CONFIG_SMP - lc = (smp_processor_id() == n) ? - &S390_lowcore : lowcore_ptr[n]; -#else - lc = &S390_lowcore; -#endif + struct cpuid *id = &per_cpu(cpu_id, n); seq_printf(m, "processor %li: " "version = %02X, " "identification = %06X, " "machine = %04X\n", - n, lc->cpu_id.version, - lc->cpu_id.ident, - lc->cpu_id.machine); + n, id->version, id->ident, id->machine); } preempt_enable(); return 0; diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 91625f7..6309276 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -113,22 +113,6 @@ static struct resource data_resource = { }; /* - * cpu_init() initializes state that is per-CPU. - */ -void __cpuinit cpu_init(void) -{ - /* - * Store processor id in lowcore (used e.g. in timer_interrupt) - */ - get_cpu_id(&S390_lowcore.cpu_id); - - atomic_inc(&init_mm.mm_count); - current->active_mm = &init_mm; - BUG_ON(current->mm); - enter_lazy_tlb(&init_mm, current); -} - -/* * condev= and conmode= setup parameter. */ @@ -695,6 +679,7 @@ static void __init setup_hwcaps(void) static const int stfl_bits[6] = { 0, 2, 7, 17, 19, 21 }; unsigned long long facility_list_extended; unsigned int facility_list; + struct cpuid cpu_id; int i; facility_list = stfl(); @@ -756,7 +741,8 @@ static void __init setup_hwcaps(void) */ elf_hwcap |= HWCAP_S390_HIGH_GPRS; - switch (S390_lowcore.cpu_id.machine) { + get_cpu_id(&cpu_id); + switch (cpu_id.machine) { case 0x9672: #if !defined(CONFIG_64BIT) default: /* Use "g5" as default for 31 bit kernels. */ diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 5116491..da6df04 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -648,6 +648,8 @@ static void css_process_crw(struct crw *crw0, struct crw *crw1, int overflow) static void __init css_generate_pgid(struct channel_subsystem *css, u32 tod_high) { + struct cpuid cpu_id; + if (css_general_characteristics.mcss) { css->global_pgid.pgid_high.ext_cssid.version = 0x80; css->global_pgid.pgid_high.ext_cssid.cssid = css->cssid; @@ -658,8 +660,9 @@ css_generate_pgid(struct channel_subsystem *css, u32 tod_high) css->global_pgid.pgid_high.cpu_addr = 0; #endif } - css->global_pgid.cpu_id = S390_lowcore.cpu_id.ident; - css->global_pgid.cpu_model = S390_lowcore.cpu_id.machine; + get_cpu_id(&cpu_id); + css->global_pgid.cpu_id = cpu_id.ident; + css->global_pgid.cpu_model = cpu_id.machine; css->global_pgid.tod_high = tod_high; } -- cgit v0.10.2 From 43d399d2ab7e96cb8d952d0ba4e9131587b7c8b9 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Mon, 17 May 2010 10:00:01 +0200 Subject: [S390] cleanup sysc_work and io_work code Cleanup the #ifdef mess at io_work in entry[64].S and streamline the TIF work code of the system call and io exit path. Signed-off-by: Martin Schwidefsky diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 6af7045..ffebfb6 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -301,31 +301,29 @@ sysc_restore_trace_psw: #endif # -# recheck if there is more work to do -# -sysc_work_loop: - tm __TI_flags+3(%r9),_TIF_WORK_SVC - bz BASED(sysc_restore) # there is no work to do -# -# One of the work bits is on. Find out which one. +# There is work to do, but first we need to check if we return to userspace. # sysc_work: tm SP_PSW+1(%r15),0x01 # returning to user ? bno BASED(sysc_restore) + +# +# One of the work bits is on. Find out which one. +# +sysc_work_loop: tm __TI_flags+3(%r9),_TIF_MCCK_PENDING bo BASED(sysc_mcck_pending) tm __TI_flags+3(%r9),_TIF_NEED_RESCHED bo BASED(sysc_reschedule) tm __TI_flags+3(%r9),_TIF_SIGPENDING - bnz BASED(sysc_sigpending) + bo BASED(sysc_sigpending) tm __TI_flags+3(%r9),_TIF_NOTIFY_RESUME - bnz BASED(sysc_notify_resume) + bo BASED(sysc_notify_resume) tm __TI_flags+3(%r9),_TIF_RESTART_SVC bo BASED(sysc_restart) tm __TI_flags+3(%r9),_TIF_SINGLE_STEP bo BASED(sysc_singlestep) - b BASED(sysc_restore) -sysc_work_done: + b BASED(sysc_return) # beware of critical section cleanup # # _TIF_NEED_RESCHED is set, call schedule @@ -386,7 +384,7 @@ sysc_singlestep: mvi SP_SVCNR+1(%r15),0xff la %r2,SP_PTREGS(%r15) # address of register-save area l %r1,BASED(.Lhandle_per) # load adr. of per handler - la %r14,BASED(sysc_return) # load adr. of system return + la %r14,BASED(sysc_work_loop) # load adr. of system return br %r1 # branch to do_single_step # @@ -636,30 +634,36 @@ io_restore_trace_psw: #endif # -# switch to kernel stack, then check the TIF bits +# There is work todo, find out in which context we have been interrupted: +# 1) if we return to user space we can do all _TIF_WORK_INT work +# 2) if we return to kernel code and preemptive scheduling is enabled check +# the preemption counter and if it is zero call preempt_schedule_irq +# Before any work can be done, a switch to the kernel stack is required. # io_work: tm SP_PSW+1(%r15),0x01 # returning to user ? -#ifndef CONFIG_PREEMPT - bno BASED(io_restore) # no-> skip resched & signal -#else - bnz BASED(io_work_user) # no -> check for preemptive scheduling + bo BASED(io_work_user) # yes -> do resched & signal +#ifdef CONFIG_PREEMPT # check for preemptive scheduling icm %r0,15,__TI_precount(%r9) bnz BASED(io_restore) # preemption disabled + # switch to kernel stack l %r1,SP_R15(%r15) s %r1,BASED(.Lc_spsize) mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain lr %r15,%r1 io_resume_loop: - tm __TI_flags+3(%r9),_TIF_NEED_RESCHED - bno BASED(io_restore) l %r1,BASED(.Lpreempt_schedule_irq) la %r14,BASED(io_resume_loop) - br %r1 # call schedule + tm __TI_flags+3(%r9),_TIF_NEED_RESCHED + bor %r1 # call preempt_schedule_irq #endif + b BASED(io_restore) +# +# Need to do work before returning to userspace, switch to kernel stack +# io_work_user: l %r1,__LC_KERNEL_STACK s %r1,BASED(.Lc_spsize) @@ -668,7 +672,7 @@ io_work_user: lr %r15,%r1 # # One of the work bits is on. Find out which one. -# Checked are: _TIF_SIGPENDING, _TIF_NEED_RESCHED +# Checked are: _TIF_SIGPENDING, _TIF_NOTIFY_RESUME, _TIF_NEED_RESCHED # and _TIF_MCCK_PENDING # io_work_loop: @@ -677,11 +681,10 @@ io_work_loop: tm __TI_flags+3(%r9),_TIF_NEED_RESCHED bo BASED(io_reschedule) tm __TI_flags+3(%r9),_TIF_SIGPENDING - bnz BASED(io_sigpending) + bo BASED(io_sigpending) tm __TI_flags+3(%r9),_TIF_NOTIFY_RESUME - bnz BASED(io_notify_resume) - b BASED(io_restore) -io_work_done: + bo BASED(io_notify_resume) + b BASED(io_return) # beware of critical section cleanup # # _TIF_MCCK_PENDING is set, call handler @@ -701,8 +704,6 @@ io_reschedule: basr %r14,%r1 # call scheduler stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts TRACE_IRQS_OFF - tm __TI_flags+3(%r9),_TIF_WORK_INT - bz BASED(io_restore) # there is no work to do b BASED(io_work_loop) # @@ -921,14 +922,10 @@ cleanup_table_sysc_return: .long sysc_return + 0x80000000, sysc_leave + 0x80000000 cleanup_table_sysc_leave: .long sysc_leave + 0x80000000, sysc_done + 0x80000000 -cleanup_table_sysc_work_loop: - .long sysc_work_loop + 0x80000000, sysc_work_done + 0x80000000 cleanup_table_io_return: .long io_return + 0x80000000, io_leave + 0x80000000 cleanup_table_io_leave: .long io_leave + 0x80000000, io_done + 0x80000000 -cleanup_table_io_work_loop: - .long io_work_loop + 0x80000000, io_work_done + 0x80000000 cleanup_critical: clc 4(4,%r12),BASED(cleanup_table_system_call) @@ -946,11 +943,6 @@ cleanup_critical: clc 4(4,%r12),BASED(cleanup_table_sysc_leave+4) bl BASED(cleanup_sysc_leave) 0: - clc 4(4,%r12),BASED(cleanup_table_sysc_work_loop) - bl BASED(0f) - clc 4(4,%r12),BASED(cleanup_table_sysc_work_loop+4) - bl BASED(cleanup_sysc_return) -0: clc 4(4,%r12),BASED(cleanup_table_io_return) bl BASED(0f) clc 4(4,%r12),BASED(cleanup_table_io_return+4) @@ -961,11 +953,6 @@ cleanup_critical: clc 4(4,%r12),BASED(cleanup_table_io_leave+4) bl BASED(cleanup_io_leave) 0: - clc 4(4,%r12),BASED(cleanup_table_io_work_loop) - bl BASED(0f) - clc 4(4,%r12),BASED(cleanup_table_io_work_loop+4) - bl BASED(cleanup_io_work_loop) -0: br %r14 cleanup_system_call: @@ -1043,12 +1030,6 @@ cleanup_io_return: la %r12,__LC_RETURN_PSW br %r14 -cleanup_io_work_loop: - mvc __LC_RETURN_PSW(4),0(%r12) - mvc __LC_RETURN_PSW+4(4),BASED(cleanup_table_io_work_loop) - la %r12,__LC_RETURN_PSW - br %r14 - cleanup_io_leave: clc 4(4,%r12),BASED(cleanup_io_leave_insn) be BASED(2f) diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 52106d5..ca02b10 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -291,38 +291,36 @@ sysc_restore_trace_psw: #endif # -# recheck if there is more work to do -# -sysc_work_loop: - tm __TI_flags+7(%r9),_TIF_WORK_SVC - jz sysc_restore # there is no work to do -# -# One of the work bits is on. Find out which one. +# There is work to do, but first we need to check if we return to userspace. # sysc_work: tm SP_PSW+1(%r15),0x01 # returning to user ? jno sysc_restore + +# +# One of the work bits is on. Find out which one. +# +sysc_work_loop: tm __TI_flags+7(%r9),_TIF_MCCK_PENDING jo sysc_mcck_pending tm __TI_flags+7(%r9),_TIF_NEED_RESCHED jo sysc_reschedule tm __TI_flags+7(%r9),_TIF_SIGPENDING - jnz sysc_sigpending + jo sysc_sigpending tm __TI_flags+7(%r9),_TIF_NOTIFY_RESUME - jnz sysc_notify_resume + jo sysc_notify_resume tm __TI_flags+7(%r9),_TIF_RESTART_SVC jo sysc_restart tm __TI_flags+7(%r9),_TIF_SINGLE_STEP jo sysc_singlestep - j sysc_restore -sysc_work_done: + j sysc_return # beware of critical section cleanup # # _TIF_NEED_RESCHED is set, call schedule # sysc_reschedule: larl %r14,sysc_work_loop - jg schedule # return point is sysc_return + jg schedule # return point is sysc_work_loop # # _TIF_MCCK_PENDING is set, call handler @@ -369,7 +367,7 @@ sysc_singlestep: ni __TI_flags+7(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number la %r2,SP_PTREGS(%r15) # address of register-save area - larl %r14,sysc_return # load adr. of system return + larl %r14,sysc_work_loop # load adr. of system return jg do_single_step # branch to do_sigtrap # @@ -605,37 +603,27 @@ io_restore_trace_psw: #endif # -# There is work todo, we need to check if we return to userspace, then -# check, if we are in SIE, if yes leave it +# There is work todo, find out in which context we have been interrupted: +# 1) if we return to user space we can do all _TIF_WORK_INT work +# 2) if we return to kernel code and kvm is enabled check if we need to +# modify the psw to leave SIE +# 3) if we return to kernel code and preemptive scheduling is enabled check +# the preemption counter and if it is zero call preempt_schedule_irq +# Before any work can be done, a switch to the kernel stack is required. # io_work: tm SP_PSW+1(%r15),0x01 # returning to user ? -#ifndef CONFIG_PREEMPT -#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) - jnz io_work_user # yes -> no need to check for SIE - la %r1, BASED(sie_opcode) # we return to kernel here - lg %r2, SP_PSW+8(%r15) - clc 0(2,%r1), 0(%r2) # is current instruction = SIE? - jne io_restore # no-> return to kernel - lg %r1, SP_PSW+8(%r15) # yes-> add 4 bytes to leave SIE - aghi %r1, 4 - stg %r1, SP_PSW+8(%r15) - j io_restore # return to kernel -#else - jno io_restore # no-> skip resched & signal -#endif -#else - jnz io_work_user # yes -> do resched & signal + jo io_work_user # yes -> do resched & signal #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) - la %r1, BASED(sie_opcode) - lg %r2, SP_PSW+8(%r15) - clc 0(2,%r1), 0(%r2) # is current instruction = SIE? + lg %r2,SP_PSW+8(%r15) # check if current instruction is SIE + lh %r1,0(%r2) + chi %r1,-19948 # signed 16 bit compare with 0xb214 jne 0f # no -> leave PSW alone - lg %r1, SP_PSW+8(%r15) # yes-> add 4 bytes to leave SIE - aghi %r1, 4 - stg %r1, SP_PSW+8(%r15) + aghi %r2,4 # yes-> add 4 bytes to leave SIE + stg %r2,SP_PSW+8(%r15) 0: #endif +#ifdef CONFIG_PREEMPT # check for preemptive scheduling icm %r0,15,__TI_precount(%r9) jnz io_restore # preemption is disabled @@ -646,21 +634,25 @@ io_work: xc __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain lgr %r15,%r1 io_resume_loop: - tm __TI_flags+7(%r9),_TIF_NEED_RESCHED - jno io_restore larl %r14,io_resume_loop - jg preempt_schedule_irq + tm __TI_flags+7(%r12),_TIF_NEED_RESCHED + jgo preempt_schedule_irq #endif + j io_restore +# +# Need to do work before returning to userspace, switch to kernel stack +# io_work_user: lg %r1,__LC_KERNEL_STACK aghi %r1,-SP_SIZE mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) xc __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain lgr %r15,%r1 + # # One of the work bits is on. Find out which one. -# Checked are: _TIF_SIGPENDING, _TIF_RESTORE_SIGPENDING, _TIF_NEED_RESCHED +# Checked are: _TIF_SIGPENDING, _TIF_NOTIFY_RESUME, _TIF_NEED_RESCHED # and _TIF_MCCK_PENDING # io_work_loop: @@ -669,16 +661,10 @@ io_work_loop: tm __TI_flags+7(%r9),_TIF_NEED_RESCHED jo io_reschedule tm __TI_flags+7(%r9),_TIF_SIGPENDING - jnz io_sigpending + jo io_sigpending tm __TI_flags+7(%r9),_TIF_NOTIFY_RESUME - jnz io_notify_resume - j io_restore -io_work_done: - -#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) -sie_opcode: - .long 0xb2140000 -#endif + jo io_notify_resume + j io_return # beware of critical section cleanup # # _TIF_MCCK_PENDING is set, call handler @@ -696,8 +682,6 @@ io_reschedule: brasl %r14,schedule # call scheduler stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts TRACE_IRQS_OFF - tm __TI_flags+7(%r9),_TIF_WORK_INT - jz io_restore # there is no work to do j io_work_loop # @@ -903,14 +887,10 @@ cleanup_table_sysc_return: .quad sysc_return, sysc_leave cleanup_table_sysc_leave: .quad sysc_leave, sysc_done -cleanup_table_sysc_work_loop: - .quad sysc_work_loop, sysc_work_done cleanup_table_io_return: .quad io_return, io_leave cleanup_table_io_leave: .quad io_leave, io_done -cleanup_table_io_work_loop: - .quad io_work_loop, io_work_done cleanup_critical: clc 8(8,%r12),BASED(cleanup_table_system_call) @@ -928,11 +908,6 @@ cleanup_critical: clc 8(8,%r12),BASED(cleanup_table_sysc_leave+8) jl cleanup_sysc_leave 0: - clc 8(8,%r12),BASED(cleanup_table_sysc_work_loop) - jl 0f - clc 8(8,%r12),BASED(cleanup_table_sysc_work_loop+8) - jl cleanup_sysc_return -0: clc 8(8,%r12),BASED(cleanup_table_io_return) jl 0f clc 8(8,%r12),BASED(cleanup_table_io_return+8) @@ -943,11 +918,6 @@ cleanup_critical: clc 8(8,%r12),BASED(cleanup_table_io_leave+8) jl cleanup_io_leave 0: - clc 8(8,%r12),BASED(cleanup_table_io_work_loop) - jl 0f - clc 8(8,%r12),BASED(cleanup_table_io_work_loop+8) - jl cleanup_io_work_loop -0: br %r14 cleanup_system_call: @@ -1025,12 +995,6 @@ cleanup_io_return: la %r12,__LC_RETURN_PSW br %r14 -cleanup_io_work_loop: - mvc __LC_RETURN_PSW(8),0(%r12) - mvc __LC_RETURN_PSW+8(8),BASED(cleanup_table_io_work_loop) - la %r12,__LC_RETURN_PSW - br %r14 - cleanup_io_leave: clc 8(8,%r12),BASED(cleanup_io_leave_insn) je 3f -- cgit v0.10.2 From 6a2df3a87276cdc08fd87070d09ea18d1fb9d622 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Mon, 17 May 2010 10:00:02 +0200 Subject: [S390] improve irq tracing code in entry[64].S The system call path in entry[64].S is run with interrupts enabled. Remove the irq tracing check from the system call exit code. If a program check interrupted a context enabled for interrupts do a call to trace_irq_off_caller in the program check handler before branching to the system call exit code. Restructure the system call and io interrupt return code to avoid avoid the lpsw[e] to disable machine checks. Signed-off-by: Martin Schwidefsky diff --git a/arch/s390/include/asm/system.h b/arch/s390/include/asm/system.h index 1741c15..cef6621 100644 --- a/arch/s390/include/asm/system.h +++ b/arch/s390/include/asm/system.h @@ -459,11 +459,6 @@ extern void (*_machine_power_off)(void); #define arch_align_stack(x) (x) -#ifdef CONFIG_TRACE_IRQFLAGS -extern psw_t sysc_restore_trace_psw; -extern psw_t io_restore_trace_psw; -#endif - static inline int tprot(unsigned long addr) { int rc = -EFAULT; diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index ffebfb6..07d8499 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -73,21 +73,24 @@ STACK_SIZE = 1 << STACK_SHIFT basr %r14,%r1 .endm - .macro TRACE_IRQS_CHECK - basr %r2,%r0 + .macro TRACE_IRQS_CHECK_ON tm SP_PSW(%r15),0x03 # irqs enabled? - jz 0f - l %r1,BASED(.Ltrace_irq_on_caller) - basr %r14,%r1 - j 1f -0: l %r1,BASED(.Ltrace_irq_off_caller) - basr %r14,%r1 -1: + bz BASED(0f) + TRACE_IRQS_ON +0: + .endm + + .macro TRACE_IRQS_CHECK_OFF + tm SP_PSW(%r15),0x03 # irqs enabled? + bz BASED(0f) + TRACE_IRQS_OFF +0: .endm #else #define TRACE_IRQS_ON #define TRACE_IRQS_OFF -#define TRACE_IRQS_CHECK +#define TRACE_IRQS_CHECK_ON +#define TRACE_IRQS_CHECK_OFF #endif #ifdef CONFIG_LOCKDEP @@ -273,33 +276,14 @@ sysc_do_restart: st %r2,SP_R2(%r15) # store return value (change R2 on stack) sysc_return: + LOCKDEP_SYS_EXIT +sysc_tif: tm __TI_flags+3(%r9),_TIF_WORK_SVC bnz BASED(sysc_work) # there is work to do (signals etc.) sysc_restore: -#ifdef CONFIG_TRACE_IRQFLAGS - la %r1,BASED(sysc_restore_trace_psw_addr) - l %r1,0(%r1) - lpsw 0(%r1) -sysc_restore_trace: - TRACE_IRQS_CHECK - LOCKDEP_SYS_EXIT -#endif -sysc_leave: RESTORE_ALL __LC_RETURN_PSW,1 sysc_done: -#ifdef CONFIG_TRACE_IRQFLAGS -sysc_restore_trace_psw_addr: - .long sysc_restore_trace_psw - - .section .data,"aw",@progbits - .align 8 - .globl sysc_restore_trace_psw -sysc_restore_trace_psw: - .long 0, sysc_restore_trace + 0x80000000 - .previous -#endif - # # There is work to do, but first we need to check if we return to userspace. # @@ -310,7 +294,7 @@ sysc_work: # # One of the work bits is on. Find out which one. # -sysc_work_loop: +sysc_work_tif: tm __TI_flags+3(%r9),_TIF_MCCK_PENDING bo BASED(sysc_mcck_pending) tm __TI_flags+3(%r9),_TIF_NEED_RESCHED @@ -330,7 +314,7 @@ sysc_work_loop: # sysc_reschedule: l %r1,BASED(.Lschedule) - la %r14,BASED(sysc_work_loop) + la %r14,BASED(sysc_return) br %r1 # call scheduler # @@ -338,7 +322,7 @@ sysc_reschedule: # sysc_mcck_pending: l %r1,BASED(.Ls390_handle_mcck) - la %r14,BASED(sysc_work_loop) + la %r14,BASED(sysc_return) br %r1 # TIF bit will be cleared by handler # @@ -353,7 +337,7 @@ sysc_sigpending: bo BASED(sysc_restart) tm __TI_flags+3(%r9),_TIF_SINGLE_STEP bo BASED(sysc_singlestep) - b BASED(sysc_work_loop) + b BASED(sysc_return) # # _TIF_NOTIFY_RESUME is set, call do_notify_resume @@ -361,7 +345,7 @@ sysc_sigpending: sysc_notify_resume: la %r2,SP_PTREGS(%r15) # load pt_regs l %r1,BASED(.Ldo_notify_resume) - la %r14,BASED(sysc_work_loop) + la %r14,BASED(sysc_return) br %r1 # call do_notify_resume @@ -384,7 +368,7 @@ sysc_singlestep: mvi SP_SVCNR+1(%r15),0xff la %r2,SP_PTREGS(%r15) # address of register-save area l %r1,BASED(.Lhandle_per) # load adr. of per handler - la %r14,BASED(sysc_work_loop) # load adr. of system return + la %r14,BASED(sysc_return) # load adr. of system return br %r1 # branch to do_single_step # @@ -456,11 +440,13 @@ kernel_execve: br %r14 # execve succeeded. 0: stnsm __SF_EMPTY(%r15),0xfc # disable interrupts + TRACE_IRQS_OFF l %r15,__LC_KERNEL_STACK # load ksp s %r15,BASED(.Lc_spsize) # make room for registers & psw l %r9,__LC_THREAD_INFO mvc SP_PTREGS(__PT_SIZE,%r15),0(%r12) # copy pt_regs xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) + TRACE_IRQS_ON stosm __SF_EMPTY(%r15),0x03 # reenable interrupts l %r1,BASED(.Lexecve_tail) basr %r14,%r1 @@ -497,8 +483,8 @@ pgm_check_handler: UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER pgm_no_vtime: + TRACE_IRQS_CHECK_OFF l %r9,__LC_THREAD_INFO # load pointer to thread_info struct - TRACE_IRQS_OFF l %r3,__LC_PGM_ILC # load program interruption code la %r8,0x7f nr %r8,%r3 @@ -507,8 +493,10 @@ pgm_do_call: sll %r8,2 l %r7,0(%r8,%r7) # load address of handler routine la %r2,SP_PTREGS(%r15) # address of register-save area - la %r14,BASED(sysc_return) - br %r7 # branch to interrupt-handler + basr %r14,%r7 # branch to interrupt-handler +pgm_exit: + TRACE_IRQS_CHECK_ON + b BASED(sysc_return) # # handle per exception @@ -535,19 +523,19 @@ pgm_per_std: UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER pgm_no_vtime2: + TRACE_IRQS_CHECK_OFF l %r9,__LC_THREAD_INFO # load pointer to thread_info struct - TRACE_IRQS_OFF l %r1,__TI_task(%r9) + tm SP_PSW+1(%r15),0x01 # kernel per event ? + bz BASED(kernel_per) mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID mvc __THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID oi __TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP - tm SP_PSW+1(%r15),0x01 # kernel per event ? - bz BASED(kernel_per) l %r3,__LC_PGM_ILC # load program interruption code la %r8,0x7f nr %r8,%r3 # clear per-event-bit and ilc - be BASED(sysc_return) # only per or per+check ? + be BASED(pgm_exit) # only per or per+check ? b BASED(pgm_do_call) # @@ -568,8 +556,8 @@ pgm_svcper: mvc __THREAD_per+__PER_access_id(1,%r8),__LC_PER_ACCESS_ID oi __TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP TRACE_IRQS_ON - lm %r2,%r6,SP_R2(%r15) # load svc arguments stosm __SF_EMPTY(%r15),0x03 # reenable interrupts + lm %r2,%r6,SP_R2(%r15) # load svc arguments b BASED(sysc_do_svc) # @@ -580,8 +568,8 @@ kernel_per: mvi SP_SVCNR+1(%r15),0xff la %r2,SP_PTREGS(%r15) # address of register-save area l %r1,BASED(.Lhandle_per) # load adr. of per handler - la %r14,BASED(sysc_restore)# load adr. of system return - br %r1 # branch to do_single_step + basr %r14,%r1 # branch to do_single_step + b BASED(pgm_exit) /* * IO interrupt handler routine @@ -600,39 +588,21 @@ io_int_handler: UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER io_no_vtime: - l %r9,__LC_THREAD_INFO # load pointer to thread_info struct TRACE_IRQS_OFF + l %r9,__LC_THREAD_INFO # load pointer to thread_info struct l %r1,BASED(.Ldo_IRQ) # load address of do_IRQ la %r2,SP_PTREGS(%r15) # address of register-save area basr %r14,%r1 # branch to standard irq handler io_return: + LOCKDEP_SYS_EXIT + TRACE_IRQS_ON +io_tif: tm __TI_flags+3(%r9),_TIF_WORK_INT bnz BASED(io_work) # there is work to do (signals etc.) io_restore: -#ifdef CONFIG_TRACE_IRQFLAGS - la %r1,BASED(io_restore_trace_psw_addr) - l %r1,0(%r1) - lpsw 0(%r1) -io_restore_trace: - TRACE_IRQS_CHECK - LOCKDEP_SYS_EXIT -#endif -io_leave: RESTORE_ALL __LC_RETURN_PSW,0 io_done: -#ifdef CONFIG_TRACE_IRQFLAGS -io_restore_trace_psw_addr: - .long io_restore_trace_psw - - .section .data,"aw",@progbits - .align 8 - .globl io_restore_trace_psw -io_restore_trace_psw: - .long 0, io_restore_trace + 0x80000000 - .previous -#endif - # # There is work todo, find out in which context we have been interrupted: # 1) if we return to user space we can do all _TIF_WORK_INT work @@ -647,19 +617,23 @@ io_work: # check for preemptive scheduling icm %r0,15,__TI_precount(%r9) bnz BASED(io_restore) # preemption disabled + tm __TI_flags+3(%r9),_TIF_NEED_RESCHED + bno BASED(io_restore) # switch to kernel stack l %r1,SP_R15(%r15) s %r1,BASED(.Lc_spsize) mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain lr %r15,%r1 -io_resume_loop: + # TRACE_IRQS_ON already done at io_return, call + # TRACE_IRQS_OFF to keep things symmetrical + TRACE_IRQS_OFF l %r1,BASED(.Lpreempt_schedule_irq) - la %r14,BASED(io_resume_loop) - tm __TI_flags+3(%r9),_TIF_NEED_RESCHED - bor %r1 # call preempt_schedule_irq -#endif + basr %r14,%r1 # call preempt_schedule_irq + b BASED(io_return) +#else b BASED(io_restore) +#endif # # Need to do work before returning to userspace, switch to kernel stack @@ -670,12 +644,13 @@ io_work_user: mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain lr %r15,%r1 + # # One of the work bits is on. Find out which one. # Checked are: _TIF_SIGPENDING, _TIF_NOTIFY_RESUME, _TIF_NEED_RESCHED # and _TIF_MCCK_PENDING # -io_work_loop: +io_work_tif: tm __TI_flags+3(%r9),_TIF_MCCK_PENDING bo BASED(io_mcck_pending) tm __TI_flags+3(%r9),_TIF_NEED_RESCHED @@ -690,47 +665,49 @@ io_work_loop: # _TIF_MCCK_PENDING is set, call handler # io_mcck_pending: + # TRACE_IRQS_ON already done at io_return l %r1,BASED(.Ls390_handle_mcck) basr %r14,%r1 # TIF bit will be cleared by handler - b BASED(io_work_loop) + TRACE_IRQS_OFF + b BASED(io_return) # # _TIF_NEED_RESCHED is set, call schedule # io_reschedule: - TRACE_IRQS_ON + # TRACE_IRQS_ON already done at io_return l %r1,BASED(.Lschedule) stosm __SF_EMPTY(%r15),0x03 # reenable interrupts basr %r14,%r1 # call scheduler stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts TRACE_IRQS_OFF - b BASED(io_work_loop) + b BASED(io_return) # # _TIF_SIGPENDING is set, call do_signal # io_sigpending: - TRACE_IRQS_ON + # TRACE_IRQS_ON already done at io_return stosm __SF_EMPTY(%r15),0x03 # reenable interrupts la %r2,SP_PTREGS(%r15) # load pt_regs l %r1,BASED(.Ldo_signal) basr %r14,%r1 # call do_signal stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts TRACE_IRQS_OFF - b BASED(io_work_loop) + b BASED(io_return) # # _TIF_SIGPENDING is set, call do_signal # io_notify_resume: - TRACE_IRQS_ON + # TRACE_IRQS_ON already done at io_return stosm __SF_EMPTY(%r15),0x03 # reenable interrupts la %r2,SP_PTREGS(%r15) # load pt_regs l %r1,BASED(.Ldo_notify_resume) basr %r14,%r1 # call do_signal stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts TRACE_IRQS_OFF - b BASED(io_work_loop) + b BASED(io_return) /* * External interrupt handler routine @@ -918,14 +895,14 @@ stack_overflow: cleanup_table_system_call: .long system_call + 0x80000000, sysc_do_svc + 0x80000000 -cleanup_table_sysc_return: - .long sysc_return + 0x80000000, sysc_leave + 0x80000000 -cleanup_table_sysc_leave: - .long sysc_leave + 0x80000000, sysc_done + 0x80000000 -cleanup_table_io_return: - .long io_return + 0x80000000, io_leave + 0x80000000 -cleanup_table_io_leave: - .long io_leave + 0x80000000, io_done + 0x80000000 +cleanup_table_sysc_tif: + .long sysc_tif + 0x80000000, sysc_restore + 0x80000000 +cleanup_table_sysc_restore: + .long sysc_restore + 0x80000000, sysc_done + 0x80000000 +cleanup_table_io_tif: + .long io_tif + 0x80000000, io_restore + 0x80000000 +cleanup_table_io_restore: + .long io_restore + 0x80000000, io_done + 0x80000000 cleanup_critical: clc 4(4,%r12),BASED(cleanup_table_system_call) @@ -933,25 +910,25 @@ cleanup_critical: clc 4(4,%r12),BASED(cleanup_table_system_call+4) bl BASED(cleanup_system_call) 0: - clc 4(4,%r12),BASED(cleanup_table_sysc_return) + clc 4(4,%r12),BASED(cleanup_table_sysc_tif) bl BASED(0f) - clc 4(4,%r12),BASED(cleanup_table_sysc_return+4) - bl BASED(cleanup_sysc_return) + clc 4(4,%r12),BASED(cleanup_table_sysc_tif+4) + bl BASED(cleanup_sysc_tif) 0: - clc 4(4,%r12),BASED(cleanup_table_sysc_leave) + clc 4(4,%r12),BASED(cleanup_table_sysc_restore) bl BASED(0f) - clc 4(4,%r12),BASED(cleanup_table_sysc_leave+4) - bl BASED(cleanup_sysc_leave) + clc 4(4,%r12),BASED(cleanup_table_sysc_restore+4) + bl BASED(cleanup_sysc_restore) 0: - clc 4(4,%r12),BASED(cleanup_table_io_return) + clc 4(4,%r12),BASED(cleanup_table_io_tif) bl BASED(0f) - clc 4(4,%r12),BASED(cleanup_table_io_return+4) - bl BASED(cleanup_io_return) + clc 4(4,%r12),BASED(cleanup_table_io_tif+4) + bl BASED(cleanup_io_tif) 0: - clc 4(4,%r12),BASED(cleanup_table_io_leave) + clc 4(4,%r12),BASED(cleanup_table_io_restore) bl BASED(0f) - clc 4(4,%r12),BASED(cleanup_table_io_leave+4) - bl BASED(cleanup_io_leave) + clc 4(4,%r12),BASED(cleanup_table_io_restore+4) + bl BASED(cleanup_io_restore) 0: br %r14 @@ -998,17 +975,17 @@ cleanup_system_call_insn: .long sysc_stime + 0x80000000 .long sysc_update + 0x80000000 -cleanup_sysc_return: +cleanup_sysc_tif: mvc __LC_RETURN_PSW(4),0(%r12) - mvc __LC_RETURN_PSW+4(4),BASED(cleanup_table_sysc_return) + mvc __LC_RETURN_PSW+4(4),BASED(cleanup_table_sysc_tif) la %r12,__LC_RETURN_PSW br %r14 -cleanup_sysc_leave: - clc 4(4,%r12),BASED(cleanup_sysc_leave_insn) +cleanup_sysc_restore: + clc 4(4,%r12),BASED(cleanup_sysc_restore_insn) be BASED(2f) mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER - clc 4(4,%r12),BASED(cleanup_sysc_leave_insn+4) + clc 4(4,%r12),BASED(cleanup_sysc_restore_insn+4) be BASED(2f) mvc __LC_RETURN_PSW(8),SP_PSW(%r15) c %r12,BASED(.Lmck_old_psw) @@ -1020,21 +997,21 @@ cleanup_sysc_leave: l %r15,SP_R15(%r15) 2: la %r12,__LC_RETURN_PSW br %r14 -cleanup_sysc_leave_insn: +cleanup_sysc_restore_insn: .long sysc_done - 4 + 0x80000000 .long sysc_done - 8 + 0x80000000 -cleanup_io_return: +cleanup_io_tif: mvc __LC_RETURN_PSW(4),0(%r12) - mvc __LC_RETURN_PSW+4(4),BASED(cleanup_table_io_return) + mvc __LC_RETURN_PSW+4(4),BASED(cleanup_table_io_tif) la %r12,__LC_RETURN_PSW br %r14 -cleanup_io_leave: - clc 4(4,%r12),BASED(cleanup_io_leave_insn) +cleanup_io_restore: + clc 4(4,%r12),BASED(cleanup_io_restore_insn) be BASED(2f) mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER - clc 4(4,%r12),BASED(cleanup_io_leave_insn+4) + clc 4(4,%r12),BASED(cleanup_io_restore_insn+4) be BASED(2f) mvc __LC_RETURN_PSW(8),SP_PSW(%r15) c %r12,BASED(.Lmck_old_psw) @@ -1046,7 +1023,7 @@ cleanup_io_leave: l %r15,SP_R15(%r15) 2: la %r12,__LC_RETURN_PSW br %r14 -cleanup_io_leave_insn: +cleanup_io_restore_insn: .long io_done - 4 + 0x80000000 .long io_done - 8 + 0x80000000 diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index ca02b10..860cea1 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -61,28 +61,33 @@ _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \ #ifdef CONFIG_TRACE_IRQFLAGS .macro TRACE_IRQS_ON - basr %r2,%r0 - brasl %r14,trace_hardirqs_on_caller + basr %r2,%r0 + brasl %r14,trace_hardirqs_on_caller .endm .macro TRACE_IRQS_OFF - basr %r2,%r0 - brasl %r14,trace_hardirqs_off_caller + basr %r2,%r0 + brasl %r14,trace_hardirqs_off_caller .endm - .macro TRACE_IRQS_CHECK - basr %r2,%r0 + .macro TRACE_IRQS_CHECK_ON tm SP_PSW(%r15),0x03 # irqs enabled? jz 0f - brasl %r14,trace_hardirqs_on_caller - j 1f -0: brasl %r14,trace_hardirqs_off_caller -1: + TRACE_IRQS_ON +0: + .endm + + .macro TRACE_IRQS_CHECK_OFF + tm SP_PSW(%r15),0x03 # irqs enabled? + jz 0f + TRACE_IRQS_OFF +0: .endm #else #define TRACE_IRQS_ON #define TRACE_IRQS_OFF -#define TRACE_IRQS_CHECK +#define TRACE_IRQS_CHECK_ON +#define TRACE_IRQS_CHECK_OFF #endif #ifdef CONFIG_LOCKDEP @@ -267,29 +272,14 @@ sysc_noemu: stg %r2,SP_R2(%r15) # store return value (change R2 on stack) sysc_return: + LOCKDEP_SYS_EXIT +sysc_tif: tm __TI_flags+7(%r9),_TIF_WORK_SVC jnz sysc_work # there is work to do (signals etc.) sysc_restore: -#ifdef CONFIG_TRACE_IRQFLAGS - larl %r1,sysc_restore_trace_psw - lpswe 0(%r1) -sysc_restore_trace: - TRACE_IRQS_CHECK - LOCKDEP_SYS_EXIT -#endif -sysc_leave: RESTORE_ALL __LC_RETURN_PSW,1 sysc_done: -#ifdef CONFIG_TRACE_IRQFLAGS - .section .data,"aw",@progbits - .align 8 - .globl sysc_restore_trace_psw -sysc_restore_trace_psw: - .quad 0, sysc_restore_trace - .previous -#endif - # # There is work to do, but first we need to check if we return to userspace. # @@ -300,7 +290,7 @@ sysc_work: # # One of the work bits is on. Find out which one. # -sysc_work_loop: +sysc_work_tif: tm __TI_flags+7(%r9),_TIF_MCCK_PENDING jo sysc_mcck_pending tm __TI_flags+7(%r9),_TIF_NEED_RESCHED @@ -319,14 +309,14 @@ sysc_work_loop: # _TIF_NEED_RESCHED is set, call schedule # sysc_reschedule: - larl %r14,sysc_work_loop - jg schedule # return point is sysc_work_loop + larl %r14,sysc_return + jg schedule # return point is sysc_return # # _TIF_MCCK_PENDING is set, call handler # sysc_mcck_pending: - larl %r14,sysc_work_loop + larl %r14,sysc_return jg s390_handle_mcck # TIF bit will be cleared by handler # @@ -340,14 +330,14 @@ sysc_sigpending: jo sysc_restart tm __TI_flags+7(%r9),_TIF_SINGLE_STEP jo sysc_singlestep - j sysc_work_loop + j sysc_return # # _TIF_NOTIFY_RESUME is set, call do_notify_resume # sysc_notify_resume: la %r2,SP_PTREGS(%r15) # load pt_regs - larl %r14,sysc_work_loop + larl %r14,sysc_return jg do_notify_resume # call do_notify_resume # @@ -367,7 +357,7 @@ sysc_singlestep: ni __TI_flags+7(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number la %r2,SP_PTREGS(%r15) # address of register-save area - larl %r14,sysc_work_loop # load adr. of system return + larl %r14,sysc_return # load adr. of system return jg do_single_step # branch to do_sigtrap # @@ -433,12 +423,14 @@ kernel_execve: br %r14 # execve succeeded. 0: stnsm __SF_EMPTY(%r15),0xfc # disable interrupts +# TRACE_IRQS_OFF lg %r15,__LC_KERNEL_STACK # load ksp aghi %r15,-SP_SIZE # make room for registers & psw lg %r13,__LC_SVC_NEW_PSW+8 lg %r9,__LC_THREAD_INFO mvc SP_PTREGS(__PT_SIZE,%r15),0(%r12) # copy pt_regs xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) +# TRACE_IRQS_ON stosm __SF_EMPTY(%r15),0x03 # reenable interrupts brasl %r14,execve_tail j sysc_return @@ -474,9 +466,9 @@ pgm_check_handler: UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER pgm_no_vtime: + TRACE_IRQS_CHECK_OFF lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct mvc SP_ARGS(8,%r15),__LC_LAST_BREAK - TRACE_IRQS_OFF lgf %r3,__LC_PGM_ILC # load program interruption code lghi %r8,0x7f ngr %r8,%r3 @@ -485,8 +477,10 @@ pgm_do_call: larl %r1,pgm_check_table lg %r1,0(%r8,%r1) # load address of handler routine la %r2,SP_PTREGS(%r15) # address of register-save area - larl %r14,sysc_return - br %r1 # branch to interrupt-handler + basr %r14,%r1 # branch to interrupt-handler +pgm_exit: + TRACE_IRQS_CHECK_ON + j sysc_return # # handle per exception @@ -513,8 +507,8 @@ pgm_per_std: UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER pgm_no_vtime2: + TRACE_IRQS_CHECK_OFF lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct - TRACE_IRQS_OFF lg %r1,__TI_task(%r9) tm SP_PSW+1(%r15),0x01 # kernel per event ? jz kernel_per @@ -525,7 +519,7 @@ pgm_no_vtime2: lgf %r3,__LC_PGM_ILC # load program interruption code lghi %r8,0x7f ngr %r8,%r3 # clear per-event-bit and ilc - je sysc_return + je pgm_exit j pgm_do_call # @@ -539,14 +533,15 @@ pgm_svcper: mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct + TRACE_IRQS_OFF lg %r8,__TI_task(%r9) mvc __THREAD_per+__PER_atmid(2,%r8),__LC_PER_ATMID mvc __THREAD_per+__PER_address(8,%r8),__LC_PER_ADDRESS mvc __THREAD_per+__PER_access_id(1,%r8),__LC_PER_ACCESS_ID oi __TI_flags+7(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP TRACE_IRQS_ON - lmg %r2,%r6,SP_R2(%r15) # load svc arguments stosm __SF_EMPTY(%r15),0x03 # reenable interrupts + lmg %r2,%r6,SP_R2(%r15) # load svc arguments j sysc_do_svc # @@ -555,8 +550,8 @@ pgm_svcper: kernel_per: xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number la %r2,SP_PTREGS(%r15) # address of register-save area - larl %r14,sysc_restore # load adr. of system ret, no work - jg do_single_step # branch to do_single_step + brasl %r14,do_single_step + j pgm_exit /* * IO interrupt handler routine @@ -579,29 +574,15 @@ io_no_vtime: la %r2,SP_PTREGS(%r15) # address of register-save area brasl %r14,do_IRQ # call standard irq handler io_return: + LOCKDEP_SYS_EXIT + TRACE_IRQS_ON +io_tif: tm __TI_flags+7(%r9),_TIF_WORK_INT jnz io_work # there is work to do (signals etc.) io_restore: -#ifdef CONFIG_TRACE_IRQFLAGS - larl %r1,io_restore_trace_psw - lpswe 0(%r1) -io_restore_trace: - TRACE_IRQS_CHECK - LOCKDEP_SYS_EXIT -#endif -io_leave: RESTORE_ALL __LC_RETURN_PSW,0 io_done: -#ifdef CONFIG_TRACE_IRQFLAGS - .section .data,"aw",@progbits - .align 8 - .globl io_restore_trace_psw -io_restore_trace_psw: - .quad 0, io_restore_trace - .previous -#endif - # # There is work todo, find out in which context we have been interrupted: # 1) if we return to user space we can do all _TIF_WORK_INT work @@ -627,18 +608,22 @@ io_work: # check for preemptive scheduling icm %r0,15,__TI_precount(%r9) jnz io_restore # preemption is disabled + tm __TI_flags+7(%r12),_TIF_NEED_RESCHED + jno io_restore # switch to kernel stack lg %r1,SP_R15(%r15) aghi %r1,-SP_SIZE mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15) xc __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain lgr %r15,%r1 -io_resume_loop: - larl %r14,io_resume_loop - tm __TI_flags+7(%r12),_TIF_NEED_RESCHED - jgo preempt_schedule_irq -#endif + # TRACE_IRQS_ON already done at io_return, call + # TRACE_IRQS_OFF to keep things symmetrical + TRACE_IRQS_OFF + brasl %r14,preempt_schedule_irq + j io_return +#else j io_restore +#endif # # Need to do work before returning to userspace, switch to kernel stack @@ -655,7 +640,7 @@ io_work_user: # Checked are: _TIF_SIGPENDING, _TIF_NOTIFY_RESUME, _TIF_NEED_RESCHED # and _TIF_MCCK_PENDING # -io_work_loop: +io_work_tif: tm __TI_flags+7(%r9),_TIF_MCCK_PENDING jo io_mcck_pending tm __TI_flags+7(%r9),_TIF_NEED_RESCHED @@ -670,43 +655,45 @@ io_work_loop: # _TIF_MCCK_PENDING is set, call handler # io_mcck_pending: + # TRACE_IRQS_ON already done at io_return brasl %r14,s390_handle_mcck # TIF bit will be cleared by handler - j io_work_loop + TRACE_IRQS_OFF + j io_return # # _TIF_NEED_RESCHED is set, call schedule # io_reschedule: - TRACE_IRQS_ON + # TRACE_IRQS_ON already done at io_return stosm __SF_EMPTY(%r15),0x03 # reenable interrupts brasl %r14,schedule # call scheduler stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts TRACE_IRQS_OFF - j io_work_loop + j io_return # # _TIF_SIGPENDING or is set, call do_signal # io_sigpending: - TRACE_IRQS_ON + # TRACE_IRQS_ON already done at io_return stosm __SF_EMPTY(%r15),0x03 # reenable interrupts la %r2,SP_PTREGS(%r15) # load pt_regs brasl %r14,do_signal # call do_signal stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts TRACE_IRQS_OFF - j io_work_loop + j io_return # # _TIF_NOTIFY_RESUME or is set, call do_notify_resume # io_notify_resume: - TRACE_IRQS_ON + # TRACE_IRQS_ON already done at io_return stosm __SF_EMPTY(%r15),0x03 # reenable interrupts la %r2,SP_PTREGS(%r15) # load pt_regs brasl %r14,do_notify_resume # call do_notify_resume stnsm __SF_EMPTY(%r15),0xfc # disable I/O and ext. interrupts TRACE_IRQS_OFF - j io_work_loop + j io_return /* * External interrupt handler routine @@ -883,14 +870,14 @@ stack_overflow: cleanup_table_system_call: .quad system_call, sysc_do_svc -cleanup_table_sysc_return: - .quad sysc_return, sysc_leave -cleanup_table_sysc_leave: - .quad sysc_leave, sysc_done -cleanup_table_io_return: - .quad io_return, io_leave -cleanup_table_io_leave: - .quad io_leave, io_done +cleanup_table_sysc_tif: + .quad sysc_tif, sysc_restore +cleanup_table_sysc_restore: + .quad sysc_restore, sysc_done +cleanup_table_io_tif: + .quad io_tif, io_restore +cleanup_table_io_restore: + .quad io_restore, io_done cleanup_critical: clc 8(8,%r12),BASED(cleanup_table_system_call) @@ -898,25 +885,25 @@ cleanup_critical: clc 8(8,%r12),BASED(cleanup_table_system_call+8) jl cleanup_system_call 0: - clc 8(8,%r12),BASED(cleanup_table_sysc_return) + clc 8(8,%r12),BASED(cleanup_table_sysc_tif) jl 0f - clc 8(8,%r12),BASED(cleanup_table_sysc_return+8) - jl cleanup_sysc_return + clc 8(8,%r12),BASED(cleanup_table_sysc_tif+8) + jl cleanup_sysc_tif 0: - clc 8(8,%r12),BASED(cleanup_table_sysc_leave) + clc 8(8,%r12),BASED(cleanup_table_sysc_restore) jl 0f - clc 8(8,%r12),BASED(cleanup_table_sysc_leave+8) - jl cleanup_sysc_leave + clc 8(8,%r12),BASED(cleanup_table_sysc_restore+8) + jl cleanup_sysc_restore 0: - clc 8(8,%r12),BASED(cleanup_table_io_return) + clc 8(8,%r12),BASED(cleanup_table_io_tif) jl 0f - clc 8(8,%r12),BASED(cleanup_table_io_return+8) - jl cleanup_io_return + clc 8(8,%r12),BASED(cleanup_table_io_tif+8) + jl cleanup_io_tif 0: - clc 8(8,%r12),BASED(cleanup_table_io_leave) + clc 8(8,%r12),BASED(cleanup_table_io_restore) jl 0f - clc 8(8,%r12),BASED(cleanup_table_io_leave+8) - jl cleanup_io_leave + clc 8(8,%r12),BASED(cleanup_table_io_restore+8) + jl cleanup_io_restore 0: br %r14 @@ -963,16 +950,16 @@ cleanup_system_call_insn: .quad sysc_stime .quad sysc_update -cleanup_sysc_return: +cleanup_sysc_tif: mvc __LC_RETURN_PSW(8),0(%r12) - mvc __LC_RETURN_PSW+8(8),BASED(cleanup_table_sysc_return) + mvc __LC_RETURN_PSW+8(8),BASED(cleanup_table_sysc_tif) la %r12,__LC_RETURN_PSW br %r14 -cleanup_sysc_leave: - clc 8(8,%r12),BASED(cleanup_sysc_leave_insn) +cleanup_sysc_restore: + clc 8(8,%r12),BASED(cleanup_sysc_restore_insn) je 3f - clc 8(8,%r12),BASED(cleanup_sysc_leave_insn+8) + clc 8(8,%r12),BASED(cleanup_sysc_restore_insn+8) jhe 0f mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER 0: mvc __LC_RETURN_PSW(16),SP_PSW(%r15) @@ -985,20 +972,20 @@ cleanup_sysc_leave: lg %r15,SP_R15(%r15) 3: la %r12,__LC_RETURN_PSW br %r14 -cleanup_sysc_leave_insn: +cleanup_sysc_restore_insn: .quad sysc_done - 4 .quad sysc_done - 16 -cleanup_io_return: +cleanup_io_tif: mvc __LC_RETURN_PSW(8),0(%r12) - mvc __LC_RETURN_PSW+8(8),BASED(cleanup_table_io_return) + mvc __LC_RETURN_PSW+8(8),BASED(cleanup_table_io_tif) la %r12,__LC_RETURN_PSW br %r14 -cleanup_io_leave: - clc 8(8,%r12),BASED(cleanup_io_leave_insn) +cleanup_io_restore: + clc 8(8,%r12),BASED(cleanup_io_restore_insn) je 3f - clc 8(8,%r12),BASED(cleanup_io_leave_insn+8) + clc 8(8,%r12),BASED(cleanup_io_restore_insn+8) jhe 0f mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER 0: mvc __LC_RETURN_PSW(16),SP_PSW(%r15) @@ -1011,7 +998,7 @@ cleanup_io_leave: lg %r15,SP_R15(%r15) 3: la %r12,__LC_RETURN_PSW br %r14 -cleanup_io_leave_insn: +cleanup_io_restore_insn: .quad io_done - 4 .quad io_done - 16 diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 6309276..5987524 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -369,10 +369,6 @@ static void setup_addressing_mode(void) pr_info("Address spaces switched, " "mvcos not available\n"); } -#ifdef CONFIG_TRACE_IRQFLAGS - sysc_restore_trace_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK; - io_restore_trace_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK; -#endif } static void __init -- cgit v0.10.2 From 6377981faf1a4425b0531e577736ef03df97c8f6 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Mon, 17 May 2010 10:00:03 +0200 Subject: [S390] idle time accounting vs. machine checks A machine check can interrupt the i/o and external interrupt handler anytime. If the machine check occurs while the interrupt handler is waking up from idle vtime_start_cpu can get executed a second time and the int_clock / async_enter_timer values in the lowcore get clobbered. This can confuse the cpu time accounting. To fix this problem two changes are needed. First the machine check handler has to use its own copies of int_clock and async_enter_timer, named mcck_clock and mcck_enter_timer. Second the nested execution of vtime_start_cpu has to be prevented. This is done in s390_idle_check by checking the wait bit in the program status word. Signed-off-by: Martin Schwidefsky diff --git a/arch/s390/include/asm/cputime.h b/arch/s390/include/asm/cputime.h index 258ba88..8b1a52a 100644 --- a/arch/s390/include/asm/cputime.h +++ b/arch/s390/include/asm/cputime.h @@ -188,15 +188,16 @@ struct s390_idle_data { DECLARE_PER_CPU(struct s390_idle_data, s390_idle); -void vtime_start_cpu(void); +void vtime_start_cpu(__u64 int_clock, __u64 enter_timer); cputime64_t s390_get_idle_time(int cpu); #define arch_idle_time(cpu) s390_get_idle_time(cpu) -static inline void s390_idle_check(void) +static inline void s390_idle_check(struct pt_regs *regs, __u64 int_clock, + __u64 enter_timer) { - if ((&__get_cpu_var(s390_idle))->idle_enter != 0ULL) - vtime_start_cpu(); + if (regs->psw.mask & PSW_MASK_WAIT) + vtime_start_cpu(int_clock, enter_timer); } static inline int s390_nohz_delay(int cpu) diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index f7e78c7..2c02d46 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h @@ -104,37 +104,39 @@ struct _lowcore { /* CPU time accounting values */ __u64 sync_enter_timer; /* 0x0250 */ __u64 async_enter_timer; /* 0x0258 */ - __u64 exit_timer; /* 0x0260 */ - __u64 user_timer; /* 0x0268 */ - __u64 system_timer; /* 0x0270 */ - __u64 steal_timer; /* 0x0278 */ - __u64 last_update_timer; /* 0x0280 */ - __u64 last_update_clock; /* 0x0288 */ + __u64 mcck_enter_timer; /* 0x0260 */ + __u64 exit_timer; /* 0x0268 */ + __u64 user_timer; /* 0x0270 */ + __u64 system_timer; /* 0x0278 */ + __u64 steal_timer; /* 0x0280 */ + __u64 last_update_timer; /* 0x0288 */ + __u64 last_update_clock; /* 0x0290 */ /* Current process. */ - __u32 current_task; /* 0x0290 */ - __u32 thread_info; /* 0x0294 */ - __u32 kernel_stack; /* 0x0298 */ + __u32 current_task; /* 0x0298 */ + __u32 thread_info; /* 0x029c */ + __u32 kernel_stack; /* 0x02a0 */ /* Interrupt and panic stack. */ - __u32 async_stack; /* 0x029c */ - __u32 panic_stack; /* 0x02a0 */ + __u32 async_stack; /* 0x02a4 */ + __u32 panic_stack; /* 0x02a8 */ /* Address space pointer. */ - __u32 kernel_asce; /* 0x02a4 */ - __u32 user_asce; /* 0x02a8 */ - __u32 user_exec_asce; /* 0x02ac */ + __u32 kernel_asce; /* 0x02ac */ + __u32 user_asce; /* 0x02b0 */ + __u32 user_exec_asce; /* 0x02b4 */ /* SMP info area */ - __u32 cpu_nr; /* 0x02b0 */ - __u32 softirq_pending; /* 0x02b4 */ - __u32 percpu_offset; /* 0x02b8 */ - __u32 ext_call_fast; /* 0x02bc */ - __u64 int_clock; /* 0x02c0 */ - __u64 clock_comparator; /* 0x02c8 */ - __u32 machine_flags; /* 0x02d0 */ - __u32 ftrace_func; /* 0x02d4 */ - __u8 pad_0x02d8[0x0300-0x02d8]; /* 0x02d8 */ + __u32 cpu_nr; /* 0x02b8 */ + __u32 softirq_pending; /* 0x02bc */ + __u32 percpu_offset; /* 0x02c0 */ + __u32 ext_call_fast; /* 0x02c4 */ + __u64 int_clock; /* 0x02c8 */ + __u64 mcck_clock; /* 0x02d0 */ + __u64 clock_comparator; /* 0x02d8 */ + __u32 machine_flags; /* 0x02e0 */ + __u32 ftrace_func; /* 0x02e4 */ + __u8 pad_0x02e8[0x0300-0x02e8]; /* 0x02e8 */ /* Interrupt response block */ __u8 irb[64]; /* 0x0300 */ @@ -232,38 +234,40 @@ struct _lowcore { /* CPU accounting and timing values. */ __u64 sync_enter_timer; /* 0x02a0 */ __u64 async_enter_timer; /* 0x02a8 */ - __u64 exit_timer; /* 0x02b0 */ - __u64 user_timer; /* 0x02b8 */ - __u64 system_timer; /* 0x02c0 */ - __u64 steal_timer; /* 0x02c8 */ - __u64 last_update_timer; /* 0x02d0 */ - __u64 last_update_clock; /* 0x02d8 */ + __u64 mcck_enter_timer; /* 0x02b0 */ + __u64 exit_timer; /* 0x02b8 */ + __u64 user_timer; /* 0x02c0 */ + __u64 system_timer; /* 0x02c8 */ + __u64 steal_timer; /* 0x02d0 */ + __u64 last_update_timer; /* 0x02d8 */ + __u64 last_update_clock; /* 0x02e0 */ /* Current process. */ - __u64 current_task; /* 0x02e0 */ - __u64 thread_info; /* 0x02e8 */ - __u64 kernel_stack; /* 0x02f0 */ + __u64 current_task; /* 0x02e8 */ + __u64 thread_info; /* 0x02f0 */ + __u64 kernel_stack; /* 0x02f8 */ /* Interrupt and panic stack. */ - __u64 async_stack; /* 0x02f8 */ - __u64 panic_stack; /* 0x0300 */ + __u64 async_stack; /* 0x0300 */ + __u64 panic_stack; /* 0x0308 */ /* Address space pointer. */ - __u64 kernel_asce; /* 0x0308 */ - __u64 user_asce; /* 0x0310 */ - __u64 user_exec_asce; /* 0x0318 */ + __u64 kernel_asce; /* 0x0310 */ + __u64 user_asce; /* 0x0318 */ + __u64 user_exec_asce; /* 0x0320 */ /* SMP info area */ - __u32 cpu_nr; /* 0x0320 */ - __u32 softirq_pending; /* 0x0324 */ - __u64 percpu_offset; /* 0x0328 */ - __u64 ext_call_fast; /* 0x0330 */ - __u64 int_clock; /* 0x0338 */ - __u64 clock_comparator; /* 0x0340 */ - __u64 vdso_per_cpu_data; /* 0x0348 */ - __u64 machine_flags; /* 0x0350 */ - __u64 ftrace_func; /* 0x0358 */ - __u8 pad_0x0368[0x0380-0x0360]; /* 0x0360 */ + __u32 cpu_nr; /* 0x0328 */ + __u32 softirq_pending; /* 0x032c */ + __u64 percpu_offset; /* 0x0330 */ + __u64 ext_call_fast; /* 0x0338 */ + __u64 int_clock; /* 0x0340 */ + __u64 mcck_clock; /* 0x0348 */ + __u64 clock_comparator; /* 0x0350 */ + __u64 vdso_per_cpu_data; /* 0x0358 */ + __u64 machine_flags; /* 0x0360 */ + __u64 ftrace_func; /* 0x0368 */ + __u8 pad_0x0370[0x0380-0x0370]; /* 0x0370 */ /* Interrupt response block. */ __u8 irb[64]; /* 0x0380 */ diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index 32b1ede..816d81f 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c @@ -112,6 +112,7 @@ int main(void) DEFINE(__LC_RETURN_MCCK_PSW, offsetof(struct _lowcore, return_mcck_psw)); DEFINE(__LC_SYNC_ENTER_TIMER, offsetof(struct _lowcore, sync_enter_timer)); DEFINE(__LC_ASYNC_ENTER_TIMER, offsetof(struct _lowcore, async_enter_timer)); + DEFINE(__LC_MCCK_ENTER_TIMER, offsetof(struct _lowcore, mcck_enter_timer)); DEFINE(__LC_EXIT_TIMER, offsetof(struct _lowcore, exit_timer)); DEFINE(__LC_USER_TIMER, offsetof(struct _lowcore, user_timer)); DEFINE(__LC_SYSTEM_TIMER, offsetof(struct _lowcore, system_timer)); @@ -127,6 +128,7 @@ int main(void) DEFINE(__LC_USER_ASCE, offsetof(struct _lowcore, user_asce)); DEFINE(__LC_USER_EXEC_ASCE, offsetof(struct _lowcore, user_exec_asce)); DEFINE(__LC_INT_CLOCK, offsetof(struct _lowcore, int_clock)); + DEFINE(__LC_MCCK_CLOCK, offsetof(struct _lowcore, mcck_clock)); DEFINE(__LC_MACHINE_FLAGS, offsetof(struct _lowcore, machine_flags)); DEFINE(__LC_FTRACE_FUNC, offsetof(struct _lowcore, ftrace_func)); DEFINE(__LC_IRB, offsetof(struct _lowcore, irb)); diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 07d8499..0e2b162 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -742,15 +742,14 @@ __critical_end: .globl mcck_int_handler mcck_int_handler: - stck __LC_INT_CLOCK + stck __LC_MCCK_CLOCK spt __LC_CPU_TIMER_SAVE_AREA # revalidate cpu timer lm %r0,%r15,__LC_GPREGS_SAVE_AREA # revalidate gprs SAVE_ALL_BASE __LC_SAVE_AREA+32 la %r12,__LC_MCK_OLD_PSW tm __LC_MCCK_CODE,0x80 # system damage? bo BASED(mcck_int_main) # yes -> rest of mcck code invalid - mvc __LC_SAVE_AREA+52(8),__LC_ASYNC_ENTER_TIMER - mvc __LC_ASYNC_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA + mvc __LC_MCCK_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid? bo BASED(1f) la %r14,__LC_SYNC_ENTER_TIMER @@ -764,7 +763,7 @@ mcck_int_handler: bl BASED(0f) la %r14,__LC_LAST_UPDATE_TIMER 0: spt 0(%r14) - mvc __LC_ASYNC_ENTER_TIMER(8),0(%r14) + mvc __LC_MCCK_ENTER_TIMER(8),0(%r14) 1: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? bno BASED(mcck_int_main) # no -> skip cleanup critical tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit @@ -786,9 +785,9 @@ mcck_int_main: bno BASED(mcck_no_vtime) # no -> skip cleanup critical tm SP_PSW+1(%r15),0x01 # interrupting from user ? bz BASED(mcck_no_vtime) - UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER + UPDATE_VTIME __LC_EXIT_TIMER,__LC_MCCK_ENTER_TIMER,__LC_USER_TIMER UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER - mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER + mvc __LC_LAST_UPDATE_TIMER(8),__LC_MCCK_ENTER_TIMER mcck_no_vtime: l %r9,__LC_THREAD_INFO # load pointer to thread_info struct la %r2,SP_PTREGS(%r15) # load pt_regs @@ -811,7 +810,6 @@ mcck_no_vtime: mcck_return: mvc __LC_RETURN_MCCK_PSW(8),SP_PSW(%r15) # move return PSW ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit - mvc __LC_ASYNC_ENTER_TIMER(8),__LC_SAVE_AREA+52 tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ? bno BASED(0f) lm %r0,%r15,SP_R0(%r15) # load gprs 0-15 @@ -934,15 +932,16 @@ cleanup_critical: cleanup_system_call: mvc __LC_RETURN_PSW(8),0(%r12) - c %r12,BASED(.Lmck_old_psw) - be BASED(0f) - la %r12,__LC_SAVE_AREA+16 - b BASED(1f) -0: la %r12,__LC_SAVE_AREA+32 -1: clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+4) bh BASED(0f) + mvc __LC_SYNC_ENTER_TIMER(8),__LC_MCCK_ENTER_TIMER + c %r12,BASED(.Lmck_old_psw) + be BASED(0f) mvc __LC_SYNC_ENTER_TIMER(8),__LC_ASYNC_ENTER_TIMER +0: c %r12,BASED(.Lmck_old_psw) + la %r12,__LC_SAVE_AREA+32 + be BASED(0f) + la %r12,__LC_SAVE_AREA+16 0: clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+8) bhe BASED(cleanup_vtime) clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn) @@ -984,16 +983,19 @@ cleanup_sysc_tif: cleanup_sysc_restore: clc 4(4,%r12),BASED(cleanup_sysc_restore_insn) be BASED(2f) + mvc __LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER + c %r12,BASED(.Lmck_old_psw) + be BASED(0f) mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER - clc 4(4,%r12),BASED(cleanup_sysc_restore_insn+4) +0: clc 4(4,%r12),BASED(cleanup_sysc_restore_insn+4) be BASED(2f) mvc __LC_RETURN_PSW(8),SP_PSW(%r15) c %r12,BASED(.Lmck_old_psw) - bne BASED(0f) - mvc __LC_SAVE_AREA+32(16),SP_R12(%r15) - b BASED(1f) -0: mvc __LC_SAVE_AREA+16(16),SP_R12(%r15) -1: lm %r0,%r11,SP_R0(%r15) + la %r12,__LC_SAVE_AREA+32 + be BASED(1f) + la %r12,__LC_SAVE_AREA+16 +1: mvc 0(16,%r12),SP_R12(%r15) + lm %r0,%r11,SP_R0(%r15) l %r15,SP_R15(%r15) 2: la %r12,__LC_RETURN_PSW br %r14 @@ -1009,19 +1011,15 @@ cleanup_io_tif: cleanup_io_restore: clc 4(4,%r12),BASED(cleanup_io_restore_insn) - be BASED(2f) - mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER + be BASED(1f) + mvc __LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER clc 4(4,%r12),BASED(cleanup_io_restore_insn+4) - be BASED(2f) + be BASED(1f) mvc __LC_RETURN_PSW(8),SP_PSW(%r15) - c %r12,BASED(.Lmck_old_psw) - bne BASED(0f) mvc __LC_SAVE_AREA+32(16),SP_R12(%r15) - b BASED(1f) -0: mvc __LC_SAVE_AREA+16(16),SP_R12(%r15) -1: lm %r0,%r11,SP_R0(%r15) + lm %r0,%r11,SP_R0(%r15) l %r15,SP_R15(%r15) -2: la %r12,__LC_RETURN_PSW +1: la %r12,__LC_RETURN_PSW br %r14 cleanup_io_restore_insn: .long io_done - 4 + 0x80000000 diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 860cea1..6536f5c 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -725,7 +725,7 @@ __critical_end: */ .globl mcck_int_handler mcck_int_handler: - stck __LC_INT_CLOCK + stck __LC_MCCK_CLOCK la %r1,4095 # revalidate r1 spt __LC_CPU_TIMER_SAVE_AREA-4095(%r1) # revalidate cpu timer lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs @@ -734,8 +734,7 @@ mcck_int_handler: tm __LC_MCCK_CODE,0x80 # system damage? jo mcck_int_main # yes -> rest of mcck code invalid la %r14,4095 - mvc __LC_SAVE_AREA+104(8),__LC_ASYNC_ENTER_TIMER - mvc __LC_ASYNC_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA-4095(%r14) + mvc __LC_MCCK_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA-4095(%r14) tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid? jo 1f la %r14,__LC_SYNC_ENTER_TIMER @@ -749,7 +748,7 @@ mcck_int_handler: jl 0f la %r14,__LC_LAST_UPDATE_TIMER 0: spt 0(%r14) - mvc __LC_ASYNC_ENTER_TIMER(8),0(%r14) + mvc __LC_MCCK_ENTER_TIMER(8),0(%r14) 1: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? jno mcck_int_main # no -> skip cleanup critical tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit @@ -770,9 +769,9 @@ mcck_int_main: jno mcck_no_vtime # no -> no timer update tm SP_PSW+1(%r15),0x01 # interrupting from user ? jz mcck_no_vtime - UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER + UPDATE_VTIME __LC_EXIT_TIMER,__LC_MCCK_ENTER_TIMER,__LC_USER_TIMER UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER - mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER + mvc __LC_LAST_UPDATE_TIMER(8),__LC_MCCK_ENTER_TIMER mcck_no_vtime: lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct la %r2,SP_PTREGS(%r15) # load pt_regs @@ -794,7 +793,6 @@ mcck_return: mvc __LC_RETURN_MCCK_PSW(16),SP_PSW(%r15) # move return PSW ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit lmg %r0,%r15,SP_R0(%r15) # load gprs 0-15 - mvc __LC_ASYNC_ENTER_TIMER(8),__LC_SAVE_AREA+104 tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ? jno 0f stpt __LC_EXIT_TIMER @@ -909,15 +907,16 @@ cleanup_critical: cleanup_system_call: mvc __LC_RETURN_PSW(16),0(%r12) - cghi %r12,__LC_MCK_OLD_PSW - je 0f - la %r12,__LC_SAVE_AREA+32 - j 1f -0: la %r12,__LC_SAVE_AREA+64 -1: clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+8) jh 0f + mvc __LC_SYNC_ENTER_TIMER(8),__LC_MCCK_ENTER_TIMER + cghi %r12,__LC_MCK_OLD_PSW + je 0f mvc __LC_SYNC_ENTER_TIMER(8),__LC_ASYNC_ENTER_TIMER +0: cghi %r12,__LC_MCK_OLD_PSW + la %r12,__LC_SAVE_AREA+64 + je 0f + la %r12,__LC_SAVE_AREA+32 0: clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+16) jhe cleanup_vtime clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn) @@ -958,19 +957,22 @@ cleanup_sysc_tif: cleanup_sysc_restore: clc 8(8,%r12),BASED(cleanup_sysc_restore_insn) - je 3f + je 2f clc 8(8,%r12),BASED(cleanup_sysc_restore_insn+8) jhe 0f + mvc __LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER + cghi %r12,__LC_MCK_OLD_PSW + je 0f mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER 0: mvc __LC_RETURN_PSW(16),SP_PSW(%r15) cghi %r12,__LC_MCK_OLD_PSW - jne 1f - mvc __LC_SAVE_AREA+64(32),SP_R12(%r15) - j 2f -1: mvc __LC_SAVE_AREA+32(32),SP_R12(%r15) -2: lmg %r0,%r11,SP_R0(%r15) + la %r12,__LC_SAVE_AREA+64 + je 1f + la %r12,__LC_SAVE_AREA+32 +1: mvc 0(32,%r12),SP_R12(%r15) + lmg %r0,%r11,SP_R0(%r15) lg %r15,SP_R15(%r15) -3: la %r12,__LC_RETURN_PSW +2: la %r12,__LC_RETURN_PSW br %r14 cleanup_sysc_restore_insn: .quad sysc_done - 4 @@ -984,19 +986,15 @@ cleanup_io_tif: cleanup_io_restore: clc 8(8,%r12),BASED(cleanup_io_restore_insn) - je 3f + je 1f clc 8(8,%r12),BASED(cleanup_io_restore_insn+8) jhe 0f - mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER + mvc __LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER 0: mvc __LC_RETURN_PSW(16),SP_PSW(%r15) - cghi %r12,__LC_MCK_OLD_PSW - jne 1f mvc __LC_SAVE_AREA+64(32),SP_R12(%r15) - j 2f -1: mvc __LC_SAVE_AREA+32(32),SP_R12(%r15) -2: lmg %r0,%r11,SP_R0(%r15) + lmg %r0,%r11,SP_R0(%r15) lg %r15,SP_R15(%r15) -3: la %r12,__LC_RETURN_PSW +1: la %r12,__LC_RETURN_PSW br %r14 cleanup_io_restore_insn: .quad io_done - 4 diff --git a/arch/s390/kernel/nmi.c b/arch/s390/kernel/nmi.c index 015e27d..ac15139 100644 --- a/arch/s390/kernel/nmi.c +++ b/arch/s390/kernel/nmi.c @@ -255,7 +255,8 @@ void notrace s390_do_machine_check(struct pt_regs *regs) int umode; nmi_enter(); - s390_idle_check(); + s390_idle_check(regs, S390_lowcore.mcck_clock, + S390_lowcore.mcck_enter_timer); mci = (struct mci *) &S390_lowcore.mcck_interruption_code; mcck = &__get_cpu_var(cpu_mcck); diff --git a/arch/s390/kernel/s390_ext.c b/arch/s390/kernel/s390_ext.c index 59618bc..9ce641b 100644 --- a/arch/s390/kernel/s390_ext.c +++ b/arch/s390/kernel/s390_ext.c @@ -120,7 +120,8 @@ void __irq_entry do_extint(struct pt_regs *regs, unsigned short code) struct pt_regs *old_regs; old_regs = set_irq_regs(regs); - s390_idle_check(); + s390_idle_check(regs, S390_lowcore.int_clock, + S390_lowcore.async_enter_timer); irq_enter(); if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator) /* Serve timer interrupts first. */ diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index b59a812..3479f1b 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c @@ -121,32 +121,35 @@ void account_system_vtime(struct task_struct *tsk) } EXPORT_SYMBOL_GPL(account_system_vtime); -void vtime_start_cpu(void) +void vtime_start_cpu(__u64 int_clock, __u64 enter_timer) { struct s390_idle_data *idle = &__get_cpu_var(s390_idle); struct vtimer_queue *vq = &__get_cpu_var(virt_cpu_timer); __u64 idle_time, expires; + if (idle->idle_enter == 0ULL) + return; + /* Account time spent with enabled wait psw loaded as idle time. */ - idle_time = S390_lowcore.int_clock - idle->idle_enter; + idle_time = int_clock - idle->idle_enter; account_idle_time(idle_time); S390_lowcore.steal_timer += idle->idle_enter - S390_lowcore.last_update_clock; - S390_lowcore.last_update_clock = S390_lowcore.int_clock; + S390_lowcore.last_update_clock = int_clock; /* Account system time spent going idle. */ S390_lowcore.system_timer += S390_lowcore.last_update_timer - vq->idle; - S390_lowcore.last_update_timer = S390_lowcore.async_enter_timer; + S390_lowcore.last_update_timer = enter_timer; /* Restart vtime CPU timer */ if (vq->do_spt) { /* Program old expire value but first save progress. */ - expires = vq->idle - S390_lowcore.async_enter_timer; + expires = vq->idle - enter_timer; expires += get_vtimer(); set_vtimer(expires); } else { /* Don't account the CPU timer delta while the cpu was idle. */ - vq->elapsed -= vq->idle - S390_lowcore.async_enter_timer; + vq->elapsed -= vq->idle - enter_timer; } idle->sequence++; diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 5feea1a..f4e6cf3 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -616,7 +616,8 @@ void __irq_entry do_IRQ(struct pt_regs *regs) struct pt_regs *old_regs; old_regs = set_irq_regs(regs); - s390_idle_check(); + s390_idle_check(regs, S390_lowcore.int_clock, + S390_lowcore.async_enter_timer); irq_enter(); __get_cpu_var(s390_idle).nohz_delay = 1; if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator) -- cgit v0.10.2 From cd3b70f5d4d82f85d1e1d6e822f38ae098cf7c72 Mon Sep 17 00:00:00 2001 From: Carsten Otte Date: Mon, 17 May 2010 10:00:04 +0200 Subject: [S390] virtualization aware cpu measurement Use the SPP instruction to set a tag on entry to / exit of the virtual machine context. This allows the cpu measurement facility to distinguish the samples from the host and the different guests. Signed-off-by: Carsten Otte diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index 2c02d46..0f97ef2 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h @@ -267,7 +267,8 @@ struct _lowcore { __u64 vdso_per_cpu_data; /* 0x0358 */ __u64 machine_flags; /* 0x0360 */ __u64 ftrace_func; /* 0x0368 */ - __u8 pad_0x0370[0x0380-0x0370]; /* 0x0370 */ + __u64 sie_hook; /* 0x0370 */ + __u64 cmf_hpp; /* 0x0378 */ /* Interrupt response block. */ __u8 irb[64]; /* 0x0380 */ diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h index 9ab6bd3..25e831d 100644 --- a/arch/s390/include/asm/setup.h +++ b/arch/s390/include/asm/setup.h @@ -2,7 +2,7 @@ * include/asm-s390/setup.h * * S390 version - * Copyright IBM Corp. 1999,2006 + * Copyright IBM Corp. 1999,2010 */ #ifndef _ASM_S390_SETUP_H @@ -72,6 +72,7 @@ extern unsigned int user_mode; #define MACHINE_FLAG_HPAGE (1UL << 10) #define MACHINE_FLAG_PFMF (1UL << 11) #define MACHINE_FLAG_LPAR (1UL << 12) +#define MACHINE_FLAG_SPP (1UL << 13) #define MACHINE_IS_VM (S390_lowcore.machine_flags & MACHINE_FLAG_VM) #define MACHINE_IS_KVM (S390_lowcore.machine_flags & MACHINE_FLAG_KVM) @@ -88,6 +89,7 @@ extern unsigned int user_mode; #define MACHINE_HAS_MVCOS (0) #define MACHINE_HAS_HPAGE (0) #define MACHINE_HAS_PFMF (0) +#define MACHINE_HAS_SPP (0) #else /* __s390x__ */ #define MACHINE_HAS_IEEE (1) #define MACHINE_HAS_CSP (1) @@ -97,6 +99,7 @@ extern unsigned int user_mode; #define MACHINE_HAS_MVCOS (S390_lowcore.machine_flags & MACHINE_FLAG_MVCOS) #define MACHINE_HAS_HPAGE (S390_lowcore.machine_flags & MACHINE_FLAG_HPAGE) #define MACHINE_HAS_PFMF (S390_lowcore.machine_flags & MACHINE_FLAG_PFMF) +#define MACHINE_HAS_SPP (S390_lowcore.machine_flags & MACHINE_FLAG_SPP) #endif /* __s390x__ */ #define ZFCPDUMP_HSA_SIZE (32UL<<20) diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index 816d81f..44a4336 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c @@ -131,6 +131,8 @@ int main(void) DEFINE(__LC_MCCK_CLOCK, offsetof(struct _lowcore, mcck_clock)); DEFINE(__LC_MACHINE_FLAGS, offsetof(struct _lowcore, machine_flags)); DEFINE(__LC_FTRACE_FUNC, offsetof(struct _lowcore, ftrace_func)); + DEFINE(__LC_SIE_HOOK, offsetof(struct _lowcore, sie_hook)); + DEFINE(__LC_CMF_HPP, offsetof(struct _lowcore, cmf_hpp)); DEFINE(__LC_IRB, offsetof(struct _lowcore, irb)); DEFINE(__LC_CPU_TIMER_SAVE_AREA, offsetof(struct _lowcore, cpu_timer_save_area)); DEFINE(__LC_CLOCK_COMP_SAVE_AREA, offsetof(struct _lowcore, clock_comp_save_area)); diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 2d92c2c..c00856a 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -356,6 +356,7 @@ static __init void detect_machine_facilities(void) { #ifdef CONFIG_64BIT unsigned int facilities; + unsigned long long facility_bits; facilities = stfl(); if (facilities & (1 << 28)) @@ -364,6 +365,9 @@ static __init void detect_machine_facilities(void) S390_lowcore.machine_flags |= MACHINE_FLAG_PFMF; if (facilities & (1 << 4)) S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS; + if ((stfle(&facility_bits, 1) > 0) && + (facility_bits & (1ULL << (63 - 40)))) + S390_lowcore.machine_flags |= MACHINE_FLAG_SPP; #endif } diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 6536f5c..829b759 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -2,7 +2,7 @@ * arch/s390/kernel/entry64.S * S390 low-level entry points. * - * Copyright (C) IBM Corp. 1999,2006 + * Copyright (C) IBM Corp. 1999,2010 * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), * Hartmut Penner (hp@de.ibm.com), * Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com), @@ -59,6 +59,16 @@ _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \ #define BASED(name) name-system_call(%r13) + .macro HANDLE_SIE_INTERCEPT +#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) + lg %r3,__LC_SIE_HOOK + ltgr %r3,%r3 + jz 0f + basr %r14,%r3 + 0: +#endif + .endm + #ifdef CONFIG_TRACE_IRQFLAGS .macro TRACE_IRQS_ON basr %r2,%r0 @@ -466,6 +476,7 @@ pgm_check_handler: UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER pgm_no_vtime: + HANDLE_SIE_INTERCEPT TRACE_IRQS_CHECK_OFF lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct mvc SP_ARGS(8,%r15),__LC_LAST_BREAK @@ -507,6 +518,7 @@ pgm_per_std: UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER pgm_no_vtime2: + HANDLE_SIE_INTERCEPT TRACE_IRQS_CHECK_OFF lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct lg %r1,__TI_task(%r9) @@ -570,6 +582,7 @@ io_int_handler: mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER io_no_vtime: lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct + HANDLE_SIE_INTERCEPT TRACE_IRQS_OFF la %r2,SP_PTREGS(%r15) # address of register-save area brasl %r14,do_IRQ # call standard irq handler @@ -595,15 +608,6 @@ io_done: io_work: tm SP_PSW+1(%r15),0x01 # returning to user ? jo io_work_user # yes -> do resched & signal -#if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) - lg %r2,SP_PSW+8(%r15) # check if current instruction is SIE - lh %r1,0(%r2) - chi %r1,-19948 # signed 16 bit compare with 0xb214 - jne 0f # no -> leave PSW alone - aghi %r2,4 # yes-> add 4 bytes to leave SIE - stg %r2,SP_PSW+8(%r15) -0: -#endif #ifdef CONFIG_PREEMPT # check for preemptive scheduling icm %r0,15,__TI_precount(%r9) @@ -712,6 +716,7 @@ ext_int_handler: mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER ext_no_vtime: lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct + HANDLE_SIE_INTERCEPT TRACE_IRQS_OFF la %r2,SP_PTREGS(%r15) # address of register-save area llgh %r3,__LC_EXT_INT_CODE # get interruption code @@ -786,6 +791,7 @@ mcck_no_vtime: stosm __SF_EMPTY(%r15),0x04 # turn dat on tm __TI_flags+7(%r9),_TIF_MCCK_PENDING jno mcck_return + HANDLE_SIE_INTERCEPT TRACE_IRQS_OFF brasl %r14,s390_handle_mcck TRACE_IRQS_ON diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 5987524..7d89324 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -2,7 +2,7 @@ * arch/s390/kernel/setup.c * * S390 version - * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Copyright (C) IBM Corp. 1999,2010 * Author(s): Hartmut Penner (hp@de.ibm.com), * Martin Schwidefsky (schwidefsky@de.ibm.com) * @@ -401,6 +401,7 @@ setup_lowcore(void) lc->io_new_psw.mask = psw_kernel_bits; lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler; lc->clock_comparator = -1ULL; + lc->cmf_hpp = -1ULL; lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE; lc->async_stack = (unsigned long) __alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0) + ASYNC_SIZE; diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig index a725158..2f4b687c 100644 --- a/arch/s390/kvm/Kconfig +++ b/arch/s390/kvm/Kconfig @@ -33,6 +33,17 @@ config KVM If unsure, say N. +config KVM_AWARE_CMF + depends on KVM + bool "KVM aware sampling" + ---help--- + This option enhances the sampling data from the CPU Measurement + Facility with additional information, that allows to distinguish + guest(s) and host when using the kernel based virtual machine + functionality. + + If unsure, say N. + # OK, it's a little counter-intuitive to do this, but it puts it neatly under # the virtualization menu. source drivers/vhost/Kconfig diff --git a/arch/s390/kvm/sie64a.S b/arch/s390/kvm/sie64a.S index 934fd6a..31646bd 100644 --- a/arch/s390/kvm/sie64a.S +++ b/arch/s390/kvm/sie64a.S @@ -1,20 +1,60 @@ /* * sie64a.S - low level sie call * - * Copyright IBM Corp. 2008 + * Copyright IBM Corp. 2008,2010 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License (version 2 only) * as published by the Free Software Foundation. * * Author(s): Heiko Carstens + * Christian Ehrhardt */ #include #include +#include +#include +#include +#include + +_TIF_EXIT_SIE = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING) + +/* + * offsets into stackframe + * SP_ = offsets into stack sie64 is called with + * SPI_ = offsets into irq stack + */ +SP_GREGS = __SF_EMPTY +SP_HOOK = __SF_EMPTY+8 +SP_GPP = __SF_EMPTY+16 +SPI_PSW = STACK_FRAME_OVERHEAD + __PT_PSW + -SP_R5 = 5 * 8 # offset into stackframe -SP_R6 = 6 * 8 + .macro SPP newpp +#ifdef CONFIG_KVM_AWARE_CMF + tm __LC_MACHINE_FLAGS+6,0x20 # MACHINE_FLAG_SPP + jz 0f + .insn s,0xb2800000,\newpp + 0: +#endif + .endm + +sie_irq_handler: + SPP __LC_CMF_HPP # set host id + larl %r2,sie_inst + clg %r2,SPI_PSW+8(0,%r15) # intercepted sie + jne 1f + xc __LC_SIE_HOOK(8),__LC_SIE_HOOK + lg %r2,__LC_THREAD_INFO # pointer thread_info struct + tm __TI_flags+7(%r2),_TIF_EXIT_SIE + jz 0f + larl %r2,sie_exit # work pending, leave sie + stg %r2,__LC_RETURN_PSW+8 + br %r14 +0: larl %r2,sie_reenter # re-enter with guest id + stg %r2,__LC_RETURN_PSW+8 +1: br %r14 /* * sie64a calling convention: @@ -23,23 +63,34 @@ SP_R6 = 6 * 8 */ .globl sie64a sie64a: - lgr %r5,%r3 - stmg %r5,%r14,SP_R5(%r15) # save register on entry - lgr %r14,%r2 # pointer to sie control block - lmg %r0,%r13,0(%r3) # load guest gprs 0-13 + stg %r3,SP_GREGS(%r15) # save guest register save area + stmg %r6,%r14,__SF_GPRS(%r15) # save registers on entry + lgr %r14,%r2 # pointer to sie control block + larl %r5,sie_irq_handler + stg %r2,SP_GPP(%r15) + stg %r5,SP_HOOK(%r15) # save hook target + lmg %r0,%r13,0(%r3) # load guest gprs 0-13 +sie_reenter: + mvc __LC_SIE_HOOK(8),SP_HOOK(%r15) + SPP SP_GPP(%r15) # set guest id sie_inst: sie 0(%r14) - lg %r14,SP_R5(%r15) - stmg %r0,%r13,0(%r14) # save guest gprs 0-13 + xc __LC_SIE_HOOK(8),__LC_SIE_HOOK + SPP __LC_CMF_HPP # set host id +sie_exit: + lg %r14,SP_GREGS(%r15) + stmg %r0,%r13,0(%r14) # save guest gprs 0-13 lghi %r2,0 - lmg %r6,%r14,SP_R6(%r15) + lmg %r6,%r14,__SF_GPRS(%r15) br %r14 sie_err: - lg %r14,SP_R5(%r15) - stmg %r0,%r13,0(%r14) # save guest gprs 0-13 + xc __LC_SIE_HOOK(8),__LC_SIE_HOOK + SPP __LC_CMF_HPP # set host id + lg %r14,SP_GREGS(%r15) + stmg %r0,%r13,0(%r14) # save guest gprs 0-13 lghi %r2,-EFAULT - lmg %r6,%r14,SP_R6(%r15) + lmg %r6,%r14,__SF_GPRS(%r15) br %r14 .section __ex_table,"a" -- cgit v0.10.2 From 86f2552bbd0e17b19bb5e9881042533eaea553c7 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Mon, 17 May 2010 10:00:05 +0200 Subject: [S390] add breaking event address for user space Copy the last breaking event address from the lowcore to a new field in the thread_struct on each system entry. Add a new ptrace request PTRACE_GET_LAST_BREAK and a new utrace regset REGSET_LAST_BREAK to query the last breaking event. This is useful for debugging wild branches in user space code. Signed-off-by: Martin Schwidefsky diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h index fef9b33..e2c218d 100644 --- a/arch/s390/include/asm/ptrace.h +++ b/arch/s390/include/asm/ptrace.h @@ -328,8 +328,8 @@ struct pt_regs psw_t psw; unsigned long gprs[NUM_GPRS]; unsigned long orig_gpr2; - unsigned short svcnr; unsigned short ilc; + unsigned short svcnr; }; #endif @@ -436,6 +436,7 @@ typedef struct #define PTRACE_PEEKDATA_AREA 0x5003 #define PTRACE_POKETEXT_AREA 0x5004 #define PTRACE_POKEDATA_AREA 0x5005 +#define PTRACE_GET_LAST_BREAK 0x5006 /* * PT_PROT definition is loosely based on hppa bsd definition in diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h index 34f0873..be3d3f9 100644 --- a/arch/s390/include/asm/thread_info.h +++ b/arch/s390/include/asm/thread_info.h @@ -50,6 +50,7 @@ struct thread_info { struct restart_block restart_block; __u64 user_timer; __u64 system_timer; + unsigned long last_break; /* last breaking-event-address. */ }; /* diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index 44a4336..d9b490a 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c @@ -39,6 +39,7 @@ int main(void) DEFINE(__TI_precount, offsetof(struct thread_info, preempt_count)); DEFINE(__TI_user_timer, offsetof(struct thread_info, user_timer)); DEFINE(__TI_system_timer, offsetof(struct thread_info, system_timer)); + DEFINE(__TI_last_break, offsetof(struct thread_info, last_break)); BLANK(); DEFINE(__PT_ARGS, offsetof(struct pt_regs, args)); DEFINE(__PT_PSW, offsetof(struct pt_regs, psw)); diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 0e2b162..d5e3e60 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -180,9 +180,9 @@ STACK_SIZE = 1 << STACK_SHIFT s %r15,BASED(.Lc_spsize) # make room for registers & psw mvc SP_PSW(8,%r15),0(%r12) # move user PSW to stack st %r2,SP_ORIG_R2(%r15) # store original content of gpr 2 - icm %r12,3,__LC_SVC_ILC + icm %r12,12,__LC_SVC_ILC stm %r0,%r11,SP_R0(%r15) # store gprs %r0-%r11 to kernel stack - st %r12,SP_SVCNR(%r15) + st %r12,SP_ILC(%r15) mvc SP_R12(16,%r15),\savearea # move %r12-%r15 to stack la %r12,0 st %r12,__SF_BACKCHAIN(%r15) # clear back chain diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 829b759..178d925 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -126,31 +126,35 @@ _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \ * R15 - kernel stack pointer */ - .macro SAVE_ALL_BASE savearea - stmg %r12,%r15,\savearea - larl %r13,system_call - .endm - .macro SAVE_ALL_SVC psworg,savearea - la %r12,\psworg + stmg %r11,%r15,\savearea lg %r15,__LC_KERNEL_STACK # problem state -> load ksp + aghi %r15,-SP_SIZE # make room for registers & psw + lg %r11,__LC_LAST_BREAK .endm - .macro SAVE_ALL_SYNC psworg,savearea - la %r12,\psworg + .macro SAVE_ALL_PGM psworg,savearea + stmg %r11,%r15,\savearea tm \psworg+1,0x01 # test problem state bit - jz 2f # skip stack setup save - lg %r15,__LC_KERNEL_STACK # problem state -> load ksp #ifdef CONFIG_CHECK_STACK - j 3f -2: tml %r15,STACK_SIZE - CONFIG_STACK_GUARD - jz stack_overflow -3: + jnz 1f + tml %r15,STACK_SIZE - CONFIG_STACK_GUARD + jnz 2f + la %r12,\psworg + j stack_overflow +#else + jz 2f #endif -2: +1: lg %r15,__LC_KERNEL_STACK # problem state -> load ksp +2: aghi %r15,-SP_SIZE # make room for registers & psw + larl %r13,system_call + lg %r11,__LC_LAST_BREAK .endm .macro SAVE_ALL_ASYNC psworg,savearea + stmg %r11,%r15,\savearea + larl %r13,system_call + lg %r11,__LC_LAST_BREAK la %r12,\psworg tm \psworg+1,0x01 # test problem state bit jnz 1f # from user -> load kernel stack @@ -164,27 +168,23 @@ _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \ 0: lg %r14,__LC_ASYNC_STACK # are we already on the async. stack ? slgr %r14,%r15 srag %r14,%r14,STACK_SHIFT - jz 2f -1: lg %r15,__LC_ASYNC_STACK # load async stack #ifdef CONFIG_CHECK_STACK - j 3f -2: tml %r15,STACK_SIZE - CONFIG_STACK_GUARD - jz stack_overflow -3: + jnz 1f + tml %r15,STACK_SIZE - CONFIG_STACK_GUARD + jnz 2f + j stack_overflow +#else + jz 2f #endif -2: +1: lg %r15,__LC_ASYNC_STACK # load async stack +2: aghi %r15,-SP_SIZE # make room for registers & psw .endm - .macro CREATE_STACK_FRAME psworg,savearea - aghi %r15,-SP_SIZE # make room for registers & psw - mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack + .macro CREATE_STACK_FRAME savearea + xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) stg %r2,SP_ORIG_R2(%r15) # store original content of gpr 2 - icm %r12,3,__LC_SVC_ILC - stmg %r0,%r11,SP_R0(%r15) # store gprs %r0-%r11 to kernel stack - st %r12,SP_SVCNR(%r15) - mvc SP_R12(32,%r15),\savearea # move %r12-%r15 to stack - la %r12,0 - stg %r12,__SF_BACKCHAIN(%r15) + mvc SP_R11(40,%r15),\savearea # move %r11-%r15 to stack + stmg %r0,%r10,SP_R0(%r15) # store gprs %r0-%r10 to kernel stack .endm .macro RESTORE_ALL psworg,sync @@ -200,6 +200,13 @@ _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \ lpswe \psworg # back to caller .endm + .macro LAST_BREAK + srag %r10,%r11,23 + jz 0f + stg %r11,__TI_last_break(%r12) +0: + .endm + /* * Scheduler resume function, called by switch_to * gpr2 = (task_struct *) prev @@ -245,37 +252,38 @@ __critical_start: system_call: stpt __LC_SYNC_ENTER_TIMER sysc_saveall: - SAVE_ALL_BASE __LC_SAVE_AREA SAVE_ALL_SVC __LC_SVC_OLD_PSW,__LC_SAVE_AREA - CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA - llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore + CREATE_STACK_FRAME __LC_SAVE_AREA + mvc SP_PSW(16,%r15),__LC_SVC_OLD_PSW + mvc SP_ILC(4,%r15),__LC_SVC_ILC + stg %r7,SP_ARGS(%r15) + lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct sysc_vtime: UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER sysc_stime: UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER sysc_update: mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER + LAST_BREAK sysc_do_svc: - lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct - ltgr %r7,%r7 # test for svc 0 + llgh %r7,SP_SVCNR(%r15) + slag %r7,%r7,2 # shift and test for svc 0 jnz sysc_nr_ok # svc 0: system call number in %r1 - cl %r1,BASED(.Lnr_syscalls) + llgfr %r1,%r1 # clear high word in r1 + cghi %r1,NR_syscalls jnl sysc_nr_ok - lgfr %r7,%r1 # clear high word in r1 + sth %r1,SP_SVCNR(%r15) + slag %r7,%r1,2 # shift and test for svc 0 sysc_nr_ok: - mvc SP_ARGS(8,%r15),SP_R7(%r15) -sysc_do_restart: - sth %r7,SP_SVCNR(%r15) - sllg %r7,%r7,2 # svc number * 4 larl %r10,sys_call_table #ifdef CONFIG_COMPAT - tm __TI_flags+5(%r9),(_TIF_31BIT>>16) # running in 31 bit mode ? + tm __TI_flags+5(%r12),(_TIF_31BIT>>16) # running in 31 bit mode ? jno sysc_noemu larl %r10,sys_call_table_emu # use 31 bit emulation system calls sysc_noemu: #endif - tm __TI_flags+6(%r9),_TIF_SYSCALL + tm __TI_flags+6(%r12),_TIF_SYSCALL lgf %r8,0(%r7,%r10) # load address of system call routine jnz sysc_tracesys basr %r14,%r8 # call sys_xxxx @@ -284,7 +292,7 @@ sysc_noemu: sysc_return: LOCKDEP_SYS_EXIT sysc_tif: - tm __TI_flags+7(%r9),_TIF_WORK_SVC + tm __TI_flags+7(%r12),_TIF_WORK_SVC jnz sysc_work # there is work to do (signals etc.) sysc_restore: RESTORE_ALL __LC_RETURN_PSW,1 @@ -301,17 +309,17 @@ sysc_work: # One of the work bits is on. Find out which one. # sysc_work_tif: - tm __TI_flags+7(%r9),_TIF_MCCK_PENDING + tm __TI_flags+7(%r12),_TIF_MCCK_PENDING jo sysc_mcck_pending - tm __TI_flags+7(%r9),_TIF_NEED_RESCHED + tm __TI_flags+7(%r12),_TIF_NEED_RESCHED jo sysc_reschedule - tm __TI_flags+7(%r9),_TIF_SIGPENDING + tm __TI_flags+7(%r12),_TIF_SIGPENDING jo sysc_sigpending - tm __TI_flags+7(%r9),_TIF_NOTIFY_RESUME + tm __TI_flags+7(%r12),_TIF_NOTIFY_RESUME jo sysc_notify_resume - tm __TI_flags+7(%r9),_TIF_RESTART_SVC + tm __TI_flags+7(%r12),_TIF_RESTART_SVC jo sysc_restart - tm __TI_flags+7(%r9),_TIF_SINGLE_STEP + tm __TI_flags+7(%r12),_TIF_SINGLE_STEP jo sysc_singlestep j sysc_return # beware of critical section cleanup @@ -333,12 +341,12 @@ sysc_mcck_pending: # _TIF_SIGPENDING is set, call do_signal # sysc_sigpending: - ni __TI_flags+7(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP + ni __TI_flags+7(%r12),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP la %r2,SP_PTREGS(%r15) # load pt_regs brasl %r14,do_signal # call do_signal - tm __TI_flags+7(%r9),_TIF_RESTART_SVC + tm __TI_flags+7(%r12),_TIF_RESTART_SVC jo sysc_restart - tm __TI_flags+7(%r9),_TIF_SINGLE_STEP + tm __TI_flags+7(%r12),_TIF_SINGLE_STEP jo sysc_singlestep j sysc_return @@ -354,17 +362,19 @@ sysc_notify_resume: # _TIF_RESTART_SVC is set, set up registers and restart svc # sysc_restart: - ni __TI_flags+7(%r9),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC + ni __TI_flags+7(%r12),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC lg %r7,SP_R2(%r15) # load new svc number mvc SP_R2(8,%r15),SP_ORIG_R2(%r15) # restore first argument lmg %r2,%r6,SP_R2(%r15) # load svc arguments - j sysc_do_restart # restart svc + sth %r7,SP_SVCNR(%r15) + slag %r7,%r7,2 + j sysc_nr_ok # restart svc # # _TIF_SINGLE_STEP is set, call do_single_step # sysc_singlestep: - ni __TI_flags+7(%r9),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP + ni __TI_flags+7(%r12),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number la %r2,SP_PTREGS(%r15) # address of register-save area larl %r14,sysc_return # load adr. of system return @@ -377,8 +387,8 @@ sysc_singlestep: sysc_tracesys: la %r2,SP_PTREGS(%r15) # load pt_regs la %r3,0 - srl %r7,2 - stg %r7,SP_R2(%r15) + llgh %r0,SP_SVCNR(%r15) + stg %r0,SP_R2(%r15) brasl %r14,do_syscall_trace_enter lghi %r0,NR_syscalls clgr %r0,%r2 @@ -391,7 +401,7 @@ sysc_tracego: basr %r14,%r8 # call sys_xxx stg %r2,SP_R2(%r15) # store return value sysc_tracenogo: - tm __TI_flags+6(%r9),_TIF_SYSCALL + tm __TI_flags+6(%r12),_TIF_SYSCALL jz sysc_return la %r2,SP_PTREGS(%r15) # load pt_regs larl %r14,sysc_return # return point is sysc_return @@ -403,7 +413,7 @@ sysc_tracenogo: .globl ret_from_fork ret_from_fork: lg %r13,__LC_SVC_NEW_PSW+8 - lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct + lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct tm SP_PSW+1(%r15),0x01 # forking a kernel thread ? jo 0f stg %r15,SP_R15(%r15) # store stack pointer for new kthread @@ -437,8 +447,8 @@ kernel_execve: lg %r15,__LC_KERNEL_STACK # load ksp aghi %r15,-SP_SIZE # make room for registers & psw lg %r13,__LC_SVC_NEW_PSW+8 - lg %r9,__LC_THREAD_INFO mvc SP_PTREGS(__PT_SIZE,%r15),0(%r12) # copy pt_regs + lg %r12,__LC_THREAD_INFO xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) # TRACE_IRQS_ON stosm __SF_EMPTY(%r15),0x03 # reenable interrupts @@ -465,21 +475,23 @@ pgm_check_handler: * for LPSW?). */ stpt __LC_SYNC_ENTER_TIMER - SAVE_ALL_BASE __LC_SAVE_AREA tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception jnz pgm_per # got per exception -> special case - SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA - CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA + SAVE_ALL_PGM __LC_PGM_OLD_PSW,__LC_SAVE_AREA + CREATE_STACK_FRAME __LC_SAVE_AREA + xc SP_ILC(4,%r15),SP_ILC(%r15) + mvc SP_PSW(16,%r15),__LC_PGM_OLD_PSW + lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct tm SP_PSW+1(%r15),0x01 # interrupting from user ? jz pgm_no_vtime UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER + LAST_BREAK pgm_no_vtime: HANDLE_SIE_INTERCEPT TRACE_IRQS_CHECK_OFF - lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct - mvc SP_ARGS(8,%r15),__LC_LAST_BREAK + stg %r11,SP_ARGS(%r15) lgf %r3,__LC_PGM_ILC # load program interruption code lghi %r8,0x7f ngr %r8,%r3 @@ -503,31 +515,32 @@ pgm_per: clc __LC_PGM_OLD_PSW(16),__LC_SVC_NEW_PSW je pgm_svcper # no interesting special case, ignore PER event - lmg %r12,%r15,__LC_SAVE_AREA lpswe __LC_PGM_OLD_PSW # # Normal per exception # pgm_per_std: - SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA - CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA + SAVE_ALL_PGM __LC_PGM_OLD_PSW,__LC_SAVE_AREA + CREATE_STACK_FRAME __LC_SAVE_AREA + mvc SP_PSW(16,%r15),__LC_PGM_OLD_PSW + lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct tm SP_PSW+1(%r15),0x01 # interrupting from user ? jz pgm_no_vtime2 UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER + LAST_BREAK pgm_no_vtime2: HANDLE_SIE_INTERCEPT TRACE_IRQS_CHECK_OFF - lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct - lg %r1,__TI_task(%r9) + lg %r1,__TI_task(%r12) tm SP_PSW+1(%r15),0x01 # kernel per event ? jz kernel_per mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID mvc __THREAD_per+__PER_address(8,%r1),__LC_PER_ADDRESS mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID - oi __TI_flags+7(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP + oi __TI_flags+7(%r12),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP lgf %r3,__LC_PGM_ILC # load program interruption code lghi %r8,0x7f ngr %r8,%r3 # clear per-event-bit and ilc @@ -538,19 +551,21 @@ pgm_no_vtime2: # it was a single stepped SVC that is causing all the trouble # pgm_svcper: - SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA - CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA + SAVE_ALL_PGM __LC_SVC_OLD_PSW,__LC_SAVE_AREA + CREATE_STACK_FRAME __LC_SAVE_AREA + mvc SP_PSW(16,%r15),__LC_SVC_OLD_PSW + mvc SP_ILC(4,%r15),__LC_SVC_ILC + lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct UPDATE_VTIME __LC_EXIT_TIMER,__LC_SYNC_ENTER_TIMER,__LC_USER_TIMER UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER - llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore - lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct + LAST_BREAK TRACE_IRQS_OFF - lg %r8,__TI_task(%r9) + lg %r8,__TI_task(%r12) mvc __THREAD_per+__PER_atmid(2,%r8),__LC_PER_ATMID mvc __THREAD_per+__PER_address(8,%r8),__LC_PER_ADDRESS mvc __THREAD_per+__PER_access_id(1,%r8),__LC_PER_ACCESS_ID - oi __TI_flags+7(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP + oi __TI_flags+7(%r12),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP TRACE_IRQS_ON stosm __SF_EMPTY(%r15),0x03 # reenable interrupts lmg %r2,%r6,SP_R2(%r15) # load svc arguments @@ -572,16 +587,17 @@ kernel_per: io_int_handler: stck __LC_INT_CLOCK stpt __LC_ASYNC_ENTER_TIMER - SAVE_ALL_BASE __LC_SAVE_AREA+32 - SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+32 - CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+32 + SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+40 + CREATE_STACK_FRAME __LC_SAVE_AREA+40 + mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack + lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct tm SP_PSW+1(%r15),0x01 # interrupting from user ? jz io_no_vtime UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER + LAST_BREAK io_no_vtime: - lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct HANDLE_SIE_INTERCEPT TRACE_IRQS_OFF la %r2,SP_PTREGS(%r15) # address of register-save area @@ -590,7 +606,7 @@ io_return: LOCKDEP_SYS_EXIT TRACE_IRQS_ON io_tif: - tm __TI_flags+7(%r9),_TIF_WORK_INT + tm __TI_flags+7(%r12),_TIF_WORK_INT jnz io_work # there is work to do (signals etc.) io_restore: RESTORE_ALL __LC_RETURN_PSW,0 @@ -610,7 +626,7 @@ io_work: jo io_work_user # yes -> do resched & signal #ifdef CONFIG_PREEMPT # check for preemptive scheduling - icm %r0,15,__TI_precount(%r9) + icm %r0,15,__TI_precount(%r12) jnz io_restore # preemption is disabled tm __TI_flags+7(%r12),_TIF_NEED_RESCHED jno io_restore @@ -645,13 +661,13 @@ io_work_user: # and _TIF_MCCK_PENDING # io_work_tif: - tm __TI_flags+7(%r9),_TIF_MCCK_PENDING + tm __TI_flags+7(%r12),_TIF_MCCK_PENDING jo io_mcck_pending - tm __TI_flags+7(%r9),_TIF_NEED_RESCHED + tm __TI_flags+7(%r12),_TIF_NEED_RESCHED jo io_reschedule - tm __TI_flags+7(%r9),_TIF_SIGPENDING + tm __TI_flags+7(%r12),_TIF_SIGPENDING jo io_sigpending - tm __TI_flags+7(%r9),_TIF_NOTIFY_RESUME + tm __TI_flags+7(%r12),_TIF_NOTIFY_RESUME jo io_notify_resume j io_return # beware of critical section cleanup @@ -706,16 +722,17 @@ io_notify_resume: ext_int_handler: stck __LC_INT_CLOCK stpt __LC_ASYNC_ENTER_TIMER - SAVE_ALL_BASE __LC_SAVE_AREA+32 - SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32 - CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32 + SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+40 + CREATE_STACK_FRAME __LC_SAVE_AREA+40 + mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack + lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct tm SP_PSW+1(%r15),0x01 # interrupting from user ? jz ext_no_vtime UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER + LAST_BREAK ext_no_vtime: - lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct HANDLE_SIE_INTERCEPT TRACE_IRQS_OFF la %r2,SP_PTREGS(%r15) # address of register-save area @@ -734,7 +751,9 @@ mcck_int_handler: la %r1,4095 # revalidate r1 spt __LC_CPU_TIMER_SAVE_AREA-4095(%r1) # revalidate cpu timer lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs - SAVE_ALL_BASE __LC_SAVE_AREA+64 + stmg %r11,%r15,__LC_SAVE_AREA+80 + larl %r13,system_call + lg %r11,__LC_LAST_BREAK la %r12,__LC_MCK_OLD_PSW tm __LC_MCCK_CODE,0x80 # system damage? jo mcck_int_main # yes -> rest of mcck code invalid @@ -769,7 +788,10 @@ mcck_int_main: srag %r14,%r14,PAGE_SHIFT jz 0f lg %r15,__LC_PANIC_STACK # load panic stack -0: CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+64 +0: aghi %r15,-SP_SIZE # make room for registers & psw + CREATE_STACK_FRAME __LC_SAVE_AREA+80 + mvc SP_PSW(16,%r15),0(%r12) + lg %r12,__LC_THREAD_INFO # load pointer to thread_info struct tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid? jno mcck_no_vtime # no -> no timer update tm SP_PSW+1(%r15),0x01 # interrupting from user ? @@ -777,8 +799,8 @@ mcck_int_main: UPDATE_VTIME __LC_EXIT_TIMER,__LC_MCCK_ENTER_TIMER,__LC_USER_TIMER UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER mvc __LC_LAST_UPDATE_TIMER(8),__LC_MCCK_ENTER_TIMER + LAST_BREAK mcck_no_vtime: - lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct la %r2,SP_PTREGS(%r15) # load pt_regs brasl %r14,s390_do_machine_check tm SP_PSW+1(%r15),0x01 # returning to user ? @@ -789,7 +811,7 @@ mcck_no_vtime: xc __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain lgr %r15,%r1 stosm __SF_EMPTY(%r15),0x04 # turn dat on - tm __TI_flags+7(%r9),_TIF_MCCK_PENDING + tm __TI_flags+7(%r12),_TIF_MCCK_PENDING jno mcck_return HANDLE_SIE_INTERCEPT TRACE_IRQS_OFF @@ -803,6 +825,7 @@ mcck_return: jno 0f stpt __LC_EXIT_TIMER 0: lpswe __LC_RETURN_MCCK_PSW # back to caller +mcck_done: /* * Restart interruption handler, kick starter for additional CPUs @@ -858,14 +881,14 @@ stack_overflow: lg %r15,__LC_PANIC_STACK # change to panic stack aghi %r15,-SP_SIZE mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack - stmg %r0,%r11,SP_R0(%r15) # store gprs %r0-%r11 to kernel stack + stmg %r0,%r10,SP_R0(%r15) # store gprs %r0-%r10 to kernel stack la %r1,__LC_SAVE_AREA chi %r12,__LC_SVC_OLD_PSW je 0f chi %r12,__LC_PGM_OLD_PSW je 0f - la %r1,__LC_SAVE_AREA+32 -0: mvc SP_R12(32,%r15),0(%r1) # move %r12-%r15 to stack + la %r1,__LC_SAVE_AREA+40 +0: mvc SP_R11(40,%r15),0(%r1) # move %r11-%r15 to stack mvc SP_ARGS(8,%r15),__LC_LAST_BREAK xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) # clear back chain la %r2,SP_PTREGS(%r15) # load pt_regs @@ -920,21 +943,23 @@ cleanup_system_call: je 0f mvc __LC_SYNC_ENTER_TIMER(8),__LC_ASYNC_ENTER_TIMER 0: cghi %r12,__LC_MCK_OLD_PSW - la %r12,__LC_SAVE_AREA+64 + la %r12,__LC_SAVE_AREA+80 je 0f - la %r12,__LC_SAVE_AREA+32 + la %r12,__LC_SAVE_AREA+40 0: clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+16) jhe cleanup_vtime clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn) jh 0f - mvc __LC_SAVE_AREA(32),0(%r12) -0: stg %r13,8(%r12) - stg %r12,__LC_SAVE_AREA+96 # argh - SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA - CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA - lg %r12,__LC_SAVE_AREA+96 # argh - stg %r15,24(%r12) - llgh %r7,__LC_SVC_INT_CODE + mvc __LC_SAVE_AREA(40),0(%r12) +0: lg %r15,__LC_KERNEL_STACK # problem state -> load ksp + aghi %r15,-SP_SIZE # make room for registers & psw + stg %r15,32(%r12) + stg %r11,0(%r12) + CREATE_STACK_FRAME __LC_SAVE_AREA + mvc SP_PSW(16,%r15),__LC_SVC_OLD_PSW + mvc SP_ILC(4,%r15),__LC_SVC_ILC + stg %r7,SP_ARGS(%r15) + mvc 8(8,%r12),__LC_THREAD_INFO cleanup_vtime: clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+24) jhe cleanup_stime @@ -945,7 +970,11 @@ cleanup_stime: UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER cleanup_update: mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER - mvc __LC_RETURN_PSW+8(8),BASED(cleanup_table_system_call+8) + srag %r12,%r11,23 + lg %r12,__LC_THREAD_INFO + jz 0f + stg %r11,__TI_last_break(%r12) +0: mvc __LC_RETURN_PSW+8(8),BASED(cleanup_table_system_call+8) la %r12,__LC_RETURN_PSW br %r14 cleanup_system_call_insn: @@ -972,11 +1001,11 @@ cleanup_sysc_restore: mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER 0: mvc __LC_RETURN_PSW(16),SP_PSW(%r15) cghi %r12,__LC_MCK_OLD_PSW - la %r12,__LC_SAVE_AREA+64 + la %r12,__LC_SAVE_AREA+80 je 1f - la %r12,__LC_SAVE_AREA+32 -1: mvc 0(32,%r12),SP_R12(%r15) - lmg %r0,%r11,SP_R0(%r15) + la %r12,__LC_SAVE_AREA+40 +1: mvc 0(40,%r12),SP_R11(%r15) + lmg %r0,%r10,SP_R0(%r15) lg %r15,SP_R15(%r15) 2: la %r12,__LC_RETURN_PSW br %r14 @@ -997,8 +1026,8 @@ cleanup_io_restore: jhe 0f mvc __LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER 0: mvc __LC_RETURN_PSW(16),SP_PSW(%r15) - mvc __LC_SAVE_AREA+64(32),SP_R12(%r15) - lmg %r0,%r11,SP_R0(%r15) + mvc __LC_SAVE_AREA+80(40),SP_R11(%r15) + lmg %r0,%r10,SP_R0(%r15) lg %r15,SP_R15(%r15) 1: la %r12,__LC_RETURN_PSW br %r14 @@ -1010,13 +1039,6 @@ cleanup_io_restore_insn: * Integer constants */ .align 4 -.Lconst: -.Lnr_syscalls: .long NR_syscalls -.L0x0130: .short 0x130 -.L0x0140: .short 0x140 -.L0x0150: .short 0x150 -.L0x0160: .short 0x160 -.L0x0170: .short 0x170 .Lcritical_start: .quad __critical_start .Lcritical_end: diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index 9f654da..83339d3 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -57,6 +57,7 @@ enum s390_regset { REGSET_GENERAL, REGSET_FP, + REGSET_LAST_BREAK, REGSET_GENERAL_EXTENDED, }; @@ -381,6 +382,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) copied += sizeof(unsigned long); } return 0; + case PTRACE_GET_LAST_BREAK: + put_user(task_thread_info(child)->last_break, + (unsigned long __user *) data); + return 0; default: /* Removing high order bit from addr (only for 31 bit). */ addr &= PSW_ADDR_INSN; @@ -633,6 +638,10 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, copied += sizeof(unsigned int); } return 0; + case PTRACE_GET_LAST_BREAK: + put_user(task_thread_info(child)->last_break, + (unsigned int __user *) data); + return 0; } return compat_ptrace_request(child, request, addr, data); } @@ -797,6 +806,28 @@ static int s390_fpregs_set(struct task_struct *target, return rc; } +#ifdef CONFIG_64BIT + +static int s390_last_break_get(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + void *kbuf, void __user *ubuf) +{ + if (count > 0) { + if (kbuf) { + unsigned long *k = kbuf; + *k = task_thread_info(target)->last_break; + } else { + unsigned long __user *u = ubuf; + if (__put_user(task_thread_info(target)->last_break, u)) + return -EFAULT; + } + } + return 0; +} + +#endif + static const struct user_regset s390_regsets[] = { [REGSET_GENERAL] = { .core_note_type = NT_PRSTATUS, @@ -814,6 +845,15 @@ static const struct user_regset s390_regsets[] = { .get = s390_fpregs_get, .set = s390_fpregs_set, }, +#ifdef CONFIG_64BIT + [REGSET_LAST_BREAK] = { + .core_note_type = NT_S390_LAST_BREAK, + .n = 1, + .size = sizeof(long), + .align = sizeof(long), + .get = s390_last_break_get, + }, +#endif }; static const struct user_regset_view user_s390_view = { @@ -948,6 +988,27 @@ static int s390_compat_regs_high_set(struct task_struct *target, return rc; } +static int s390_compat_last_break_get(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + void *kbuf, void __user *ubuf) +{ + compat_ulong_t last_break; + + if (count > 0) { + last_break = task_thread_info(target)->last_break; + if (kbuf) { + unsigned long *k = kbuf; + *k = last_break; + } else { + unsigned long __user *u = ubuf; + if (__put_user(last_break, u)) + return -EFAULT; + } + } + return 0; +} + static const struct user_regset s390_compat_regsets[] = { [REGSET_GENERAL] = { .core_note_type = NT_PRSTATUS, @@ -965,6 +1026,13 @@ static const struct user_regset s390_compat_regsets[] = { .get = s390_fpregs_get, .set = s390_fpregs_set, }, + [REGSET_LAST_BREAK] = { + .core_note_type = NT_S390_LAST_BREAK, + .n = 1, + .size = sizeof(long), + .align = sizeof(long), + .get = s390_compat_last_break_get, + }, [REGSET_GENERAL_EXTENDED] = { .core_note_type = NT_S390_HIGH_GPRS, .n = sizeof(s390_compat_regs_high) / sizeof(compat_long_t), diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c index 6289945..ee7ac8b 100644 --- a/arch/s390/kernel/signal.c +++ b/arch/s390/kernel/signal.c @@ -313,6 +313,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, To avoid breaking binary compatibility, they are passed as args. */ regs->gprs[4] = current->thread.trap_no; regs->gprs[5] = current->thread.prot_addr; + regs->gprs[6] = task_thread_info(current)->last_break; /* Place signal number on stack to allow backtrace from handler. */ if (__put_user(regs->gprs[2], (int __user *) &frame->signo)) @@ -376,6 +377,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, regs->gprs[2] = map_signal(sig); regs->gprs[3] = (unsigned long) &frame->info; regs->gprs[4] = (unsigned long) &frame->uc; + regs->gprs[5] = task_thread_info(current)->last_break; return 0; give_sigsegv: diff --git a/include/linux/elf.h b/include/linux/elf.h index 5978584..4d60801 100644 --- a/include/linux/elf.h +++ b/include/linux/elf.h @@ -394,6 +394,7 @@ typedef struct elf64_shdr { #define NT_S390_TODPREG 0x303 /* s390 TOD programmable register */ #define NT_S390_CTRS 0x304 /* s390 control registers */ #define NT_S390_PREFIX 0x305 /* s390 prefix register */ +#define NT_S390_LAST_BREAK 0x306 /* s390 breaking event address */ /* Note header in a PT_NOTE section */ -- cgit v0.10.2 From f73a2b03c59b95a3ee8eebcc127350c77c950e87 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 17 May 2010 10:00:06 +0200 Subject: [S390] vmcp: disallow modular build Change the tristate Kbuild option into a bool option so that the module is either builtin or not available at all. There have been too many cases where people were missing the 'vmcp' device node and unable to send z/VM CP commands. So let's make sure that on distros it will always be present. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky diff --git a/drivers/s390/char/Kconfig b/drivers/s390/char/Kconfig index 4e34d36..40834f1 100644 --- a/drivers/s390/char/Kconfig +++ b/drivers/s390/char/Kconfig @@ -148,13 +148,12 @@ config VMLOGRDR This driver depends on the IUCV support driver. config VMCP - tristate "Support for the z/VM CP interface (VM only)" + bool "Support for the z/VM CP interface" depends on S390 help Select this option if you want to be able to interact with the control program on z/VM - config MONREADER tristate "API for reading z/VM monitor service records" depends on IUCV diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c index 5bb59d3..04e532e 100644 --- a/drivers/s390/char/vmcp.c +++ b/drivers/s390/char/vmcp.c @@ -1,24 +1,20 @@ /* - * Copyright IBM Corp. 2004,2007 + * Copyright IBM Corp. 2004,2010 * Interface implementation for communication with the z/VM control program - * Author(s): Christian Borntraeger * + * Author(s): Christian Borntraeger * * z/VMs CP offers the possibility to issue commands via the diagnose code 8 * this driver implements a character device that issues these commands and * returns the answer of CP. - + * * The idea of this driver is based on cpint from Neale Ferguson and #CP in CMS */ -#define KMSG_COMPONENT "vmcp" -#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt - #include #include #include #include -#include #include #include #include @@ -26,10 +22,6 @@ #include #include "vmcp.h" -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Christian Borntraeger "); -MODULE_DESCRIPTION("z/VM CP interface"); - static debug_info_t *vmcp_debug; static int vmcp_open(struct inode *inode, struct file *file) @@ -197,11 +189,8 @@ static int __init vmcp_init(void) { int ret; - if (!MACHINE_IS_VM) { - pr_warning("The z/VM CP interface device driver cannot be " - "loaded without z/VM\n"); - return -ENODEV; - } + if (!MACHINE_IS_VM) + return 0; vmcp_debug = debug_register("vmcp", 1, 1, 240); if (!vmcp_debug) @@ -214,19 +203,8 @@ static int __init vmcp_init(void) } ret = misc_register(&vmcp_dev); - if (ret) { + if (ret) debug_unregister(vmcp_debug); - return ret; - } - - return 0; -} - -static void __exit vmcp_exit(void) -{ - misc_deregister(&vmcp_dev); - debug_unregister(vmcp_debug); + return ret; } - -module_init(vmcp_init); -module_exit(vmcp_exit); +device_initcall(vmcp_init); -- cgit v0.10.2 From 58ea91c05346f7c6336e6248b743aa9a8e1c19a9 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Mon, 17 May 2010 10:00:07 +0200 Subject: [S390] avoid default_llseek in s390 drivers Use nonseekable_open for a couple of s390 device drivers. This avoids the use of default_llseek function which has a dependency on the BKL. Signed-off-by: Martin Schwidefsky diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c index c53f8ac..95c1aaa 100644 --- a/arch/s390/hypfs/inode.c +++ b/arch/s390/hypfs/inode.c @@ -145,7 +145,7 @@ static int hypfs_open(struct inode *inode, struct file *filp) } mutex_unlock(&fs_info->lock); } - return 0; + return nonseekable_open(inode, filp); } static ssize_t hypfs_aio_read(struct kiocb *iocb, const struct iovec *iov, diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c index 0168472..9819226 100644 --- a/arch/s390/kernel/debug.c +++ b/arch/s390/kernel/debug.c @@ -655,6 +655,7 @@ found: p_info->act_entry_offset = 0; file->private_data = p_info; debug_info_get(debug_info); + nonseekable_open(inode, file); out: mutex_unlock(&debug_mutex); return rc; diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c index 0eabcca..857dfcb 100644 --- a/drivers/s390/char/fs3270.c +++ b/drivers/s390/char/fs3270.c @@ -484,6 +484,7 @@ fs3270_open(struct inode *inode, struct file *filp) raw3270_del_view(&fp->view); goto out; } + nonseekable_open(inode, filp); filp->private_data = fp; out: mutex_unlock(&fs3270_mutex); diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index 7217966..f5ea338 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c @@ -445,7 +445,7 @@ static int zcore_memmap_open(struct inode *inode, struct file *filp) } kfree(chunk_array); filp->private_data = buf; - return 0; + return nonseekable_open(inode, filp); } static int zcore_memmap_release(struct inode *inode, struct file *filp) @@ -473,7 +473,7 @@ static ssize_t zcore_reipl_write(struct file *filp, const char __user *buf, static int zcore_reipl_open(struct inode *inode, struct file *filp) { - return 0; + return nonseekable_open(inode, filp); } static int zcore_reipl_release(struct inode *inode, struct file *filp) diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c index 3b6f4ad..a83877c 100644 --- a/drivers/s390/cio/chsc_sch.c +++ b/drivers/s390/cio/chsc_sch.c @@ -803,6 +803,7 @@ static long chsc_ioctl(struct file *filp, unsigned int cmd, static const struct file_operations chsc_fops = { .owner = THIS_MODULE, + .open = nonseekable_open, .unlocked_ioctl = chsc_ioctl, .compat_ioctl = chsc_ioctl, }; diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index da6df04..ac94ac75 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -1065,6 +1065,7 @@ static ssize_t cio_settle_write(struct file *file, const char __user *buf, } static const struct file_operations cio_settle_proc_fops = { + .open = nonseekable_open, .write = cio_settle_write, }; diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index 304caf5..41e0aae 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c @@ -302,7 +302,7 @@ static ssize_t zcrypt_write(struct file *filp, const char __user *buf, static int zcrypt_open(struct inode *inode, struct file *filp) { atomic_inc(&zcrypt_open_count); - return 0; + return nonseekable_open(inode, filp); } /** diff --git a/drivers/s390/scsi/zfcp_cfdc.c b/drivers/s390/scsi/zfcp_cfdc.c index 25d9e0a..1a2db0a 100644 --- a/drivers/s390/scsi/zfcp_cfdc.c +++ b/drivers/s390/scsi/zfcp_cfdc.c @@ -254,6 +254,7 @@ static long zfcp_cfdc_dev_ioctl(struct file *file, unsigned int command, } static const struct file_operations zfcp_cfdc_fops = { + .open = nonseekable_open, .unlocked_ioctl = zfcp_cfdc_dev_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = zfcp_cfdc_dev_ioctl -- cgit v0.10.2 From a78f1c4c1dc4b9dedd17c46dd414f26c7bf1e503 Mon Sep 17 00:00:00 2001 From: Christoph Egger Date: Mon, 17 May 2010 10:00:08 +0200 Subject: [S390] vdso: remove redundant check for CONFIG_64BIT This is a check for CONFIG_64BIT inside a block that is only active when CONFIG_64BIT is set. So the check is actually useless and potentially irritating. Signed-off-by: Christoph Egger Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c index 6bc9c19..6b83870 100644 --- a/arch/s390/kernel/vdso.c +++ b/arch/s390/kernel/vdso.c @@ -102,11 +102,7 @@ static void vdso_init_per_cpu_data(int cpu, struct vdso_per_cpu_data *vpcd) /* * Allocate/free per cpu vdso data. */ -#ifdef CONFIG_64BIT #define SEGMENT_ORDER 2 -#else -#define SEGMENT_ORDER 1 -#endif int vdso_alloc_per_cpu(int cpu, struct _lowcore *lowcore) { -- cgit v0.10.2 From f3cb31e495668eae568c584c666631e26c68bdea Mon Sep 17 00:00:00 2001 From: Hendrik Brueckner Date: Mon, 17 May 2010 10:00:09 +0200 Subject: [S390] vdso: add missing vdso_install target Add missing vdso_install target to install the unstripped vdso images into $(MODLIB)/vdso/. These files are helpful when containing additional debugging information. Signed-off-by: Hendrik Brueckner Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky diff --git a/arch/s390/Makefile b/arch/s390/Makefile index 0da1074..30c5f01 100644 --- a/arch/s390/Makefile +++ b/arch/s390/Makefile @@ -116,6 +116,12 @@ image bzImage: vmlinux zfcpdump: $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ +vdso_install: +ifeq ($(CONFIG_64BIT),y) + $(Q)$(MAKE) $(build)=arch/$(ARCH)/kernel/vdso64 $@ +endif + $(Q)$(MAKE) $(build)=arch/$(ARCH)/kernel/vdso32 $@ + archclean: $(Q)$(MAKE) $(clean)=$(boot) -- cgit v0.10.2 From 501183f2ed74434e30a1b039b2f3af30f1f3f461 Mon Sep 17 00:00:00 2001 From: Stefan Haberland Date: Mon, 17 May 2010 10:00:10 +0200 Subject: [S390] dasd: add dynamic pav toleration For base Parallel Access Volume (PAV) there is a fixed mapping of base and alias devices. With dynamic PAV this mapping can be changed so that an alias device is used with another base device. This patch enables the DASD device driver to tolerate dynamic PAV changes. Signed-off-by: Stefan Haberland Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index fa2339c..0e86247 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -65,6 +65,7 @@ static void dasd_device_tasklet(struct dasd_device *); static void dasd_block_tasklet(struct dasd_block *); static void do_kick_device(struct work_struct *); static void do_restore_device(struct work_struct *); +static void do_reload_device(struct work_struct *); static void dasd_return_cqr_cb(struct dasd_ccw_req *, void *); static void dasd_device_timeout(unsigned long); static void dasd_block_timeout(unsigned long); @@ -115,6 +116,7 @@ struct dasd_device *dasd_alloc_device(void) device->timer.data = (unsigned long) device; INIT_WORK(&device->kick_work, do_kick_device); INIT_WORK(&device->restore_device, do_restore_device); + INIT_WORK(&device->reload_device, do_reload_device); device->state = DASD_STATE_NEW; device->target = DASD_STATE_NEW; mutex_init(&device->state_mutex); @@ -521,6 +523,26 @@ void dasd_kick_device(struct dasd_device *device) } /* + * dasd_reload_device will schedule a call do do_reload_device to the kernel + * event daemon. + */ +static void do_reload_device(struct work_struct *work) +{ + struct dasd_device *device = container_of(work, struct dasd_device, + reload_device); + device->discipline->reload(device); + dasd_put_device(device); +} + +void dasd_reload_device(struct dasd_device *device) +{ + dasd_get_device(device); + /* queue call to dasd_reload_device to the kernel event daemon. */ + schedule_work(&device->reload_device); +} +EXPORT_SYMBOL(dasd_reload_device); + +/* * dasd_restore_device will schedule a call do do_restore_device to the kernel * event daemon. */ diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c index 6632649..85bfd87 100644 --- a/drivers/s390/block/dasd_3990_erp.c +++ b/drivers/s390/block/dasd_3990_erp.c @@ -1418,9 +1418,29 @@ static struct dasd_ccw_req *dasd_3990_erp_inspect_alias( struct dasd_ccw_req *erp) { struct dasd_ccw_req *cqr = erp->refers; + char *sense; if (cqr->block && (cqr->block->base != cqr->startdev)) { + + sense = dasd_get_sense(&erp->refers->irb); + /* + * dynamic pav may have changed base alias mapping + */ + if (!test_bit(DASD_FLAG_OFFLINE, &cqr->startdev->flags) && sense + && (sense[0] == 0x10) && (sense[7] == 0x0F) + && (sense[8] == 0x67)) { + /* + * remove device from alias handling to prevent new + * requests from being scheduled on the + * wrong alias device + */ + dasd_alias_remove_device(cqr->startdev); + + /* schedule worker to reload device */ + dasd_reload_device(cqr->startdev); + } + if (cqr->startdev->features & DASD_FEATURE_ERPLOG) { DBF_DEV_EVENT(DBF_ERR, cqr->startdev, "ERP on alias device for request %p," diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c index 8c48142..a564b99 100644 --- a/drivers/s390/block/dasd_alias.c +++ b/drivers/s390/block/dasd_alias.c @@ -642,6 +642,14 @@ int dasd_alias_add_device(struct dasd_device *device) return rc; } +int dasd_alias_update_add_device(struct dasd_device *device) +{ + struct dasd_eckd_private *private; + private = (struct dasd_eckd_private *) device->private; + private->lcu->flags |= UPDATE_PENDING; + return dasd_alias_add_device(device); +} + int dasd_alias_remove_device(struct dasd_device *device) { struct dasd_eckd_private *private; diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 0cb2331..4305c23 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -1451,6 +1451,7 @@ static int dasd_eckd_ready_to_online(struct dasd_device *device) static int dasd_eckd_online_to_ready(struct dasd_device *device) { + cancel_work_sync(&device->reload_device); return dasd_alias_remove_device(device); }; @@ -1709,10 +1710,27 @@ static void dasd_eckd_handle_unsolicited_interrupt(struct dasd_device *device, { char mask; char *sense = NULL; + struct dasd_eckd_private *private; + private = (struct dasd_eckd_private *) device->private; /* first of all check for state change pending interrupt */ mask = DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP; if ((scsw_dstat(&irb->scsw) & mask) == mask) { + /* for alias only and not in offline processing*/ + if (!device->block && private->lcu && + !test_bit(DASD_FLAG_OFFLINE, &device->flags)) { + /* + * the state change could be caused by an alias + * reassignment remove device from alias handling + * to prevent new requests from being scheduled on + * the wrong alias device + */ + dasd_alias_remove_device(device); + + /* schedule worker to reload device */ + dasd_reload_device(device); + } + dasd_generic_handle_state_change(device); return; } @@ -3259,7 +3277,7 @@ static void dasd_eckd_dump_sense(struct dasd_device *device, dasd_eckd_dump_sense_ccw(device, req, irb); } -int dasd_eckd_pm_freeze(struct dasd_device *device) +static int dasd_eckd_pm_freeze(struct dasd_device *device) { /* * the device should be disconnected from our LCU structure @@ -3272,7 +3290,7 @@ int dasd_eckd_pm_freeze(struct dasd_device *device) return 0; } -int dasd_eckd_restore_device(struct dasd_device *device) +static int dasd_eckd_restore_device(struct dasd_device *device) { struct dasd_eckd_private *private; struct dasd_eckd_characteristics temp_rdc_data; @@ -3336,6 +3354,53 @@ out_err: return -1; } +static int dasd_eckd_reload_device(struct dasd_device *device) +{ + struct dasd_eckd_private *private; + int rc, old_base; + char uid[60]; + + private = (struct dasd_eckd_private *) device->private; + old_base = private->uid.base_unit_addr; + /* Read Configuration Data */ + rc = dasd_eckd_read_conf(device); + if (rc) + goto out_err; + + rc = dasd_eckd_generate_uid(device, &private->uid); + if (rc) + goto out_err; + + dasd_set_uid(device->cdev, &private->uid); + + /* + * update unit address configuration and + * add device to alias management + */ + dasd_alias_update_add_device(device); + + if (old_base != private->uid.base_unit_addr) { + if (strlen(private->uid.vduit) > 0) + snprintf(uid, 60, "%s.%s.%04x.%02x.%s", + private->uid.vendor, private->uid.serial, + private->uid.ssid, private->uid.base_unit_addr, + private->uid.vduit); + else + snprintf(uid, 60, "%s.%s.%04x.%02x", + private->uid.vendor, private->uid.serial, + private->uid.ssid, + private->uid.base_unit_addr); + + dev_info(&device->cdev->dev, + "An Alias device was reassigned to a new base device " + "with UID: %s\n", uid); + } + return 0; + +out_err: + return -1; +} + static struct ccw_driver dasd_eckd_driver = { .name = "dasd-eckd", .owner = THIS_MODULE, @@ -3389,6 +3454,7 @@ static struct dasd_discipline dasd_eckd_discipline = { .ioctl = dasd_eckd_ioctl, .freeze = dasd_eckd_pm_freeze, .restore = dasd_eckd_restore_device, + .reload = dasd_eckd_reload_device, }; static int __init diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h index 864d53c..dd6385a 100644 --- a/drivers/s390/block/dasd_eckd.h +++ b/drivers/s390/block/dasd_eckd.h @@ -426,7 +426,6 @@ struct alias_pav_group { struct dasd_device *next; }; - struct dasd_eckd_private { struct dasd_eckd_characteristics rdc_data; u8 *conf_data; @@ -463,4 +462,5 @@ void dasd_alias_handle_summary_unit_check(struct dasd_device *, struct irb *); void dasd_eckd_reset_ccw_to_base_io(struct dasd_ccw_req *); void dasd_alias_lcu_setup_complete(struct dasd_device *); void dasd_alias_wait_for_lcu_setup(struct dasd_device *); +int dasd_alias_update_add_device(struct dasd_device *); #endif /* DASD_ECKD_H */ diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index a91d4a9..1ae7b12 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -312,6 +312,9 @@ struct dasd_discipline { /* suspend/resume functions */ int (*freeze) (struct dasd_device *); int (*restore) (struct dasd_device *); + + /* reload device after state change */ + int (*reload) (struct dasd_device *); }; extern struct dasd_discipline *dasd_diag_discipline_pointer; @@ -386,6 +389,7 @@ struct dasd_device { struct tasklet_struct tasklet; struct work_struct kick_work; struct work_struct restore_device; + struct work_struct reload_device; struct timer_list timer; debug_info_t *debug_area; @@ -582,6 +586,7 @@ void dasd_enable_device(struct dasd_device *); void dasd_set_target_state(struct dasd_device *, int); void dasd_kick_device(struct dasd_device *); void dasd_restore_device(struct dasd_device *); +void dasd_reload_device(struct dasd_device *); void dasd_add_request_head(struct dasd_ccw_req *); void dasd_add_request_tail(struct dasd_ccw_req *); -- cgit v0.10.2 From 2dedf0d9eadf39660f2e1686b5d36e4a7515803f Mon Sep 17 00:00:00 2001 From: Stefan Haberland Date: Mon, 17 May 2010 10:00:11 +0200 Subject: [S390] dasd: remove uid from devmap Remove the duplicate of the DASD uid from the devmap structure. Use the uid from the device private structure instead. This also removes a lockdep warning complaining about a possible SOFTIRQ-safe -> SOFTIRQ-unsafe lock order. Signed-off-by: Stefan Haberland Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c index a564b99..4155805 100644 --- a/drivers/s390/block/dasd_alias.c +++ b/drivers/s390/block/dasd_alias.c @@ -190,20 +190,21 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device) struct alias_server *server, *newserver; struct alias_lcu *lcu, *newlcu; int is_lcu_known; - struct dasd_uid *uid; + struct dasd_uid uid; private = (struct dasd_eckd_private *) device->private; - uid = &private->uid; + + device->discipline->get_uid(device, &uid); spin_lock_irqsave(&aliastree.lock, flags); is_lcu_known = 1; - server = _find_server(uid); + server = _find_server(&uid); if (!server) { spin_unlock_irqrestore(&aliastree.lock, flags); - newserver = _allocate_server(uid); + newserver = _allocate_server(&uid); if (IS_ERR(newserver)) return PTR_ERR(newserver); spin_lock_irqsave(&aliastree.lock, flags); - server = _find_server(uid); + server = _find_server(&uid); if (!server) { list_add(&newserver->server, &aliastree.serverlist); server = newserver; @@ -214,14 +215,14 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device) } } - lcu = _find_lcu(server, uid); + lcu = _find_lcu(server, &uid); if (!lcu) { spin_unlock_irqrestore(&aliastree.lock, flags); - newlcu = _allocate_lcu(uid); + newlcu = _allocate_lcu(&uid); if (IS_ERR(newlcu)) return PTR_ERR(newlcu); spin_lock_irqsave(&aliastree.lock, flags); - lcu = _find_lcu(server, uid); + lcu = _find_lcu(server, &uid); if (!lcu) { list_add(&newlcu->lcu, &server->lculist); lcu = newlcu; @@ -256,20 +257,20 @@ void dasd_alias_lcu_setup_complete(struct dasd_device *device) unsigned long flags; struct alias_server *server; struct alias_lcu *lcu; - struct dasd_uid *uid; + struct dasd_uid uid; private = (struct dasd_eckd_private *) device->private; - uid = &private->uid; + device->discipline->get_uid(device, &uid); lcu = NULL; spin_lock_irqsave(&aliastree.lock, flags); - server = _find_server(uid); + server = _find_server(&uid); if (server) - lcu = _find_lcu(server, uid); + lcu = _find_lcu(server, &uid); spin_unlock_irqrestore(&aliastree.lock, flags); if (!lcu) { DBF_EVENT_DEVID(DBF_ERR, device->cdev, "could not find lcu for %04x %02x", - uid->ssid, uid->real_unit_addr); + uid.ssid, uid.real_unit_addr); WARN_ON(1); return; } @@ -282,20 +283,20 @@ void dasd_alias_wait_for_lcu_setup(struct dasd_device *device) unsigned long flags; struct alias_server *server; struct alias_lcu *lcu; - struct dasd_uid *uid; + struct dasd_uid uid; private = (struct dasd_eckd_private *) device->private; - uid = &private->uid; + device->discipline->get_uid(device, &uid); lcu = NULL; spin_lock_irqsave(&aliastree.lock, flags); - server = _find_server(uid); + server = _find_server(&uid); if (server) - lcu = _find_lcu(server, uid); + lcu = _find_lcu(server, &uid); spin_unlock_irqrestore(&aliastree.lock, flags); if (!lcu) { DBF_EVENT_DEVID(DBF_ERR, device->cdev, "could not find lcu for %04x %02x", - uid->ssid, uid->real_unit_addr); + uid.ssid, uid.real_unit_addr); WARN_ON(1); return; } @@ -314,9 +315,11 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device) struct alias_lcu *lcu; struct alias_server *server; int was_pending; + struct dasd_uid uid; private = (struct dasd_eckd_private *) device->private; lcu = private->lcu; + device->discipline->get_uid(device, &uid); spin_lock_irqsave(&lcu->lock, flags); list_del_init(&device->alias_list); /* make sure that the workers don't use this device */ @@ -353,7 +356,7 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device) _schedule_lcu_update(lcu, NULL); spin_unlock(&lcu->lock); } - server = _find_server(&private->uid); + server = _find_server(&uid); if (server && list_empty(&server->lculist)) { list_del(&server->server); _free_server(server); @@ -366,19 +369,30 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device) * in the lcu is up to date and will update the device uid before * adding it to a pav group. */ + static int _add_device_to_lcu(struct alias_lcu *lcu, - struct dasd_device *device) + struct dasd_device *device, + struct dasd_device *pos) { struct dasd_eckd_private *private; struct alias_pav_group *group; - struct dasd_uid *uid; + struct dasd_uid uid; + unsigned long flags; private = (struct dasd_eckd_private *) device->private; - uid = &private->uid; - uid->type = lcu->uac->unit[uid->real_unit_addr].ua_type; - uid->base_unit_addr = lcu->uac->unit[uid->real_unit_addr].base_ua; - dasd_set_uid(device->cdev, &private->uid); + + /* only lock if not already locked */ + if (device != pos) + spin_lock_irqsave_nested(get_ccwdev_lock(device->cdev), flags, + CDEV_NESTED_SECOND); + private->uid.type = lcu->uac->unit[private->uid.real_unit_addr].ua_type; + private->uid.base_unit_addr = + lcu->uac->unit[private->uid.real_unit_addr].base_ua; + uid = private->uid; + + if (device != pos) + spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); /* if we have no PAV anyway, we don't need to bother with PAV groups */ if (lcu->pav == NO_PAV) { @@ -386,25 +400,25 @@ static int _add_device_to_lcu(struct alias_lcu *lcu, return 0; } - group = _find_group(lcu, uid); + group = _find_group(lcu, &uid); if (!group) { group = kzalloc(sizeof(*group), GFP_ATOMIC); if (!group) return -ENOMEM; - memcpy(group->uid.vendor, uid->vendor, sizeof(uid->vendor)); - memcpy(group->uid.serial, uid->serial, sizeof(uid->serial)); - group->uid.ssid = uid->ssid; - if (uid->type == UA_BASE_DEVICE) - group->uid.base_unit_addr = uid->real_unit_addr; + memcpy(group->uid.vendor, uid.vendor, sizeof(uid.vendor)); + memcpy(group->uid.serial, uid.serial, sizeof(uid.serial)); + group->uid.ssid = uid.ssid; + if (uid.type == UA_BASE_DEVICE) + group->uid.base_unit_addr = uid.real_unit_addr; else - group->uid.base_unit_addr = uid->base_unit_addr; - memcpy(group->uid.vduit, uid->vduit, sizeof(uid->vduit)); + group->uid.base_unit_addr = uid.base_unit_addr; + memcpy(group->uid.vduit, uid.vduit, sizeof(uid.vduit)); INIT_LIST_HEAD(&group->group); INIT_LIST_HEAD(&group->baselist); INIT_LIST_HEAD(&group->aliaslist); list_add(&group->group, &lcu->grouplist); } - if (uid->type == UA_BASE_DEVICE) + if (uid.type == UA_BASE_DEVICE) list_move(&device->alias_list, &group->baselist); else list_move(&device->alias_list, &group->aliaslist); @@ -525,7 +539,10 @@ static int _lcu_update(struct dasd_device *refdev, struct alias_lcu *lcu) if (rc) return rc; - spin_lock_irqsave(&lcu->lock, flags); + /* need to take cdev lock before lcu lock */ + spin_lock_irqsave_nested(get_ccwdev_lock(refdev->cdev), flags, + CDEV_NESTED_FIRST); + spin_lock(&lcu->lock); lcu->pav = NO_PAV; for (i = 0; i < MAX_DEVICES_PER_LCU; ++i) { switch (lcu->uac->unit[i].ua_type) { @@ -542,9 +559,10 @@ static int _lcu_update(struct dasd_device *refdev, struct alias_lcu *lcu) list_for_each_entry_safe(device, tempdev, &lcu->active_devices, alias_list) { - _add_device_to_lcu(lcu, device); + _add_device_to_lcu(lcu, device, refdev); } - spin_unlock_irqrestore(&lcu->lock, flags); + spin_unlock(&lcu->lock); + spin_unlock_irqrestore(get_ccwdev_lock(refdev->cdev), flags); return 0; } @@ -628,9 +646,12 @@ int dasd_alias_add_device(struct dasd_device *device) private = (struct dasd_eckd_private *) device->private; lcu = private->lcu; rc = 0; - spin_lock_irqsave(&lcu->lock, flags); + + /* need to take cdev lock before lcu lock */ + spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); + spin_lock(&lcu->lock); if (!(lcu->flags & UPDATE_PENDING)) { - rc = _add_device_to_lcu(lcu, device); + rc = _add_device_to_lcu(lcu, device, device); if (rc) lcu->flags |= UPDATE_PENDING; } @@ -638,7 +659,8 @@ int dasd_alias_add_device(struct dasd_device *device) list_move(&device->alias_list, &lcu->active_devices); _schedule_lcu_update(lcu, device); } - spin_unlock_irqrestore(&lcu->lock, flags); + spin_unlock(&lcu->lock); + spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); return rc; } @@ -748,19 +770,30 @@ static void _restart_all_base_devices_on_lcu(struct alias_lcu *lcu) struct alias_pav_group *pavgroup; struct dasd_device *device; struct dasd_eckd_private *private; + unsigned long flags; /* active and inactive list can contain alias as well as base devices */ list_for_each_entry(device, &lcu->active_devices, alias_list) { private = (struct dasd_eckd_private *) device->private; - if (private->uid.type != UA_BASE_DEVICE) + spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); + if (private->uid.type != UA_BASE_DEVICE) { + spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), + flags); continue; + } + spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); dasd_schedule_block_bh(device->block); dasd_schedule_device_bh(device); } list_for_each_entry(device, &lcu->inactive_devices, alias_list) { private = (struct dasd_eckd_private *) device->private; - if (private->uid.type != UA_BASE_DEVICE) + spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); + if (private->uid.type != UA_BASE_DEVICE) { + spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), + flags); continue; + } + spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); dasd_schedule_block_bh(device->block); dasd_schedule_device_bh(device); } diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index eff9c81..34d51dd 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c @@ -49,7 +49,6 @@ struct dasd_devmap { unsigned int devindex; unsigned short features; struct dasd_device *device; - struct dasd_uid uid; }; /* @@ -936,42 +935,46 @@ dasd_device_status_show(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR(status, 0444, dasd_device_status_show, NULL); -static ssize_t -dasd_alias_show(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t dasd_alias_show(struct device *dev, + struct device_attribute *attr, char *buf) { - struct dasd_devmap *devmap; - int alias; + struct dasd_device *device; + struct dasd_uid uid; - devmap = dasd_find_busid(dev_name(dev)); - spin_lock(&dasd_devmap_lock); - if (IS_ERR(devmap) || strlen(devmap->uid.vendor) == 0) { - spin_unlock(&dasd_devmap_lock); + device = dasd_device_from_cdev(to_ccwdev(dev)); + if (IS_ERR(device)) return sprintf(buf, "0\n"); + + if (device->discipline && device->discipline->get_uid && + !device->discipline->get_uid(device, &uid)) { + if (uid.type == UA_BASE_PAV_ALIAS || + uid.type == UA_HYPER_PAV_ALIAS) + return sprintf(buf, "1\n"); } - if (devmap->uid.type == UA_BASE_PAV_ALIAS || - devmap->uid.type == UA_HYPER_PAV_ALIAS) - alias = 1; - else - alias = 0; - spin_unlock(&dasd_devmap_lock); - return sprintf(buf, alias ? "1\n" : "0\n"); + dasd_put_device(device); + + return sprintf(buf, "0\n"); } static DEVICE_ATTR(alias, 0444, dasd_alias_show, NULL); -static ssize_t -dasd_vendor_show(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t dasd_vendor_show(struct device *dev, + struct device_attribute *attr, char *buf) { - struct dasd_devmap *devmap; + struct dasd_device *device; + struct dasd_uid uid; char *vendor; - devmap = dasd_find_busid(dev_name(dev)); - spin_lock(&dasd_devmap_lock); - if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0) - vendor = devmap->uid.vendor; - else - vendor = ""; - spin_unlock(&dasd_devmap_lock); + device = dasd_device_from_cdev(to_ccwdev(dev)); + vendor = ""; + if (IS_ERR(device)) + return snprintf(buf, PAGE_SIZE, "%s\n", vendor); + + if (device->discipline && device->discipline->get_uid && + !device->discipline->get_uid(device, &uid)) + vendor = uid.vendor; + + dasd_put_device(device); return snprintf(buf, PAGE_SIZE, "%s\n", vendor); } @@ -985,48 +988,51 @@ static DEVICE_ATTR(vendor, 0444, dasd_vendor_show, NULL); static ssize_t dasd_uid_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct dasd_devmap *devmap; + struct dasd_device *device; + struct dasd_uid uid; char uid_string[UID_STRLEN]; char ua_string[3]; - struct dasd_uid *uid; - devmap = dasd_find_busid(dev_name(dev)); - spin_lock(&dasd_devmap_lock); - if (IS_ERR(devmap) || strlen(devmap->uid.vendor) == 0) { - spin_unlock(&dasd_devmap_lock); - return sprintf(buf, "\n"); - } - uid = &devmap->uid; - switch (uid->type) { - case UA_BASE_DEVICE: - sprintf(ua_string, "%02x", uid->real_unit_addr); - break; - case UA_BASE_PAV_ALIAS: - sprintf(ua_string, "%02x", uid->base_unit_addr); - break; - case UA_HYPER_PAV_ALIAS: - sprintf(ua_string, "xx"); - break; - default: - /* should not happen, treat like base device */ - sprintf(ua_string, "%02x", uid->real_unit_addr); - break; + device = dasd_device_from_cdev(to_ccwdev(dev)); + uid_string[0] = 0; + if (IS_ERR(device)) + return snprintf(buf, PAGE_SIZE, "%s\n", uid_string); + + if (device->discipline && device->discipline->get_uid && + !device->discipline->get_uid(device, &uid)) { + switch (uid.type) { + case UA_BASE_DEVICE: + snprintf(ua_string, sizeof(ua_string), "%02x", + uid.real_unit_addr); + break; + case UA_BASE_PAV_ALIAS: + snprintf(ua_string, sizeof(ua_string), "%02x", + uid.base_unit_addr); + break; + case UA_HYPER_PAV_ALIAS: + snprintf(ua_string, sizeof(ua_string), "xx"); + break; + default: + /* should not happen, treat like base device */ + snprintf(ua_string, sizeof(ua_string), "%02x", + uid.real_unit_addr); + break; + } + + if (strlen(uid.vduit) > 0) + snprintf(uid_string, sizeof(uid_string), + "%s.%s.%04x.%s.%s", + uid.vendor, uid.serial, uid.ssid, ua_string, + uid.vduit); + else + snprintf(uid_string, sizeof(uid_string), + "%s.%s.%04x.%s", + uid.vendor, uid.serial, uid.ssid, ua_string); } - if (strlen(uid->vduit) > 0) - snprintf(uid_string, sizeof(uid_string), - "%s.%s.%04x.%s.%s", - uid->vendor, uid->serial, - uid->ssid, ua_string, - uid->vduit); - else - snprintf(uid_string, sizeof(uid_string), - "%s.%s.%04x.%s", - uid->vendor, uid->serial, - uid->ssid, ua_string); - spin_unlock(&dasd_devmap_lock); + dasd_put_device(device); + return snprintf(buf, PAGE_SIZE, "%s\n", uid_string); } - static DEVICE_ATTR(uid, 0444, dasd_uid_show, NULL); /* @@ -1094,50 +1100,6 @@ static struct attribute_group dasd_attr_group = { }; /* - * Return copy of the device unique identifier. - */ -int -dasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid) -{ - struct dasd_devmap *devmap; - - devmap = dasd_find_busid(dev_name(&cdev->dev)); - if (IS_ERR(devmap)) - return PTR_ERR(devmap); - spin_lock(&dasd_devmap_lock); - *uid = devmap->uid; - spin_unlock(&dasd_devmap_lock); - return 0; -} -EXPORT_SYMBOL_GPL(dasd_get_uid); - -/* - * Register the given device unique identifier into devmap struct. - * In addition check if the related storage server subsystem ID is already - * contained in the dasd_server_ssid_list. If subsystem ID is not contained, - * create new entry. - * Return 0 if server was already in serverlist, - * 1 if the server was added successful - * <0 in case of error. - */ -int -dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid) -{ - struct dasd_devmap *devmap; - - devmap = dasd_find_busid(dev_name(&cdev->dev)); - if (IS_ERR(devmap)) - return PTR_ERR(devmap); - - spin_lock(&dasd_devmap_lock); - devmap->uid = *uid; - spin_unlock(&dasd_devmap_lock); - - return 0; -} -EXPORT_SYMBOL_GPL(dasd_set_uid); - -/* * Return value of the specified feature. */ int diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 4305c23..5b1cd8d 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -692,18 +692,20 @@ dasd_eckd_cdl_reclen(int recid) /* * Generate device unique id that specifies the physical device. */ -static int dasd_eckd_generate_uid(struct dasd_device *device, - struct dasd_uid *uid) +static int dasd_eckd_generate_uid(struct dasd_device *device) { struct dasd_eckd_private *private; + struct dasd_uid *uid; int count; + unsigned long flags; private = (struct dasd_eckd_private *) device->private; if (!private) return -ENODEV; if (!private->ned || !private->gneq) return -ENODEV; - + uid = &private->uid; + spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); memset(uid, 0, sizeof(struct dasd_uid)); memcpy(uid->vendor, private->ned->HDA_manufacturer, sizeof(uid->vendor) - 1); @@ -726,9 +728,25 @@ static int dasd_eckd_generate_uid(struct dasd_device *device, private->vdsneq->uit[count]); } } + spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); return 0; } +static int dasd_eckd_get_uid(struct dasd_device *device, struct dasd_uid *uid) +{ + struct dasd_eckd_private *private; + unsigned long flags; + + if (device->private) { + private = (struct dasd_eckd_private *)device->private; + spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); + *uid = private->uid; + spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); + return 0; + } + return -EINVAL; +} + static struct dasd_ccw_req *dasd_eckd_build_rcd_lpm(struct dasd_device *device, void *rcd_buffer, struct ciw *ciw, __u8 lpm) @@ -1088,6 +1106,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device) { struct dasd_eckd_private *private; struct dasd_block *block; + struct dasd_uid temp_uid; int is_known, rc; int readonly; @@ -1124,13 +1143,13 @@ dasd_eckd_check_characteristics(struct dasd_device *device) if (rc) goto out_err1; - /* Generate device unique id and register in devmap */ - rc = dasd_eckd_generate_uid(device, &private->uid); + /* Generate device unique id */ + rc = dasd_eckd_generate_uid(device); if (rc) goto out_err1; - dasd_set_uid(device->cdev, &private->uid); - if (private->uid.type == UA_BASE_DEVICE) { + dasd_eckd_get_uid(device, &temp_uid); + if (temp_uid.type == UA_BASE_DEVICE) { block = dasd_alloc_block(); if (IS_ERR(block)) { DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s", @@ -3305,15 +3324,16 @@ static int dasd_eckd_restore_device(struct dasd_device *device) if (rc) goto out_err; - /* Generate device unique id and register in devmap */ - rc = dasd_eckd_generate_uid(device, &private->uid); - dasd_get_uid(device->cdev, &temp_uid); + dasd_eckd_get_uid(device, &temp_uid); + /* Generate device unique id */ + rc = dasd_eckd_generate_uid(device); + spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); if (memcmp(&private->uid, &temp_uid, sizeof(struct dasd_uid)) != 0) dev_err(&device->cdev->dev, "The UID of the DASD has " "changed\n"); + spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); if (rc) goto out_err; - dasd_set_uid(device->cdev, &private->uid); /* register lcu with alias handling, enable PAV if this is a new lcu */ is_known = dasd_alias_make_device_known_to_lcu(device); @@ -3358,42 +3378,45 @@ static int dasd_eckd_reload_device(struct dasd_device *device) { struct dasd_eckd_private *private; int rc, old_base; - char uid[60]; + char print_uid[60]; + struct dasd_uid uid; + unsigned long flags; private = (struct dasd_eckd_private *) device->private; + + spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); old_base = private->uid.base_unit_addr; + spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); + /* Read Configuration Data */ rc = dasd_eckd_read_conf(device); if (rc) goto out_err; - rc = dasd_eckd_generate_uid(device, &private->uid); + rc = dasd_eckd_generate_uid(device); if (rc) goto out_err; - - dasd_set_uid(device->cdev, &private->uid); - /* * update unit address configuration and * add device to alias management */ dasd_alias_update_add_device(device); - if (old_base != private->uid.base_unit_addr) { - if (strlen(private->uid.vduit) > 0) - snprintf(uid, 60, "%s.%s.%04x.%02x.%s", - private->uid.vendor, private->uid.serial, - private->uid.ssid, private->uid.base_unit_addr, - private->uid.vduit); + dasd_eckd_get_uid(device, &uid); + + if (old_base != uid.base_unit_addr) { + if (strlen(uid.vduit) > 0) + snprintf(print_uid, sizeof(print_uid), + "%s.%s.%04x.%02x.%s", uid.vendor, uid.serial, + uid.ssid, uid.base_unit_addr, uid.vduit); else - snprintf(uid, 60, "%s.%s.%04x.%02x", - private->uid.vendor, private->uid.serial, - private->uid.ssid, - private->uid.base_unit_addr); + snprintf(print_uid, sizeof(print_uid), + "%s.%s.%04x.%02x", uid.vendor, uid.serial, + uid.ssid, uid.base_unit_addr); dev_info(&device->cdev->dev, "An Alias device was reassigned to a new base device " - "with UID: %s\n", uid); + "with UID: %s\n", print_uid); } return 0; @@ -3455,6 +3478,7 @@ static struct dasd_discipline dasd_eckd_discipline = { .freeze = dasd_eckd_pm_freeze, .restore = dasd_eckd_restore_device, .reload = dasd_eckd_reload_device, + .get_uid = dasd_eckd_get_uid, }; static int __init diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 1ae7b12..32fac18 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -81,6 +81,10 @@ struct dasd_block; #define DASD_SIM_MSG_TO_OP 0x03 #define DASD_SIM_LOG 0x0C +/* lock class for nested cdev lock */ +#define CDEV_NESTED_FIRST 1 +#define CDEV_NESTED_SECOND 2 + /* * SECTION: MACROs for klogd and s390 debug feature (dbf) */ @@ -229,6 +233,24 @@ struct dasd_ccw_req { typedef struct dasd_ccw_req *(*dasd_erp_fn_t) (struct dasd_ccw_req *); /* + * Unique identifier for dasd device. + */ +#define UA_NOT_CONFIGURED 0x00 +#define UA_BASE_DEVICE 0x01 +#define UA_BASE_PAV_ALIAS 0x02 +#define UA_HYPER_PAV_ALIAS 0x03 + +struct dasd_uid { + __u8 type; + char vendor[4]; + char serial[15]; + __u16 ssid; + __u8 real_unit_addr; + __u8 base_unit_addr; + char vduit[33]; +}; + +/* * the struct dasd_discipline is * sth like a table of virtual functions, if you think of dasd_eckd * inheriting dasd... @@ -315,29 +337,13 @@ struct dasd_discipline { /* reload device after state change */ int (*reload) (struct dasd_device *); + + int (*get_uid) (struct dasd_device *, struct dasd_uid *); }; extern struct dasd_discipline *dasd_diag_discipline_pointer; /* - * Unique identifier for dasd device. - */ -#define UA_NOT_CONFIGURED 0x00 -#define UA_BASE_DEVICE 0x01 -#define UA_BASE_PAV_ALIAS 0x02 -#define UA_HYPER_PAV_ALIAS 0x03 - -struct dasd_uid { - __u8 type; - char vendor[4]; - char serial[15]; - __u16 ssid; - __u8 real_unit_addr; - __u8 base_unit_addr; - char vduit[33]; -}; - -/* * Notification numbers for extended error reporting notifications: * The DASD_EER_DISABLE notification is sent before a dasd_device (and it's * eer pointer) is freed. The error reporting module needs to do all necessary @@ -634,8 +640,6 @@ void dasd_devmap_exit(void); struct dasd_device *dasd_create_device(struct ccw_device *); void dasd_delete_device(struct dasd_device *); -int dasd_get_uid(struct ccw_device *, struct dasd_uid *); -int dasd_set_uid(struct ccw_device *, struct dasd_uid *); int dasd_get_feature(struct ccw_device *, int); int dasd_set_feature(struct ccw_device *, int, int); -- cgit v0.10.2 From 10d3858950557cd3cc05f647ede597114c610177 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 17 May 2010 10:00:12 +0200 Subject: [S390] topology: expose core identifier Provide a topology_core_id define which makes sure that the contents of /sys/devices/system/cpu/cpuX/topology/core_id indeed do contain the core id and not always 0. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky diff --git a/arch/s390/include/asm/topology.h b/arch/s390/include/asm/topology.h index 6e7211a..dc8a672 100644 --- a/arch/s390/include/asm/topology.h +++ b/arch/s390/include/asm/topology.h @@ -7,8 +7,10 @@ const struct cpumask *cpu_coregroup_mask(unsigned int cpu); +extern unsigned char cpu_core_id[NR_CPUS]; extern cpumask_t cpu_core_map[NR_CPUS]; +#define topology_core_id(cpu) (cpu_core_id[cpu]) #define topology_core_cpumask(cpu) (&cpu_core_map[cpu]) int topology_set_cpu_management(int fc); diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c index 247b4c2..bcef007 100644 --- a/arch/s390/kernel/topology.c +++ b/arch/s390/kernel/topology.c @@ -37,7 +37,8 @@ struct tl_cpu { }; struct tl_container { - unsigned char reserved[8]; + unsigned char reserved[7]; + unsigned char id; }; union tl_entry { @@ -58,6 +59,7 @@ struct tl_info { struct core_info { struct core_info *next; + unsigned char id; cpumask_t mask; }; @@ -73,6 +75,7 @@ static DECLARE_WORK(topology_work, topology_work_fn); static DEFINE_SPINLOCK(topology_lock); cpumask_t cpu_core_map[NR_CPUS]; +unsigned char cpu_core_id[NR_CPUS]; static cpumask_t cpu_coregroup_map(unsigned int cpu) { @@ -116,6 +119,7 @@ static void add_cpus_to_core(struct tl_cpu *tl_cpu, struct core_info *core) for_each_present_cpu(lcpu) { if (cpu_logical_map(lcpu) == rcpu) { cpu_set(lcpu, core->mask); + cpu_core_id[lcpu] = core->id; smp_cpu_polarization[lcpu] = tl_cpu->pp; } } @@ -158,6 +162,7 @@ static void tl_to_cores(struct tl_info *info) break; case 1: core = core->next; + core->id = tle->container.id; break; case 0: add_cpus_to_core(&tle->cpu, core); -- cgit v0.10.2 From 6ea50968274673ea7b58695efec2eeb55ca2f5dd Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 17 May 2010 10:00:13 +0200 Subject: [S390] user space fault: report fault before calling do_exit Report user space faults before calling do_exit, since do_exit does not return and therefore we will never see the fault message on the console. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 6e7ad63..e605f07 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -390,8 +390,8 @@ static void default_trap_handler(struct pt_regs * regs, long interruption_code) { if (regs->psw.mask & PSW_MASK_PSTATE) { local_irq_enable(); - do_exit(SIGSEGV); report_user_fault(interruption_code, regs); + do_exit(SIGSEGV); } else die("Unknown program exception", regs, interruption_code); } -- cgit v0.10.2 From 09a308f384c4ad2fb45959f5da9918e812207c50 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Mon, 17 May 2010 10:00:14 +0200 Subject: [S390] qdio: count number of qdio interrupts Add missing increment for the qdio interrupt counter. Signed-off-by: Signed-off-by: Jan Glauber Signed-off-by: Martin Schwidefsky diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 88be7b9..1fc8126 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -955,6 +955,9 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm, return; } + if (irq_ptr->perf_stat_enabled) + irq_ptr->perf_stat.qdio_int++; + if (IS_ERR(irb)) { switch (PTR_ERR(irb)) { case -EIO: -- cgit v0.10.2 From f3eb20fafdc10aea0fb13b113ac3b9a3dc9a5dc6 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Mon, 17 May 2010 10:00:15 +0200 Subject: [S390] qdio: prevent starvation on PCI devices If adapter interrupts are not available and traditional IO interrupts are used for qdio the inbound tasklet continued to run if new data arrived. That could possibly block other tasklets scheduled on the same CPU. If new data arrives schedule the tasklet again instead of directly processing the new data. Signed-off-by: Jan Glauber Signed-off-by: Martin Schwidefsky diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 1fc8126..f4fd6cd 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -606,7 +606,7 @@ static void qdio_kick_handler(struct qdio_q *q) static void __qdio_inbound_processing(struct qdio_q *q) { qperf_inc(q, tasklet_inbound); -again: + if (!qdio_inbound_q_moved(q)) return; @@ -615,7 +615,10 @@ again: if (!qdio_inbound_q_done(q)) { /* means poll time is not yet over */ qperf_inc(q, tasklet_inbound_resched); - goto again; + if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) { + tasklet_schedule(&q->tasklet); + return; + } } qdio_stop_polling(q); @@ -625,7 +628,8 @@ again: */ if (!qdio_inbound_q_done(q)) { qperf_inc(q, tasklet_inbound_resched2); - goto again; + if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) + tasklet_schedule(&q->tasklet); } } -- cgit v0.10.2 From 5382fe11d90e3ed9602ce655e523852e3dbf3e35 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Mon, 17 May 2010 10:00:16 +0200 Subject: [S390] qdio: remove memset hack Remove memset hack that relied on the layout of struct qdio_q to avoid deletion of the slib pointer. Signed-off-by: Jan Glauber Signed-off-by: Martin Schwidefsky diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index 48aa064..da80e9b 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h @@ -296,10 +296,8 @@ struct qdio_q { struct qdio_irq *irq_ptr; struct sl *sl; /* - * Warning: Leave this member at the end so it won't be cleared in - * qdio_fill_qs. A page is allocated under this pointer and used for - * slib and sl. slib is 2048 bytes big and sl points to offset - * PAGE_SIZE / 2. + * A page is allocated under this pointer and used for slib and sl. + * slib is 2048 bytes big and sl points to offset PAGE_SIZE / 2. */ struct slib *slib; } __attribute__ ((aligned(256))); diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c index 7f4a754..6326b67 100644 --- a/drivers/s390/cio/qdio_setup.c +++ b/drivers/s390/cio/qdio_setup.c @@ -106,10 +106,12 @@ int qdio_allocate_qs(struct qdio_irq *irq_ptr, int nr_input_qs, int nr_output_qs static void setup_queues_misc(struct qdio_q *q, struct qdio_irq *irq_ptr, qdio_handler_t *handler, int i) { - /* must be cleared by every qdio_establish */ - memset(q, 0, ((char *)&q->slib) - ((char *)q)); - memset(q->slib, 0, PAGE_SIZE); + struct slib *slib = q->slib; + /* queue must be cleared for qdio_establish */ + memset(q, 0, sizeof(*q)); + memset(slib, 0, PAGE_SIZE); + q->slib = slib; q->irq_ptr = irq_ptr; q->mask = 1 << (31 - i); q->nr = i; -- cgit v0.10.2 From 3a601bfef33c82537511c7d970d8010c38aaecd1 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Mon, 17 May 2010 10:00:17 +0200 Subject: [S390] qdio: dont convert timestamps to microseconds Don't convert timestamps to microseconds, use timestamps returned by get_clock() directly. Signed-off-by: Jan Glauber Signed-off-by: Martin Schwidefsky diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index da80e9b..f0037ee 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h @@ -13,8 +13,8 @@ #include #include "chsc.h" -#define QDIO_BUSY_BIT_PATIENCE 100 /* 100 microseconds */ -#define QDIO_INPUT_THRESHOLD 500 /* 500 microseconds */ +#define QDIO_BUSY_BIT_PATIENCE (100 << 12) /* 100 microseconds */ +#define QDIO_INPUT_THRESHOLD (500 << 12) /* 500 microseconds */ /* * if an asynchronous HiperSockets queue runs full, the 10 seconds timer wait @@ -370,11 +370,6 @@ static inline int multicast_outbound(struct qdio_q *q) (q->nr == q->irq_ptr->nr_output_qs - 1); } -static inline unsigned long long get_usecs(void) -{ - return monotonic_clock() >> 12; -} - #define pci_out_supported(q) \ (q->irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED) #define is_qebsm(q) (q->irq_ptr->sch_token != 0) diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index f4fd6cd..dafb3e5 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -336,10 +336,10 @@ again: WARN_ON(queue_type(q) != QDIO_IQDIO_QFMT || cc != 2); if (!start_time) { - start_time = get_usecs(); + start_time = get_clock(); goto again; } - if ((get_usecs() - start_time) < QDIO_BUSY_BIT_PATIENCE) + if ((get_clock() - start_time) < QDIO_BUSY_BIT_PATIENCE) goto again; } return cc; @@ -536,7 +536,7 @@ static int qdio_inbound_q_moved(struct qdio_q *q) if ((bufnr != q->last_move) || q->qdio_error) { q->last_move = bufnr; if (!is_thinint_irq(q->irq_ptr) && MACHINE_IS_LPAR) - q->u.in.timestamp = get_usecs(); + q->u.in.timestamp = get_clock(); return 1; } else return 0; @@ -567,7 +567,7 @@ static inline int qdio_inbound_q_done(struct qdio_q *q) * At this point we know, that inbound first_to_check * has (probably) not moved (see qdio_inbound_processing). */ - if (get_usecs() > q->u.in.timestamp + QDIO_INPUT_THRESHOLD) { + if (get_clock() > q->u.in.timestamp + QDIO_INPUT_THRESHOLD) { DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in done:%02x", q->first_to_check); return 1; -- cgit v0.10.2 From d0c9d4a89fff4352b20ae8704b84cd99a8372f66 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Mon, 17 May 2010 10:00:18 +0200 Subject: [S390] qdio: set correct bit in dsci The state change indicator is bit 7 not bit 0 of the dsci. Use the correct bit for setting the indicator. Signed-off-by: Jan Glauber Signed-off-by: Martin Schwidefsky diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c index ce5f891..8daf1b9 100644 --- a/drivers/s390/cio/qdio_thinint.c +++ b/drivers/s390/cio/qdio_thinint.c @@ -95,7 +95,7 @@ void tiqdio_add_input_queues(struct qdio_irq *irq_ptr) for_each_input_queue(irq_ptr, q, i) list_add_rcu(&q->entry, &tiq_list); mutex_unlock(&tiq_list_lock); - xchg(irq_ptr->dsci, 1); + xchg(irq_ptr->dsci, 1 << 7); } void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr) @@ -173,7 +173,7 @@ static void tiqdio_thinint_handler(void *ind, void *drv_data) /* prevent racing */ if (*tiqdio_alsi) - xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 1); + xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 1 << 7); } } -- cgit v0.10.2 From cc961d400e06e78c7aa39aeab1f001eb8f76ef90 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Mon, 17 May 2010 10:00:19 +0200 Subject: [S390] qdio: remove API wrappers Remove qdio API wrappers used by qeth and replace them by calling the appropriate functions directly. Signed-off-by: Jan Glauber Signed-off-by: Martin Schwidefsky diff --git a/arch/s390/include/asm/qdio.h b/arch/s390/include/asm/qdio.h index 9b04b11..0eaae626 100644 --- a/arch/s390/include/asm/qdio.h +++ b/arch/s390/include/asm/qdio.h @@ -368,14 +368,12 @@ struct qdio_initialize { #define QDIO_FLAG_SYNC_OUTPUT 0x02 #define QDIO_FLAG_PCI_OUT 0x10 -extern int qdio_initialize(struct qdio_initialize *); extern int qdio_allocate(struct qdio_initialize *); extern int qdio_establish(struct qdio_initialize *); extern int qdio_activate(struct ccw_device *); extern int do_QDIO(struct ccw_device *cdev, unsigned int callflags, int q_nr, unsigned int bufnr, unsigned int count); -extern int qdio_cleanup(struct ccw_device*, int); extern int qdio_shutdown(struct ccw_device*, int); extern int qdio_free(struct ccw_device *); extern int qdio_get_ssqd_desc(struct ccw_device *dev, struct qdio_ssqd_desc*); diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index dafb3e5..00520f9 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -1023,30 +1023,6 @@ int qdio_get_ssqd_desc(struct ccw_device *cdev, } EXPORT_SYMBOL_GPL(qdio_get_ssqd_desc); -/** - * qdio_cleanup - shutdown queues and free data structures - * @cdev: associated ccw device - * @how: use halt or clear to shutdown - * - * This function calls qdio_shutdown() for @cdev with method @how. - * and qdio_free(). The qdio_free() return value is ignored since - * !irq_ptr is already checked. - */ -int qdio_cleanup(struct ccw_device *cdev, int how) -{ - struct qdio_irq *irq_ptr = cdev->private->qdio_data; - int rc; - - if (!irq_ptr) - return -ENODEV; - - rc = qdio_shutdown(cdev, how); - - qdio_free(cdev); - return rc; -} -EXPORT_SYMBOL_GPL(qdio_cleanup); - static void qdio_shutdown_queues(struct ccw_device *cdev) { struct qdio_irq *irq_ptr = cdev->private->qdio_data; @@ -1164,28 +1140,6 @@ int qdio_free(struct ccw_device *cdev) EXPORT_SYMBOL_GPL(qdio_free); /** - * qdio_initialize - allocate and establish queues for a qdio subchannel - * @init_data: initialization data - * - * This function first allocates queues via qdio_allocate() and on success - * establishes them via qdio_establish(). - */ -int qdio_initialize(struct qdio_initialize *init_data) -{ - int rc; - - rc = qdio_allocate(init_data); - if (rc) - return rc; - - rc = qdio_establish(init_data); - if (rc) - qdio_free(init_data->cdev); - return rc; -} -EXPORT_SYMBOL_GPL(qdio_initialize); - -/** * qdio_allocate - allocate qdio queues and associated data * @init_data: initialization data */ diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 3ba738b..28f7134 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -1292,13 +1292,14 @@ int qeth_qdio_clear_card(struct qeth_card *card, int use_halt) QETH_QDIO_CLEANING)) { case QETH_QDIO_ESTABLISHED: if (card->info.type == QETH_CARD_TYPE_IQD) - rc = qdio_cleanup(CARD_DDEV(card), + rc = qdio_shutdown(CARD_DDEV(card), QDIO_FLAG_CLEANUP_USING_HALT); else - rc = qdio_cleanup(CARD_DDEV(card), + rc = qdio_shutdown(CARD_DDEV(card), QDIO_FLAG_CLEANUP_USING_CLEAR); if (rc) QETH_DBF_TEXT_(TRACE, 3, "1err%d", rc); + qdio_free(CARD_DDEV(card)); atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED); break; case QETH_QDIO_CLEANING: @@ -3810,10 +3811,18 @@ static int qeth_qdio_establish(struct qeth_card *card) if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ALLOCATED, QETH_QDIO_ESTABLISHED) == QETH_QDIO_ALLOCATED) { - rc = qdio_initialize(&init_data); - if (rc) + rc = qdio_allocate(&init_data); + if (rc) { + atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED); + goto out; + } + rc = qdio_establish(&init_data); + if (rc) { atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED); + qdio_free(CARD_DDEV(card)); + } } +out: kfree(out_sbal_ptrs); kfree(in_sbal_ptrs); kfree(qib_param_field); -- cgit v0.10.2 From 57b28f66316d287b9dbf7b28358ca90257230769 Mon Sep 17 00:00:00 2001 From: Michael Holzheu Date: Mon, 17 May 2010 10:00:20 +0200 Subject: [S390] s390_hypfs: Add new attributes In order to access the data of the hypfs diagnose calls from user space also in binary form, this patch adds two new attributes in debugfs: * z/VM: s390_hypfs/d2fc_bin * LPAR: s390_hypfs/d204_bin Signed-off-by: Michael Holzheu Signed-off-by: Martin Schwidefsky diff --git a/arch/s390/hypfs/hypfs.h b/arch/s390/hypfs/hypfs.h index aea5720..fa487d4 100644 --- a/arch/s390/hypfs/hypfs.h +++ b/arch/s390/hypfs/hypfs.h @@ -11,6 +11,7 @@ #include #include +#include #define REG_FILE_MODE 0440 #define UPDATE_FILE_MODE 0220 @@ -34,6 +35,9 @@ extern int hypfs_diag_create_files(struct super_block *sb, struct dentry *root); /* VM Hypervisor */ extern int hypfs_vm_init(void); +extern void hypfs_vm_exit(void); extern int hypfs_vm_create_files(struct super_block *sb, struct dentry *root); +/* Directory for debugfs files */ +extern struct dentry *hypfs_dbfs_dir; #endif /* _HYPFS_H_ */ diff --git a/arch/s390/hypfs/hypfs_diag.c b/arch/s390/hypfs/hypfs_diag.c index 5b1acdb..1211bb1 100644 --- a/arch/s390/hypfs/hypfs_diag.c +++ b/arch/s390/hypfs/hypfs_diag.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include "hypfs.h" @@ -22,6 +23,8 @@ #define CPU_NAME_LEN 16 /* type name len of cpus in diag224 name table */ #define TMP_SIZE 64 /* size of temporary buffers */ +#define DBFS_D204_HDR_VERSION 0 + /* diag 204 subcodes */ enum diag204_sc { SUBC_STIB4 = 4, @@ -47,6 +50,8 @@ static void *diag204_buf; /* 4K aligned buffer for diag204 data */ static void *diag204_buf_vmalloc; /* vmalloc pointer for diag204 data */ static int diag204_buf_pages; /* number of pages for diag204 data */ +static struct dentry *dbfs_d204_file; + /* * DIAG 204 data structures and member access functions. * @@ -364,18 +369,21 @@ static void diag204_free_buffer(void) } else { free_pages((unsigned long) diag204_buf, 0); } - diag204_buf_pages = 0; diag204_buf = NULL; } +static void *page_align_ptr(void *ptr) +{ + return (void *) PAGE_ALIGN((unsigned long) ptr); +} + static void *diag204_alloc_vbuf(int pages) { /* The buffer has to be page aligned! */ diag204_buf_vmalloc = vmalloc(PAGE_SIZE * (pages + 1)); if (!diag204_buf_vmalloc) return ERR_PTR(-ENOMEM); - diag204_buf = (void*)((unsigned long)diag204_buf_vmalloc - & ~0xfffUL) + 0x1000; + diag204_buf = page_align_ptr(diag204_buf_vmalloc); diag204_buf_pages = pages; return diag204_buf; } @@ -468,17 +476,26 @@ fail_alloc: return rc; } +static int diag204_do_store(void *buf, int pages) +{ + int rc; + + rc = diag204((unsigned long) diag204_store_sc | + (unsigned long) diag204_info_type, pages, buf); + return rc < 0 ? -ENOSYS : 0; +} + static void *diag204_store(void) { void *buf; - int pages; + int pages, rc; buf = diag204_get_buffer(diag204_info_type, &pages); if (IS_ERR(buf)) goto out; - if (diag204((unsigned long)diag204_store_sc | - (unsigned long)diag204_info_type, pages, buf) < 0) - return ERR_PTR(-ENOSYS); + rc = diag204_do_store(buf, pages); + if (rc) + return ERR_PTR(rc); out: return buf; } @@ -526,6 +543,92 @@ static int diag224_idx2name(int index, char *name) return 0; } +struct dbfs_d204_hdr { + u64 len; /* Length of d204 buffer without header */ + u16 version; /* Version of header */ + u8 sc; /* Used subcode */ + char reserved[53]; +} __attribute__ ((packed)); + +struct dbfs_d204 { + struct dbfs_d204_hdr hdr; /* 64 byte header */ + char buf[]; /* d204 buffer */ +} __attribute__ ((packed)); + +struct dbfs_d204_private { + struct dbfs_d204 *d204; /* Aligned d204 data with header */ + void *base; /* Base pointer (needed for vfree) */ +}; + +static int dbfs_d204_open(struct inode *inode, struct file *file) +{ + struct dbfs_d204_private *data; + struct dbfs_d204 *d204; + int rc, buf_size; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + buf_size = PAGE_SIZE * (diag204_buf_pages + 1) + sizeof(d204->hdr); + data->base = vmalloc(buf_size); + if (!data->base) { + rc = -ENOMEM; + goto fail_kfree_data; + } + memset(data->base, 0, buf_size); + d204 = page_align_ptr(data->base + sizeof(d204->hdr)) + - sizeof(d204->hdr); + rc = diag204_do_store(&d204->buf, diag204_buf_pages); + if (rc) + goto fail_vfree_base; + d204->hdr.version = DBFS_D204_HDR_VERSION; + d204->hdr.len = PAGE_SIZE * diag204_buf_pages; + d204->hdr.sc = diag204_store_sc; + data->d204 = d204; + file->private_data = data; + return nonseekable_open(inode, file); + +fail_vfree_base: + vfree(data->base); +fail_kfree_data: + kfree(data); + return rc; +} + +static int dbfs_d204_release(struct inode *inode, struct file *file) +{ + struct dbfs_d204_private *data = file->private_data; + + vfree(data->base); + kfree(data); + return 0; +} + +static ssize_t dbfs_d204_read(struct file *file, char __user *buf, + size_t size, loff_t *ppos) +{ + struct dbfs_d204_private *data = file->private_data; + + return simple_read_from_buffer(buf, size, ppos, data->d204, + data->d204->hdr.len + + sizeof(data->d204->hdr)); +} + +static const struct file_operations dbfs_d204_ops = { + .open = dbfs_d204_open, + .read = dbfs_d204_read, + .release = dbfs_d204_release, +}; + +static int hypfs_dbfs_init(void) +{ + dbfs_d204_file = debugfs_create_file("diag_204", 0400, hypfs_dbfs_dir, + NULL, &dbfs_d204_ops); + if (IS_ERR(dbfs_d204_file)) + return PTR_ERR(dbfs_d204_file); + return 0; +} + __init int hypfs_diag_init(void) { int rc; @@ -540,11 +643,17 @@ __init int hypfs_diag_init(void) pr_err("The hardware system does not provide all " "functions required by hypfs\n"); } + if (diag204_info_type == INFO_EXT) { + rc = hypfs_dbfs_init(); + if (rc) + diag204_free_buffer(); + } return rc; } void hypfs_diag_exit(void) { + debugfs_remove(dbfs_d204_file); diag224_delete_name_table(); diag204_free_buffer(); } diff --git a/arch/s390/hypfs/hypfs_vm.c b/arch/s390/hypfs/hypfs_vm.c index f0b0d31..ee5ab1a 100644 --- a/arch/s390/hypfs/hypfs_vm.c +++ b/arch/s390/hypfs/hypfs_vm.c @@ -10,14 +10,18 @@ #include #include #include +#include #include "hypfs.h" #define NAME_LEN 8 +#define DBFS_D2FC_HDR_VERSION 0 static char local_guest[] = " "; static char all_guests[] = "* "; static char *guest_query; +static struct dentry *dbfs_d2fc_file; + struct diag2fc_data { __u32 version; __u32 flags; @@ -76,23 +80,26 @@ static int diag2fc(int size, char* query, void *addr) return -residual_cnt; } -static struct diag2fc_data *diag2fc_store(char *query, int *count) +/* + * Allocate buffer for "query" and store diag 2fc at "offset" + */ +static void *diag2fc_store(char *query, unsigned int *count, int offset) { + void *data; int size; - struct diag2fc_data *data; do { size = diag2fc(0, query, NULL); if (size < 0) return ERR_PTR(-EACCES); - data = vmalloc(size); + data = vmalloc(size + offset); if (!data) return ERR_PTR(-ENOMEM); - if (diag2fc(size, query, data) == 0) + if (diag2fc(size, query, data + offset) == 0) break; vfree(data); } while (1); - *count = (size / sizeof(*data)); + *count = (size / sizeof(struct diag2fc_data)); return data; } @@ -168,9 +175,10 @@ int hypfs_vm_create_files(struct super_block *sb, struct dentry *root) { struct dentry *dir, *file; struct diag2fc_data *data; - int rc, i, count = 0; + unsigned int count = 0; + int rc, i; - data = diag2fc_store(guest_query, &count); + data = diag2fc_store(guest_query, &count, 0); if (IS_ERR(data)) return PTR_ERR(data); @@ -218,8 +226,61 @@ failed: return rc; } +struct dbfs_d2fc_hdr { + u64 len; /* Length of d2fc buffer without header */ + u16 version; /* Version of header */ + char tod_ext[16]; /* TOD clock for d2fc */ + u64 count; /* Number of VM guests in d2fc buffer */ + char reserved[30]; +} __attribute__ ((packed)); + +struct dbfs_d2fc { + struct dbfs_d2fc_hdr hdr; /* 64 byte header */ + char buf[]; /* d2fc buffer */ +} __attribute__ ((packed)); + +static int dbfs_d2fc_open(struct inode *inode, struct file *file) +{ + struct dbfs_d2fc *data; + unsigned int count; + + data = diag2fc_store(guest_query, &count, sizeof(data->hdr)); + if (IS_ERR(data)) + return PTR_ERR(data); + get_clock_ext(data->hdr.tod_ext); + data->hdr.len = count * sizeof(struct diag2fc_data); + data->hdr.version = DBFS_D2FC_HDR_VERSION; + data->hdr.count = count; + memset(&data->hdr.reserved, 0, sizeof(data->hdr.reserved)); + file->private_data = data; + return nonseekable_open(inode, file); +} + +static int dbfs_d2fc_release(struct inode *inode, struct file *file) +{ + diag2fc_free(file->private_data); + return 0; +} + +static ssize_t dbfs_d2fc_read(struct file *file, char __user *buf, + size_t size, loff_t *ppos) +{ + struct dbfs_d2fc *data = file->private_data; + + return simple_read_from_buffer(buf, size, ppos, data, data->hdr.len + + sizeof(struct dbfs_d2fc_hdr)); +} + +static const struct file_operations dbfs_d2fc_ops = { + .open = dbfs_d2fc_open, + .read = dbfs_d2fc_read, + .release = dbfs_d2fc_release, +}; + int hypfs_vm_init(void) { + if (!MACHINE_IS_VM) + return 0; if (diag2fc(0, all_guests, NULL) > 0) guest_query = all_guests; else if (diag2fc(0, local_guest, NULL) > 0) @@ -227,5 +288,17 @@ int hypfs_vm_init(void) else return -EACCES; + dbfs_d2fc_file = debugfs_create_file("diag_2fc", 0400, hypfs_dbfs_dir, + NULL, &dbfs_d2fc_ops); + if (IS_ERR(dbfs_d2fc_file)) + return PTR_ERR(dbfs_d2fc_file); + return 0; } + +void hypfs_vm_exit(void) +{ + if (!MACHINE_IS_VM) + return; + debugfs_remove(dbfs_d2fc_file); +} diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c index 95c1aaa..6b120f0 100644 --- a/arch/s390/hypfs/inode.c +++ b/arch/s390/hypfs/inode.c @@ -46,6 +46,8 @@ static const struct super_operations hypfs_s_ops; /* start of list of all dentries, which have to be deleted on update */ static struct dentry *hypfs_last_dentry; +struct dentry *hypfs_dbfs_dir; + static void hypfs_update_update(struct super_block *sb) { struct hypfs_sb_info *sb_info = sb->s_fs_info; @@ -468,20 +470,22 @@ static int __init hypfs_init(void) { int rc; - if (MACHINE_IS_VM) { - if (hypfs_vm_init()) - /* no diag 2fc, just exit */ - return -ENODATA; - } else { - if (hypfs_diag_init()) { - rc = -ENODATA; - goto fail_diag; - } + hypfs_dbfs_dir = debugfs_create_dir("s390_hypfs", NULL); + if (IS_ERR(hypfs_dbfs_dir)) + return PTR_ERR(hypfs_dbfs_dir); + + if (hypfs_diag_init()) { + rc = -ENODATA; + goto fail_debugfs_remove; + } + if (hypfs_vm_init()) { + rc = -ENODATA; + goto fail_hypfs_diag_exit; } s390_kobj = kobject_create_and_add("s390", hypervisor_kobj); if (!s390_kobj) { rc = -ENOMEM; - goto fail_sysfs; + goto fail_hypfs_vm_exit; } rc = register_filesystem(&hypfs_type); if (rc) @@ -490,18 +494,22 @@ static int __init hypfs_init(void) fail_filesystem: kobject_put(s390_kobj); -fail_sysfs: - if (!MACHINE_IS_VM) - hypfs_diag_exit(); -fail_diag: +fail_hypfs_vm_exit: + hypfs_vm_exit(); +fail_hypfs_diag_exit: + hypfs_diag_exit(); +fail_debugfs_remove: + debugfs_remove(hypfs_dbfs_dir); + pr_err("Initialization of hypfs failed with rc=%i\n", rc); return rc; } static void __exit hypfs_exit(void) { - if (!MACHINE_IS_VM) - hypfs_diag_exit(); + hypfs_diag_exit(); + hypfs_vm_exit(); + debugfs_remove(hypfs_dbfs_dir); unregister_filesystem(&hypfs_type); kobject_put(s390_kobj); } diff --git a/arch/s390/include/asm/timex.h b/arch/s390/include/asm/timex.h index f174bda..09d345a 100644 --- a/arch/s390/include/asm/timex.h +++ b/arch/s390/include/asm/timex.h @@ -61,11 +61,15 @@ static inline unsigned long long get_clock (void) return clk; } +static inline void get_clock_ext(char *clk) +{ + asm volatile("stcke %0" : "=Q" (*clk) : : "cc"); +} + static inline unsigned long long get_clock_xt(void) { unsigned char clk[16]; - - asm volatile("stcke %0" : "=Q" (clk) : : "cc"); + get_clock_ext(clk); return *((unsigned long long *)&clk[1]); } -- cgit v0.10.2 From ab3c68ee5fd329ba48094d3417fd60e30ea14a87 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 17 May 2010 10:00:21 +0200 Subject: [S390] debug: enable exception-trace debug facility The exception-trace facility on x86 and other architectures prints traces to dmesg whenever a user space application crashes. s390 has such a feature since ages however it is called userprocess_debug and is enabled differently. This patch makes sure that whenever one of the two procfs files /proc/sys/kernel/userprocess_debug /proc/sys/debug/exception-trace is modified the contents of the second one changes as well. That way we keep backwards compatibilty but also support the same interface like other architectures do. Besides that the output of the traces is improved since it will now also contain the corresponding filename of the vma (when available) where the process caused a fault or trap. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 0d8cd9b..79d0ca0 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -444,13 +444,6 @@ config FORCE_MAX_ZONEORDER int default "9" -config PROCESS_DEBUG - bool "Show crashed user process info" - help - Say Y to print all process fault locations to the console. This is - a debugging option; you probably do not want to set it unless you - are an S390 port maintainer. - config PFAULT bool "Pseudo page fault support" help diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index e605f07..5d8f0f3 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -46,13 +46,7 @@ pgm_check_handler_t *pgm_check_table[128]; -#ifdef CONFIG_SYSCTL -#ifdef CONFIG_PROCESS_DEBUG -int sysctl_userprocess_debug = 1; -#else -int sysctl_userprocess_debug = 0; -#endif -#endif +int show_unhandled_signals; extern pgm_check_handler_t do_protection_exception; extern pgm_check_handler_t do_dat_exception; @@ -315,18 +309,19 @@ void die(const char * str, struct pt_regs * regs, long err) do_exit(SIGSEGV); } -static void inline -report_user_fault(long interruption_code, struct pt_regs *regs) +static void inline report_user_fault(struct pt_regs *regs, long int_code, + int signr) { -#if defined(CONFIG_SYSCTL) - if (!sysctl_userprocess_debug) + if ((task_pid_nr(current) > 1) && !show_unhandled_signals) return; -#endif -#if defined(CONFIG_SYSCTL) || defined(CONFIG_PROCESS_DEBUG) - printk("User process fault: interruption code 0x%lX\n", - interruption_code); + if (!unhandled_signal(current, signr)) + return; + if (!printk_ratelimit()) + return; + printk("User process fault: interruption code 0x%lX ", int_code); + print_vma_addr("in ", regs->psw.addr & PSW_ADDR_INSN); + printk("\n"); show_regs(regs); -#endif } int is_valid_bugaddr(unsigned long addr) @@ -354,7 +349,7 @@ static void __kprobes inline do_trap(long interruption_code, int signr, tsk->thread.trap_no = interruption_code & 0xffff; force_sig_info(signr, info, tsk); - report_user_fault(interruption_code, regs); + report_user_fault(regs, interruption_code, signr); } else { const struct exception_table_entry *fixup; fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN); @@ -390,7 +385,7 @@ static void default_trap_handler(struct pt_regs * regs, long interruption_code) { if (regs->psw.mask & PSW_MASK_PSTATE) { local_irq_enable(); - report_user_fault(interruption_code, regs); + report_user_fault(regs, interruption_code, SIGSEGV); do_exit(SIGSEGV); } else die("Unknown program exception", regs, interruption_code); diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 3040d7c..2505b2e 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -48,10 +48,6 @@ #define __PF_RES_FIELD 0x8000000000000000ULL #endif /* CONFIG_64BIT */ -#ifdef CONFIG_SYSCTL -extern int sysctl_userprocess_debug; -#endif - #define VM_FAULT_BADCONTEXT 0x010000 #define VM_FAULT_BADMAP 0x020000 #define VM_FAULT_BADACCESS 0x040000 @@ -120,6 +116,22 @@ static inline int user_space_fault(unsigned long trans_exc_code) return trans_exc_code != 3; } +static inline void report_user_fault(struct pt_regs *regs, long int_code, + int signr, unsigned long address) +{ + if ((task_pid_nr(current) > 1) && !show_unhandled_signals) + return; + if (!unhandled_signal(current, signr)) + return; + if (!printk_ratelimit()) + return; + printk("User process fault: interruption code 0x%lX ", int_code); + print_vma_addr(KERN_CONT "in ", regs->psw.addr & PSW_ADDR_INSN); + printk("\n"); + printk("failing address: %lX\n", address); + show_regs(regs); +} + /* * Send SIGSEGV to task. This is an external routine * to keep the stack usage of do_page_fault small. @@ -133,17 +145,7 @@ static noinline void do_sigsegv(struct pt_regs *regs, long int_code, address = trans_exc_code & __FAIL_ADDR_MASK; current->thread.prot_addr = address; current->thread.trap_no = int_code; -#if defined(CONFIG_SYSCTL) || defined(CONFIG_PROCESS_DEBUG) -#if defined(CONFIG_SYSCTL) - if (sysctl_userprocess_debug) -#endif - { - printk("User process fault: interruption code 0x%lX\n", - int_code); - printk("failing address: %lX\n", address); - show_regs(regs); - } -#endif + report_user_fault(regs, int_code, SIGSEGV, address); si.si_signo = SIGSEGV; si.si_code = si_code; si.si_addr = (void __user *) address; diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 8686b0f..90f536d 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -621,7 +621,7 @@ static struct ctl_table kern_table[] = { #endif { .procname = "userprocess_debug", - .data = &sysctl_userprocess_debug, + .data = &show_unhandled_signals, .maxlen = sizeof(int), .mode = 0644, .proc_handler = proc_dointvec, @@ -1431,7 +1431,8 @@ static struct ctl_table fs_table[] = { }; static struct ctl_table debug_table[] = { -#if defined(CONFIG_X86) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) +#if defined(CONFIG_X86) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) || \ + defined(CONFIG_S390) { .procname = "exception-trace", .data = &show_unhandled_signals, -- cgit v0.10.2 From 777a5510093a6d6443351160c6969a0e66f3ba8a Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 17 May 2010 10:00:22 +0200 Subject: [S390] drivers/s390/char: Use kstrdup Use kstrdup when the goal of an allocation is copy a string into the allocated region. Additionally drop the now unused variable len. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @@ expression from,to; expression flag,E1,E2; statement S; @@ - to = kmalloc(strlen(from) + 1,flag); + to = kstrdup(from, flag); ... when != \(from = E1 \| to = E1 \) if (to==NULL || ...) S ... when != \(from = E2 \| to = E2 \) - strcpy(to, from); // Signed-off-by: Julia Lawall Signed-off-by: Martin Schwidefsky diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c index cb6bffe..24021fd 100644 --- a/drivers/s390/char/keyboard.c +++ b/drivers/s390/char/keyboard.c @@ -49,7 +49,7 @@ static unsigned char ret_diacr[NR_DEAD] = { struct kbd_data * kbd_alloc(void) { struct kbd_data *kbd; - int i, len; + int i; kbd = kzalloc(sizeof(struct kbd_data), GFP_KERNEL); if (!kbd) @@ -72,11 +72,10 @@ kbd_alloc(void) { goto out_maps; for (i = 0; i < ARRAY_SIZE(func_table); i++) { if (func_table[i]) { - len = strlen(func_table[i]) + 1; - kbd->func_table[i] = kmalloc(len, GFP_KERNEL); + kbd->func_table[i] = kstrdup(func_table[i], + GFP_KERNEL); if (!kbd->func_table[i]) goto out_func; - memcpy(kbd->func_table[i], func_table[i], len); } } kbd->fn_handler = -- cgit v0.10.2 From 939e379e9e183ae6291ac7caa4a5e1dfadae4ccc Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 17 May 2010 10:00:23 +0200 Subject: [S390] drivers/s390/char: Use kmemdup Use kmemdup when some other buffer is immediately copied into the allocated region. A simplified version of the semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @@ expression from,to,size,flag; statement S; @@ - to = \(kmalloc\|kzalloc\)(size,flag); + to = kmemdup(from,size,flag); if (to==NULL || ...) S - memcpy(to, from, size); // Signed-off-by: Julia Lawall Signed-off-by: Martin Schwidefsky diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c index 24021fd..18d9a49 100644 --- a/drivers/s390/char/keyboard.c +++ b/drivers/s390/char/keyboard.c @@ -59,12 +59,11 @@ kbd_alloc(void) { goto out_kbd; for (i = 0; i < ARRAY_SIZE(key_maps); i++) { if (key_maps[i]) { - kbd->key_maps[i] = - kmalloc(sizeof(u_short)*NR_KEYS, GFP_KERNEL); + kbd->key_maps[i] = kmemdup(key_maps[i], + sizeof(u_short) * NR_KEYS, + GFP_KERNEL); if (!kbd->key_maps[i]) goto out_maps; - memcpy(kbd->key_maps[i], key_maps[i], - sizeof(u_short)*NR_KEYS); } } kbd->func_table = kzalloc(sizeof(func_table), GFP_KERNEL); @@ -82,12 +81,11 @@ kbd_alloc(void) { kzalloc(sizeof(fn_handler_fn *) * NR_FN_HANDLER, GFP_KERNEL); if (!kbd->fn_handler) goto out_func; - kbd->accent_table = - kmalloc(sizeof(struct kbdiacruc)*MAX_DIACR, GFP_KERNEL); + kbd->accent_table = kmemdup(accent_table, + sizeof(struct kbdiacruc) * MAX_DIACR, + GFP_KERNEL); if (!kbd->accent_table) goto out_fn_handler; - memcpy(kbd->accent_table, accent_table, - sizeof(struct kbdiacruc)*MAX_DIACR); kbd->accent_table_size = accent_table_size; return kbd; -- cgit v0.10.2 From 47ab0dee661dbd5aca67abe44a333e471134fbf9 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 15 May 2010 11:02:43 +0100 Subject: ARM: Optionally allow ARMv6 to use 'normal, bufferable' memory for DMA Provide a configuration option to allow the ARMv6 to use normal bufferable memory for coherent DMA. This option is forced to 'y' for ARMv7, and offered as a configuration option on ARMv6. Enabling this option requires drivers to have the necessary barriers to ensure that data in DMA coherent memory is visible prior to the DMA operation commencing. Reviewed-by: Catalin Marinas Signed-off-by: Russell King diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index 1139768..ab68cf1 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -314,7 +314,7 @@ static inline pte_t pte_mkspecial(pte_t pte) { return pte; } __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED) #define pgprot_writecombine(prot) \ __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE) -#if __LINUX_ARM_ARCH__ >= 7 +#ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE #define pgprot_dmacoherent(prot) \ __pgprot_modify(prot, L_PTE_MT_MASK|L_PTE_EXEC, L_PTE_MT_BUFFERABLE) #else diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index ca88e6a..02f5d99 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -137,7 +137,7 @@ extern unsigned int user_debug; #define dmb() __asm__ __volatile__ ("" : : : "memory") #endif -#if __LINUX_ARM_ARCH__ >= 7 || defined(CONFIG_SMP) +#if defined(CONFIG_ARM_DMA_MEM_BUFFERABLE) || defined(CONFIG_SMP) #define mb() dmb() #define rmb() dmb() #define wmb() dmb() diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index c4ed9f9..573528d 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -781,3 +781,22 @@ config ARM_L1_CACHE_SHIFT int default 6 if ARM_L1_CACHE_SHIFT_6 default 5 + +config ARM_DMA_MEM_BUFFERABLE + bool "Use non-cacheable memory for DMA" if CPU_V6 && !CPU_V7 + default y if CPU_V6 || CPU_V7 + help + Historically, the kernel has used strongly ordered mappings to + provide DMA coherent memory. With the advent of ARMv7, mapping + memory with differing types results in unpredictable behaviour, + so on these CPUs, this option is forced on. + + Multiple mappings with differing attributes is also unpredictable + on ARMv6 CPUs, but since they do not have aggressive speculative + prefetch, no harm appears to occur. + + However, drivers may be missing the necessary barriers for ARMv6, + and therefore turning this on may result in unpredictable driver + behaviour. Therefore, we offer this as an option. + + You are recommended say 'Y' here and debug any affected drivers. -- cgit v0.10.2 From 49c006b93769a86bec2b32b9234abf016ac0d50e Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Thu, 29 Apr 2010 17:13:24 +0100 Subject: ARM: 6064/1: pmu: register IRQs at runtime The current PMU infrastructure for ARM requires that the IRQs for the PMU device are fixed at compile time and are selected based on the ARCH_ or MACH_ flags. This has the disadvantage of tying the Kernel down to a particular board as far as profiling is concerned. This patch replaces the compile-time IRQ registration with a runtime mechanism which allows the IRQs to be registered with the framework as a platform_device. A further advantage of this change is that there is scope for registering different types of performance counters in the future by changing the id of the platform_device and attaching different resources to it. Acked-by: Jamie Iles Signed-off-by: Will Deacon Signed-off-by: Russell King diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h index 44bec1f..8ccea01 100644 --- a/arch/arm/include/asm/pmu.h +++ b/arch/arm/include/asm/pmu.h @@ -19,31 +19,26 @@ enum arm_pmu_type { #ifdef CONFIG_CPU_HAS_PMU -struct pmu_irqs { - const int *irqs; - int num_irqs; -}; - /** * reserve_pmu() - reserve the hardware performance counters * * Reserve the hardware performance counters in the system for exclusive use. - * The 'struct pmu_irqs' for the system is returned on success, ERR_PTR() + * The platform_device for the system is returned on success, ERR_PTR() * encoded error on failure. */ -extern const struct pmu_irqs * -reserve_pmu(void); +extern struct platform_device * +reserve_pmu(enum arm_pmu_type device); /** * release_pmu() - Relinquish control of the performance counters * * Release the performance counters and allow someone else to use them. * Callers must have disabled the counters and released IRQs before calling - * this. The 'struct pmu_irqs' returned from reserve_pmu() must be passed as + * this. The platform_device returned from reserve_pmu() must be passed as * a cookie. */ extern int -release_pmu(const struct pmu_irqs *irqs); +release_pmu(struct platform_device *pdev); /** * init_pmu() - Initialise the PMU. @@ -53,24 +48,26 @@ release_pmu(const struct pmu_irqs *irqs); * the actual hardware initialisation. */ extern int -init_pmu(void); +init_pmu(enum arm_pmu_type device); #else /* CONFIG_CPU_HAS_PMU */ -static inline const struct pmu_irqs * -reserve_pmu(void) +#include + +static inline struct platform_device * +reserve_pmu(enum arm_pmu_type device) { return ERR_PTR(-ENODEV); } static inline int -release_pmu(const struct pmu_irqs *irqs) +release_pmu(struct platform_device *pdev) { return -ENODEV; } static inline int -init_pmu(void) +init_pmu(enum arm_pmu_type device) { return -ENODEV; } diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index 9e70f20..89a77fc 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -26,7 +27,7 @@ #include #include -static const struct pmu_irqs *pmu_irqs; +static struct platform_device *pmu_device; /* * Hardware lock to serialize accesses to PMU registers. Needed for the @@ -314,38 +315,44 @@ validate_group(struct perf_event *event) static int armpmu_reserve_hardware(void) { - int i; - int err; + int i, err = -ENODEV, irq; - pmu_irqs = reserve_pmu(); - if (IS_ERR(pmu_irqs)) { + pmu_device = reserve_pmu(ARM_PMU_DEVICE_CPU); + if (IS_ERR(pmu_device)) { pr_warning("unable to reserve pmu\n"); - return PTR_ERR(pmu_irqs); + return PTR_ERR(pmu_device); } - init_pmu(); + init_pmu(ARM_PMU_DEVICE_CPU); - if (pmu_irqs->num_irqs < 1) { + if (pmu_device->num_resources < 1) { pr_err("no irqs for PMUs defined\n"); return -ENODEV; } - for (i = 0; i < pmu_irqs->num_irqs; ++i) { - err = request_irq(pmu_irqs->irqs[i], armpmu->handle_irq, + for (i = 0; i < pmu_device->num_resources; ++i) { + irq = platform_get_irq(pmu_device, i); + if (irq < 0) + continue; + + err = request_irq(irq, armpmu->handle_irq, IRQF_DISABLED | IRQF_NOBALANCING, "armpmu", NULL); if (err) { - pr_warning("unable to request IRQ%d for ARM " - "perf counters\n", pmu_irqs->irqs[i]); + pr_warning("unable to request IRQ%d for ARM perf " + "counters\n", irq); break; } } if (err) { - for (i = i - 1; i >= 0; --i) - free_irq(pmu_irqs->irqs[i], NULL); - release_pmu(pmu_irqs); - pmu_irqs = NULL; + for (i = i - 1; i >= 0; --i) { + irq = platform_get_irq(pmu_device, i); + if (irq >= 0) + free_irq(irq, NULL); + } + release_pmu(pmu_device); + pmu_device = NULL; } return err; @@ -354,14 +361,17 @@ armpmu_reserve_hardware(void) static void armpmu_release_hardware(void) { - int i; + int i, irq; - for (i = pmu_irqs->num_irqs - 1; i >= 0; --i) - free_irq(pmu_irqs->irqs[i], NULL); + for (i = pmu_device->num_resources - 1; i >= 0; --i) { + irq = platform_get_irq(pmu_device, i); + if (irq >= 0) + free_irq(irq, NULL); + } armpmu->stop(); - release_pmu(pmu_irqs); - pmu_irqs = NULL; + release_pmu(pmu_device); + pmu_device = NULL; } static atomic_t active_events = ATOMIC_INIT(0); diff --git a/arch/arm/kernel/pmu.c b/arch/arm/kernel/pmu.c index a124312..b8af96e 100644 --- a/arch/arm/kernel/pmu.c +++ b/arch/arm/kernel/pmu.c @@ -2,6 +2,7 @@ * linux/arch/arm/kernel/pmu.c * * Copyright (C) 2009 picoChip Designs Ltd, Jamie Iles + * Copyright (C) 2010 ARM Ltd, Will Deacon * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -9,65 +10,78 @@ * */ +#define pr_fmt(fmt) "PMU: " fmt + #include #include #include #include #include +#include #include -/* - * Define the IRQs for the system. We could use something like a platform - * device but that seems fairly heavyweight for this. Also, the performance - * counters can't be removed or hotplugged. - * - * Ordering is important: init_pmu() will use the ordering to set the affinity - * to the corresponding core. e.g. the first interrupt will go to cpu 0, the - * second goes to cpu 1 etc. - */ -static const int irqs[] = { -#if defined(CONFIG_ARCH_OMAP2) - 3, -#elif defined(CONFIG_ARCH_BCMRING) - IRQ_PMUIRQ, -#elif defined(CONFIG_MACH_REALVIEW_EB) - IRQ_EB11MP_PMU_CPU0, - IRQ_EB11MP_PMU_CPU1, - IRQ_EB11MP_PMU_CPU2, - IRQ_EB11MP_PMU_CPU3, -#elif defined(CONFIG_ARCH_OMAP3) - INT_34XX_BENCH_MPU_EMUL, -#elif defined(CONFIG_ARCH_IOP32X) - IRQ_IOP32X_CORE_PMU, -#elif defined(CONFIG_ARCH_IOP33X) - IRQ_IOP33X_CORE_PMU, -#elif defined(CONFIG_ARCH_PXA) - IRQ_PMU, -#endif -}; +static volatile long pmu_lock; + +static struct platform_device *pmu_devices[ARM_NUM_PMU_DEVICES]; + +static int __devinit pmu_device_probe(struct platform_device *pdev) +{ + + if (pdev->id < 0 || pdev->id >= ARM_NUM_PMU_DEVICES) { + pr_warning("received registration request for unknown " + "device %d\n", pdev->id); + return -EINVAL; + } + + if (pmu_devices[pdev->id]) + pr_warning("registering new PMU device type %d overwrites " + "previous registration!\n", pdev->id); + else + pr_info("registered new PMU device of type %d\n", + pdev->id); -static const struct pmu_irqs pmu_irqs = { - .irqs = irqs, - .num_irqs = ARRAY_SIZE(irqs), + pmu_devices[pdev->id] = pdev; + return 0; +} + +static struct platform_driver pmu_driver = { + .driver = { + .name = "arm-pmu", + }, + .probe = pmu_device_probe, }; -static volatile long pmu_lock; +static int __init register_pmu_driver(void) +{ + return platform_driver_register(&pmu_driver); +} +device_initcall(register_pmu_driver); -const struct pmu_irqs * -reserve_pmu(void) +struct platform_device * +reserve_pmu(enum arm_pmu_type device) { - return test_and_set_bit_lock(0, &pmu_lock) ? ERR_PTR(-EBUSY) : - &pmu_irqs; + struct platform_device *pdev; + + if (test_and_set_bit_lock(device, &pmu_lock)) { + pdev = ERR_PTR(-EBUSY); + } else if (pmu_devices[device] == NULL) { + clear_bit_unlock(device, &pmu_lock); + pdev = ERR_PTR(-ENODEV); + } else { + pdev = pmu_devices[device]; + } + + return pdev; } EXPORT_SYMBOL_GPL(reserve_pmu); int -release_pmu(const struct pmu_irqs *irqs) +release_pmu(struct platform_device *pdev) { - if (WARN_ON(irqs != &pmu_irqs)) + if (WARN_ON(pdev != pmu_devices[pdev->id])) return -EINVAL; - clear_bit_unlock(0, &pmu_lock); + clear_bit_unlock(pdev->id, &pmu_lock); return 0; } EXPORT_SYMBOL_GPL(release_pmu); @@ -87,17 +101,42 @@ set_irq_affinity(int irq, #endif } -int -init_pmu(void) +static int +init_cpu_pmu(void) { int i, err = 0; + struct platform_device *pdev = pmu_devices[ARM_PMU_DEVICE_CPU]; + + if (!pdev) { + err = -ENODEV; + goto out; + } - for (i = 0; i < pmu_irqs.num_irqs; ++i) { - err = set_irq_affinity(pmu_irqs.irqs[i], i); + for (i = 0; i < pdev->num_resources; ++i) { + err = set_irq_affinity(platform_get_irq(pdev, i), i); if (err) break; } +out: + return err; +} + +int +init_pmu(enum arm_pmu_type device) +{ + int err = 0; + + switch (device) { + case ARM_PMU_DEVICE_CPU: + err = init_cpu_pmu(); + break; + default: + pr_warning("attempt to initialise unknown device %d\n", + device); + err = -EINVAL; + } + return err; } EXPORT_SYMBOL_GPL(init_pmu); -- cgit v0.10.2 From 181193f398e7d8da6b1196138f0e219709621743 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 30 Apr 2010 11:32:44 +0100 Subject: ARM: 6069/1: perf-events: use numeric ID to identify PMU The ARM perf-events framework provides support for a number of different PMUs using struct arm_pmu. The char *name field of this struct can be used to identify the PMU, but this is cumbersome if used outside of perf. This patch replaces the name string for a PMU with an enum, which holds a unique ID for the PMU being represented. This ID can be used to index an array of names within perf, so no functionality is lost. The presence of the ID field, allows other kernel subsystems [currently oprofile] to use their own mappings for the PMU name. Cc: Jean Pihet Acked-by: Jamie Iles Signed-off-by: Will Deacon Signed-off-by: Russell King diff --git a/arch/arm/include/asm/perf_event.h b/arch/arm/include/asm/perf_event.h index 49e3049..fa4b326 100644 --- a/arch/arm/include/asm/perf_event.h +++ b/arch/arm/include/asm/perf_event.h @@ -28,4 +28,18 @@ set_perf_event_pending(void) * same indexes here for consistency. */ #define PERF_EVENT_INDEX_OFFSET 1 +/* ARM perf PMU IDs for use by internal perf clients. */ +enum arm_perf_pmu_ids { + ARM_PERF_PMU_ID_XSCALE1 = 0, + ARM_PERF_PMU_ID_XSCALE2, + ARM_PERF_PMU_ID_V6, + ARM_PERF_PMU_ID_V6MP, + ARM_PERF_PMU_ID_CA8, + ARM_PERF_PMU_ID_CA9, + ARM_NUM_PMU_IDS, +}; + +extern enum arm_perf_pmu_ids +armpmu_get_pmu_id(void); + #endif /* __ARM_PERF_EVENT_H__ */ diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index 89a77fc..10a0bcd 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -68,8 +69,18 @@ struct cpu_hw_events { }; DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events); +/* PMU names. */ +static const char *arm_pmu_names[] = { + [ARM_PERF_PMU_ID_XSCALE1] = "xscale1", + [ARM_PERF_PMU_ID_XSCALE2] = "xscale2", + [ARM_PERF_PMU_ID_V6] = "v6", + [ARM_PERF_PMU_ID_V6MP] = "v6mpcore", + [ARM_PERF_PMU_ID_CA8] = "ARMv7 Cortex-A8", + [ARM_PERF_PMU_ID_CA9] = "ARMv7 Cortex-A9", +}; + struct arm_pmu { - char *name; + enum arm_perf_pmu_ids id; irqreturn_t (*handle_irq)(int irq_num, void *dev); void (*enable)(struct hw_perf_event *evt, int idx); void (*disable)(struct hw_perf_event *evt, int idx); @@ -88,6 +99,18 @@ struct arm_pmu { /* Set at runtime when we know what CPU type we are. */ static const struct arm_pmu *armpmu; +enum arm_perf_pmu_ids +armpmu_get_pmu_id(void) +{ + int id = -ENODEV; + + if (armpmu != NULL) + id = armpmu->id; + + return id; +} +EXPORT_SYMBOL_GPL(armpmu_get_pmu_id); + #define HW_OP_UNSUPPORTED 0xFFFF #define C(_x) \ @@ -1154,7 +1177,7 @@ armv6mpcore_pmu_disable_event(struct hw_perf_event *hwc, } static const struct arm_pmu armv6pmu = { - .name = "v6", + .id = ARM_PERF_PMU_ID_V6, .handle_irq = armv6pmu_handle_irq, .enable = armv6pmu_enable_event, .disable = armv6pmu_disable_event, @@ -1177,7 +1200,7 @@ static const struct arm_pmu armv6pmu = { * reset the period and enable the interrupt reporting. */ static const struct arm_pmu armv6mpcore_pmu = { - .name = "v6mpcore", + .id = ARM_PERF_PMU_ID_V6MP, .handle_irq = armv6pmu_handle_irq, .enable = armv6pmu_enable_event, .disable = armv6mpcore_pmu_disable_event, @@ -1207,10 +1230,6 @@ static const struct arm_pmu armv6mpcore_pmu = { * counter and all 4 performance counters together can be reset separately. */ -#define ARMV7_PMU_CORTEX_A8_NAME "ARMv7 Cortex-A8" - -#define ARMV7_PMU_CORTEX_A9_NAME "ARMv7 Cortex-A9" - /* Common ARMv7 event types */ enum armv7_perf_types { ARMV7_PERFCTR_PMNC_SW_INCR = 0x00, @@ -2115,7 +2134,7 @@ init_hw_perf_events(void) perf_max_events = armv6mpcore_pmu.num_events; break; case 0xC080: /* Cortex-A8 */ - armv7pmu.name = ARMV7_PMU_CORTEX_A8_NAME; + armv7pmu.id = ARM_PERF_PMU_ID_CA8; memcpy(armpmu_perf_cache_map, armv7_a8_perf_cache_map, sizeof(armv7_a8_perf_cache_map)); armv7pmu.event_map = armv7_a8_pmu_event_map; @@ -2127,7 +2146,7 @@ init_hw_perf_events(void) perf_max_events = armv7pmu.num_events; break; case 0xC090: /* Cortex-A9 */ - armv7pmu.name = ARMV7_PMU_CORTEX_A9_NAME; + armv7pmu.id = ARM_PERF_PMU_ID_CA9; memcpy(armpmu_perf_cache_map, armv7_a9_perf_cache_map, sizeof(armv7_a9_perf_cache_map)); armv7pmu.event_map = armv7_a9_pmu_event_map; @@ -2146,7 +2165,7 @@ init_hw_perf_events(void) if (armpmu) pr_info("enabled with %s PMU driver, %d counters available\n", - armpmu->name, armpmu->num_events); + arm_pmu_names[armpmu->id], armpmu->num_events); return 0; } -- cgit v0.10.2 From 49e6a32f2f0876b6267584d9c7e0e213bca6e2b8 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 30 Apr 2010 11:33:33 +0100 Subject: ARM: 6070/1: perf-events: add support for xscale PMUs The perf-events framework for ARM only supports v6 and v7 cores. This patch adds support for xscale v1 and v2 PMUs to perf, based on the OProfile drivers in arch/arm/oprofile/op_model_xscale.c Signed-off-by: Will Deacon Signed-off-by: Russell King diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index 10a0bcd..381f121 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -2108,6 +2108,803 @@ static u32 __init armv7_reset_read_pmnc(void) return nb_cnt + 1; } +/* + * ARMv5 [xscale] Performance counter handling code. + * + * Based on xscale OProfile code. + * + * There are two variants of the xscale PMU that we support: + * - xscale1pmu: 2 event counters and a cycle counter + * - xscale2pmu: 4 event counters and a cycle counter + * The two variants share event definitions, but have different + * PMU structures. + */ + +enum xscale_perf_types { + XSCALE_PERFCTR_ICACHE_MISS = 0x00, + XSCALE_PERFCTR_ICACHE_NO_DELIVER = 0x01, + XSCALE_PERFCTR_DATA_STALL = 0x02, + XSCALE_PERFCTR_ITLB_MISS = 0x03, + XSCALE_PERFCTR_DTLB_MISS = 0x04, + XSCALE_PERFCTR_BRANCH = 0x05, + XSCALE_PERFCTR_BRANCH_MISS = 0x06, + XSCALE_PERFCTR_INSTRUCTION = 0x07, + XSCALE_PERFCTR_DCACHE_FULL_STALL = 0x08, + XSCALE_PERFCTR_DCACHE_FULL_STALL_CONTIG = 0x09, + XSCALE_PERFCTR_DCACHE_ACCESS = 0x0A, + XSCALE_PERFCTR_DCACHE_MISS = 0x0B, + XSCALE_PERFCTR_DCACHE_WRITE_BACK = 0x0C, + XSCALE_PERFCTR_PC_CHANGED = 0x0D, + XSCALE_PERFCTR_BCU_REQUEST = 0x10, + XSCALE_PERFCTR_BCU_FULL = 0x11, + XSCALE_PERFCTR_BCU_DRAIN = 0x12, + XSCALE_PERFCTR_BCU_ECC_NO_ELOG = 0x14, + XSCALE_PERFCTR_BCU_1_BIT_ERR = 0x15, + XSCALE_PERFCTR_RMW = 0x16, + /* XSCALE_PERFCTR_CCNT is not hardware defined */ + XSCALE_PERFCTR_CCNT = 0xFE, + XSCALE_PERFCTR_UNUSED = 0xFF, +}; + +enum xscale_counters { + XSCALE_CYCLE_COUNTER = 1, + XSCALE_COUNTER0, + XSCALE_COUNTER1, + XSCALE_COUNTER2, + XSCALE_COUNTER3, +}; + +static const unsigned xscale_perf_map[PERF_COUNT_HW_MAX] = { + [PERF_COUNT_HW_CPU_CYCLES] = XSCALE_PERFCTR_CCNT, + [PERF_COUNT_HW_INSTRUCTIONS] = XSCALE_PERFCTR_INSTRUCTION, + [PERF_COUNT_HW_CACHE_REFERENCES] = HW_OP_UNSUPPORTED, + [PERF_COUNT_HW_CACHE_MISSES] = HW_OP_UNSUPPORTED, + [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = XSCALE_PERFCTR_BRANCH, + [PERF_COUNT_HW_BRANCH_MISSES] = XSCALE_PERFCTR_BRANCH_MISS, + [PERF_COUNT_HW_BUS_CYCLES] = HW_OP_UNSUPPORTED, +}; + +static const unsigned xscale_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] + [PERF_COUNT_HW_CACHE_OP_MAX] + [PERF_COUNT_HW_CACHE_RESULT_MAX] = { + [C(L1D)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = XSCALE_PERFCTR_DCACHE_ACCESS, + [C(RESULT_MISS)] = XSCALE_PERFCTR_DCACHE_MISS, + }, + [C(OP_WRITE)] = { + [C(RESULT_ACCESS)] = XSCALE_PERFCTR_DCACHE_ACCESS, + [C(RESULT_MISS)] = XSCALE_PERFCTR_DCACHE_MISS, + }, + [C(OP_PREFETCH)] = { + [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, + [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, + }, + }, + [C(L1I)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, + [C(RESULT_MISS)] = XSCALE_PERFCTR_ICACHE_MISS, + }, + [C(OP_WRITE)] = { + [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, + [C(RESULT_MISS)] = XSCALE_PERFCTR_ICACHE_MISS, + }, + [C(OP_PREFETCH)] = { + [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, + [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, + }, + }, + [C(LL)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, + [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, + }, + [C(OP_WRITE)] = { + [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, + [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, + }, + [C(OP_PREFETCH)] = { + [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, + [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, + }, + }, + [C(DTLB)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, + [C(RESULT_MISS)] = XSCALE_PERFCTR_DTLB_MISS, + }, + [C(OP_WRITE)] = { + [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, + [C(RESULT_MISS)] = XSCALE_PERFCTR_DTLB_MISS, + }, + [C(OP_PREFETCH)] = { + [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, + [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, + }, + }, + [C(ITLB)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, + [C(RESULT_MISS)] = XSCALE_PERFCTR_ITLB_MISS, + }, + [C(OP_WRITE)] = { + [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, + [C(RESULT_MISS)] = XSCALE_PERFCTR_ITLB_MISS, + }, + [C(OP_PREFETCH)] = { + [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, + [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, + }, + }, + [C(BPU)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, + [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, + }, + [C(OP_WRITE)] = { + [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, + [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, + }, + [C(OP_PREFETCH)] = { + [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED, + [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED, + }, + }, +}; + +#define XSCALE_PMU_ENABLE 0x001 +#define XSCALE_PMN_RESET 0x002 +#define XSCALE_CCNT_RESET 0x004 +#define XSCALE_PMU_RESET (CCNT_RESET | PMN_RESET) +#define XSCALE_PMU_CNT64 0x008 + +static inline int +xscalepmu_event_map(int config) +{ + int mapping = xscale_perf_map[config]; + if (HW_OP_UNSUPPORTED == mapping) + mapping = -EOPNOTSUPP; + return mapping; +} + +static u64 +xscalepmu_raw_event(u64 config) +{ + return config & 0xff; +} + +#define XSCALE1_OVERFLOWED_MASK 0x700 +#define XSCALE1_CCOUNT_OVERFLOW 0x400 +#define XSCALE1_COUNT0_OVERFLOW 0x100 +#define XSCALE1_COUNT1_OVERFLOW 0x200 +#define XSCALE1_CCOUNT_INT_EN 0x040 +#define XSCALE1_COUNT0_INT_EN 0x010 +#define XSCALE1_COUNT1_INT_EN 0x020 +#define XSCALE1_COUNT0_EVT_SHFT 12 +#define XSCALE1_COUNT0_EVT_MASK (0xff << XSCALE1_COUNT0_EVT_SHFT) +#define XSCALE1_COUNT1_EVT_SHFT 20 +#define XSCALE1_COUNT1_EVT_MASK (0xff << XSCALE1_COUNT1_EVT_SHFT) + +static inline u32 +xscale1pmu_read_pmnc(void) +{ + u32 val; + asm volatile("mrc p14, 0, %0, c0, c0, 0" : "=r" (val)); + return val; +} + +static inline void +xscale1pmu_write_pmnc(u32 val) +{ + /* upper 4bits and 7, 11 are write-as-0 */ + val &= 0xffff77f; + asm volatile("mcr p14, 0, %0, c0, c0, 0" : : "r" (val)); +} + +static inline int +xscale1_pmnc_counter_has_overflowed(unsigned long pmnc, + enum xscale_counters counter) +{ + int ret = 0; + + switch (counter) { + case XSCALE_CYCLE_COUNTER: + ret = pmnc & XSCALE1_CCOUNT_OVERFLOW; + break; + case XSCALE_COUNTER0: + ret = pmnc & XSCALE1_COUNT0_OVERFLOW; + break; + case XSCALE_COUNTER1: + ret = pmnc & XSCALE1_COUNT1_OVERFLOW; + break; + default: + WARN_ONCE(1, "invalid counter number (%d)\n", counter); + } + + return ret; +} + +static irqreturn_t +xscale1pmu_handle_irq(int irq_num, void *dev) +{ + unsigned long pmnc; + struct perf_sample_data data; + struct cpu_hw_events *cpuc; + struct pt_regs *regs; + int idx; + + /* + * NOTE: there's an A stepping erratum that states if an overflow + * bit already exists and another occurs, the previous + * Overflow bit gets cleared. There's no workaround. + * Fixed in B stepping or later. + */ + pmnc = xscale1pmu_read_pmnc(); + + /* + * Write the value back to clear the overflow flags. Overflow + * flags remain in pmnc for use below. We also disable the PMU + * while we process the interrupt. + */ + xscale1pmu_write_pmnc(pmnc & ~XSCALE_PMU_ENABLE); + + if (!(pmnc & XSCALE1_OVERFLOWED_MASK)) + return IRQ_NONE; + + regs = get_irq_regs(); + + perf_sample_data_init(&data, 0); + + cpuc = &__get_cpu_var(cpu_hw_events); + for (idx = 0; idx <= armpmu->num_events; ++idx) { + struct perf_event *event = cpuc->events[idx]; + struct hw_perf_event *hwc; + + if (!test_bit(idx, cpuc->active_mask)) + continue; + + if (!xscale1_pmnc_counter_has_overflowed(pmnc, idx)) + continue; + + hwc = &event->hw; + armpmu_event_update(event, hwc, idx); + data.period = event->hw.last_period; + if (!armpmu_event_set_period(event, hwc, idx)) + continue; + + if (perf_event_overflow(event, 0, &data, regs)) + armpmu->disable(hwc, idx); + } + + perf_event_do_pending(); + + /* + * Re-enable the PMU. + */ + pmnc = xscale1pmu_read_pmnc() | XSCALE_PMU_ENABLE; + xscale1pmu_write_pmnc(pmnc); + + return IRQ_HANDLED; +} + +static void +xscale1pmu_enable_event(struct hw_perf_event *hwc, int idx) +{ + unsigned long val, mask, evt, flags; + + switch (idx) { + case XSCALE_CYCLE_COUNTER: + mask = 0; + evt = XSCALE1_CCOUNT_INT_EN; + break; + case XSCALE_COUNTER0: + mask = XSCALE1_COUNT0_EVT_MASK; + evt = (hwc->config_base << XSCALE1_COUNT0_EVT_SHFT) | + XSCALE1_COUNT0_INT_EN; + break; + case XSCALE_COUNTER1: + mask = XSCALE1_COUNT1_EVT_MASK; + evt = (hwc->config_base << XSCALE1_COUNT1_EVT_SHFT) | + XSCALE1_COUNT1_INT_EN; + break; + default: + WARN_ONCE(1, "invalid counter number (%d)\n", idx); + return; + } + + spin_lock_irqsave(&pmu_lock, flags); + val = xscale1pmu_read_pmnc(); + val &= ~mask; + val |= evt; + xscale1pmu_write_pmnc(val); + spin_unlock_irqrestore(&pmu_lock, flags); +} + +static void +xscale1pmu_disable_event(struct hw_perf_event *hwc, int idx) +{ + unsigned long val, mask, evt, flags; + + switch (idx) { + case XSCALE_CYCLE_COUNTER: + mask = XSCALE1_CCOUNT_INT_EN; + evt = 0; + break; + case XSCALE_COUNTER0: + mask = XSCALE1_COUNT0_INT_EN | XSCALE1_COUNT0_EVT_MASK; + evt = XSCALE_PERFCTR_UNUSED << XSCALE1_COUNT0_EVT_SHFT; + break; + case XSCALE_COUNTER1: + mask = XSCALE1_COUNT1_INT_EN | XSCALE1_COUNT1_EVT_MASK; + evt = XSCALE_PERFCTR_UNUSED << XSCALE1_COUNT1_EVT_SHFT; + break; + default: + WARN_ONCE(1, "invalid counter number (%d)\n", idx); + return; + } + + spin_lock_irqsave(&pmu_lock, flags); + val = xscale1pmu_read_pmnc(); + val &= ~mask; + val |= evt; + xscale1pmu_write_pmnc(val); + spin_unlock_irqrestore(&pmu_lock, flags); +} + +static int +xscale1pmu_get_event_idx(struct cpu_hw_events *cpuc, + struct hw_perf_event *event) +{ + if (XSCALE_PERFCTR_CCNT == event->config_base) { + if (test_and_set_bit(XSCALE_CYCLE_COUNTER, cpuc->used_mask)) + return -EAGAIN; + + return XSCALE_CYCLE_COUNTER; + } else { + if (!test_and_set_bit(XSCALE_COUNTER1, cpuc->used_mask)) { + return XSCALE_COUNTER1; + } + + if (!test_and_set_bit(XSCALE_COUNTER0, cpuc->used_mask)) { + return XSCALE_COUNTER0; + } + + return -EAGAIN; + } +} + +static void +xscale1pmu_start(void) +{ + unsigned long flags, val; + + spin_lock_irqsave(&pmu_lock, flags); + val = xscale1pmu_read_pmnc(); + val |= XSCALE_PMU_ENABLE; + xscale1pmu_write_pmnc(val); + spin_unlock_irqrestore(&pmu_lock, flags); +} + +static void +xscale1pmu_stop(void) +{ + unsigned long flags, val; + + spin_lock_irqsave(&pmu_lock, flags); + val = xscale1pmu_read_pmnc(); + val &= ~XSCALE_PMU_ENABLE; + xscale1pmu_write_pmnc(val); + spin_unlock_irqrestore(&pmu_lock, flags); +} + +static inline u32 +xscale1pmu_read_counter(int counter) +{ + u32 val = 0; + + switch (counter) { + case XSCALE_CYCLE_COUNTER: + asm volatile("mrc p14, 0, %0, c1, c0, 0" : "=r" (val)); + break; + case XSCALE_COUNTER0: + asm volatile("mrc p14, 0, %0, c2, c0, 0" : "=r" (val)); + break; + case XSCALE_COUNTER1: + asm volatile("mrc p14, 0, %0, c3, c0, 0" : "=r" (val)); + break; + } + + return val; +} + +static inline void +xscale1pmu_write_counter(int counter, u32 val) +{ + switch (counter) { + case XSCALE_CYCLE_COUNTER: + asm volatile("mcr p14, 0, %0, c1, c0, 0" : : "r" (val)); + break; + case XSCALE_COUNTER0: + asm volatile("mcr p14, 0, %0, c2, c0, 0" : : "r" (val)); + break; + case XSCALE_COUNTER1: + asm volatile("mcr p14, 0, %0, c3, c0, 0" : : "r" (val)); + break; + } +} + +static const struct arm_pmu xscale1pmu = { + .id = ARM_PERF_PMU_ID_XSCALE1, + .handle_irq = xscale1pmu_handle_irq, + .enable = xscale1pmu_enable_event, + .disable = xscale1pmu_disable_event, + .event_map = xscalepmu_event_map, + .raw_event = xscalepmu_raw_event, + .read_counter = xscale1pmu_read_counter, + .write_counter = xscale1pmu_write_counter, + .get_event_idx = xscale1pmu_get_event_idx, + .start = xscale1pmu_start, + .stop = xscale1pmu_stop, + .num_events = 3, + .max_period = (1LLU << 32) - 1, +}; + +#define XSCALE2_OVERFLOWED_MASK 0x01f +#define XSCALE2_CCOUNT_OVERFLOW 0x001 +#define XSCALE2_COUNT0_OVERFLOW 0x002 +#define XSCALE2_COUNT1_OVERFLOW 0x004 +#define XSCALE2_COUNT2_OVERFLOW 0x008 +#define XSCALE2_COUNT3_OVERFLOW 0x010 +#define XSCALE2_CCOUNT_INT_EN 0x001 +#define XSCALE2_COUNT0_INT_EN 0x002 +#define XSCALE2_COUNT1_INT_EN 0x004 +#define XSCALE2_COUNT2_INT_EN 0x008 +#define XSCALE2_COUNT3_INT_EN 0x010 +#define XSCALE2_COUNT0_EVT_SHFT 0 +#define XSCALE2_COUNT0_EVT_MASK (0xff << XSCALE2_COUNT0_EVT_SHFT) +#define XSCALE2_COUNT1_EVT_SHFT 8 +#define XSCALE2_COUNT1_EVT_MASK (0xff << XSCALE2_COUNT1_EVT_SHFT) +#define XSCALE2_COUNT2_EVT_SHFT 16 +#define XSCALE2_COUNT2_EVT_MASK (0xff << XSCALE2_COUNT2_EVT_SHFT) +#define XSCALE2_COUNT3_EVT_SHFT 24 +#define XSCALE2_COUNT3_EVT_MASK (0xff << XSCALE2_COUNT3_EVT_SHFT) + +static inline u32 +xscale2pmu_read_pmnc(void) +{ + u32 val; + asm volatile("mrc p14, 0, %0, c0, c1, 0" : "=r" (val)); + /* bits 1-2 and 4-23 are read-unpredictable */ + return val & 0xff000009; +} + +static inline void +xscale2pmu_write_pmnc(u32 val) +{ + /* bits 4-23 are write-as-0, 24-31 are write ignored */ + val &= 0xf; + asm volatile("mcr p14, 0, %0, c0, c1, 0" : : "r" (val)); +} + +static inline u32 +xscale2pmu_read_overflow_flags(void) +{ + u32 val; + asm volatile("mrc p14, 0, %0, c5, c1, 0" : "=r" (val)); + return val; +} + +static inline void +xscale2pmu_write_overflow_flags(u32 val) +{ + asm volatile("mcr p14, 0, %0, c5, c1, 0" : : "r" (val)); +} + +static inline u32 +xscale2pmu_read_event_select(void) +{ + u32 val; + asm volatile("mrc p14, 0, %0, c8, c1, 0" : "=r" (val)); + return val; +} + +static inline void +xscale2pmu_write_event_select(u32 val) +{ + asm volatile("mcr p14, 0, %0, c8, c1, 0" : : "r"(val)); +} + +static inline u32 +xscale2pmu_read_int_enable(void) +{ + u32 val; + asm volatile("mrc p14, 0, %0, c4, c1, 0" : "=r" (val)); + return val; +} + +static void +xscale2pmu_write_int_enable(u32 val) +{ + asm volatile("mcr p14, 0, %0, c4, c1, 0" : : "r" (val)); +} + +static inline int +xscale2_pmnc_counter_has_overflowed(unsigned long of_flags, + enum xscale_counters counter) +{ + int ret = 0; + + switch (counter) { + case XSCALE_CYCLE_COUNTER: + ret = of_flags & XSCALE2_CCOUNT_OVERFLOW; + break; + case XSCALE_COUNTER0: + ret = of_flags & XSCALE2_COUNT0_OVERFLOW; + break; + case XSCALE_COUNTER1: + ret = of_flags & XSCALE2_COUNT1_OVERFLOW; + break; + case XSCALE_COUNTER2: + ret = of_flags & XSCALE2_COUNT2_OVERFLOW; + break; + case XSCALE_COUNTER3: + ret = of_flags & XSCALE2_COUNT3_OVERFLOW; + break; + default: + WARN_ONCE(1, "invalid counter number (%d)\n", counter); + } + + return ret; +} + +static irqreturn_t +xscale2pmu_handle_irq(int irq_num, void *dev) +{ + unsigned long pmnc, of_flags; + struct perf_sample_data data; + struct cpu_hw_events *cpuc; + struct pt_regs *regs; + int idx; + + /* Disable the PMU. */ + pmnc = xscale2pmu_read_pmnc(); + xscale2pmu_write_pmnc(pmnc & ~XSCALE_PMU_ENABLE); + + /* Check the overflow flag register. */ + of_flags = xscale2pmu_read_overflow_flags(); + if (!(of_flags & XSCALE2_OVERFLOWED_MASK)) + return IRQ_NONE; + + /* Clear the overflow bits. */ + xscale2pmu_write_overflow_flags(of_flags); + + regs = get_irq_regs(); + + perf_sample_data_init(&data, 0); + + cpuc = &__get_cpu_var(cpu_hw_events); + for (idx = 0; idx <= armpmu->num_events; ++idx) { + struct perf_event *event = cpuc->events[idx]; + struct hw_perf_event *hwc; + + if (!test_bit(idx, cpuc->active_mask)) + continue; + + if (!xscale2_pmnc_counter_has_overflowed(pmnc, idx)) + continue; + + hwc = &event->hw; + armpmu_event_update(event, hwc, idx); + data.period = event->hw.last_period; + if (!armpmu_event_set_period(event, hwc, idx)) + continue; + + if (perf_event_overflow(event, 0, &data, regs)) + armpmu->disable(hwc, idx); + } + + perf_event_do_pending(); + + /* + * Re-enable the PMU. + */ + pmnc = xscale2pmu_read_pmnc() | XSCALE_PMU_ENABLE; + xscale2pmu_write_pmnc(pmnc); + + return IRQ_HANDLED; +} + +static void +xscale2pmu_enable_event(struct hw_perf_event *hwc, int idx) +{ + unsigned long flags, ien, evtsel; + + ien = xscale2pmu_read_int_enable(); + evtsel = xscale2pmu_read_event_select(); + + switch (idx) { + case XSCALE_CYCLE_COUNTER: + ien |= XSCALE2_CCOUNT_INT_EN; + break; + case XSCALE_COUNTER0: + ien |= XSCALE2_COUNT0_INT_EN; + evtsel &= ~XSCALE2_COUNT0_EVT_MASK; + evtsel |= hwc->config_base << XSCALE2_COUNT0_EVT_SHFT; + break; + case XSCALE_COUNTER1: + ien |= XSCALE2_COUNT1_INT_EN; + evtsel &= ~XSCALE2_COUNT1_EVT_MASK; + evtsel |= hwc->config_base << XSCALE2_COUNT1_EVT_SHFT; + break; + case XSCALE_COUNTER2: + ien |= XSCALE2_COUNT2_INT_EN; + evtsel &= ~XSCALE2_COUNT2_EVT_MASK; + evtsel |= hwc->config_base << XSCALE2_COUNT2_EVT_SHFT; + break; + case XSCALE_COUNTER3: + ien |= XSCALE2_COUNT3_INT_EN; + evtsel &= ~XSCALE2_COUNT3_EVT_MASK; + evtsel |= hwc->config_base << XSCALE2_COUNT3_EVT_SHFT; + break; + default: + WARN_ONCE(1, "invalid counter number (%d)\n", idx); + return; + } + + spin_lock_irqsave(&pmu_lock, flags); + xscale2pmu_write_event_select(evtsel); + xscale2pmu_write_int_enable(ien); + spin_unlock_irqrestore(&pmu_lock, flags); +} + +static void +xscale2pmu_disable_event(struct hw_perf_event *hwc, int idx) +{ + unsigned long flags, ien, evtsel; + + ien = xscale2pmu_read_int_enable(); + evtsel = xscale2pmu_read_event_select(); + + switch (idx) { + case XSCALE_CYCLE_COUNTER: + ien &= ~XSCALE2_CCOUNT_INT_EN; + break; + case XSCALE_COUNTER0: + ien &= ~XSCALE2_COUNT0_INT_EN; + evtsel &= ~XSCALE2_COUNT0_EVT_MASK; + evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT0_EVT_SHFT; + break; + case XSCALE_COUNTER1: + ien &= ~XSCALE2_COUNT1_INT_EN; + evtsel &= ~XSCALE2_COUNT1_EVT_MASK; + evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT1_EVT_SHFT; + break; + case XSCALE_COUNTER2: + ien &= ~XSCALE2_COUNT2_INT_EN; + evtsel &= ~XSCALE2_COUNT2_EVT_MASK; + evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT2_EVT_SHFT; + break; + case XSCALE_COUNTER3: + ien &= ~XSCALE2_COUNT3_INT_EN; + evtsel &= ~XSCALE2_COUNT3_EVT_MASK; + evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT3_EVT_SHFT; + break; + default: + WARN_ONCE(1, "invalid counter number (%d)\n", idx); + return; + } + + spin_lock_irqsave(&pmu_lock, flags); + xscale2pmu_write_event_select(evtsel); + xscale2pmu_write_int_enable(ien); + spin_unlock_irqrestore(&pmu_lock, flags); +} + +static int +xscale2pmu_get_event_idx(struct cpu_hw_events *cpuc, + struct hw_perf_event *event) +{ + int idx = xscale1pmu_get_event_idx(cpuc, event); + if (idx >= 0) + goto out; + + if (!test_and_set_bit(XSCALE_COUNTER3, cpuc->used_mask)) + idx = XSCALE_COUNTER3; + else if (!test_and_set_bit(XSCALE_COUNTER2, cpuc->used_mask)) + idx = XSCALE_COUNTER2; +out: + return idx; +} + +static void +xscale2pmu_start(void) +{ + unsigned long flags, val; + + spin_lock_irqsave(&pmu_lock, flags); + val = xscale2pmu_read_pmnc() & ~XSCALE_PMU_CNT64; + val |= XSCALE_PMU_ENABLE; + xscale2pmu_write_pmnc(val); + spin_unlock_irqrestore(&pmu_lock, flags); +} + +static void +xscale2pmu_stop(void) +{ + unsigned long flags, val; + + spin_lock_irqsave(&pmu_lock, flags); + val = xscale2pmu_read_pmnc(); + val &= ~XSCALE_PMU_ENABLE; + xscale2pmu_write_pmnc(val); + spin_unlock_irqrestore(&pmu_lock, flags); +} + +static inline u32 +xscale2pmu_read_counter(int counter) +{ + u32 val = 0; + + switch (counter) { + case XSCALE_CYCLE_COUNTER: + asm volatile("mrc p14, 0, %0, c1, c1, 0" : "=r" (val)); + break; + case XSCALE_COUNTER0: + asm volatile("mrc p14, 0, %0, c0, c2, 0" : "=r" (val)); + break; + case XSCALE_COUNTER1: + asm volatile("mrc p14, 0, %0, c1, c2, 0" : "=r" (val)); + break; + case XSCALE_COUNTER2: + asm volatile("mrc p14, 0, %0, c2, c2, 0" : "=r" (val)); + break; + case XSCALE_COUNTER3: + asm volatile("mrc p14, 0, %0, c3, c2, 0" : "=r" (val)); + break; + } + + return val; +} + +static inline void +xscale2pmu_write_counter(int counter, u32 val) +{ + switch (counter) { + case XSCALE_CYCLE_COUNTER: + asm volatile("mcr p14, 0, %0, c1, c1, 0" : : "r" (val)); + break; + case XSCALE_COUNTER0: + asm volatile("mcr p14, 0, %0, c0, c2, 0" : : "r" (val)); + break; + case XSCALE_COUNTER1: + asm volatile("mcr p14, 0, %0, c1, c2, 0" : : "r" (val)); + break; + case XSCALE_COUNTER2: + asm volatile("mcr p14, 0, %0, c2, c2, 0" : : "r" (val)); + break; + case XSCALE_COUNTER3: + asm volatile("mcr p14, 0, %0, c3, c2, 0" : : "r" (val)); + break; + } +} + +static const struct arm_pmu xscale2pmu = { + .id = ARM_PERF_PMU_ID_XSCALE2, + .handle_irq = xscale2pmu_handle_irq, + .enable = xscale2pmu_enable_event, + .disable = xscale2pmu_disable_event, + .event_map = xscalepmu_event_map, + .raw_event = xscalepmu_raw_event, + .read_counter = xscale2pmu_read_counter, + .write_counter = xscale2pmu_write_counter, + .get_event_idx = xscale2pmu_get_event_idx, + .start = xscale2pmu_start, + .stop = xscale2pmu_stop, + .num_events = 5, + .max_period = (1LLU << 32) - 1, +}; + static int __init init_hw_perf_events(void) { @@ -2115,7 +2912,7 @@ init_hw_perf_events(void) unsigned long implementor = (cpuid & 0xFF000000) >> 24; unsigned long part_number = (cpuid & 0xFFF0); - /* We only support ARM CPUs implemented by ARM at the moment. */ + /* ARM Ltd CPUs. */ if (0x41 == implementor) { switch (part_number) { case 0xB360: /* ARM1136 */ @@ -2157,15 +2954,33 @@ init_hw_perf_events(void) armv7pmu.num_events = armv7_reset_read_pmnc(); perf_max_events = armv7pmu.num_events; break; - default: - pr_info("no hardware support available\n"); - perf_max_events = -1; + } + /* Intel CPUs [xscale]. */ + } else if (0x69 == implementor) { + part_number = (cpuid >> 13) & 0x7; + switch (part_number) { + case 1: + armpmu = &xscale1pmu; + memcpy(armpmu_perf_cache_map, xscale_perf_cache_map, + sizeof(xscale_perf_cache_map)); + perf_max_events = xscale1pmu.num_events; + break; + case 2: + armpmu = &xscale2pmu; + memcpy(armpmu_perf_cache_map, xscale_perf_cache_map, + sizeof(xscale_perf_cache_map)); + perf_max_events = xscale2pmu.num_events; + break; } } - if (armpmu) + if (armpmu) { pr_info("enabled with %s PMU driver, %d counters available\n", - arm_pmu_names[armpmu->id], armpmu->num_events); + arm_pmu_names[armpmu->id], armpmu->num_events); + } else { + pr_info("no hardware support available\n"); + perf_max_events = -1; + } return 0; } -- cgit v0.10.2 From 929f5199448a67d41bb249d58815ef77bcd53622 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 30 Apr 2010 11:34:26 +0100 Subject: ARM: 6071/1: perf-events: allow modules to query the number of hardware counters For OProfile to initialise oprofilefs correctly, it needs to know the number of counters it can represent. This patch adds a function to the ARM perf-events backend to return the number of hardware counters available for the current PMU. Cc: Jamie Iles Signed-off-by: Will Deacon Signed-off-by: Russell King diff --git a/arch/arm/include/asm/perf_event.h b/arch/arm/include/asm/perf_event.h index fa4b326..48837e6 100644 --- a/arch/arm/include/asm/perf_event.h +++ b/arch/arm/include/asm/perf_event.h @@ -42,4 +42,7 @@ enum arm_perf_pmu_ids { extern enum arm_perf_pmu_ids armpmu_get_pmu_id(void); +extern int +armpmu_get_max_events(void); + #endif /* __ARM_PERF_EVENT_H__ */ diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index 381f121..c457686 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -111,6 +111,18 @@ armpmu_get_pmu_id(void) } EXPORT_SYMBOL_GPL(armpmu_get_pmu_id); +int +armpmu_get_max_events(void) +{ + int max_events = 0; + + if (armpmu != NULL) + max_events = armpmu->num_events; + + return max_events; +} +EXPORT_SYMBOL_GPL(armpmu_get_max_events); + #define HW_OP_UNSUPPORTED 0xFFFF #define C(_x) \ -- cgit v0.10.2 From 8c1fc96f6fd1f361428ba805103af0d0eee65179 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 30 Apr 2010 11:36:54 +0100 Subject: ARM: 6072/1: oprofile: use perf-events framework as backend There are currently two hardware performance monitoring subsystems in the kernel for ARM: OProfile and perf-events. This creates the following problems: 1.) Duplicate PMU accessor code. Inevitable code drift may lead to bugs in one framework that are fixed in the other. 2.) Locking issues. OProfile doesn't reprogram hardware counters between profiling runs if the events to be monitored have not been changed. This means that other profiling frameworks cannot use the counters if OProfile is in use. 3.) Due to differences in the two frameworks, it may not be possible to compare the results obtained by OProfile with those obtained by perf. This patch removes the OProfile PMU driver code and replaces it with calls to perf, therefore solving the issues mentioned above. The only userspace-visible change is the lack of SCU counter support for 11MPCore. This is currently unsupported by OProfile userspace tools anyway and therefore shouldn't cause any problems. Cc: Ingo Molnar Cc: Peter Zijlstra Cc: Robert Richter Cc: Jamie Iles Cc: Jean Pihet Signed-off-by: Will Deacon Signed-off-by: Russell King diff --git a/arch/arm/oprofile/common.c b/arch/arm/oprofile/common.c index 3fcd752..aad83df 100644 --- a/arch/arm/oprofile/common.c +++ b/arch/arm/oprofile/common.c @@ -2,32 +2,183 @@ * @file common.c * * @remark Copyright 2004 Oprofile Authors + * @remark Copyright 2010 ARM Ltd. * @remark Read the file COPYING * * @author Zwane Mwaikambo + * @author Will Deacon [move to perf] */ +#include +#include #include +#include #include -#include +#include #include #include -#include +#include +#include + +#include +#include -#include "op_counter.h" -#include "op_arm_model.h" +#ifdef CONFIG_HW_PERF_EVENTS +/* + * Per performance monitor configuration as set via oprofilefs. + */ +struct op_counter_config { + unsigned long count; + unsigned long enabled; + unsigned long event; + unsigned long unit_mask; + unsigned long kernel; + unsigned long user; + struct perf_event_attr attr; +}; -static struct op_arm_model_spec *op_arm_model; static int op_arm_enabled; static DEFINE_MUTEX(op_arm_mutex); -struct op_counter_config *counter_config; +static struct op_counter_config *counter_config; +static struct perf_event **perf_events[nr_cpumask_bits]; +static int perf_num_counters; + +/* + * Overflow callback for oprofile. + */ +static void op_overflow_handler(struct perf_event *event, int unused, + struct perf_sample_data *data, struct pt_regs *regs) +{ + int id; + u32 cpu = smp_processor_id(); + + for (id = 0; id < perf_num_counters; ++id) + if (perf_events[cpu][id] == event) + break; + + if (id != perf_num_counters) + oprofile_add_sample(regs, id); + else + pr_warning("oprofile: ignoring spurious overflow " + "on cpu %u\n", cpu); +} + +/* + * Called by op_arm_setup to create perf attributes to mirror the oprofile + * settings in counter_config. Attributes are created as `pinned' events and + * so are permanently scheduled on the PMU. + */ +static void op_perf_setup(void) +{ + int i; + u32 size = sizeof(struct perf_event_attr); + struct perf_event_attr *attr; + + for (i = 0; i < perf_num_counters; ++i) { + attr = &counter_config[i].attr; + memset(attr, 0, size); + attr->type = PERF_TYPE_RAW; + attr->size = size; + attr->config = counter_config[i].event; + attr->sample_period = counter_config[i].count; + attr->pinned = 1; + } +} + +static int op_create_counter(int cpu, int event) +{ + int ret = 0; + struct perf_event *pevent; + + if (!counter_config[event].enabled || (perf_events[cpu][event] != NULL)) + return ret; + + pevent = perf_event_create_kernel_counter(&counter_config[event].attr, + cpu, -1, + op_overflow_handler); + + if (IS_ERR(pevent)) { + ret = PTR_ERR(pevent); + } else if (pevent->state != PERF_EVENT_STATE_ACTIVE) { + pr_warning("oprofile: failed to enable event %d " + "on CPU %d\n", event, cpu); + ret = -EBUSY; + } else { + perf_events[cpu][event] = pevent; + } + + return ret; +} + +static void op_destroy_counter(int cpu, int event) +{ + struct perf_event *pevent = perf_events[cpu][event]; + + if (pevent) { + perf_event_release_kernel(pevent); + perf_events[cpu][event] = NULL; + } +} + +/* + * Called by op_arm_start to create active perf events based on the + * perviously configured attributes. + */ +static int op_perf_start(void) +{ + int cpu, event, ret = 0; + + for_each_online_cpu(cpu) { + for (event = 0; event < perf_num_counters; ++event) { + ret = op_create_counter(cpu, event); + if (ret) + goto out; + } + } + +out: + return ret; +} + +/* + * Called by op_arm_stop at the end of a profiling run. + */ +static void op_perf_stop(void) +{ + int cpu, event; + + for_each_online_cpu(cpu) + for (event = 0; event < perf_num_counters; ++event) + op_destroy_counter(cpu, event); +} + + +static char *op_name_from_perf_id(enum arm_perf_pmu_ids id) +{ + switch (id) { + case ARM_PERF_PMU_ID_XSCALE1: + return "arm/xscale1"; + case ARM_PERF_PMU_ID_XSCALE2: + return "arm/xscale2"; + case ARM_PERF_PMU_ID_V6: + return "arm/armv6"; + case ARM_PERF_PMU_ID_V6MP: + return "arm/mpcore"; + case ARM_PERF_PMU_ID_CA8: + return "arm/armv7"; + case ARM_PERF_PMU_ID_CA9: + return "arm/armv7-ca9"; + default: + return NULL; + } +} static int op_arm_create_files(struct super_block *sb, struct dentry *root) { unsigned int i; - for (i = 0; i < op_arm_model->num_counters; i++) { + for (i = 0; i < perf_num_counters; i++) { struct dentry *dir; char buf[4]; @@ -46,12 +197,10 @@ static int op_arm_create_files(struct super_block *sb, struct dentry *root) static int op_arm_setup(void) { - int ret; - spin_lock(&oprofilefs_lock); - ret = op_arm_model->setup_ctrs(); + op_perf_setup(); spin_unlock(&oprofilefs_lock); - return ret; + return 0; } static int op_arm_start(void) @@ -60,8 +209,9 @@ static int op_arm_start(void) mutex_lock(&op_arm_mutex); if (!op_arm_enabled) { - ret = op_arm_model->start(); - op_arm_enabled = !ret; + ret = 0; + op_perf_start(); + op_arm_enabled = 1; } mutex_unlock(&op_arm_mutex); return ret; @@ -71,7 +221,7 @@ static void op_arm_stop(void) { mutex_lock(&op_arm_mutex); if (op_arm_enabled) - op_arm_model->stop(); + op_perf_stop(); op_arm_enabled = 0; mutex_unlock(&op_arm_mutex); } @@ -81,7 +231,7 @@ static int op_arm_suspend(struct sys_device *dev, pm_message_t state) { mutex_lock(&op_arm_mutex); if (op_arm_enabled) - op_arm_model->stop(); + op_perf_stop(); mutex_unlock(&op_arm_mutex); return 0; } @@ -89,7 +239,7 @@ static int op_arm_suspend(struct sys_device *dev, pm_message_t state) static int op_arm_resume(struct sys_device *dev) { mutex_lock(&op_arm_mutex); - if (op_arm_enabled && op_arm_model->start()) + if (op_arm_enabled && op_perf_start()) op_arm_enabled = 0; mutex_unlock(&op_arm_mutex); return 0; @@ -126,58 +276,137 @@ static void exit_driverfs(void) #define exit_driverfs() do { } while (0) #endif /* CONFIG_PM */ -int __init oprofile_arch_init(struct oprofile_operations *ops) +static int report_trace(struct stackframe *frame, void *d) { - struct op_arm_model_spec *spec = NULL; - int ret = -ENODEV; + unsigned int *depth = d; - ops->backtrace = arm_backtrace; + if (*depth) { + oprofile_add_trace(frame->pc); + (*depth)--; + } -#ifdef CONFIG_CPU_XSCALE - spec = &op_xscale_spec; -#endif + return *depth == 0; +} -#ifdef CONFIG_OPROFILE_ARMV6 - spec = &op_armv6_spec; -#endif +/* + * The registers we're interested in are at the end of the variable + * length saved register structure. The fp points at the end of this + * structure so the address of this struct is: + * (struct frame_tail *)(xxx->fp)-1 + */ +struct frame_tail { + struct frame_tail *fp; + unsigned long sp; + unsigned long lr; +} __attribute__((packed)); -#ifdef CONFIG_OPROFILE_MPCORE - spec = &op_mpcore_spec; -#endif +static struct frame_tail* user_backtrace(struct frame_tail *tail) +{ + struct frame_tail buftail[2]; -#ifdef CONFIG_OPROFILE_ARMV7 - spec = &op_armv7_spec; -#endif + /* Also check accessibility of one struct frame_tail beyond */ + if (!access_ok(VERIFY_READ, tail, sizeof(buftail))) + return NULL; + if (__copy_from_user_inatomic(buftail, tail, sizeof(buftail))) + return NULL; - if (spec) { - ret = spec->init(); - if (ret < 0) - return ret; + oprofile_add_trace(buftail[0].lr); - counter_config = kcalloc(spec->num_counters, sizeof(struct op_counter_config), - GFP_KERNEL); - if (!counter_config) - return -ENOMEM; + /* frame pointers should strictly progress back up the stack + * (towards higher addresses) */ + if (tail >= buftail[0].fp) + return NULL; + + return buftail[0].fp-1; +} + +static void arm_backtrace(struct pt_regs * const regs, unsigned int depth) +{ + struct frame_tail *tail = ((struct frame_tail *) regs->ARM_fp) - 1; + + if (!user_mode(regs)) { + struct stackframe frame; + frame.fp = regs->ARM_fp; + frame.sp = regs->ARM_sp; + frame.lr = regs->ARM_lr; + frame.pc = regs->ARM_pc; + walk_stackframe(&frame, report_trace, &depth); + return; + } + + while (depth-- && tail && !((unsigned long) tail & 3)) + tail = user_backtrace(tail); +} + +int __init oprofile_arch_init(struct oprofile_operations *ops) +{ + int cpu, ret = 0; + + perf_num_counters = armpmu_get_max_events(); + + counter_config = kcalloc(perf_num_counters, + sizeof(struct op_counter_config), GFP_KERNEL); - op_arm_model = spec; - init_driverfs(); - ops->create_files = op_arm_create_files; - ops->setup = op_arm_setup; - ops->shutdown = op_arm_stop; - ops->start = op_arm_start; - ops->stop = op_arm_stop; - ops->cpu_type = op_arm_model->name; - printk(KERN_INFO "oprofile: using %s\n", spec->name); + if (!counter_config) { + pr_info("oprofile: failed to allocate %d " + "counters\n", perf_num_counters); + return -ENOMEM; } + for_each_possible_cpu(cpu) { + perf_events[cpu] = kcalloc(perf_num_counters, + sizeof(struct perf_event *), GFP_KERNEL); + if (!perf_events[cpu]) { + pr_info("oprofile: failed to allocate %d perf events " + "for cpu %d\n", perf_num_counters, cpu); + while (--cpu >= 0) + kfree(perf_events[cpu]); + return -ENOMEM; + } + } + + init_driverfs(); + ops->backtrace = arm_backtrace; + ops->create_files = op_arm_create_files; + ops->setup = op_arm_setup; + ops->start = op_arm_start; + ops->stop = op_arm_stop; + ops->shutdown = op_arm_stop; + ops->cpu_type = op_name_from_perf_id(armpmu_get_pmu_id()); + + if (!ops->cpu_type) + ret = -ENODEV; + else + pr_info("oprofile: using %s\n", ops->cpu_type); + return ret; } void oprofile_arch_exit(void) { - if (op_arm_model) { + int cpu, id; + struct perf_event *event; + + if (*perf_events) { exit_driverfs(); - op_arm_model = NULL; + for_each_possible_cpu(cpu) { + for (id = 0; id < perf_num_counters; ++id) { + event = perf_events[cpu][id]; + if (event != NULL) + perf_event_release_kernel(event); + } + kfree(perf_events[cpu]); + } } - kfree(counter_config); + + if (counter_config) + kfree(counter_config); +} +#else +int __init oprofile_arch_init(struct oprofile_operations *ops) +{ + pr_info("oprofile: hardware counters not available\n"); + return -ENODEV; } +void oprofile_arch_exit(void) {} +#endif /* CONFIG_HW_PERF_EVENTS */ -- cgit v0.10.2 From fe166148f699cc7865ca07b6754872cfb5ebc312 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 30 Apr 2010 11:37:51 +0100 Subject: ARM: 6073/1: oprofile: remove old files and update KConfig Enable hardware perf-events if CPU_HAS_PMU and select HAVE_OPROFILE if HAVE_PERF_EVENTS. If no hardware support is present, OProfile will fall back to timer mode. This patch also removes the old OProfile drivers in favour of the code implemented by perf. Signed-off-by: Will Deacon Signed-off-by: Russell King diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index daaa4b2..f7c2a88 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -13,7 +13,7 @@ config ARM select RTC_LIB select SYS_SUPPORTS_APM_EMULATION select GENERIC_ATOMIC64 if (!CPU_32v6K) - select HAVE_OPROFILE + select HAVE_OPROFILE if (HAVE_PERF_EVENTS) select HAVE_ARCH_KGDB select HAVE_KPROBES if (!XIP_KERNEL) select HAVE_KRETPROBES if (HAVE_KPROBES) @@ -181,28 +181,6 @@ config ARM_L1_CACHE_SHIFT_6 help Setting ARM L1 cache line size to 64 Bytes. -if OPROFILE - -config OPROFILE_ARMV6 - def_bool y - depends on CPU_V6 && !SMP - select OPROFILE_ARM11_CORE - -config OPROFILE_MPCORE - def_bool y - depends on CPU_V6 && SMP - select OPROFILE_ARM11_CORE - -config OPROFILE_ARM11_CORE - bool - -config OPROFILE_ARMV7 - def_bool y - depends on CPU_V7 && !SMP - bool - -endif - config VECTORS_BASE hex default 0xffff0000 if MMU || CPU_HIGH_VECTOR @@ -1334,7 +1312,7 @@ config HIGHPTE config HW_PERF_EVENTS bool "Enable hardware performance counter support for perf events" - depends on PERF_EVENTS && CPU_HAS_PMU && (CPU_V6 || CPU_V7) + depends on PERF_EVENTS && CPU_HAS_PMU default y help Enable hardware performance counter support for perf events. If diff --git a/arch/arm/oprofile/Makefile b/arch/arm/oprofile/Makefile index 88e31f5..e666eaf 100644 --- a/arch/arm/oprofile/Makefile +++ b/arch/arm/oprofile/Makefile @@ -6,9 +6,4 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \ oprofilefs.o oprofile_stats.o \ timer_int.o ) -oprofile-y := $(DRIVER_OBJS) common.o backtrace.o -oprofile-$(CONFIG_CPU_XSCALE) += op_model_xscale.o -oprofile-$(CONFIG_OPROFILE_ARM11_CORE) += op_model_arm11_core.o -oprofile-$(CONFIG_OPROFILE_ARMV6) += op_model_v6.o -oprofile-$(CONFIG_OPROFILE_MPCORE) += op_model_mpcore.o -oprofile-$(CONFIG_OPROFILE_ARMV7) += op_model_v7.o +oprofile-y := $(DRIVER_OBJS) common.o diff --git a/arch/arm/oprofile/backtrace.c b/arch/arm/oprofile/backtrace.c deleted file mode 100644 index d805a52..0000000 --- a/arch/arm/oprofile/backtrace.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Arm specific backtracing code for oprofile - * - * Copyright 2005 Openedhand Ltd. - * - * Author: Richard Purdie - * - * Based on i386 oprofile backtrace code by John Levon, David Smith - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include - -static int report_trace(struct stackframe *frame, void *d) -{ - unsigned int *depth = d; - - if (*depth) { - oprofile_add_trace(frame->pc); - (*depth)--; - } - - return *depth == 0; -} - -/* - * The registers we're interested in are at the end of the variable - * length saved register structure. The fp points at the end of this - * structure so the address of this struct is: - * (struct frame_tail *)(xxx->fp)-1 - */ -struct frame_tail { - struct frame_tail *fp; - unsigned long sp; - unsigned long lr; -} __attribute__((packed)); - -static struct frame_tail* user_backtrace(struct frame_tail *tail) -{ - struct frame_tail buftail[2]; - - /* Also check accessibility of one struct frame_tail beyond */ - if (!access_ok(VERIFY_READ, tail, sizeof(buftail))) - return NULL; - if (__copy_from_user_inatomic(buftail, tail, sizeof(buftail))) - return NULL; - - oprofile_add_trace(buftail[0].lr); - - /* frame pointers should strictly progress back up the stack - * (towards higher addresses) */ - if (tail >= buftail[0].fp) - return NULL; - - return buftail[0].fp-1; -} - -void arm_backtrace(struct pt_regs * const regs, unsigned int depth) -{ - struct frame_tail *tail = ((struct frame_tail *) regs->ARM_fp) - 1; - - if (!user_mode(regs)) { - struct stackframe frame; - frame.fp = regs->ARM_fp; - frame.sp = regs->ARM_sp; - frame.lr = regs->ARM_lr; - frame.pc = regs->ARM_pc; - walk_stackframe(&frame, report_trace, &depth); - return; - } - - while (depth-- && tail && !((unsigned long) tail & 3)) - tail = user_backtrace(tail); -} diff --git a/arch/arm/oprofile/op_arm_model.h b/arch/arm/oprofile/op_arm_model.h deleted file mode 100644 index 8c4e4f6..0000000 --- a/arch/arm/oprofile/op_arm_model.h +++ /dev/null @@ -1,35 +0,0 @@ -/** - * @file op_arm_model.h - * interface to ARM machine specific operations - * - * @remark Copyright 2004 Oprofile Authors - * @remark Read the file COPYING - * - * @author Zwane Mwaikambo - */ - -#ifndef OP_ARM_MODEL_H -#define OP_ARM_MODEL_H - -struct op_arm_model_spec { - int (*init)(void); - unsigned int num_counters; - int (*setup_ctrs)(void); - int (*start)(void); - void (*stop)(void); - char *name; -}; - -#ifdef CONFIG_CPU_XSCALE -extern struct op_arm_model_spec op_xscale_spec; -#endif - -extern struct op_arm_model_spec op_armv6_spec; -extern struct op_arm_model_spec op_mpcore_spec; -extern struct op_arm_model_spec op_armv7_spec; - -extern void arm_backtrace(struct pt_regs * const regs, unsigned int depth); - -extern int __init op_arm_init(struct oprofile_operations *ops, struct op_arm_model_spec *spec); -extern void op_arm_exit(void); -#endif /* OP_ARM_MODEL_H */ diff --git a/arch/arm/oprofile/op_counter.h b/arch/arm/oprofile/op_counter.h deleted file mode 100644 index ca942a6..0000000 --- a/arch/arm/oprofile/op_counter.h +++ /dev/null @@ -1,27 +0,0 @@ -/** - * @file op_counter.h - * - * @remark Copyright 2004 Oprofile Authors - * @remark Read the file COPYING - * - * @author Zwane Mwaikambo - */ - -#ifndef OP_COUNTER_H -#define OP_COUNTER_H - -/* Per performance monitor configuration as set via - * oprofilefs. - */ -struct op_counter_config { - unsigned long count; - unsigned long enabled; - unsigned long event; - unsigned long unit_mask; - unsigned long kernel; - unsigned long user; -}; - -extern struct op_counter_config *counter_config; - -#endif /* OP_COUNTER_H */ diff --git a/arch/arm/oprofile/op_model_arm11_core.c b/arch/arm/oprofile/op_model_arm11_core.c deleted file mode 100644 index ef3e265..0000000 --- a/arch/arm/oprofile/op_model_arm11_core.c +++ /dev/null @@ -1,162 +0,0 @@ -/** - * @file op_model_arm11_core.c - * ARM11 Event Monitor Driver - * @remark Copyright 2004 ARM SMP Development Team - */ -#include -#include -#include -#include -#include -#include - -#include "op_counter.h" -#include "op_arm_model.h" -#include "op_model_arm11_core.h" - -/* - * ARM11 PMU support - */ -static inline void arm11_write_pmnc(u32 val) -{ - /* upper 4bits and 7, 11 are write-as-0 */ - val &= 0x0ffff77f; - asm volatile("mcr p15, 0, %0, c15, c12, 0" : : "r" (val)); -} - -static inline u32 arm11_read_pmnc(void) -{ - u32 val; - asm volatile("mrc p15, 0, %0, c15, c12, 0" : "=r" (val)); - return val; -} - -static void arm11_reset_counter(unsigned int cnt) -{ - u32 val = -(u32)counter_config[CPU_COUNTER(smp_processor_id(), cnt)].count; - switch (cnt) { - case CCNT: - asm volatile("mcr p15, 0, %0, c15, c12, 1" : : "r" (val)); - break; - - case PMN0: - asm volatile("mcr p15, 0, %0, c15, c12, 2" : : "r" (val)); - break; - - case PMN1: - asm volatile("mcr p15, 0, %0, c15, c12, 3" : : "r" (val)); - break; - } -} - -int arm11_setup_pmu(void) -{ - unsigned int cnt; - u32 pmnc; - - if (arm11_read_pmnc() & PMCR_E) { - printk(KERN_ERR "oprofile: CPU%u PMU still enabled when setup new event counter.\n", smp_processor_id()); - return -EBUSY; - } - - /* initialize PMNC, reset overflow, D bit, C bit and P bit. */ - arm11_write_pmnc(PMCR_OFL_PMN0 | PMCR_OFL_PMN1 | PMCR_OFL_CCNT | - PMCR_C | PMCR_P); - - for (pmnc = 0, cnt = PMN0; cnt <= CCNT; cnt++) { - unsigned long event; - - if (!counter_config[CPU_COUNTER(smp_processor_id(), cnt)].enabled) - continue; - - event = counter_config[CPU_COUNTER(smp_processor_id(), cnt)].event & 255; - - /* - * Set event (if destined for PMNx counters) - */ - if (cnt == PMN0) { - pmnc |= event << 20; - } else if (cnt == PMN1) { - pmnc |= event << 12; - } - - /* - * We don't need to set the event if it's a cycle count - * Enable interrupt for this counter - */ - pmnc |= PMCR_IEN_PMN0 << cnt; - arm11_reset_counter(cnt); - } - arm11_write_pmnc(pmnc); - - return 0; -} - -int arm11_start_pmu(void) -{ - arm11_write_pmnc(arm11_read_pmnc() | PMCR_E); - return 0; -} - -int arm11_stop_pmu(void) -{ - unsigned int cnt; - - arm11_write_pmnc(arm11_read_pmnc() & ~PMCR_E); - - for (cnt = PMN0; cnt <= CCNT; cnt++) - arm11_reset_counter(cnt); - - return 0; -} - -/* - * CPU counters' IRQ handler (one IRQ per CPU) - */ -static irqreturn_t arm11_pmu_interrupt(int irq, void *arg) -{ - struct pt_regs *regs = get_irq_regs(); - unsigned int cnt; - u32 pmnc; - - pmnc = arm11_read_pmnc(); - - for (cnt = PMN0; cnt <= CCNT; cnt++) { - if ((pmnc & (PMCR_OFL_PMN0 << cnt)) && (pmnc & (PMCR_IEN_PMN0 << cnt))) { - arm11_reset_counter(cnt); - oprofile_add_sample(regs, CPU_COUNTER(smp_processor_id(), cnt)); - } - } - /* Clear counter flag(s) */ - arm11_write_pmnc(pmnc); - return IRQ_HANDLED; -} - -int arm11_request_interrupts(const int *irqs, int nr) -{ - unsigned int i; - int ret = 0; - - for(i = 0; i < nr; i++) { - ret = request_irq(irqs[i], arm11_pmu_interrupt, IRQF_DISABLED, "CP15 PMU", NULL); - if (ret != 0) { - printk(KERN_ERR "oprofile: unable to request IRQ%u for MPCORE-EM\n", - irqs[i]); - break; - } - } - - if (i != nr) - while (i-- != 0) - free_irq(irqs[i], NULL); - - return ret; -} - -void arm11_release_interrupts(const int *irqs, int nr) -{ - unsigned int i; - - for (i = 0; i < nr; i++) - free_irq(irqs[i], NULL); -} diff --git a/arch/arm/oprofile/op_model_arm11_core.h b/arch/arm/oprofile/op_model_arm11_core.h deleted file mode 100644 index 1902b99..0000000 --- a/arch/arm/oprofile/op_model_arm11_core.h +++ /dev/null @@ -1,45 +0,0 @@ -/** - * @file op_model_arm11_core.h - * ARM11 Event Monitor Driver - * @remark Copyright 2004 ARM SMP Development Team - * @remark Copyright 2000-2004 Deepak Saxena - * @remark Copyright 2000-2004 MontaVista Software Inc - * @remark Copyright 2004 Dave Jiang - * @remark Copyright 2004 Intel Corporation - * @remark Copyright 2004 Zwane Mwaikambo - * @remark Copyright 2004 Oprofile Authors - * - * @remark Read the file COPYING - * - * @author Zwane Mwaikambo - */ -#ifndef OP_MODEL_ARM11_CORE_H -#define OP_MODEL_ARM11_CORE_H - -/* - * Per-CPU PMCR - */ -#define PMCR_E (1 << 0) /* Enable */ -#define PMCR_P (1 << 1) /* Count reset */ -#define PMCR_C (1 << 2) /* Cycle counter reset */ -#define PMCR_D (1 << 3) /* Cycle counter counts every 64th cpu cycle */ -#define PMCR_IEN_PMN0 (1 << 4) /* Interrupt enable count reg 0 */ -#define PMCR_IEN_PMN1 (1 << 5) /* Interrupt enable count reg 1 */ -#define PMCR_IEN_CCNT (1 << 6) /* Interrupt enable cycle counter */ -#define PMCR_OFL_PMN0 (1 << 8) /* Count reg 0 overflow */ -#define PMCR_OFL_PMN1 (1 << 9) /* Count reg 1 overflow */ -#define PMCR_OFL_CCNT (1 << 10) /* Cycle counter overflow */ - -#define PMN0 0 -#define PMN1 1 -#define CCNT 2 - -#define CPU_COUNTER(cpu, counter) ((cpu) * 3 + (counter)) - -int arm11_setup_pmu(void); -int arm11_start_pmu(void); -int arm11_stop_pmu(void); -int arm11_request_interrupts(const int *, int); -void arm11_release_interrupts(const int *, int); - -#endif diff --git a/arch/arm/oprofile/op_model_mpcore.c b/arch/arm/oprofile/op_model_mpcore.c deleted file mode 100644 index f73ce87..0000000 --- a/arch/arm/oprofile/op_model_mpcore.c +++ /dev/null @@ -1,306 +0,0 @@ -/** - * @file op_model_mpcore.c - * MPCORE Event Monitor Driver - * @remark Copyright 2004 ARM SMP Development Team - * @remark Copyright 2000-2004 Deepak Saxena - * @remark Copyright 2000-2004 MontaVista Software Inc - * @remark Copyright 2004 Dave Jiang - * @remark Copyright 2004 Intel Corporation - * @remark Copyright 2004 Zwane Mwaikambo - * @remark Copyright 2004 Oprofile Authors - * - * @remark Read the file COPYING - * - * @author Zwane Mwaikambo - * - * Counters: - * 0: PMN0 on CPU0, per-cpu configurable event counter - * 1: PMN1 on CPU0, per-cpu configurable event counter - * 2: CCNT on CPU0 - * 3: PMN0 on CPU1 - * 4: PMN1 on CPU1 - * 5: CCNT on CPU1 - * 6: PMN0 on CPU1 - * 7: PMN1 on CPU1 - * 8: CCNT on CPU1 - * 9: PMN0 on CPU1 - * 10: PMN1 on CPU1 - * 11: CCNT on CPU1 - * 12-19: configurable SCU event counters - */ - -/* #define DEBUG */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "op_counter.h" -#include "op_arm_model.h" -#include "op_model_arm11_core.h" -#include "op_model_mpcore.h" - -/* - * MPCore SCU event monitor support - */ -#define SCU_EVENTMONITORS_VA_BASE __io_address(REALVIEW_EB11MP_SCU_BASE + 0x10) - -/* - * Bitmask of used SCU counters - */ -static unsigned int scu_em_used; -static const struct pmu_irqs *pmu_irqs; - -/* - * 2 helper fns take a counter number from 0-7 (not the userspace-visible counter number) - */ -static inline void scu_reset_counter(struct eventmonitor __iomem *emc, unsigned int n) -{ - writel(-(u32)counter_config[SCU_COUNTER(n)].count, &emc->MC[n]); -} - -static inline void scu_set_event(struct eventmonitor __iomem *emc, unsigned int n, u32 event) -{ - event &= 0xff; - writeb(event, &emc->MCEB[n]); -} - -/* - * SCU counters' IRQ handler (one IRQ per counter => 2 IRQs per CPU) - */ -static irqreturn_t scu_em_interrupt(int irq, void *arg) -{ - struct eventmonitor __iomem *emc = SCU_EVENTMONITORS_VA_BASE; - unsigned int cnt; - - cnt = irq - IRQ_EB11MP_PMU_SCU0; - oprofile_add_sample(get_irq_regs(), SCU_COUNTER(cnt)); - scu_reset_counter(emc, cnt); - - /* Clear overflow flag for this counter */ - writel(1 << (cnt + 16), &emc->PMCR); - - return IRQ_HANDLED; -} - -/* Configure just the SCU counters that the user has requested */ -static void scu_setup(void) -{ - struct eventmonitor __iomem *emc = SCU_EVENTMONITORS_VA_BASE; - unsigned int i; - - scu_em_used = 0; - - for (i = 0; i < NUM_SCU_COUNTERS; i++) { - if (counter_config[SCU_COUNTER(i)].enabled && - counter_config[SCU_COUNTER(i)].event) { - scu_set_event(emc, i, 0); /* disable counter for now */ - scu_em_used |= 1 << i; - } - } -} - -static int scu_start(void) -{ - struct eventmonitor __iomem *emc = SCU_EVENTMONITORS_VA_BASE; - unsigned int temp, i; - unsigned long event; - int ret = 0; - - /* - * request the SCU counter interrupts that we need - */ - for (i = 0; i < NUM_SCU_COUNTERS; i++) { - if (scu_em_used & (1 << i)) { - ret = request_irq(IRQ_EB11MP_PMU_SCU0 + i, scu_em_interrupt, IRQF_DISABLED, "SCU PMU", NULL); - if (ret) { - printk(KERN_ERR "oprofile: unable to request IRQ%u for SCU Event Monitor\n", - IRQ_EB11MP_PMU_SCU0 + i); - goto err_free_scu; - } - } - } - - /* - * clear overflow and enable interrupt for all used counters - */ - temp = readl(&emc->PMCR); - for (i = 0; i < NUM_SCU_COUNTERS; i++) { - if (scu_em_used & (1 << i)) { - scu_reset_counter(emc, i); - event = counter_config[SCU_COUNTER(i)].event; - scu_set_event(emc, i, event); - - /* clear overflow/interrupt */ - temp |= 1 << (i + 16); - /* enable interrupt*/ - temp |= 1 << (i + 8); - } - } - - /* Enable all 8 counters */ - temp |= PMCR_E; - writel(temp, &emc->PMCR); - - return 0; - - err_free_scu: - while (i--) - free_irq(IRQ_EB11MP_PMU_SCU0 + i, NULL); - return ret; -} - -static void scu_stop(void) -{ - struct eventmonitor __iomem *emc = SCU_EVENTMONITORS_VA_BASE; - unsigned int temp, i; - - /* Disable counter interrupts */ - /* Don't disable all 8 counters (with the E bit) as they may be in use */ - temp = readl(&emc->PMCR); - for (i = 0; i < NUM_SCU_COUNTERS; i++) { - if (scu_em_used & (1 << i)) - temp &= ~(1 << (i + 8)); - } - writel(temp, &emc->PMCR); - - /* Free counter interrupts and reset counters */ - for (i = 0; i < NUM_SCU_COUNTERS; i++) { - if (scu_em_used & (1 << i)) { - scu_reset_counter(emc, i); - free_irq(IRQ_EB11MP_PMU_SCU0 + i, NULL); - } - } -} - -struct em_function_data { - int (*fn)(void); - int ret; -}; - -static void em_func(void *data) -{ - struct em_function_data *d = data; - int ret = d->fn(); - if (ret) - d->ret = ret; -} - -static int em_call_function(int (*fn)(void)) -{ - struct em_function_data data; - - data.fn = fn; - data.ret = 0; - - preempt_disable(); - smp_call_function(em_func, &data, 1); - em_func(&data); - preempt_enable(); - - return data.ret; -} - -/* - * Glue to stick the individual ARM11 PMUs and the SCU - * into the oprofile framework. - */ -static int em_setup_ctrs(void) -{ - int ret; - - /* Configure CPU counters by cross-calling to the other CPUs */ - ret = em_call_function(arm11_setup_pmu); - if (ret == 0) - scu_setup(); - - return 0; -} - -static int em_start(void) -{ - int ret; - - pmu_irqs = reserve_pmu(); - if (IS_ERR(pmu_irqs)) { - ret = PTR_ERR(pmu_irqs); - goto out; - } - - ret = arm11_request_interrupts(pmu_irqs->irqs, pmu_irqs->num_irqs); - if (ret == 0) { - em_call_function(arm11_start_pmu); - - ret = scu_start(); - if (ret) { - arm11_release_interrupts(pmu_irqs->irqs, - pmu_irqs->num_irqs); - } else { - release_pmu(pmu_irqs); - pmu_irqs = NULL; - } - } - -out: - return ret; -} - -static void em_stop(void) -{ - em_call_function(arm11_stop_pmu); - arm11_release_interrupts(pmu_irqs->irqs, pmu_irqs->num_irqs); - scu_stop(); - release_pmu(pmu_irqs); -} - -/* - * Why isn't there a function to route an IRQ to a specific CPU in - * genirq? - */ -static void em_route_irq(int irq, unsigned int cpu) -{ - struct irq_desc *desc = irq_desc + irq; - const struct cpumask *mask = cpumask_of(cpu); - - spin_lock_irq(&desc->lock); - cpumask_copy(desc->affinity, mask); - desc->chip->set_affinity(irq, mask); - spin_unlock_irq(&desc->lock); -} - -static int em_setup(void) -{ - /* - * Send SCU PMU interrupts to the "owner" CPU. - */ - em_route_irq(IRQ_EB11MP_PMU_SCU0, 0); - em_route_irq(IRQ_EB11MP_PMU_SCU1, 0); - em_route_irq(IRQ_EB11MP_PMU_SCU2, 1); - em_route_irq(IRQ_EB11MP_PMU_SCU3, 1); - em_route_irq(IRQ_EB11MP_PMU_SCU4, 2); - em_route_irq(IRQ_EB11MP_PMU_SCU5, 2); - em_route_irq(IRQ_EB11MP_PMU_SCU6, 3); - em_route_irq(IRQ_EB11MP_PMU_SCU7, 3); - - return init_pmu(); -} - -struct op_arm_model_spec op_mpcore_spec = { - .init = em_setup, - .num_counters = MPCORE_NUM_COUNTERS, - .setup_ctrs = em_setup_ctrs, - .start = em_start, - .stop = em_stop, - .name = "arm/mpcore", -}; diff --git a/arch/arm/oprofile/op_model_mpcore.h b/arch/arm/oprofile/op_model_mpcore.h deleted file mode 100644 index 73d8110..0000000 --- a/arch/arm/oprofile/op_model_mpcore.h +++ /dev/null @@ -1,61 +0,0 @@ -/** - * @file op_model_mpcore.c - * MPCORE Event Monitor Driver - * @remark Copyright 2004 ARM SMP Development Team - * @remark Copyright 2000-2004 Deepak Saxena - * @remark Copyright 2000-2004 MontaVista Software Inc - * @remark Copyright 2004 Dave Jiang - * @remark Copyright 2004 Intel Corporation - * @remark Copyright 2004 Zwane Mwaikambo - * @remark Copyright 2004 Oprofile Authors - * - * @remark Read the file COPYING - * - * @author Zwane Mwaikambo - */ -#ifndef OP_MODEL_MPCORE_H -#define OP_MODEL_MPCORE_H - -struct eventmonitor { - unsigned long PMCR; - unsigned char MCEB[8]; - unsigned long MC[8]; -}; - -/* - * List of userspace counter numbers: note that the structure is important. - * The code relies on CPUn's counters being CPU0's counters + 3n - * and on CPU0's counters starting at 0 - */ - -#define COUNTER_CPU0_PMN0 0 -#define COUNTER_CPU0_PMN1 1 -#define COUNTER_CPU0_CCNT 2 - -#define COUNTER_CPU1_PMN0 3 -#define COUNTER_CPU1_PMN1 4 -#define COUNTER_CPU1_CCNT 5 - -#define COUNTER_CPU2_PMN0 6 -#define COUNTER_CPU2_PMN1 7 -#define COUNTER_CPU2_CCNT 8 - -#define COUNTER_CPU3_PMN0 9 -#define COUNTER_CPU3_PMN1 10 -#define COUNTER_CPU3_CCNT 11 - -#define COUNTER_SCU_MN0 12 -#define COUNTER_SCU_MN1 13 -#define COUNTER_SCU_MN2 14 -#define COUNTER_SCU_MN3 15 -#define COUNTER_SCU_MN4 16 -#define COUNTER_SCU_MN5 17 -#define COUNTER_SCU_MN6 18 -#define COUNTER_SCU_MN7 19 -#define NUM_SCU_COUNTERS 8 - -#define SCU_COUNTER(number) ((number) + COUNTER_SCU_MN0) - -#define MPCORE_NUM_COUNTERS SCU_COUNTER(NUM_SCU_COUNTERS) - -#endif diff --git a/arch/arm/oprofile/op_model_v6.c b/arch/arm/oprofile/op_model_v6.c deleted file mode 100644 index a22357a..0000000 --- a/arch/arm/oprofile/op_model_v6.c +++ /dev/null @@ -1,78 +0,0 @@ -/** - * @file op_model_v6.c - * ARM11 Performance Monitor Driver - * - * Based on op_model_xscale.c - * - * @remark Copyright 2000-2004 Deepak Saxena - * @remark Copyright 2000-2004 MontaVista Software Inc - * @remark Copyright 2004 Dave Jiang - * @remark Copyright 2004 Intel Corporation - * @remark Copyright 2004 Zwane Mwaikambo - * @remark Copyright 2004 OProfile Authors - * - * @remark Read the file COPYING - * - * @author Tony Lindgren - */ - -/* #define DEBUG */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "op_counter.h" -#include "op_arm_model.h" -#include "op_model_arm11_core.h" - -static const struct pmu_irqs *pmu_irqs; - -static void armv6_pmu_stop(void) -{ - arm11_stop_pmu(); - arm11_release_interrupts(pmu_irqs->irqs, pmu_irqs->num_irqs); - release_pmu(pmu_irqs); - pmu_irqs = NULL; -} - -static int armv6_pmu_start(void) -{ - int ret; - - pmu_irqs = reserve_pmu(); - if (IS_ERR(pmu_irqs)) { - ret = PTR_ERR(pmu_irqs); - goto out; - } - - ret = arm11_request_interrupts(pmu_irqs->irqs, pmu_irqs->num_irqs); - if (ret >= 0) { - ret = arm11_start_pmu(); - } else { - release_pmu(pmu_irqs); - pmu_irqs = NULL; - } - -out: - return ret; -} - -static int armv6_detect_pmu(void) -{ - return 0; -} - -struct op_arm_model_spec op_armv6_spec = { - .init = armv6_detect_pmu, - .num_counters = 3, - .setup_ctrs = arm11_setup_pmu, - .start = armv6_pmu_start, - .stop = armv6_pmu_stop, - .name = "arm/armv6", -}; diff --git a/arch/arm/oprofile/op_model_v7.c b/arch/arm/oprofile/op_model_v7.c deleted file mode 100644 index 8642d08..0000000 --- a/arch/arm/oprofile/op_model_v7.c +++ /dev/null @@ -1,415 +0,0 @@ -/** - * op_model_v7.c - * ARM V7 (Cortex A8) Event Monitor Driver - * - * Copyright 2008 Jean Pihet - * Copyright 2004 ARM SMP Development Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "op_counter.h" -#include "op_arm_model.h" -#include "op_model_v7.h" - -/* #define DEBUG */ - - -/* - * ARM V7 PMNC support - */ - -static u32 cnt_en[CNTMAX]; - -static inline void armv7_pmnc_write(u32 val) -{ - val &= PMNC_MASK; - asm volatile("mcr p15, 0, %0, c9, c12, 0" : : "r" (val)); -} - -static inline u32 armv7_pmnc_read(void) -{ - u32 val; - - asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (val)); - return val; -} - -static inline u32 armv7_pmnc_enable_counter(unsigned int cnt) -{ - u32 val; - - if (cnt >= CNTMAX) { - printk(KERN_ERR "oprofile: CPU%u enabling wrong PMNC counter" - " %d\n", smp_processor_id(), cnt); - return -1; - } - - if (cnt == CCNT) - val = CNTENS_C; - else - val = (1 << (cnt - CNT0)); - - val &= CNTENS_MASK; - asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (val)); - - return cnt; -} - -static inline u32 armv7_pmnc_disable_counter(unsigned int cnt) -{ - u32 val; - - if (cnt >= CNTMAX) { - printk(KERN_ERR "oprofile: CPU%u disabling wrong PMNC counter" - " %d\n", smp_processor_id(), cnt); - return -1; - } - - if (cnt == CCNT) - val = CNTENC_C; - else - val = (1 << (cnt - CNT0)); - - val &= CNTENC_MASK; - asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (val)); - - return cnt; -} - -static inline u32 armv7_pmnc_enable_intens(unsigned int cnt) -{ - u32 val; - - if (cnt >= CNTMAX) { - printk(KERN_ERR "oprofile: CPU%u enabling wrong PMNC counter" - " interrupt enable %d\n", smp_processor_id(), cnt); - return -1; - } - - if (cnt == CCNT) - val = INTENS_C; - else - val = (1 << (cnt - CNT0)); - - val &= INTENS_MASK; - asm volatile("mcr p15, 0, %0, c9, c14, 1" : : "r" (val)); - - return cnt; -} - -static inline u32 armv7_pmnc_getreset_flags(void) -{ - u32 val; - - /* Read */ - asm volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (val)); - - /* Write to clear flags */ - val &= FLAG_MASK; - asm volatile("mcr p15, 0, %0, c9, c12, 3" : : "r" (val)); - - return val; -} - -static inline int armv7_pmnc_select_counter(unsigned int cnt) -{ - u32 val; - - if ((cnt == CCNT) || (cnt >= CNTMAX)) { - printk(KERN_ERR "oprofile: CPU%u selecting wrong PMNC counteri" - " %d\n", smp_processor_id(), cnt); - return -1; - } - - val = (cnt - CNT0) & SELECT_MASK; - asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (val)); - - return cnt; -} - -static inline void armv7_pmnc_write_evtsel(unsigned int cnt, u32 val) -{ - if (armv7_pmnc_select_counter(cnt) == cnt) { - val &= EVTSEL_MASK; - asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (val)); - } -} - -static void armv7_pmnc_reset_counter(unsigned int cnt) -{ - u32 cpu_cnt = CPU_COUNTER(smp_processor_id(), cnt); - u32 val = -(u32)counter_config[cpu_cnt].count; - - switch (cnt) { - case CCNT: - armv7_pmnc_disable_counter(cnt); - - asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (val)); - - if (cnt_en[cnt] != 0) - armv7_pmnc_enable_counter(cnt); - - break; - - case CNT0: - case CNT1: - case CNT2: - case CNT3: - armv7_pmnc_disable_counter(cnt); - - if (armv7_pmnc_select_counter(cnt) == cnt) - asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" (val)); - - if (cnt_en[cnt] != 0) - armv7_pmnc_enable_counter(cnt); - - break; - - default: - printk(KERN_ERR "oprofile: CPU%u resetting wrong PMNC counter" - " %d\n", smp_processor_id(), cnt); - break; - } -} - -int armv7_setup_pmnc(void) -{ - unsigned int cnt; - - if (armv7_pmnc_read() & PMNC_E) { - printk(KERN_ERR "oprofile: CPU%u PMNC still enabled when setup" - " new event counter.\n", smp_processor_id()); - return -EBUSY; - } - - /* Initialize & Reset PMNC: C bit and P bit */ - armv7_pmnc_write(PMNC_P | PMNC_C); - - - for (cnt = CCNT; cnt < CNTMAX; cnt++) { - unsigned long event; - u32 cpu_cnt = CPU_COUNTER(smp_processor_id(), cnt); - - /* - * Disable counter - */ - armv7_pmnc_disable_counter(cnt); - cnt_en[cnt] = 0; - - if (!counter_config[cpu_cnt].enabled) - continue; - - event = counter_config[cpu_cnt].event & 255; - - /* - * Set event (if destined for PMNx counters) - * We don't need to set the event if it's a cycle count - */ - if (cnt != CCNT) - armv7_pmnc_write_evtsel(cnt, event); - - /* - * Enable interrupt for this counter - */ - armv7_pmnc_enable_intens(cnt); - - /* - * Reset counter - */ - armv7_pmnc_reset_counter(cnt); - - /* - * Enable counter - */ - armv7_pmnc_enable_counter(cnt); - cnt_en[cnt] = 1; - } - - return 0; -} - -static inline void armv7_start_pmnc(void) -{ - armv7_pmnc_write(armv7_pmnc_read() | PMNC_E); -} - -static inline void armv7_stop_pmnc(void) -{ - armv7_pmnc_write(armv7_pmnc_read() & ~PMNC_E); -} - -/* - * CPU counters' IRQ handler (one IRQ per CPU) - */ -static irqreturn_t armv7_pmnc_interrupt(int irq, void *arg) -{ - struct pt_regs *regs = get_irq_regs(); - unsigned int cnt; - u32 flags; - - - /* - * Stop IRQ generation - */ - armv7_stop_pmnc(); - - /* - * Get and reset overflow status flags - */ - flags = armv7_pmnc_getreset_flags(); - - /* - * Cycle counter - */ - if (flags & FLAG_C) { - u32 cpu_cnt = CPU_COUNTER(smp_processor_id(), CCNT); - armv7_pmnc_reset_counter(CCNT); - oprofile_add_sample(regs, cpu_cnt); - } - - /* - * PMNC counters 0:3 - */ - for (cnt = CNT0; cnt < CNTMAX; cnt++) { - if (flags & (1 << (cnt - CNT0))) { - u32 cpu_cnt = CPU_COUNTER(smp_processor_id(), cnt); - armv7_pmnc_reset_counter(cnt); - oprofile_add_sample(regs, cpu_cnt); - } - } - - /* - * Allow IRQ generation - */ - armv7_start_pmnc(); - - return IRQ_HANDLED; -} - -int armv7_request_interrupts(const int *irqs, int nr) -{ - unsigned int i; - int ret = 0; - - for (i = 0; i < nr; i++) { - ret = request_irq(irqs[i], armv7_pmnc_interrupt, - IRQF_DISABLED, "CP15 PMNC", NULL); - if (ret != 0) { - printk(KERN_ERR "oprofile: unable to request IRQ%u" - " for ARMv7\n", - irqs[i]); - break; - } - } - - if (i != nr) - while (i-- != 0) - free_irq(irqs[i], NULL); - - return ret; -} - -void armv7_release_interrupts(const int *irqs, int nr) -{ - unsigned int i; - - for (i = 0; i < nr; i++) - free_irq(irqs[i], NULL); -} - -#ifdef DEBUG -static void armv7_pmnc_dump_regs(void) -{ - u32 val; - unsigned int cnt; - - printk(KERN_INFO "PMNC registers dump:\n"); - - asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (val)); - printk(KERN_INFO "PMNC =0x%08x\n", val); - - asm volatile("mrc p15, 0, %0, c9, c12, 1" : "=r" (val)); - printk(KERN_INFO "CNTENS=0x%08x\n", val); - - asm volatile("mrc p15, 0, %0, c9, c14, 1" : "=r" (val)); - printk(KERN_INFO "INTENS=0x%08x\n", val); - - asm volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (val)); - printk(KERN_INFO "FLAGS =0x%08x\n", val); - - asm volatile("mrc p15, 0, %0, c9, c12, 5" : "=r" (val)); - printk(KERN_INFO "SELECT=0x%08x\n", val); - - asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val)); - printk(KERN_INFO "CCNT =0x%08x\n", val); - - for (cnt = CNT0; cnt < CNTMAX; cnt++) { - armv7_pmnc_select_counter(cnt); - asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (val)); - printk(KERN_INFO "CNT[%d] count =0x%08x\n", cnt-CNT0, val); - asm volatile("mrc p15, 0, %0, c9, c13, 1" : "=r" (val)); - printk(KERN_INFO "CNT[%d] evtsel=0x%08x\n", cnt-CNT0, val); - } -} -#endif - -static const struct pmu_irqs *pmu_irqs; - -static void armv7_pmnc_stop(void) -{ -#ifdef DEBUG - armv7_pmnc_dump_regs(); -#endif - armv7_stop_pmnc(); - armv7_release_interrupts(pmu_irqs->irqs, pmu_irqs->num_irqs); - release_pmu(pmu_irqs); - pmu_irqs = NULL; -} - -static int armv7_pmnc_start(void) -{ - int ret; - - pmu_irqs = reserve_pmu(); - if (IS_ERR(pmu_irqs)) - return PTR_ERR(pmu_irqs); - -#ifdef DEBUG - armv7_pmnc_dump_regs(); -#endif - ret = armv7_request_interrupts(pmu_irqs->irqs, pmu_irqs->num_irqs); - if (ret >= 0) { - armv7_start_pmnc(); - } else { - release_pmu(pmu_irqs); - pmu_irqs = NULL; - } - - return ret; -} - -static int armv7_detect_pmnc(void) -{ - return 0; -} - -struct op_arm_model_spec op_armv7_spec = { - .init = armv7_detect_pmnc, - .num_counters = 5, - .setup_ctrs = armv7_setup_pmnc, - .start = armv7_pmnc_start, - .stop = armv7_pmnc_stop, - .name = "arm/armv7", -}; diff --git a/arch/arm/oprofile/op_model_v7.h b/arch/arm/oprofile/op_model_v7.h deleted file mode 100644 index 9ca334b..0000000 --- a/arch/arm/oprofile/op_model_v7.h +++ /dev/null @@ -1,103 +0,0 @@ -/** - * op_model_v7.h - * ARM v7 (Cortex A8) Event Monitor Driver - * - * Copyright 2008 Jean Pihet - * Copyright 2004 ARM SMP Development Team - * Copyright 2000-2004 Deepak Saxena - * Copyright 2000-2004 MontaVista Software Inc - * Copyright 2004 Dave Jiang - * Copyright 2004 Intel Corporation - * Copyright 2004 Zwane Mwaikambo - * Copyright 2004 Oprofile Authors - * - * Read the file COPYING - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#ifndef OP_MODEL_V7_H -#define OP_MODEL_V7_H - -/* - * Per-CPU PMNC: config reg - */ -#define PMNC_E (1 << 0) /* Enable all counters */ -#define PMNC_P (1 << 1) /* Reset all counters */ -#define PMNC_C (1 << 2) /* Cycle counter reset */ -#define PMNC_D (1 << 3) /* CCNT counts every 64th cpu cycle */ -#define PMNC_X (1 << 4) /* Export to ETM */ -#define PMNC_DP (1 << 5) /* Disable CCNT if non-invasive debug*/ -#define PMNC_MASK 0x3f /* Mask for writable bits */ - -/* - * Available counters - */ -#define CCNT 0 -#define CNT0 1 -#define CNT1 2 -#define CNT2 3 -#define CNT3 4 -#define CNTMAX 5 - -#define CPU_COUNTER(cpu, counter) ((cpu) * CNTMAX + (counter)) - -/* - * CNTENS: counters enable reg - */ -#define CNTENS_P0 (1 << 0) -#define CNTENS_P1 (1 << 1) -#define CNTENS_P2 (1 << 2) -#define CNTENS_P3 (1 << 3) -#define CNTENS_C (1 << 31) -#define CNTENS_MASK 0x8000000f /* Mask for writable bits */ - -/* - * CNTENC: counters disable reg - */ -#define CNTENC_P0 (1 << 0) -#define CNTENC_P1 (1 << 1) -#define CNTENC_P2 (1 << 2) -#define CNTENC_P3 (1 << 3) -#define CNTENC_C (1 << 31) -#define CNTENC_MASK 0x8000000f /* Mask for writable bits */ - -/* - * INTENS: counters overflow interrupt enable reg - */ -#define INTENS_P0 (1 << 0) -#define INTENS_P1 (1 << 1) -#define INTENS_P2 (1 << 2) -#define INTENS_P3 (1 << 3) -#define INTENS_C (1 << 31) -#define INTENS_MASK 0x8000000f /* Mask for writable bits */ - -/* - * EVTSEL: Event selection reg - */ -#define EVTSEL_MASK 0x7f /* Mask for writable bits */ - -/* - * SELECT: Counter selection reg - */ -#define SELECT_MASK 0x1f /* Mask for writable bits */ - -/* - * FLAG: counters overflow flag status reg - */ -#define FLAG_P0 (1 << 0) -#define FLAG_P1 (1 << 1) -#define FLAG_P2 (1 << 2) -#define FLAG_P3 (1 << 3) -#define FLAG_C (1 << 31) -#define FLAG_MASK 0x8000000f /* Mask for writable bits */ - - -int armv7_setup_pmu(void); -int armv7_start_pmu(void); -int armv7_stop_pmu(void); -int armv7_request_interrupts(const int *, int); -void armv7_release_interrupts(const int *, int); - -#endif diff --git a/arch/arm/oprofile/op_model_xscale.c b/arch/arm/oprofile/op_model_xscale.c deleted file mode 100644 index 1d34a02..0000000 --- a/arch/arm/oprofile/op_model_xscale.c +++ /dev/null @@ -1,444 +0,0 @@ -/** - * @file op_model_xscale.c - * XScale Performance Monitor Driver - * - * @remark Copyright 2000-2004 Deepak Saxena - * @remark Copyright 2000-2004 MontaVista Software Inc - * @remark Copyright 2004 Dave Jiang - * @remark Copyright 2004 Intel Corporation - * @remark Copyright 2004 Zwane Mwaikambo - * @remark Copyright 2004 OProfile Authors - * - * @remark Read the file COPYING - * - * @author Zwane Mwaikambo - */ - -/* #define DEBUG */ -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "op_counter.h" -#include "op_arm_model.h" - -#define PMU_ENABLE 0x001 /* Enable counters */ -#define PMN_RESET 0x002 /* Reset event counters */ -#define CCNT_RESET 0x004 /* Reset clock counter */ -#define PMU_RESET (CCNT_RESET | PMN_RESET) -#define PMU_CNT64 0x008 /* Make CCNT count every 64th cycle */ - -/* - * Different types of events that can be counted by the XScale PMU - * as used by Oprofile userspace. Here primarily for documentation - * purposes. - */ - -#define EVT_ICACHE_MISS 0x00 -#define EVT_ICACHE_NO_DELIVER 0x01 -#define EVT_DATA_STALL 0x02 -#define EVT_ITLB_MISS 0x03 -#define EVT_DTLB_MISS 0x04 -#define EVT_BRANCH 0x05 -#define EVT_BRANCH_MISS 0x06 -#define EVT_INSTRUCTION 0x07 -#define EVT_DCACHE_FULL_STALL 0x08 -#define EVT_DCACHE_FULL_STALL_CONTIG 0x09 -#define EVT_DCACHE_ACCESS 0x0A -#define EVT_DCACHE_MISS 0x0B -#define EVT_DCACE_WRITE_BACK 0x0C -#define EVT_PC_CHANGED 0x0D -#define EVT_BCU_REQUEST 0x10 -#define EVT_BCU_FULL 0x11 -#define EVT_BCU_DRAIN 0x12 -#define EVT_BCU_ECC_NO_ELOG 0x14 -#define EVT_BCU_1_BIT_ERR 0x15 -#define EVT_RMW 0x16 -/* EVT_CCNT is not hardware defined */ -#define EVT_CCNT 0xFE -#define EVT_UNUSED 0xFF - -struct pmu_counter { - volatile unsigned long ovf; - unsigned long reset_counter; -}; - -enum { CCNT, PMN0, PMN1, PMN2, PMN3, MAX_COUNTERS }; - -static struct pmu_counter results[MAX_COUNTERS]; - -/* - * There are two versions of the PMU in current XScale processors - * with differing register layouts and number of performance counters. - * e.g. IOP32x is xsc1 whilst IOP33x is xsc2. - * We detect which register layout to use in xscale_detect_pmu() - */ -enum { PMU_XSC1, PMU_XSC2 }; - -struct pmu_type { - int id; - char *name; - int num_counters; - unsigned int int_enable; - unsigned int cnt_ovf[MAX_COUNTERS]; - unsigned int int_mask[MAX_COUNTERS]; -}; - -static struct pmu_type pmu_parms[] = { - { - .id = PMU_XSC1, - .name = "arm/xscale1", - .num_counters = 3, - .int_mask = { [PMN0] = 0x10, [PMN1] = 0x20, - [CCNT] = 0x40 }, - .cnt_ovf = { [CCNT] = 0x400, [PMN0] = 0x100, - [PMN1] = 0x200}, - }, - { - .id = PMU_XSC2, - .name = "arm/xscale2", - .num_counters = 5, - .int_mask = { [CCNT] = 0x01, [PMN0] = 0x02, - [PMN1] = 0x04, [PMN2] = 0x08, - [PMN3] = 0x10 }, - .cnt_ovf = { [CCNT] = 0x01, [PMN0] = 0x02, - [PMN1] = 0x04, [PMN2] = 0x08, - [PMN3] = 0x10 }, - }, -}; - -static struct pmu_type *pmu; - -static void write_pmnc(u32 val) -{ - if (pmu->id == PMU_XSC1) { - /* upper 4bits and 7, 11 are write-as-0 */ - val &= 0xffff77f; - __asm__ __volatile__ ("mcr p14, 0, %0, c0, c0, 0" : : "r" (val)); - } else { - /* bits 4-23 are write-as-0, 24-31 are write ignored */ - val &= 0xf; - __asm__ __volatile__ ("mcr p14, 0, %0, c0, c1, 0" : : "r" (val)); - } -} - -static u32 read_pmnc(void) -{ - u32 val; - - if (pmu->id == PMU_XSC1) - __asm__ __volatile__ ("mrc p14, 0, %0, c0, c0, 0" : "=r" (val)); - else { - __asm__ __volatile__ ("mrc p14, 0, %0, c0, c1, 0" : "=r" (val)); - /* bits 1-2 and 4-23 are read-unpredictable */ - val &= 0xff000009; - } - - return val; -} - -static u32 __xsc1_read_counter(int counter) -{ - u32 val = 0; - - switch (counter) { - case CCNT: - __asm__ __volatile__ ("mrc p14, 0, %0, c1, c0, 0" : "=r" (val)); - break; - case PMN0: - __asm__ __volatile__ ("mrc p14, 0, %0, c2, c0, 0" : "=r" (val)); - break; - case PMN1: - __asm__ __volatile__ ("mrc p14, 0, %0, c3, c0, 0" : "=r" (val)); - break; - } - return val; -} - -static u32 __xsc2_read_counter(int counter) -{ - u32 val = 0; - - switch (counter) { - case CCNT: - __asm__ __volatile__ ("mrc p14, 0, %0, c1, c1, 0" : "=r" (val)); - break; - case PMN0: - __asm__ __volatile__ ("mrc p14, 0, %0, c0, c2, 0" : "=r" (val)); - break; - case PMN1: - __asm__ __volatile__ ("mrc p14, 0, %0, c1, c2, 0" : "=r" (val)); - break; - case PMN2: - __asm__ __volatile__ ("mrc p14, 0, %0, c2, c2, 0" : "=r" (val)); - break; - case PMN3: - __asm__ __volatile__ ("mrc p14, 0, %0, c3, c2, 0" : "=r" (val)); - break; - } - return val; -} - -static u32 read_counter(int counter) -{ - u32 val; - - if (pmu->id == PMU_XSC1) - val = __xsc1_read_counter(counter); - else - val = __xsc2_read_counter(counter); - - return val; -} - -static void __xsc1_write_counter(int counter, u32 val) -{ - switch (counter) { - case CCNT: - __asm__ __volatile__ ("mcr p14, 0, %0, c1, c0, 0" : : "r" (val)); - break; - case PMN0: - __asm__ __volatile__ ("mcr p14, 0, %0, c2, c0, 0" : : "r" (val)); - break; - case PMN1: - __asm__ __volatile__ ("mcr p14, 0, %0, c3, c0, 0" : : "r" (val)); - break; - } -} - -static void __xsc2_write_counter(int counter, u32 val) -{ - switch (counter) { - case CCNT: - __asm__ __volatile__ ("mcr p14, 0, %0, c1, c1, 0" : : "r" (val)); - break; - case PMN0: - __asm__ __volatile__ ("mcr p14, 0, %0, c0, c2, 0" : : "r" (val)); - break; - case PMN1: - __asm__ __volatile__ ("mcr p14, 0, %0, c1, c2, 0" : : "r" (val)); - break; - case PMN2: - __asm__ __volatile__ ("mcr p14, 0, %0, c2, c2, 0" : : "r" (val)); - break; - case PMN3: - __asm__ __volatile__ ("mcr p14, 0, %0, c3, c2, 0" : : "r" (val)); - break; - } -} - -static void write_counter(int counter, u32 val) -{ - if (pmu->id == PMU_XSC1) - __xsc1_write_counter(counter, val); - else - __xsc2_write_counter(counter, val); -} - -static int xscale_setup_ctrs(void) -{ - u32 evtsel, pmnc; - int i; - - for (i = CCNT; i < MAX_COUNTERS; i++) { - if (counter_config[i].enabled) - continue; - - counter_config[i].event = EVT_UNUSED; - } - - switch (pmu->id) { - case PMU_XSC1: - pmnc = (counter_config[PMN1].event << 20) | (counter_config[PMN0].event << 12); - pr_debug("xscale_setup_ctrs: pmnc: %#08x\n", pmnc); - write_pmnc(pmnc); - break; - - case PMU_XSC2: - evtsel = counter_config[PMN0].event | (counter_config[PMN1].event << 8) | - (counter_config[PMN2].event << 16) | (counter_config[PMN3].event << 24); - - pr_debug("xscale_setup_ctrs: evtsel %#08x\n", evtsel); - __asm__ __volatile__ ("mcr p14, 0, %0, c8, c1, 0" : : "r" (evtsel)); - break; - } - - for (i = CCNT; i < MAX_COUNTERS; i++) { - if (counter_config[i].event == EVT_UNUSED) { - counter_config[i].event = 0; - pmu->int_enable &= ~pmu->int_mask[i]; - continue; - } - - results[i].reset_counter = counter_config[i].count; - write_counter(i, -(u32)counter_config[i].count); - pmu->int_enable |= pmu->int_mask[i]; - pr_debug("xscale_setup_ctrs: counter%d %#08x from %#08lx\n", i, - read_counter(i), counter_config[i].count); - } - - return 0; -} - -static void inline __xsc1_check_ctrs(void) -{ - int i; - u32 pmnc = read_pmnc(); - - /* NOTE: there's an A stepping errata that states if an overflow */ - /* bit already exists and another occurs, the previous */ - /* Overflow bit gets cleared. There's no workaround. */ - /* Fixed in B stepping or later */ - - /* Write the value back to clear the overflow flags. Overflow */ - /* flags remain in pmnc for use below */ - write_pmnc(pmnc & ~PMU_ENABLE); - - for (i = CCNT; i <= PMN1; i++) { - if (!(pmu->int_mask[i] & pmu->int_enable)) - continue; - - if (pmnc & pmu->cnt_ovf[i]) - results[i].ovf++; - } -} - -static void inline __xsc2_check_ctrs(void) -{ - int i; - u32 flag = 0, pmnc = read_pmnc(); - - pmnc &= ~PMU_ENABLE; - write_pmnc(pmnc); - - /* read overflow flag register */ - __asm__ __volatile__ ("mrc p14, 0, %0, c5, c1, 0" : "=r" (flag)); - - for (i = CCNT; i <= PMN3; i++) { - if (!(pmu->int_mask[i] & pmu->int_enable)) - continue; - - if (flag & pmu->cnt_ovf[i]) - results[i].ovf++; - } - - /* writeback clears overflow bits */ - __asm__ __volatile__ ("mcr p14, 0, %0, c5, c1, 0" : : "r" (flag)); -} - -static irqreturn_t xscale_pmu_interrupt(int irq, void *arg) -{ - int i; - u32 pmnc; - - if (pmu->id == PMU_XSC1) - __xsc1_check_ctrs(); - else - __xsc2_check_ctrs(); - - for (i = CCNT; i < MAX_COUNTERS; i++) { - if (!results[i].ovf) - continue; - - write_counter(i, -(u32)results[i].reset_counter); - oprofile_add_sample(get_irq_regs(), i); - results[i].ovf--; - } - - pmnc = read_pmnc() | PMU_ENABLE; - write_pmnc(pmnc); - - return IRQ_HANDLED; -} - -static const struct pmu_irqs *pmu_irqs; - -static void xscale_pmu_stop(void) -{ - u32 pmnc = read_pmnc(); - - pmnc &= ~PMU_ENABLE; - write_pmnc(pmnc); - - free_irq(pmu_irqs->irqs[0], results); - release_pmu(pmu_irqs); - pmu_irqs = NULL; -} - -static int xscale_pmu_start(void) -{ - int ret; - u32 pmnc; - - pmu_irqs = reserve_pmu(); - if (IS_ERR(pmu_irqs)) - return PTR_ERR(pmu_irqs); - - pmnc = read_pmnc(); - - ret = request_irq(pmu_irqs->irqs[0], xscale_pmu_interrupt, - IRQF_DISABLED, "XScale PMU", (void *)results); - - if (ret < 0) { - printk(KERN_ERR "oprofile: unable to request IRQ%d for XScale PMU\n", - pmu_irqs->irqs[0]); - release_pmu(pmu_irqs); - pmu_irqs = NULL; - return ret; - } - - if (pmu->id == PMU_XSC1) - pmnc |= pmu->int_enable; - else { - __asm__ __volatile__ ("mcr p14, 0, %0, c4, c1, 0" : : "r" (pmu->int_enable)); - pmnc &= ~PMU_CNT64; - } - - pmnc |= PMU_ENABLE; - write_pmnc(pmnc); - pr_debug("xscale_pmu_start: pmnc: %#08x mask: %08x\n", pmnc, pmu->int_enable); - return 0; -} - -static int xscale_detect_pmu(void) -{ - int ret = 0; - u32 id; - - id = (read_cpuid(CPUID_ID) >> 13) & 0x7; - - switch (id) { - case 1: - pmu = &pmu_parms[PMU_XSC1]; - break; - case 2: - pmu = &pmu_parms[PMU_XSC2]; - break; - default: - ret = -ENODEV; - break; - } - - if (!ret) { - op_xscale_spec.name = pmu->name; - op_xscale_spec.num_counters = pmu->num_counters; - pr_debug("xscale_detect_pmu: detected %s PMU\n", pmu->name); - } - - return ret; -} - -struct op_arm_model_spec op_xscale_spec = { - .init = xscale_detect_pmu, - .setup_ctrs = xscale_setup_ctrs, - .start = xscale_pmu_start, - .stop = xscale_pmu_stop, -}; - -- cgit v0.10.2 From d1e86d64bc48dedd0d68d182d0ce6951d8b4fd0d Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 30 Apr 2010 11:38:39 +0100 Subject: ARM: 6074/1: oprofile: convert from sysdev to platform device This is a reworking of an original patch posted by Aaro Koskinen: oprofile does not work with PM, because sysdev_suspend() is done with interrupts disabled and oprofile needs a mutex. Implementing oprofile as a platform device solves this problem. Cc: Aaro Koskinen Signed-off-by: Will Deacon Signed-off-by: Aaro Koskinen Signed-off-by: Russell King diff --git a/arch/arm/oprofile/common.c b/arch/arm/oprofile/common.c index aad83df..0691176 100644 --- a/arch/arm/oprofile/common.c +++ b/arch/arm/oprofile/common.c @@ -10,13 +10,14 @@ */ #include +#include #include #include #include #include #include +#include #include -#include #include #include @@ -227,7 +228,7 @@ static void op_arm_stop(void) } #ifdef CONFIG_PM -static int op_arm_suspend(struct sys_device *dev, pm_message_t state) +static int op_arm_suspend(struct platform_device *dev, pm_message_t state) { mutex_lock(&op_arm_mutex); if (op_arm_enabled) @@ -236,7 +237,7 @@ static int op_arm_suspend(struct sys_device *dev, pm_message_t state) return 0; } -static int op_arm_resume(struct sys_device *dev) +static int op_arm_resume(struct platform_device *dev) { mutex_lock(&op_arm_mutex); if (op_arm_enabled && op_perf_start()) @@ -245,34 +246,42 @@ static int op_arm_resume(struct sys_device *dev) return 0; } -static struct sysdev_class oprofile_sysclass = { - .name = "oprofile", +static struct platform_driver oprofile_driver = { + .driver = { + .name = "arm-oprofile", + }, .resume = op_arm_resume, .suspend = op_arm_suspend, }; -static struct sys_device device_oprofile = { - .id = 0, - .cls = &oprofile_sysclass, -}; +static struct platform_device *oprofile_pdev; static int __init init_driverfs(void) { int ret; - if (!(ret = sysdev_class_register(&oprofile_sysclass))) - ret = sysdev_register(&device_oprofile); + ret = platform_driver_register(&oprofile_driver); + if (ret) + goto out; + + oprofile_pdev = platform_device_register_simple( + oprofile_driver.driver.name, 0, NULL, 0); + if (IS_ERR(oprofile_pdev)) { + ret = PTR_ERR(oprofile_pdev); + platform_driver_unregister(&oprofile_driver); + } +out: return ret; } static void exit_driverfs(void) { - sysdev_unregister(&device_oprofile); - sysdev_class_unregister(&oprofile_sysclass); + platform_device_unregister(oprofile_pdev); + platform_driver_unregister(&oprofile_driver); } #else -#define init_driverfs() do { } while (0) +static int __init init_driverfs(void) { return 0; } #define exit_driverfs() do { } while (0) #endif /* CONFIG_PM */ @@ -353,6 +362,12 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) return -ENOMEM; } + ret = init_driverfs(); + if (ret) { + kfree(counter_config); + return ret; + } + for_each_possible_cpu(cpu) { perf_events[cpu] = kcalloc(perf_num_counters, sizeof(struct perf_event *), GFP_KERNEL); @@ -365,7 +380,6 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) } } - init_driverfs(); ops->backtrace = arm_backtrace; ops->create_files = op_arm_create_files; ops->setup = op_arm_setup; -- cgit v0.10.2 From f3d46f9d3194e0329216002a8724d4c0957abc79 Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 17 May 2010 14:33:53 +1000 Subject: atomic_t: Cast to volatile when accessing atomic variables In preparation for removing volatile from the atomic_t definition, this patch adds a volatile cast to all the atomic read functions. Signed-off-by: Anton Blanchard Signed-off-by: Linus Torvalds diff --git a/arch/alpha/include/asm/atomic.h b/arch/alpha/include/asm/atomic.h index 610dff4..e756d04 100644 --- a/arch/alpha/include/asm/atomic.h +++ b/arch/alpha/include/asm/atomic.h @@ -17,8 +17,8 @@ #define ATOMIC_INIT(i) ( (atomic_t) { (i) } ) #define ATOMIC64_INIT(i) ( (atomic64_t) { (i) } ) -#define atomic_read(v) ((v)->counter + 0) -#define atomic64_read(v) ((v)->counter + 0) +#define atomic_read(v) (*(volatile int *)&(v)->counter) +#define atomic64_read(v) (*(volatile long *)&(v)->counter) #define atomic_set(v,i) ((v)->counter = (i)) #define atomic64_set(v,i) ((v)->counter = (i)) diff --git a/arch/arm/include/asm/atomic.h b/arch/arm/include/asm/atomic.h index e8ddec2..a0162fa 100644 --- a/arch/arm/include/asm/atomic.h +++ b/arch/arm/include/asm/atomic.h @@ -24,7 +24,7 @@ * strex/ldrex monitor on some implementations. The reason we can use it for * atomic_set() is the clrex or dummy strex done on every exception return. */ -#define atomic_read(v) ((v)->counter) +#define atomic_read(v) (*(volatile int *)&(v)->counter) #define atomic_set(v,i) (((v)->counter) = (i)) #if __LINUX_ARM_ARCH__ >= 6 diff --git a/arch/avr32/include/asm/atomic.h b/arch/avr32/include/asm/atomic.h index b131c27..bbce6a1c 100644 --- a/arch/avr32/include/asm/atomic.h +++ b/arch/avr32/include/asm/atomic.h @@ -19,7 +19,7 @@ #define ATOMIC_INIT(i) { (i) } -#define atomic_read(v) ((v)->counter) +#define atomic_read(v) (*(volatile int *)&(v)->counter) #define atomic_set(v, i) (((v)->counter) = i) /* diff --git a/arch/cris/include/asm/atomic.h b/arch/cris/include/asm/atomic.h index a6aca81..88dc9b9 100644 --- a/arch/cris/include/asm/atomic.h +++ b/arch/cris/include/asm/atomic.h @@ -15,7 +15,7 @@ #define ATOMIC_INIT(i) { (i) } -#define atomic_read(v) ((v)->counter) +#define atomic_read(v) (*(volatile int *)&(v)->counter) #define atomic_set(v,i) (((v)->counter) = (i)) /* These should be written in asm but we do it in C for now. */ diff --git a/arch/frv/include/asm/atomic.h b/arch/frv/include/asm/atomic.h index 00a57af..fae32c7 100644 --- a/arch/frv/include/asm/atomic.h +++ b/arch/frv/include/asm/atomic.h @@ -36,7 +36,7 @@ #define smp_mb__after_atomic_inc() barrier() #define ATOMIC_INIT(i) { (i) } -#define atomic_read(v) ((v)->counter) +#define atomic_read(v) (*(volatile int *)&(v)->counter) #define atomic_set(v, i) (((v)->counter) = (i)) #ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS diff --git a/arch/h8300/include/asm/atomic.h b/arch/h8300/include/asm/atomic.h index 33c8c0f..e936804 100644 --- a/arch/h8300/include/asm/atomic.h +++ b/arch/h8300/include/asm/atomic.h @@ -10,7 +10,7 @@ #define ATOMIC_INIT(i) { (i) } -#define atomic_read(v) ((v)->counter) +#define atomic_read(v) (*(volatile int *)&(v)->counter) #define atomic_set(v, i) (((v)->counter) = i) #include diff --git a/arch/ia64/include/asm/atomic.h b/arch/ia64/include/asm/atomic.h index 88405cb..4e19484 100644 --- a/arch/ia64/include/asm/atomic.h +++ b/arch/ia64/include/asm/atomic.h @@ -21,8 +21,8 @@ #define ATOMIC_INIT(i) ((atomic_t) { (i) }) #define ATOMIC64_INIT(i) ((atomic64_t) { (i) }) -#define atomic_read(v) ((v)->counter) -#define atomic64_read(v) ((v)->counter) +#define atomic_read(v) (*(volatile int *)&(v)->counter) +#define atomic64_read(v) (*(volatile long *)&(v)->counter) #define atomic_set(v,i) (((v)->counter) = (i)) #define atomic64_set(v,i) (((v)->counter) = (i)) diff --git a/arch/m32r/include/asm/atomic.h b/arch/m32r/include/asm/atomic.h index 63f0cf0..d44a51e 100644 --- a/arch/m32r/include/asm/atomic.h +++ b/arch/m32r/include/asm/atomic.h @@ -26,7 +26,7 @@ * * Atomically reads the value of @v. */ -#define atomic_read(v) ((v)->counter) +#define atomic_read(v) (*(volatile int *)&(v)->counter) /** * atomic_set - set atomic variable diff --git a/arch/m68k/include/asm/atomic_mm.h b/arch/m68k/include/asm/atomic_mm.h index d9d2ed6..6a223b3 100644 --- a/arch/m68k/include/asm/atomic_mm.h +++ b/arch/m68k/include/asm/atomic_mm.h @@ -15,7 +15,7 @@ #define ATOMIC_INIT(i) { (i) } -#define atomic_read(v) ((v)->counter) +#define atomic_read(v) (*(volatile int *)&(v)->counter) #define atomic_set(v, i) (((v)->counter) = i) static inline void atomic_add(int i, atomic_t *v) diff --git a/arch/m68k/include/asm/atomic_no.h b/arch/m68k/include/asm/atomic_no.h index 5674cb9..289310c 100644 --- a/arch/m68k/include/asm/atomic_no.h +++ b/arch/m68k/include/asm/atomic_no.h @@ -15,7 +15,7 @@ #define ATOMIC_INIT(i) { (i) } -#define atomic_read(v) ((v)->counter) +#define atomic_read(v) (*(volatile int *)&(v)->counter) #define atomic_set(v, i) (((v)->counter) = i) static __inline__ void atomic_add(int i, atomic_t *v) diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h index 519197e..59dc0c7 100644 --- a/arch/mips/include/asm/atomic.h +++ b/arch/mips/include/asm/atomic.h @@ -29,7 +29,7 @@ * * Atomically reads the value of @v. */ -#define atomic_read(v) ((v)->counter) +#define atomic_read(v) (*(volatile int *)&(v)->counter) /* * atomic_set - set atomic variable @@ -410,7 +410,7 @@ static __inline__ int atomic_add_unless(atomic_t *v, int a, int u) * @v: pointer of type atomic64_t * */ -#define atomic64_read(v) ((v)->counter) +#define atomic64_read(v) (*(volatile long *)&(v)->counter) /* * atomic64_set - set atomic variable diff --git a/arch/mn10300/include/asm/atomic.h b/arch/mn10300/include/asm/atomic.h index 5bf5be9..e41222d 100644 --- a/arch/mn10300/include/asm/atomic.h +++ b/arch/mn10300/include/asm/atomic.h @@ -31,7 +31,7 @@ * Atomically reads the value of @v. Note that the guaranteed * useful range of an atomic_t is only 24 bits. */ -#define atomic_read(v) ((v)->counter) +#define atomic_read(v) (*(volatile int *)&(v)->counter) /** * atomic_set - set atomic variable diff --git a/arch/parisc/include/asm/atomic.h b/arch/parisc/include/asm/atomic.h index 716634d..f819559 100644 --- a/arch/parisc/include/asm/atomic.h +++ b/arch/parisc/include/asm/atomic.h @@ -189,7 +189,7 @@ static __inline__ void atomic_set(atomic_t *v, int i) static __inline__ int atomic_read(const atomic_t *v) { - return v->counter; + return (*(volatile int *)&(v)->counter); } /* exported interface */ @@ -286,7 +286,7 @@ atomic64_set(atomic64_t *v, s64 i) static __inline__ s64 atomic64_read(const atomic64_t *v) { - return v->counter; + return (*(volatile long *)&(v)->counter); } #define atomic64_add(i,v) ((void)(__atomic64_add_return( ((s64)(i)),(v)))) diff --git a/arch/sh/include/asm/atomic.h b/arch/sh/include/asm/atomic.h index 275a448..c798312 100644 --- a/arch/sh/include/asm/atomic.h +++ b/arch/sh/include/asm/atomic.h @@ -13,7 +13,7 @@ #define ATOMIC_INIT(i) ( (atomic_t) { (i) } ) -#define atomic_read(v) ((v)->counter) +#define atomic_read(v) (*(volatile int *)&(v)->counter) #define atomic_set(v,i) ((v)->counter = (i)) #if defined(CONFIG_GUSA_RB) diff --git a/arch/sparc/include/asm/atomic_32.h b/arch/sparc/include/asm/atomic_32.h index f0d343c..7ae128b 100644 --- a/arch/sparc/include/asm/atomic_32.h +++ b/arch/sparc/include/asm/atomic_32.h @@ -25,7 +25,7 @@ extern int atomic_cmpxchg(atomic_t *, int, int); extern int atomic_add_unless(atomic_t *, int, int); extern void atomic_set(atomic_t *, int); -#define atomic_read(v) ((v)->counter) +#define atomic_read(v) (*(volatile int *)&(v)->counter) #define atomic_add(i, v) ((void)__atomic_add_return( (int)(i), (v))) #define atomic_sub(i, v) ((void)__atomic_add_return(-(int)(i), (v))) diff --git a/arch/sparc/include/asm/atomic_64.h b/arch/sparc/include/asm/atomic_64.h index f2e4800..2050ca0 100644 --- a/arch/sparc/include/asm/atomic_64.h +++ b/arch/sparc/include/asm/atomic_64.h @@ -13,8 +13,8 @@ #define ATOMIC_INIT(i) { (i) } #define ATOMIC64_INIT(i) { (i) } -#define atomic_read(v) ((v)->counter) -#define atomic64_read(v) ((v)->counter) +#define atomic_read(v) (*(volatile int *)&(v)->counter) +#define atomic64_read(v) (*(volatile long *)&(v)->counter) #define atomic_set(v, i) (((v)->counter) = i) #define atomic64_set(v, i) (((v)->counter) = i) diff --git a/arch/x86/include/asm/atomic.h b/arch/x86/include/asm/atomic.h index 8f8217b..37b39d2 100644 --- a/arch/x86/include/asm/atomic.h +++ b/arch/x86/include/asm/atomic.h @@ -22,7 +22,7 @@ */ static inline int atomic_read(const atomic_t *v) { - return v->counter; + return (*(volatile int *)&(v)->counter); } /** diff --git a/arch/x86/include/asm/atomic64_64.h b/arch/x86/include/asm/atomic64_64.h index 51c5b40..b014e23 100644 --- a/arch/x86/include/asm/atomic64_64.h +++ b/arch/x86/include/asm/atomic64_64.h @@ -18,7 +18,7 @@ */ static inline long atomic64_read(const atomic64_t *v) { - return v->counter; + return (*(volatile long *)&(v)->counter); } /** diff --git a/arch/xtensa/include/asm/atomic.h b/arch/xtensa/include/asm/atomic.h index 22d6dde..a96a061 100644 --- a/arch/xtensa/include/asm/atomic.h +++ b/arch/xtensa/include/asm/atomic.h @@ -46,7 +46,7 @@ * * Atomically reads the value of @v. */ -#define atomic_read(v) ((v)->counter) +#define atomic_read(v) (*(volatile int *)&(v)->counter) /** * atomic_set - set atomic variable diff --git a/include/asm-generic/atomic.h b/include/asm-generic/atomic.h index c99c64d..c33749f 100644 --- a/include/asm-generic/atomic.h +++ b/include/asm-generic/atomic.h @@ -33,7 +33,7 @@ * Atomically reads the value of @v. Note that the guaranteed * useful range of an atomic_t is only 24 bits. */ -#define atomic_read(v) ((v)->counter) +#define atomic_read(v) (*(volatile int *)&(v)->counter) /** * atomic_set - set atomic variable -- cgit v0.10.2 From 81880d603d00c645e0890d0a44d50711c503b72b Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Mon, 17 May 2010 14:34:57 +1000 Subject: atomic_t: Remove volatile from atomic_t definition When looking at a performance problem on PowerPC, I noticed some awful code generation: c00000000051fc98: 3b 60 00 01 li r27,1 ... c00000000051fca0: 3b 80 00 00 li r28,0 ... c00000000051fcdc: 93 61 00 70 stw r27,112(r1) c00000000051fce0: 93 81 00 74 stw r28,116(r1) c00000000051fce4: 81 21 00 70 lwz r9,112(r1) c00000000051fce8: 80 01 00 74 lwz r0,116(r1) c00000000051fcec: 7d 29 07 b4 extsw r9,r9 c00000000051fcf0: 7c 00 07 b4 extsw r0,r0 c00000000051fcf4: 7c 20 04 ac lwsync c00000000051fcf8: 7d 60 f8 28 lwarx r11,0,r31 c00000000051fcfc: 7c 0b 48 00 cmpw r11,r9 c00000000051fd00: 40 c2 00 10 bne- c00000000051fd10 c00000000051fd04: 7c 00 f9 2d stwcx. r0,0,r31 c00000000051fd08: 40 c2 ff f0 bne+ c00000000051fcf8 c00000000051fd0c: 4c 00 01 2c isync We create two constants, write them out to the stack, read them straight back in and sign extend them. What a mess. It turns out this bad code is a result of us defining atomic_t as a volatile int. We removed the volatile attribute from the powerpc atomic_t definition years ago, but commit ea435467500612636f8f4fb639ff6e76b2496e4b (atomic_t: unify all arch definitions) added it back in. To dig up an old quote from Linus: > The fact is, volatile on data structures is a bug. It's a wart in the C > language. It shouldn't be used. > > Volatile accesses in *code* can be ok, and if we have "atomic_read()" > expand to a "*(volatile int *)&(x)->value", then I'd be ok with that. > > But marking data structures volatile just makes the compiler screw up > totally, and makes code for initialization sequences etc much worse. And screw up it does :) With the volatile removed, we see much more reasonable code generation: c00000000051f5b8: 3b 60 00 01 li r27,1 ... c00000000051f5c0: 3b 80 00 00 li r28,0 ... c00000000051fc7c: 7c 20 04 ac lwsync c00000000051fc80: 7c 00 f8 28 lwarx r0,0,r31 c00000000051fc84: 7c 00 d8 00 cmpw r0,r27 c00000000051fc88: 40 c2 00 10 bne- c00000000051fc98 c00000000051fc8c: 7f 80 f9 2d stwcx. r28,0,r31 c00000000051fc90: 40 c2 ff f0 bne+ c00000000051fc80 c00000000051fc94: 4c 00 01 2c isync Six instructions less. Signed-off-by: Anton Blanchard Signed-off-by: Linus Torvalds diff --git a/include/linux/types.h b/include/linux/types.h index c42724f..23d237a 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -188,12 +188,12 @@ typedef u32 phys_addr_t; typedef phys_addr_t resource_size_t; typedef struct { - volatile int counter; + int counter; } atomic_t; #ifdef CONFIG_64BIT typedef struct { - volatile long counter; + long counter; } atomic64_t; #endif -- cgit v0.10.2 From 6ba85cea872954a36d79e46bf6a9c6ea92794f01 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 17 May 2010 12:16:48 -0300 Subject: perf options: Introduce OPT_U64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have things like user_interval (-c/--count) in 'perf record' that needs this. Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c index ed88764..b05d51d 100644 --- a/tools/perf/util/parse-options.c +++ b/tools/perf/util/parse-options.c @@ -60,6 +60,7 @@ static int get_value(struct parse_opt_ctx_t *p, case OPTION_STRING: case OPTION_INTEGER: case OPTION_LONG: + case OPTION_U64: default: break; } @@ -141,6 +142,22 @@ static int get_value(struct parse_opt_ctx_t *p, return opterror(opt, "expects a numerical value", flags); return 0; + case OPTION_U64: + if (unset) { + *(u64 *)opt->value = 0; + return 0; + } + if (opt->flags & PARSE_OPT_OPTARG && !p->opt) { + *(u64 *)opt->value = opt->defval; + return 0; + } + if (get_arg(p, opt, flags, &arg)) + return -1; + *(u64 *)opt->value = strtoull(arg, (char **)&s, 10); + if (*s) + return opterror(opt, "expects a numerical value", flags); + return 0; + case OPTION_END: case OPTION_ARGUMENT: case OPTION_GROUP: @@ -487,6 +504,7 @@ int usage_with_options_internal(const char * const *usagestr, case OPTION_SET_INT: case OPTION_SET_PTR: case OPTION_LONG: + case OPTION_U64: break; } diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h index b2da725..e301e96 100644 --- a/tools/perf/util/parse-options.h +++ b/tools/perf/util/parse-options.h @@ -17,6 +17,7 @@ enum parse_opt_type { OPTION_INTEGER, OPTION_LONG, OPTION_CALLBACK, + OPTION_U64, }; enum parse_opt_flags { @@ -101,6 +102,7 @@ struct option { #define OPT_SET_PTR(s, l, v, h, p) { .type = OPTION_SET_PTR, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (p) } #define OPT_INTEGER(s, l, v, h) { .type = OPTION_INTEGER, .short_name = (s), .long_name = (l), .value = (v), .help = (h) } #define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = (v), .help = (h) } +#define OPT_U64(s, l, v, h) { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = (v), .help = (h) } #define OPT_STRING(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h) } #define OPT_DATE(s, l, v, h) \ { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb } -- cgit v0.10.2 From 3de29cab1f8d62db557a4afed0fb17eebfe64438 Mon Sep 17 00:00:00 2001 From: Stephane Eranian Date: Mon, 17 May 2010 12:20:43 -0300 Subject: perf record: Fix bug mismatch with -c option definition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The -c option defines the user requested sampling period. It was implemented using an unsigned int variable but the type of the option was OPT_LONG. Thus, the option parser was overwriting memory belonging to other variables, namely the mmap_pages leading to a zero page sampling buffer. The bug was exposed only when compiling at -O0, probably because the compiler was padding variables at higher optimization levels. This patch fixes this problem by declaring user_interval as u64. This also avoids wrap-around issues for large period on 32-bit systems. Commiter note: Made it use OPT_U64(user_interval) after implementing OPT_U64 in the previous patch. Cc: David S. Miller Cc: Frédéric Weisbecker Cc: Ingo Molnar Cc: Paul Mackerras Cc: Peter Zijlstra LKML-Reference: <4bf11ae9.e88cd80a.06b0.ffffa8e3@mx.google.com> Signed-off-by: Stephane Eranian Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 0f467cf..b93573c 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -33,8 +33,8 @@ enum write_mode_t { static int *fd[MAX_NR_CPUS][MAX_COUNTERS]; -static unsigned int user_interval = UINT_MAX; -static long default_interval = 0; +static u64 user_interval = ULLONG_MAX; +static u64 default_interval = 0; static int nr_cpus = 0; static unsigned int page_size; @@ -268,7 +268,7 @@ static void create_counter(int counter, int cpu) * it a weak assumption overridable by the user. */ if (!attr->sample_period || (user_freq != UINT_MAX && - user_interval != UINT_MAX)) { + user_interval != ULLONG_MAX)) { if (freq) { attr->sample_type |= PERF_SAMPLE_PERIOD; attr->freq = 1; @@ -817,8 +817,7 @@ static const struct option options[] = { "CPU to profile on"), OPT_BOOLEAN('f', "force", &force, "overwrite existing data file (deprecated)"), - OPT_LONG('c', "count", &user_interval, - "event period to sample"), + OPT_U64('c', "count", &user_interval, "event period to sample"), OPT_STRING('o', "output", &output_name, "file", "output file name"), OPT_BOOLEAN('i', "no-inherit", &no_inherit, @@ -901,7 +900,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used) if (!event_array) return -ENOMEM; - if (user_interval != UINT_MAX) + if (user_interval != ULLONG_MAX) default_interval = user_interval; if (user_freq != UINT_MAX) freq = user_freq; -- cgit v0.10.2 From dc4ff19341126155c5714119396efbae62ab40bf Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 17 May 2010 12:25:09 -0300 Subject: perf tui: Add workaround for slang < 2.1.4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Older versions of the slang library didn't used the 'const' specifier, causing problems with modern compilers of this kind: util/newt.c:252: error: passing argument 1 of ‘SLsmg_printf’ discards qualifiers from pointer target type Fix it by using some wrappers that when needed const the affected parameters back to plain (char *). Reported-by: Lin Ming Cc: Frédéric Weisbecker Cc: Lin Ming Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Tom Zanussi LKML-Reference: <20100517145421.GD29052@ghostprotocols.net> Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index 2001d26..ccb7c5b 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c @@ -14,6 +14,17 @@ #include "sort.h" #include "symbol.h" +#if SLANG_VERSION < 20104 +#define slsmg_printf(msg, args...) SLsmg_printf((char *)msg, ##args) +#define slsmg_write_nstring(msg, len) SLsmg_write_nstring((char *)msg, len) +#define sltt_set_color(obj, name, fg, bg) SLtt_set_color(obj,(char *)name,\ + (char *)fg, (char *)bg) +#else +#define slsmg_printf SLsmg_printf +#define slsmg_write_nstring SLsmg_write_nstring +#define sltt_set_color SLtt_set_color +#endif + struct ui_progress { newtComponent form, scale; }; @@ -292,21 +303,21 @@ static int objdump_line__show(struct objdump_line *self, struct list_head *head, color = ui_browser__percent_color(percent, current_entry); SLsmg_set_color(color); - SLsmg_printf(" %7.2f ", percent); + slsmg_printf(" %7.2f ", percent); if (!current_entry) SLsmg_set_color(HE_COLORSET_CODE); } else { int color = ui_browser__percent_color(0, current_entry); SLsmg_set_color(color); - SLsmg_write_nstring(" ", 9); + slsmg_write_nstring(" ", 9); } SLsmg_write_char(':'); - SLsmg_write_nstring(" ", 8); + slsmg_write_nstring(" ", 8); if (!*self->line) - SLsmg_write_nstring(" ", width - 18); + slsmg_write_nstring(" ", width - 18); else - SLsmg_write_nstring(self->line, width - 18); + slsmg_write_nstring(self->line, width - 18); return 0; } @@ -1054,11 +1065,11 @@ void setup_browser(void) newtInit(); newtCls(); ui_helpline__puts(" "); - SLtt_set_color(HE_COLORSET_TOP, NULL, c->topColorFg, c->topColorBg); - SLtt_set_color(HE_COLORSET_MEDIUM, NULL, c->mediumColorFg, c->mediumColorBg); - SLtt_set_color(HE_COLORSET_NORMAL, NULL, c->normalColorFg, c->normalColorBg); - SLtt_set_color(HE_COLORSET_SELECTED, NULL, c->selColorFg, c->selColorBg); - SLtt_set_color(HE_COLORSET_CODE, NULL, c->codeColorFg, c->codeColorBg); + sltt_set_color(HE_COLORSET_TOP, NULL, c->topColorFg, c->topColorBg); + sltt_set_color(HE_COLORSET_MEDIUM, NULL, c->mediumColorFg, c->mediumColorBg); + sltt_set_color(HE_COLORSET_NORMAL, NULL, c->normalColorFg, c->normalColorBg); + sltt_set_color(HE_COLORSET_SELECTED, NULL, c->selColorFg, c->selColorBg); + sltt_set_color(HE_COLORSET_CODE, NULL, c->codeColorFg, c->codeColorBg); } void exit_browser(bool wait_for_ok) -- cgit v0.10.2 From 98830bc9967b18d6f9a614a1f354f5580196ef85 Mon Sep 17 00:00:00 2001 From: Hartley Sweeten Date: Mon, 17 May 2010 17:18:10 +0100 Subject: ARM: 6136/1: ARCH_REQUIRE_GPIOLIB selects GENERIC_GPIO The ARCH_REQUIRE_GPIOLIB config option will select GPIOLIB which in turn will select GENERIC_GPIO. Because of this, there is no reason to do the select GENERIC_GPIO in arch/arm/Kconfig for the architectures that have ARCH_REQUIRE_GPIOLIB. Signed-off-by: H Hartley Sweeten Signed-off-by: Russell King diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index daaa4b2..9e938a7 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -296,7 +296,6 @@ config ARCH_VEXPRESS config ARCH_AT91 bool "Atmel AT91" - select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB select HAVE_CLK select ARCH_USES_GETTIMEOFFSET @@ -326,7 +325,6 @@ config ARCH_CLPS711X config ARCH_GEMINI bool "Cortina Systems Gemini" select CPU_FA526 - select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB select ARCH_USES_GETTIMEOFFSET help @@ -349,7 +347,6 @@ config ARCH_EP93XX select CPU_ARM920T select ARM_AMBA select ARM_VIC - select GENERIC_GPIO select COMMON_CLKDEV select ARCH_REQUIRE_GPIOLIB select ARCH_HAS_HOLES_MEMORYMODEL @@ -382,7 +379,6 @@ config ARCH_STMP3XXX select ARCH_REQUIRE_GPIOLIB select GENERIC_TIME select GENERIC_CLOCKEVENTS - select GENERIC_GPIO select USB_ARCH_HAS_EHCI help Support for systems based on the Freescale 3xxx CPUs. @@ -421,7 +417,6 @@ config ARCH_IOP32X select CPU_XSCALE select PLAT_IOP select PCI - select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB help Support for Intel's 80219 and IOP32X (XScale) family of @@ -433,7 +428,6 @@ config ARCH_IOP33X select CPU_XSCALE select PLAT_IOP select PCI - select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB help Support for Intel's IOP33X (XScale) family of processors. @@ -485,7 +479,6 @@ config ARCH_L7200 config ARCH_DOVE bool "Marvell Dove" select PCI - select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB select GENERIC_TIME select GENERIC_CLOCKEVENTS @@ -497,7 +490,6 @@ config ARCH_KIRKWOOD bool "Marvell Kirkwood" select CPU_FEROCEON select PCI - select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB select GENERIC_TIME select GENERIC_CLOCKEVENTS @@ -519,7 +511,6 @@ config ARCH_MV78XX0 bool "Marvell MV78xx0" select CPU_FEROCEON select PCI - select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB select GENERIC_TIME select GENERIC_CLOCKEVENTS @@ -533,7 +524,6 @@ config ARCH_ORION5X depends on MMU select CPU_FEROCEON select PCI - select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB select GENERIC_TIME select GENERIC_CLOCKEVENTS @@ -546,7 +536,6 @@ config ARCH_ORION5X config ARCH_MMP bool "Marvell PXA168/910/MMP2" depends on MMU - select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB select COMMON_CLKDEV select GENERIC_TIME @@ -559,8 +548,7 @@ config ARCH_MMP config ARCH_KS8695 bool "Micrel/Kendin KS8695" select CPU_ARM922T - select GENERIC_GPIO - select ARCH_REQUIRE_GPIOLIB + select ARCH_REQUIRE_GPIOLIB select ARCH_USES_GETTIMEOFFSET help Support for Micrel/Kendin KS8695 "Centaur" (ARM922T) based @@ -583,7 +571,6 @@ config ARCH_W90X900 bool "Nuvoton W90X900 CPU" select CPU_ARM926T select ARCH_REQUIRE_GPIOLIB - select GENERIC_GPIO select COMMON_CLKDEV select GENERIC_TIME select GENERIC_CLOCKEVENTS @@ -617,7 +604,6 @@ config ARCH_PXA depends on MMU select ARCH_MTD_XIP select ARCH_HAS_CPUFREQ - select GENERIC_GPIO select COMMON_CLKDEV select ARCH_REQUIRE_GPIOLIB select GENERIC_TIME @@ -666,7 +652,6 @@ config ARCH_SA1100 select ARCH_MTD_XIP select ARCH_HAS_CPUFREQ select CPU_FREQ - select GENERIC_GPIO select GENERIC_TIME select GENERIC_CLOCKEVENTS select HAVE_CLK @@ -690,7 +675,6 @@ config ARCH_S3C64XX bool "Samsung S3C64XX" select PLAT_SAMSUNG select CPU_V6 - select GENERIC_GPIO select ARM_VIC select HAVE_CLK select NO_IOPORT @@ -801,7 +785,6 @@ config ARCH_NOMADIK select COMMON_CLKDEV select GENERIC_TIME select GENERIC_CLOCKEVENTS - select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB help Support for the Nomadik platform by ST-Ericsson @@ -811,7 +794,6 @@ config ARCH_DAVINCI select CPU_ARM926T select GENERIC_TIME select GENERIC_CLOCKEVENTS - select GENERIC_GPIO select ARCH_REQUIRE_GPIOLIB select ZONE_DMA select HAVE_IDE @@ -823,7 +805,6 @@ config ARCH_DAVINCI config ARCH_OMAP bool "TI OMAP" - select GENERIC_GPIO select HAVE_CLK select ARCH_REQUIRE_GPIOLIB select ARCH_HAS_CPUFREQ @@ -839,7 +820,6 @@ config PLAT_SPEAR select ARCH_REQUIRE_GPIOLIB select COMMON_CLKDEV select GENERIC_CLOCKEVENTS - select GENERIC_GPIO select GENERIC_TIME select HAVE_CLK help -- cgit v0.10.2 From c100edbee8dbf033ec4095a976a74c1c75c9fc1d Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 17 May 2010 15:30:00 -0300 Subject: perf options: Introduce OPT_UINTEGER MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For unsigned int options to be parsed, next patches will make use of it. Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c index b05d51d..36d955e 100644 --- a/tools/perf/util/parse-options.c +++ b/tools/perf/util/parse-options.c @@ -59,6 +59,7 @@ static int get_value(struct parse_opt_ctx_t *p, case OPTION_GROUP: case OPTION_STRING: case OPTION_INTEGER: + case OPTION_UINTEGER: case OPTION_LONG: case OPTION_U64: default: @@ -126,6 +127,22 @@ static int get_value(struct parse_opt_ctx_t *p, return opterror(opt, "expects a numerical value", flags); return 0; + case OPTION_UINTEGER: + if (unset) { + *(unsigned int *)opt->value = 0; + return 0; + } + if (opt->flags & PARSE_OPT_OPTARG && !p->opt) { + *(unsigned int *)opt->value = opt->defval; + return 0; + } + if (get_arg(p, opt, flags, &arg)) + return -1; + *(unsigned int *)opt->value = strtol(arg, (char **)&s, 10); + if (*s) + return opterror(opt, "expects a numerical value", flags); + return 0; + case OPTION_LONG: if (unset) { *(long *)opt->value = 0; @@ -463,7 +480,10 @@ int usage_with_options_internal(const char * const *usagestr, switch (opts->type) { case OPTION_ARGUMENT: break; + case OPTION_LONG: + case OPTION_U64: case OPTION_INTEGER: + case OPTION_UINTEGER: if (opts->flags & PARSE_OPT_OPTARG) if (opts->long_name) pos += fprintf(stderr, "[=]"); @@ -503,8 +523,6 @@ int usage_with_options_internal(const char * const *usagestr, case OPTION_INCR: case OPTION_SET_INT: case OPTION_SET_PTR: - case OPTION_LONG: - case OPTION_U64: break; } diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h index e301e96..c6aa4ee 100644 --- a/tools/perf/util/parse-options.h +++ b/tools/perf/util/parse-options.h @@ -18,6 +18,7 @@ enum parse_opt_type { OPTION_LONG, OPTION_CALLBACK, OPTION_U64, + OPTION_UINTEGER, }; enum parse_opt_flags { @@ -101,6 +102,7 @@ struct option { #define OPT_SET_INT(s, l, v, h, i) { .type = OPTION_SET_INT, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (i) } #define OPT_SET_PTR(s, l, v, h, p) { .type = OPTION_SET_PTR, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (p) } #define OPT_INTEGER(s, l, v, h) { .type = OPTION_INTEGER, .short_name = (s), .long_name = (l), .value = (v), .help = (h) } +#define OPT_UINTEGER(s, l, v, h) { .type = OPTION_UINTEGER, .short_name = (s), .long_name = (l), .value = (v), .help = (h) } #define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = (v), .help = (h) } #define OPT_U64(s, l, v, h) { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = (v), .help = (h) } #define OPT_STRING(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h) } -- cgit v0.10.2 From 1967936d688c475b85d34d84e09858cf514c893c Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 17 May 2010 15:39:16 -0300 Subject: perf options: Check v type in OPT_U?INTEGER MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To avoid problems like the one fixed by Stephane Eranian in 3de29ca, now we'll got this instead: bench/sched-messaging.c:259: error: negative width in bit-field ‘’ bench/sched-messaging.c:261: error: negative width in bit-field ‘’ Which is rather cryptic, but is how BUILD_BUG_ON_ZERO works, so kernel hackers should be already used to this. With it in place found some problems, fixed by changing the affected variables to sensible types or changed some OPT_INTEGER to OPT_UINTEGER. Next csets will go thru converting each of the remaining OPT_ so that review can be made easier by grouping changes per type per patch. Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/bench/sched-messaging.c b/tools/perf/bench/sched-messaging.c index da1b2e9..d1d1b30 100644 --- a/tools/perf/bench/sched-messaging.c +++ b/tools/perf/bench/sched-messaging.c @@ -256,10 +256,8 @@ static const struct option options[] = { "Use pipe() instead of socketpair()"), OPT_BOOLEAN('t', "thread", &thread_mode, "Be multi thread instead of multi process"), - OPT_INTEGER('g', "group", &num_groups, - "Specify number of groups"), - OPT_INTEGER('l', "loop", &loops, - "Specify number of loops"), + OPT_UINTEGER('g', "group", &num_groups, "Specify number of groups"), + OPT_UINTEGER('l', "loop", &loops, "Specify number of loops"), OPT_END() }; diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index b93573c..cb46c7d 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -45,7 +45,7 @@ static int output; static int pipe_output = 0; static const char *output_name = "perf.data"; static int group = 0; -static unsigned int realtime_prio = 0; +static int realtime_prio = 0; static bool raw_samples = false; static bool system_wide = false; static int profile_cpu = -1; @@ -822,10 +822,8 @@ static const struct option options[] = { "output file name"), OPT_BOOLEAN('i', "no-inherit", &no_inherit, "child tasks do not inherit counters"), - OPT_INTEGER('F', "freq", &user_freq, - "profile at this frequency"), - OPT_INTEGER('m', "mmap-pages", &mmap_pages, - "number of mmap data pages"), + OPT_UINTEGER('F', "freq", &user_freq, "profile at this frequency"), + OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"), OPT_BOOLEAN('g', "call-graph", &call_graph, "do call-graph (stack chain/backtrace) recording"), OPT_INCR('v', "verbose", &verbose, diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index be7bc92..c80acdf 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -105,7 +105,7 @@ static u64 sum_runtime; static u64 sum_fluct; static u64 run_avg; -static unsigned long replay_repeat = 10; +static unsigned int replay_repeat = 10; static unsigned long nr_timestamps; static unsigned long nr_unordered_timestamps; static unsigned long nr_state_machine_bugs; @@ -1816,8 +1816,8 @@ static const char * const replay_usage[] = { }; static const struct option replay_options[] = { - OPT_INTEGER('r', "repeat", &replay_repeat, - "repeat the workload replay N times (-1: infinite)"), + OPT_UINTEGER('r', "repeat", &replay_repeat, + "repeat the workload replay N times (-1: infinite)"), OPT_INCR('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"), OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index ed9b5b6..9f0cfa0 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -71,7 +71,7 @@ static int thread_num = 0; static bool inherit = false; static int profile_cpu = -1; static int nr_cpus = 0; -static unsigned int realtime_prio = 0; +static int realtime_prio = 0; static bool group = false; static unsigned int page_size; static unsigned int mmap_pages = 16; @@ -1357,8 +1357,7 @@ static const struct option options[] = { "file", "vmlinux pathname"), OPT_BOOLEAN('K', "hide_kernel_symbols", &hide_kernel_symbols, "hide kernel symbols"), - OPT_INTEGER('m', "mmap-pages", &mmap_pages, - "number of mmap data pages"), + OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"), OPT_INTEGER('r', "realtime", &realtime_prio, "collect data with this RT SCHED_FIFO priority"), OPT_INTEGER('d', "delay", &delay_secs, diff --git a/tools/perf/util/include/linux/kernel.h b/tools/perf/util/include/linux/kernel.h index 388ab1b..1eb804f 100644 --- a/tools/perf/util/include/linux/kernel.h +++ b/tools/perf/util/include/linux/kernel.h @@ -28,6 +28,8 @@ (type *)((char *)__mptr - offsetof(type, member)); }) #endif +#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); })) + #ifndef max #define max(x, y) ({ \ typeof(x) _max1 = (x); \ diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h index c6aa4ee..9ca348e 100644 --- a/tools/perf/util/parse-options.h +++ b/tools/perf/util/parse-options.h @@ -1,6 +1,8 @@ #ifndef __PERF_PARSE_OPTIONS_H #define __PERF_PARSE_OPTIONS_H +#include + enum parse_opt_type { /* special types */ OPTION_END, @@ -93,6 +95,8 @@ struct option { intptr_t defval; }; +#define check_vtype(v, type) ( BUILD_BUG_ON_ZERO(!__builtin_types_compatible_p(typeof(v), type)) + v ) + #define OPT_END() { .type = OPTION_END } #define OPT_ARGUMENT(l, h) { .type = OPTION_ARGUMENT, .long_name = (l), .help = (h) } #define OPT_GROUP(h) { .type = OPTION_GROUP, .help = (h) } @@ -101,8 +105,8 @@ struct option { #define OPT_INCR(s, l, v, h) { .type = OPTION_INCR, .short_name = (s), .long_name = (l), .value = (v), .help = (h) } #define OPT_SET_INT(s, l, v, h, i) { .type = OPTION_SET_INT, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (i) } #define OPT_SET_PTR(s, l, v, h, p) { .type = OPTION_SET_PTR, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (p) } -#define OPT_INTEGER(s, l, v, h) { .type = OPTION_INTEGER, .short_name = (s), .long_name = (l), .value = (v), .help = (h) } -#define OPT_UINTEGER(s, l, v, h) { .type = OPTION_UINTEGER, .short_name = (s), .long_name = (l), .value = (v), .help = (h) } +#define OPT_INTEGER(s, l, v, h) { .type = OPTION_INTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h) } +#define OPT_UINTEGER(s, l, v, h) { .type = OPTION_UINTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h) } #define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = (v), .help = (h) } #define OPT_U64(s, l, v, h) { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = (v), .help = (h) } #define OPT_STRING(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h) } -- cgit v0.10.2 From b1f3bb494e8acddeb972331c2ac642b3c7bceeb9 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 15 Oct 2009 08:42:21 +0000 Subject: m68k: Remove BKL from rtc implementations m68k does not support SMP. The access to the rtc is already serialized with local_irq_save/restore which is sufficient on UP. The open() protection in arch/m68k/mvme16x/rtc.c is not pretty but sufficient on UP and safe w/o the BKL. open() in arch/m68k/bvme6000/rtc.c can do with the same atomic logic as arch/m68k/mvme16x/rtc.c Signed-off-by: Thomas Gleixner Signed-off-by: Geert Uytterhoeven diff --git a/arch/m68k/bvme6000/rtc.c b/arch/m68k/bvme6000/rtc.c index b46ea17..cb8617b 100644 --- a/arch/m68k/bvme6000/rtc.c +++ b/arch/m68k/bvme6000/rtc.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -35,10 +34,9 @@ static unsigned char days_in_mo[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; -static char rtc_status; +static atomic_t rtc_status = ATOMIC_INIT(1); -static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) +static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE; unsigned char msr; @@ -132,29 +130,20 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, } /* - * We enforce only one user at a time here with the open/close. - * Also clear the previous interrupt data on an open, and clean - * up things on a close. + * We enforce only one user at a time here with the open/close. */ - static int rtc_open(struct inode *inode, struct file *file) { - lock_kernel(); - if(rtc_status) { - unlock_kernel(); + if (!atomic_dec_and_test(&rtc_status)) { + atomic_inc(&rtc_status); return -EBUSY; } - - rtc_status = 1; - unlock_kernel(); return 0; } static int rtc_release(struct inode *inode, struct file *file) { - lock_kernel(); - rtc_status = 0; - unlock_kernel(); + atomic_inc(&rtc_status); return 0; } @@ -163,9 +152,9 @@ static int rtc_release(struct inode *inode, struct file *file) */ static const struct file_operations rtc_fops = { - .ioctl = rtc_ioctl, - .open = rtc_open, - .release = rtc_release, + .unlocked_ioctl = rtc_ioctl, + .open = rtc_open, + .release = rtc_release, }; static struct miscdevice rtc_dev = { diff --git a/arch/m68k/mvme16x/rtc.c b/arch/m68k/mvme16x/rtc.c index 8da9c25..11ac6f6 100644 --- a/arch/m68k/mvme16x/rtc.c +++ b/arch/m68k/mvme16x/rtc.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -36,8 +35,7 @@ static const unsigned char days_in_mo[] = static atomic_t rtc_ready = ATOMIC_INIT(1); -static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) +static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { volatile MK48T08ptr_t rtc = (MK48T08ptr_t)MVME_RTC_BASE; unsigned long flags; @@ -120,22 +118,15 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, } /* - * We enforce only one user at a time here with the open/close. - * Also clear the previous interrupt data on an open, and clean - * up things on a close. + * We enforce only one user at a time here with the open/close. */ - static int rtc_open(struct inode *inode, struct file *file) { - lock_kernel(); if( !atomic_dec_and_test(&rtc_ready) ) { atomic_inc( &rtc_ready ); - unlock_kernel(); return -EBUSY; } - unlock_kernel(); - return 0; } @@ -150,9 +141,9 @@ static int rtc_release(struct inode *inode, struct file *file) */ static const struct file_operations rtc_fops = { - .ioctl = rtc_ioctl, - .open = rtc_open, - .release = rtc_release, + .unlocked_ioctl = rtc_ioctl, + .open = rtc_open, + .release = rtc_release, }; static struct miscdevice rtc_dev= -- cgit v0.10.2 From 291d7e9553fef2e18825b1ef1345fbd316dff98f Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" Date: Thu, 31 Dec 2009 15:35:44 -0500 Subject: m68k: Simplify param.h by using Signed-off-by: Robert P. J. Day Signed-off-by: Geert Uytterhoeven diff --git a/arch/m68k/include/asm/param.h b/arch/m68k/include/asm/param.h index 85c41b7..36265cc 100644 --- a/arch/m68k/include/asm/param.h +++ b/arch/m68k/include/asm/param.h @@ -1,26 +1,12 @@ #ifndef _M68K_PARAM_H #define _M68K_PARAM_H -#ifdef __KERNEL__ -# define HZ CONFIG_HZ /* Internal kernel timer frequency */ -# define USER_HZ 100 /* .. some user interfaces are in "ticks" */ -# define CLOCKS_PER_SEC (USER_HZ) /* like times() */ -#endif - -#ifndef HZ -#define HZ 100 -#endif - #ifdef __uClinux__ #define EXEC_PAGESIZE 4096 #else #define EXEC_PAGESIZE 8192 #endif -#ifndef NOGROUP -#define NOGROUP (-1) -#endif - -#define MAXHOSTNAMELEN 64 /* max length of hostname */ +#include #endif /* _M68K_PARAM_H */ -- cgit v0.10.2 From b9b0d8b430ebd61d32e2a9544e75a3c4b10cddcd Mon Sep 17 00:00:00 2001 From: Frans Pop Date: Sat, 6 Feb 2010 18:47:11 +0100 Subject: m68k: Remove trailing spaces in messages Signed-off-by: Frans Pop Signed-off-by: Geert Uytterhoeven diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c index aacd6d1..ada4f4c 100644 --- a/arch/m68k/kernel/traps.c +++ b/arch/m68k/kernel/traps.c @@ -455,7 +455,7 @@ static inline void access_error040(struct frame *fp) if (do_page_fault(&fp->ptregs, addr, errorcode)) { #ifdef DEBUG - printk("do_page_fault() !=0 \n"); + printk("do_page_fault() !=0\n"); #endif if (user_mode(&fp->ptregs)){ /* delay writebacks after signal delivery */ diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c index 0356da9..1c16b1b 100644 --- a/arch/m68k/mac/config.c +++ b/arch/m68k/mac/config.c @@ -148,7 +148,7 @@ static void mac_cache_card_flush(int writeback) void __init config_mac(void) { if (!MACH_IS_MAC) - printk(KERN_ERR "ERROR: no Mac, but config_mac() called!! \n"); + printk(KERN_ERR "ERROR: no Mac, but config_mac() called!!\n"); mach_sched_init = mac_sched_init; mach_init_IRQ = mac_init_IRQ; @@ -867,7 +867,7 @@ static void __init mac_identify(void) */ iop_preinit(); - printk(KERN_INFO "Detected Macintosh model: %d \n", model); + printk(KERN_INFO "Detected Macintosh model: %d\n", model); /* * Report booter data: @@ -878,12 +878,12 @@ static void __init mac_identify(void) mac_bi_data.videoaddr, mac_bi_data.videorow, mac_bi_data.videodepth, mac_bi_data.dimensions & 0xFFFF, mac_bi_data.dimensions >> 16); - printk(KERN_DEBUG " Videological 0x%lx phys. 0x%lx, SCC at 0x%lx \n", + printk(KERN_DEBUG " Videological 0x%lx phys. 0x%lx, SCC at 0x%lx\n", mac_bi_data.videological, mac_orig_videoaddr, mac_bi_data.sccbase); - printk(KERN_DEBUG " Boottime: 0x%lx GMTBias: 0x%lx \n", + printk(KERN_DEBUG " Boottime: 0x%lx GMTBias: 0x%lx\n", mac_bi_data.boottime, mac_bi_data.gmtbias); - printk(KERN_DEBUG " Machine ID: %ld CPUid: 0x%lx memory size: 0x%lx \n", + printk(KERN_DEBUG " Machine ID: %ld CPUid: 0x%lx memory size: 0x%lx\n", mac_bi_data.id, mac_bi_data.cpuid, mac_bi_data.memsize); iop_init(); diff --git a/arch/m68k/q40/config.c b/arch/m68k/q40/config.c index 31ab3f0..ad10fec 100644 --- a/arch/m68k/q40/config.c +++ b/arch/m68k/q40/config.c @@ -126,7 +126,7 @@ static void q40_reset(void) { halted = 1; printk("\n\n*******************************************\n" - "Called q40_reset : press the RESET button!! \n" + "Called q40_reset : press the RESET button!!\n" "*******************************************\n"); Q40_LED_ON(); while (1) -- cgit v0.10.2 From 9881bbb269e8f287d0e55ae3384e48b26f1872f7 Mon Sep 17 00:00:00 2001 From: Andrea Gelmini Date: Sat, 27 Feb 2010 17:51:33 +0100 Subject: m68k: hp300 - Checkpatch cleanup arch/m68k/hp300/time.h:2: WARNING: space prohibited between function name and open parenthesis '(' Signed-off-by: Andrea Gelmini Signed-off-by: Geert Uytterhoeven diff --git a/arch/m68k/hp300/time.h b/arch/m68k/hp300/time.h index f5b3d09..7b98242 100644 --- a/arch/m68k/hp300/time.h +++ b/arch/m68k/hp300/time.h @@ -1,4 +1,2 @@ extern void hp300_sched_init(irq_handler_t vector); -extern unsigned long hp300_gettimeoffset (void); - - +extern unsigned long hp300_gettimeoffset(void); -- cgit v0.10.2 From b52dd0077cde89111c00efc73a8db07f50ebb3e8 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 28 Feb 2010 13:06:27 +0100 Subject: m68k: Implement generic_find_next_{zero_,}le_bit() linux-next: fs/udf/balloc.c: In function 'udf_bitmap_new_block': fs/udf/balloc.c:274: error: implicit declaration of function 'generic_find_next_le_bit' Convert ext2_find_next_{zero_,}bit() into generic_find_next_{zero_,}le_bit(), and wrap the ext2_find_next_{zero_,}bit() around the latter. Signed-off-by: Geert Uytterhoeven diff --git a/arch/m68k/include/asm/bitops_mm.h b/arch/m68k/include/asm/bitops_mm.h index 9bde784..b4ecdaa 100644 --- a/arch/m68k/include/asm/bitops_mm.h +++ b/arch/m68k/include/asm/bitops_mm.h @@ -365,6 +365,10 @@ static inline int minix_test_bit(int nr, const void *vaddr) #define ext2_set_bit_atomic(lock, nr, addr) test_and_set_bit((nr) ^ 24, (unsigned long *)(addr)) #define ext2_clear_bit(nr, addr) __test_and_clear_bit((nr) ^ 24, (unsigned long *)(addr)) #define ext2_clear_bit_atomic(lock, nr, addr) test_and_clear_bit((nr) ^ 24, (unsigned long *)(addr)) +#define ext2_find_next_zero_bit(addr, size, offset) \ + generic_find_next_zero_le_bit((unsigned long *)addr, size, offset) +#define ext2_find_next_bit(addr, size, offset) \ + generic_find_next_le_bit((unsigned long *)addr, size, offset) static inline int ext2_test_bit(int nr, const void *vaddr) { @@ -394,10 +398,9 @@ static inline int ext2_find_first_zero_bit(const void *vaddr, unsigned size) return (p - addr) * 32 + res; } -static inline int ext2_find_next_zero_bit(const void *vaddr, unsigned size, - unsigned offset) +static inline unsigned long generic_find_next_zero_le_bit(const unsigned long *addr, + unsigned long size, unsigned long offset) { - const unsigned long *addr = vaddr; const unsigned long *p = addr + (offset >> 5); int bit = offset & 31UL, res; @@ -437,10 +440,9 @@ static inline int ext2_find_first_bit(const void *vaddr, unsigned size) return (p - addr) * 32 + res; } -static inline int ext2_find_next_bit(const void *vaddr, unsigned size, - unsigned offset) +static inline unsigned long generic_find_next_le_bit(const unsigned long *addr, + unsigned long size, unsigned long offset) { - const unsigned long *addr = vaddr; const unsigned long *p = addr + (offset >> 5); int bit = offset & 31UL, res; -- cgit v0.10.2 From 8035458fbb567ae138c77a5f710050107c6a7066 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 17 May 2010 15:51:10 -0300 Subject: perf options: Type check OPT_BOOLEAN and fix the offenders MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index a4c7cae..b1c6b38 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -22,8 +22,8 @@ static char *file_name; static char name_buffer[256]; -int perf_host = 1; -int perf_guest; +bool perf_host = 1; +bool perf_guest; static const char * const kvm_usage[] = { "perf kvm [] {top|record|report|diff|buildid-list}", diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index e18dfdc..821c158 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c @@ -792,8 +792,7 @@ static void print_result(void) print_bad_events(bad, total); } -static int info_threads; -static int info_map; +static bool info_threads, info_map; static void dump_threads(void) { diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c index 0339612..035b9fa 100644 --- a/tools/perf/builtin-test.c +++ b/tools/perf/builtin-test.c @@ -257,7 +257,7 @@ static const char * const test_usage[] = { }; static const struct option test_options[] = { - OPT_BOOLEAN('v', "verbose", &verbose, + OPT_INTEGER('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"), OPT_END() }; diff --git a/tools/perf/perf.h b/tools/perf/perf.h index 02821fe..ef7aa0a 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h @@ -80,6 +80,7 @@ void get_term_dimensions(struct winsize *ws); #include "../../include/linux/perf_event.h" #include "util/types.h" +#include /* * prctl(PR_TASK_PERF_EVENTS_DISABLE) will (cheaply) disable all @@ -131,6 +132,6 @@ struct ip_callchain { u64 ips[0]; }; -extern int perf_host, perf_guest; +extern bool perf_host, perf_guest; #endif diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h index 9ca348e..5838e2d 100644 --- a/tools/perf/util/parse-options.h +++ b/tools/perf/util/parse-options.h @@ -2,6 +2,7 @@ #define __PERF_PARSE_OPTIONS_H #include +#include enum parse_opt_type { /* special types */ @@ -101,7 +102,7 @@ struct option { #define OPT_ARGUMENT(l, h) { .type = OPTION_ARGUMENT, .long_name = (l), .help = (h) } #define OPT_GROUP(h) { .type = OPTION_GROUP, .help = (h) } #define OPT_BIT(s, l, v, h, b) { .type = OPTION_BIT, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (b) } -#define OPT_BOOLEAN(s, l, v, h) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = (v), .help = (h) } +#define OPT_BOOLEAN(s, l, v, h) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = check_vtype(v, bool *), .help = (h) } #define OPT_INCR(s, l, v, h) { .type = OPTION_INCR, .short_name = (s), .long_name = (l), .value = (v), .help = (h) } #define OPT_SET_INT(s, l, v, h, i) { .type = OPTION_SET_INT, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (i) } #define OPT_SET_PTR(s, l, v, h, p) { .type = OPTION_SET_PTR, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (p) } -- cgit v0.10.2 From edb7c60e27c1baff38d82440dc52eaffac9a45f4 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 17 May 2010 16:22:41 -0300 Subject: perf options: Type check all the remaining OPT_ variants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OPT_SET_INT was renamed to OPT_SET_UINT since the only use in these tools is to set something that has an enum type, that is builtin compatible with unsigned int. Several string constifications were done to make OPT_STRING require a const char * type. Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Tom Zanussi LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c index 4699677..fcb9626 100644 --- a/tools/perf/builtin-bench.c +++ b/tools/perf/builtin-bench.c @@ -95,7 +95,7 @@ static void dump_suites(int subsys_index) return; } -static char *bench_format_str; +static const char *bench_format_str; int bench_format = BENCH_FORMAT_DEFAULT; static const struct option bench_options[] = { @@ -126,7 +126,7 @@ static void print_usage(void) printf("\n"); } -static int bench_str2int(char *str) +static int bench_str2int(const char *str) { if (!str) return BENCH_FORMAT_DEFAULT; diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c index 81e3ecc..6d5a8a7 100644 --- a/tools/perf/builtin-help.c +++ b/tools/perf/builtin-help.c @@ -33,10 +33,10 @@ static bool show_all = false; static enum help_format help_format = HELP_FORMAT_MAN; static struct option builtin_help_options[] = { OPT_BOOLEAN('a', "all", &show_all, "print all available commands"), - OPT_SET_INT('m', "man", &help_format, "show man page", HELP_FORMAT_MAN), - OPT_SET_INT('w', "web", &help_format, "show manual in web browser", + OPT_SET_UINT('m', "man", &help_format, "show man page", HELP_FORMAT_MAN), + OPT_SET_UINT('w', "web", &help_format, "show manual in web browser", HELP_FORMAT_WEB), - OPT_SET_INT('i', "info", &help_format, "show info page", + OPT_SET_UINT('i', "info", &help_format, "show info page", HELP_FORMAT_INFO), OPT_END(), }; diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index b1c6b38..34d1e85 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -19,7 +19,7 @@ #include #include -static char *file_name; +static const char *file_name; static char name_buffer[256]; bool perf_host = 1; diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 6826512..1d3c100 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -39,8 +39,8 @@ static bool dont_use_callchains; static bool show_threads; static struct perf_read_values show_threads_values; -static char default_pretty_printing_style[] = "normal"; -static char *pretty_printing_style = default_pretty_printing_style; +static const char default_pretty_printing_style[] = "normal"; +static const char *pretty_printing_style = default_pretty_printing_style; static char callchain_default_opt[] = "fractal,0.5"; diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index c80acdf..f67bce2 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -22,7 +22,7 @@ static char const *input_name = "perf.data"; static char default_sort_order[] = "avg, max, switch, runtime"; -static char *sort_order = default_sort_order; +static const char *sort_order = default_sort_order; static int profile_cpu = -1; diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 9f0cfa0..397290a 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -96,7 +96,7 @@ struct source_line { struct source_line *next; }; -static char *sym_filter = NULL; +static const char *sym_filter = NULL; struct sym_entry *sym_filter_entry = NULL; struct sym_entry *sym_filter_entry_sched = NULL; static int sym_pcnt_filter = 5; diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index f75c5f6..9a71c94 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -662,7 +662,7 @@ size_t hists__fprintf(struct hists *self, struct hists *pair, long displacement = 0; unsigned int width; const char *sep = symbol_conf.field_sep; - char *col_width = symbol_conf.col_width_list_str; + const char *col_width = symbol_conf.col_width_list_str; init_rem_hits(); diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c index 36d955e..99d02aa 100644 --- a/tools/perf/util/parse-options.c +++ b/tools/perf/util/parse-options.c @@ -51,7 +51,7 @@ static int get_value(struct parse_opt_ctx_t *p, case OPTION_BOOLEAN: case OPTION_INCR: case OPTION_BIT: - case OPTION_SET_INT: + case OPTION_SET_UINT: case OPTION_SET_PTR: return opterror(opt, "takes no value", flags); case OPTION_END: @@ -83,8 +83,8 @@ static int get_value(struct parse_opt_ctx_t *p, *(int *)opt->value = unset ? 0 : *(int *)opt->value + 1; return 0; - case OPTION_SET_INT: - *(int *)opt->value = unset ? 0 : opt->defval; + case OPTION_SET_UINT: + *(unsigned int *)opt->value = unset ? 0 : opt->defval; return 0; case OPTION_SET_PTR: @@ -515,13 +515,13 @@ int usage_with_options_internal(const char * const *usagestr, pos += fprintf(stderr, " ..."); } break; - default: /* OPTION_{BIT,BOOLEAN,SET_INT,SET_PTR} */ + default: /* OPTION_{BIT,BOOLEAN,SET_UINT,SET_PTR} */ case OPTION_END: case OPTION_GROUP: case OPTION_BIT: case OPTION_BOOLEAN: case OPTION_INCR: - case OPTION_SET_INT: + case OPTION_SET_UINT: case OPTION_SET_PTR: break; } diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h index 5838e2d..c7d72dc 100644 --- a/tools/perf/util/parse-options.h +++ b/tools/perf/util/parse-options.h @@ -13,7 +13,7 @@ enum parse_opt_type { OPTION_BIT, OPTION_BOOLEAN, OPTION_INCR, - OPTION_SET_INT, + OPTION_SET_UINT, OPTION_SET_PTR, /* options with arguments (usually) */ OPTION_STRING, @@ -79,7 +79,7 @@ typedef int parse_opt_cb(const struct option *, const char *arg, int unset); * * `defval`:: * default value to fill (*->value) with for PARSE_OPT_OPTARG. - * OPTION_{BIT,SET_INT,SET_PTR} store the {mask,integer,pointer} to put in + * OPTION_{BIT,SET_UINT,SET_PTR} store the {mask,integer,pointer} to put in * the value when met. * CALLBACKS can use it like they want. */ @@ -101,16 +101,16 @@ struct option { #define OPT_END() { .type = OPTION_END } #define OPT_ARGUMENT(l, h) { .type = OPTION_ARGUMENT, .long_name = (l), .help = (h) } #define OPT_GROUP(h) { .type = OPTION_GROUP, .help = (h) } -#define OPT_BIT(s, l, v, h, b) { .type = OPTION_BIT, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (b) } +#define OPT_BIT(s, l, v, h, b) { .type = OPTION_BIT, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h), .defval = (b) } #define OPT_BOOLEAN(s, l, v, h) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = check_vtype(v, bool *), .help = (h) } -#define OPT_INCR(s, l, v, h) { .type = OPTION_INCR, .short_name = (s), .long_name = (l), .value = (v), .help = (h) } -#define OPT_SET_INT(s, l, v, h, i) { .type = OPTION_SET_INT, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (i) } +#define OPT_INCR(s, l, v, h) { .type = OPTION_INCR, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h) } +#define OPT_SET_UINT(s, l, v, h, i) { .type = OPTION_SET_UINT, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h), .defval = (i) } #define OPT_SET_PTR(s, l, v, h, p) { .type = OPTION_SET_PTR, .short_name = (s), .long_name = (l), .value = (v), .help = (h), .defval = (p) } #define OPT_INTEGER(s, l, v, h) { .type = OPTION_INTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h) } #define OPT_UINTEGER(s, l, v, h) { .type = OPTION_UINTEGER, .short_name = (s), .long_name = (l), .value = check_vtype(v, unsigned int *), .help = (h) } -#define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = (v), .help = (h) } -#define OPT_U64(s, l, v, h) { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = (v), .help = (h) } -#define OPT_STRING(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = (v), (a), .help = (h) } +#define OPT_LONG(s, l, v, h) { .type = OPTION_LONG, .short_name = (s), .long_name = (l), .value = check_vtype(v, long *), .help = (h) } +#define OPT_U64(s, l, v, h) { .type = OPTION_U64, .short_name = (s), .long_name = (l), .value = check_vtype(v, u64 *), .help = (h) } +#define OPT_STRING(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h) } #define OPT_DATE(s, l, v, h) \ { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb } #define OPT_CALLBACK(s, l, v, a, h, f) \ diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index da30b30..2316cb5 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -1,10 +1,10 @@ #include "sort.h" regex_t parent_regex; -char default_parent_pattern[] = "^sys_|^do_page_fault"; -char *parent_pattern = default_parent_pattern; -char default_sort_order[] = "comm,dso,symbol"; -char *sort_order = default_sort_order; +const char default_parent_pattern[] = "^sys_|^do_page_fault"; +const char *parent_pattern = default_parent_pattern; +const char default_sort_order[] = "comm,dso,symbol"; +const char *sort_order = default_sort_order; int sort__need_collapse = 0; int sort__has_parent = 0; diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index eab2e0b3..0d61c40 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h @@ -25,10 +25,10 @@ #include "sort.h" extern regex_t parent_regex; -extern char *sort_order; -extern char default_parent_pattern[]; -extern char *parent_pattern; -extern char default_sort_order[]; +extern const char *sort_order; +extern const char default_parent_pattern[]; +extern const char *parent_pattern; +extern const char default_sort_order[]; extern int sort__need_collapse; extern int sort__has_parent; extern char *field_sep; diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 6389d1a..032469e 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -78,7 +78,7 @@ struct symbol_conf { *default_guest_kallsyms, *default_guest_modules; const char *guestmount; - char *dso_list_str, + const char *dso_list_str, *comm_list_str, *sym_list_str, *col_width_list_str; -- cgit v0.10.2 From f3c7f317c91e45aac0ef9d0b6474cd4637de69f0 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 14 Apr 2010 18:48:50 +0200 Subject: serial167: Kill unused variables commits 638157bc1461f6718eeca06bedd9a09cf1f35c36 ("serial167: prepare to push BKL down into drivers") and 4165fe4ef7305609a96c7f248cefb9c414d0ede5 ("tty: Fix up char drivers request_room usage") removed code without removing the corresponding variables: | drivers/char/serial167.c: In function 'cd2401_rx_interrupt': | drivers/char/serial167.c:630: warning: unused variable 'len' | drivers/char/serial167.c: In function 'cy_ioctl': | drivers/char/serial167.c:1531: warning: unused variable 'val' Remove the variables to kill the warnings. Signed-off-by: Geert Uytterhoeven diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index 8dfd247..78a62eb 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c @@ -627,7 +627,6 @@ static irqreturn_t cd2401_rx_interrupt(int irq, void *dev_id) char data; int char_count; int save_cnt; - int len; /* determine the channel and change to that context */ channel = (u_short) (base_addr[CyLICR] >> 2); @@ -1528,7 +1527,6 @@ static int cy_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { - unsigned long val; struct cyclades_port *info = tty->driver_data; int ret_val = 0; void __user *argp = (void __user *)arg; -- cgit v0.10.2 From adbf6e6952e80ae42a403442dcae21438cae94b3 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Fri, 23 Apr 2010 02:06:20 +1000 Subject: m68k: invoke oom-killer from page fault As explained in commit 1c0fe6e3bd, we want to call the architecture independent oom killer when getting an unexplained OOM from handle_mm_fault, rather than simply killing current. Cc: linux-m68k@lists.linux-m68k.org Cc: Geert Uytterhoeven Cc: linux-arch@vger.kernel.org Signed-off-by: Nick Piggin Acked-by: David Rientjes [Geert] Kill 2 introduced compiler warnings Signed-off-by: Geert Uytterhoeven diff --git a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c index d0e35cf..a96394a 100644 --- a/arch/m68k/mm/fault.c +++ b/arch/m68k/mm/fault.c @@ -154,7 +154,6 @@ good_area: * the fault. */ - survive: fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0); #ifdef DEBUG printk("handle_mm_fault returns %d\n",fault); @@ -180,15 +179,10 @@ good_area: */ out_of_memory: up_read(&mm->mmap_sem); - if (is_global_init(current)) { - yield(); - down_read(&mm->mmap_sem); - goto survive; - } - - printk("VM: killing process %s\n", current->comm); - if (user_mode(regs)) - do_group_exit(SIGKILL); + if (!user_mode(regs)) + goto no_context; + pagefault_out_of_memory(); + return 0; no_context: current->thread.signo = SIGBUS; -- cgit v0.10.2 From 0b7f1a7efb38b551f5948a13d0b36e876ba536db Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 28 Jan 2009 21:01:02 +0100 Subject: platform: Make platform resource input parameters const Make the platform resource input parameters of platform_device_add_resources() and platform_device_register_simple() const, as the resources are copied and never modified. Signed-off-by: Geert Uytterhoeven Acked-by: Greg Kroah-Hartman diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 4b4b565..c5fbe19 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -187,7 +187,7 @@ EXPORT_SYMBOL_GPL(platform_device_alloc); * released. */ int platform_device_add_resources(struct platform_device *pdev, - struct resource *res, unsigned int num) + const struct resource *res, unsigned int num) { struct resource *r; @@ -367,7 +367,7 @@ EXPORT_SYMBOL_GPL(platform_device_unregister); */ struct platform_device *platform_device_register_simple(const char *name, int id, - struct resource *res, + const struct resource *res, unsigned int num) { struct platform_device *pdev; diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 212da17..5417944 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -44,12 +44,14 @@ extern int platform_get_irq_byname(struct platform_device *, const char *); extern int platform_add_devices(struct platform_device **, int); extern struct platform_device *platform_device_register_simple(const char *, int id, - struct resource *, unsigned int); + const struct resource *, unsigned int); extern struct platform_device *platform_device_register_data(struct device *, const char *, int, const void *, size_t); extern struct platform_device *platform_device_alloc(const char *name, int id); -extern int platform_device_add_resources(struct platform_device *pdev, struct resource *res, unsigned int num); +extern int platform_device_add_resources(struct platform_device *pdev, + const struct resource *res, + unsigned int num); extern int platform_device_add_data(struct platform_device *pdev, const void *data, size_t size); extern int platform_device_add(struct platform_device *pdev); extern void platform_device_del(struct platform_device *pdev); -- cgit v0.10.2 From bf54a2b3c0dbf76136f00ff785bf6d8f6291311d Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 18 Nov 2008 21:13:53 +0100 Subject: m68k: amiga - Zorro bus modalias support Add Amiga Zorro bus modalias and uevent support Signed-off-by: Geert Uytterhoeven diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c index ed5e974..a8f0512 100644 --- a/drivers/net/a2065.c +++ b/drivers/net/a2065.c @@ -674,6 +674,7 @@ static struct zorro_device_id a2065_zorro_tbl[] __devinitdata = { { ZORRO_PROD_AMERISTAR_A2065 }, { 0 } }; +MODULE_DEVICE_TABLE(zorro, a2065_zorro_tbl); static struct zorro_driver a2065_driver = { .name = "a2065", diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c index fa1a235..4b30a46 100644 --- a/drivers/net/ariadne.c +++ b/drivers/net/ariadne.c @@ -145,6 +145,7 @@ static struct zorro_device_id ariadne_zorro_tbl[] __devinitdata = { { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE }, { 0 } }; +MODULE_DEVICE_TABLE(zorro, ariadne_zorro_tbl); static struct zorro_driver ariadne_driver = { .name = "ariadne", diff --git a/drivers/net/hydra.c b/drivers/net/hydra.c index 24724b4..07d8e5b 100644 --- a/drivers/net/hydra.c +++ b/drivers/net/hydra.c @@ -71,6 +71,7 @@ static struct zorro_device_id hydra_zorro_tbl[] __devinitdata = { { ZORRO_PROD_HYDRA_SYSTEMS_AMIGANET }, { 0 } }; +MODULE_DEVICE_TABLE(zorro, hydra_zorro_tbl); static struct zorro_driver hydra_driver = { .name = "hydra", diff --git a/drivers/net/zorro8390.c b/drivers/net/zorro8390.c index 81c753a..9548cbb 100644 --- a/drivers/net/zorro8390.c +++ b/drivers/net/zorro8390.c @@ -102,6 +102,7 @@ static struct zorro_device_id zorro8390_zorro_tbl[] __devinitdata = { { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, }, { 0 } }; +MODULE_DEVICE_TABLE(zorro, zorro8390_zorro_tbl); static struct zorro_driver zorro8390_driver = { .name = "zorro8390", diff --git a/drivers/scsi/zorro7xx.c b/drivers/scsi/zorro7xx.c index 105449c..e17764d 100644 --- a/drivers/scsi/zorro7xx.c +++ b/drivers/scsi/zorro7xx.c @@ -69,6 +69,7 @@ static struct zorro_device_id zorro7xx_zorro_tbl[] __devinitdata = { }, { 0 } }; +MODULE_DEVICE_TABLE(zorro, zorro7xx_zorro_tbl); static int __devinit zorro7xx_init_one(struct zorro_dev *z, const struct zorro_device_id *ent) diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index 8d8dfda..6df7c54 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c @@ -299,6 +299,7 @@ static const struct zorro_device_id cirrusfb_zorro_table[] = { }, { 0 } }; +MODULE_DEVICE_TABLE(zorro, cirrusfb_zorro_table); static const struct { zorro_id id2; diff --git a/drivers/video/fm2fb.c b/drivers/video/fm2fb.c index 6c91c61..1b0feb8 100644 --- a/drivers/video/fm2fb.c +++ b/drivers/video/fm2fb.c @@ -219,6 +219,7 @@ static struct zorro_device_id fm2fb_devices[] __devinitdata = { { ZORRO_PROD_HELFRICH_RAINBOW_II }, { 0 } }; +MODULE_DEVICE_TABLE(zorro, fm2fb_devices); static struct zorro_driver fm2fb_driver = { .name = "fm2fb", diff --git a/drivers/zorro/zorro-driver.c b/drivers/zorro/zorro-driver.c index 53180a3..7ee2b6e 100644 --- a/drivers/zorro/zorro-driver.c +++ b/drivers/zorro/zorro-driver.c @@ -137,10 +137,34 @@ static int zorro_bus_match(struct device *dev, struct device_driver *drv) return 0; } +static int zorro_uevent(struct device *dev, struct kobj_uevent_env *env) +{ +#ifdef CONFIG_HOTPLUG + struct zorro_dev *z; + + if (!dev) + return -ENODEV; + + z = to_zorro_dev(dev); + if (!z) + return -ENODEV; + + if (add_uevent_var(env, "ZORRO_ID=%08X", z->id) || + add_uevent_var(env, "ZORRO_SLOT_NAME=%s", dev_name(dev)) || + add_uevent_var(env, "ZORRO_SLOT_ADDR=%04X", z->slotaddr) || + add_uevent_var(env, "MODALIAS=" ZORRO_DEVICE_MODALIAS_FMT, z->id)) + return -ENOMEM; + + return 0; +#else /* !CONFIG_HOTPLUG */ + return -ENODEV; +#endif /* !CONFIG_HOTPLUG */ +} struct bus_type zorro_bus_type = { .name = "zorro", .match = zorro_bus_match, + .uevent = zorro_uevent, .probe = zorro_device_probe, .remove = zorro_device_remove, }; diff --git a/drivers/zorro/zorro-sysfs.c b/drivers/zorro/zorro-sysfs.c index 1d2a772e..eb924e0 100644 --- a/drivers/zorro/zorro-sysfs.c +++ b/drivers/zorro/zorro-sysfs.c @@ -77,6 +77,16 @@ static struct bin_attribute zorro_config_attr = { .read = zorro_read_config, }; +static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct zorro_dev *z = to_zorro_dev(dev); + + return sprintf(buf, ZORRO_DEVICE_MODALIAS_FMT "\n", z->id); +} + +static DEVICE_ATTR(modalias, S_IRUGO, modalias_show, NULL); + int zorro_create_sysfs_dev_files(struct zorro_dev *z) { struct device *dev = &z->dev; @@ -89,6 +99,7 @@ int zorro_create_sysfs_dev_files(struct zorro_dev *z) (error = device_create_file(dev, &dev_attr_slotaddr)) || (error = device_create_file(dev, &dev_attr_slotsize)) || (error = device_create_file(dev, &dev_attr_resource)) || + (error = device_create_file(dev, &dev_attr_modalias)) || (error = sysfs_create_bin_file(&dev->kobj, &zorro_config_attr))) return error; diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index f58e9d83..56fde43 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -474,4 +474,13 @@ struct platform_device_id { __attribute__((aligned(sizeof(kernel_ulong_t)))); }; +struct zorro_device_id { + __u32 id; /* Device ID or ZORRO_WILDCARD */ + kernel_ulong_t driver_data; /* Data private to the driver */ +}; + +#define ZORRO_WILDCARD (0xffffffff) /* not official */ + +#define ZORRO_DEVICE_MODALIAS_FMT "zorro:i%08X" + #endif /* LINUX_MOD_DEVICETABLE_H */ diff --git a/include/linux/zorro.h b/include/linux/zorro.h index 913bfc2..908db1b 100644 --- a/include/linux/zorro.h +++ b/include/linux/zorro.h @@ -38,8 +38,6 @@ typedef __u32 zorro_id; -#define ZORRO_WILDCARD (0xffffffff) /* not official */ - /* Include the ID list */ #include @@ -116,6 +114,7 @@ struct ConfigDev { #include #include +#include #include @@ -155,16 +154,6 @@ extern struct bus_type zorro_bus_type; /* - * Zorro device IDs - */ - -struct zorro_device_id { - zorro_id id; /* Device ID or ZORRO_WILDCARD */ - unsigned long driver_data; /* Data private to the driver */ -}; - - - /* * Zorro device drivers */ diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 220213e..df90f31 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -796,6 +796,16 @@ static int do_platform_entry(const char *filename, return 1; } +/* Looks like: zorro:iN. */ +static int do_zorro_entry(const char *filename, struct zorro_device_id *id, + char *alias) +{ + id->id = TO_NATIVE(id->id); + strcpy(alias, "zorro:"); + ADD(alias, "i", id->id != ZORRO_WILDCARD, id->id); + return 1; +} + /* Ignore any prefix, eg. some architectures prepend _ */ static inline int sym_is(const char *symbol, const char *name) { @@ -943,6 +953,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, do_table(symval, sym->st_size, sizeof(struct platform_device_id), "platform", do_platform_entry, mod); + else if (sym_is(symname, "__mod_zorro_device_table")) + do_table(symval, sym->st_size, + sizeof(struct zorro_device_id), "zorro", + do_zorro_entry, mod); free(zeros); } -- cgit v0.10.2 From 0d305464aefff342c85b4db8b3d7a4345246e5a1 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 5 Apr 2009 12:40:41 +0200 Subject: m68k: amiga - Zorro host bridge platform device conversion Signed-off-by: Geert Uytterhoeven diff --git a/arch/m68k/amiga/Makefile b/arch/m68k/amiga/Makefile index 6a0d765..11dd30b 100644 --- a/arch/m68k/amiga/Makefile +++ b/arch/m68k/amiga/Makefile @@ -2,6 +2,6 @@ # Makefile for Linux arch/m68k/amiga source directory # -obj-y := config.o amiints.o cia.o chipram.o amisound.o +obj-y := config.o amiints.o cia.o chipram.o amisound.o platform.o obj-$(CONFIG_AMIGA_PCMCIA) += pcmcia.o diff --git a/arch/m68k/amiga/platform.c b/arch/m68k/amiga/platform.c new file mode 100644 index 0000000..33a7669 --- /dev/null +++ b/arch/m68k/amiga/platform.c @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2007-2009 Geert Uytterhoeven + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + */ + +#include +#include +#include + +#include + + +#ifdef CONFIG_ZORRO + +static const struct resource zorro_resources[] __initconst = { + /* Zorro II regions (on Zorro II/III) */ + { + .name = "Zorro II exp", + .start = 0x00e80000, + .end = 0x00efffff, + .flags = IORESOURCE_MEM, + }, { + .name = "Zorro II mem", + .start = 0x00200000, + .end = 0x009fffff, + .flags = IORESOURCE_MEM, + }, + /* Zorro III regions (on Zorro III only) */ + { + .name = "Zorro III exp", + .start = 0xff000000, + .end = 0xffffffff, + .flags = IORESOURCE_MEM, + }, { + .name = "Zorro III cfg", + .start = 0x40000000, + .end = 0x7fffffff, + .flags = IORESOURCE_MEM, + } +}; + + +static int __init amiga_init_bus(void) +{ + if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(ZORRO)) + return -ENODEV; + + platform_device_register_simple("amiga-zorro", -1, zorro_resources, + AMIGAHW_PRESENT(ZORRO3) ? 4 : 2); + return 0; +} + +subsys_initcall(amiga_init_bus); + +#endif /* CONFIG_ZORRO */ diff --git a/drivers/zorro/proc.c b/drivers/zorro/proc.c index d47c47f..3c7046d 100644 --- a/drivers/zorro/proc.c +++ b/drivers/zorro/proc.c @@ -97,7 +97,7 @@ static void zorro_seq_stop(struct seq_file *m, void *v) static int zorro_seq_show(struct seq_file *m, void *v) { - u_int slot = *(loff_t *)v; + unsigned int slot = *(loff_t *)v; struct zorro_dev *z = &zorro_autocon[slot]; seq_printf(m, "%02x\t%08x\t%08lx\t%08lx\t%02x\n", slot, z->id, @@ -129,7 +129,7 @@ static const struct file_operations zorro_devices_proc_fops = { static struct proc_dir_entry *proc_bus_zorro_dir; -static int __init zorro_proc_attach_device(u_int slot) +static int __init zorro_proc_attach_device(unsigned int slot) { struct proc_dir_entry *entry; char name[4]; @@ -146,7 +146,7 @@ static int __init zorro_proc_attach_device(u_int slot) static int __init zorro_proc_init(void) { - u_int slot; + unsigned int slot; if (MACH_IS_AMIGA && AMIGAHW_PRESENT(ZORRO)) { proc_bus_zorro_dir = proc_mkdir("bus/zorro", NULL); diff --git a/drivers/zorro/zorro.c b/drivers/zorro/zorro.c index d45fb34..6455f3a 100644 --- a/drivers/zorro/zorro.c +++ b/drivers/zorro/zorro.c @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include #include @@ -26,24 +28,17 @@ * Zorro Expansion Devices */ -u_int zorro_num_autocon = 0; +unsigned int zorro_num_autocon; struct zorro_dev zorro_autocon[ZORRO_NUM_AUTO]; /* - * Single Zorro bus + * Zorro bus */ -struct zorro_bus zorro_bus = {\ - .resources = { - /* Zorro II regions (on Zorro II/III) */ - { .name = "Zorro II exp", .start = 0x00e80000, .end = 0x00efffff }, - { .name = "Zorro II mem", .start = 0x00200000, .end = 0x009fffff }, - /* Zorro III regions (on Zorro III only) */ - { .name = "Zorro III exp", .start = 0xff000000, .end = 0xffffffff }, - { .name = "Zorro III cfg", .start = 0x40000000, .end = 0x7fffffff } - }, - .name = "Zorro bus" +struct zorro_bus { + struct list_head devices; /* list of devices on this bus */ + struct device dev; }; @@ -53,18 +48,19 @@ struct zorro_bus zorro_bus = {\ struct zorro_dev *zorro_find_device(zorro_id id, struct zorro_dev *from) { - struct zorro_dev *z; + struct zorro_dev *z; - if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(ZORRO)) - return NULL; + if (!zorro_num_autocon) + return NULL; - for (z = from ? from+1 : &zorro_autocon[0]; - z < zorro_autocon+zorro_num_autocon; - z++) - if (id == ZORRO_WILDCARD || id == z->id) - return z; - return NULL; + for (z = from ? from+1 : &zorro_autocon[0]; + z < zorro_autocon+zorro_num_autocon; + z++) + if (id == ZORRO_WILDCARD || id == z->id) + return z; + return NULL; } +EXPORT_SYMBOL(zorro_find_device); /* @@ -83,121 +79,138 @@ struct zorro_dev *zorro_find_device(zorro_id id, struct zorro_dev *from) */ DECLARE_BITMAP(zorro_unused_z2ram, 128); +EXPORT_SYMBOL(zorro_unused_z2ram); static void __init mark_region(unsigned long start, unsigned long end, int flag) { - if (flag) - start += Z2RAM_CHUNKMASK; - else - end += Z2RAM_CHUNKMASK; - start &= ~Z2RAM_CHUNKMASK; - end &= ~Z2RAM_CHUNKMASK; - - if (end <= Z2RAM_START || start >= Z2RAM_END) - return; - start = start < Z2RAM_START ? 0x00000000 : start-Z2RAM_START; - end = end > Z2RAM_END ? Z2RAM_SIZE : end-Z2RAM_START; - while (start < end) { - u32 chunk = start>>Z2RAM_CHUNKSHIFT; if (flag) - set_bit(chunk, zorro_unused_z2ram); + start += Z2RAM_CHUNKMASK; else - clear_bit(chunk, zorro_unused_z2ram); - start += Z2RAM_CHUNKSIZE; - } + end += Z2RAM_CHUNKMASK; + start &= ~Z2RAM_CHUNKMASK; + end &= ~Z2RAM_CHUNKMASK; + + if (end <= Z2RAM_START || start >= Z2RAM_END) + return; + start = start < Z2RAM_START ? 0x00000000 : start-Z2RAM_START; + end = end > Z2RAM_END ? Z2RAM_SIZE : end-Z2RAM_START; + while (start < end) { + u32 chunk = start>>Z2RAM_CHUNKSHIFT; + if (flag) + set_bit(chunk, zorro_unused_z2ram); + else + clear_bit(chunk, zorro_unused_z2ram); + start += Z2RAM_CHUNKSIZE; + } } -static struct resource __init *zorro_find_parent_resource(struct zorro_dev *z) +static struct resource __init *zorro_find_parent_resource( + struct platform_device *bridge, struct zorro_dev *z) { - int i; + int i; - for (i = 0; i < zorro_bus.num_resources; i++) - if (zorro_resource_start(z) >= zorro_bus.resources[i].start && - zorro_resource_end(z) <= zorro_bus.resources[i].end) - return &zorro_bus.resources[i]; - return &iomem_resource; + for (i = 0; i < bridge->num_resources; i++) { + struct resource *r = &bridge->resource[i]; + if (zorro_resource_start(z) >= r->start && + zorro_resource_end(z) <= r->end) + return r; + } + return &iomem_resource; } - /* - * Initialization - */ -static int __init zorro_init(void) +static int __init amiga_zorro_probe(struct platform_device *pdev) { - struct zorro_dev *z; - unsigned int i; - int error; - - if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(ZORRO)) - return 0; - - pr_info("Zorro: Probing AutoConfig expansion devices: %d device%s\n", - zorro_num_autocon, zorro_num_autocon == 1 ? "" : "s"); - - /* Initialize the Zorro bus */ - INIT_LIST_HEAD(&zorro_bus.devices); - dev_set_name(&zorro_bus.dev, "zorro"); - error = device_register(&zorro_bus.dev); - if (error) { - pr_err("Zorro: Error registering zorro_bus\n"); - return error; - } - - /* Request the resources */ - zorro_bus.num_resources = AMIGAHW_PRESENT(ZORRO3) ? 4 : 2; - for (i = 0; i < zorro_bus.num_resources; i++) - request_resource(&iomem_resource, &zorro_bus.resources[i]); - - /* Register all devices */ - for (i = 0; i < zorro_num_autocon; i++) { - z = &zorro_autocon[i]; - z->id = (z->rom.er_Manufacturer<<16) | (z->rom.er_Product<<8); - if (z->id == ZORRO_PROD_GVP_EPC_BASE) { - /* GVP quirk */ - unsigned long magic = zorro_resource_start(z)+0x8000; - z->id |= *(u16 *)ZTWO_VADDR(magic) & GVP_PRODMASK; - } - sprintf(z->name, "Zorro device %08x", z->id); - zorro_name_device(z); - z->resource.name = z->name; - if (request_resource(zorro_find_parent_resource(z), &z->resource)) - pr_err("Zorro: Address space collision on device %s %pR\n", - z->name, &z->resource); - dev_set_name(&z->dev, "%02x", i); - z->dev.parent = &zorro_bus.dev; - z->dev.bus = &zorro_bus_type; - error = device_register(&z->dev); + struct zorro_bus *bus; + struct zorro_dev *z; + struct resource *r; + unsigned int i; + int error; + + /* Initialize the Zorro bus */ + bus = kzalloc(sizeof(*bus), GFP_KERNEL); + if (!bus) + return -ENOMEM; + + INIT_LIST_HEAD(&bus->devices); + bus->dev.parent = &pdev->dev; + dev_set_name(&bus->dev, "zorro"); + error = device_register(&bus->dev); if (error) { - pr_err("Zorro: Error registering device %s\n", z->name); - continue; + pr_err("Zorro: Error registering zorro_bus\n"); + kfree(bus); + return error; } - error = zorro_create_sysfs_dev_files(z); - if (error) - dev_err(&z->dev, "Error creating sysfs files\n"); - } - - /* Mark all available Zorro II memory */ - zorro_for_each_dev(z) { - if (z->rom.er_Type & ERTF_MEMLIST) - mark_region(zorro_resource_start(z), zorro_resource_end(z)+1, 1); - } - - /* Unmark all used Zorro II memory */ - for (i = 0; i < m68k_num_memory; i++) - if (m68k_memory[i].addr < 16*1024*1024) - mark_region(m68k_memory[i].addr, - m68k_memory[i].addr+m68k_memory[i].size, 0); - - return 0; + platform_set_drvdata(pdev, bus); + + /* Register all devices */ + pr_info("Zorro: Probing AutoConfig expansion devices: %u device%s\n", + zorro_num_autocon, zorro_num_autocon == 1 ? "" : "s"); + + for (i = 0; i < zorro_num_autocon; i++) { + z = &zorro_autocon[i]; + z->id = (z->rom.er_Manufacturer<<16) | (z->rom.er_Product<<8); + if (z->id == ZORRO_PROD_GVP_EPC_BASE) { + /* GVP quirk */ + unsigned long magic = zorro_resource_start(z)+0x8000; + z->id |= *(u16 *)ZTWO_VADDR(magic) & GVP_PRODMASK; + } + sprintf(z->name, "Zorro device %08x", z->id); + zorro_name_device(z); + z->resource.name = z->name; + r = zorro_find_parent_resource(pdev, z); + error = request_resource(r, &z->resource); + if (error) + dev_err(&bus->dev, + "Address space collision on device %s %pR\n", + z->name, &z->resource); + dev_set_name(&z->dev, "%02x", i); + z->dev.parent = &bus->dev; + z->dev.bus = &zorro_bus_type; + error = device_register(&z->dev); + if (error) { + dev_err(&bus->dev, "Error registering device %s\n", + z->name); + continue; + } + error = zorro_create_sysfs_dev_files(z); + if (error) + dev_err(&z->dev, "Error creating sysfs files\n"); + } + + /* Mark all available Zorro II memory */ + zorro_for_each_dev(z) { + if (z->rom.er_Type & ERTF_MEMLIST) + mark_region(zorro_resource_start(z), + zorro_resource_end(z)+1, 1); + } + + /* Unmark all used Zorro II memory */ + for (i = 0; i < m68k_num_memory; i++) + if (m68k_memory[i].addr < 16*1024*1024) + mark_region(m68k_memory[i].addr, + m68k_memory[i].addr+m68k_memory[i].size, + 0); + + return 0; } -subsys_initcall(zorro_init); +static struct platform_driver amiga_zorro_driver = { + .driver = { + .name = "amiga-zorro", + .owner = THIS_MODULE, + }, +}; -EXPORT_SYMBOL(zorro_find_device); -EXPORT_SYMBOL(zorro_unused_z2ram); +static int __init amiga_zorro_init(void) +{ + return platform_driver_probe(&amiga_zorro_driver, amiga_zorro_probe); +} + +module_init(amiga_zorro_init); MODULE_LICENSE("GPL"); diff --git a/include/linux/zorro.h b/include/linux/zorro.h index 908db1b..7bf9db5 100644 --- a/include/linux/zorro.h +++ b/include/linux/zorro.h @@ -141,15 +141,6 @@ struct zorro_dev { * Zorro bus */ -struct zorro_bus { - struct list_head devices; /* list of devices on this bus */ - unsigned int num_resources; /* number of resources */ - struct resource resources[4]; /* address space routed to this bus */ - struct device dev; - char name[10]; -}; - -extern struct zorro_bus zorro_bus; /* single Zorro bus */ extern struct bus_type zorro_bus_type; -- cgit v0.10.2 From fa6688e1c7e7341fb7d1ca5878a3641762e60dec Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 5 Apr 2009 12:45:56 +0200 Subject: m68k: amiga - Frame buffer platform device conversion Signed-off-by: Geert Uytterhoeven diff --git a/arch/m68k/amiga/platform.c b/arch/m68k/amiga/platform.c index 33a7669..7fa929c 100644 --- a/arch/m68k/amiga/platform.c +++ b/arch/m68k/amiga/platform.c @@ -56,3 +56,18 @@ static int __init amiga_init_bus(void) subsys_initcall(amiga_init_bus); #endif /* CONFIG_ZORRO */ + + +static int __init amiga_init_devices(void) +{ + if (!MACH_IS_AMIGA) + return -ENODEV; + + /* video hardware */ + if (AMIGAHW_PRESENT(AMI_VIDEO)) + platform_device_register_simple("amiga-video", -1, NULL, 0); + + return 0; +} + +device_initcall(amiga_init_devices); diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c index dca48df..e5d6b56 100644 --- a/drivers/video/amifb.c +++ b/drivers/video/amifb.c @@ -50,8 +50,9 @@ #include #include #include - +#include #include + #include #include #include @@ -1135,7 +1136,7 @@ static int amifb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg * Interface to the low level console driver */ -static void amifb_deinit(void); +static void amifb_deinit(struct platform_device *pdev); /* * Internal routines @@ -2246,7 +2247,7 @@ static inline void chipfree(void) * Initialisation */ -static int __init amifb_init(void) +static int __init amifb_probe(struct platform_device *pdev) { int tag, i, err = 0; u_long chipptr; @@ -2261,16 +2262,6 @@ static int __init amifb_init(void) } amifb_setup(option); #endif - if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_VIDEO)) - return -ENODEV; - - /* - * We request all registers starting from bplpt[0] - */ - if (!request_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120, - "amifb [Denise/Lisa]")) - return -EBUSY; - custom.dmacon = DMAF_ALL | DMAF_MASTER; switch (amiga_chipset) { @@ -2377,6 +2368,7 @@ default_chipset: fb_info.fbops = &amifb_ops; fb_info.par = ¤tpar; fb_info.flags = FBINFO_DEFAULT; + fb_info.device = &pdev->dev; if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, ami_modedb, NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) { @@ -2451,18 +2443,18 @@ default_chipset: return 0; amifb_error: - amifb_deinit(); + amifb_deinit(pdev); return err; } -static void amifb_deinit(void) +static void amifb_deinit(struct platform_device *pdev) { if (fb_info.cmap.len) fb_dealloc_cmap(&fb_info.cmap); + fb_dealloc_cmap(&fb_info.cmap); chipfree(); if (videomemory) iounmap((void*)videomemory); - release_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120); custom.dmacon = DMAF_ALL | DMAF_MASTER; } @@ -3794,14 +3786,35 @@ static void ami_rebuild_copper(void) } } -static void __exit amifb_exit(void) +static int __exit amifb_remove(struct platform_device *pdev) { unregister_framebuffer(&fb_info); - amifb_deinit(); + amifb_deinit(pdev); amifb_video_off(); + return 0; +} + +static struct platform_driver amifb_driver = { + .remove = __exit_p(amifb_remove), + .driver = { + .name = "amiga-video", + .owner = THIS_MODULE, + }, +}; + +static int __init amifb_init(void) +{ + return platform_driver_probe(&amifb_driver, amifb_probe); } module_init(amifb_init); + +static void __exit amifb_exit(void) +{ + platform_driver_unregister(&amifb_driver); +} + module_exit(amifb_exit); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:amiga-video"); -- cgit v0.10.2 From ff2db7c5ab78817eb3c5d15dd87f18e9be726f1a Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 5 Apr 2009 12:59:54 +0200 Subject: m68k: amiga - Sound platform device conversion Signed-off-by: Geert Uytterhoeven diff --git a/arch/m68k/amiga/platform.c b/arch/m68k/amiga/platform.c index 7fa929c..2e308e7 100644 --- a/arch/m68k/amiga/platform.c +++ b/arch/m68k/amiga/platform.c @@ -67,6 +67,11 @@ static int __init amiga_init_devices(void) if (AMIGAHW_PRESENT(AMI_VIDEO)) platform_device_register_simple("amiga-video", -1, NULL, 0); + + /* sound hardware */ + if (AMIGAHW_PRESENT(AMI_AUDIO)) + platform_device_register_simple("amiga-audio", -1, NULL, 0); + return 0; } diff --git a/sound/oss/dmasound/dmasound_paula.c b/sound/oss/dmasound/dmasound_paula.c index bb14e4c..87910e9 100644 --- a/sound/oss/dmasound/dmasound_paula.c +++ b/sound/oss/dmasound/dmasound_paula.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -710,31 +711,41 @@ static MACHINE machAmiga = { /*** Config & Setup **********************************************************/ -static int __init dmasound_paula_init(void) +static int __init amiga_audio_probe(struct platform_device *pdev) { - int err; - - if (MACH_IS_AMIGA && AMIGAHW_PRESENT(AMI_AUDIO)) { - if (!request_mem_region(CUSTOM_PHYSADDR+0xa0, 0x40, - "dmasound [Paula]")) - return -EBUSY; - dmasound.mach = machAmiga; - dmasound.mach.default_hard = def_hard ; - dmasound.mach.default_soft = def_soft ; - err = dmasound_init(); - if (err) - release_mem_region(CUSTOM_PHYSADDR+0xa0, 0x40); - return err; - } else - return -ENODEV; + dmasound.mach = machAmiga; + dmasound.mach.default_hard = def_hard ; + dmasound.mach.default_soft = def_soft ; + return dmasound_init(); } -static void __exit dmasound_paula_cleanup(void) +static int __exit amiga_audio_remove(struct platform_device *pdev) { dmasound_deinit(); - release_mem_region(CUSTOM_PHYSADDR+0xa0, 0x40); + return 0; +} + +static struct platform_driver amiga_audio_driver = { + .remove = __exit_p(amiga_audio_remove), + .driver = { + .name = "amiga-audio", + .owner = THIS_MODULE, + }, +}; + +static int __init amiga_audio_init(void) +{ + return platform_driver_probe(&amiga_audio_driver, amiga_audio_probe); } -module_init(dmasound_paula_init); -module_exit(dmasound_paula_cleanup); +module_init(amiga_audio_init); + +static void __exit amiga_audio_exit(void) +{ + platform_driver_unregister(&amiga_audio_driver); +} + +module_exit(amiga_audio_exit); + MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:amiga-audio"); -- cgit v0.10.2 From 92183b346f02773dae09182c65f16b013f295d80 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 5 Apr 2009 13:02:13 +0200 Subject: m68k: amiga - Floppy platform device conversion Signed-off-by: Geert Uytterhoeven diff --git a/arch/m68k/amiga/platform.c b/arch/m68k/amiga/platform.c index 2e308e7..38f18bf 100644 --- a/arch/m68k/amiga/platform.c +++ b/arch/m68k/amiga/platform.c @@ -72,6 +72,11 @@ static int __init amiga_init_devices(void) if (AMIGAHW_PRESENT(AMI_AUDIO)) platform_device_register_simple("amiga-audio", -1, NULL, 0); + + /* storage interfaces */ + if (AMIGAHW_PRESENT(AMI_FLOPPY)) + platform_device_register_simple("amiga-floppy", -1, NULL, 0); + return 0; } diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index 0182a22..832798a 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c @@ -66,6 +66,7 @@ #include #include #include +#include #include #include @@ -1696,34 +1697,18 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data) return get_disk(unit[drive].gendisk); } -static int __init amiga_floppy_init(void) +static int __init amiga_floppy_probe(struct platform_device *pdev) { int i, ret; - if (!MACH_IS_AMIGA) - return -ENODEV; - - if (!AMIGAHW_PRESENT(AMI_FLOPPY)) - return -ENODEV; - if (register_blkdev(FLOPPY_MAJOR,"fd")) return -EBUSY; - /* - * We request DSKPTR, DSKLEN and DSKDATA only, because the other - * floppy registers are too spreaded over the custom register space - */ - ret = -EBUSY; - if (!request_mem_region(CUSTOM_PHYSADDR+0x20, 8, "amiflop [Paula]")) { - printk("fd: cannot get floppy registers\n"); - goto out_blkdev; - } - ret = -ENOMEM; if ((raw_buf = (char *)amiga_chip_alloc (RAW_BUF_SIZE, "Floppy")) == NULL) { printk("fd: cannot get chip mem buffer\n"); - goto out_memregion; + goto out_blkdev; } ret = -EBUSY; @@ -1792,18 +1777,13 @@ out_irq2: free_irq(IRQ_AMIGA_DSKBLK, NULL); out_irq: amiga_chip_free(raw_buf); -out_memregion: - release_mem_region(CUSTOM_PHYSADDR+0x20, 8); out_blkdev: unregister_blkdev(FLOPPY_MAJOR,"fd"); return ret; } -module_init(amiga_floppy_init); -#ifdef MODULE - #if 0 /* not safe to unload */ -void cleanup_module(void) +static int __exit amiga_floppy_remove(struct platform_device *pdev) { int i; @@ -1820,12 +1800,25 @@ void cleanup_module(void) custom.dmacon = DMAF_DISK; /* disable DMA */ amiga_chip_free(raw_buf); blk_cleanup_queue(floppy_queue); - release_mem_region(CUSTOM_PHYSADDR+0x20, 8); unregister_blkdev(FLOPPY_MAJOR, "fd"); } #endif -#else +static struct platform_driver amiga_floppy_driver = { + .driver = { + .name = "amiga-floppy", + .owner = THIS_MODULE, + }, +}; + +static int __init amiga_floppy_init(void) +{ + return platform_driver_probe(&amiga_floppy_driver, amiga_floppy_probe); +} + +module_init(amiga_floppy_init); + +#ifndef MODULE static int __init amiga_floppy_setup (char *str) { int n; @@ -1840,3 +1833,5 @@ static int __init amiga_floppy_setup (char *str) __setup("floppy=", amiga_floppy_setup); #endif + +MODULE_ALIAS("platform:amiga-floppy"); -- cgit v0.10.2 From 63aa9e7e3ab28ad5362502b1a69fae945367ad65 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 17 May 2010 16:42:37 -0300 Subject: perf tui: Add explicit -lslang option At least on rawhide using -lnewt is not enough if we use SLang routines directly, so add an explicit -lslang since we use SLang routines. Reported-by: Ingo Molnar Tested-by: Ingo Molnar Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Makefile b/tools/perf/Makefile index a9281cc..e2729fc 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -564,7 +564,7 @@ ifneq ($(shell sh -c "(echo '\#include '; echo 'int main(void) { newtIni else # Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h BASIC_CFLAGS += -I/usr/include/slang - EXTLIBS += -lnewt + EXTLIBS += -lnewt -lslang LIB_OBJS += $(OUTPUT)util/newt.o endif -- cgit v0.10.2 From db19272edc93661835bf6ec9736cfd0754aa3c62 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 17 May 2010 14:51:49 -0400 Subject: cifs: always revalidate hardlinked inodes when using noserverino The old cifs_revalidate logic always revalidated hardlinked inodes. This hack allowed CIFS to pass some connectathon tests when server inode numbers aren't used (basic test7, in particular). Signed-off-by: Jeff Layton Signed-off-by: Steve French diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 5b042fc..8e05e8a 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -1528,6 +1528,11 @@ cifs_inode_needs_reval(struct inode *inode) if (time_after_eq(jiffies, cifs_i->time + HZ)) return true; + /* hardlinked files w/ noserverino get "special" treatment */ + if (!(CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) && + S_ISREG(inode->i_mode) && inode->i_nlink != 1) + return true; + return false; } -- cgit v0.10.2 From 84f30c66c3689745abbd3b9ce39816caeb9bec3b Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 17 May 2010 07:18:57 -0400 Subject: cifs: don't update uniqueid in cifs_fattr_to_inode We use this value to find an inode within the hash bucket, so we can't change this without re-hashing the inode. For now, treat this value as immutable. Eventually, we should probably use an inode number change on a path based operation to indicate that the lookup cache is invalid, but that's a bit more code to deal with. Signed-off-by: Jeff Layton Signed-off-by: Steve French diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 8e05e8a..b0ff252 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -137,7 +137,6 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) inode->i_mode = fattr->cf_mode; cifs_i->cifsAttrs = fattr->cf_cifsattrs; - cifs_i->uniqueid = fattr->cf_uniqueid; if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL) cifs_i->time = 0; -- cgit v0.10.2 From 2f51903bc3139e25ec908f8944a0001c7b868e90 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 17 May 2010 17:57:59 -0300 Subject: perf symbols: symbol inconsistency message should be done only at verbose=1 That happened for an old perf.data file that had no fake MMAP events for the kernel modules, but even then it should warn once for each module, not one time for every symbol in every module not found. Reported-by: Ingo Molnar LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index ecccc8d..a06131f 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -525,7 +525,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map, curr_map = map_groups__find_by_name(kmaps, map->type, module); if (curr_map == NULL) { - pr_err("%s/proc/{kallsyms,modules} " + pr_debug("%s/proc/{kallsyms,modules} " "inconsistency while looking " "for \"%s\" module!\n", machine->root_dir, module); -- cgit v0.10.2 From 4065c802da7484fa36f8cdf10f18d087233ecb88 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 17 May 2010 07:18:58 -0400 Subject: cifs: fix noserverino handling when unix extensions are enabled The uniqueid field sent by the server when unix extensions are enabled is currently used sometimes when it shouldn't be. The readdir codepath is correct, but most others are not. Fix it. Signed-off-by: Jeff Layton Signed-off-by: Steve French diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 2e07da9..fb1657e 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -110,6 +110,7 @@ extern int cifs_posix_open(char *full_path, struct inode **pinode, struct super_block *sb, int mode, int oflags, __u32 *poplock, __u16 *pnetfid, int xid); +void cifs_fill_uniqueid(struct super_block *sb, struct cifs_fattr *fattr); extern void cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info, struct cifs_sb_info *cifs_sb); diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 86d3c0c..391816b 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -248,6 +248,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode, /* get new inode and set it up */ if (*pinode == NULL) { + cifs_fill_uniqueid(sb, &fattr); *pinode = cifs_iget(sb, &fattr); if (!*pinode) { rc = -ENOMEM; diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index b0ff252..62b324f 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -169,6 +169,17 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) cifs_set_ops(inode, fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL); } +void +cifs_fill_uniqueid(struct super_block *sb, struct cifs_fattr *fattr) +{ + struct cifs_sb_info *cifs_sb = CIFS_SB(sb); + + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) + return; + + fattr->cf_uniqueid = iunique(sb, ROOT_I); +} + /* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */ void cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info, @@ -322,6 +333,7 @@ int cifs_get_inode_info_unix(struct inode **pinode, if (*pinode == NULL) { /* get new inode */ + cifs_fill_uniqueid(sb, &fattr); *pinode = cifs_iget(sb, &fattr); if (!*pinode) rc = -ENOMEM; @@ -1197,6 +1209,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) direntry->d_op = &cifs_dentry_ops; cifs_unix_basic_to_fattr(&fattr, pInfo, cifs_sb); + cifs_fill_uniqueid(inode->i_sb, &fattr); newinode = cifs_iget(inode->i_sb, &fattr); if (!newinode) { kfree(pInfo); -- cgit v0.10.2 From 94f3ca95787ada3d64339a4ecb2754236ab563f6 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 17 May 2010 18:18:11 -0300 Subject: perf tools: Add mode to build without newt support make NO_NEWT=1 Will avoid building the newt (tui) support. Suggested-by: Ingo Molnar LKML-Reference: Signed-off-by: Arnaldo Carvalho de Melo diff --git a/tools/perf/Makefile b/tools/perf/Makefile index e2729fc..3d8f31e 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -558,6 +558,9 @@ else endif # PERF_HAVE_DWARF_REGS endif # NO_DWARF +ifdef NO_NEWT + BASIC_CFLAGS += -DNO_NEWT_SUPPORT +else ifneq ($(shell sh -c "(echo '\#include '; echo 'int main(void) { newtInit(); newtCls(); return newtFinished(); }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -lnewt -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y) msg := $(warning newt not found, disables TUI support. Please install newt-devel or libnewt-dev); BASIC_CFLAGS += -DNO_NEWT_SUPPORT @@ -567,6 +570,7 @@ else EXTLIBS += -lnewt -lslang LIB_OBJS += $(OUTPUT)util/newt.o endif +endif # NO_NEWT ifndef NO_LIBPERL PERL_EMBED_LDOPTS = `perl -MExtUtils::Embed -e ldopts 2>/dev/null` -- cgit v0.10.2 From c59bd5688299cddb71183e156e7a3c1409b90df2 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 17 May 2010 15:13:23 -0700 Subject: x86, hweight: Use a 32-bit popcnt for __arch_hweight32() Use a 32-bit popcnt instruction for __arch_hweight32(), even on x86-64. Even though the input register will *usually* be zero-extended due to the standard operation of the hardware, it isn't necessarily so if the input value was the result of truncating a 64-bit operation. Note: the POPCNT32 variant used on x86-64 has a technically unnecessary REX prefix to make it five bytes long, the same as a CALL instruction, therefore avoiding an unnecessary NOP. Reported-by: Linus Torvalds Signed-off-by: H. Peter Anvin Cc: Borislav Petkov LKML-Reference: diff --git a/arch/x86/include/asm/arch_hweight.h b/arch/x86/include/asm/arch_hweight.h index d1fc3c2..9686c3d 100644 --- a/arch/x86/include/asm/arch_hweight.h +++ b/arch/x86/include/asm/arch_hweight.h @@ -2,13 +2,15 @@ #define _ASM_X86_HWEIGHT_H #ifdef CONFIG_64BIT +/* popcnt %edi, %eax -- redundant REX prefix for alignment */ +#define POPCNT32 ".byte 0xf3,0x40,0x0f,0xb8,0xc7" /* popcnt %rdi, %rax */ -#define POPCNT ".byte 0xf3,0x48,0x0f,0xb8,0xc7" +#define POPCNT64 ".byte 0xf3,0x48,0x0f,0xb8,0xc7" #define REG_IN "D" #define REG_OUT "a" #else /* popcnt %eax, %eax */ -#define POPCNT ".byte 0xf3,0x0f,0xb8,0xc0" +#define POPCNT32 ".byte 0xf3,0x0f,0xb8,0xc0" #define REG_IN "a" #define REG_OUT "a" #endif @@ -23,7 +25,7 @@ static inline unsigned int __arch_hweight32(unsigned int w) { unsigned int res = 0; - asm (ALTERNATIVE("call __sw_hweight32", POPCNT, X86_FEATURE_POPCNT) + asm (ALTERNATIVE("call __sw_hweight32", POPCNT32, X86_FEATURE_POPCNT) : "="REG_OUT (res) : REG_IN (w)); @@ -48,7 +50,7 @@ static inline unsigned long __arch_hweight64(__u64 w) return __arch_hweight32((u32)w) + __arch_hweight32((u32)(w >> 32)); #else - asm (ALTERNATIVE("call __sw_hweight64", POPCNT, X86_FEATURE_POPCNT) + asm (ALTERNATIVE("call __sw_hweight64", POPCNT64, X86_FEATURE_POPCNT) : "="REG_OUT (res) : REG_IN (w)); #endif /* CONFIG_X86_32 */ -- cgit v0.10.2 From 9c6f7e43b4e02c161b53e97ba913855246876c61 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 18 May 2010 00:17:44 +0200 Subject: stop_machine: Move local variable closer to the usage site in cpu_stop_cpu_callback() This addresses the following compiler warning: kernel/stop_machine.c: In function 'cpu_stop_cpu_callback': kernel/stop_machine.c:297: warning: unused variable 'work' Cc: Tejun Heo Cc: Peter Zijlstra LKML-Reference: Signed-off-by: Ingo Molnar diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c index ef51d1f..b4e7431 100644 --- a/kernel/stop_machine.c +++ b/kernel/stop_machine.c @@ -294,7 +294,6 @@ static int __cpuinit cpu_stop_cpu_callback(struct notifier_block *nfb, struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 }; unsigned int cpu = (unsigned long)hcpu; struct cpu_stopper *stopper = &per_cpu(cpu_stopper, cpu); - struct cpu_stop_work *work; struct task_struct *p; switch (action & ~CPU_TASKS_FROZEN) { @@ -323,6 +322,9 @@ static int __cpuinit cpu_stop_cpu_callback(struct notifier_block *nfb, #ifdef CONFIG_HOTPLUG_CPU case CPU_UP_CANCELED: case CPU_DEAD: + { + struct cpu_stop_work *work; + /* kill the stopper */ kthread_stop(stopper->thread); /* drain remaining works */ @@ -335,6 +337,7 @@ static int __cpuinit cpu_stop_cpu_callback(struct notifier_block *nfb, put_task_struct(stopper->thread); stopper->thread = NULL; break; + } #endif } -- cgit v0.10.2 From 26be1b7b317f1d6e9226ba3f450476b0a6d423a3 Mon Sep 17 00:00:00 2001 From: Mike Solovyev Date: Wed, 12 May 2010 15:38:00 +0400 Subject: ARM: h1940: framebuffer configuration fix Seems like a typo, wrong setup leads to broken image on ipaq screen. Signed-off-by: Mike Solovyev Signed-off-by: Arnaud Patard Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c index b212561..03028b9 100644 --- a/arch/arm/mach-s3c2410/mach-h1940.c +++ b/arch/arm/mach-s3c2410/mach-h1940.c @@ -162,8 +162,8 @@ static struct s3c2410fb_display h1940_lcd __initdata = { .xres = 240, .yres = 320, .bpp = 16, - .left_margin = 20, - .right_margin = 8, + .left_margin = 8, + .right_margin = 20, .hsync_len = 4, .upper_margin = 8, .lower_margin = 7, -- cgit v0.10.2 From 4f7cdc38c000deba82479205f4c99f4c1e7c6d1f Mon Sep 17 00:00:00 2001 From: Naveen Krishna Date: Thu, 13 May 2010 22:06:36 +0900 Subject: ARM: SAMSUNG: Moving ADC device definition to plat-samsung. This patch moves ADC device definition to plat-samsung. Because that is generic to the S3C64XX and S5P Series SoCs. Signed-off-by: Naveen Krishna Ch Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c64xx/Kconfig b/arch/arm/mach-s3c64xx/Kconfig index 959df38..69e9fbf 100644 --- a/arch/arm/mach-s3c64xx/Kconfig +++ b/arch/arm/mach-s3c64xx/Kconfig @@ -85,6 +85,7 @@ config MACH_ANW6410 config MACH_SMDK6410 bool "SMDK6410" select CPU_S3C6410 + select SAMSUNG_DEV_ADC select S3C_DEV_HSMMC select S3C_DEV_HSMMC1 select S3C_DEV_I2C1 diff --git a/arch/arm/mach-s3c64xx/Makefile b/arch/arm/mach-s3c64xx/Makefile index 3758e15..da66278 100644 --- a/arch/arm/mach-s3c64xx/Makefile +++ b/arch/arm/mach-s3c64xx/Makefile @@ -58,5 +58,4 @@ obj-$(CONFIG_MACH_HMT) += mach-hmt.o obj-y += dev-uart.o obj-y += dev-rtc.o obj-y += dev-audio.o -obj-$(CONFIG_S3C_ADC) += dev-adc.o obj-$(CONFIG_S3C64XX_DEV_SPI) += dev-spi.o diff --git a/arch/arm/mach-s3c64xx/dev-adc.c b/arch/arm/mach-s3c64xx/dev-adc.c deleted file mode 100644 index fafef9b..0000000 --- a/arch/arm/mach-s3c64xx/dev-adc.c +++ /dev/null @@ -1,46 +0,0 @@ -/* linux/arch/arm/plat-s3c64xx/dev-adc.c - * - * Copyright 2010 Maurus Cuelenaere - * - * S3C64xx series device definition for ADC device - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#include -#include -#include - -#include -#include - -#include -#include -#include - -static struct resource s3c_adc_resource[] = { - [0] = { - .start = S3C64XX_PA_ADC, - .end = S3C64XX_PA_ADC + SZ_256 - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_TC, - .end = IRQ_TC, - .flags = IORESOURCE_IRQ, - }, - [2] = { - .start = IRQ_ADC, - .end = IRQ_ADC, - .flags = IORESOURCE_IRQ, - }, -}; - -struct platform_device s3c_device_adc = { - .name = "s3c64xx-adc", - .id = -1, - .num_resources = ARRAY_SIZE(s3c_adc_resource), - .resource = s3c_adc_resource, -}; diff --git a/arch/arm/mach-s3c64xx/include/mach/map.h b/arch/arm/mach-s3c64xx/include/mach/map.h index 801c1c0..869c8e0 100644 --- a/arch/arm/mach-s3c64xx/include/mach/map.h +++ b/arch/arm/mach-s3c64xx/include/mach/map.h @@ -103,5 +103,6 @@ #define S3C_PA_USBHOST S3C64XX_PA_USBHOST #define S3C_PA_USB_HSOTG S3C64XX_PA_USB_HSOTG #define S3C_VA_USB_HSPHY S3C64XX_VA_USB_HSPHY +#define SAMSUNG_PA_ADC S3C64XX_PA_ADC #endif /* __ASM_ARCH_6400_MAP_H */ diff --git a/arch/arm/mach-s3c64xx/s3c6410.c b/arch/arm/mach-s3c64xx/s3c6410.c index 59635d1..3ab695c 100644 --- a/arch/arm/mach-s3c64xx/s3c6410.c +++ b/arch/arm/mach-s3c64xx/s3c6410.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -52,6 +53,7 @@ void __init s3c6410_map_io(void) s3c_i2c0_setname("s3c2440-i2c"); s3c_i2c1_setname("s3c2440-i2c"); + s3c_device_adc.name = "s3c64xx-adc"; s3c_device_nand.name = "s3c6400-nand"; } diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig index d552c65..641649f 100644 --- a/arch/arm/plat-samsung/Kconfig +++ b/arch/arm/plat-samsung/Kconfig @@ -185,6 +185,11 @@ config S3C_DEV_NAND help Compile in platform device definition for NAND controller +config SAMSUNG_DEV_ADC + bool + help + Compile in platform device definition for ADC controller + config S3C64XX_DEV_SPI bool help diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile index 22c89d0..3cf30a4 100644 --- a/arch/arm/plat-samsung/Makefile +++ b/arch/arm/plat-samsung/Makefile @@ -40,6 +40,7 @@ obj-y += dev-uart.o obj-$(CONFIG_S3C_DEV_USB_HOST) += dev-usb.o obj-$(CONFIG_S3C_DEV_USB_HSOTG) += dev-usb-hsotg.o obj-$(CONFIG_S3C_DEV_NAND) += dev-nand.o +obj-$(CONFIG_SAMSUNG_DEV_ADC) += dev-adc.o # DMA support diff --git a/arch/arm/plat-samsung/dev-adc.c b/arch/arm/plat-samsung/dev-adc.c new file mode 100644 index 0000000..9d903d4 --- /dev/null +++ b/arch/arm/plat-samsung/dev-adc.c @@ -0,0 +1,46 @@ +/* linux/arch/arm/plat-samsung/dev-adc.c + * + * Copyright 2010 Maurus Cuelenaere + * + * S3C64xx series device definition for ADC device + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include +#include + +#include +#include + +#include +#include +#include + +static struct resource s3c_adc_resource[] = { + [0] = { + .start = SAMSUNG_PA_ADC, + .end = SAMSUNG_PA_ADC + SZ_256 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_TC, + .end = IRQ_TC, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IRQ_ADC, + .end = IRQ_ADC, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device s3c_device_adc = { + .name = "samsung-adc", + .id = -1, + .num_resources = ARRAY_SIZE(s3c_adc_resource), + .resource = s3c_adc_resource, +}; -- cgit v0.10.2 From c77b29db74a0ea4fdce0564a63b8876798625d64 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 18 May 2010 14:53:23 +0900 Subject: sh: fix up CONFIG_KEXEC=n build. The reserve_crashkernel() definition is in asm/kexec.h which is only dragged in via linux/kexec.h if CONFIG_KEXEC is set. Just switch over to asm/kexec.h unconditionally to fix up the build. Signed-off-by: Paul Mundt diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c index 7f3cb52..46f84de 100644 --- a/arch/sh/mm/init.c +++ b/arch/sh/mm/init.c @@ -17,10 +17,10 @@ #include #include #include -#include #include #include #include +#include #include #include #include -- cgit v0.10.2 From dd2fdd264eaa616fab4cf80e89f83f4a2fc26288 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 18 May 2010 15:23:48 +0900 Subject: sh64: provide a stub per_cpu_trap_init() definition. This is needed to fix up the build at the moment. Gradually this will be reworked to follow the 32-bit initialization path and deal with delayed VBR initialization. Signed-off-by: Paul Mundt diff --git a/arch/sh/kernel/traps_64.c b/arch/sh/kernel/traps_64.c index e3f92eb..e67e140 100644 --- a/arch/sh/kernel/traps_64.c +++ b/arch/sh/kernel/traps_64.c @@ -944,3 +944,8 @@ asmlinkage void do_debug_interrupt(unsigned long code, struct pt_regs *regs) /* Clear all DEBUGINT causes */ poke_real_address_q(DM_EXP_CAUSE_PHY, 0x0); } + +void __cpuinit per_cpu_trap_init(void) +{ + /* Nothing to do for now, VBR initialization later. */ +} -- cgit v0.10.2 From 717e7c2672e37253a4d3aa70e4716b5b0a658761 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 18 May 2010 08:17:56 +0100 Subject: ARM: remove 'select GENERIC_TIME' GENERIC_TIME is now enabled by default, so 'select GENERIC_TIME' is redundant. Remove them. Signed-off-by: Russell King diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 492f813..a07b6c4 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -225,7 +225,6 @@ config ARCH_INTEGRATOR select ARCH_HAS_CPUFREQ select COMMON_CLKDEV select ICST - select GENERIC_TIME select GENERIC_CLOCKEVENTS select PLAT_VERSATILE help @@ -236,7 +235,6 @@ config ARCH_REALVIEW select ARM_AMBA select COMMON_CLKDEV select ICST - select GENERIC_TIME select GENERIC_CLOCKEVENTS select ARCH_WANT_OPTIONAL_GPIOLIB select PLAT_VERSATILE @@ -251,7 +249,6 @@ config ARCH_VERSATILE select ARM_VIC select COMMON_CLKDEV select ICST - select GENERIC_TIME select GENERIC_CLOCKEVENTS select ARCH_WANT_OPTIONAL_GPIOLIB select PLAT_VERSATILE @@ -266,7 +263,6 @@ config ARCH_VEXPRESS select ARM_TIMER_SP804 select COMMON_CLKDEV select GENERIC_CLOCKEVENTS - select GENERIC_TIME select HAVE_CLK select ICST select PLAT_VERSATILE @@ -288,7 +284,6 @@ config ARCH_BCMRING select CPU_V6 select ARM_AMBA select COMMON_CLKDEV - select GENERIC_TIME select GENERIC_CLOCKEVENTS select ARCH_WANT_OPTIONAL_GPIOLIB help @@ -304,7 +299,6 @@ config ARCH_CLPS711X config ARCH_CNS3XXX bool "Cavium Networks CNS3XXX family" select CPU_V6 - select GENERIC_TIME select GENERIC_CLOCKEVENTS select ARM_GIC help @@ -353,7 +347,6 @@ config ARCH_FOOTBRIDGE config ARCH_MXC bool "Freescale MXC/iMX-based" - select GENERIC_TIME select GENERIC_CLOCKEVENTS select ARCH_REQUIRE_GPIOLIB select COMMON_CLKDEV @@ -365,7 +358,6 @@ config ARCH_STMP3XXX select CPU_ARM926T select COMMON_CLKDEV select ARCH_REQUIRE_GPIOLIB - select GENERIC_TIME select GENERIC_CLOCKEVENTS select USB_ARCH_HAS_EHCI help @@ -376,7 +368,6 @@ config ARCH_NETX select CPU_ARM926T select ARM_VIC select GENERIC_CLOCKEVENTS - select GENERIC_TIME help This enables support for systems based on the Hilscher NetX Soc @@ -443,7 +434,6 @@ config ARCH_IXP4XX depends on MMU select CPU_XSCALE select GENERIC_GPIO - select GENERIC_TIME select GENERIC_CLOCKEVENTS select DMABOUNCE if PCI help @@ -468,7 +458,6 @@ config ARCH_DOVE bool "Marvell Dove" select PCI select ARCH_REQUIRE_GPIOLIB - select GENERIC_TIME select GENERIC_CLOCKEVENTS select PLAT_ORION help @@ -479,7 +468,6 @@ config ARCH_KIRKWOOD select CPU_FEROCEON select PCI select ARCH_REQUIRE_GPIOLIB - select GENERIC_TIME select GENERIC_CLOCKEVENTS select PLAT_ORION help @@ -489,7 +477,6 @@ config ARCH_KIRKWOOD config ARCH_LOKI bool "Marvell Loki (88RC8480)" select CPU_FEROCEON - select GENERIC_TIME select GENERIC_CLOCKEVENTS select PLAT_ORION help @@ -500,7 +487,6 @@ config ARCH_MV78XX0 select CPU_FEROCEON select PCI select ARCH_REQUIRE_GPIOLIB - select GENERIC_TIME select GENERIC_CLOCKEVENTS select PLAT_ORION help @@ -513,7 +499,6 @@ config ARCH_ORION5X select CPU_FEROCEON select PCI select ARCH_REQUIRE_GPIOLIB - select GENERIC_TIME select GENERIC_CLOCKEVENTS select PLAT_ORION help @@ -526,7 +511,6 @@ config ARCH_MMP depends on MMU select ARCH_REQUIRE_GPIOLIB select COMMON_CLKDEV - select GENERIC_TIME select GENERIC_CLOCKEVENTS select TICK_ONESHOT select PLAT_PXA @@ -546,7 +530,6 @@ config ARCH_NS9XXX bool "NetSilicon NS9xxx" select CPU_ARM926T select GENERIC_GPIO - select GENERIC_TIME select GENERIC_CLOCKEVENTS select HAVE_CLK help @@ -560,7 +543,6 @@ config ARCH_W90X900 select CPU_ARM926T select ARCH_REQUIRE_GPIOLIB select COMMON_CLKDEV - select GENERIC_TIME select GENERIC_CLOCKEVENTS help Support for Nuvoton (Winbond logic dept.) ARM9 processor, @@ -594,7 +576,6 @@ config ARCH_PXA select ARCH_HAS_CPUFREQ select COMMON_CLKDEV select ARCH_REQUIRE_GPIOLIB - select GENERIC_TIME select GENERIC_CLOCKEVENTS select TICK_ONESHOT select PLAT_PXA @@ -604,7 +585,6 @@ config ARCH_PXA config ARCH_MSM bool "Qualcomm MSM" select HAVE_CLK - select GENERIC_TIME select GENERIC_CLOCKEVENTS help Support for Qualcomm MSM/QSD based systems. This runs on the @@ -641,7 +621,6 @@ config ARCH_SA1100 select ARCH_MTD_XIP select ARCH_HAS_CPUFREQ select CPU_FREQ - select GENERIC_TIME select GENERIC_CLOCKEVENTS select HAVE_CLK select TICK_ONESHOT @@ -752,7 +731,6 @@ config ARCH_U300 select HAVE_TCM select ARM_AMBA select ARM_VIC - select GENERIC_TIME select GENERIC_CLOCKEVENTS select COMMON_CLKDEV select GENERIC_GPIO @@ -763,7 +741,6 @@ config ARCH_U8500 bool "ST-Ericsson U8500 Series" select CPU_V7 select ARM_AMBA - select GENERIC_TIME select GENERIC_CLOCKEVENTS select COMMON_CLKDEV select ARCH_REQUIRE_GPIOLIB @@ -776,7 +753,6 @@ config ARCH_NOMADIK select ARM_VIC select CPU_ARM926T select COMMON_CLKDEV - select GENERIC_TIME select GENERIC_CLOCKEVENTS select ARCH_REQUIRE_GPIOLIB help @@ -785,7 +761,6 @@ config ARCH_NOMADIK config ARCH_DAVINCI bool "TI DaVinci" select CPU_ARM926T - select GENERIC_TIME select GENERIC_CLOCKEVENTS select ARCH_REQUIRE_GPIOLIB select ZONE_DMA @@ -801,7 +776,6 @@ config ARCH_OMAP select HAVE_CLK select ARCH_REQUIRE_GPIOLIB select ARCH_HAS_CPUFREQ - select GENERIC_TIME select GENERIC_CLOCKEVENTS select ARCH_HAS_HOLES_MEMORYMODEL help @@ -813,7 +787,6 @@ config PLAT_SPEAR select ARCH_REQUIRE_GPIOLIB select COMMON_CLKDEV select GENERIC_CLOCKEVENTS - select GENERIC_TIME select HAVE_CLK help Support for ST's SPEAr platform (SPEAr3xx, SPEAr6xx and SPEAr13xx). @@ -951,7 +924,6 @@ config ARCH_ACORN config PLAT_IOP bool select GENERIC_CLOCKEVENTS - select GENERIC_TIME config PLAT_ORION bool diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 1039764..841eaf8 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -23,14 +23,12 @@ choice config ARCH_AT91RM9200 bool "AT91RM9200" select CPU_ARM920T - select GENERIC_TIME select GENERIC_CLOCKEVENTS select HAVE_AT91_USART3 config ARCH_AT91SAM9260 bool "AT91SAM9260 or AT91SAM9XE" select CPU_ARM926T - select GENERIC_TIME select GENERIC_CLOCKEVENTS select HAVE_AT91_USART3 select HAVE_AT91_USART4 @@ -39,28 +37,24 @@ config ARCH_AT91SAM9260 config ARCH_AT91SAM9261 bool "AT91SAM9261" select CPU_ARM926T - select GENERIC_TIME select GENERIC_CLOCKEVENTS select HAVE_FB_ATMEL config ARCH_AT91SAM9G10 bool "AT91SAM9G10" select CPU_ARM926T - select GENERIC_TIME select GENERIC_CLOCKEVENTS select HAVE_FB_ATMEL config ARCH_AT91SAM9263 bool "AT91SAM9263" select CPU_ARM926T - select GENERIC_TIME select GENERIC_CLOCKEVENTS select HAVE_FB_ATMEL config ARCH_AT91SAM9RL bool "AT91SAM9RL" select CPU_ARM926T - select GENERIC_TIME select GENERIC_CLOCKEVENTS select HAVE_AT91_USART3 select HAVE_FB_ATMEL @@ -68,7 +62,6 @@ config ARCH_AT91SAM9RL config ARCH_AT91SAM9G20 bool "AT91SAM9G20" select CPU_ARM926T - select GENERIC_TIME select GENERIC_CLOCKEVENTS select HAVE_AT91_USART3 select HAVE_AT91_USART4 @@ -77,7 +70,6 @@ config ARCH_AT91SAM9G20 config ARCH_AT91SAM9G45 bool "AT91SAM9G45" select CPU_ARM926T - select GENERIC_TIME select GENERIC_CLOCKEVENTS select HAVE_AT91_USART3 select HAVE_FB_ATMEL @@ -85,14 +77,12 @@ config ARCH_AT91SAM9G45 config ARCH_AT91CAP9 bool "AT91CAP9" select CPU_ARM926T - select GENERIC_TIME select GENERIC_CLOCKEVENTS select HAVE_FB_ATMEL config ARCH_AT572D940HF bool "AT572D940HF" select CPU_ARM926T - select GENERIC_TIME select GENERIC_CLOCKEVENTS config ARCH_AT91X40 diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index aeceb9b..f2b88c5 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -7,7 +7,6 @@ config ARCH_SH7367 select CPU_V6 select HAVE_CLK select COMMON_CLKDEV - select GENERIC_TIME select GENERIC_CLOCKEVENTS config ARCH_SH7377 @@ -15,7 +14,6 @@ config ARCH_SH7377 select CPU_V7 select HAVE_CLK select COMMON_CLKDEV - select GENERIC_TIME select GENERIC_CLOCKEVENTS config ARCH_SH7372 @@ -23,7 +21,6 @@ config ARCH_SH7372 select CPU_V7 select HAVE_CLK select COMMON_CLKDEV - select GENERIC_TIME select GENERIC_CLOCKEVENTS comment "SH-Mobile Board Type" -- cgit v0.10.2 From adc0950c08e1f433f6933759f4facf9b2cf8d29d Mon Sep 17 00:00:00 2001 From: Atul Dahiya Date: Tue, 18 May 2010 14:58:56 +0900 Subject: ARM: SAMSUNG: Move RTC device definitions in plat-samsung This patch moves RTC device definitions from mach-s3c64xx to plat-samsung, to enable the other SoCs to use same device definition. Signed-off-by: Atul Dahiya Signed-off-by: Sangbeom Kim Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c64xx/Makefile b/arch/arm/mach-s3c64xx/Makefile index 3758e15..56ef972 100644 --- a/arch/arm/mach-s3c64xx/Makefile +++ b/arch/arm/mach-s3c64xx/Makefile @@ -56,7 +56,6 @@ obj-$(CONFIG_MACH_HMT) += mach-hmt.o # device support obj-y += dev-uart.o -obj-y += dev-rtc.o obj-y += dev-audio.o obj-$(CONFIG_S3C_ADC) += dev-adc.o obj-$(CONFIG_S3C64XX_DEV_SPI) += dev-spi.o diff --git a/arch/arm/mach-s3c64xx/dev-rtc.c b/arch/arm/mach-s3c64xx/dev-rtc.c deleted file mode 100644 index b9e7a05..0000000 --- a/arch/arm/mach-s3c64xx/dev-rtc.c +++ /dev/null @@ -1,43 +0,0 @@ -/* linux/arch/arm/plat-s3c64xx/dev-rtc.c - * - * Copyright 2009 by Maurus Cuelenaere - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include - -#include -#include - -#include - -static struct resource s3c_rtc_resource[] = { - [0] = { - .start = S3C64XX_PA_RTC, - .end = S3C64XX_PA_RTC + 0xff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_RTC_ALARM, - .end = IRQ_RTC_ALARM, - .flags = IORESOURCE_IRQ, - }, - [2] = { - .start = IRQ_RTC_TIC, - .end = IRQ_RTC_TIC, - .flags = IORESOURCE_IRQ - } -}; - -struct platform_device s3c_device_rtc = { - .name = "s3c64xx-rtc", - .id = -1, - .num_resources = ARRAY_SIZE(s3c_rtc_resource), - .resource = s3c_rtc_resource, -}; -EXPORT_SYMBOL(s3c_device_rtc); diff --git a/arch/arm/mach-s3c64xx/include/mach/map.h b/arch/arm/mach-s3c64xx/include/mach/map.h index 801c1c0..cce28a9 100644 --- a/arch/arm/mach-s3c64xx/include/mach/map.h +++ b/arch/arm/mach-s3c64xx/include/mach/map.h @@ -103,5 +103,6 @@ #define S3C_PA_USBHOST S3C64XX_PA_USBHOST #define S3C_PA_USB_HSOTG S3C64XX_PA_USB_HSOTG #define S3C_VA_USB_HSPHY S3C64XX_VA_USB_HSPHY +#define S3C_PA_RTC S3C64XX_PA_RTC #endif /* __ASM_ARCH_6400_MAP_H */ diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig index d552c65..f4a017d 100644 --- a/arch/arm/plat-samsung/Kconfig +++ b/arch/arm/plat-samsung/Kconfig @@ -185,6 +185,11 @@ config S3C_DEV_NAND help Compile in platform device definition for NAND controller +config S3C_DEV_RTC + bool + help + Complie in platform device definition for RTC + config S3C64XX_DEV_SPI bool help diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile index 22c89d0..4326c1b 100644 --- a/arch/arm/plat-samsung/Makefile +++ b/arch/arm/plat-samsung/Makefile @@ -40,6 +40,7 @@ obj-y += dev-uart.o obj-$(CONFIG_S3C_DEV_USB_HOST) += dev-usb.o obj-$(CONFIG_S3C_DEV_USB_HSOTG) += dev-usb-hsotg.o obj-$(CONFIG_S3C_DEV_NAND) += dev-nand.o +obj-$(CONFIG_S3C_DEV_RTC) += dev-rtc.o # DMA support diff --git a/arch/arm/plat-samsung/dev-rtc.c b/arch/arm/plat-samsung/dev-rtc.c new file mode 100644 index 0000000..bf4e226 --- /dev/null +++ b/arch/arm/plat-samsung/dev-rtc.c @@ -0,0 +1,43 @@ +/* linux/arch/arm/plat-samsung/dev-rtc.c + * + * Copyright 2009 by Maurus Cuelenaere + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include + +#include +#include + +#include + +static struct resource s3c_rtc_resource[] = { + [0] = { + .start = S3C_PA_RTC, + .end = S3C_PA_RTC + 0xff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_RTC_ALARM, + .end = IRQ_RTC_ALARM, + .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IRQ_RTC_TIC, + .end = IRQ_RTC_TIC, + .flags = IORESOURCE_IRQ + } +}; + +struct platform_device s3c_device_rtc = { + .name = "s3c64xx-rtc", + .id = -1, + .num_resources = ARRAY_SIZE(s3c_rtc_resource), + .resource = s3c_rtc_resource, +}; +EXPORT_SYMBOL(s3c_device_rtc); -- cgit v0.10.2 From d800edebe33cac300ab1ff3b95e8a74d53e842d2 Mon Sep 17 00:00:00 2001 From: Jassi Brar Date: Tue, 18 May 2010 11:59:06 +0900 Subject: S3C: DMA: Add api driver for PL330 Latest Samsung SoCs have one or more PL330 as their DMACs. This patch implements the S3C DMA API for PL330 core driver. The design has been kept as generic as possible while keeping effort to add support for new SoCs to the minimum possible level. Some of the salient features of this driver are:- o Automatic scheduling of client requests onto DMAC if more than one DMAC can reach the peripheral. Factors, such as current load and number of exclusive but inactive peripherals that are supported by the DMAC, are used to decide suitability of a DMAC for a particular client. o CIRCULAR buffer option is supported. o The driver scales transparently with the number of DMACs and total peripherals in the platform, since all peripherals are added to the peripheral pool and DMACs to the controller pool. For most conservative use of memory, smallest driver size and best performance, we don't employ legacy data structures of the S3C DMA API. That should not have any affect since those data structures are completely invisible to the DMA clients. Signed-off-by: Jassi Brar Signed-off-by: Ben Dooks diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig index d552c65..78b8b89 100644 --- a/arch/arm/plat-samsung/Kconfig +++ b/arch/arm/plat-samsung/Kconfig @@ -198,6 +198,12 @@ config S3C_DMA help Internal configuration for S3C DMA core +config S3C_PL330_DMA + bool + select PL330 + help + S3C DMA API Driver for PL330 DMAC. + comment "Power management" config SAMSUNG_PM_DEBUG diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile index 22c89d0..05718a3 100644 --- a/arch/arm/plat-samsung/Makefile +++ b/arch/arm/plat-samsung/Makefile @@ -45,6 +45,8 @@ obj-$(CONFIG_S3C_DEV_NAND) += dev-nand.o obj-$(CONFIG_S3C_DMA) += dma.o +obj-$(CONFIG_S3C_PL330_DMA) += s3c-pl330.o + # PM support obj-$(CONFIG_PM) += pm.o diff --git a/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h b/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h new file mode 100644 index 0000000..5fe6721 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2010 Samsung Electronics Co. Ltd. + * Jaswinder Singh + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef __S3C_DMA_PL330_H_ +#define __S3C_DMA_PL330_H_ + +#define S3C2410_DMAF_AUTOSTART (1 << 0) +#define S3C2410_DMAF_CIRCULAR (1 << 1) + +/* + * PL330 can assign any channel to communicate with + * any of the peripherals attched to the DMAC. + * For the sake of consistency across client drivers, + * We keep the channel names unchanged and only add + * missing peripherals are added. + * Order is not important since S3C PL330 API driver + * use these just as IDs. + */ +enum dma_ch { + DMACH_UART0_RX, + DMACH_UART0_TX, + DMACH_UART1_RX, + DMACH_UART1_TX, + DMACH_UART2_RX, + DMACH_UART2_TX, + DMACH_UART3_RX, + DMACH_UART3_TX, + DMACH_IRDA, + DMACH_I2S0_RX, + DMACH_I2S0_TX, + DMACH_I2S0S_TX, + DMACH_I2S1_RX, + DMACH_I2S1_TX, + DMACH_I2S2_RX, + DMACH_I2S2_TX, + DMACH_SPI0_RX, + DMACH_SPI0_TX, + DMACH_SPI1_RX, + DMACH_SPI1_TX, + DMACH_SPI2_RX, + DMACH_SPI2_TX, + DMACH_AC97_MICIN, + DMACH_AC97_PCMIN, + DMACH_AC97_PCMOUT, + DMACH_EXTERNAL, + DMACH_PWM, + DMACH_SPDIF, + DMACH_HSI_RX, + DMACH_HSI_TX, + DMACH_PCM0_TX, + DMACH_PCM0_RX, + DMACH_PCM1_TX, + DMACH_PCM1_RX, + DMACH_PCM2_TX, + DMACH_PCM2_RX, + DMACH_MSM_REQ3, + DMACH_MSM_REQ2, + DMACH_MSM_REQ1, + DMACH_MSM_REQ0, + /* END Marker, also used to denote a reserved channel */ + DMACH_MAX, +}; + +static inline bool s3c_dma_has_circular(void) +{ + return true; +} + +#include + +#endif /* __S3C_DMA_PL330_H_ */ diff --git a/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h b/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h new file mode 100644 index 0000000..bf5e2a9 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h @@ -0,0 +1,32 @@ +/* linux/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h + * + * Copyright (C) 2010 Samsung Electronics Co. Ltd. + * Jaswinder Singh + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef __S3C_PL330_PDATA_H +#define __S3C_PL330_PDATA_H + +#include + +/* + * Every PL330 DMAC has max 32 peripheral interfaces, + * of which some may be not be really used in your + * DMAC's configuration. + * Populate this array of 32 peri i/fs with relevant + * channel IDs for used peri i/f and DMACH_MAX for + * those unused. + * + * The platforms just need to provide this info + * to the S3C DMA API driver for PL330. + */ +struct s3c_pl330_platdata { + enum dma_ch peri[32]; +}; + +#endif /* __S3C_PL330_PDATA_H */ diff --git a/arch/arm/plat-samsung/s3c-pl330.c b/arch/arm/plat-samsung/s3c-pl330.c new file mode 100644 index 0000000..a91305a --- /dev/null +++ b/arch/arm/plat-samsung/s3c-pl330.c @@ -0,0 +1,1224 @@ +/* linux/arch/arm/plat-samsung/s3c-pl330.c + * + * Copyright (C) 2010 Samsung Electronics Co. Ltd. + * Jaswinder Singh + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include + +/** + * struct s3c_pl330_dmac - Logical representation of a PL330 DMAC. + * @busy_chan: Number of channels currently busy. + * @peri: List of IDs of peripherals this DMAC can work with. + * @node: To attach to the global list of DMACs. + * @pi: PL330 configuration info for the DMAC. + * @kmcache: Pool to quickly allocate xfers for all channels in the dmac. + */ +struct s3c_pl330_dmac { + unsigned busy_chan; + enum dma_ch *peri; + struct list_head node; + struct pl330_info *pi; + struct kmem_cache *kmcache; +}; + +/** + * struct s3c_pl330_xfer - A request submitted by S3C DMA clients. + * @token: Xfer ID provided by the client. + * @node: To attach to the list of xfers on a channel. + * @px: Xfer for PL330 core. + * @chan: Owner channel of this xfer. + */ +struct s3c_pl330_xfer { + void *token; + struct list_head node; + struct pl330_xfer px; + struct s3c_pl330_chan *chan; +}; + +/** + * struct s3c_pl330_chan - Logical channel to communicate with + * a Physical peripheral. + * @pl330_chan_id: Token of a hardware channel thread of PL330 DMAC. + * NULL if the channel is available to be acquired. + * @id: ID of the peripheral that this channel can communicate with. + * @options: Options specified by the client. + * @sdaddr: Address provided via s3c2410_dma_devconfig. + * @node: To attach to the global list of channels. + * @lrq: Pointer to the last submitted pl330_req to PL330 core. + * @xfer_list: To manage list of xfers enqueued. + * @req: Two requests to communicate with the PL330 engine. + * @callback_fn: Callback function to the client. + * @rqcfg: Channel configuration for the xfers. + * @xfer_head: Pointer to the xfer to be next excecuted. + * @dmac: Pointer to the DMAC that manages this channel, NULL if the + * channel is available to be acquired. + * @client: Client of this channel. NULL if the + * channel is available to be acquired. + */ +struct s3c_pl330_chan { + void *pl330_chan_id; + enum dma_ch id; + unsigned int options; + unsigned long sdaddr; + struct list_head node; + struct pl330_req *lrq; + struct list_head xfer_list; + struct pl330_req req[2]; + s3c2410_dma_cbfn_t callback_fn; + struct pl330_reqcfg rqcfg; + struct s3c_pl330_xfer *xfer_head; + struct s3c_pl330_dmac *dmac; + struct s3c2410_dma_client *client; +}; + +/* All DMACs in the platform */ +static LIST_HEAD(dmac_list); + +/* All channels to peripherals in the platform */ +static LIST_HEAD(chan_list); + +/* + * Since we add resources(DMACs and Channels) to the global pool, + * we need to guard access to the resources using a global lock + */ +static DEFINE_SPINLOCK(res_lock); + +/* Returns the channel with ID 'id' in the chan_list */ +static struct s3c_pl330_chan *id_to_chan(const enum dma_ch id) +{ + struct s3c_pl330_chan *ch; + + list_for_each_entry(ch, &chan_list, node) + if (ch->id == id) + return ch; + + return NULL; +} + +/* Allocate a new channel with ID 'id' and add to chan_list */ +static void chan_add(const enum dma_ch id) +{ + struct s3c_pl330_chan *ch = id_to_chan(id); + + /* Return if the channel already exists */ + if (ch) + return; + + ch = kmalloc(sizeof(*ch), GFP_KERNEL); + /* Return silently to work with other channels */ + if (!ch) + return; + + ch->id = id; + ch->dmac = NULL; + + list_add_tail(&ch->node, &chan_list); +} + +/* If the channel is not yet acquired by any client */ +static bool chan_free(struct s3c_pl330_chan *ch) +{ + if (!ch) + return false; + + /* Channel points to some DMAC only when it's acquired */ + return ch->dmac ? false : true; +} + +/* + * Returns 0 is peripheral i/f is invalid or not present on the dmac. + * Index + 1, otherwise. + */ +static unsigned iface_of_dmac(struct s3c_pl330_dmac *dmac, enum dma_ch ch_id) +{ + enum dma_ch *id = dmac->peri; + int i; + + /* Discount invalid markers */ + if (ch_id == DMACH_MAX) + return 0; + + for (i = 0; i < PL330_MAX_PERI; i++) + if (id[i] == ch_id) + return i + 1; + + return 0; +} + +/* If all channel threads of the DMAC are busy */ +static inline bool dmac_busy(struct s3c_pl330_dmac *dmac) +{ + struct pl330_info *pi = dmac->pi; + + return (dmac->busy_chan < pi->pcfg.num_chan) ? false : true; +} + +/* + * Returns the number of free channels that + * can be handled by this dmac only. + */ +static unsigned ch_onlyby_dmac(struct s3c_pl330_dmac *dmac) +{ + enum dma_ch *id = dmac->peri; + struct s3c_pl330_dmac *d; + struct s3c_pl330_chan *ch; + unsigned found, count = 0; + enum dma_ch p; + int i; + + for (i = 0; i < PL330_MAX_PERI; i++) { + p = id[i]; + ch = id_to_chan(p); + + if (p == DMACH_MAX || !chan_free(ch)) + continue; + + found = 0; + list_for_each_entry(d, &dmac_list, node) { + if (d != dmac && iface_of_dmac(d, ch->id)) { + found = 1; + break; + } + } + if (!found) + count++; + } + + return count; +} + +/* + * Measure of suitability of 'dmac' handling 'ch' + * + * 0 indicates 'dmac' can not handle 'ch' either + * because it is not supported by the hardware or + * because all dmac channels are currently busy. + * + * >0 vlaue indicates 'dmac' has the capability. + * The bigger the value the more suitable the dmac. + */ +#define MAX_SUIT UINT_MAX +#define MIN_SUIT 0 + +static unsigned suitablility(struct s3c_pl330_dmac *dmac, + struct s3c_pl330_chan *ch) +{ + struct pl330_info *pi = dmac->pi; + enum dma_ch *id = dmac->peri; + struct s3c_pl330_dmac *d; + unsigned s; + int i; + + s = MIN_SUIT; + /* If all the DMAC channel threads are busy */ + if (dmac_busy(dmac)) + return s; + + for (i = 0; i < PL330_MAX_PERI; i++) + if (id[i] == ch->id) + break; + + /* If the 'dmac' can't talk to 'ch' */ + if (i == PL330_MAX_PERI) + return s; + + s = MAX_SUIT; + list_for_each_entry(d, &dmac_list, node) { + /* + * If some other dmac can talk to this + * peri and has some channel free. + */ + if (d != dmac && iface_of_dmac(d, ch->id) && !dmac_busy(d)) { + s = 0; + break; + } + } + if (s) + return s; + + s = 100; + + /* Good if free chans are more, bad otherwise */ + s += (pi->pcfg.num_chan - dmac->busy_chan) - ch_onlyby_dmac(dmac); + + return s; +} + +/* More than one DMAC may have capability to transfer data with the + * peripheral. This function assigns most suitable DMAC to manage the + * channel and hence communicate with the peripheral. + */ +static struct s3c_pl330_dmac *map_chan_to_dmac(struct s3c_pl330_chan *ch) +{ + struct s3c_pl330_dmac *d, *dmac = NULL; + unsigned sn, sl = MIN_SUIT; + + list_for_each_entry(d, &dmac_list, node) { + sn = suitablility(d, ch); + + if (sn == MAX_SUIT) + return d; + + if (sn > sl) + dmac = d; + } + + return dmac; +} + +/* Acquire the channel for peripheral 'id' */ +static struct s3c_pl330_chan *chan_acquire(const enum dma_ch id) +{ + struct s3c_pl330_chan *ch = id_to_chan(id); + struct s3c_pl330_dmac *dmac; + + /* If the channel doesn't exist or is already acquired */ + if (!ch || !chan_free(ch)) { + ch = NULL; + goto acq_exit; + } + + dmac = map_chan_to_dmac(ch); + /* If couldn't map */ + if (!dmac) { + ch = NULL; + goto acq_exit; + } + + dmac->busy_chan++; + ch->dmac = dmac; + +acq_exit: + return ch; +} + +/* Delete xfer from the queue */ +static inline void del_from_queue(struct s3c_pl330_xfer *xfer) +{ + struct s3c_pl330_xfer *t; + struct s3c_pl330_chan *ch; + int found; + + if (!xfer) + return; + + ch = xfer->chan; + + /* Make sure xfer is in the queue */ + found = 0; + list_for_each_entry(t, &ch->xfer_list, node) + if (t == xfer) { + found = 1; + break; + } + + if (!found) + return; + + /* If xfer is last entry in the queue */ + if (xfer->node.next == &ch->xfer_list) + t = list_entry(ch->xfer_list.next, + struct s3c_pl330_xfer, node); + else + t = list_entry(xfer->node.next, + struct s3c_pl330_xfer, node); + + /* If there was only one node left */ + if (t == xfer) + ch->xfer_head = NULL; + else if (ch->xfer_head == xfer) + ch->xfer_head = t; + + list_del(&xfer->node); +} + +/* Provides pointer to the next xfer in the queue. + * If CIRCULAR option is set, the list is left intact, + * otherwise the xfer is removed from the list. + * Forced delete 'pluck' can be set to override the CIRCULAR option. + */ +static struct s3c_pl330_xfer *get_from_queue(struct s3c_pl330_chan *ch, + int pluck) +{ + struct s3c_pl330_xfer *xfer = ch->xfer_head; + + if (!xfer) + return NULL; + + /* If xfer is last entry in the queue */ + if (xfer->node.next == &ch->xfer_list) + ch->xfer_head = list_entry(ch->xfer_list.next, + struct s3c_pl330_xfer, node); + else + ch->xfer_head = list_entry(xfer->node.next, + struct s3c_pl330_xfer, node); + + if (pluck || !(ch->options & S3C2410_DMAF_CIRCULAR)) + del_from_queue(xfer); + + return xfer; +} + +static inline void add_to_queue(struct s3c_pl330_chan *ch, + struct s3c_pl330_xfer *xfer, int front) +{ + struct pl330_xfer *xt; + + /* If queue empty */ + if (ch->xfer_head == NULL) + ch->xfer_head = xfer; + + xt = &ch->xfer_head->px; + /* If the head already submitted (CIRCULAR head) */ + if (ch->options & S3C2410_DMAF_CIRCULAR && + (xt == ch->req[0].x || xt == ch->req[1].x)) + ch->xfer_head = xfer; + + /* If this is a resubmission, it should go at the head */ + if (front) { + ch->xfer_head = xfer; + list_add(&xfer->node, &ch->xfer_list); + } else { + list_add_tail(&xfer->node, &ch->xfer_list); + } +} + +static inline void _finish_off(struct s3c_pl330_xfer *xfer, + enum s3c2410_dma_buffresult res, int ffree) +{ + struct s3c_pl330_chan *ch; + + if (!xfer) + return; + + ch = xfer->chan; + + /* Do callback */ + if (ch->callback_fn) + ch->callback_fn(NULL, xfer->token, xfer->px.bytes, res); + + /* Force Free or if buffer is not needed anymore */ + if (ffree || !(ch->options & S3C2410_DMAF_CIRCULAR)) + kmem_cache_free(ch->dmac->kmcache, xfer); +} + +static inline int s3c_pl330_submit(struct s3c_pl330_chan *ch, + struct pl330_req *r) +{ + struct s3c_pl330_xfer *xfer; + int ret = 0; + + /* If already submitted */ + if (r->x) + return 0; + + xfer = get_from_queue(ch, 0); + if (xfer) { + r->x = &xfer->px; + + /* Use max bandwidth for M<->M xfers */ + if (r->rqtype == MEMTOMEM) { + struct pl330_info *pi = xfer->chan->dmac->pi; + int burst = 1 << ch->rqcfg.brst_size; + u32 bytes = r->x->bytes; + int bl; + + bl = pi->pcfg.data_bus_width / 8; + bl *= pi->pcfg.data_buf_dep; + bl /= burst; + + /* src/dst_burst_len can't be more than 16 */ + if (bl > 16) + bl = 16; + + while (bl > 1) { + if (!(bytes % (bl * burst))) + break; + bl--; + } + + ch->rqcfg.brst_len = bl; + } else { + ch->rqcfg.brst_len = 1; + } + + ret = pl330_submit_req(ch->pl330_chan_id, r); + + /* If submission was successful */ + if (!ret) { + ch->lrq = r; /* latest submitted req */ + return 0; + } + + r->x = NULL; + + /* If both of the PL330 ping-pong buffers filled */ + if (ret == -EAGAIN) { + dev_err(ch->dmac->pi->dev, "%s:%d!\n", + __func__, __LINE__); + /* Queue back again */ + add_to_queue(ch, xfer, 1); + ret = 0; + } else { + dev_err(ch->dmac->pi->dev, "%s:%d!\n", + __func__, __LINE__); + _finish_off(xfer, S3C2410_RES_ERR, 0); + } + } + + return ret; +} + +static void s3c_pl330_rq(struct s3c_pl330_chan *ch, + struct pl330_req *r, enum pl330_op_err err) +{ + unsigned long flags; + struct s3c_pl330_xfer *xfer; + struct pl330_xfer *xl = r->x; + enum s3c2410_dma_buffresult res; + + spin_lock_irqsave(&res_lock, flags); + + r->x = NULL; + + s3c_pl330_submit(ch, r); + + spin_unlock_irqrestore(&res_lock, flags); + + /* Map result to S3C DMA API */ + if (err == PL330_ERR_NONE) + res = S3C2410_RES_OK; + else if (err == PL330_ERR_ABORT) + res = S3C2410_RES_ABORT; + else + res = S3C2410_RES_ERR; + + /* If last request had some xfer */ + if (xl) { + xfer = container_of(xl, struct s3c_pl330_xfer, px); + _finish_off(xfer, res, 0); + } else { + dev_info(ch->dmac->pi->dev, "%s:%d No Xfer?!\n", + __func__, __LINE__); + } +} + +static void s3c_pl330_rq0(void *token, enum pl330_op_err err) +{ + struct pl330_req *r = token; + struct s3c_pl330_chan *ch = container_of(r, + struct s3c_pl330_chan, req[0]); + s3c_pl330_rq(ch, r, err); +} + +static void s3c_pl330_rq1(void *token, enum pl330_op_err err) +{ + struct pl330_req *r = token; + struct s3c_pl330_chan *ch = container_of(r, + struct s3c_pl330_chan, req[1]); + s3c_pl330_rq(ch, r, err); +} + +/* Release an acquired channel */ +static void chan_release(struct s3c_pl330_chan *ch) +{ + struct s3c_pl330_dmac *dmac; + + if (chan_free(ch)) + return; + + dmac = ch->dmac; + ch->dmac = NULL; + dmac->busy_chan--; +} + +int s3c2410_dma_ctrl(enum dma_ch id, enum s3c2410_chan_op op) +{ + struct s3c_pl330_xfer *xfer; + enum pl330_chan_op pl330op; + struct s3c_pl330_chan *ch; + unsigned long flags; + int idx, ret; + + spin_lock_irqsave(&res_lock, flags); + + ch = id_to_chan(id); + + if (!ch || chan_free(ch)) { + ret = -EINVAL; + goto ctrl_exit; + } + + switch (op) { + case S3C2410_DMAOP_START: + /* Make sure both reqs are enqueued */ + idx = (ch->lrq == &ch->req[0]) ? 1 : 0; + s3c_pl330_submit(ch, &ch->req[idx]); + s3c_pl330_submit(ch, &ch->req[1 - idx]); + pl330op = PL330_OP_START; + break; + + case S3C2410_DMAOP_STOP: + pl330op = PL330_OP_ABORT; + break; + + case S3C2410_DMAOP_FLUSH: + pl330op = PL330_OP_FLUSH; + break; + + case S3C2410_DMAOP_PAUSE: + case S3C2410_DMAOP_RESUME: + case S3C2410_DMAOP_TIMEOUT: + case S3C2410_DMAOP_STARTED: + spin_unlock_irqrestore(&res_lock, flags); + return 0; + + default: + spin_unlock_irqrestore(&res_lock, flags); + return -EINVAL; + } + + ret = pl330_chan_ctrl(ch->pl330_chan_id, pl330op); + + if (pl330op == PL330_OP_START) { + spin_unlock_irqrestore(&res_lock, flags); + return ret; + } + + idx = (ch->lrq == &ch->req[0]) ? 1 : 0; + + /* Abort the current xfer */ + if (ch->req[idx].x) { + xfer = container_of(ch->req[idx].x, + struct s3c_pl330_xfer, px); + + /* Drop xfer during FLUSH */ + if (pl330op == PL330_OP_FLUSH) + del_from_queue(xfer); + + ch->req[idx].x = NULL; + + spin_unlock_irqrestore(&res_lock, flags); + _finish_off(xfer, S3C2410_RES_ABORT, + pl330op == PL330_OP_FLUSH ? 1 : 0); + spin_lock_irqsave(&res_lock, flags); + } + + /* Flush the whole queue */ + if (pl330op == PL330_OP_FLUSH) { + + if (ch->req[1 - idx].x) { + xfer = container_of(ch->req[1 - idx].x, + struct s3c_pl330_xfer, px); + + del_from_queue(xfer); + + ch->req[1 - idx].x = NULL; + + spin_unlock_irqrestore(&res_lock, flags); + _finish_off(xfer, S3C2410_RES_ABORT, 1); + spin_lock_irqsave(&res_lock, flags); + } + + /* Finish off the remaining in the queue */ + xfer = ch->xfer_head; + while (xfer) { + + del_from_queue(xfer); + + spin_unlock_irqrestore(&res_lock, flags); + _finish_off(xfer, S3C2410_RES_ABORT, 1); + spin_lock_irqsave(&res_lock, flags); + + xfer = ch->xfer_head; + } + } + +ctrl_exit: + spin_unlock_irqrestore(&res_lock, flags); + + return ret; +} +EXPORT_SYMBOL(s3c2410_dma_ctrl); + +int s3c2410_dma_enqueue(enum dma_ch id, void *token, + dma_addr_t addr, int size) +{ + struct s3c_pl330_chan *ch; + struct s3c_pl330_xfer *xfer; + unsigned long flags; + int idx, ret = 0; + + spin_lock_irqsave(&res_lock, flags); + + ch = id_to_chan(id); + + /* Error if invalid or free channel */ + if (!ch || chan_free(ch)) { + ret = -EINVAL; + goto enq_exit; + } + + /* Error if size is unaligned */ + if (ch->rqcfg.brst_size && size % (1 << ch->rqcfg.brst_size)) { + ret = -EINVAL; + goto enq_exit; + } + + xfer = kmem_cache_alloc(ch->dmac->kmcache, GFP_ATOMIC); + if (!xfer) { + ret = -ENOMEM; + goto enq_exit; + } + + xfer->token = token; + xfer->chan = ch; + xfer->px.bytes = size; + xfer->px.next = NULL; /* Single request */ + + /* For S3C DMA API, direction is always fixed for all xfers */ + if (ch->req[0].rqtype == MEMTODEV) { + xfer->px.src_addr = addr; + xfer->px.dst_addr = ch->sdaddr; + } else { + xfer->px.src_addr = ch->sdaddr; + xfer->px.dst_addr = addr; + } + + add_to_queue(ch, xfer, 0); + + /* Try submitting on either request */ + idx = (ch->lrq == &ch->req[0]) ? 1 : 0; + + if (!ch->req[idx].x) + s3c_pl330_submit(ch, &ch->req[idx]); + else + s3c_pl330_submit(ch, &ch->req[1 - idx]); + + spin_unlock_irqrestore(&res_lock, flags); + + if (ch->options & S3C2410_DMAF_AUTOSTART) + s3c2410_dma_ctrl(id, S3C2410_DMAOP_START); + + return 0; + +enq_exit: + spin_unlock_irqrestore(&res_lock, flags); + + return ret; +} +EXPORT_SYMBOL(s3c2410_dma_enqueue); + +int s3c2410_dma_request(enum dma_ch id, + struct s3c2410_dma_client *client, + void *dev) +{ + struct s3c_pl330_dmac *dmac; + struct s3c_pl330_chan *ch; + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&res_lock, flags); + + ch = chan_acquire(id); + if (!ch) { + ret = -EBUSY; + goto req_exit; + } + + dmac = ch->dmac; + + ch->pl330_chan_id = pl330_request_channel(dmac->pi); + if (!ch->pl330_chan_id) { + chan_release(ch); + ret = -EBUSY; + goto req_exit; + } + + ch->client = client; + ch->options = 0; /* Clear any option */ + ch->callback_fn = NULL; /* Clear any callback */ + ch->lrq = NULL; + + ch->rqcfg.brst_size = 2; /* Default word size */ + ch->rqcfg.swap = SWAP_NO; + ch->rqcfg.scctl = SCCTRL0; /* Noncacheable and nonbufferable */ + ch->rqcfg.dcctl = DCCTRL0; /* Noncacheable and nonbufferable */ + ch->rqcfg.privileged = 0; + ch->rqcfg.insnaccess = 0; + + /* Set invalid direction */ + ch->req[0].rqtype = DEVTODEV; + ch->req[1].rqtype = ch->req[0].rqtype; + + ch->req[0].cfg = &ch->rqcfg; + ch->req[1].cfg = ch->req[0].cfg; + + ch->req[0].peri = iface_of_dmac(dmac, id) - 1; /* Original index */ + ch->req[1].peri = ch->req[0].peri; + + ch->req[0].token = &ch->req[0]; + ch->req[0].xfer_cb = s3c_pl330_rq0; + ch->req[1].token = &ch->req[1]; + ch->req[1].xfer_cb = s3c_pl330_rq1; + + ch->req[0].x = NULL; + ch->req[1].x = NULL; + + /* Reset xfer list */ + INIT_LIST_HEAD(&ch->xfer_list); + ch->xfer_head = NULL; + +req_exit: + spin_unlock_irqrestore(&res_lock, flags); + + return ret; +} +EXPORT_SYMBOL(s3c2410_dma_request); + +int s3c2410_dma_free(enum dma_ch id, struct s3c2410_dma_client *client) +{ + struct s3c_pl330_chan *ch; + struct s3c_pl330_xfer *xfer; + unsigned long flags; + int ret = 0; + unsigned idx; + + spin_lock_irqsave(&res_lock, flags); + + ch = id_to_chan(id); + + if (!ch || chan_free(ch)) + goto free_exit; + + /* Refuse if someone else wanted to free the channel */ + if (ch->client != client) { + ret = -EBUSY; + goto free_exit; + } + + /* Stop any active xfer, Flushe the queue and do callbacks */ + pl330_chan_ctrl(ch->pl330_chan_id, PL330_OP_FLUSH); + + /* Abort the submitted requests */ + idx = (ch->lrq == &ch->req[0]) ? 1 : 0; + + if (ch->req[idx].x) { + xfer = container_of(ch->req[idx].x, + struct s3c_pl330_xfer, px); + + ch->req[idx].x = NULL; + del_from_queue(xfer); + + spin_unlock_irqrestore(&res_lock, flags); + _finish_off(xfer, S3C2410_RES_ABORT, 1); + spin_lock_irqsave(&res_lock, flags); + } + + if (ch->req[1 - idx].x) { + xfer = container_of(ch->req[1 - idx].x, + struct s3c_pl330_xfer, px); + + ch->req[1 - idx].x = NULL; + del_from_queue(xfer); + + spin_unlock_irqrestore(&res_lock, flags); + _finish_off(xfer, S3C2410_RES_ABORT, 1); + spin_lock_irqsave(&res_lock, flags); + } + + /* Pluck and Abort the queued requests in order */ + do { + xfer = get_from_queue(ch, 1); + + spin_unlock_irqrestore(&res_lock, flags); + _finish_off(xfer, S3C2410_RES_ABORT, 1); + spin_lock_irqsave(&res_lock, flags); + } while (xfer); + + ch->client = NULL; + + pl330_release_channel(ch->pl330_chan_id); + + ch->pl330_chan_id = NULL; + + chan_release(ch); + +free_exit: + spin_unlock_irqrestore(&res_lock, flags); + + return ret; +} +EXPORT_SYMBOL(s3c2410_dma_free); + +int s3c2410_dma_config(enum dma_ch id, int xferunit) +{ + struct s3c_pl330_chan *ch; + struct pl330_info *pi; + unsigned long flags; + int i, dbwidth, ret = 0; + + spin_lock_irqsave(&res_lock, flags); + + ch = id_to_chan(id); + + if (!ch || chan_free(ch)) { + ret = -EINVAL; + goto cfg_exit; + } + + pi = ch->dmac->pi; + dbwidth = pi->pcfg.data_bus_width / 8; + + /* Max size of xfer can be pcfg.data_bus_width */ + if (xferunit > dbwidth) { + ret = -EINVAL; + goto cfg_exit; + } + + i = 0; + while (xferunit != (1 << i)) + i++; + + /* If valid value */ + if (xferunit == (1 << i)) + ch->rqcfg.brst_size = i; + else + ret = -EINVAL; + +cfg_exit: + spin_unlock_irqrestore(&res_lock, flags); + + return ret; +} +EXPORT_SYMBOL(s3c2410_dma_config); + +/* Options that are supported by this driver */ +#define S3C_PL330_FLAGS (S3C2410_DMAF_CIRCULAR | S3C2410_DMAF_AUTOSTART) + +int s3c2410_dma_setflags(enum dma_ch id, unsigned int options) +{ + struct s3c_pl330_chan *ch; + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&res_lock, flags); + + ch = id_to_chan(id); + + if (!ch || chan_free(ch) || options & ~(S3C_PL330_FLAGS)) + ret = -EINVAL; + else + ch->options = options; + + spin_unlock_irqrestore(&res_lock, flags); + + return 0; +} +EXPORT_SYMBOL(s3c2410_dma_setflags); + +int s3c2410_dma_set_buffdone_fn(enum dma_ch id, s3c2410_dma_cbfn_t rtn) +{ + struct s3c_pl330_chan *ch; + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&res_lock, flags); + + ch = id_to_chan(id); + + if (!ch || chan_free(ch)) + ret = -EINVAL; + else + ch->callback_fn = rtn; + + spin_unlock_irqrestore(&res_lock, flags); + + return ret; +} +EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn); + +int s3c2410_dma_devconfig(enum dma_ch id, enum s3c2410_dmasrc source, + unsigned long address) +{ + struct s3c_pl330_chan *ch; + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&res_lock, flags); + + ch = id_to_chan(id); + + if (!ch || chan_free(ch)) { + ret = -EINVAL; + goto devcfg_exit; + } + + switch (source) { + case S3C2410_DMASRC_HW: /* P->M */ + ch->req[0].rqtype = DEVTOMEM; + ch->req[1].rqtype = DEVTOMEM; + ch->rqcfg.src_inc = 0; + ch->rqcfg.dst_inc = 1; + break; + case S3C2410_DMASRC_MEM: /* M->P */ + ch->req[0].rqtype = MEMTODEV; + ch->req[1].rqtype = MEMTODEV; + ch->rqcfg.src_inc = 1; + ch->rqcfg.dst_inc = 0; + break; + default: + ret = -EINVAL; + goto devcfg_exit; + } + + ch->sdaddr = address; + +devcfg_exit: + spin_unlock_irqrestore(&res_lock, flags); + + return ret; +} +EXPORT_SYMBOL(s3c2410_dma_devconfig); + +int s3c2410_dma_getposition(enum dma_ch id, dma_addr_t *src, dma_addr_t *dst) +{ + struct s3c_pl330_chan *ch = id_to_chan(id); + struct pl330_chanstatus status; + int ret; + + if (!ch || chan_free(ch)) + return -EINVAL; + + ret = pl330_chan_status(ch->pl330_chan_id, &status); + if (ret < 0) + return ret; + + *src = status.src_addr; + *dst = status.dst_addr; + + return 0; +} +EXPORT_SYMBOL(s3c2410_dma_getposition); + +static irqreturn_t pl330_irq_handler(int irq, void *data) +{ + if (pl330_update(data)) + return IRQ_HANDLED; + else + return IRQ_NONE; +} + +static int pl330_probe(struct platform_device *pdev) +{ + struct s3c_pl330_dmac *s3c_pl330_dmac; + struct s3c_pl330_platdata *pl330pd; + struct pl330_info *pl330_info; + struct resource *res; + int i, ret, irq; + + pl330pd = pdev->dev.platform_data; + + /* Can't do without the list of _32_ peripherals */ + if (!pl330pd || !pl330pd->peri) { + dev_err(&pdev->dev, "platform data missing!\n"); + return -ENODEV; + } + + pl330_info = kzalloc(sizeof(*pl330_info), GFP_KERNEL); + if (!pl330_info) + return -ENOMEM; + + pl330_info->pl330_data = NULL; + pl330_info->dev = &pdev->dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + ret = -ENODEV; + goto probe_err1; + } + + request_mem_region(res->start, resource_size(res), pdev->name); + + pl330_info->base = ioremap(res->start, resource_size(res)); + if (!pl330_info->base) { + ret = -ENXIO; + goto probe_err2; + } + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + ret = irq; + goto probe_err3; + } + + ret = request_irq(irq, pl330_irq_handler, 0, + dev_name(&pdev->dev), pl330_info); + if (ret) + goto probe_err4; + + ret = pl330_add(pl330_info); + if (ret) + goto probe_err5; + + /* Allocate a new DMAC */ + s3c_pl330_dmac = kmalloc(sizeof(*s3c_pl330_dmac), GFP_KERNEL); + if (!s3c_pl330_dmac) { + ret = -ENOMEM; + goto probe_err6; + } + + /* Hook the info */ + s3c_pl330_dmac->pi = pl330_info; + + /* No busy channels */ + s3c_pl330_dmac->busy_chan = 0; + + s3c_pl330_dmac->kmcache = kmem_cache_create(dev_name(&pdev->dev), + sizeof(struct s3c_pl330_xfer), 0, 0, NULL); + + if (!s3c_pl330_dmac->kmcache) { + ret = -ENOMEM; + goto probe_err7; + } + + /* Get the list of peripherals */ + s3c_pl330_dmac->peri = pl330pd->peri; + + /* Attach to the list of DMACs */ + list_add_tail(&s3c_pl330_dmac->node, &dmac_list); + + /* Create a channel for each peripheral in the DMAC + * that is, if it doesn't already exist + */ + for (i = 0; i < PL330_MAX_PERI; i++) + if (s3c_pl330_dmac->peri[i] != DMACH_MAX) + chan_add(s3c_pl330_dmac->peri[i]); + + printk(KERN_INFO + "Loaded driver for PL330 DMAC-%d %s\n", pdev->id, pdev->name); + printk(KERN_INFO + "\tDBUFF-%ux%ubytes Num_Chans-%u Num_Peri-%u Num_Events-%u\n", + pl330_info->pcfg.data_buf_dep, + pl330_info->pcfg.data_bus_width / 8, pl330_info->pcfg.num_chan, + pl330_info->pcfg.num_peri, pl330_info->pcfg.num_events); + + return 0; + +probe_err7: + kfree(s3c_pl330_dmac); +probe_err6: + pl330_del(pl330_info); +probe_err5: + free_irq(irq, pl330_info); +probe_err4: +probe_err3: + iounmap(pl330_info->base); +probe_err2: + release_mem_region(res->start, resource_size(res)); +probe_err1: + kfree(pl330_info); + + return ret; +} + +static int pl330_remove(struct platform_device *pdev) +{ + struct s3c_pl330_dmac *dmac, *d; + struct s3c_pl330_chan *ch; + unsigned long flags; + int del, found; + + if (!pdev->dev.platform_data) + return -EINVAL; + + spin_lock_irqsave(&res_lock, flags); + + found = 0; + list_for_each_entry(d, &dmac_list, node) + if (d->pi->dev == &pdev->dev) { + found = 1; + break; + } + + if (!found) { + spin_unlock_irqrestore(&res_lock, flags); + return 0; + } + + dmac = d; + + /* Remove all Channels that are managed only by this DMAC */ + list_for_each_entry(ch, &chan_list, node) { + + /* Only channels that are handled by this DMAC */ + if (iface_of_dmac(dmac, ch->id)) + del = 1; + else + continue; + + /* Don't remove if some other DMAC has it too */ + list_for_each_entry(d, &dmac_list, node) + if (d != dmac && iface_of_dmac(d, ch->id)) { + del = 0; + break; + } + + if (del) { + spin_unlock_irqrestore(&res_lock, flags); + s3c2410_dma_free(ch->id, ch->client); + spin_lock_irqsave(&res_lock, flags); + list_del(&ch->node); + kfree(ch); + } + } + + /* Remove the DMAC */ + list_del(&dmac->node); + kfree(dmac); + + spin_unlock_irqrestore(&res_lock, flags); + + return 0; +} + +static struct platform_driver pl330_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "s3c-pl330", + }, + .probe = pl330_probe, + .remove = pl330_remove, +}; + +static int __init pl330_init(void) +{ + return platform_driver_register(&pl330_driver); +} +module_init(pl330_init); + +static void __exit pl330_exit(void) +{ + platform_driver_unregister(&pl330_driver); + return; +} +module_exit(pl330_exit); + +MODULE_AUTHOR("Jaswinder Singh "); +MODULE_DESCRIPTION("Driver for PL330 DMA Controller"); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From d8b5065b75e87e87c2cbba984b3050e869b4b910 Mon Sep 17 00:00:00 2001 From: Jassi Brar Date: Tue, 18 May 2010 11:59:20 +0900 Subject: S5P6440: DMA: Add platform devices for PL330 DMACs Samsung's Soc S5P6440 has one PL330 DMAC. Define and add the PL330 DMAC as platform device on the S5P6440 platform. Signed-off-by: Jassi Brar Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5p6440/Kconfig b/arch/arm/mach-s5p6440/Kconfig index 4c29ff8..77aeffd 100644 --- a/arch/arm/mach-s5p6440/Kconfig +++ b/arch/arm/mach-s5p6440/Kconfig @@ -9,6 +9,7 @@ if ARCH_S5P6440 config CPU_S5P6440 bool + select S3C_PL330_DMA help Enable S5P6440 CPU support diff --git a/arch/arm/mach-s5p6440/Makefile b/arch/arm/mach-s5p6440/Makefile index 1ad894b..3f243dd 100644 --- a/arch/arm/mach-s5p6440/Makefile +++ b/arch/arm/mach-s5p6440/Makefile @@ -12,7 +12,7 @@ obj- := # Core support for S5P6440 system -obj-$(CONFIG_CPU_S5P6440) += cpu.o init.o clock.o gpio.o +obj-$(CONFIG_CPU_S5P6440) += cpu.o init.o clock.o gpio.o dma.o # machine support diff --git a/arch/arm/mach-s5p6440/dma.c b/arch/arm/mach-s5p6440/dma.c new file mode 100644 index 0000000..07606ad --- /dev/null +++ b/arch/arm/mach-s5p6440/dma.c @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2010 Samsung Electronics Co. Ltd. + * Jaswinder Singh + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#include +#include + +#include +#include + +#include + +static u64 dma_dmamask = DMA_BIT_MASK(32); + +static struct resource s5p6440_pdma_resource[] = { + [0] = { + .start = S5P6440_PA_PDMA, + .end = S5P6440_PA_PDMA + SZ_4K, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_DMA0, + .end = IRQ_DMA0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct s3c_pl330_platdata s5p6440_pdma_pdata = { + .peri = { + [0] = DMACH_UART0_RX, + [1] = DMACH_UART0_TX, + [2] = DMACH_UART1_RX, + [3] = DMACH_UART1_TX, + [4] = DMACH_UART2_RX, + [5] = DMACH_UART2_TX, + [6] = DMACH_UART3_RX, + [7] = DMACH_UART3_TX, + [8] = DMACH_MAX, + [9] = DMACH_MAX, + [10] = DMACH_PCM0_TX, + [11] = DMACH_PCM0_RX, + [12] = DMACH_I2S0_TX, + [13] = DMACH_I2S0_RX, + [14] = DMACH_SPI0_TX, + [15] = DMACH_SPI0_RX, + [16] = DMACH_MAX, + [17] = DMACH_MAX, + [18] = DMACH_MAX, + [19] = DMACH_MAX, + [20] = DMACH_SPI1_TX, + [21] = DMACH_SPI1_RX, + [22] = DMACH_MAX, + [23] = DMACH_MAX, + [24] = DMACH_MAX, + [25] = DMACH_MAX, + [26] = DMACH_MAX, + [27] = DMACH_MAX, + [28] = DMACH_MAX, + [29] = DMACH_PWM, + [30] = DMACH_MAX, + [31] = DMACH_MAX, + }, +}; + +static struct platform_device s5p6440_device_pdma = { + .name = "s3c-pl330", + .id = 1, + .num_resources = ARRAY_SIZE(s5p6440_pdma_resource), + .resource = s5p6440_pdma_resource, + .dev = { + .dma_mask = &dma_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &s5p6440_pdma_pdata, + }, +}; + +static struct platform_device *s5p6440_dmacs[] __initdata = { + &s5p6440_device_pdma, +}; + +static int __init s5p6440_dma_init(void) +{ + platform_add_devices(s5p6440_dmacs, ARRAY_SIZE(s5p6440_dmacs)); + + return 0; +} +arch_initcall(s5p6440_dma_init); diff --git a/arch/arm/mach-s5p6440/include/mach/dma.h b/arch/arm/mach-s5p6440/include/mach/dma.h new file mode 100644 index 0000000..81209eb --- /dev/null +++ b/arch/arm/mach-s5p6440/include/mach/dma.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2010 Samsung Electronics Co. Ltd. + * Jaswinder Singh + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __MACH_DMA_H +#define __MACH_DMA_H + +/* This platform uses the common S3C DMA API driver for PL330 */ +#include + +#endif /* __MACH_DMA_H */ diff --git a/arch/arm/mach-s5p6440/include/mach/map.h b/arch/arm/mach-s5p6440/include/mach/map.h index 8924e5a..0275784 100644 --- a/arch/arm/mach-s5p6440/include/mach/map.h +++ b/arch/arm/mach-s5p6440/include/mach/map.h @@ -29,6 +29,8 @@ #define S5P6440_PA_VIC0 (0xE4000000) #define S5P_PA_VIC0 S5P6440_PA_VIC0 +#define S5P6440_PA_PDMA 0xE9000000 + #define S5P6440_PA_VIC1 (0xE4100000) #define S5P_PA_VIC1 S5P6440_PA_VIC1 -- cgit v0.10.2 From d460f5b035c3b1d192d7ba1dbca50cb441fef08e Mon Sep 17 00:00:00 2001 From: Jassi Brar Date: Tue, 18 May 2010 11:59:27 +0900 Subject: S5P6442: DMA: Add platform devices for PL330 DMACs Samsung's Soc S5P6442 has two PL330 DMACs. First is dedicated for Memory->Memory data transfer while the second is meant for data transfer with peripherals. Define and add the peripheral PL330 DMAC as platform device on the S5P6442 platform. Signed-off-by: Jassi Brar Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5p6442/Kconfig b/arch/arm/mach-s5p6442/Kconfig index 4f3f6de..0fd41b4 100644 --- a/arch/arm/mach-s5p6442/Kconfig +++ b/arch/arm/mach-s5p6442/Kconfig @@ -12,6 +12,7 @@ if ARCH_S5P6442 config CPU_S5P6442 bool select PLAT_S5P + select S3C_PL330_DMA help Enable S5P6442 CPU support diff --git a/arch/arm/mach-s5p6442/Makefile b/arch/arm/mach-s5p6442/Makefile index dde39a6..17bd22e 100644 --- a/arch/arm/mach-s5p6442/Makefile +++ b/arch/arm/mach-s5p6442/Makefile @@ -12,7 +12,7 @@ obj- := # Core support for S5P6442 system -obj-$(CONFIG_CPU_S5P6442) += cpu.o init.o clock.o +obj-$(CONFIG_CPU_S5P6442) += cpu.o init.o clock.o dma.o # machine support diff --git a/arch/arm/mach-s5p6442/dma.c b/arch/arm/mach-s5p6442/dma.c new file mode 100644 index 0000000..ad4f870 --- /dev/null +++ b/arch/arm/mach-s5p6442/dma.c @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2010 Samsung Electronics Co. Ltd. + * Jaswinder Singh + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#include +#include + +#include +#include + +#include + +static u64 dma_dmamask = DMA_BIT_MASK(32); + +static struct resource s5p6442_pdma_resource[] = { + [0] = { + .start = S5P6442_PA_PDMA, + .end = S5P6442_PA_PDMA + SZ_4K, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_PDMA, + .end = IRQ_PDMA, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct s3c_pl330_platdata s5p6442_pdma_pdata = { + .peri = { + [0] = DMACH_UART0_RX, + [1] = DMACH_UART0_TX, + [2] = DMACH_UART1_RX, + [3] = DMACH_UART1_TX, + [4] = DMACH_UART2_RX, + [5] = DMACH_UART2_TX, + [6] = DMACH_MAX, + [7] = DMACH_MAX, + [8] = DMACH_MAX, + [9] = DMACH_I2S0_RX, + [10] = DMACH_I2S0_TX, + [11] = DMACH_I2S0S_TX, + [12] = DMACH_I2S1_RX, + [13] = DMACH_I2S1_TX, + [14] = DMACH_MAX, + [15] = DMACH_MAX, + [16] = DMACH_SPI0_RX, + [17] = DMACH_SPI0_TX, + [18] = DMACH_MAX, + [19] = DMACH_MAX, + [20] = DMACH_PCM0_RX, + [21] = DMACH_PCM0_TX, + [22] = DMACH_PCM1_RX, + [23] = DMACH_PCM1_TX, + [24] = DMACH_MAX, + [25] = DMACH_MAX, + [26] = DMACH_MAX, + [27] = DMACH_MSM_REQ0, + [28] = DMACH_MSM_REQ1, + [29] = DMACH_MSM_REQ2, + [30] = DMACH_MSM_REQ3, + [31] = DMACH_MAX, + }, +}; + +static struct platform_device s5p6442_device_pdma = { + .name = "s3c-pl330", + .id = 1, + .num_resources = ARRAY_SIZE(s5p6442_pdma_resource), + .resource = s5p6442_pdma_resource, + .dev = { + .dma_mask = &dma_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &s5p6442_pdma_pdata, + }, +}; + +static struct platform_device *s5p6442_dmacs[] __initdata = { + &s5p6442_device_pdma, +}; + +static int __init s5p6442_dma_init(void) +{ + platform_add_devices(s5p6442_dmacs, ARRAY_SIZE(s5p6442_dmacs)); + + return 0; +} +arch_initcall(s5p6442_dma_init); diff --git a/arch/arm/mach-s5p6442/include/mach/dma.h b/arch/arm/mach-s5p6442/include/mach/dma.h new file mode 100644 index 0000000..81209eb --- /dev/null +++ b/arch/arm/mach-s5p6442/include/mach/dma.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2010 Samsung Electronics Co. Ltd. + * Jaswinder Singh + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __MACH_DMA_H +#define __MACH_DMA_H + +/* This platform uses the common S3C DMA API driver for PL330 */ +#include + +#endif /* __MACH_DMA_H */ diff --git a/arch/arm/mach-s5p6442/include/mach/map.h b/arch/arm/mach-s5p6442/include/mach/map.h index 685277d..a263d77 100644 --- a/arch/arm/mach-s5p6442/include/mach/map.h +++ b/arch/arm/mach-s5p6442/include/mach/map.h @@ -34,6 +34,9 @@ #define S5P6442_PA_VIC2 (0xE4200000) #define S5P_PA_VIC2 S5P6442_PA_VIC2 +#define S5P6442_PA_MDMA 0xE8000000 +#define S5P6442_PA_PDMA 0xE9000000 + #define S5P6442_PA_TIMER (0xEA000000) #define S5P_PA_TIMER S5P6442_PA_TIMER -- cgit v0.10.2 From 7d1a2077a7e519fc0c68617526abea3f72632e60 Mon Sep 17 00:00:00 2001 From: Jassi Brar Date: Tue, 18 May 2010 11:59:34 +0900 Subject: S5PV210: DMA: Add platform devices for PL330 DMACs Samsung's Soc S5PV210 has three PL330 DMACs. First is dedicated for Memory->Memory data transfer while the other two meant for data transfer with peripherals. Define and add latter two PL330 DMACs as platform devices on the S5PV210 platform. Signed-off-by: Jassi Brar Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig index af33a1a..7601c28 100644 --- a/arch/arm/mach-s5pv210/Kconfig +++ b/arch/arm/mach-s5pv210/Kconfig @@ -12,6 +12,7 @@ if ARCH_S5PV210 config CPU_S5PV210 bool select PLAT_S5P + select S3C_PL330_DMA help Enable S5PV210 CPU support diff --git a/arch/arm/mach-s5pv210/Makefile b/arch/arm/mach-s5pv210/Makefile index 8ebf51c..f7f1cdc 100644 --- a/arch/arm/mach-s5pv210/Makefile +++ b/arch/arm/mach-s5pv210/Makefile @@ -12,7 +12,7 @@ obj- := # Core support for S5PV210 system -obj-$(CONFIG_CPU_S5PV210) += cpu.o init.o clock.o +obj-$(CONFIG_CPU_S5PV210) += cpu.o init.o clock.o dma.o # machine support diff --git a/arch/arm/mach-s5pv210/dma.c b/arch/arm/mach-s5pv210/dma.c new file mode 100644 index 0000000..778ad5f --- /dev/null +++ b/arch/arm/mach-s5pv210/dma.c @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2010 Samsung Electronics Co. Ltd. + * Jaswinder Singh + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +#include +#include + +#include +#include + +#include + +static u64 dma_dmamask = DMA_BIT_MASK(32); + +static struct resource s5pv210_pdma0_resource[] = { + [0] = { + .start = S5PV210_PA_PDMA0, + .end = S5PV210_PA_PDMA0 + SZ_4K, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_PDMA0, + .end = IRQ_PDMA0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct s3c_pl330_platdata s5pv210_pdma0_pdata = { + .peri = { + [0] = DMACH_UART0_RX, + [1] = DMACH_UART0_TX, + [2] = DMACH_UART1_RX, + [3] = DMACH_UART1_TX, + [4] = DMACH_UART2_RX, + [5] = DMACH_UART2_TX, + [6] = DMACH_UART3_RX, + [7] = DMACH_UART3_TX, + [8] = DMACH_MAX, + [9] = DMACH_I2S0_RX, + [10] = DMACH_I2S0_TX, + [11] = DMACH_I2S0S_TX, + [12] = DMACH_I2S1_RX, + [13] = DMACH_I2S1_TX, + [14] = DMACH_MAX, + [15] = DMACH_MAX, + [16] = DMACH_SPI0_RX, + [17] = DMACH_SPI0_TX, + [18] = DMACH_SPI1_RX, + [19] = DMACH_SPI1_TX, + [20] = DMACH_MAX, + [21] = DMACH_MAX, + [22] = DMACH_AC97_MICIN, + [23] = DMACH_AC97_PCMIN, + [24] = DMACH_AC97_PCMOUT, + [25] = DMACH_MAX, + [26] = DMACH_PWM, + [27] = DMACH_SPDIF, + [28] = DMACH_MAX, + [29] = DMACH_MAX, + [30] = DMACH_MAX, + [31] = DMACH_MAX, + }, +}; + +static struct platform_device s5pv210_device_pdma0 = { + .name = "s3c-pl330", + .id = 1, + .num_resources = ARRAY_SIZE(s5pv210_pdma0_resource), + .resource = s5pv210_pdma0_resource, + .dev = { + .dma_mask = &dma_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &s5pv210_pdma0_pdata, + }, +}; + +static struct resource s5pv210_pdma1_resource[] = { + [0] = { + .start = S5PV210_PA_PDMA1, + .end = S5PV210_PA_PDMA1 + SZ_4K, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_PDMA1, + .end = IRQ_PDMA1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct s3c_pl330_platdata s5pv210_pdma1_pdata = { + .peri = { + [0] = DMACH_UART0_RX, + [1] = DMACH_UART0_TX, + [2] = DMACH_UART1_RX, + [3] = DMACH_UART1_TX, + [4] = DMACH_UART2_RX, + [5] = DMACH_UART2_TX, + [6] = DMACH_UART3_RX, + [7] = DMACH_UART3_TX, + [8] = DMACH_MAX, + [9] = DMACH_I2S0_RX, + [10] = DMACH_I2S0_TX, + [11] = DMACH_I2S0S_TX, + [12] = DMACH_I2S1_RX, + [13] = DMACH_I2S1_TX, + [14] = DMACH_I2S2_RX, + [15] = DMACH_I2S2_TX, + [16] = DMACH_SPI0_RX, + [17] = DMACH_SPI0_TX, + [18] = DMACH_SPI1_RX, + [19] = DMACH_SPI1_TX, + [20] = DMACH_MAX, + [21] = DMACH_MAX, + [22] = DMACH_PCM0_RX, + [23] = DMACH_PCM0_TX, + [24] = DMACH_PCM1_RX, + [25] = DMACH_PCM1_TX, + [26] = DMACH_MSM_REQ0, + [27] = DMACH_MSM_REQ1, + [28] = DMACH_MSM_REQ2, + [29] = DMACH_MSM_REQ3, + [30] = DMACH_PCM2_RX, + [31] = DMACH_PCM2_TX, + }, +}; + +static struct platform_device s5pv210_device_pdma1 = { + .name = "s3c-pl330", + .id = 2, + .num_resources = ARRAY_SIZE(s5pv210_pdma1_resource), + .resource = s5pv210_pdma1_resource, + .dev = { + .dma_mask = &dma_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = &s5pv210_pdma1_pdata, + }, +}; + +static struct platform_device *s5pv210_dmacs[] __initdata = { + &s5pv210_device_pdma0, + &s5pv210_device_pdma1, +}; + +static int __init s5pv210_dma_init(void) +{ + platform_add_devices(s5pv210_dmacs, ARRAY_SIZE(s5pv210_dmacs)); + + return 0; +} +arch_initcall(s5pv210_dma_init); diff --git a/arch/arm/mach-s5pv210/include/mach/dma.h b/arch/arm/mach-s5pv210/include/mach/dma.h new file mode 100644 index 0000000..81209eb --- /dev/null +++ b/arch/arm/mach-s5pv210/include/mach/dma.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2010 Samsung Electronics Co. Ltd. + * Jaswinder Singh + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __MACH_DMA_H +#define __MACH_DMA_H + +/* This platform uses the common S3C DMA API driver for PL330 */ +#include + +#endif /* __MACH_DMA_H */ diff --git a/arch/arm/mach-s5pv210/include/mach/map.h b/arch/arm/mach-s5pv210/include/mach/map.h index c22694c..c038585 100644 --- a/arch/arm/mach-s5pv210/include/mach/map.h +++ b/arch/arm/mach-s5pv210/include/mach/map.h @@ -43,6 +43,10 @@ #define S5PV210_PA_SROMC (0xE8000000) +#define S5PV210_PA_MDMA 0xFA200000 +#define S5PV210_PA_PDMA0 0xE0900000 +#define S5PV210_PA_PDMA1 0xE0A00000 + #define S5PV210_PA_VIC0 (0xF2000000) #define S5P_PA_VIC0 S5PV210_PA_VIC0 -- cgit v0.10.2 From 06225c08ec2ad0f0dec063df7f08773a8358db12 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 18 May 2010 18:15:44 +0900 Subject: sh: Fix up the NUMA build for recent LMB changes. Now that the node 0 initialization code has been overhauled, kill off the now obsolete setup_memory() bits. Signed-off-by: Paul Mundt diff --git a/arch/sh/mm/numa.c b/arch/sh/mm/numa.c index 961b340..a2e645f 100644 --- a/arch/sh/mm/numa.c +++ b/arch/sh/mm/numa.c @@ -24,44 +24,6 @@ EXPORT_SYMBOL_GPL(node_data); * latency. Each node's pgdat is node-local at the beginning of the node, * immediately followed by the node mem map. */ -void __init setup_memory(void) -{ - unsigned long free_pfn = PFN_UP(__pa(_end)); - u64 base = min_low_pfn << PAGE_SHIFT; - u64 size = (max_low_pfn << PAGE_SHIFT) - base; - - lmb_add(base, size); - - /* Reserve the LMB regions used by the kernel, initrd, etc.. */ - lmb_reserve(__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET, - (PFN_PHYS(free_pfn) + PAGE_SIZE - 1) - - (__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET)); - - /* - * Reserve physical pages below CONFIG_ZERO_PAGE_OFFSET. - */ - if (CONFIG_ZERO_PAGE_OFFSET != 0) - lmb_reserve(__MEMORY_START, CONFIG_ZERO_PAGE_OFFSET); - - lmb_analyze(); - lmb_dump_all(); - - /* - * Node 0 sets up its pgdat at the first available pfn, - * and bumps it up before setting up the bootmem allocator. - */ - NODE_DATA(0) = pfn_to_kaddr(free_pfn); - memset(NODE_DATA(0), 0, sizeof(struct pglist_data)); - free_pfn += PFN_UP(sizeof(struct pglist_data)); - NODE_DATA(0)->bdata = &bootmem_node_data[0]; - - /* Set up node 0 */ - setup_bootmem_allocator(free_pfn); - - /* Give the platforms a chance to hook up their nodes */ - plat_mem_setup(); -} - void __init setup_bootmem_node(int nid, unsigned long start, unsigned long end) { unsigned long bootmap_pages; -- cgit v0.10.2 From 4d0956b8f597aac10208ca763f8fe641fde16aab Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 18 May 2010 18:18:28 +0900 Subject: sh: update defconfigs. Signed-off-by: Paul Mundt diff --git a/arch/sh/configs/ap325rxa_defconfig b/arch/sh/configs/ap325rxa_defconfig index 8931a60..7fefa2b 100644 --- a/arch/sh/configs/ap325rxa_defconfig +++ b/arch/sh/configs/ap325rxa_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 11:10:59 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 15:04:35 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y CONFIG_GENERIC_GPIO=y CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -32,6 +32,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -47,9 +48,11 @@ CONFIG_LOCALVERSION="" CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -71,11 +74,6 @@ CONFIG_RCU_FANOUT=32 # CONFIG_TREE_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 -CONFIG_GROUP_SCHED=y -CONFIG_FAIR_GROUP_SCHED=y -# CONFIG_RT_GROUP_SCHED is not set -CONFIG_USER_SCHED=y -# CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -107,7 +105,7 @@ CONFIG_PERF_USE_VMALLOC=y # # Kernel Performance Events And Counters # -# CONFIG_PERF_EVENTS is not set +CONFIG_PERF_EVENTS=y # CONFIG_PERF_COUNTERS is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_COMPAT_BRK=y @@ -116,13 +114,13 @@ CONFIG_SLAB=y # CONFIG_SLOB is not set # CONFIG_PROFILING is not set CONFIG_HAVE_OPROFILE=y -CONFIG_HAVE_IOREMAP_PROT=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -237,8 +235,8 @@ CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_MEMORY_START=0x08000000 CONFIG_MEMORY_SIZE=0x08000000 CONFIG_29BIT=y -# CONFIG_PMB_ENABLE is not set -# CONFIG_X2TLB is not set +# CONFIG_PMB is not set +CONFIG_X2TLB=y CONFIG_VSYSCALL=y CONFIG_ARCH_FLATMEM_ENABLE=y CONFIG_ARCH_SPARSEMEM_ENABLE=y @@ -246,6 +244,8 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_IOREMAP_FIXED=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -261,7 +261,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -335,7 +335,7 @@ CONFIG_SECCOMP=y # CONFIG_PREEMPT_VOLUNTARY is not set CONFIG_PREEMPT=y CONFIG_GUSA=y -# CONFIG_SPARSE_IRQ is not set +# CONFIG_INTC_USERIMASK is not set # # Boot options @@ -371,6 +371,7 @@ CONFIG_SUSPEND=y CONFIG_SUSPEND_FREEZER=y # CONFIG_HIBERNATION is not set CONFIG_PM_RUNTIME=y +CONFIG_PM_OPS=y # CONFIG_CPU_IDLE is not set CONFIG_NET=y @@ -378,7 +379,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y # CONFIG_NET_KEY is not set CONFIG_INET=y @@ -594,6 +594,7 @@ CONFIG_MISC_DEVICES=y # CONFIG_ICS932S401 is not set # CONFIG_ENCLOSURE_SERVICES is not set # CONFIG_ISL29003 is not set +# CONFIG_SENSORS_TSL2550 is not set # CONFIG_DS1682 is not set # CONFIG_TI_DAC7512 is not set # CONFIG_C2PORT is not set @@ -613,6 +614,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y @@ -774,6 +776,7 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=6 CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y @@ -802,6 +805,7 @@ CONFIG_I2C_HELPER_AUTO=y # CONFIG_I2C_OCORES is not set CONFIG_I2C_SH_MOBILE=y # CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set # # External I2C/SMBus adapter drivers @@ -814,15 +818,9 @@ CONFIG_I2C_SH_MOBILE=y # # CONFIG_I2C_PCA_PLATFORM is not set # CONFIG_I2C_STUB is not set - -# -# Miscellaneous I2C Chip support -# -# CONFIG_SENSORS_TSL2550 is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set CONFIG_SPI=y CONFIG_SPI_MASTER=y @@ -853,13 +851,16 @@ CONFIG_GPIOLIB=y # # Memory mapped GPIO expanders: # +# CONFIG_GPIO_IT8761E is not set # # I2C GPIO expanders: # +# CONFIG_GPIO_MAX7300 is not set # CONFIG_GPIO_MAX732X is not set # CONFIG_GPIO_PCA953X is not set # CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_ADP5588 is not set # # PCI GPIO expanders: @@ -891,22 +892,25 @@ CONFIG_SSB_POSSIBLE=y # Multifunction device drivers # # CONFIG_MFD_CORE is not set +# CONFIG_MFD_88PM860X is not set # CONFIG_MFD_SM501 is not set # CONFIG_MFD_SH_MOBILE_SDHI is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set # CONFIG_TPS65010 is not set # CONFIG_TWL4030_CORE is not set # CONFIG_MFD_TMIO is not set # CONFIG_PMIC_DA903X is not set # CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X is not set # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set # CONFIG_MFD_PCF50633 is not set # CONFIG_MFD_MC13783 is not set # CONFIG_AB3100_CORE is not set # CONFIG_EZX_PCAP is not set -# CONFIG_MFD_88PM8607 is not set # CONFIG_AB4500_CORE is not set # CONFIG_REGULATOR is not set CONFIG_MEDIA_SUPPORT=y @@ -1041,10 +1045,7 @@ CONFIG_MMC_BLOCK_BOUNCE=y # MMC/SD/SDIO Host Controller Drivers # # CONFIG_MMC_SDHCI is not set -# CONFIG_MMC_AT91 is not set -# CONFIG_MMC_ATMELMCI is not set CONFIG_MMC_SPI=y -# CONFIG_MMC_TMIO is not set # CONFIG_MEMSTICK is not set # CONFIG_NEW_LEDS is not set # CONFIG_ACCESSIBILITY is not set @@ -1120,8 +1121,6 @@ CONFIG_RTC_DRV_PCF8563=y CONFIG_UIO=y # CONFIG_UIO_PDRV is not set CONFIG_UIO_PDRV_GENIRQ=y -# CONFIG_UIO_SMX is not set -# CONFIG_UIO_SERCOS3 is not set # # TI VLYNQ @@ -1206,6 +1205,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_EFS_FS is not set # CONFIG_JFFS2_FS is not set # CONFIG_UBIFS_FS is not set +# CONFIG_LOGFS is not set # CONFIG_CRAMFS is not set # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -1234,6 +1234,7 @@ CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1426,6 +1427,7 @@ CONFIG_CRYPTO_CBC=y # # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y +# CONFIG_VIRTUALIZATION is not set # CONFIG_BINARY_PRINTF is not set # diff --git a/arch/sh/configs/cayman_defconfig b/arch/sh/configs/cayman_defconfig index 92589a9..edae0a6 100644 --- a/arch/sh/configs/cayman_defconfig +++ b/arch/sh/configs/cayman_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 11:14:50 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 18:01:02 2010 # CONFIG_SUPERH=y # CONFIG_SUPERH32 is not set @@ -13,7 +13,6 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y @@ -32,6 +31,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -47,9 +47,11 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SWAP=y # CONFIG_SYSVIPC is not set CONFIG_POSIX_MQUEUE=y @@ -70,7 +72,6 @@ CONFIG_RCU_FANOUT=32 # CONFIG_TREE_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -114,7 +115,6 @@ CONFIG_SLAB=y # CONFIG_SLOB is not set # CONFIG_PROFILING is not set CONFIG_HAVE_OPROFILE=y -CONFIG_HAVE_IOREMAP_PROT=y CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y @@ -204,6 +204,7 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_IOREMAP_FIXED=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -225,7 +226,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -294,7 +295,6 @@ CONFIG_HZ=250 # CONFIG_PREEMPT_NONE is not set # CONFIG_PREEMPT_VOLUNTARY is not set CONFIG_PREEMPT=y -# CONFIG_SPARSE_IRQ is not set # # Boot options @@ -309,9 +309,9 @@ CONFIG_ENTRY_OFFSET=0x00001000 # Bus options # CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y # CONFIG_PCIEPORTBUS is not set # CONFIG_ARCH_SUPPORTS_MSI is not set -CONFIG_PCI_LEGACY=y # CONFIG_PCI_DEBUG is not set # CONFIG_PCI_STUB is not set # CONFIG_PCI_IOV is not set @@ -337,7 +337,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -463,6 +462,7 @@ CONFIG_MISC_DEVICES=y # CONFIG_ENCLOSURE_SERVICES is not set # CONFIG_HP_ILO is not set # CONFIG_ISL29003 is not set +# CONFIG_SENSORS_TSL2550 is not set # CONFIG_DS1682 is not set # CONFIG_C2PORT is not set @@ -480,6 +480,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y @@ -569,7 +570,7 @@ CONFIG_SCSI_LOWLEVEL=y # # -# See the help texts for more information. +# The newer stack is recommended. # # CONFIG_FIREWIRE is not set # CONFIG_IEEE1394 is not set @@ -638,6 +639,8 @@ CONFIG_NETDEV_10000=y # CONFIG_CHELSIO_T1 is not set CONFIG_CHELSIO_T3_DEPENDS=y # CONFIG_CHELSIO_T3 is not set +CONFIG_CHELSIO_T4_DEPENDS=y +# CONFIG_CHELSIO_T4 is not set # CONFIG_ENIC is not set # CONFIG_IXGBE is not set # CONFIG_IXGB is not set @@ -650,6 +653,7 @@ CONFIG_CHELSIO_T3_DEPENDS=y # CONFIG_MLX4_CORE is not set # CONFIG_TEHUTI is not set # CONFIG_BNX2X is not set +# CONFIG_QLCNIC is not set # CONFIG_QLGE is not set # CONFIG_SFC is not set # CONFIG_BE2NET is not set @@ -732,6 +736,7 @@ CONFIG_DEVKMEM=y # # CONFIG_SERIAL_SH_SCI is not set # CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y @@ -779,6 +784,7 @@ CONFIG_I2C_HELPER_AUTO=y # CONFIG_I2C_OCORES is not set # CONFIG_I2C_SH_MOBILE is not set # CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set # # External I2C/SMBus adapter drivers @@ -791,15 +797,9 @@ CONFIG_I2C_HELPER_AUTO=y # # CONFIG_I2C_PCA_PLATFORM is not set # CONFIG_I2C_STUB is not set - -# -# Miscellaneous I2C Chip support -# -# CONFIG_SENSORS_TSL2550 is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set # CONFIG_SPI is not set # @@ -823,10 +823,11 @@ CONFIG_HWMON=y # CONFIG_SENSORS_ADM1029 is not set # CONFIG_SENSORS_ADM1031 is not set # CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7411 is not set # CONFIG_SENSORS_ADT7462 is not set # CONFIG_SENSORS_ADT7470 is not set -# CONFIG_SENSORS_ADT7473 is not set # CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ASC7621 is not set # CONFIG_SENSORS_ATXP1 is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_I5K_AMB is not set @@ -863,6 +864,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_SMSC47M192 is not set # CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_AMC6821 is not set # CONFIG_SENSORS_THMC50 is not set # CONFIG_SENSORS_TMP401 is not set # CONFIG_SENSORS_TMP421 is not set @@ -909,9 +911,9 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_HTC_PASIC3 is not set # CONFIG_MFD_TMIO is not set # CONFIG_MFD_WM8400 is not set -# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set # CONFIG_MFD_PCF50633 is not set -# CONFIG_AB3100_CORE is not set +# CONFIG_LPC_SCH is not set # CONFIG_REGULATOR is not set # CONFIG_MEDIA_SUPPORT is not set @@ -919,6 +921,7 @@ CONFIG_SSB_POSSIBLE=y # Graphics support # CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 # CONFIG_DRM is not set # CONFIG_VGASTATE is not set CONFIG_VIDEO_OUTPUT_CONTROL=y @@ -1125,6 +1128,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set +# CONFIG_LOGFS is not set # CONFIG_CRAMFS is not set # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -1153,6 +1157,7 @@ CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1208,6 +1213,7 @@ CONFIG_SCHEDSTATS=y # CONFIG_TIMER_STATS is not set # CONFIG_DEBUG_OBJECTS is not set # CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_KMEMLEAK is not set CONFIG_DEBUG_PREEMPT=y # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set @@ -1234,6 +1240,7 @@ CONFIG_FRAME_POINTER=y # CONFIG_BACKTRACE_SELF_TEST is not set # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_LKDTM is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set # CONFIG_SYSCTL_SYSCALL_CHECK is not set @@ -1361,6 +1368,7 @@ CONFIG_CRYPTO=y # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y # CONFIG_CRYPTO_DEV_HIFN_795X is not set +# CONFIG_VIRTUALIZATION is not set # CONFIG_BINARY_PRINTF is not set # diff --git a/arch/sh/configs/dreamcast_defconfig b/arch/sh/configs/dreamcast_defconfig index 55f652b..b96bf3d 100644 --- a/arch/sh/configs/dreamcast_defconfig +++ b/arch/sh/configs/dreamcast_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 11:17:35 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 15:11:55 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -33,6 +33,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -48,9 +49,11 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -72,7 +75,6 @@ CONFIG_RCU_FANOUT=32 # CONFIG_TREE_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -124,6 +126,7 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -242,6 +245,7 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -263,7 +267,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -360,7 +364,6 @@ CONFIG_SECCOMP=y CONFIG_PREEMPT=y CONFIG_GUSA=y # CONFIG_GUSA_RB is not set -# CONFIG_SPARSE_IRQ is not set # # Boot options @@ -377,9 +380,9 @@ CONFIG_CMDLINE="console=ttySC1,115200 panic=3" # CONFIG_MAPLE=y CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y # CONFIG_PCIEPORTBUS is not set # CONFIG_ARCH_SUPPORTS_MSI is not set -CONFIG_PCI_LEGACY=y # CONFIG_PCI_STUB is not set # CONFIG_PCI_IOV is not set # CONFIG_PCCARD is not set @@ -404,7 +407,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -532,6 +534,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set # CONFIG_SCSI_DMA is not set @@ -549,7 +552,7 @@ CONFIG_HAVE_IDE=y # # -# See the help texts for more information. +# The newer stack is recommended. # # CONFIG_FIREWIRE is not set # CONFIG_IEEE1394 is not set @@ -589,6 +592,7 @@ CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set # CONFIG_AMD8111_ETH is not set # CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_KSZ884X_PCI is not set # CONFIG_B44 is not set # CONFIG_FORCEDETH is not set # CONFIG_E100 is not set @@ -717,6 +721,7 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y @@ -771,6 +776,7 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_SH_MOBILE_SDHI is not set # CONFIG_HTC_PASIC3 is not set # CONFIG_MFD_TMIO is not set +# CONFIG_LPC_SCH is not set # CONFIG_REGULATOR is not set # CONFIG_MEDIA_SUPPORT is not set @@ -778,6 +784,7 @@ CONFIG_SSB_POSSIBLE=y # Graphics support # CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 # CONFIG_DRM is not set # CONFIG_VGASTATE is not set CONFIG_VIDEO_OUTPUT_CONTROL=m @@ -918,7 +925,6 @@ CONFIG_RTC_LIB=y # CONFIG_EXT2_FS is not set # CONFIG_EXT3_FS is not set # CONFIG_EXT4_FS is not set -CONFIG_EXT4_USE_FOR_EXT23=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set @@ -976,6 +982,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set +# CONFIG_LOGFS is not set # CONFIG_CRAMFS is not set # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -990,6 +997,7 @@ CONFIG_NETWORK_FILESYSTEMS=y # CONFIG_NFS_FS is not set # CONFIG_NFSD is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1135,6 +1143,7 @@ CONFIG_CRYPTO=y # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y # CONFIG_CRYPTO_DEV_HIFN_795X is not set +# CONFIG_VIRTUALIZATION is not set # CONFIG_BINARY_PRINTF is not set # diff --git a/arch/sh/configs/ecovec24-romimage_defconfig b/arch/sh/configs/ecovec24-romimage_defconfig index 662c1ad..58aec9d 100644 --- a/arch/sh/configs/ecovec24-romimage_defconfig +++ b/arch/sh/configs/ecovec24-romimage_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 11:18:17 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 15:14:56 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y CONFIG_GENERIC_GPIO=y CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -32,6 +32,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -46,9 +47,11 @@ CONFIG_LOCALVERSION="" CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -71,11 +74,6 @@ CONFIG_RCU_FANOUT=32 CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 -CONFIG_GROUP_SCHED=y -CONFIG_FAIR_GROUP_SCHED=y -# CONFIG_RT_GROUP_SCHED is not set -CONFIG_USER_SCHED=y -# CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -86,6 +84,7 @@ CONFIG_INITRAMFS_SOURCE="" CONFIG_RD_GZIP=y # CONFIG_RD_BZIP2 is not set # CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_ANON_INODES=y @@ -111,7 +110,7 @@ CONFIG_PERF_USE_VMALLOC=y # # Kernel Performance Events And Counters # -# CONFIG_PERF_EVENTS is not set +CONFIG_PERF_EVENTS=y # CONFIG_PERF_COUNTERS is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_COMPAT_BRK=y @@ -120,13 +119,13 @@ CONFIG_SLAB=y # CONFIG_SLOB is not set # CONFIG_PROFILING is not set CONFIG_HAVE_OPROFILE=y -CONFIG_HAVE_IOREMAP_PROT=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -237,8 +236,8 @@ CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_MEMORY_START=0x08000000 CONFIG_MEMORY_SIZE=0x10000000 CONFIG_29BIT=y -# CONFIG_PMB_ENABLE is not set -# CONFIG_X2TLB is not set +# CONFIG_PMB is not set +CONFIG_X2TLB=y CONFIG_VSYSCALL=y CONFIG_ARCH_FLATMEM_ENABLE=y CONFIG_ARCH_SPARSEMEM_ENABLE=y @@ -246,6 +245,8 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_IOREMAP_FIXED=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -261,7 +262,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -336,7 +337,7 @@ CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set CONFIG_GUSA=y -# CONFIG_SPARSE_IRQ is not set +# CONFIG_INTC_USERIMASK is not set # # Boot options @@ -370,6 +371,7 @@ CONFIG_PM=y # CONFIG_SUSPEND is not set # CONFIG_HIBERNATION is not set CONFIG_PM_RUNTIME=y +CONFIG_PM_OPS=y # CONFIG_CPU_IDLE is not set CONFIG_NET=y @@ -377,7 +379,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y CONFIG_UNIX=y # CONFIG_NET_KEY is not set CONFIG_INET=y @@ -485,6 +486,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y @@ -585,6 +587,7 @@ CONFIG_WLAN=y # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set # CONFIG_USB_USBNET is not set +# CONFIG_USB_IPHETH is not set # CONFIG_WAN is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -650,6 +653,7 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=6 CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y @@ -678,6 +682,7 @@ CONFIG_I2C_HELPER_AUTO=y # CONFIG_I2C_OCORES is not set CONFIG_I2C_SH_MOBILE=y # CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set # # External I2C/SMBus adapter drivers @@ -690,15 +695,9 @@ CONFIG_I2C_SH_MOBILE=y # Other I2C/SMBus bus drivers # # CONFIG_I2C_PCA_PLATFORM is not set - -# -# Miscellaneous I2C Chip support -# -# CONFIG_SENSORS_TSL2550 is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set # CONFIG_SPI is not set # @@ -712,13 +711,16 @@ CONFIG_GPIO_SYSFS=y # # Memory mapped GPIO expanders: # +# CONFIG_GPIO_IT8761E is not set # # I2C GPIO expanders: # +# CONFIG_GPIO_MAX7300 is not set # CONFIG_GPIO_MAX732X is not set # CONFIG_GPIO_PCA953X is not set # CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_ADP5588 is not set # # PCI GPIO expanders: @@ -747,20 +749,23 @@ CONFIG_SSB_POSSIBLE=y # Multifunction device drivers # # CONFIG_MFD_CORE is not set +# CONFIG_MFD_88PM860X is not set # CONFIG_MFD_SM501 is not set # CONFIG_MFD_SH_MOBILE_SDHI is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set # CONFIG_TPS65010 is not set # CONFIG_TWL4030_CORE is not set # CONFIG_MFD_TMIO is not set # CONFIG_PMIC_DA903X is not set # CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X is not set # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set # CONFIG_MFD_PCF50633 is not set # CONFIG_AB3100_CORE is not set -# CONFIG_MFD_88PM8607 is not set # CONFIG_REGULATOR is not set # CONFIG_MEDIA_SUPPORT is not set @@ -868,7 +873,6 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set -# CONFIG_USB_BERRY_CHARGE is not set # CONFIG_USB_LED is not set # CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set @@ -880,7 +884,6 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set # CONFIG_USB_ISIGHTFW is not set -# CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set # @@ -911,7 +914,6 @@ CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XIP is not set # CONFIG_EXT3_FS is not set # CONFIG_EXT4_FS is not set -CONFIG_EXT4_USE_FOR_EXT23=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set @@ -1027,6 +1029,7 @@ CONFIG_DEBUG_FS=y CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_MEMORY_INIT is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_LKDTM is not set # CONFIG_LATENCYTOP is not set # CONFIG_SYSCTL_SYSCALL_CHECK is not set CONFIG_HAVE_FUNCTION_TRACER=y @@ -1056,6 +1059,7 @@ CONFIG_HAVE_ARCH_KGDB=y CONFIG_DEFAULT_SECURITY_DAC=y CONFIG_DEFAULT_SECURITY="" # CONFIG_CRYPTO is not set +# CONFIG_VIRTUALIZATION is not set # CONFIG_BINARY_PRINTF is not set # diff --git a/arch/sh/configs/ecovec24_defconfig b/arch/sh/configs/ecovec24_defconfig index 6041c66..67c6656 100644 --- a/arch/sh/configs/ecovec24_defconfig +++ b/arch/sh/configs/ecovec24_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.34-rc2 -# Mon Mar 29 02:21:58 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 15:17:28 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -336,6 +336,7 @@ CONFIG_SECCOMP=y # CONFIG_PREEMPT_VOLUNTARY is not set CONFIG_PREEMPT=y CONFIG_GUSA=y +# CONFIG_INTC_USERIMASK is not set # # Boot options @@ -762,6 +763,7 @@ CONFIG_WLAN=y # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set # CONFIG_USB_USBNET is not set +# CONFIG_USB_IPHETH is not set # CONFIG_WAN is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -1755,6 +1757,7 @@ CONFIG_CRYPTO_CBC=y # # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y +# CONFIG_VIRTUALIZATION is not set # CONFIG_BINARY_PRINTF is not set # diff --git a/arch/sh/configs/edosk7705_defconfig b/arch/sh/configs/edosk7705_defconfig index 72f8718..0883d873 100644 --- a/arch/sh/configs/edosk7705_defconfig +++ b/arch/sh/configs/edosk7705_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 11:24:26 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 15:21:52 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -12,8 +12,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -29,6 +29,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -43,9 +44,11 @@ CONFIG_LOCALVERSION="" CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set # CONFIG_SYSVIPC is not set # CONFIG_BSD_PROCESS_ACCT is not set @@ -61,11 +64,11 @@ CONFIG_RCU_FANOUT=32 # CONFIG_TREE_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=17 -# CONFIG_CGROUPS is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set # CONFIG_BLK_DEV_INITRD is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_ANON_INODES=y CONFIG_EMBEDDED=y # CONFIG_UID16 is not set # CONFIG_KALLSYMS is not set @@ -87,7 +90,7 @@ CONFIG_PERF_USE_VMALLOC=y # # Kernel Performance Events And Counters # -# CONFIG_PERF_EVENTS is not set +CONFIG_PERF_EVENTS=y # CONFIG_PERF_COUNTERS is not set # CONFIG_VM_EVENT_COUNTERS is not set # CONFIG_COMPAT_BRK is not set @@ -103,6 +106,7 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -202,6 +206,7 @@ CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -217,7 +222,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_MIGRATION=y # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -330,6 +335,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_SCSI_DMA is not set # CONFIG_SCSI_NETLINK is not set # CONFIG_PHONE is not set @@ -361,6 +367,7 @@ CONFIG_HAVE_IDE=y # Non-8250 serial port support # # CONFIG_SERIAL_SH_SCI is not set +# CONFIG_SERIAL_TIMBERDALE is not set # CONFIG_UNIX98_PTYS is not set # CONFIG_LEGACY_PTYS is not set # CONFIG_IPMI_HANDLER is not set @@ -440,6 +447,7 @@ CONFIG_INOTIFY_USER=y # # Caches # +# CONFIG_FSCACHE is not set # # Pseudo filesystems @@ -491,6 +499,7 @@ CONFIG_HAVE_ARCH_KGDB=y CONFIG_DEFAULT_SECURITY_DAC=y CONFIG_DEFAULT_SECURITY="" # CONFIG_CRYPTO is not set +# CONFIG_VIRTUALIZATION is not set # CONFIG_BINARY_PRINTF is not set # diff --git a/arch/sh/configs/edosk7760_defconfig b/arch/sh/configs/edosk7760_defconfig index 0932e6d..8257f57 100644 --- a/arch/sh/configs/edosk7760_defconfig +++ b/arch/sh/configs/edosk7760_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 11:24:44 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 15:23:10 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -31,6 +31,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -46,9 +47,11 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -72,7 +75,6 @@ CONFIG_RCU_FANOUT=32 CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=17 -# CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -83,6 +85,7 @@ CONFIG_INITRAMFS_SOURCE="" CONFIG_RD_GZIP=y # CONFIG_RD_BZIP2 is not set # CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_ANON_INODES=y @@ -110,8 +113,9 @@ CONFIG_PERF_USE_VMALLOC=y # # Kernel Performance Events And Counters # -# CONFIG_PERF_EVENTS is not set +CONFIG_PERF_EVENTS=y # CONFIG_PERF_COUNTERS is not set +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_SLUB_DEBUG=y CONFIG_COMPAT_BRK=y @@ -128,6 +132,7 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -246,6 +251,7 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -261,7 +267,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -342,7 +348,6 @@ CONFIG_SCHED_HRTICK=y CONFIG_PREEMPT=y CONFIG_GUSA=y # CONFIG_GUSA_RB is not set -# CONFIG_SPARSE_IRQ is not set # # Boot options @@ -379,7 +384,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y # CONFIG_NET_KEY is not set CONFIG_INET=y @@ -579,6 +583,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set # CONFIG_SCSI_DMA is not set @@ -685,6 +690,7 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=3 CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y @@ -713,6 +719,7 @@ CONFIG_I2C_HELPER_AUTO=y CONFIG_I2C_SH7760=y # CONFIG_I2C_SH_MOBILE is not set # CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set # # External I2C/SMBus adapter drivers @@ -725,15 +732,9 @@ CONFIG_I2C_SH7760=y # # CONFIG_I2C_PCA_PLATFORM is not set # CONFIG_I2C_STUB is not set - -# -# Miscellaneous I2C Chip support -# -# CONFIG_SENSORS_TSL2550 is not set CONFIG_I2C_DEBUG_CORE=y CONFIG_I2C_DEBUG_ALGO=y CONFIG_I2C_DEBUG_BUS=y -CONFIG_I2C_DEBUG_CHIP=y # CONFIG_SPI is not set # @@ -756,6 +757,7 @@ CONFIG_SSB_POSSIBLE=y # Multifunction device drivers # # CONFIG_MFD_CORE is not set +# CONFIG_MFD_88PM860X is not set # CONFIG_MFD_SM501 is not set # CONFIG_MFD_SH_MOBILE_SDHI is not set # CONFIG_HTC_PASIC3 is not set @@ -763,12 +765,13 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_TMIO is not set # CONFIG_PMIC_DA903X is not set # CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X is not set # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set # CONFIG_MFD_PCF50633 is not set # CONFIG_AB3100_CORE is not set -# CONFIG_MFD_88PM8607 is not set # CONFIG_REGULATOR is not set # CONFIG_MEDIA_SUPPORT is not set @@ -947,6 +950,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set # CONFIG_JFFS2_FS is not set +# CONFIG_LOGFS is not set # CONFIG_CRAMFS is not set # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -969,6 +973,7 @@ CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1048,6 +1053,7 @@ CONFIG_TIMER_STATS=y # CONFIG_DEBUG_OBJECTS is not set # CONFIG_SLUB_DEBUG_ON is not set # CONFIG_SLUB_STATS is not set +# CONFIG_DEBUG_KMEMLEAK is not set CONFIG_DEBUG_PREEMPT=y # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set @@ -1096,6 +1102,7 @@ CONFIG_FTRACE=y CONFIG_BRANCH_PROFILE_NONE=y # CONFIG_PROFILE_ANNOTATED_BRANCHES is not set # CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_KSYM_TRACER is not set # CONFIG_STACK_TRACER is not set # CONFIG_KMEMTRACE is not set # CONFIG_WORKQUEUE_TRACER is not set @@ -1214,6 +1221,7 @@ CONFIG_CRYPTO_DES=y # # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y +# CONFIG_VIRTUALIZATION is not set # CONFIG_BINARY_PRINTF is not set # diff --git a/arch/sh/configs/espt_defconfig b/arch/sh/configs/espt_defconfig index f899e56..8acdc37 100644 --- a/arch/sh/configs/espt_defconfig +++ b/arch/sh/configs/espt_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 11:26:55 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 15:27:14 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -31,6 +31,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -45,9 +46,11 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -69,11 +72,6 @@ CONFIG_RCU_FANOUT=32 CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 -CONFIG_GROUP_SCHED=y -CONFIG_FAIR_GROUP_SCHED=y -# CONFIG_RT_GROUP_SCHED is not set -CONFIG_USER_SCHED=y -# CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -112,7 +110,6 @@ CONFIG_PERF_USE_VMALLOC=y # Kernel Performance Events And Counters # CONFIG_PERF_EVENTS=y -CONFIG_EVENT_PROFILE=y # CONFIG_PERF_COUNTERS is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_COMPAT_BRK=y @@ -120,7 +117,6 @@ CONFIG_SLAB=y # CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_PROFILING=y -CONFIG_TRACEPOINTS=y CONFIG_OPROFILE=y CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set @@ -131,6 +127,7 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -243,7 +240,7 @@ CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_MEMORY_START=0x0c000000 CONFIG_MEMORY_SIZE=0x04000000 CONFIG_29BIT=y -# CONFIG_PMB_ENABLE is not set +# CONFIG_PMB is not set CONFIG_VSYSCALL=y CONFIG_ARCH_FLATMEM_ENABLE=y CONFIG_ARCH_SPARSEMEM_ENABLE=y @@ -253,6 +250,7 @@ CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -269,7 +267,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_MIGRATION=y # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -344,7 +342,7 @@ CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set CONFIG_GUSA=y -# CONFIG_SPARSE_IRQ is not set +# CONFIG_INTC_USERIMASK is not set # # Boot options @@ -381,7 +379,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -444,7 +441,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # Network testing # # CONFIG_NET_PKTGEN is not set -# CONFIG_NET_DROP_MONITOR is not set # CONFIG_HAMRADIO is not set # CONFIG_CAN is not set # CONFIG_IRDA is not set @@ -584,6 +580,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y @@ -688,6 +685,7 @@ CONFIG_WLAN=y # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set # CONFIG_USB_USBNET is not set +# CONFIG_USB_IPHETH is not set # CONFIG_WAN is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -753,6 +751,7 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=3 CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y @@ -944,7 +943,6 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set -# CONFIG_USB_BERRY_CHARGE is not set # CONFIG_USB_LED is not set # CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set @@ -956,7 +954,6 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set # CONFIG_USB_ISIGHTFW is not set -# CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set # @@ -1052,6 +1049,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set # CONFIG_JFFS2_FS is not set +# CONFIG_LOGFS is not set CONFIG_CRAMFS=y # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -1078,6 +1076,7 @@ CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1144,13 +1143,12 @@ CONFIG_FRAME_WARN=1024 CONFIG_DEBUG_FS=y # CONFIG_HEADERS_CHECK is not set # CONFIG_DEBUG_KERNEL is not set -CONFIG_STACKTRACE=y CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_MEMORY_INIT is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_LKDTM is not set # CONFIG_LATENCYTOP is not set # CONFIG_SYSCTL_SYSCALL_CHECK is not set -CONFIG_NOP_TRACER=y CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y @@ -1158,10 +1156,7 @@ CONFIG_HAVE_DYNAMIC_FTRACE=y CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y CONFIG_HAVE_SYSCALL_TRACEPOINTS=y CONFIG_RING_BUFFER=y -CONFIG_EVENT_TRACING=y -CONFIG_CONTEXT_SWITCH_TRACER=y CONFIG_RING_BUFFER_ALLOW_SWAP=y -CONFIG_TRACING=y CONFIG_TRACING_SUPPORT=y # CONFIG_FTRACE is not set # CONFIG_DYNAMIC_DEBUG is not set @@ -1269,7 +1264,8 @@ CONFIG_CRYPTO=y # # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y -CONFIG_BINARY_PRINTF=y +# CONFIG_VIRTUALIZATION is not set +# CONFIG_BINARY_PRINTF is not set # # Library routines diff --git a/arch/sh/configs/hp6xx_defconfig b/arch/sh/configs/hp6xx_defconfig index 0664490..f894bdc 100644 --- a/arch/sh/configs/hp6xx_defconfig +++ b/arch/sh/configs/hp6xx_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 11:30:31 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 15:30:50 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -31,6 +31,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -45,9 +46,11 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SWAP=y # CONFIG_SYSVIPC is not set CONFIG_BSD_PROCESS_ACCT=y @@ -66,7 +69,6 @@ CONFIG_RCU_FANOUT=32 CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -99,7 +101,7 @@ CONFIG_PERF_USE_VMALLOC=y # # Kernel Performance Events And Counters # -# CONFIG_PERF_EVENTS is not set +CONFIG_PERF_EVENTS=y # CONFIG_PERF_COUNTERS is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_COMPAT_BRK=y @@ -115,6 +117,7 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -228,6 +231,7 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -243,7 +247,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -326,7 +330,6 @@ CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT is not set CONFIG_GUSA=y # CONFIG_GUSA_RB is not set -# CONFIG_SPARSE_IRQ is not set # # Boot options @@ -344,7 +347,6 @@ CONFIG_ENTRY_OFFSET=0x00001000 CONFIG_PCCARD=y CONFIG_PCMCIA=y CONFIG_PCMCIA_LOAD_CIS=y -CONFIG_PCMCIA_IOCTL=y # # PC-card bridges @@ -369,6 +371,7 @@ CONFIG_SUSPEND_FREEZER=y # CONFIG_HIBERNATION is not set CONFIG_APM_EMULATION=y # CONFIG_PM_RUNTIME is not set +CONFIG_PM_OPS=y # CONFIG_CPU_IDLE is not set # CONFIG_NET is not set @@ -412,6 +415,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y @@ -544,6 +548,7 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=3 CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y @@ -722,7 +727,6 @@ CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XIP is not set # CONFIG_EXT3_FS is not set # CONFIG_EXT4_FS is not set -CONFIG_EXT4_USE_FOR_EXT23=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set @@ -780,6 +784,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set +# CONFIG_LOGFS is not set # CONFIG_CRAMFS is not set # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -977,6 +982,7 @@ CONFIG_CRYPTO_MD5=y # # CONFIG_CRYPTO_ANSI_CPRNG is not set # CONFIG_CRYPTO_HW is not set +# CONFIG_VIRTUALIZATION is not set # CONFIG_BINARY_PRINTF is not set # diff --git a/arch/sh/configs/kfr2r09-romimage_defconfig b/arch/sh/configs/kfr2r09-romimage_defconfig index 3d834e5..8c54e16 100644 --- a/arch/sh/configs/kfr2r09-romimage_defconfig +++ b/arch/sh/configs/kfr2r09-romimage_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 11:31:09 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 15:33:23 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y CONFIG_GENERIC_GPIO=y CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -32,6 +32,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -46,9 +47,11 @@ CONFIG_LOCALVERSION="" CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y # CONFIG_POSIX_MQUEUE is not set @@ -70,11 +73,6 @@ CONFIG_RCU_FANOUT=32 CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 -CONFIG_GROUP_SCHED=y -CONFIG_FAIR_GROUP_SCHED=y -# CONFIG_RT_GROUP_SCHED is not set -CONFIG_USER_SCHED=y -# CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -85,6 +83,7 @@ CONFIG_INITRAMFS_SOURCE="" CONFIG_RD_GZIP=y # CONFIG_RD_BZIP2 is not set # CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_ANON_INODES=y @@ -110,7 +109,7 @@ CONFIG_PERF_USE_VMALLOC=y # # Kernel Performance Events And Counters # -# CONFIG_PERF_EVENTS is not set +CONFIG_PERF_EVENTS=y # CONFIG_PERF_COUNTERS is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_COMPAT_BRK=y @@ -119,13 +118,13 @@ CONFIG_SLAB=y # CONFIG_SLOB is not set # CONFIG_PROFILING is not set CONFIG_HAVE_OPROFILE=y -CONFIG_HAVE_IOREMAP_PROT=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -222,8 +221,8 @@ CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_MEMORY_START=0x08000000 CONFIG_MEMORY_SIZE=0x08000000 CONFIG_29BIT=y -# CONFIG_PMB_ENABLE is not set -# CONFIG_X2TLB is not set +# CONFIG_PMB is not set +CONFIG_X2TLB=y CONFIG_VSYSCALL=y CONFIG_ARCH_FLATMEM_ENABLE=y CONFIG_ARCH_SPARSEMEM_ENABLE=y @@ -231,6 +230,8 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_IOREMAP_FIXED=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -246,7 +247,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -321,7 +322,7 @@ CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set CONFIG_GUSA=y -# CONFIG_SPARSE_IRQ is not set +# CONFIG_INTC_USERIMASK is not set # # Boot options @@ -354,6 +355,7 @@ CONFIG_PM=y # CONFIG_PM_DEBUG is not set # CONFIG_SUSPEND is not set CONFIG_PM_RUNTIME=y +CONFIG_PM_OPS=y # CONFIG_CPU_IDLE is not set CONFIG_NET=y @@ -361,7 +363,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y CONFIG_UNIX=y # CONFIG_NET_KEY is not set CONFIG_INET=y @@ -449,6 +450,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_SCSI_DMA is not set # CONFIG_SCSI_NETLINK is not set # CONFIG_NETDEVICES is not set @@ -511,6 +513,7 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=6 CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y @@ -538,6 +541,7 @@ CONFIG_I2C_HELPER_AUTO=y # CONFIG_I2C_OCORES is not set CONFIG_I2C_SH_MOBILE=y # CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set # # External I2C/SMBus adapter drivers @@ -549,15 +553,9 @@ CONFIG_I2C_SH_MOBILE=y # Other I2C/SMBus bus drivers # # CONFIG_I2C_PCA_PLATFORM is not set - -# -# Miscellaneous I2C Chip support -# -# CONFIG_SENSORS_TSL2550 is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set # CONFIG_SPI is not set # @@ -571,13 +569,16 @@ CONFIG_GPIO_SYSFS=y # # Memory mapped GPIO expanders: # +# CONFIG_GPIO_IT8761E is not set # # I2C GPIO expanders: # +# CONFIG_GPIO_MAX7300 is not set # CONFIG_GPIO_MAX732X is not set # CONFIG_GPIO_PCA953X is not set # CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_ADP5588 is not set # # PCI GPIO expanders: @@ -606,20 +607,23 @@ CONFIG_SSB_POSSIBLE=y # Multifunction device drivers # # CONFIG_MFD_CORE is not set +# CONFIG_MFD_88PM860X is not set # CONFIG_MFD_SM501 is not set # CONFIG_MFD_SH_MOBILE_SDHI is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set # CONFIG_TPS65010 is not set # CONFIG_TWL4030_CORE is not set # CONFIG_MFD_TMIO is not set # CONFIG_PMIC_DA903X is not set # CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X is not set # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set # CONFIG_MFD_PCF50633 is not set # CONFIG_AB3100_CORE is not set -# CONFIG_MFD_88PM8607 is not set # CONFIG_REGULATOR is not set # CONFIG_MEDIA_SUPPORT is not set @@ -690,6 +694,7 @@ CONFIG_USB_GADGET_DUALSPEED=y # CONFIG_USB_MIDI_GADGET is not set # CONFIG_USB_G_PRINTER is not set CONFIG_USB_CDC_COMPOSITE=y +# CONFIG_USB_G_NOKIA is not set # CONFIG_USB_G_MULTI is not set # @@ -794,6 +799,7 @@ CONFIG_HAVE_ARCH_KGDB=y CONFIG_DEFAULT_SECURITY_DAC=y CONFIG_DEFAULT_SECURITY="" # CONFIG_CRYPTO is not set +# CONFIG_VIRTUALIZATION is not set # CONFIG_BINARY_PRINTF is not set # diff --git a/arch/sh/configs/kfr2r09_defconfig b/arch/sh/configs/kfr2r09_defconfig index f22be49..2e74b08 100644 --- a/arch/sh/configs/kfr2r09_defconfig +++ b/arch/sh/configs/kfr2r09_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 11:32:55 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 15:35:20 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y CONFIG_GENERIC_GPIO=y CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -32,6 +32,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -47,9 +48,11 @@ CONFIG_LOCALVERSION="" CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -72,11 +75,6 @@ CONFIG_RCU_FANOUT=32 CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 -CONFIG_GROUP_SCHED=y -CONFIG_FAIR_GROUP_SCHED=y -# CONFIG_RT_GROUP_SCHED is not set -CONFIG_USER_SCHED=y -# CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -87,6 +85,7 @@ CONFIG_INITRAMFS_SOURCE="" CONFIG_RD_GZIP=y # CONFIG_RD_BZIP2 is not set # CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_ANON_INODES=y @@ -112,7 +111,7 @@ CONFIG_PERF_USE_VMALLOC=y # # Kernel Performance Events And Counters # -# CONFIG_PERF_EVENTS is not set +CONFIG_PERF_EVENTS=y # CONFIG_PERF_COUNTERS is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_COMPAT_BRK=y @@ -121,13 +120,13 @@ CONFIG_SLAB=y # CONFIG_SLOB is not set # CONFIG_PROFILING is not set CONFIG_HAVE_OPROFILE=y -CONFIG_HAVE_IOREMAP_PROT=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -243,8 +242,8 @@ CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_MEMORY_START=0x08000000 CONFIG_MEMORY_SIZE=0x08000000 CONFIG_29BIT=y -# CONFIG_PMB_ENABLE is not set -# CONFIG_X2TLB is not set +# CONFIG_PMB is not set +CONFIG_X2TLB=y CONFIG_VSYSCALL=y CONFIG_ARCH_FLATMEM_ENABLE=y CONFIG_ARCH_SPARSEMEM_ENABLE=y @@ -252,6 +251,8 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_IOREMAP_FIXED=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -267,7 +268,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -343,7 +344,7 @@ CONFIG_KEXEC=y # CONFIG_PREEMPT_VOLUNTARY is not set CONFIG_PREEMPT=y CONFIG_GUSA=y -# CONFIG_SPARSE_IRQ is not set +# CONFIG_INTC_USERIMASK is not set # # Boot options @@ -377,6 +378,7 @@ CONFIG_PM=y # CONFIG_SUSPEND is not set # CONFIG_HIBERNATION is not set CONFIG_PM_RUNTIME=y +CONFIG_PM_OPS=y CONFIG_CPU_IDLE=y CONFIG_CPU_IDLE_GOV_LADDER=y CONFIG_CPU_IDLE_GOV_MENU=y @@ -386,7 +388,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y CONFIG_UNIX=y # CONFIG_NET_KEY is not set CONFIG_INET=y @@ -580,6 +581,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set # CONFIG_SCSI_DMA is not set @@ -659,6 +661,7 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=6 CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y @@ -687,6 +690,7 @@ CONFIG_I2C_HELPER_AUTO=y # CONFIG_I2C_OCORES is not set CONFIG_I2C_SH_MOBILE=y # CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set # # External I2C/SMBus adapter drivers @@ -699,15 +703,9 @@ CONFIG_I2C_SH_MOBILE=y # # CONFIG_I2C_PCA_PLATFORM is not set # CONFIG_I2C_STUB is not set - -# -# Miscellaneous I2C Chip support -# -# CONFIG_SENSORS_TSL2550 is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set # CONFIG_SPI is not set # @@ -721,13 +719,16 @@ CONFIG_GPIO_SYSFS=y # # Memory mapped GPIO expanders: # +# CONFIG_GPIO_IT8761E is not set # # I2C GPIO expanders: # +# CONFIG_GPIO_MAX7300 is not set # CONFIG_GPIO_MAX732X is not set # CONFIG_GPIO_PCA953X is not set # CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_ADP5588 is not set # # PCI GPIO expanders: @@ -756,20 +757,23 @@ CONFIG_SSB_POSSIBLE=y # Multifunction device drivers # # CONFIG_MFD_CORE is not set +# CONFIG_MFD_88PM860X is not set # CONFIG_MFD_SM501 is not set # CONFIG_MFD_SH_MOBILE_SDHI is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set # CONFIG_TPS65010 is not set # CONFIG_TWL4030_CORE is not set # CONFIG_MFD_TMIO is not set # CONFIG_PMIC_DA903X is not set # CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X is not set # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set # CONFIG_MFD_PCF50633 is not set # CONFIG_AB3100_CORE is not set -# CONFIG_MFD_88PM8607 is not set # CONFIG_REGULATOR is not set # CONFIG_MEDIA_SUPPORT is not set @@ -889,6 +893,7 @@ CONFIG_USB_GADGET_DUALSPEED=y # CONFIG_USB_MIDI_GADGET is not set # CONFIG_USB_G_PRINTER is not set CONFIG_USB_CDC_COMPOSITE=m +# CONFIG_USB_G_NOKIA is not set # CONFIG_USB_G_MULTI is not set # @@ -912,9 +917,6 @@ CONFIG_MMC_BLOCK_BOUNCE=y # MMC/SD/SDIO Host Controller Drivers # # CONFIG_MMC_SDHCI is not set -# CONFIG_MMC_AT91 is not set -# CONFIG_MMC_ATMELMCI is not set -# CONFIG_MMC_TMIO is not set # CONFIG_MEMSTICK is not set # CONFIG_NEW_LEDS is not set # CONFIG_ACCESSIBILITY is not set @@ -982,8 +984,6 @@ CONFIG_RTC_DRV_SH=y CONFIG_UIO=y # CONFIG_UIO_PDRV is not set CONFIG_UIO_PDRV_GENIRQ=y -# CONFIG_UIO_SMX is not set -# CONFIG_UIO_SERCOS3 is not set # # TI VLYNQ @@ -996,7 +996,6 @@ CONFIG_UIO_PDRV_GENIRQ=y # CONFIG_EXT2_FS is not set # CONFIG_EXT3_FS is not set # CONFIG_EXT4_FS is not set -CONFIG_EXT4_USE_FOR_EXT23=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set @@ -1074,6 +1073,7 @@ CONFIG_DEBUG_FS=y CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_MEMORY_INIT is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_LKDTM is not set # CONFIG_LATENCYTOP is not set # CONFIG_SYSCTL_SYSCALL_CHECK is not set CONFIG_HAVE_FUNCTION_TRACER=y @@ -1103,6 +1103,7 @@ CONFIG_HAVE_ARCH_KGDB=y CONFIG_DEFAULT_SECURITY_DAC=y CONFIG_DEFAULT_SECURITY="" # CONFIG_CRYPTO is not set +# CONFIG_VIRTUALIZATION is not set # CONFIG_BINARY_PRINTF is not set # diff --git a/arch/sh/configs/landisk_defconfig b/arch/sh/configs/landisk_defconfig index 2a42d49..8778934 100644 --- a/arch/sh/configs/landisk_defconfig +++ b/arch/sh/configs/landisk_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 11:35:31 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 15:38:08 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -32,6 +32,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -46,9 +47,11 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -69,7 +72,6 @@ CONFIG_RCU_FANOUT=32 # CONFIG_TREE_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -102,7 +104,7 @@ CONFIG_PERF_USE_VMALLOC=y # # Kernel Performance Events And Counters # -# CONFIG_PERF_EVENTS is not set +CONFIG_PERF_EVENTS=y # CONFIG_PERF_COUNTERS is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_PCI_QUIRKS=y @@ -120,6 +122,7 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -238,6 +241,7 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -253,7 +257,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -333,7 +337,6 @@ CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT is not set CONFIG_GUSA=y # CONFIG_GUSA_RB is not set -# CONFIG_SPARSE_IRQ is not set # # Boot options @@ -348,15 +351,14 @@ CONFIG_ENTRY_OFFSET=0x00001000 # Bus options # CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y # CONFIG_PCIEPORTBUS is not set # CONFIG_ARCH_SUPPORTS_MSI is not set -CONFIG_PCI_LEGACY=y # CONFIG_PCI_STUB is not set # CONFIG_PCI_IOV is not set CONFIG_PCCARD=y CONFIG_PCMCIA=y CONFIG_PCMCIA_LOAD_CIS=y -CONFIG_PCMCIA_IOCTL=y CONFIG_CARDBUS=y # @@ -392,7 +394,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -612,6 +613,7 @@ CONFIG_BLK_DEV_IDEDMA=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y @@ -711,7 +713,7 @@ CONFIG_MD_RAID1=m # # -# See the help texts for more information. +# The newer stack is recommended. # # CONFIG_FIREWIRE is not set # CONFIG_IEEE1394 is not set @@ -751,6 +753,7 @@ CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set # CONFIG_AMD8111_ETH is not set # CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_KSZ884X_PCI is not set # CONFIG_B44 is not set # CONFIG_FORCEDETH is not set # CONFIG_E100 is not set @@ -798,6 +801,8 @@ CONFIG_NETDEV_10000=y # CONFIG_CHELSIO_T1 is not set CONFIG_CHELSIO_T3_DEPENDS=y # CONFIG_CHELSIO_T3 is not set +CONFIG_CHELSIO_T4_DEPENDS=y +# CONFIG_CHELSIO_T4 is not set # CONFIG_ENIC is not set # CONFIG_IXGBE is not set # CONFIG_IXGB is not set @@ -810,6 +815,7 @@ CONFIG_CHELSIO_T3_DEPENDS=y # CONFIG_MLX4_CORE is not set # CONFIG_TEHUTI is not set # CONFIG_BNX2X is not set +# CONFIG_QLCNIC is not set # CONFIG_QLGE is not set # CONFIG_SFC is not set # CONFIG_BE2NET is not set @@ -835,6 +841,7 @@ CONFIG_WLAN=y CONFIG_USB_PEGASUS=m CONFIG_USB_RTL8150=m # CONFIG_USB_USBNET is not set +# CONFIG_USB_IPHETH is not set # CONFIG_NET_PCMCIA is not set # CONFIG_WAN is not set # CONFIG_FDDI is not set @@ -910,6 +917,7 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y @@ -977,6 +985,7 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_SH_MOBILE_SDHI is not set # CONFIG_HTC_PASIC3 is not set # CONFIG_MFD_TMIO is not set +# CONFIG_LPC_SCH is not set # CONFIG_REGULATOR is not set # CONFIG_MEDIA_SUPPORT is not set @@ -984,6 +993,7 @@ CONFIG_SSB_POSSIBLE=y # Graphics support # CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 # CONFIG_DRM is not set # CONFIG_VGASTATE is not set # CONFIG_VIDEO_OUTPUT_CONTROL is not set @@ -1025,6 +1035,7 @@ CONFIG_USB_HID=m # # Special HID drivers # +# CONFIG_HID_3M_PCT is not set CONFIG_HID_A4TECH=m CONFIG_HID_APPLE=m CONFIG_HID_BELKIN=m @@ -1040,14 +1051,19 @@ CONFIG_HID_GYRATION=m CONFIG_HID_LOGITECH=m # CONFIG_LOGITECH_FF is not set # CONFIG_LOGIRUMBLEPAD2_FF is not set +# CONFIG_LOGIG940_FF is not set CONFIG_HID_MICROSOFT=m +# CONFIG_HID_MOSART is not set CONFIG_HID_MONTEREY=m # CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set CONFIG_HID_PANTHERLORD=m # CONFIG_PANTHERLORD_FF is not set CONFIG_HID_PETALYNX=m +# CONFIG_HID_QUANTA is not set CONFIG_HID_SAMSUNG=m CONFIG_HID_SONY=m +# CONFIG_HID_STANTUM is not set CONFIG_HID_SUNPLUS=m # CONFIG_HID_GREENASIA is not set # CONFIG_HID_SMARTJOYPLUS is not set @@ -1169,6 +1185,7 @@ CONFIG_USB_SERIAL_FTDI_SIO=m # CONFIG_USB_SERIAL_NAVMAN is not set CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_SERIAL_OTI6858 is not set +# CONFIG_USB_SERIAL_QCAUX is not set # CONFIG_USB_SERIAL_QUALCOMM is not set # CONFIG_USB_SERIAL_SPCP8X5 is not set # CONFIG_USB_SERIAL_HP4X is not set @@ -1182,6 +1199,7 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_SERIAL_OPTION is not set # CONFIG_USB_SERIAL_OMNINET is not set # CONFIG_USB_SERIAL_OPTICON is not set +# CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set # CONFIG_USB_SERIAL_DEBUG is not set # @@ -1194,7 +1212,6 @@ CONFIG_USB_EMI26=m # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set -# CONFIG_USB_BERRY_CHARGE is not set # CONFIG_USB_LED is not set # CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set @@ -1208,7 +1225,6 @@ CONFIG_USB_SISUSBVGA_CON=y # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set # CONFIG_USB_ISIGHTFW is not set -# CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set # @@ -1313,6 +1329,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set +# CONFIG_LOGFS is not set # CONFIG_CRAMFS is not set # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -1347,6 +1364,7 @@ CONFIG_SUNRPC=m # CONFIG_RPCSEC_GSS_SPKM3 is not set CONFIG_SMB_FS=m # CONFIG_SMB_NLS_DEFAULT is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1531,6 +1549,7 @@ CONFIG_CRYPTO=y # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y # CONFIG_CRYPTO_DEV_HIFN_795X is not set +# CONFIG_VIRTUALIZATION is not set # CONFIG_BINARY_PRINTF is not set # diff --git a/arch/sh/configs/lboxre2_defconfig b/arch/sh/configs/lboxre2_defconfig index f2f1f8c..6088a76 100644 --- a/arch/sh/configs/lboxre2_defconfig +++ b/arch/sh/configs/lboxre2_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 11:37:01 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 15:42:57 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -32,6 +32,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -46,9 +47,11 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -69,7 +72,6 @@ CONFIG_RCU_FANOUT=32 # CONFIG_TREE_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -102,7 +104,7 @@ CONFIG_PERF_USE_VMALLOC=y # # Kernel Performance Events And Counters # -# CONFIG_PERF_EVENTS is not set +CONFIG_PERF_EVENTS=y # CONFIG_PERF_COUNTERS is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_PCI_QUIRKS=y @@ -120,6 +122,7 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -238,6 +241,7 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -253,7 +257,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -333,7 +337,6 @@ CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT is not set CONFIG_GUSA=y # CONFIG_GUSA_RB is not set -# CONFIG_SPARSE_IRQ is not set # # Boot options @@ -349,15 +352,14 @@ CONFIG_CMDLINE="console=ttySC1,115200 root=/dev/sda1" # Bus options # CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y # CONFIG_PCIEPORTBUS is not set # CONFIG_ARCH_SUPPORTS_MSI is not set -CONFIG_PCI_LEGACY=y # CONFIG_PCI_STUB is not set # CONFIG_PCI_IOV is not set CONFIG_PCCARD=y CONFIG_PCMCIA=y CONFIG_PCMCIA_LOAD_CIS=y -CONFIG_PCMCIA_IOCTL=y CONFIG_CARDBUS=y # @@ -392,7 +394,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -552,6 +553,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y @@ -670,6 +672,7 @@ CONFIG_ATA_SFF=y # CONFIG_PATA_IT821X is not set # CONFIG_PATA_IT8213 is not set # CONFIG_PATA_JMICRON is not set +# CONFIG_PATA_LEGACY is not set # CONFIG_PATA_TRIFLEX is not set # CONFIG_PATA_MARVELL is not set # CONFIG_PATA_MPIIX is not set @@ -707,7 +710,7 @@ CONFIG_PATA_PLATFORM=y # # -# See the help texts for more information. +# The newer stack is recommended. # # CONFIG_FIREWIRE is not set # CONFIG_IEEE1394 is not set @@ -747,6 +750,7 @@ CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set # CONFIG_AMD8111_ETH is not set # CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_KSZ884X_PCI is not set # CONFIG_B44 is not set # CONFIG_FORCEDETH is not set # CONFIG_E100 is not set @@ -798,6 +802,8 @@ CONFIG_NETDEV_10000=y # CONFIG_CHELSIO_T1 is not set CONFIG_CHELSIO_T3_DEPENDS=y # CONFIG_CHELSIO_T3 is not set +CONFIG_CHELSIO_T4_DEPENDS=y +# CONFIG_CHELSIO_T4 is not set # CONFIG_ENIC is not set # CONFIG_IXGBE is not set # CONFIG_IXGB is not set @@ -810,6 +816,7 @@ CONFIG_CHELSIO_T3_DEPENDS=y # CONFIG_MLX4_CORE is not set # CONFIG_TEHUTI is not set # CONFIG_BNX2X is not set +# CONFIG_QLCNIC is not set # CONFIG_QLGE is not set # CONFIG_SFC is not set # CONFIG_BE2NET is not set @@ -908,6 +915,7 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y @@ -975,6 +983,7 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_SH_MOBILE_SDHI is not set # CONFIG_HTC_PASIC3 is not set # CONFIG_MFD_TMIO is not set +# CONFIG_LPC_SCH is not set # CONFIG_REGULATOR is not set # CONFIG_MEDIA_SUPPORT is not set @@ -982,6 +991,7 @@ CONFIG_SSB_POSSIBLE=y # Graphics support # CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 # CONFIG_DRM is not set # CONFIG_VGASTATE is not set # CONFIG_VIDEO_OUTPUT_CONTROL is not set @@ -1155,6 +1165,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set +# CONFIG_LOGFS is not set # CONFIG_CRAMFS is not set # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -1173,6 +1184,7 @@ CONFIG_NETWORK_FILESYSTEMS=y # CONFIG_NFS_FS is not set # CONFIG_NFSD is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1357,6 +1369,7 @@ CONFIG_CRYPTO=y # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y # CONFIG_CRYPTO_DEV_HIFN_795X is not set +# CONFIG_VIRTUALIZATION is not set # CONFIG_BINARY_PRINTF is not set # diff --git a/arch/sh/configs/magicpanelr2_defconfig b/arch/sh/configs/magicpanelr2_defconfig index a7a16ce..28c104d 100644 --- a/arch/sh/configs/magicpanelr2_defconfig +++ b/arch/sh/configs/magicpanelr2_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 11:37:42 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 15:44:00 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y CONFIG_GENERIC_GPIO=y CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -31,6 +31,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -45,9 +46,11 @@ CONFIG_LOCALVERSION="" CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -71,7 +74,6 @@ CONFIG_RCU_FANOUT=32 # CONFIG_TREE_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=17 -# CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -82,6 +84,7 @@ CONFIG_INITRAMFS_SOURCE="" CONFIG_RD_GZIP=y # CONFIG_RD_BZIP2 is not set # CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SYSCTL=y CONFIG_ANON_INODES=y @@ -109,8 +112,9 @@ CONFIG_PERF_USE_VMALLOC=y # # Kernel Performance Events And Counters # -# CONFIG_PERF_EVENTS is not set +CONFIG_PERF_EVENTS=y # CONFIG_PERF_COUNTERS is not set +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_COMPAT_BRK=y CONFIG_SLAB=y @@ -126,6 +130,7 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -244,6 +249,7 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -259,7 +265,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -344,7 +350,6 @@ CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT is not set CONFIG_GUSA=y # CONFIG_GUSA_RB is not set -# CONFIG_SPARSE_IRQ is not set # # Boot options @@ -380,7 +385,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y CONFIG_UNIX=y # CONFIG_NET_KEY is not set CONFIG_INET=y @@ -586,6 +590,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set # CONFIG_SCSI_DMA is not set @@ -741,6 +746,7 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=2 CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y @@ -765,6 +771,7 @@ CONFIG_GPIOLIB=y # # Memory mapped GPIO expanders: # +# CONFIG_GPIO_IT8761E is not set # # I2C GPIO expanders: @@ -953,6 +960,7 @@ CONFIG_JFFS2_ZLIB=y # CONFIG_JFFS2_LZO is not set CONFIG_JFFS2_RTIME=y # CONFIG_JFFS2_RUBIN is not set +# CONFIG_LOGFS is not set # CONFIG_CRAMFS is not set # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -977,6 +985,7 @@ CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1051,6 +1060,7 @@ CONFIG_DEBUG_KERNEL=y # CONFIG_TIMER_STATS is not set # CONFIG_DEBUG_OBJECTS is not set # CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_KMEMLEAK is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set @@ -1097,6 +1107,7 @@ CONFIG_FTRACE=y CONFIG_BRANCH_PROFILE_NONE=y # CONFIG_PROFILE_ANNOTATED_BRANCHES is not set # CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_KSYM_TRACER is not set # CONFIG_STACK_TRACER is not set # CONFIG_KMEMTRACE is not set # CONFIG_WORKQUEUE_TRACER is not set @@ -1125,6 +1136,7 @@ CONFIG_DUMP_CODE=y CONFIG_DEFAULT_SECURITY_DAC=y CONFIG_DEFAULT_SECURITY="" # CONFIG_CRYPTO is not set +# CONFIG_VIRTUALIZATION is not set # CONFIG_BINARY_PRINTF is not set # diff --git a/arch/sh/configs/microdev_defconfig b/arch/sh/configs/microdev_defconfig index 7d43fab..41cefa4 100644 --- a/arch/sh/configs/microdev_defconfig +++ b/arch/sh/configs/microdev_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 11:40:41 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 15:48:22 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -31,6 +31,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -46,9 +47,11 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SWAP=y # CONFIG_SYSVIPC is not set # CONFIG_POSIX_MQUEUE is not set @@ -69,7 +72,6 @@ CONFIG_RCU_FANOUT=32 # CONFIG_TREE_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -80,6 +82,7 @@ CONFIG_INITRAMFS_SOURCE="" CONFIG_RD_GZIP=y # CONFIG_RD_BZIP2 is not set # CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SYSCTL=y CONFIG_ANON_INODES=y @@ -106,7 +109,7 @@ CONFIG_PERF_USE_VMALLOC=y # # Kernel Performance Events And Counters # -# CONFIG_PERF_EVENTS is not set +CONFIG_PERF_EVENTS=y # CONFIG_PERF_COUNTERS is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_COMPAT_BRK=y @@ -122,6 +125,7 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -235,6 +239,7 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -256,7 +261,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -334,7 +339,6 @@ CONFIG_HZ=250 CONFIG_PREEMPT=y CONFIG_GUSA=y # CONFIG_GUSA_RB is not set -# CONFIG_SPARSE_IRQ is not set # # Boot options @@ -515,6 +519,7 @@ CONFIG_IDE_PROC_FS=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set # CONFIG_SCSI_DMA is not set @@ -596,6 +601,7 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=2 CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y @@ -774,6 +780,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set +# CONFIG_LOGFS is not set # CONFIG_CRAMFS is not set # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -800,6 +807,7 @@ CONFIG_SUNRPC_GSS=y CONFIG_RPCSEC_GSS_KRB5=y # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -992,6 +1000,7 @@ CONFIG_CRYPTO_DES=y # # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y +# CONFIG_VIRTUALIZATION is not set # CONFIG_BINARY_PRINTF is not set # diff --git a/arch/sh/configs/migor_defconfig b/arch/sh/configs/migor_defconfig index d2b1831..1c889b7 100644 --- a/arch/sh/configs/migor_defconfig +++ b/arch/sh/configs/migor_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 11:41:41 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 18:01:29 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y CONFIG_GENERIC_GPIO=y CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -33,6 +33,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -47,9 +48,11 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -71,7 +74,6 @@ CONFIG_RCU_FANOUT=32 CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -82,6 +84,7 @@ CONFIG_INITRAMFS_SOURCE="" CONFIG_RD_GZIP=y # CONFIG_RD_BZIP2 is not set # CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SYSCTL=y CONFIG_ANON_INODES=y @@ -109,7 +112,6 @@ CONFIG_PERF_USE_VMALLOC=y # Kernel Performance Events And Counters # CONFIG_PERF_EVENTS=y -CONFIG_EVENT_PROFILE=y # CONFIG_PERF_COUNTERS is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_COMPAT_BRK=y @@ -117,17 +119,16 @@ CONFIG_SLAB=y # CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_PROFILING=y -CONFIG_TRACEPOINTS=y CONFIG_OPROFILE=y CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set -CONFIG_HAVE_IOREMAP_PROT=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -243,7 +244,7 @@ CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_MEMORY_START=0x0c000000 CONFIG_MEMORY_SIZE=0x04000000 CONFIG_29BIT=y -# CONFIG_X2TLB is not set +CONFIG_X2TLB=y CONFIG_VSYSCALL=y CONFIG_NUMA=y CONFIG_NODES_SHIFT=1 @@ -254,6 +255,8 @@ CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y +CONFIG_IOREMAP_FIXED=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -271,7 +274,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_MIGRATION is not set # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -348,7 +351,7 @@ CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set CONFIG_GUSA=y -# CONFIG_SPARSE_IRQ is not set +# CONFIG_INTC_USERIMASK is not set # # Boot options @@ -384,6 +387,7 @@ CONFIG_SUSPEND=y CONFIG_SUSPEND_FREEZER=y # CONFIG_HIBERNATION is not set CONFIG_PM_RUNTIME=y +CONFIG_PM_OPS=y # CONFIG_CPU_IDLE is not set CONFIG_NET=y @@ -391,7 +395,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -454,7 +457,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # Network testing # # CONFIG_NET_PKTGEN is not set -# CONFIG_NET_DROP_MONITOR is not set # CONFIG_HAMRADIO is not set # CONFIG_CAN is not set # CONFIG_IRDA is not set @@ -564,6 +566,7 @@ CONFIG_MTD_NAND_IDS=y # CONFIG_MTD_NAND_DISKONCHIP is not set # CONFIG_MTD_NAND_NANDSIM is not set CONFIG_MTD_NAND_PLATFORM=y +# CONFIG_MTD_NAND_SH_FLCTL is not set # CONFIG_MTD_ONENAND is not set # @@ -596,6 +599,7 @@ CONFIG_MISC_DEVICES=y # CONFIG_ICS932S401 is not set # CONFIG_ENCLOSURE_SERVICES is not set # CONFIG_ISL29003 is not set +# CONFIG_SENSORS_TSL2550 is not set # CONFIG_DS1682 is not set # CONFIG_C2PORT is not set @@ -612,6 +616,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y @@ -764,6 +769,7 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=3 CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y @@ -792,6 +798,7 @@ CONFIG_I2C_HELPER_AUTO=y # CONFIG_I2C_OCORES is not set CONFIG_I2C_SH_MOBILE=y # CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set # # External I2C/SMBus adapter drivers @@ -804,15 +811,9 @@ CONFIG_I2C_SH_MOBILE=y # # CONFIG_I2C_PCA_PLATFORM is not set # CONFIG_I2C_STUB is not set - -# -# Miscellaneous I2C Chip support -# -# CONFIG_SENSORS_TSL2550 is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set # CONFIG_SPI is not set # @@ -826,13 +827,16 @@ CONFIG_GPIOLIB=y # # Memory mapped GPIO expanders: # +# CONFIG_GPIO_IT8761E is not set # # I2C GPIO expanders: # +# CONFIG_GPIO_MAX7300 is not set # CONFIG_GPIO_MAX732X is not set # CONFIG_GPIO_PCA953X is not set # CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_ADP5588 is not set # # PCI GPIO expanders: @@ -861,20 +865,23 @@ CONFIG_SSB_POSSIBLE=y # Multifunction device drivers # # CONFIG_MFD_CORE is not set +# CONFIG_MFD_88PM860X is not set # CONFIG_MFD_SM501 is not set # CONFIG_MFD_SH_MOBILE_SDHI is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set # CONFIG_TPS65010 is not set # CONFIG_TWL4030_CORE is not set # CONFIG_MFD_TMIO is not set # CONFIG_PMIC_DA903X is not set # CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X is not set # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set # CONFIG_MFD_PCF50633 is not set # CONFIG_AB3100_CORE is not set -# CONFIG_MFD_88PM8607 is not set # CONFIG_REGULATOR is not set CONFIG_MEDIA_SUPPORT=y @@ -1054,6 +1061,7 @@ CONFIG_USB_G_SERIAL=m # CONFIG_USB_MIDI_GADGET is not set # CONFIG_USB_G_PRINTER is not set # CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_G_NOKIA is not set # CONFIG_USB_G_MULTI is not set # @@ -1129,8 +1137,6 @@ CONFIG_RTC_DRV_SH=y CONFIG_UIO=y # CONFIG_UIO_PDRV is not set CONFIG_UIO_PDRV_GENIRQ=y -# CONFIG_UIO_SMX is not set -# CONFIG_UIO_SERCOS3 is not set # # TI VLYNQ @@ -1143,7 +1149,6 @@ CONFIG_UIO_PDRV_GENIRQ=y # CONFIG_EXT2_FS is not set # CONFIG_EXT3_FS is not set # CONFIG_EXT4_FS is not set -CONFIG_EXT4_USE_FOR_EXT23=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set @@ -1202,6 +1207,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set # CONFIG_JFFS2_FS is not set +# CONFIG_LOGFS is not set # CONFIG_CRAMFS is not set # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -1224,6 +1230,7 @@ CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1251,13 +1258,12 @@ CONFIG_FRAME_WARN=1024 CONFIG_DEBUG_FS=y # CONFIG_HEADERS_CHECK is not set # CONFIG_DEBUG_KERNEL is not set -CONFIG_STACKTRACE=y CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_MEMORY_INIT is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_LKDTM is not set # CONFIG_LATENCYTOP is not set # CONFIG_SYSCTL_SYSCALL_CHECK is not set -CONFIG_NOP_TRACER=y CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y @@ -1265,10 +1271,7 @@ CONFIG_HAVE_DYNAMIC_FTRACE=y CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y CONFIG_HAVE_SYSCALL_TRACEPOINTS=y CONFIG_RING_BUFFER=y -CONFIG_EVENT_TRACING=y -CONFIG_CONTEXT_SWITCH_TRACER=y CONFIG_RING_BUFFER_ALLOW_SWAP=y -CONFIG_TRACING=y CONFIG_TRACING_SUPPORT=y # CONFIG_FTRACE is not set # CONFIG_DYNAMIC_DEBUG is not set @@ -1383,7 +1386,8 @@ CONFIG_CRYPTO_WORKQUEUE=y # # CONFIG_CRYPTO_ANSI_CPRNG is not set # CONFIG_CRYPTO_HW is not set -CONFIG_BINARY_PRINTF=y +# CONFIG_VIRTUALIZATION is not set +# CONFIG_BINARY_PRINTF is not set # # Library routines diff --git a/arch/sh/configs/polaris_defconfig b/arch/sh/configs/polaris_defconfig index d50c031..826b119 100644 --- a/arch/sh/configs/polaris_defconfig +++ b/arch/sh/configs/polaris_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 11:45:25 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 15:53:51 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -30,6 +30,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -45,9 +46,11 @@ CONFIG_LOCALVERSION="" CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set # CONFIG_SWAP is not set CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -71,11 +74,6 @@ CONFIG_RCU_FANOUT=32 # CONFIG_TREE_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 -CONFIG_GROUP_SCHED=y -CONFIG_FAIR_GROUP_SCHED=y -# CONFIG_RT_GROUP_SCHED is not set -CONFIG_USER_SCHED=y -# CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -109,8 +107,9 @@ CONFIG_PERF_USE_VMALLOC=y # # Kernel Performance Events And Counters # -# CONFIG_PERF_EVENTS is not set +CONFIG_PERF_EVENTS=y # CONFIG_PERF_COUNTERS is not set +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_COMPAT_BRK=y CONFIG_SLAB=y @@ -126,6 +125,7 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -244,6 +244,7 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -259,7 +260,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=999999 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -340,7 +341,6 @@ CONFIG_SCHED_HRTICK=y CONFIG_PREEMPT=y CONFIG_GUSA=y # CONFIG_GUSA_RB is not set -# CONFIG_SPARSE_IRQ is not set # # Boot options @@ -377,7 +377,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y CONFIG_UNIX=y # CONFIG_NET_KEY is not set CONFIG_INET=y @@ -583,6 +582,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set # CONFIG_SCSI_DMA is not set @@ -712,6 +712,7 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=3 CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set # CONFIG_LEGACY_PTYS is not set @@ -829,7 +830,6 @@ CONFIG_RTC_DRV_SH=y # CONFIG_EXT2_FS is not set # CONFIG_EXT3_FS is not set # CONFIG_EXT4_FS is not set -CONFIG_EXT4_USE_FOR_EXT23=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set @@ -896,6 +896,7 @@ CONFIG_JFFS2_ZLIB=y # CONFIG_JFFS2_LZO is not set CONFIG_JFFS2_RTIME=y # CONFIG_JFFS2_RUBIN is not set +# CONFIG_LOGFS is not set # CONFIG_CRAMFS is not set # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -919,6 +920,7 @@ CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -958,6 +960,7 @@ CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 # CONFIG_TIMER_STATS is not set # CONFIG_DEBUG_OBJECTS is not set # CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_KMEMLEAK is not set CONFIG_DEBUG_PREEMPT=y CONFIG_DEBUG_RT_MUTEXES=y CONFIG_DEBUG_PI_LIST=y @@ -1010,6 +1013,7 @@ CONFIG_FTRACE=y CONFIG_BRANCH_PROFILE_NONE=y # CONFIG_PROFILE_ANNOTATED_BRANCHES is not set # CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_KSYM_TRACER is not set # CONFIG_STACK_TRACER is not set # CONFIG_KMEMTRACE is not set # CONFIG_WORKQUEUE_TRACER is not set @@ -1038,6 +1042,7 @@ CONFIG_DUMP_CODE=y CONFIG_DEFAULT_SECURITY_DAC=y CONFIG_DEFAULT_SECURITY="" # CONFIG_CRYPTO is not set +# CONFIG_VIRTUALIZATION is not set # CONFIG_BINARY_PRINTF is not set # diff --git a/arch/sh/configs/r7780mp_defconfig b/arch/sh/configs/r7780mp_defconfig index efda63d..4b751bd 100644 --- a/arch/sh/configs/r7780mp_defconfig +++ b/arch/sh/configs/r7780mp_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 13:16:13 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 15:58:09 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -33,6 +33,7 @@ CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_IO_TRAPPED=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -48,9 +49,11 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -73,11 +76,6 @@ CONFIG_RCU_FANOUT=32 CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 -CONFIG_GROUP_SCHED=y -CONFIG_FAIR_GROUP_SCHED=y -# CONFIG_RT_GROUP_SCHED is not set -CONFIG_USER_SCHED=y -# CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -112,7 +110,6 @@ CONFIG_PERF_USE_VMALLOC=y # Kernel Performance Events And Counters # CONFIG_PERF_EVENTS=y -CONFIG_EVENT_PROFILE=y # CONFIG_PERF_COUNTERS is not set # CONFIG_DEBUG_PERF_USE_VMALLOC is not set CONFIG_VM_EVENT_COUNTERS=y @@ -122,7 +119,6 @@ CONFIG_SLAB=y # CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_PROFILING=y -CONFIG_TRACEPOINTS=y CONFIG_OPROFILE=m CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set @@ -133,6 +129,7 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -245,11 +242,8 @@ CONFIG_PAGE_OFFSET=0x80000000 CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_MEMORY_START=0x08000000 CONFIG_MEMORY_SIZE=0x08000000 -# CONFIG_29BIT is not set -CONFIG_32BIT=y -CONFIG_PMB_ENABLE=y +CONFIG_29BIT=y # CONFIG_PMB is not set -CONFIG_PMB_FIXED=y CONFIG_VSYSCALL=y CONFIG_ARCH_FLATMEM_ENABLE=y CONFIG_ARCH_SPARSEMEM_ENABLE=y @@ -257,6 +251,7 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -278,7 +273,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -358,7 +353,7 @@ CONFIG_KEXEC=y # CONFIG_PREEMPT_VOLUNTARY is not set CONFIG_PREEMPT=y CONFIG_GUSA=y -# CONFIG_SPARSE_IRQ is not set +# CONFIG_INTC_USERIMASK is not set # # Boot options @@ -374,9 +369,9 @@ CONFIG_CMDLINE="console=ttySC0,115200 root=/dev/sda1" # Bus options # CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y # CONFIG_PCIEPORTBUS is not set # CONFIG_ARCH_SUPPORTS_MSI is not set -CONFIG_PCI_LEGACY=y # CONFIG_PCI_DEBUG is not set # CONFIG_PCI_STUB is not set # CONFIG_PCI_IOV is not set @@ -402,7 +397,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -452,6 +446,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_ATM is not set CONFIG_STP=m CONFIG_BRIDGE=m +CONFIG_BRIDGE_IGMP_SNOOPING=y # CONFIG_NET_DSA is not set # CONFIG_VLAN_8021Q is not set # CONFIG_DECNET is not set @@ -472,7 +467,6 @@ CONFIG_LLC=m # Network testing # # CONFIG_NET_PKTGEN is not set -# CONFIG_NET_DROP_MONITOR is not set # CONFIG_HAMRADIO is not set # CONFIG_CAN is not set # CONFIG_IRDA is not set @@ -621,6 +615,7 @@ CONFIG_MISC_DEVICES=y # CONFIG_ENCLOSURE_SERVICES is not set # CONFIG_HP_ILO is not set # CONFIG_ISL29003 is not set +# CONFIG_SENSORS_TSL2550 is not set # CONFIG_DS1682 is not set # CONFIG_C2PORT is not set @@ -638,6 +633,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y @@ -755,6 +751,7 @@ CONFIG_SATA_SIL=y # CONFIG_PATA_IT821X is not set # CONFIG_PATA_IT8213 is not set # CONFIG_PATA_JMICRON is not set +# CONFIG_PATA_LEGACY is not set # CONFIG_PATA_TRIFLEX is not set # CONFIG_PATA_MARVELL is not set # CONFIG_PATA_MPIIX is not set @@ -791,7 +788,7 @@ CONFIG_PATA_PLATFORM=y # # -# See the help texts for more information. +# The newer stack is recommended. # # CONFIG_FIREWIRE is not set # CONFIG_IEEE1394 is not set @@ -832,6 +829,7 @@ CONFIG_NET_PCI=y CONFIG_PCNET32=m # CONFIG_AMD8111_ETH is not set # CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_KSZ884X_PCI is not set # CONFIG_B44 is not set # CONFIG_FORCEDETH is not set # CONFIG_E100 is not set @@ -884,6 +882,8 @@ CONFIG_NETDEV_10000=y # CONFIG_CHELSIO_T1 is not set CONFIG_CHELSIO_T3_DEPENDS=y # CONFIG_CHELSIO_T3 is not set +CONFIG_CHELSIO_T4_DEPENDS=y +# CONFIG_CHELSIO_T4 is not set # CONFIG_ENIC is not set # CONFIG_IXGBE is not set # CONFIG_IXGB is not set @@ -896,6 +896,7 @@ CONFIG_CHELSIO_T3_DEPENDS=y # CONFIG_MLX4_CORE is not set # CONFIG_TEHUTI is not set # CONFIG_BNX2X is not set +# CONFIG_QLCNIC is not set # CONFIG_QLGE is not set # CONFIG_SFC is not set # CONFIG_BE2NET is not set @@ -995,6 +996,7 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y @@ -1043,6 +1045,7 @@ CONFIG_I2C_HIGHLANDER=y # CONFIG_I2C_OCORES is not set # CONFIG_I2C_SH_MOBILE is not set # CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set # # External I2C/SMBus adapter drivers @@ -1055,15 +1058,9 @@ CONFIG_I2C_HIGHLANDER=y # # CONFIG_I2C_PCA_PLATFORM is not set # CONFIG_I2C_STUB is not set - -# -# Miscellaneous I2C Chip support -# -# CONFIG_SENSORS_TSL2550 is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set # CONFIG_SPI is not set # @@ -1087,10 +1084,11 @@ CONFIG_HWMON=y # CONFIG_SENSORS_ADM1029 is not set # CONFIG_SENSORS_ADM1031 is not set # CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7411 is not set # CONFIG_SENSORS_ADT7462 is not set # CONFIG_SENSORS_ADT7470 is not set -# CONFIG_SENSORS_ADT7473 is not set # CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ASC7621 is not set # CONFIG_SENSORS_ATXP1 is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_I5K_AMB is not set @@ -1127,6 +1125,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_SMSC47M192 is not set # CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_AMC6821 is not set # CONFIG_SENSORS_THMC50 is not set # CONFIG_SENSORS_TMP401 is not set # CONFIG_SENSORS_TMP421 is not set @@ -1156,6 +1155,7 @@ CONFIG_SSB_POSSIBLE=y # Multifunction device drivers # # CONFIG_MFD_CORE is not set +# CONFIG_MFD_88PM860X is not set # CONFIG_MFD_SM501 is not set # CONFIG_MFD_SH_MOBILE_SDHI is not set # CONFIG_HTC_PASIC3 is not set @@ -1163,12 +1163,14 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_TMIO is not set # CONFIG_PMIC_DA903X is not set # CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X is not set # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set # CONFIG_MFD_PCF50633 is not set # CONFIG_AB3100_CORE is not set -# CONFIG_MFD_88PM8607 is not set +# CONFIG_LPC_SCH is not set # CONFIG_REGULATOR is not set # CONFIG_MEDIA_SUPPORT is not set @@ -1176,6 +1178,7 @@ CONFIG_SSB_POSSIBLE=y # Graphics support # CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 # CONFIG_DRM is not set # CONFIG_VGASTATE is not set # CONFIG_VIDEO_OUTPUT_CONTROL is not set @@ -1372,6 +1375,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set # CONFIG_JFFS2_FS is not set +# CONFIG_LOGFS is not set # CONFIG_CRAMFS is not set # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -1402,6 +1406,7 @@ CONFIG_SUNRPC_GSS=y CONFIG_RPCSEC_GSS_KRB5=y # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1480,6 +1485,7 @@ CONFIG_SCHED_DEBUG=y # CONFIG_TIMER_STATS is not set # CONFIG_DEBUG_OBJECTS is not set # CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_KMEMLEAK is not set # CONFIG_DEBUG_PREEMPT is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set @@ -1490,7 +1496,6 @@ CONFIG_SCHED_DEBUG=y # CONFIG_LOCK_STAT is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set -CONFIG_STACKTRACE=y # CONFIG_DEBUG_KOBJECT is not set CONFIG_DEBUG_BUGVERBOSE=y CONFIG_DEBUG_INFO=y @@ -1507,11 +1512,11 @@ CONFIG_DEBUG_INFO=y # CONFIG_BACKTRACE_SELF_TEST is not set # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_LKDTM is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set # CONFIG_SYSCTL_SYSCALL_CHECK is not set # CONFIG_PAGE_POISONING is not set -CONFIG_NOP_TRACER=y CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y @@ -1519,10 +1524,7 @@ CONFIG_HAVE_DYNAMIC_FTRACE=y CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y CONFIG_HAVE_SYSCALL_TRACEPOINTS=y CONFIG_RING_BUFFER=y -CONFIG_EVENT_TRACING=y -CONFIG_CONTEXT_SWITCH_TRACER=y CONFIG_RING_BUFFER_ALLOW_SWAP=y -CONFIG_TRACING=y CONFIG_TRACING_SUPPORT=y CONFIG_FTRACE=y # CONFIG_FUNCTION_TRACER is not set @@ -1535,6 +1537,7 @@ CONFIG_FTRACE=y CONFIG_BRANCH_PROFILE_NONE=y # CONFIG_PROFILE_ANNOTATED_BRANCHES is not set # CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_KSYM_TRACER is not set # CONFIG_STACK_TRACER is not set # CONFIG_KMEMTRACE is not set # CONFIG_WORKQUEUE_TRACER is not set @@ -1662,7 +1665,8 @@ CONFIG_CRYPTO_DES=y # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y # CONFIG_CRYPTO_DEV_HIFN_795X is not set -CONFIG_BINARY_PRINTF=y +# CONFIG_VIRTUALIZATION is not set +# CONFIG_BINARY_PRINTF is not set # # Library routines diff --git a/arch/sh/configs/r7785rp_defconfig b/arch/sh/configs/r7785rp_defconfig index f4b0045..f5e3819 100644 --- a/arch/sh/configs/r7785rp_defconfig +++ b/arch/sh/configs/r7785rp_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 13:19:35 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 16:03:27 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y CONFIG_GENERIC_GPIO=y CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -34,6 +34,7 @@ CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_IO_TRAPPED=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -49,9 +50,11 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -77,7 +80,6 @@ CONFIG_TREE_RCU_TRACE=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -112,7 +114,6 @@ CONFIG_PERF_USE_VMALLOC=y # Kernel Performance Events And Counters # CONFIG_PERF_EVENTS=y -CONFIG_EVENT_PROFILE=y # CONFIG_PERF_COUNTERS is not set # CONFIG_DEBUG_PERF_USE_VMALLOC is not set CONFIG_VM_EVENT_COUNTERS=y @@ -122,18 +123,17 @@ CONFIG_SLAB=y # CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_PROFILING=y -CONFIG_TRACEPOINTS=y CONFIG_OPROFILE=y CONFIG_HAVE_OPROFILE=y CONFIG_KPROBES=y CONFIG_KRETPROBES=y -CONFIG_HAVE_IOREMAP_PROT=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -247,12 +247,9 @@ CONFIG_PAGE_OFFSET=0x80000000 CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_MEMORY_START=0x08000000 CONFIG_MEMORY_SIZE=0x08000000 -# CONFIG_29BIT is not set -CONFIG_32BIT=y -CONFIG_PMB_ENABLE=y +CONFIG_29BIT=y # CONFIG_PMB is not set -CONFIG_PMB_FIXED=y -# CONFIG_X2TLB is not set +CONFIG_X2TLB=y CONFIG_VSYSCALL=y # CONFIG_NUMA is not set CONFIG_ARCH_FLATMEM_ENABLE=y @@ -263,6 +260,8 @@ CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y +CONFIG_IOREMAP_FIXED=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -285,7 +284,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=999999 CONFIG_MIGRATION=y # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -303,6 +302,7 @@ CONFIG_CPU_LITTLE_ENDIAN=y # CONFIG_CPU_BIG_ENDIAN is not set CONFIG_SH_FPU=y CONFIG_SH_STORE_QUEUES=y +# CONFIG_SPECULATIVE_EXECUTION is not set CONFIG_CPU_HAS_INTEVT=y CONFIG_CPU_HAS_SR_RB=y CONFIG_CPU_HAS_FPU=y @@ -377,7 +377,7 @@ CONFIG_KEXEC=y # CONFIG_PREEMPT_VOLUNTARY is not set CONFIG_PREEMPT=y CONFIG_GUSA=y -# CONFIG_SPARSE_IRQ is not set +# CONFIG_INTC_USERIMASK is not set # # Boot options @@ -393,9 +393,9 @@ CONFIG_CMDLINE="console=ttySC0,115200 root=/dev/sda1" # Bus options # CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y # CONFIG_PCIEPORTBUS is not set # CONFIG_ARCH_SUPPORTS_MSI is not set -# CONFIG_PCI_LEGACY is not set # CONFIG_PCI_DEBUG is not set # CONFIG_PCI_STUB is not set # CONFIG_PCI_IOV is not set @@ -421,7 +421,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -471,6 +470,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_ATM is not set CONFIG_STP=m CONFIG_BRIDGE=m +CONFIG_BRIDGE_IGMP_SNOOPING=y # CONFIG_NET_DSA is not set # CONFIG_VLAN_8021Q is not set # CONFIG_DECNET is not set @@ -492,7 +492,6 @@ CONFIG_LLC=m # # CONFIG_NET_PKTGEN is not set # CONFIG_NET_TCPPROBE is not set -# CONFIG_NET_DROP_MONITOR is not set # CONFIG_HAMRADIO is not set # CONFIG_CAN is not set # CONFIG_IRDA is not set @@ -557,6 +556,7 @@ CONFIG_MISC_DEVICES=y # CONFIG_ENCLOSURE_SERVICES is not set # CONFIG_HP_ILO is not set # CONFIG_ISL29003 is not set +# CONFIG_SENSORS_TSL2550 is not set # CONFIG_DS1682 is not set # CONFIG_C2PORT is not set @@ -574,6 +574,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y @@ -691,6 +692,7 @@ CONFIG_SATA_SIL=y # CONFIG_PATA_IT821X is not set # CONFIG_PATA_IT8213 is not set # CONFIG_PATA_JMICRON is not set +# CONFIG_PATA_LEGACY is not set # CONFIG_PATA_TRIFLEX is not set # CONFIG_PATA_MARVELL is not set # CONFIG_PATA_MPIIX is not set @@ -727,7 +729,7 @@ CONFIG_PATA_PLATFORM=y # # -# See the help texts for more information. +# The newer stack is recommended. # # CONFIG_FIREWIRE is not set # CONFIG_IEEE1394 is not set @@ -797,6 +799,8 @@ CONFIG_NETDEV_10000=y # CONFIG_CHELSIO_T1 is not set CONFIG_CHELSIO_T3_DEPENDS=y # CONFIG_CHELSIO_T3 is not set +CONFIG_CHELSIO_T4_DEPENDS=y +# CONFIG_CHELSIO_T4 is not set # CONFIG_ENIC is not set # CONFIG_IXGBE is not set # CONFIG_IXGB is not set @@ -809,6 +813,7 @@ CONFIG_CHELSIO_T3_DEPENDS=y # CONFIG_MLX4_CORE is not set # CONFIG_TEHUTI is not set # CONFIG_BNX2X is not set +# CONFIG_QLCNIC is not set # CONFIG_QLGE is not set # CONFIG_SFC is not set # CONFIG_BE2NET is not set @@ -910,6 +915,7 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y @@ -959,6 +965,7 @@ CONFIG_I2C_HIGHLANDER=y # CONFIG_I2C_OCORES is not set # CONFIG_I2C_SH_MOBILE is not set # CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set # # External I2C/SMBus adapter drivers @@ -971,15 +978,9 @@ CONFIG_I2C_HIGHLANDER=y # # CONFIG_I2C_PCA_PLATFORM is not set # CONFIG_I2C_STUB is not set - -# -# Miscellaneous I2C Chip support -# -# CONFIG_SENSORS_TSL2550 is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set # CONFIG_SPI is not set # @@ -994,13 +995,17 @@ CONFIG_GPIOLIB=y # # Memory mapped GPIO expanders: # +# CONFIG_GPIO_IT8761E is not set +# CONFIG_GPIO_SCH is not set # # I2C GPIO expanders: # +# CONFIG_GPIO_MAX7300 is not set # CONFIG_GPIO_MAX732X is not set # CONFIG_GPIO_PCA953X is not set # CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_ADP5588 is not set # # PCI GPIO expanders: @@ -1033,10 +1038,11 @@ CONFIG_HWMON=y # CONFIG_SENSORS_ADM1029 is not set # CONFIG_SENSORS_ADM1031 is not set # CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7411 is not set # CONFIG_SENSORS_ADT7462 is not set # CONFIG_SENSORS_ADT7470 is not set -# CONFIG_SENSORS_ADT7473 is not set # CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ASC7621 is not set # CONFIG_SENSORS_ATXP1 is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_I5K_AMB is not set @@ -1074,6 +1080,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_SMSC47M192 is not set # CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_AMC6821 is not set # CONFIG_SENSORS_THMC50 is not set # CONFIG_SENSORS_TMP401 is not set # CONFIG_SENSORS_TMP421 is not set @@ -1102,20 +1109,25 @@ CONFIG_SSB_POSSIBLE=y # Multifunction device drivers # # CONFIG_MFD_CORE is not set +# CONFIG_MFD_88PM860X is not set # CONFIG_MFD_SM501 is not set # CONFIG_MFD_SH_MOBILE_SDHI is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set # CONFIG_TPS65010 is not set # CONFIG_TWL4030_CORE is not set # CONFIG_MFD_TMIO is not set # CONFIG_PMIC_DA903X is not set # CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X is not set # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set # CONFIG_MFD_PCF50633 is not set # CONFIG_AB3100_CORE is not set -# CONFIG_MFD_88PM8607 is not set +# CONFIG_MFD_TIMBERDALE is not set +# CONFIG_LPC_SCH is not set # CONFIG_REGULATOR is not set # CONFIG_MEDIA_SUPPORT is not set @@ -1123,6 +1135,7 @@ CONFIG_SSB_POSSIBLE=y # Graphics support # CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 # CONFIG_DRM is not set # CONFIG_VGASTATE is not set # CONFIG_VIDEO_OUTPUT_CONTROL is not set @@ -1371,6 +1384,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set +# CONFIG_LOGFS is not set # CONFIG_CRAMFS is not set # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -1401,6 +1415,7 @@ CONFIG_SUNRPC_GSS=y CONFIG_RPCSEC_GSS_KRB5=y # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1475,6 +1490,7 @@ CONFIG_SCHED_DEBUG=y # CONFIG_TIMER_STATS is not set # CONFIG_DEBUG_OBJECTS is not set # CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_KMEMLEAK is not set # CONFIG_DEBUG_PREEMPT is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set @@ -1510,7 +1526,6 @@ CONFIG_FRAME_POINTER=y # CONFIG_LATENCYTOP is not set # CONFIG_SYSCTL_SYSCALL_CHECK is not set # CONFIG_PAGE_POISONING is not set -CONFIG_NOP_TRACER=y CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y @@ -1518,10 +1533,7 @@ CONFIG_HAVE_DYNAMIC_FTRACE=y CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y CONFIG_HAVE_SYSCALL_TRACEPOINTS=y CONFIG_RING_BUFFER=y -CONFIG_EVENT_TRACING=y -CONFIG_CONTEXT_SWITCH_TRACER=y CONFIG_RING_BUFFER_ALLOW_SWAP=y -CONFIG_TRACING=y CONFIG_TRACING_SUPPORT=y CONFIG_FTRACE=y # CONFIG_FUNCTION_TRACER is not set @@ -1534,6 +1546,7 @@ CONFIG_FTRACE=y CONFIG_BRANCH_PROFILE_NONE=y # CONFIG_PROFILE_ANNOTATED_BRANCHES is not set # CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_KSYM_TRACER is not set # CONFIG_STACK_TRACER is not set # CONFIG_KMEMTRACE is not set # CONFIG_WORKQUEUE_TRACER is not set @@ -1661,7 +1674,8 @@ CONFIG_CRYPTO_DES=y # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y # CONFIG_CRYPTO_DEV_HIFN_795X is not set -CONFIG_BINARY_PRINTF=y +# CONFIG_VIRTUALIZATION is not set +# CONFIG_BINARY_PRINTF is not set # # Library routines diff --git a/arch/sh/configs/rsk7201_defconfig b/arch/sh/configs/rsk7201_defconfig index 2fc635a..80e7b41 100644 --- a/arch/sh/configs/rsk7201_defconfig +++ b/arch/sh/configs/rsk7201_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 13:23:12 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 16:09:18 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -30,6 +30,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -44,9 +45,11 @@ CONFIG_LOCALVERSION="" CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y CONFIG_BSD_PROCESS_ACCT=y @@ -65,7 +68,6 @@ CONFIG_RCU_FANOUT=32 CONFIG_IKCONFIG=y # CONFIG_IKCONFIG_PROC is not set CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set # CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set @@ -79,6 +81,7 @@ CONFIG_INITRAMFS_SOURCE="" CONFIG_RD_GZIP=y # CONFIG_RD_BZIP2 is not set # CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_ANON_INODES=y @@ -105,7 +108,6 @@ CONFIG_PERF_USE_VMALLOC=y # Kernel Performance Events And Counters # CONFIG_PERF_EVENTS=y -CONFIG_EVENT_PROFILE=y # CONFIG_PERF_COUNTERS is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_COMPAT_BRK=y @@ -114,7 +116,6 @@ CONFIG_COMPAT_BRK=y CONFIG_SLOB=y # CONFIG_MMAP_ALLOW_UNINITIALIZED is not set CONFIG_PROFILING=y -CONFIG_TRACEPOINTS=y CONFIG_OPROFILE=y CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set @@ -124,6 +125,7 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -240,6 +242,7 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -255,7 +258,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 CONFIG_NOMMU_INITIAL_TRIM_EXCESS=1 # @@ -326,7 +329,6 @@ CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set CONFIG_GUSA=y -# CONFIG_SPARSE_IRQ is not set # # Boot options @@ -485,6 +487,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set # CONFIG_SCSI_DMA is not set @@ -545,6 +548,7 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=8 CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set # CONFIG_UNIX98_PTYS is not set # CONFIG_LEGACY_PTYS is not set # CONFIG_IPMI_HANDLER is not set @@ -657,7 +661,6 @@ CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XATTR is not set # CONFIG_EXT3_FS is not set # CONFIG_EXT4_FS is not set -CONFIG_EXT4_USE_FOR_EXT23=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set @@ -720,6 +723,7 @@ CONFIG_JFFS2_ZLIB=y # CONFIG_JFFS2_LZO is not set CONFIG_JFFS2_RTIME=y # CONFIG_JFFS2_RUBIN is not set +# CONFIG_LOGFS is not set # CONFIG_CRAMFS is not set # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -756,13 +760,12 @@ CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_FS=y # CONFIG_HEADERS_CHECK is not set # CONFIG_DEBUG_KERNEL is not set -CONFIG_STACKTRACE=y CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_MEMORY_INIT is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_LKDTM is not set # CONFIG_LATENCYTOP is not set CONFIG_SYSCTL_SYSCALL_CHECK=y -CONFIG_NOP_TRACER=y CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y @@ -770,10 +773,7 @@ CONFIG_HAVE_DYNAMIC_FTRACE=y CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y CONFIG_HAVE_SYSCALL_TRACEPOINTS=y CONFIG_RING_BUFFER=y -CONFIG_EVENT_TRACING=y -CONFIG_CONTEXT_SWITCH_TRACER=y CONFIG_RING_BUFFER_ALLOW_SWAP=y -CONFIG_TRACING=y CONFIG_TRACING_SUPPORT=y # CONFIG_FTRACE is not set # CONFIG_DYNAMIC_DEBUG is not set @@ -795,7 +795,8 @@ CONFIG_HAVE_ARCH_KGDB=y CONFIG_DEFAULT_SECURITY_DAC=y CONFIG_DEFAULT_SECURITY="" # CONFIG_CRYPTO is not set -CONFIG_BINARY_PRINTF=y +# CONFIG_VIRTUALIZATION is not set +# CONFIG_BINARY_PRINTF is not set # # Library routines diff --git a/arch/sh/configs/rsk7203_defconfig b/arch/sh/configs/rsk7203_defconfig index 0169e60..66eb7d7 100644 --- a/arch/sh/configs/rsk7203_defconfig +++ b/arch/sh/configs/rsk7203_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 13:23:54 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 16:11:37 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y CONFIG_GENERIC_GPIO=y CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -31,6 +31,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -45,9 +46,11 @@ CONFIG_LOCALVERSION="" CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y CONFIG_POSIX_MQUEUE=y @@ -70,7 +73,6 @@ CONFIG_RCU_FANOUT=32 CONFIG_IKCONFIG=y # CONFIG_IKCONFIG_PROC is not set CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set # CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set @@ -85,6 +87,7 @@ CONFIG_INITRAMFS_SOURCE="" CONFIG_RD_GZIP=y # CONFIG_RD_BZIP2 is not set # CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_ANON_INODES=y @@ -112,7 +115,6 @@ CONFIG_PERF_USE_VMALLOC=y # Kernel Performance Events And Counters # CONFIG_PERF_EVENTS=y -CONFIG_EVENT_PROFILE=y # CONFIG_PERF_COUNTERS is not set # CONFIG_DEBUG_PERF_USE_VMALLOC is not set CONFIG_VM_EVENT_COUNTERS=y @@ -122,7 +124,6 @@ CONFIG_COMPAT_BRK=y CONFIG_SLOB=y # CONFIG_MMAP_ALLOW_UNINITIALIZED is not set CONFIG_PROFILING=y -CONFIG_TRACEPOINTS=y CONFIG_OPROFILE=y CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set @@ -132,6 +133,7 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -248,6 +250,7 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -263,7 +266,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 CONFIG_NOMMU_INITIAL_TRIM_EXCESS=1 # @@ -350,7 +353,6 @@ CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set CONFIG_GUSA=y -# CONFIG_SPARSE_IRQ is not set # # Boot options @@ -448,7 +450,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # Network testing # # CONFIG_NET_PKTGEN is not set -# CONFIG_NET_DROP_MONITOR is not set # CONFIG_HAMRADIO is not set # CONFIG_CAN is not set # CONFIG_IRDA is not set @@ -592,6 +593,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set # CONFIG_SCSI_DMA is not set @@ -662,6 +664,7 @@ CONFIG_WLAN=y # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set # CONFIG_USB_USBNET is not set +# CONFIG_USB_IPHETH is not set # CONFIG_WAN is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -723,6 +726,7 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=4 CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set # CONFIG_UNIX98_PTYS is not set # CONFIG_LEGACY_PTYS is not set # CONFIG_IPMI_HANDLER is not set @@ -745,6 +749,7 @@ CONFIG_GPIOLIB=y # # Memory mapped GPIO expanders: # +# CONFIG_GPIO_IT8761E is not set # # I2C GPIO expanders: @@ -783,6 +788,7 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_TMIO is not set CONFIG_REGULATOR=y # CONFIG_REGULATOR_DEBUG is not set +# CONFIG_REGULATOR_DUMMY is not set # CONFIG_REGULATOR_FIXED_VOLTAGE is not set # CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set # CONFIG_REGULATOR_USERSPACE_CONSUMER is not set @@ -816,6 +822,7 @@ CONFIG_USB_HID=y # # Special HID drivers # +# CONFIG_HID_3M_PCT is not set CONFIG_HID_A4TECH=y CONFIG_HID_APPLE=y CONFIG_HID_BELKIN=y @@ -831,14 +838,19 @@ CONFIG_HID_GYRATION=y CONFIG_HID_LOGITECH=y # CONFIG_LOGITECH_FF is not set # CONFIG_LOGIRUMBLEPAD2_FF is not set +# CONFIG_LOGIG940_FF is not set CONFIG_HID_MICROSOFT=y +# CONFIG_HID_MOSART is not set CONFIG_HID_MONTEREY=y # CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set CONFIG_HID_PANTHERLORD=y # CONFIG_PANTHERLORD_FF is not set CONFIG_HID_PETALYNX=y +# CONFIG_HID_QUANTA is not set CONFIG_HID_SAMSUNG=y CONFIG_HID_SONY=y +# CONFIG_HID_STANTUM is not set CONFIG_HID_SUNPLUS=y # CONFIG_HID_GREENASIA is not set # CONFIG_HID_SMARTJOYPLUS is not set @@ -859,7 +871,6 @@ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y CONFIG_USB_DEVICEFS=y CONFIG_USB_DEVICE_CLASS=y # CONFIG_USB_DYNAMIC_MINORS is not set -# CONFIG_USB_SUSPEND is not set # CONFIG_USB_OTG is not set # CONFIG_USB_OTG_WHITELIST is not set # CONFIG_USB_OTG_BLACKLIST_HUB is not set @@ -916,7 +927,6 @@ CONFIG_USB_R8A66597_HCD=y # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set -# CONFIG_USB_BERRY_CHARGE is not set # CONFIG_USB_LED is not set # CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set @@ -928,7 +938,6 @@ CONFIG_USB_R8A66597_HCD=y # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set # CONFIG_USB_ISIGHTFW is not set -# CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set # @@ -948,11 +957,11 @@ CONFIG_LEDS_GPIO=y CONFIG_LEDS_GPIO_PLATFORM=y # CONFIG_LEDS_REGULATOR is not set # CONFIG_LEDS_LT3593 is not set +CONFIG_LEDS_TRIGGERS=y # # LED Triggers # -CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=y CONFIG_LEDS_TRIGGER_HEARTBEAT=y CONFIG_LEDS_TRIGGER_BACKLIGHT=y @@ -1018,7 +1027,6 @@ CONFIG_RTC_DRV_SH=y # CONFIG_EXT2_FS is not set # CONFIG_EXT3_FS is not set # CONFIG_EXT4_FS is not set -CONFIG_EXT4_USE_FOR_EXT23=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set @@ -1072,6 +1080,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set # CONFIG_JFFS2_FS is not set +# CONFIG_LOGFS is not set # CONFIG_CRAMFS is not set # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -1098,6 +1107,7 @@ CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1180,6 +1190,7 @@ CONFIG_DEBUG_OBJECTS=y # CONFIG_DEBUG_OBJECTS_TIMERS is not set # CONFIG_DEBUG_OBJECTS_WORK is not set CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1 +# CONFIG_DEBUG_KMEMLEAK is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set @@ -1189,7 +1200,6 @@ CONFIG_DEBUG_MUTEXES=y # CONFIG_LOCK_STAT is not set CONFIG_DEBUG_SPINLOCK_SLEEP=y # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set -CONFIG_STACKTRACE=y # CONFIG_DEBUG_KOBJECT is not set CONFIG_DEBUG_BUGVERBOSE=y CONFIG_DEBUG_INFO=y @@ -1207,11 +1217,11 @@ CONFIG_FRAME_POINTER=y # CONFIG_BACKTRACE_SELF_TEST is not set # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_LKDTM is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set CONFIG_SYSCTL_SYSCALL_CHECK=y # CONFIG_PAGE_POISONING is not set -CONFIG_NOP_TRACER=y CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y @@ -1219,10 +1229,7 @@ CONFIG_HAVE_DYNAMIC_FTRACE=y CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y CONFIG_HAVE_SYSCALL_TRACEPOINTS=y CONFIG_RING_BUFFER=y -CONFIG_EVENT_TRACING=y -CONFIG_CONTEXT_SWITCH_TRACER=y CONFIG_RING_BUFFER_ALLOW_SWAP=y -CONFIG_TRACING=y CONFIG_TRACING_SUPPORT=y CONFIG_FTRACE=y # CONFIG_FUNCTION_TRACER is not set @@ -1234,6 +1241,7 @@ CONFIG_FTRACE=y CONFIG_BRANCH_PROFILE_NONE=y # CONFIG_PROFILE_ANNOTATED_BRANCHES is not set # CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_KSYM_TRACER is not set # CONFIG_STACK_TRACER is not set # CONFIG_KMEMTRACE is not set # CONFIG_WORKQUEUE_TRACER is not set @@ -1263,7 +1271,8 @@ CONFIG_DUMP_CODE=y CONFIG_DEFAULT_SECURITY_DAC=y CONFIG_DEFAULT_SECURITY="" # CONFIG_CRYPTO is not set -CONFIG_BINARY_PRINTF=y +# CONFIG_VIRTUALIZATION is not set +# CONFIG_BINARY_PRINTF is not set # # Library routines diff --git a/arch/sh/configs/rts7751r2d1_defconfig b/arch/sh/configs/rts7751r2d1_defconfig index dba024d..6bd3d95 100644 --- a/arch/sh/configs/rts7751r2d1_defconfig +++ b/arch/sh/configs/rts7751r2d1_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 13:25:36 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 16:15:07 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -33,6 +33,7 @@ CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_IO_TRAPPED=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -47,9 +48,11 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -70,7 +73,6 @@ CONFIG_RCU_FANOUT=32 # CONFIG_TREE_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -104,7 +106,6 @@ CONFIG_PERF_USE_VMALLOC=y # Kernel Performance Events And Counters # CONFIG_PERF_EVENTS=y -CONFIG_EVENT_PROFILE=y # CONFIG_PERF_COUNTERS is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_PCI_QUIRKS=y @@ -113,7 +114,6 @@ CONFIG_SLAB=y # CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_PROFILING=y -CONFIG_TRACEPOINTS=y CONFIG_OPROFILE=y CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set @@ -124,6 +124,7 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -242,6 +243,7 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -257,7 +259,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -343,7 +345,6 @@ CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT is not set CONFIG_GUSA=y # CONFIG_GUSA_RB is not set -# CONFIG_SPARSE_IRQ is not set # # Boot options @@ -359,9 +360,9 @@ CONFIG_CMDLINE="console=tty0 console=ttySC1,115200 root=/dev/sda1" # Bus options # CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y # CONFIG_PCIEPORTBUS is not set # CONFIG_ARCH_SUPPORTS_MSI is not set -CONFIG_PCI_LEGACY=y # CONFIG_PCI_STUB is not set # CONFIG_PCI_IOV is not set # CONFIG_PCCARD is not set @@ -389,7 +390,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -449,7 +449,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # Network testing # # CONFIG_NET_PKTGEN is not set -# CONFIG_NET_DROP_MONITOR is not set # CONFIG_HAMRADIO is not set # CONFIG_CAN is not set # CONFIG_IRDA is not set @@ -525,6 +524,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y @@ -642,6 +642,7 @@ CONFIG_ATA_SFF=y # CONFIG_PATA_IT821X is not set # CONFIG_PATA_IT8213 is not set # CONFIG_PATA_JMICRON is not set +# CONFIG_PATA_LEGACY is not set # CONFIG_PATA_TRIFLEX is not set # CONFIG_PATA_MARVELL is not set # CONFIG_PATA_MPIIX is not set @@ -678,7 +679,7 @@ CONFIG_PATA_PLATFORM=y # # -# See the help texts for more information. +# The newer stack is recommended. # # CONFIG_FIREWIRE is not set # CONFIG_IEEE1394 is not set @@ -719,6 +720,7 @@ CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set # CONFIG_AMD8111_ETH is not set # CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_KSZ884X_PCI is not set # CONFIG_B44 is not set # CONFIG_FORCEDETH is not set # CONFIG_E100 is not set @@ -771,6 +773,8 @@ CONFIG_NETDEV_10000=y # CONFIG_CHELSIO_T1 is not set CONFIG_CHELSIO_T3_DEPENDS=y # CONFIG_CHELSIO_T3 is not set +CONFIG_CHELSIO_T4_DEPENDS=y +# CONFIG_CHELSIO_T4 is not set # CONFIG_ENIC is not set # CONFIG_IXGBE is not set # CONFIG_IXGB is not set @@ -783,6 +787,7 @@ CONFIG_CHELSIO_T3_DEPENDS=y # CONFIG_MLX4_CORE is not set # CONFIG_TEHUTI is not set # CONFIG_BNX2X is not set +# CONFIG_QLCNIC is not set # CONFIG_QLGE is not set # CONFIG_SFC is not set # CONFIG_BE2NET is not set @@ -805,6 +810,7 @@ CONFIG_WLAN=y # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set # CONFIG_USB_USBNET is not set +# CONFIG_USB_IPHETH is not set # CONFIG_WAN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set @@ -882,6 +888,7 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y @@ -964,6 +971,7 @@ CONFIG_MFD_SM501=y # CONFIG_MFD_MC13783 is not set # CONFIG_EZX_PCAP is not set # CONFIG_AB4500_CORE is not set +# CONFIG_LPC_SCH is not set # CONFIG_REGULATOR is not set # CONFIG_MEDIA_SUPPORT is not set @@ -971,6 +979,7 @@ CONFIG_MFD_SM501=y # Graphics support # CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 # CONFIG_DRM is not set # CONFIG_VGASTATE is not set CONFIG_VIDEO_OUTPUT_CONTROL=m @@ -1152,6 +1161,7 @@ CONFIG_SND_SPI=y CONFIG_SND_SUPERH=y CONFIG_SND_USB=y # CONFIG_SND_USB_AUDIO is not set +# CONFIG_SND_USB_UA101 is not set # CONFIG_SND_USB_CAIAQ is not set # CONFIG_SND_SOC is not set CONFIG_SOUND_PRIME=m @@ -1170,6 +1180,7 @@ CONFIG_USB_HID=y # # Special HID drivers # +# CONFIG_HID_3M_PCT is not set CONFIG_HID_A4TECH=y CONFIG_HID_APPLE=y CONFIG_HID_BELKIN=y @@ -1185,14 +1196,19 @@ CONFIG_HID_GYRATION=y CONFIG_HID_LOGITECH=y # CONFIG_LOGITECH_FF is not set # CONFIG_LOGIRUMBLEPAD2_FF is not set +# CONFIG_LOGIG940_FF is not set CONFIG_HID_MICROSOFT=y +# CONFIG_HID_MOSART is not set CONFIG_HID_MONTEREY=y # CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set CONFIG_HID_PANTHERLORD=y # CONFIG_PANTHERLORD_FF is not set CONFIG_HID_PETALYNX=y +# CONFIG_HID_QUANTA is not set CONFIG_HID_SAMSUNG=y CONFIG_HID_SONY=y +# CONFIG_HID_STANTUM is not set CONFIG_HID_SUNPLUS=y # CONFIG_HID_GREENASIA is not set # CONFIG_HID_SMARTJOYPLUS is not set @@ -1291,7 +1307,6 @@ CONFIG_USB_LIBUSUAL=y # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set -# CONFIG_USB_BERRY_CHARGE is not set # CONFIG_USB_LED is not set # CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set @@ -1303,7 +1318,6 @@ CONFIG_USB_LIBUSUAL=y # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set # CONFIG_USB_ISIGHTFW is not set -# CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set # @@ -1381,7 +1395,6 @@ CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XIP is not set # CONFIG_EXT3_FS is not set # CONFIG_EXT4_FS is not set -CONFIG_EXT4_USE_FOR_EXT23=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set @@ -1442,6 +1455,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set +# CONFIG_LOGFS is not set # CONFIG_CRAMFS is not set # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -1456,6 +1470,7 @@ CONFIG_NETWORK_FILESYSTEMS=y # CONFIG_NFS_FS is not set # CONFIG_NFSD is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1522,13 +1537,12 @@ CONFIG_FRAME_WARN=1024 CONFIG_DEBUG_FS=y # CONFIG_HEADERS_CHECK is not set # CONFIG_DEBUG_KERNEL is not set -CONFIG_STACKTRACE=y CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_MEMORY_INIT is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_LKDTM is not set # CONFIG_LATENCYTOP is not set # CONFIG_SYSCTL_SYSCALL_CHECK is not set -CONFIG_NOP_TRACER=y CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y @@ -1536,10 +1550,7 @@ CONFIG_HAVE_DYNAMIC_FTRACE=y CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y CONFIG_HAVE_SYSCALL_TRACEPOINTS=y CONFIG_RING_BUFFER=y -CONFIG_EVENT_TRACING=y -CONFIG_CONTEXT_SWITCH_TRACER=y CONFIG_RING_BUFFER_ALLOW_SWAP=y -CONFIG_TRACING=y CONFIG_TRACING_SUPPORT=y # CONFIG_FTRACE is not set # CONFIG_DYNAMIC_DEBUG is not set @@ -1648,7 +1659,8 @@ CONFIG_CRYPTO=y # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y # CONFIG_CRYPTO_DEV_HIFN_795X is not set -CONFIG_BINARY_PRINTF=y +# CONFIG_VIRTUALIZATION is not set +# CONFIG_BINARY_PRINTF is not set # # Library routines diff --git a/arch/sh/configs/rts7751r2dplus_defconfig b/arch/sh/configs/rts7751r2dplus_defconfig index 6d511d0..487abcc 100644 --- a/arch/sh/configs/rts7751r2dplus_defconfig +++ b/arch/sh/configs/rts7751r2dplus_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 13:26:39 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 16:20:00 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -33,6 +33,7 @@ CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_IO_TRAPPED=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -47,9 +48,11 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -70,7 +73,6 @@ CONFIG_RCU_FANOUT=32 # CONFIG_TREE_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -104,7 +106,6 @@ CONFIG_PERF_USE_VMALLOC=y # Kernel Performance Events And Counters # CONFIG_PERF_EVENTS=y -CONFIG_EVENT_PROFILE=y # CONFIG_PERF_COUNTERS is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_PCI_QUIRKS=y @@ -113,7 +114,6 @@ CONFIG_SLAB=y # CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_PROFILING=y -CONFIG_TRACEPOINTS=y CONFIG_OPROFILE=y CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set @@ -124,6 +124,7 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -242,6 +243,7 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -257,7 +259,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -343,7 +345,6 @@ CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT is not set CONFIG_GUSA=y # CONFIG_GUSA_RB is not set -# CONFIG_SPARSE_IRQ is not set # # Boot options @@ -359,9 +360,9 @@ CONFIG_CMDLINE="console=tty0 console=ttySC1,115200 root=/dev/sda1" # Bus options # CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y # CONFIG_PCIEPORTBUS is not set # CONFIG_ARCH_SUPPORTS_MSI is not set -CONFIG_PCI_LEGACY=y # CONFIG_PCI_STUB is not set # CONFIG_PCI_IOV is not set # CONFIG_PCCARD is not set @@ -389,7 +390,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -449,7 +449,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # Network testing # # CONFIG_NET_PKTGEN is not set -# CONFIG_NET_DROP_MONITOR is not set # CONFIG_HAMRADIO is not set # CONFIG_CAN is not set # CONFIG_IRDA is not set @@ -611,6 +610,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y @@ -728,6 +728,7 @@ CONFIG_ATA_SFF=y # CONFIG_PATA_IT821X is not set # CONFIG_PATA_IT8213 is not set # CONFIG_PATA_JMICRON is not set +# CONFIG_PATA_LEGACY is not set # CONFIG_PATA_TRIFLEX is not set # CONFIG_PATA_MARVELL is not set # CONFIG_PATA_MPIIX is not set @@ -764,7 +765,7 @@ CONFIG_PATA_PLATFORM=y # # -# See the help texts for more information. +# The newer stack is recommended. # # CONFIG_FIREWIRE is not set # CONFIG_IEEE1394 is not set @@ -805,6 +806,7 @@ CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set # CONFIG_AMD8111_ETH is not set # CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_KSZ884X_PCI is not set # CONFIG_B44 is not set # CONFIG_FORCEDETH is not set # CONFIG_E100 is not set @@ -857,6 +859,8 @@ CONFIG_NETDEV_10000=y # CONFIG_CHELSIO_T1 is not set CONFIG_CHELSIO_T3_DEPENDS=y # CONFIG_CHELSIO_T3 is not set +CONFIG_CHELSIO_T4_DEPENDS=y +# CONFIG_CHELSIO_T4 is not set # CONFIG_ENIC is not set # CONFIG_IXGBE is not set # CONFIG_IXGB is not set @@ -869,6 +873,7 @@ CONFIG_CHELSIO_T3_DEPENDS=y # CONFIG_MLX4_CORE is not set # CONFIG_TEHUTI is not set # CONFIG_BNX2X is not set +# CONFIG_QLCNIC is not set # CONFIG_QLGE is not set # CONFIG_SFC is not set # CONFIG_BE2NET is not set @@ -891,6 +896,7 @@ CONFIG_WLAN=y # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set # CONFIG_USB_USBNET is not set +# CONFIG_USB_IPHETH is not set # CONFIG_WAN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set @@ -968,6 +974,7 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y @@ -1050,6 +1057,7 @@ CONFIG_MFD_SM501=y # CONFIG_MFD_MC13783 is not set # CONFIG_EZX_PCAP is not set # CONFIG_AB4500_CORE is not set +# CONFIG_LPC_SCH is not set # CONFIG_REGULATOR is not set # CONFIG_MEDIA_SUPPORT is not set @@ -1057,6 +1065,7 @@ CONFIG_MFD_SM501=y # Graphics support # CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 # CONFIG_DRM is not set # CONFIG_VGASTATE is not set CONFIG_VIDEO_OUTPUT_CONTROL=m @@ -1238,6 +1247,7 @@ CONFIG_SND_SPI=y CONFIG_SND_SUPERH=y CONFIG_SND_USB=y # CONFIG_SND_USB_AUDIO is not set +# CONFIG_SND_USB_UA101 is not set # CONFIG_SND_USB_CAIAQ is not set # CONFIG_SND_SOC is not set CONFIG_SOUND_PRIME=m @@ -1256,6 +1266,7 @@ CONFIG_USB_HID=y # # Special HID drivers # +# CONFIG_HID_3M_PCT is not set CONFIG_HID_A4TECH=y CONFIG_HID_APPLE=y CONFIG_HID_BELKIN=y @@ -1271,14 +1282,19 @@ CONFIG_HID_GYRATION=y CONFIG_HID_LOGITECH=y # CONFIG_LOGITECH_FF is not set # CONFIG_LOGIRUMBLEPAD2_FF is not set +# CONFIG_LOGIG940_FF is not set CONFIG_HID_MICROSOFT=y +# CONFIG_HID_MOSART is not set CONFIG_HID_MONTEREY=y # CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set CONFIG_HID_PANTHERLORD=y # CONFIG_PANTHERLORD_FF is not set CONFIG_HID_PETALYNX=y +# CONFIG_HID_QUANTA is not set CONFIG_HID_SAMSUNG=y CONFIG_HID_SONY=y +# CONFIG_HID_STANTUM is not set CONFIG_HID_SUNPLUS=y # CONFIG_HID_GREENASIA is not set # CONFIG_HID_SMARTJOYPLUS is not set @@ -1377,7 +1393,6 @@ CONFIG_USB_LIBUSUAL=y # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set -# CONFIG_USB_BERRY_CHARGE is not set # CONFIG_USB_LED is not set # CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set @@ -1389,7 +1404,6 @@ CONFIG_USB_LIBUSUAL=y # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set # CONFIG_USB_ISIGHTFW is not set -# CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set # @@ -1467,7 +1481,6 @@ CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XIP is not set # CONFIG_EXT3_FS is not set # CONFIG_EXT4_FS is not set -CONFIG_EXT4_USE_FOR_EXT23=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set @@ -1529,6 +1542,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set # CONFIG_JFFS2_FS is not set +# CONFIG_LOGFS is not set # CONFIG_CRAMFS is not set # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -1543,6 +1557,7 @@ CONFIG_NETWORK_FILESYSTEMS=y # CONFIG_NFS_FS is not set # CONFIG_NFSD is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1609,13 +1624,12 @@ CONFIG_FRAME_WARN=1024 CONFIG_DEBUG_FS=y # CONFIG_HEADERS_CHECK is not set # CONFIG_DEBUG_KERNEL is not set -CONFIG_STACKTRACE=y CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_MEMORY_INIT is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_LKDTM is not set # CONFIG_LATENCYTOP is not set # CONFIG_SYSCTL_SYSCALL_CHECK is not set -CONFIG_NOP_TRACER=y CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y @@ -1623,10 +1637,7 @@ CONFIG_HAVE_DYNAMIC_FTRACE=y CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y CONFIG_HAVE_SYSCALL_TRACEPOINTS=y CONFIG_RING_BUFFER=y -CONFIG_EVENT_TRACING=y -CONFIG_CONTEXT_SWITCH_TRACER=y CONFIG_RING_BUFFER_ALLOW_SWAP=y -CONFIG_TRACING=y CONFIG_TRACING_SUPPORT=y # CONFIG_FTRACE is not set # CONFIG_DYNAMIC_DEBUG is not set @@ -1735,7 +1746,8 @@ CONFIG_CRYPTO=y # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y # CONFIG_CRYPTO_DEV_HIFN_795X is not set -CONFIG_BINARY_PRINTF=y +# CONFIG_VIRTUALIZATION is not set +# CONFIG_BINARY_PRINTF is not set # # Library routines diff --git a/arch/sh/configs/sdk7780_defconfig b/arch/sh/configs/sdk7780_defconfig index 1859ba0..fe92314 100644 --- a/arch/sh/configs/sdk7780_defconfig +++ b/arch/sh/configs/sdk7780_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 13:27:20 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 16:21:00 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -32,6 +32,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -47,9 +48,11 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -73,7 +76,6 @@ CONFIG_RCU_FANOUT=32 CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=18 -# CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -107,8 +109,9 @@ CONFIG_PERF_USE_VMALLOC=y # # Kernel Performance Events And Counters # -# CONFIG_PERF_EVENTS is not set +CONFIG_PERF_EVENTS=y # CONFIG_PERF_COUNTERS is not set +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_PCI_QUIRKS=y CONFIG_SLUB_DEBUG=y @@ -126,6 +129,7 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -237,11 +241,8 @@ CONFIG_PAGE_OFFSET=0x80000000 CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_MEMORY_START=0x08000000 CONFIG_MEMORY_SIZE=0x08000000 -# CONFIG_29BIT is not set -CONFIG_32BIT=y -CONFIG_PMB_ENABLE=y +CONFIG_29BIT=y # CONFIG_PMB is not set -CONFIG_PMB_FIXED=y CONFIG_VSYSCALL=y CONFIG_ARCH_FLATMEM_ENABLE=y CONFIG_ARCH_SPARSEMEM_ENABLE=y @@ -249,6 +250,7 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -270,7 +272,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -353,7 +355,7 @@ CONFIG_SCHED_HRTICK=y # CONFIG_PREEMPT_VOLUNTARY is not set CONFIG_PREEMPT=y CONFIG_GUSA=y -# CONFIG_SPARSE_IRQ is not set +# CONFIG_INTC_USERIMASK is not set # # Boot options @@ -369,16 +371,15 @@ CONFIG_CMDLINE="mem=128M console=tty0 console=ttySC0,115200 ip=bootp root=/dev/n # Bus options # CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y # CONFIG_PCIEPORTBUS is not set # CONFIG_ARCH_SUPPORTS_MSI is not set -# CONFIG_PCI_LEGACY is not set CONFIG_PCI_DEBUG=y # CONFIG_PCI_STUB is not set # CONFIG_PCI_IOV is not set CONFIG_PCCARD=y CONFIG_PCMCIA=y CONFIG_PCMCIA_LOAD_CIS=y -CONFIG_PCMCIA_IOCTL=y CONFIG_CARDBUS=y # @@ -417,7 +418,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -659,6 +659,7 @@ CONFIG_BLK_DEV_GENERIC=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y @@ -777,6 +778,7 @@ CONFIG_ATA_SFF=y # CONFIG_PATA_IT821X is not set # CONFIG_PATA_IT8213 is not set # CONFIG_PATA_JMICRON is not set +# CONFIG_PATA_LEGACY is not set # CONFIG_PATA_TRIFLEX is not set # CONFIG_PATA_MARVELL is not set # CONFIG_PATA_MPIIX is not set @@ -824,7 +826,7 @@ CONFIG_BLK_DEV_DM=y # # -# See the help texts for more information. +# The newer stack is recommended. # # CONFIG_FIREWIRE is not set # CONFIG_IEEE1394 is not set @@ -890,6 +892,7 @@ CONFIG_WLAN=y # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set # CONFIG_USB_USBNET is not set +# CONFIG_USB_IPHETH is not set # CONFIG_NET_PCMCIA is not set # CONFIG_WAN is not set # CONFIG_FDDI is not set @@ -995,6 +998,7 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y @@ -1057,6 +1061,7 @@ CONFIG_SSB_DRIVER_PCICORE=y # CONFIG_MFD_SH_MOBILE_SDHI is not set # CONFIG_HTC_PASIC3 is not set # CONFIG_MFD_TMIO is not set +# CONFIG_LPC_SCH is not set # CONFIG_REGULATOR is not set # CONFIG_MEDIA_SUPPORT is not set @@ -1064,6 +1069,7 @@ CONFIG_SSB_DRIVER_PCICORE=y # Graphics support # CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 # CONFIG_DRM is not set # CONFIG_VGASTATE is not set # CONFIG_VIDEO_OUTPUT_CONTROL is not set @@ -1167,6 +1173,7 @@ CONFIG_USB_HID=y # # Special HID drivers # +# CONFIG_HID_3M_PCT is not set CONFIG_HID_A4TECH=y CONFIG_HID_APPLE=y CONFIG_HID_BELKIN=y @@ -1182,14 +1189,19 @@ CONFIG_HID_GYRATION=y CONFIG_HID_LOGITECH=y # CONFIG_LOGITECH_FF is not set # CONFIG_LOGIRUMBLEPAD2_FF is not set +# CONFIG_LOGIG940_FF is not set CONFIG_HID_MICROSOFT=y +# CONFIG_HID_MOSART is not set CONFIG_HID_MONTEREY=y # CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set CONFIG_HID_PANTHERLORD=y # CONFIG_PANTHERLORD_FF is not set CONFIG_HID_PETALYNX=y +# CONFIG_HID_QUANTA is not set CONFIG_HID_SAMSUNG=y CONFIG_HID_SONY=y +# CONFIG_HID_STANTUM is not set CONFIG_HID_SUNPLUS=y # CONFIG_HID_GREENASIA is not set # CONFIG_HID_SMARTJOYPLUS is not set @@ -1288,7 +1300,6 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set -# CONFIG_USB_BERRY_CHARGE is not set # CONFIG_USB_LED is not set # CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set @@ -1301,7 +1312,6 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set # CONFIG_USB_ISIGHTFW is not set -# CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set # @@ -1317,10 +1327,6 @@ CONFIG_LEDS_CLASS=y # # LED drivers # - -# -# LED Triggers -# # CONFIG_LEDS_TRIGGERS is not set # CONFIG_ACCESSIBILITY is not set # CONFIG_INFINIBAND is not set @@ -1416,6 +1422,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set +# CONFIG_LOGFS is not set # CONFIG_CRAMFS is not set # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -1444,6 +1451,7 @@ CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1523,6 +1531,7 @@ CONFIG_TIMER_STATS=y # CONFIG_DEBUG_OBJECTS is not set # CONFIG_SLUB_DEBUG_ON is not set # CONFIG_SLUB_STATS is not set +# CONFIG_DEBUG_KMEMLEAK is not set CONFIG_DEBUG_PREEMPT=y # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set @@ -1571,6 +1580,7 @@ CONFIG_FTRACE=y CONFIG_BRANCH_PROFILE_NONE=y # CONFIG_PROFILE_ANNOTATED_BRANCHES is not set # CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_KSYM_TRACER is not set # CONFIG_STACK_TRACER is not set # CONFIG_KMEMTRACE is not set # CONFIG_WORKQUEUE_TRACER is not set @@ -1690,6 +1700,7 @@ CONFIG_CRYPTO_DES=y # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y # CONFIG_CRYPTO_DEV_HIFN_795X is not set +# CONFIG_VIRTUALIZATION is not set # CONFIG_BINARY_PRINTF is not set # diff --git a/arch/sh/configs/sdk7786_defconfig b/arch/sh/configs/sdk7786_defconfig index 740ada6..2698245 100644 --- a/arch/sh/configs/sdk7786_defconfig +++ b/arch/sh/configs/sdk7786_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit # Linux kernel version: 2.6.34-rc5 -# Mon Apr 26 16:52:58 2010 +# Tue May 18 18:03:37 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -29,6 +29,7 @@ CONFIG_SYS_SUPPORTS_PCI=y CONFIG_SYS_SUPPORTS_TMU=y CONFIG_STACKTRACE_SUPPORT=y CONFIG_LOCKDEP_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set # CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_ARCH_NO_VIRT_TO_BUS=y @@ -277,7 +278,7 @@ CONFIG_QUICKLIST=y CONFIG_MMU=y CONFIG_PAGE_OFFSET=0x80000000 CONFIG_FORCE_MAX_ZONEORDER=11 -CONFIG_MEMORY_START=0x60000000 +CONFIG_MEMORY_START=0x40000000 CONFIG_MEMORY_SIZE=0x20000000 # CONFIG_29BIT is not set CONFIG_32BIT=y @@ -410,10 +411,10 @@ CONFIG_HZ_1000=y CONFIG_HZ=1000 CONFIG_SCHED_HRTICK=y CONFIG_KEXEC=y -# CONFIG_CRASH_DUMP is not set CONFIG_SECCOMP=y CONFIG_SMP=y CONFIG_NR_CPUS=2 +CONFIG_HOTPLUG_CPU=y # CONFIG_PREEMPT_NONE is not set # CONFIG_PREEMPT_VOLUNTARY is not set CONFIG_PREEMPT=y @@ -1101,7 +1102,6 @@ CONFIG_I2C_HELPER_AUTO=y # # CONFIG_I2C_DESIGNWARE is not set # CONFIG_I2C_OCORES is not set -CONFIG_I2C_SDK7786=y # CONFIG_I2C_SH_MOBILE is not set # CONFIG_I2C_SIMTEC is not set # CONFIG_I2C_XILINX is not set @@ -1775,8 +1775,8 @@ CONFIG_DETECT_HUNG_TASK=y # CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 CONFIG_SCHED_DEBUG=y -# CONFIG_SCHEDSTATS is not set -# CONFIG_TIMER_STATS is not set +CONFIG_SCHEDSTATS=y +CONFIG_TIMER_STATS=y # CONFIG_DEBUG_OBJECTS is not set # CONFIG_DEBUG_SLAB is not set CONFIG_DEBUG_PREEMPT=y @@ -1810,6 +1810,7 @@ CONFIG_RCU_CPU_STALL_DETECTOR=y # CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set # CONFIG_LKDTM is not set # CONFIG_FAULT_INJECTION is not set +CONFIG_LATENCYTOP=y CONFIG_SYSCTL_SYSCALL_CHECK=y # CONFIG_PAGE_POISONING is not set CONFIG_NOP_TRACER=y @@ -1974,6 +1975,7 @@ CONFIG_CRYPTO_LZO=m # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y # CONFIG_CRYPTO_DEV_HIFN_795X is not set +# CONFIG_VIRTUALIZATION is not set CONFIG_BINARY_PRINTF=y # diff --git a/arch/sh/configs/se7206_defconfig b/arch/sh/configs/se7206_defconfig index 43e6780..910eaec 100644 --- a/arch/sh/configs/se7206_defconfig +++ b/arch/sh/configs/se7206_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 13:30:00 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 16:34:06 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -31,6 +31,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -46,9 +47,11 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y CONFIG_POSIX_MQUEUE=y @@ -72,7 +75,6 @@ CONFIG_RCU_FANOUT=32 CONFIG_TREE_RCU_TRACE=y # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_GROUP_SCHED is not set CONFIG_CGROUPS=y CONFIG_CGROUP_DEBUG=y CONFIG_CGROUP_NS=y @@ -82,6 +84,7 @@ CONFIG_CGROUP_DEVICE=y CONFIG_CGROUP_CPUACCT=y CONFIG_RESOURCE_COUNTERS=y CONFIG_CGROUP_MEM_RES_CTLR=y +# CONFIG_CGROUP_SCHED is not set CONFIG_MM_OWNER=y # CONFIG_SYSFS_DEPRECATED_V2 is not set CONFIG_RELAY=y @@ -96,6 +99,7 @@ CONFIG_INITRAMFS_SOURCE="" CONFIG_RD_GZIP=y # CONFIG_RD_BZIP2 is not set # CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_ANON_INODES=y @@ -123,7 +127,6 @@ CONFIG_PERF_USE_VMALLOC=y # Kernel Performance Events And Counters # CONFIG_PERF_EVENTS=y -CONFIG_EVENT_PROFILE=y # CONFIG_PERF_COUNTERS is not set # CONFIG_DEBUG_PERF_USE_VMALLOC is not set CONFIG_VM_EVENT_COUNTERS=y @@ -133,7 +136,6 @@ CONFIG_VM_EVENT_COUNTERS=y CONFIG_SLOB=y # CONFIG_MMAP_ALLOW_UNINITIALIZED is not set CONFIG_PROFILING=y -CONFIG_TRACEPOINTS=y CONFIG_OPROFILE=y CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set @@ -143,6 +145,7 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -162,7 +165,6 @@ CONFIG_BLOCK=y CONFIG_LBDAF=y # CONFIG_BLK_DEV_BSG is not set # CONFIG_BLK_DEV_INTEGRITY is not set -# CONFIG_BLK_CGROUP is not set # # IO Schedulers @@ -261,6 +263,7 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -276,7 +279,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 CONFIG_NOMMU_INITIAL_TRIM_EXCESS=1 # @@ -361,7 +364,6 @@ CONFIG_HZ=1000 # CONFIG_PREEMPT_VOLUNTARY is not set CONFIG_PREEMPT=y CONFIG_GUSA=y -# CONFIG_SPARSE_IRQ is not set # # Boot options @@ -400,7 +402,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -463,7 +464,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # Network testing # # CONFIG_NET_PKTGEN is not set -# CONFIG_NET_DROP_MONITOR is not set # CONFIG_HAMRADIO is not set # CONFIG_CAN is not set # CONFIG_IRDA is not set @@ -607,6 +607,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set # CONFIG_SCSI_DMA is not set @@ -688,6 +689,7 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=4 CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set # CONFIG_UNIX98_PTYS is not set # CONFIG_LEGACY_PTYS is not set # CONFIG_IPMI_HANDLER is not set @@ -799,7 +801,6 @@ CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XATTR is not set # CONFIG_EXT3_FS is not set # CONFIG_EXT4_FS is not set -CONFIG_EXT4_USE_FOR_EXT23=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set @@ -853,6 +854,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set # CONFIG_JFFS2_FS is not set +# CONFIG_LOGFS is not set CONFIG_CRAMFS=y # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -881,6 +883,7 @@ CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -919,6 +922,7 @@ CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set # CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_KMEMLEAK is not set CONFIG_DEBUG_PREEMPT=y # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set @@ -929,7 +933,6 @@ CONFIG_DEBUG_PREEMPT=y # CONFIG_LOCK_STAT is not set CONFIG_DEBUG_SPINLOCK_SLEEP=y # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set -CONFIG_STACKTRACE=y # CONFIG_DEBUG_KOBJECT is not set CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_INFO is not set @@ -947,11 +950,11 @@ CONFIG_FRAME_POINTER=y # CONFIG_BACKTRACE_SELF_TEST is not set # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_LKDTM is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set # CONFIG_SYSCTL_SYSCALL_CHECK is not set # CONFIG_PAGE_POISONING is not set -CONFIG_NOP_TRACER=y CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y @@ -959,10 +962,7 @@ CONFIG_HAVE_DYNAMIC_FTRACE=y CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y CONFIG_HAVE_SYSCALL_TRACEPOINTS=y CONFIG_RING_BUFFER=y -CONFIG_EVENT_TRACING=y -CONFIG_CONTEXT_SWITCH_TRACER=y CONFIG_RING_BUFFER_ALLOW_SWAP=y -CONFIG_TRACING=y CONFIG_TRACING_SUPPORT=y CONFIG_FTRACE=y # CONFIG_FUNCTION_TRACER is not set @@ -975,6 +975,7 @@ CONFIG_FTRACE=y CONFIG_BRANCH_PROFILE_NONE=y # CONFIG_PROFILE_ANNOTATED_BRANCHES is not set # CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_KSYM_TRACER is not set # CONFIG_STACK_TRACER is not set # CONFIG_KMEMTRACE is not set # CONFIG_WORKQUEUE_TRACER is not set @@ -1094,7 +1095,8 @@ CONFIG_CRYPTO_LZO=y # # CONFIG_CRYPTO_ANSI_CPRNG is not set # CONFIG_CRYPTO_HW is not set -CONFIG_BINARY_PRINTF=y +# CONFIG_VIRTUALIZATION is not set +# CONFIG_BINARY_PRINTF is not set # # Library routines diff --git a/arch/sh/configs/se7343_defconfig b/arch/sh/configs/se7343_defconfig index ec494e3..586cb1e 100644 --- a/arch/sh/configs/se7343_defconfig +++ b/arch/sh/configs/se7343_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 13:30:41 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 16:37:31 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -32,6 +32,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -46,9 +47,11 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set # CONFIG_SWAP is not set CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -70,11 +73,6 @@ CONFIG_RCU_FANOUT=32 # CONFIG_TREE_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 -CONFIG_GROUP_SCHED=y -CONFIG_FAIR_GROUP_SCHED=y -# CONFIG_RT_GROUP_SCHED is not set -CONFIG_USER_SCHED=y -# CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -107,7 +105,7 @@ CONFIG_PERF_USE_VMALLOC=y # # Kernel Performance Events And Counters # -# CONFIG_PERF_EVENTS is not set +CONFIG_PERF_EVENTS=y # CONFIG_PERF_COUNTERS is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_COMPAT_BRK=y @@ -124,6 +122,7 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -245,6 +244,7 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -260,7 +260,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -335,7 +335,7 @@ CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set CONFIG_GUSA=y -# CONFIG_SPARSE_IRQ is not set +# CONFIG_INTC_USERIMASK is not set # # Boot options @@ -370,6 +370,7 @@ CONFIG_PM_SLEEP=y CONFIG_SUSPEND=y CONFIG_SUSPEND_FREEZER=y CONFIG_PM_RUNTIME=y +CONFIG_PM_OPS=y # CONFIG_CPU_IDLE is not set CONFIG_NET=y @@ -377,7 +378,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -569,6 +569,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y @@ -635,6 +636,7 @@ CONFIG_USB_USBNET=y CONFIG_USB_NET_CDCETHER=y # CONFIG_USB_NET_CDC_EEM is not set CONFIG_USB_NET_DM9601=y +# CONFIG_USB_NET_SMSC75XX is not set # CONFIG_USB_NET_SMSC95XX is not set # CONFIG_USB_NET_GL620A is not set # CONFIG_USB_NET_NET1080 is not set @@ -644,6 +646,7 @@ CONFIG_USB_NET_DM9601=y # CONFIG_USB_NET_CDC_SUBSET is not set # CONFIG_USB_NET_ZAURUS is not set # CONFIG_USB_NET_INT51X1 is not set +# CONFIG_USB_IPHETH is not set # CONFIG_WAN is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -713,6 +716,7 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=4 CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set # CONFIG_UNIX98_PTYS is not set CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 @@ -739,6 +743,7 @@ CONFIG_I2C_HELPER_AUTO=y # CONFIG_I2C_OCORES is not set CONFIG_I2C_SH_MOBILE=y # CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set # # External I2C/SMBus adapter drivers @@ -752,15 +757,9 @@ CONFIG_I2C_SH_MOBILE=y # # CONFIG_I2C_PCA_PLATFORM is not set # CONFIG_I2C_STUB is not set - -# -# Miscellaneous I2C Chip support -# -# CONFIG_SENSORS_TSL2550 is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set # CONFIG_SPI is not set # @@ -783,6 +782,7 @@ CONFIG_SSB_POSSIBLE=y # Multifunction device drivers # # CONFIG_MFD_CORE is not set +# CONFIG_MFD_88PM860X is not set # CONFIG_MFD_SM501 is not set # CONFIG_MFD_SH_MOBILE_SDHI is not set # CONFIG_HTC_PASIC3 is not set @@ -790,12 +790,13 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_TMIO is not set # CONFIG_PMIC_DA903X is not set # CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X is not set # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set # CONFIG_MFD_PCF50633 is not set # CONFIG_AB3100_CORE is not set -# CONFIG_MFD_88PM8607 is not set # CONFIG_REGULATOR is not set # CONFIG_MEDIA_SUPPORT is not set @@ -878,6 +879,7 @@ CONFIG_SND_DRIVERS=y CONFIG_SND_SUPERH=y CONFIG_SND_USB=y # CONFIG_SND_USB_AUDIO is not set +# CONFIG_SND_USB_UA101 is not set # CONFIG_SND_USB_CAIAQ is not set # CONFIG_SND_SOC is not set # CONFIG_SOUND_PRIME is not set @@ -895,6 +897,7 @@ CONFIG_USB_HID=y # # Special HID drivers # +# CONFIG_HID_3M_PCT is not set CONFIG_HID_A4TECH=y CONFIG_HID_APPLE=y CONFIG_HID_BELKIN=y @@ -910,14 +913,19 @@ CONFIG_HID_GYRATION=y CONFIG_HID_LOGITECH=y # CONFIG_LOGITECH_FF is not set # CONFIG_LOGIRUMBLEPAD2_FF is not set +# CONFIG_LOGIG940_FF is not set CONFIG_HID_MICROSOFT=y +# CONFIG_HID_MOSART is not set CONFIG_HID_MONTEREY=y # CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set CONFIG_HID_PANTHERLORD=y # CONFIG_PANTHERLORD_FF is not set CONFIG_HID_PETALYNX=y +# CONFIG_HID_QUANTA is not set CONFIG_HID_SAMSUNG=y CONFIG_HID_SONY=y +# CONFIG_HID_STANTUM is not set CONFIG_HID_SUNPLUS=y # CONFIG_HID_GREENASIA is not set # CONFIG_HID_SMARTJOYPLUS is not set @@ -997,7 +1005,6 @@ CONFIG_USB_ISP116X_HCD=y # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set -# CONFIG_USB_BERRY_CHARGE is not set # CONFIG_USB_LED is not set # CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set @@ -1009,7 +1016,6 @@ CONFIG_USB_ISP116X_HCD=y # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set # CONFIG_USB_ISIGHTFW is not set -# CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set # @@ -1027,8 +1033,6 @@ CONFIG_RTC_LIB=y CONFIG_UIO=y # CONFIG_UIO_PDRV is not set # CONFIG_UIO_PDRV_GENIRQ is not set -# CONFIG_UIO_SMX is not set -# CONFIG_UIO_SERCOS3 is not set # # TI VLYNQ @@ -1115,6 +1119,7 @@ CONFIG_JFFS2_ZLIB=y # CONFIG_JFFS2_LZO is not set CONFIG_JFFS2_RTIME=y # CONFIG_JFFS2_RUBIN is not set +# CONFIG_LOGFS is not set CONFIG_CRAMFS=y # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -1141,6 +1146,7 @@ CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1324,6 +1330,7 @@ CONFIG_CRYPTO=y # # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y +# CONFIG_VIRTUALIZATION is not set # CONFIG_BINARY_PRINTF is not set # diff --git a/arch/sh/configs/se7619_defconfig b/arch/sh/configs/se7619_defconfig index ee87e2b..acb3e02 100644 --- a/arch/sh/configs/se7619_defconfig +++ b/arch/sh/configs/se7619_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 13:34:15 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 16:41:13 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -30,6 +30,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -44,9 +45,11 @@ CONFIG_LOCALVERSION="" CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set # CONFIG_SYSVIPC is not set # CONFIG_BSD_PROCESS_ACCT is not set @@ -62,7 +65,6 @@ CONFIG_RCU_FANOUT=32 # CONFIG_TREE_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set @@ -91,7 +93,7 @@ CONFIG_PERF_USE_VMALLOC=y # # Kernel Performance Events And Counters # -# CONFIG_PERF_EVENTS is not set +CONFIG_PERF_EVENTS=y # CONFIG_PERF_COUNTERS is not set # CONFIG_VM_EVENT_COUNTERS is not set CONFIG_COMPAT_BRK=y @@ -107,6 +109,7 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -217,6 +220,7 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -232,7 +236,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 CONFIG_NOMMU_INITIAL_TRIM_EXCESS=1 # @@ -301,7 +305,6 @@ CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set CONFIG_GUSA=y -# CONFIG_SPARSE_IRQ is not set # # Boot options @@ -453,6 +456,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set # CONFIG_SCSI_DMA is not set @@ -513,6 +517,7 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=3 CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set # CONFIG_UNIX98_PTYS is not set # CONFIG_LEGACY_PTYS is not set # CONFIG_IPMI_HANDLER is not set @@ -612,7 +617,6 @@ CONFIG_RTC_LIB=y # CONFIG_EXT2_FS is not set # CONFIG_EXT3_FS is not set # CONFIG_EXT4_FS is not set -CONFIG_EXT4_USE_FOR_EXT23=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set @@ -664,6 +668,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set # CONFIG_JFFS2_FS is not set +# CONFIG_LOGFS is not set # CONFIG_CRAMFS is not set # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -729,6 +734,7 @@ CONFIG_HAVE_ARCH_KGDB=y CONFIG_DEFAULT_SECURITY_DAC=y CONFIG_DEFAULT_SECURITY="" # CONFIG_CRYPTO is not set +# CONFIG_VIRTUALIZATION is not set # CONFIG_BINARY_PRINTF is not set # diff --git a/arch/sh/configs/se7705_defconfig b/arch/sh/configs/se7705_defconfig index 03f4219..084fec9 100644 --- a/arch/sh/configs/se7705_defconfig +++ b/arch/sh/configs/se7705_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 13:34:37 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 16:42:43 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -30,6 +30,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -45,9 +46,11 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set # CONFIG_SWAP is not set # CONFIG_SYSVIPC is not set # CONFIG_POSIX_MQUEUE is not set @@ -67,7 +70,6 @@ CONFIG_RCU_FANOUT=32 # CONFIG_TREE_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set @@ -76,6 +78,7 @@ CONFIG_INITRAMFS_SOURCE="" CONFIG_RD_GZIP=y # CONFIG_RD_BZIP2 is not set # CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SYSCTL=y CONFIG_ANON_INODES=y @@ -101,7 +104,7 @@ CONFIG_PERF_USE_VMALLOC=y # # Kernel Performance Events And Counters # -# CONFIG_PERF_EVENTS is not set +CONFIG_PERF_EVENTS=y # CONFIG_PERF_COUNTERS is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_COMPAT_BRK=y @@ -117,6 +120,7 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -234,6 +238,7 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -249,7 +254,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -327,7 +332,6 @@ CONFIG_HZ=250 CONFIG_PREEMPT=y CONFIG_GUSA=y # CONFIG_GUSA_RB is not set -# CONFIG_SPARSE_IRQ is not set # # Boot options @@ -362,7 +366,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -562,6 +565,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set # CONFIG_SCSI_DMA is not set @@ -679,6 +683,7 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=2 CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set # CONFIG_LEGACY_PTYS is not set @@ -798,7 +803,6 @@ CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XIP is not set # CONFIG_EXT3_FS is not set # CONFIG_EXT4_FS is not set -CONFIG_EXT4_USE_FOR_EXT23=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set @@ -863,6 +867,7 @@ CONFIG_JFFS2_ZLIB=y # CONFIG_JFFS2_LZO is not set CONFIG_JFFS2_RTIME=y # CONFIG_JFFS2_RUBIN is not set +# CONFIG_LOGFS is not set # CONFIG_CRAMFS is not set # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -885,6 +890,7 @@ CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1026,6 +1032,7 @@ CONFIG_CRYPTO=y # # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y +# CONFIG_VIRTUALIZATION is not set # CONFIG_BINARY_PRINTF is not set # diff --git a/arch/sh/configs/se7712_defconfig b/arch/sh/configs/se7712_defconfig index cfa5819..4487a23 100644 --- a/arch/sh/configs/se7712_defconfig +++ b/arch/sh/configs/se7712_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 13:44:56 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 18:05:15 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -12,8 +12,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -29,6 +29,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -43,9 +44,11 @@ CONFIG_LOCALVERSION="" CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set # CONFIG_SWAP is not set CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -68,7 +71,6 @@ CONFIG_RCU_FANOUT=32 # CONFIG_TREE_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -102,8 +104,9 @@ CONFIG_PERF_USE_VMALLOC=y # # Kernel Performance Events And Counters # -# CONFIG_PERF_EVENTS is not set +CONFIG_PERF_EVENTS=y # CONFIG_PERF_COUNTERS is not set +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_COMPAT_BRK=y CONFIG_SLAB=y @@ -119,6 +122,7 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -236,6 +240,7 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -251,7 +256,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -329,7 +334,6 @@ CONFIG_PREEMPT_VOLUNTARY=y # CONFIG_PREEMPT is not set CONFIG_GUSA=y # CONFIG_GUSA_RB is not set -# CONFIG_SPARSE_IRQ is not set # # Boot options @@ -366,7 +370,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -614,6 +617,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y @@ -754,6 +758,7 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=2 CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set # CONFIG_LEGACY_PTYS is not set @@ -834,11 +839,11 @@ CONFIG_LEDS_CLASS=y # # LED drivers # +CONFIG_LEDS_TRIGGERS=y # # LED Triggers # -CONFIG_LEDS_TRIGGERS=y # CONFIG_LEDS_TRIGGER_TIMER is not set # CONFIG_LEDS_TRIGGER_HEARTBEAT is not set # CONFIG_LEDS_TRIGGER_BACKLIGHT is not set @@ -940,6 +945,7 @@ CONFIG_JFFS2_ZLIB=y # CONFIG_JFFS2_LZO is not set CONFIG_JFFS2_RTIME=y # CONFIG_JFFS2_RUBIN is not set +# CONFIG_LOGFS is not set CONFIG_CRAMFS=y # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -962,6 +968,7 @@ CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -997,6 +1004,7 @@ CONFIG_SCHED_DEBUG=y # CONFIG_TIMER_STATS is not set # CONFIG_DEBUG_OBJECTS is not set # CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_KMEMLEAK is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set @@ -1042,6 +1050,7 @@ CONFIG_FTRACE=y CONFIG_BRANCH_PROFILE_NONE=y # CONFIG_PROFILE_ANNOTATED_BRANCHES is not set # CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_KSYM_TRACER is not set # CONFIG_STACK_TRACER is not set # CONFIG_KMEMTRACE is not set # CONFIG_WORKQUEUE_TRACER is not set @@ -1167,6 +1176,7 @@ CONFIG_CRYPTO_DEFLATE=y # # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y +# CONFIG_VIRTUALIZATION is not set # CONFIG_BINARY_PRINTF is not set # diff --git a/arch/sh/configs/se7721_defconfig b/arch/sh/configs/se7721_defconfig index 201283c..7c06b5c 100644 --- a/arch/sh/configs/se7721_defconfig +++ b/arch/sh/configs/se7721_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 13:46:58 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 18:06:03 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -12,8 +12,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -30,6 +30,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -44,9 +45,11 @@ CONFIG_LOCALVERSION="" CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set # CONFIG_SWAP is not set CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -69,11 +72,6 @@ CONFIG_RCU_FANOUT=32 # CONFIG_TREE_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 -CONFIG_GROUP_SCHED=y -CONFIG_FAIR_GROUP_SCHED=y -# CONFIG_RT_GROUP_SCHED is not set -CONFIG_USER_SCHED=y -# CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -107,8 +105,9 @@ CONFIG_PERF_USE_VMALLOC=y # # Kernel Performance Events And Counters # -# CONFIG_PERF_EVENTS is not set +CONFIG_PERF_EVENTS=y # CONFIG_PERF_COUNTERS is not set +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_COMPAT_BRK=y CONFIG_SLAB=y @@ -124,6 +123,7 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -241,6 +241,7 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -256,7 +257,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -334,7 +335,6 @@ CONFIG_PREEMPT_VOLUNTARY=y # CONFIG_PREEMPT is not set CONFIG_GUSA=y # CONFIG_GUSA_RB is not set -# CONFIG_SPARSE_IRQ is not set # # Boot options @@ -371,7 +371,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -620,6 +619,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y @@ -687,6 +687,7 @@ CONFIG_WLAN=y # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set # CONFIG_USB_USBNET is not set +# CONFIG_USB_IPHETH is not set # CONFIG_WAN is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -764,6 +765,7 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=2 CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set # CONFIG_LEGACY_PTYS is not set @@ -829,6 +831,7 @@ CONFIG_USB_HID=y # # Special HID drivers # +# CONFIG_HID_3M_PCT is not set CONFIG_HID_A4TECH=y CONFIG_HID_APPLE=y CONFIG_HID_BELKIN=y @@ -844,14 +847,19 @@ CONFIG_HID_GYRATION=y CONFIG_HID_LOGITECH=y # CONFIG_LOGITECH_FF is not set # CONFIG_LOGIRUMBLEPAD2_FF is not set +# CONFIG_LOGIG940_FF is not set CONFIG_HID_MICROSOFT=y +# CONFIG_HID_MOSART is not set CONFIG_HID_MONTEREY=y # CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set CONFIG_HID_PANTHERLORD=y # CONFIG_PANTHERLORD_FF is not set CONFIG_HID_PETALYNX=y +# CONFIG_HID_QUANTA is not set CONFIG_HID_SAMSUNG=y CONFIG_HID_SONY=y +# CONFIG_HID_STANTUM is not set CONFIG_HID_SUNPLUS=y # CONFIG_HID_GREENASIA is not set # CONFIG_HID_SMARTJOYPLUS is not set @@ -946,7 +954,6 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set -# CONFIG_USB_BERRY_CHARGE is not set # CONFIG_USB_LED is not set # CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set @@ -958,7 +965,6 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set # CONFIG_USB_ISIGHTFW is not set -# CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set # @@ -973,11 +979,11 @@ CONFIG_LEDS_CLASS=y # # LED drivers # +CONFIG_LEDS_TRIGGERS=y # # LED Triggers # -CONFIG_LEDS_TRIGGERS=y # CONFIG_LEDS_TRIGGER_TIMER is not set # CONFIG_LEDS_TRIGGER_HEARTBEAT is not set # CONFIG_LEDS_TRIGGER_BACKLIGHT is not set @@ -1082,6 +1088,7 @@ CONFIG_JFFS2_ZLIB=y # CONFIG_JFFS2_LZO is not set CONFIG_JFFS2_RTIME=y # CONFIG_JFFS2_RUBIN is not set +# CONFIG_LOGFS is not set CONFIG_CRAMFS=y # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -1163,6 +1170,7 @@ CONFIG_SCHED_DEBUG=y # CONFIG_TIMER_STATS is not set # CONFIG_DEBUG_OBJECTS is not set # CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_KMEMLEAK is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set @@ -1208,6 +1216,7 @@ CONFIG_FTRACE=y CONFIG_BRANCH_PROFILE_NONE=y # CONFIG_PROFILE_ANNOTATED_BRANCHES is not set # CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_KSYM_TRACER is not set # CONFIG_STACK_TRACER is not set # CONFIG_KMEMTRACE is not set # CONFIG_WORKQUEUE_TRACER is not set @@ -1333,6 +1342,7 @@ CONFIG_CRYPTO_DEFLATE=y # # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y +# CONFIG_VIRTUALIZATION is not set # CONFIG_BINARY_PRINTF is not set # diff --git a/arch/sh/configs/se7722_defconfig b/arch/sh/configs/se7722_defconfig index 4a4efd2..42782e7 100644 --- a/arch/sh/configs/se7722_defconfig +++ b/arch/sh/configs/se7722_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 13:49:15 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 18:07:07 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -33,6 +33,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -48,9 +49,11 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -73,7 +76,6 @@ CONFIG_RCU_FANOUT=32 CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -84,6 +86,7 @@ CONFIG_INITRAMFS_SOURCE="" CONFIG_RD_GZIP=y # CONFIG_RD_BZIP2 is not set # CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_ANON_INODES=y @@ -122,13 +125,13 @@ CONFIG_PROFILING=y # CONFIG_OPROFILE is not set CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set -CONFIG_HAVE_IOREMAP_PROT=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -245,7 +248,7 @@ CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_MEMORY_START=0x0c000000 CONFIG_MEMORY_SIZE=0x04000000 CONFIG_29BIT=y -# CONFIG_X2TLB is not set +CONFIG_X2TLB=y CONFIG_VSYSCALL=y CONFIG_NUMA=y CONFIG_NODES_SHIFT=1 @@ -256,6 +259,8 @@ CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y +CONFIG_IOREMAP_FIXED=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -279,7 +284,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_MIGRATION=y # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -356,7 +361,7 @@ CONFIG_KEXEC=y # CONFIG_PREEMPT_VOLUNTARY is not set CONFIG_PREEMPT=y CONFIG_GUSA=y -# CONFIG_SPARSE_IRQ is not set +# CONFIG_INTC_USERIMASK is not set # # Boot options @@ -391,6 +396,7 @@ CONFIG_SUSPEND=y CONFIG_SUSPEND_FREEZER=y # CONFIG_HIBERNATION is not set CONFIG_PM_RUNTIME=y +CONFIG_PM_OPS=y # CONFIG_CPU_IDLE is not set CONFIG_NET=y @@ -398,7 +404,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -519,6 +524,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y @@ -676,6 +682,7 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=3 CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y @@ -898,6 +905,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set +# CONFIG_LOGFS is not set # CONFIG_CRAMFS is not set # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -912,6 +920,7 @@ CONFIG_NETWORK_FILESYSTEMS=y # CONFIG_NFS_FS is not set # CONFIG_NFSD is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -944,6 +953,7 @@ CONFIG_DEBUG_FS=y CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_MEMORY_INIT is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_LKDTM is not set # CONFIG_LATENCYTOP is not set # CONFIG_SYSCTL_SYSCALL_CHECK is not set CONFIG_HAVE_FUNCTION_TRACER=y @@ -1059,6 +1069,7 @@ CONFIG_CRYPTO=y # # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y +# CONFIG_VIRTUALIZATION is not set # CONFIG_BINARY_PRINTF is not set # diff --git a/arch/sh/configs/se7724_defconfig b/arch/sh/configs/se7724_defconfig index ab371af..ebb4ac4 100644 --- a/arch/sh/configs/se7724_defconfig +++ b/arch/sh/configs/se7724_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 14:36:56 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 16:55:41 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y CONFIG_GENERIC_GPIO=y CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -32,6 +32,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -47,9 +48,11 @@ CONFIG_LOCALVERSION="" CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -71,11 +74,6 @@ CONFIG_RCU_FANOUT=32 # CONFIG_TREE_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 -CONFIG_GROUP_SCHED=y -CONFIG_FAIR_GROUP_SCHED=y -# CONFIG_RT_GROUP_SCHED is not set -CONFIG_USER_SCHED=y -# CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -107,7 +105,7 @@ CONFIG_PERF_USE_VMALLOC=y # # Kernel Performance Events And Counters # -# CONFIG_PERF_EVENTS is not set +CONFIG_PERF_EVENTS=y # CONFIG_PERF_COUNTERS is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_COMPAT_BRK=y @@ -116,13 +114,13 @@ CONFIG_SLAB=y # CONFIG_SLOB is not set # CONFIG_PROFILING is not set CONFIG_HAVE_OPROFILE=y -CONFIG_HAVE_IOREMAP_PROT=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -237,8 +235,8 @@ CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_MEMORY_START=0x08000000 CONFIG_MEMORY_SIZE=0x08000000 CONFIG_29BIT=y -# CONFIG_PMB_ENABLE is not set -# CONFIG_X2TLB is not set +# CONFIG_PMB is not set +CONFIG_X2TLB=y CONFIG_VSYSCALL=y CONFIG_ARCH_FLATMEM_ENABLE=y CONFIG_ARCH_SPARSEMEM_ENABLE=y @@ -246,6 +244,8 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_IOREMAP_FIXED=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -261,7 +261,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -340,7 +340,7 @@ CONFIG_SECCOMP=y # CONFIG_PREEMPT_VOLUNTARY is not set CONFIG_PREEMPT=y CONFIG_GUSA=y -# CONFIG_SPARSE_IRQ is not set +# CONFIG_INTC_USERIMASK is not set # # Boot options @@ -376,6 +376,7 @@ CONFIG_SUSPEND=y CONFIG_SUSPEND_FREEZER=y # CONFIG_HIBERNATION is not set CONFIG_PM_RUNTIME=y +CONFIG_PM_OPS=y # CONFIG_CPU_IDLE is not set CONFIG_NET=y @@ -383,7 +384,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y # CONFIG_NET_KEY is not set CONFIG_INET=y @@ -559,6 +559,7 @@ CONFIG_MTD_NAND_IDS=y # CONFIG_MTD_NAND_NANDSIM is not set # CONFIG_MTD_NAND_PLATFORM is not set # CONFIG_MTD_ALAUDA is not set +# CONFIG_MTD_NAND_SH_FLCTL is not set # CONFIG_MTD_ONENAND is not set # @@ -600,6 +601,7 @@ CONFIG_MISC_DEVICES=y # CONFIG_ICS932S401 is not set # CONFIG_ENCLOSURE_SERVICES is not set # CONFIG_ISL29003 is not set +# CONFIG_SENSORS_TSL2550 is not set # CONFIG_DS1682 is not set # CONFIG_TI_DAC7512 is not set # CONFIG_C2PORT is not set @@ -619,6 +621,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y @@ -726,6 +729,7 @@ CONFIG_WLAN=y # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set # CONFIG_USB_USBNET is not set +# CONFIG_USB_IPHETH is not set # CONFIG_WAN is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -805,6 +809,7 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=6 CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y @@ -833,6 +838,7 @@ CONFIG_I2C_HELPER_AUTO=y # CONFIG_I2C_OCORES is not set CONFIG_I2C_SH_MOBILE=y # CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set # # External I2C/SMBus adapter drivers @@ -846,15 +852,9 @@ CONFIG_I2C_SH_MOBILE=y # # CONFIG_I2C_PCA_PLATFORM is not set # CONFIG_I2C_STUB is not set - -# -# Miscellaneous I2C Chip support -# -# CONFIG_SENSORS_TSL2550 is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set CONFIG_SPI=y CONFIG_SPI_MASTER=y @@ -885,13 +885,16 @@ CONFIG_GPIOLIB=y # # Memory mapped GPIO expanders: # +# CONFIG_GPIO_IT8761E is not set # # I2C GPIO expanders: # +# CONFIG_GPIO_MAX7300 is not set # CONFIG_GPIO_MAX732X is not set # CONFIG_GPIO_PCA953X is not set # CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_ADP5588 is not set # # PCI GPIO expanders: @@ -923,22 +926,25 @@ CONFIG_SSB_POSSIBLE=y # Multifunction device drivers # # CONFIG_MFD_CORE is not set +# CONFIG_MFD_88PM860X is not set # CONFIG_MFD_SM501 is not set # CONFIG_MFD_SH_MOBILE_SDHI is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set # CONFIG_TPS65010 is not set # CONFIG_TWL4030_CORE is not set # CONFIG_MFD_TMIO is not set # CONFIG_PMIC_DA903X is not set # CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X is not set # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set # CONFIG_MFD_PCF50633 is not set # CONFIG_MFD_MC13783 is not set # CONFIG_AB3100_CORE is not set # CONFIG_EZX_PCAP is not set -# CONFIG_MFD_88PM8607 is not set # CONFIG_AB4500_CORE is not set # CONFIG_REGULATOR is not set CONFIG_MEDIA_SUPPORT=y @@ -1001,7 +1007,9 @@ CONFIG_USB_GSPCA=m # CONFIG_USB_M5602 is not set # CONFIG_USB_STV06XX is not set # CONFIG_USB_GL860 is not set +# CONFIG_USB_GSPCA_BENQ is not set # CONFIG_USB_GSPCA_CONEX is not set +# CONFIG_USB_GSPCA_CPIA1 is not set # CONFIG_USB_GSPCA_ETOMS is not set # CONFIG_USB_GSPCA_FINEPIX is not set # CONFIG_USB_GSPCA_JEILINJ is not set @@ -1009,9 +1017,11 @@ CONFIG_USB_GSPCA=m # CONFIG_USB_GSPCA_MR97310A is not set # CONFIG_USB_GSPCA_OV519 is not set # CONFIG_USB_GSPCA_OV534 is not set +# CONFIG_USB_GSPCA_OV534_9 is not set # CONFIG_USB_GSPCA_PAC207 is not set # CONFIG_USB_GSPCA_PAC7302 is not set # CONFIG_USB_GSPCA_PAC7311 is not set +# CONFIG_USB_GSPCA_SN9C2028 is not set # CONFIG_USB_GSPCA_SN9C20X is not set # CONFIG_USB_GSPCA_SONIXB is not set # CONFIG_USB_GSPCA_SONIXJ is not set @@ -1033,6 +1043,7 @@ CONFIG_USB_GSPCA=m # CONFIG_VIDEO_PVRUSB2 is not set # CONFIG_VIDEO_HDPVR is not set # CONFIG_VIDEO_EM28XX is not set +# CONFIG_VIDEO_TLG2300 is not set # CONFIG_VIDEO_CX231XX is not set # CONFIG_VIDEO_USBVISION is not set # CONFIG_USB_ET61X251 is not set @@ -1147,6 +1158,7 @@ CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_SUPERH is not set CONFIG_SND_USB=y # CONFIG_SND_USB_AUDIO is not set +# CONFIG_SND_USB_UA101 is not set # CONFIG_SND_USB_CAIAQ is not set CONFIG_SND_SOC=m @@ -1155,6 +1167,7 @@ CONFIG_SND_SOC=m # CONFIG_SND_SOC_SH4_FSI=m CONFIG_SND_FSI_AK4642=y +# CONFIG_SND_FSI_DA7210 is not set CONFIG_SND_SOC_I2C_AND_SPI=m CONFIG_SND_SOC_ALL_CODECS=m CONFIG_SND_SOC_WM_HUBS=m @@ -1167,6 +1180,7 @@ CONFIG_SND_SOC_AK4535=m CONFIG_SND_SOC_AK4642=m CONFIG_SND_SOC_AK4671=m CONFIG_SND_SOC_CS4270=m +CONFIG_SND_SOC_DA7210=m CONFIG_SND_SOC_L3=m CONFIG_SND_SOC_PCM3008=m CONFIG_SND_SOC_SPDIF=m @@ -1189,17 +1203,21 @@ CONFIG_SND_SOC_WM8753=m CONFIG_SND_SOC_WM8776=m CONFIG_SND_SOC_WM8900=m CONFIG_SND_SOC_WM8903=m +CONFIG_SND_SOC_WM8904=m CONFIG_SND_SOC_WM8940=m +CONFIG_SND_SOC_WM8955=m CONFIG_SND_SOC_WM8960=m CONFIG_SND_SOC_WM8961=m CONFIG_SND_SOC_WM8971=m CONFIG_SND_SOC_WM8974=m +CONFIG_SND_SOC_WM8978=m CONFIG_SND_SOC_WM8988=m CONFIG_SND_SOC_WM8990=m CONFIG_SND_SOC_WM8993=m CONFIG_SND_SOC_WM9081=m CONFIG_SND_SOC_MAX9877=m CONFIG_SND_SOC_TPA6130A2=m +CONFIG_SND_SOC_WM2000=m # CONFIG_SOUND_PRIME is not set CONFIG_HID_SUPPORT=y CONFIG_HID=y @@ -1215,6 +1233,7 @@ CONFIG_USB_HID=y # # Special HID drivers # +# CONFIG_HID_3M_PCT is not set # CONFIG_HID_A4TECH is not set # CONFIG_HID_APPLE is not set # CONFIG_HID_BELKIN is not set @@ -1229,12 +1248,16 @@ CONFIG_USB_HID=y # CONFIG_HID_KENSINGTON is not set # CONFIG_HID_LOGITECH is not set # CONFIG_HID_MICROSOFT is not set +# CONFIG_HID_MOSART is not set # CONFIG_HID_MONTEREY is not set # CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set # CONFIG_HID_PANTHERLORD is not set # CONFIG_HID_PETALYNX is not set +# CONFIG_HID_QUANTA is not set # CONFIG_HID_SAMSUNG is not set # CONFIG_HID_SONY is not set +# CONFIG_HID_STANTUM is not set # CONFIG_HID_SUNPLUS is not set # CONFIG_HID_GREENASIA is not set # CONFIG_HID_SMARTJOYPLUS is not set @@ -1327,7 +1350,6 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set -# CONFIG_USB_BERRY_CHARGE is not set # CONFIG_USB_LED is not set # CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set @@ -1339,7 +1361,6 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set # CONFIG_USB_ISIGHTFW is not set -# CONFIG_USB_VST is not set CONFIG_USB_GADGET=y # CONFIG_USB_GADGET_DEBUG_FILES is not set CONFIG_USB_GADGET_VBUS_DRAW=2 @@ -1378,6 +1399,7 @@ CONFIG_USB_G_SERIAL=m # CONFIG_USB_MIDI_GADGET is not set # CONFIG_USB_G_PRINTER is not set # CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_G_NOKIA is not set # CONFIG_USB_G_MULTI is not set # @@ -1401,10 +1423,7 @@ CONFIG_MMC_BLOCK_BOUNCE=y # MMC/SD/SDIO Host Controller Drivers # # CONFIG_MMC_SDHCI is not set -# CONFIG_MMC_AT91 is not set -# CONFIG_MMC_ATMELMCI is not set CONFIG_MMC_SPI=y -# CONFIG_MMC_TMIO is not set # CONFIG_MEMSTICK is not set # CONFIG_NEW_LEDS is not set # CONFIG_ACCESSIBILITY is not set @@ -1480,8 +1499,6 @@ CONFIG_RTC_DRV_PCF8563=y CONFIG_UIO=y # CONFIG_UIO_PDRV is not set CONFIG_UIO_PDRV_GENIRQ=y -# CONFIG_UIO_SMX is not set -# CONFIG_UIO_SERCOS3 is not set # # TI VLYNQ @@ -1566,6 +1583,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_EFS_FS is not set # CONFIG_JFFS2_FS is not set # CONFIG_UBIFS_FS is not set +# CONFIG_LOGFS is not set # CONFIG_CRAMFS is not set # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -1594,6 +1612,7 @@ CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1786,6 +1805,7 @@ CONFIG_CRYPTO_CBC=y # # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y +# CONFIG_VIRTUALIZATION is not set # CONFIG_BINARY_PRINTF is not set # diff --git a/arch/sh/configs/se7750_defconfig b/arch/sh/configs/se7750_defconfig index b15a44e..e096c3e 100644 --- a/arch/sh/configs/se7750_defconfig +++ b/arch/sh/configs/se7750_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 14:39:10 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 17:00:16 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -31,6 +31,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -45,9 +46,11 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set # CONFIG_SWAP is not set CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -70,7 +73,6 @@ CONFIG_RCU_FANOUT=32 CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -103,7 +105,7 @@ CONFIG_PERF_USE_VMALLOC=y # # Kernel Performance Events And Counters # -# CONFIG_PERF_EVENTS is not set +CONFIG_PERF_EVENTS=y # CONFIG_PERF_COUNTERS is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_COMPAT_BRK=y @@ -120,6 +122,7 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -237,6 +240,7 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -252,7 +256,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -329,7 +333,6 @@ CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT is not set CONFIG_GUSA=y # CONFIG_GUSA_RB is not set -# CONFIG_SPARSE_IRQ is not set # # Boot options @@ -364,7 +367,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -580,6 +582,7 @@ CONFIG_IDE_PROC_FS=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y @@ -698,6 +701,7 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=2 CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y @@ -816,7 +820,6 @@ CONFIG_RTC_LIB=y # CONFIG_EXT2_FS is not set # CONFIG_EXT3_FS is not set # CONFIG_EXT4_FS is not set -CONFIG_EXT4_USE_FOR_EXT23=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set @@ -885,6 +888,7 @@ CONFIG_JFFS2_ZLIB=y # CONFIG_JFFS2_LZO is not set CONFIG_JFFS2_RTIME=y # CONFIG_JFFS2_RUBIN is not set +# CONFIG_LOGFS is not set # CONFIG_CRAMFS is not set # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -907,6 +911,7 @@ CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1063,6 +1068,7 @@ CONFIG_CRYPTO=y # # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y +# CONFIG_VIRTUALIZATION is not set # CONFIG_BINARY_PRINTF is not set # diff --git a/arch/sh/configs/se7751_defconfig b/arch/sh/configs/se7751_defconfig index d1effde..84d3fac 100644 --- a/arch/sh/configs/se7751_defconfig +++ b/arch/sh/configs/se7751_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 14:39:56 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 17:03:26 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -31,6 +31,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -45,9 +46,11 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -69,7 +72,6 @@ CONFIG_RCU_FANOUT=32 # CONFIG_TREE_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -80,6 +82,7 @@ CONFIG_INITRAMFS_SOURCE="" CONFIG_RD_GZIP=y # CONFIG_RD_BZIP2 is not set # CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SYSCTL=y CONFIG_ANON_INODES=y @@ -106,7 +109,7 @@ CONFIG_PERF_USE_VMALLOC=y # # Kernel Performance Events And Counters # -# CONFIG_PERF_EVENTS is not set +CONFIG_PERF_EVENTS=y # CONFIG_PERF_COUNTERS is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_COMPAT_BRK=y @@ -123,6 +126,7 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -240,6 +244,7 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -255,7 +260,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -333,7 +338,6 @@ CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT is not set CONFIG_GUSA=y # CONFIG_GUSA_RB is not set -# CONFIG_SPARSE_IRQ is not set # # Boot options @@ -369,7 +373,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -589,6 +592,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set # CONFIG_SCSI_DMA is not set @@ -666,6 +670,7 @@ CONFIG_DEVKMEM=y # Non-8250 serial port support # # CONFIG_SERIAL_SH_SCI is not set +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y @@ -785,7 +790,6 @@ CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XIP is not set # CONFIG_EXT3_FS is not set # CONFIG_EXT4_FS is not set -CONFIG_EXT4_USE_FOR_EXT23=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set @@ -854,6 +858,7 @@ CONFIG_JFFS2_ZLIB=y # CONFIG_JFFS2_LZO is not set CONFIG_JFFS2_RTIME=y # CONFIG_JFFS2_RUBIN is not set +# CONFIG_LOGFS is not set # CONFIG_CRAMFS is not set # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -868,6 +873,7 @@ CONFIG_NETWORK_FILESYSTEMS=y # CONFIG_NFS_FS is not set # CONFIG_NFSD is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1012,6 +1018,7 @@ CONFIG_CRYPTO=y # # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y +# CONFIG_VIRTUALIZATION is not set # CONFIG_BINARY_PRINTF is not set # diff --git a/arch/sh/configs/se7780_defconfig b/arch/sh/configs/se7780_defconfig index 58533d5..f0d7e67 100644 --- a/arch/sh/configs/se7780_defconfig +++ b/arch/sh/configs/se7780_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 14:40:32 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 17:06:12 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -32,6 +32,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -46,9 +47,11 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set # CONFIG_SWAP is not set CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -100,7 +103,7 @@ CONFIG_PERF_USE_VMALLOC=y # # Kernel Performance Events And Counters # -# CONFIG_PERF_EVENTS is not set +CONFIG_PERF_EVENTS=y # CONFIG_PERF_COUNTERS is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_PCI_QUIRKS=y @@ -117,6 +120,7 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -238,6 +242,7 @@ CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -253,7 +258,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_MIGRATION=y # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -328,6 +333,7 @@ CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set CONFIG_GUSA=y +# CONFIG_INTC_USERIMASK is not set # # Boot options @@ -343,9 +349,9 @@ CONFIG_CMDLINE="console=ttySC0,115200 root=/dev/sda1" # Bus options # CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y # CONFIG_PCIEPORTBUS is not set # CONFIG_ARCH_SUPPORTS_MSI is not set -CONFIG_PCI_LEGACY=y # CONFIG_PCI_STUB is not set # CONFIG_PCI_IOV is not set @@ -362,7 +368,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -571,6 +576,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y @@ -714,7 +720,7 @@ CONFIG_SATA_SIL=y # # -# See the help texts for more information. +# The newer stack is recommended. # # CONFIG_FIREWIRE is not set # CONFIG_IEEE1394 is not set @@ -772,6 +778,7 @@ CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set # CONFIG_AMD8111_ETH is not set # CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_KSZ884X_PCI is not set # CONFIG_B44 is not set # CONFIG_FORCEDETH is not set # CONFIG_E100 is not set @@ -807,6 +814,7 @@ CONFIG_WLAN=y # CONFIG_USB_KAWETH is not set # CONFIG_USB_PEGASUS is not set # CONFIG_USB_USBNET is not set +# CONFIG_USB_IPHETH is not set # CONFIG_WAN is not set # CONFIG_FDDI is not set # CONFIG_PPP is not set @@ -878,6 +886,7 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set # CONFIG_LEGACY_PTYS is not set @@ -928,6 +937,7 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_SH_MOBILE_SDHI is not set # CONFIG_HTC_PASIC3 is not set # CONFIG_MFD_TMIO is not set +# CONFIG_LPC_SCH is not set # CONFIG_REGULATOR is not set # CONFIG_MEDIA_SUPPORT is not set @@ -935,6 +945,7 @@ CONFIG_SSB_POSSIBLE=y # Graphics support # CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 # CONFIG_DRM is not set # CONFIG_VGASTATE is not set # CONFIG_VIDEO_OUTPUT_CONTROL is not set @@ -1032,6 +1043,7 @@ CONFIG_USB_HID=y # # Special HID drivers # +# CONFIG_HID_3M_PCT is not set CONFIG_HID_A4TECH=y CONFIG_HID_APPLE=y CONFIG_HID_BELKIN=y @@ -1047,14 +1059,19 @@ CONFIG_HID_GYRATION=y CONFIG_HID_LOGITECH=y # CONFIG_LOGITECH_FF is not set # CONFIG_LOGIRUMBLEPAD2_FF is not set +# CONFIG_LOGIG940_FF is not set CONFIG_HID_MICROSOFT=y +# CONFIG_HID_MOSART is not set CONFIG_HID_MONTEREY=y # CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set CONFIG_HID_PANTHERLORD=y # CONFIG_PANTHERLORD_FF is not set CONFIG_HID_PETALYNX=y +# CONFIG_HID_QUANTA is not set CONFIG_HID_SAMSUNG=y CONFIG_HID_SONY=y +# CONFIG_HID_STANTUM is not set CONFIG_HID_SUNPLUS=y # CONFIG_HID_GREENASIA is not set # CONFIG_HID_SMARTJOYPLUS is not set @@ -1148,7 +1165,6 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set -# CONFIG_USB_BERRY_CHARGE is not set # CONFIG_USB_LED is not set # CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set @@ -1161,7 +1177,6 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set # CONFIG_USB_ISIGHTFW is not set -# CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set # @@ -1192,7 +1207,6 @@ CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XIP is not set # CONFIG_EXT3_FS is not set # CONFIG_EXT4_FS is not set -CONFIG_EXT4_USE_FOR_EXT23=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set @@ -1211,6 +1225,7 @@ CONFIG_INOTIFY_USER=y # # Caches # +# CONFIG_FSCACHE is not set # # CD-ROM/DVD Filesystems @@ -1332,6 +1347,7 @@ CONFIG_DEBUG_FS=y CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_MEMORY_INIT is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_LKDTM is not set # CONFIG_LATENCYTOP is not set # CONFIG_SYSCTL_SYSCALL_CHECK is not set CONFIG_HAVE_FUNCTION_TRACER=y @@ -1442,6 +1458,7 @@ CONFIG_CRYPTO=y # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y # CONFIG_CRYPTO_DEV_HIFN_795X is not set +# CONFIG_VIRTUALIZATION is not set # CONFIG_BINARY_PRINTF is not set # diff --git a/arch/sh/configs/sh03_defconfig b/arch/sh/configs/sh03_defconfig index 666fde1..562147d 100644 --- a/arch/sh/configs/sh03_defconfig +++ b/arch/sh/configs/sh03_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 14:41:25 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 17:10:00 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -33,6 +33,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -48,9 +49,11 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -73,7 +76,6 @@ CONFIG_RCU_FANOUT=32 # CONFIG_TREE_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -84,6 +86,7 @@ CONFIG_INITRAMFS_SOURCE="" CONFIG_RD_GZIP=y # CONFIG_RD_BZIP2 is not set # CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_ANON_INODES=y @@ -111,7 +114,6 @@ CONFIG_PERF_USE_VMALLOC=y # Kernel Performance Events And Counters # CONFIG_PERF_EVENTS=y -CONFIG_EVENT_PROFILE=y # CONFIG_PERF_COUNTERS is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_PCI_QUIRKS=y @@ -120,7 +122,6 @@ CONFIG_SLAB=y # CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_PROFILING=y -CONFIG_TRACEPOINTS=y CONFIG_OPROFILE=m CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set @@ -131,6 +132,7 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -250,6 +252,7 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -265,7 +268,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -342,7 +345,6 @@ CONFIG_HZ=250 CONFIG_PREEMPT=y CONFIG_GUSA=y # CONFIG_GUSA_RB is not set -# CONFIG_SPARSE_IRQ is not set # # Boot options @@ -358,9 +360,9 @@ CONFIG_CMDLINE="console=ttySC1,115200 mem=64M root=/dev/nfs" # Bus options # CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y # CONFIG_PCIEPORTBUS is not set # CONFIG_ARCH_SUPPORTS_MSI is not set -CONFIG_PCI_LEGACY=y # CONFIG_PCI_STUB is not set # CONFIG_PCI_IOV is not set # CONFIG_PCCARD is not set @@ -388,7 +390,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -453,7 +454,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # Network testing # # CONFIG_NET_PKTGEN is not set -# CONFIG_NET_DROP_MONITOR is not set # CONFIG_HAMRADIO is not set # CONFIG_CAN is not set # CONFIG_IRDA is not set @@ -574,6 +574,7 @@ CONFIG_IDE_PROC_FS=y # # SCSI device support # +CONFIG_SCSI_MOD=m # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=m CONFIG_SCSI_DMA=y @@ -664,7 +665,7 @@ CONFIG_SCSI_LOWLEVEL=y # # -# See the help texts for more information. +# The newer stack is recommended. # # CONFIG_FIREWIRE is not set # CONFIG_IEEE1394 is not set @@ -704,6 +705,7 @@ CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set # CONFIG_AMD8111_ETH is not set # CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_KSZ884X_PCI is not set # CONFIG_B44 is not set # CONFIG_FORCEDETH is not set # CONFIG_E100 is not set @@ -751,6 +753,8 @@ CONFIG_NETDEV_10000=y # CONFIG_CHELSIO_T1 is not set CONFIG_CHELSIO_T3_DEPENDS=y # CONFIG_CHELSIO_T3 is not set +CONFIG_CHELSIO_T4_DEPENDS=y +# CONFIG_CHELSIO_T4 is not set # CONFIG_ENIC is not set # CONFIG_IXGBE is not set # CONFIG_IXGB is not set @@ -763,6 +767,7 @@ CONFIG_CHELSIO_T3_DEPENDS=y # CONFIG_MLX4_CORE is not set # CONFIG_TEHUTI is not set # CONFIG_BNX2X is not set +# CONFIG_QLCNIC is not set # CONFIG_QLGE is not set # CONFIG_SFC is not set # CONFIG_BE2NET is not set @@ -853,6 +858,7 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y @@ -927,6 +933,7 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_SH_MOBILE_SDHI is not set # CONFIG_HTC_PASIC3 is not set # CONFIG_MFD_TMIO is not set +# CONFIG_LPC_SCH is not set # CONFIG_REGULATOR is not set # CONFIG_MEDIA_SUPPORT is not set @@ -934,6 +941,7 @@ CONFIG_SSB_POSSIBLE=y # Graphics support # CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 # CONFIG_DRM is not set # CONFIG_VGASTATE is not set # CONFIG_VIDEO_OUTPUT_CONTROL is not set @@ -1075,6 +1083,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set +# CONFIG_LOGFS is not set # CONFIG_CRAMFS is not set # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -1105,6 +1114,7 @@ CONFIG_SUNRPC_GSS=y CONFIG_RPCSEC_GSS_KRB5=y # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1187,13 +1197,12 @@ CONFIG_FRAME_WARN=1024 CONFIG_DEBUG_FS=y # CONFIG_HEADERS_CHECK is not set # CONFIG_DEBUG_KERNEL is not set -CONFIG_STACKTRACE=y CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_MEMORY_INIT is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_LKDTM is not set # CONFIG_LATENCYTOP is not set # CONFIG_SYSCTL_SYSCALL_CHECK is not set -CONFIG_NOP_TRACER=y CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y @@ -1201,10 +1210,7 @@ CONFIG_HAVE_DYNAMIC_FTRACE=y CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y CONFIG_HAVE_SYSCALL_TRACEPOINTS=y CONFIG_RING_BUFFER=y -CONFIG_EVENT_TRACING=y -CONFIG_CONTEXT_SWITCH_TRACER=y CONFIG_RING_BUFFER_ALLOW_SWAP=y -CONFIG_TRACING=y CONFIG_TRACING_SUPPORT=y # CONFIG_FTRACE is not set # CONFIG_DYNAMIC_DEBUG is not set @@ -1323,7 +1329,8 @@ CONFIG_CRYPTO_DEFLATE=y # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y # CONFIG_CRYPTO_DEV_HIFN_795X is not set -CONFIG_BINARY_PRINTF=y +# CONFIG_VIRTUALIZATION is not set +# CONFIG_BINARY_PRINTF is not set # # Library routines diff --git a/arch/sh/configs/sh7710voipgw_defconfig b/arch/sh/configs/sh7710voipgw_defconfig index 35a3bee..98485ca4 100644 --- a/arch/sh/configs/sh7710voipgw_defconfig +++ b/arch/sh/configs/sh7710voipgw_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 14:43:04 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 17:14:59 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -30,6 +30,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -44,9 +45,11 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set # CONFIG_SWAP is not set CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -68,11 +71,6 @@ CONFIG_RCU_FANOUT=32 # CONFIG_TREE_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 -CONFIG_GROUP_SCHED=y -CONFIG_FAIR_GROUP_SCHED=y -# CONFIG_RT_GROUP_SCHED is not set -CONFIG_USER_SCHED=y -# CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -105,7 +103,7 @@ CONFIG_PERF_USE_VMALLOC=y # # Kernel Performance Events And Counters # -# CONFIG_PERF_EVENTS is not set +CONFIG_PERF_EVENTS=y # CONFIG_PERF_COUNTERS is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_COMPAT_BRK=y @@ -122,6 +120,7 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -240,6 +239,7 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -255,7 +255,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -331,7 +331,6 @@ CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT is not set CONFIG_GUSA=y # CONFIG_GUSA_RB is not set -# CONFIG_SPARSE_IRQ is not set # # Boot options @@ -367,7 +366,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -620,6 +618,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set # CONFIG_SCSI_DMA is not set @@ -723,6 +722,7 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=2 CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set # CONFIG_UNIX98_PTYS is not set CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 @@ -824,7 +824,6 @@ CONFIG_RTC_LIB=y # CONFIG_EXT2_FS is not set # CONFIG_EXT3_FS is not set # CONFIG_EXT4_FS is not set -CONFIG_EXT4_USE_FOR_EXT23=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set @@ -890,6 +889,7 @@ CONFIG_JFFS2_ZLIB=y # CONFIG_JFFS2_LZO is not set CONFIG_JFFS2_RTIME=y # CONFIG_JFFS2_RUBIN is not set +# CONFIG_LOGFS is not set # CONFIG_CRAMFS is not set # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -904,6 +904,7 @@ CONFIG_NETWORK_FILESYSTEMS=y # CONFIG_NFS_FS is not set # CONFIG_NFSD is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -934,6 +935,7 @@ CONFIG_DEBUG_FS=y CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_MEMORY_INIT is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_LKDTM is not set # CONFIG_LATENCYTOP is not set # CONFIG_SYSCTL_SYSCALL_CHECK is not set CONFIG_HAVE_FUNCTION_TRACER=y @@ -1049,6 +1051,7 @@ CONFIG_CRYPTO=y # # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y +# CONFIG_VIRTUALIZATION is not set # CONFIG_BINARY_PRINTF is not set # diff --git a/arch/sh/configs/sh7724_generic_defconfig b/arch/sh/configs/sh7724_generic_defconfig index a3056b6..a6a9e68 100644 --- a/arch/sh/configs/sh7724_generic_defconfig +++ b/arch/sh/configs/sh7724_generic_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 15:03:45 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 17:17:36 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -32,6 +32,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -46,9 +47,11 @@ CONFIG_LOCALVERSION="" CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set @@ -65,11 +68,6 @@ CONFIG_RCU_FANOUT=32 # CONFIG_TREE_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=17 -CONFIG_GROUP_SCHED=y -CONFIG_FAIR_GROUP_SCHED=y -CONFIG_RT_GROUP_SCHED=y -CONFIG_USER_SCHED=y -# CONFIG_CGROUP_SCHED is not set CONFIG_CGROUPS=y # CONFIG_CGROUP_DEBUG is not set # CONFIG_CGROUP_NS is not set @@ -78,6 +76,7 @@ CONFIG_CGROUPS=y # CONFIG_CPUSETS is not set # CONFIG_CGROUP_CPUACCT is not set # CONFIG_RESOURCE_COUNTERS is not set +# CONFIG_CGROUP_SCHED is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set # CONFIG_BLK_DEV_INITRD is not set @@ -106,7 +105,6 @@ CONFIG_PERF_USE_VMALLOC=y # Kernel Performance Events And Counters # CONFIG_PERF_EVENTS=y -CONFIG_EVENT_PROFILE=y # CONFIG_PERF_COUNTERS is not set CONFIG_VM_EVENT_COUNTERS=y # CONFIG_COMPAT_BRK is not set @@ -114,21 +112,19 @@ CONFIG_VM_EVENT_COUNTERS=y CONFIG_SLUB=y # CONFIG_SLOB is not set CONFIG_PROFILING=y -CONFIG_TRACEPOINTS=y CONFIG_OPROFILE=y CONFIG_HAVE_OPROFILE=y -CONFIG_HAVE_IOREMAP_PROT=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling # -# CONFIG_GCOV_KERNEL is not set # CONFIG_SLOW_WORK is not set CONFIG_HAVE_GENERIC_DMA_COHERENT=y CONFIG_RT_MUTEXES=y @@ -138,7 +134,6 @@ CONFIG_BLOCK=y CONFIG_LBDAF=y # CONFIG_BLK_DEV_BSG is not set # CONFIG_BLK_DEV_INTEGRITY is not set -# CONFIG_BLK_CGROUP is not set # # IO Schedulers @@ -235,8 +230,8 @@ CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_MEMORY_START=0x08000000 CONFIG_MEMORY_SIZE=0x04000000 CONFIG_29BIT=y -# CONFIG_PMB_ENABLE is not set -# CONFIG_X2TLB is not set +# CONFIG_PMB is not set +CONFIG_X2TLB=y CONFIG_VSYSCALL=y CONFIG_ARCH_FLATMEM_ENABLE=y CONFIG_ARCH_SPARSEMEM_ENABLE=y @@ -246,6 +241,8 @@ CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y +CONFIG_IOREMAP_FIXED=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -262,7 +259,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_MIGRATION=y # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -353,7 +350,7 @@ CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set CONFIG_GUSA=y -# CONFIG_SPARSE_IRQ is not set +# CONFIG_INTC_USERIMASK is not set # # Boot options @@ -390,6 +387,7 @@ CONFIG_HIBERNATION_NVS=y CONFIG_HIBERNATION=y CONFIG_PM_STD_PARTITION="" CONFIG_PM_RUNTIME=y +CONFIG_PM_OPS=y CONFIG_CPU_IDLE=y CONFIG_CPU_IDLE_GOV_LADDER=y CONFIG_CPU_IDLE_GOV_MENU=y @@ -428,6 +426,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set # CONFIG_SCSI_DMA is not set @@ -467,6 +466,7 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=6 CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set # CONFIG_UNIX98_PTYS is not set # CONFIG_LEGACY_PTYS is not set # CONFIG_IPMI_HANDLER is not set @@ -491,6 +491,7 @@ CONFIG_I2C_HELPER_AUTO=y # CONFIG_I2C_OCORES is not set CONFIG_I2C_SH_MOBILE=y # CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set # # External I2C/SMBus adapter drivers @@ -502,15 +503,9 @@ CONFIG_I2C_SH_MOBILE=y # Other I2C/SMBus bus drivers # # CONFIG_I2C_PCA_PLATFORM is not set - -# -# Miscellaneous I2C Chip support -# -# CONFIG_SENSORS_TSL2550 is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set # CONFIG_SPI is not set # @@ -533,6 +528,7 @@ CONFIG_SSB_POSSIBLE=y # Multifunction device drivers # # CONFIG_MFD_CORE is not set +# CONFIG_MFD_88PM860X is not set # CONFIG_MFD_SM501 is not set # CONFIG_MFD_SH_MOBILE_SDHI is not set # CONFIG_HTC_PASIC3 is not set @@ -540,12 +536,13 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_TMIO is not set # CONFIG_PMIC_DA903X is not set # CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X is not set # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set # CONFIG_MFD_PCF50633 is not set # CONFIG_AB3100_CORE is not set -# CONFIG_MFD_88PM8607 is not set # CONFIG_REGULATOR is not set # CONFIG_MEDIA_SUPPORT is not set @@ -629,8 +626,6 @@ CONFIG_RTC_DRV_SH=y CONFIG_UIO=y # CONFIG_UIO_PDRV is not set CONFIG_UIO_PDRV_GENIRQ=y -# CONFIG_UIO_SMX is not set -# CONFIG_UIO_SERCOS3 is not set # # TI VLYNQ @@ -643,7 +638,6 @@ CONFIG_UIO_PDRV_GENIRQ=y # CONFIG_EXT2_FS is not set # CONFIG_EXT3_FS is not set # CONFIG_EXT4_FS is not set -CONFIG_EXT4_USE_FOR_EXT23=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set @@ -707,15 +701,12 @@ CONFIG_FRAME_WARN=1024 # CONFIG_MAGIC_SYSRQ is not set # CONFIG_STRIP_ASM_SYMS is not set # CONFIG_UNUSED_SYMBOLS is not set -CONFIG_DEBUG_FS=y # CONFIG_HEADERS_CHECK is not set # CONFIG_DEBUG_KERNEL is not set -CONFIG_STACKTRACE=y CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_MEMORY_INIT is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set # CONFIG_LATENCYTOP is not set -CONFIG_NOP_TRACER=y CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y @@ -723,13 +714,9 @@ CONFIG_HAVE_DYNAMIC_FTRACE=y CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y CONFIG_HAVE_SYSCALL_TRACEPOINTS=y CONFIG_RING_BUFFER=y -CONFIG_EVENT_TRACING=y -CONFIG_CONTEXT_SWITCH_TRACER=y CONFIG_RING_BUFFER_ALLOW_SWAP=y -CONFIG_TRACING=y CONFIG_TRACING_SUPPORT=y # CONFIG_FTRACE is not set -# CONFIG_DYNAMIC_DEBUG is not set # CONFIG_DMA_API_DEBUG is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y @@ -747,7 +734,8 @@ CONFIG_HAVE_ARCH_KGDB=y CONFIG_DEFAULT_SECURITY_DAC=y CONFIG_DEFAULT_SECURITY="" # CONFIG_CRYPTO is not set -CONFIG_BINARY_PRINTF=y +# CONFIG_VIRTUALIZATION is not set +# CONFIG_BINARY_PRINTF is not set # # Library routines diff --git a/arch/sh/configs/sh7763rdp_defconfig b/arch/sh/configs/sh7763rdp_defconfig index 04b841b..6f308b7 100644 --- a/arch/sh/configs/sh7763rdp_defconfig +++ b/arch/sh/configs/sh7763rdp_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 15:05:29 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 17:19:21 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -31,6 +31,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -45,9 +46,11 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -69,11 +72,6 @@ CONFIG_RCU_FANOUT=32 CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 -CONFIG_GROUP_SCHED=y -CONFIG_FAIR_GROUP_SCHED=y -# CONFIG_RT_GROUP_SCHED is not set -CONFIG_USER_SCHED=y -# CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -112,7 +110,6 @@ CONFIG_PERF_USE_VMALLOC=y # Kernel Performance Events And Counters # CONFIG_PERF_EVENTS=y -CONFIG_EVENT_PROFILE=y # CONFIG_PERF_COUNTERS is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_COMPAT_BRK=y @@ -120,7 +117,6 @@ CONFIG_SLAB=y # CONFIG_SLUB is not set # CONFIG_SLOB is not set CONFIG_PROFILING=y -CONFIG_TRACEPOINTS=y CONFIG_OPROFILE=y CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set @@ -131,6 +127,7 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -243,7 +240,7 @@ CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_MEMORY_START=0x0c000000 CONFIG_MEMORY_SIZE=0x04000000 CONFIG_29BIT=y -# CONFIG_PMB_ENABLE is not set +# CONFIG_PMB is not set CONFIG_VSYSCALL=y CONFIG_ARCH_FLATMEM_ENABLE=y CONFIG_ARCH_SPARSEMEM_ENABLE=y @@ -253,6 +250,7 @@ CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -269,7 +267,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_MIGRATION=y # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -344,7 +342,7 @@ CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set CONFIG_GUSA=y -# CONFIG_SPARSE_IRQ is not set +# CONFIG_INTC_USERIMASK is not set # # Boot options @@ -381,7 +379,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -444,7 +441,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # Network testing # # CONFIG_NET_PKTGEN is not set -# CONFIG_NET_DROP_MONITOR is not set # CONFIG_HAMRADIO is not set # CONFIG_CAN is not set # CONFIG_IRDA is not set @@ -585,6 +581,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y @@ -689,6 +686,7 @@ CONFIG_WLAN=y # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set # CONFIG_USB_USBNET is not set +# CONFIG_USB_IPHETH is not set # CONFIG_WAN is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -754,6 +752,7 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=3 CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y @@ -945,7 +944,6 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set -# CONFIG_USB_BERRY_CHARGE is not set # CONFIG_USB_LED is not set # CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set @@ -957,7 +955,6 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set # CONFIG_USB_ISIGHTFW is not set -# CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set # @@ -980,9 +977,6 @@ CONFIG_MMC_BLOCK_BOUNCE=y # MMC/SD/SDIO Host Controller Drivers # # CONFIG_MMC_SDHCI is not set -# CONFIG_MMC_AT91 is not set -# CONFIG_MMC_ATMELMCI is not set -# CONFIG_MMC_TMIO is not set # CONFIG_MEMSTICK is not set # CONFIG_NEW_LEDS is not set # CONFIG_ACCESSIBILITY is not set @@ -1074,6 +1068,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set # CONFIG_JFFS2_FS is not set +# CONFIG_LOGFS is not set # CONFIG_CRAMFS is not set # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -1096,6 +1091,7 @@ CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1162,13 +1158,12 @@ CONFIG_FRAME_WARN=1024 CONFIG_DEBUG_FS=y # CONFIG_HEADERS_CHECK is not set # CONFIG_DEBUG_KERNEL is not set -CONFIG_STACKTRACE=y CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_MEMORY_INIT is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_LKDTM is not set # CONFIG_LATENCYTOP is not set # CONFIG_SYSCTL_SYSCALL_CHECK is not set -CONFIG_NOP_TRACER=y CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y @@ -1176,10 +1171,7 @@ CONFIG_HAVE_DYNAMIC_FTRACE=y CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y CONFIG_HAVE_SYSCALL_TRACEPOINTS=y CONFIG_RING_BUFFER=y -CONFIG_EVENT_TRACING=y -CONFIG_CONTEXT_SWITCH_TRACER=y CONFIG_RING_BUFFER_ALLOW_SWAP=y -CONFIG_TRACING=y CONFIG_TRACING_SUPPORT=y # CONFIG_FTRACE is not set # CONFIG_DYNAMIC_DEBUG is not set @@ -1287,7 +1279,8 @@ CONFIG_CRYPTO=y # # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y -CONFIG_BINARY_PRINTF=y +# CONFIG_VIRTUALIZATION is not set +# CONFIG_BINARY_PRINTF is not set # # Library routines diff --git a/arch/sh/configs/sh7770_generic_defconfig b/arch/sh/configs/sh7770_generic_defconfig index 7b24705..4327f89 100644 --- a/arch/sh/configs/sh7770_generic_defconfig +++ b/arch/sh/configs/sh7770_generic_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 15:06:28 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 17:20:25 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -31,6 +31,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -45,9 +46,11 @@ CONFIG_LOCALVERSION="" CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set @@ -64,11 +67,6 @@ CONFIG_RCU_FANOUT=32 # CONFIG_TREE_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=17 -CONFIG_GROUP_SCHED=y -CONFIG_FAIR_GROUP_SCHED=y -CONFIG_RT_GROUP_SCHED=y -CONFIG_USER_SCHED=y -# CONFIG_CGROUP_SCHED is not set CONFIG_CGROUPS=y # CONFIG_CGROUP_DEBUG is not set # CONFIG_CGROUP_NS is not set @@ -77,6 +75,7 @@ CONFIG_CGROUPS=y # CONFIG_CPUSETS is not set # CONFIG_CGROUP_CPUACCT is not set # CONFIG_RESOURCE_COUNTERS is not set +# CONFIG_CGROUP_SCHED is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set # CONFIG_BLK_DEV_INITRD is not set @@ -105,7 +104,6 @@ CONFIG_PERF_USE_VMALLOC=y # Kernel Performance Events And Counters # CONFIG_PERF_EVENTS=y -CONFIG_EVENT_PROFILE=y # CONFIG_PERF_COUNTERS is not set CONFIG_VM_EVENT_COUNTERS=y # CONFIG_COMPAT_BRK is not set @@ -113,7 +111,6 @@ CONFIG_VM_EVENT_COUNTERS=y CONFIG_SLUB=y # CONFIG_SLOB is not set CONFIG_PROFILING=y -CONFIG_TRACEPOINTS=y CONFIG_OPROFILE=y CONFIG_HAVE_OPROFILE=y CONFIG_HAVE_IOREMAP_PROT=y @@ -123,11 +120,11 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling # -# CONFIG_GCOV_KERNEL is not set # CONFIG_SLOW_WORK is not set CONFIG_HAVE_GENERIC_DMA_COHERENT=y CONFIG_RT_MUTEXES=y @@ -137,7 +134,6 @@ CONFIG_BLOCK=y CONFIG_LBDAF=y # CONFIG_BLK_DEV_BSG is not set # CONFIG_BLK_DEV_INTEGRITY is not set -# CONFIG_BLK_CGROUP is not set # # IO Schedulers @@ -232,7 +228,7 @@ CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_MEMORY_START=0x08000000 CONFIG_MEMORY_SIZE=0x04000000 CONFIG_29BIT=y -# CONFIG_PMB_ENABLE is not set +# CONFIG_PMB is not set CONFIG_VSYSCALL=y CONFIG_ARCH_FLATMEM_ENABLE=y CONFIG_ARCH_SPARSEMEM_ENABLE=y @@ -242,6 +238,7 @@ CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -258,7 +255,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_MIGRATION=y # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -347,7 +344,7 @@ CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set CONFIG_GUSA=y -# CONFIG_SPARSE_IRQ is not set +# CONFIG_INTC_USERIMASK is not set # # Boot options @@ -382,6 +379,7 @@ CONFIG_HIBERNATION_NVS=y CONFIG_HIBERNATION=y CONFIG_PM_STD_PARTITION="" # CONFIG_PM_RUNTIME is not set +CONFIG_PM_OPS=y CONFIG_CPU_IDLE=y CONFIG_CPU_IDLE_GOV_LADDER=y CONFIG_CPU_IDLE_GOV_MENU=y @@ -420,6 +418,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set # CONFIG_SCSI_DMA is not set @@ -459,6 +458,7 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=6 CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set # CONFIG_UNIX98_PTYS is not set # CONFIG_LEGACY_PTYS is not set # CONFIG_IPMI_HANDLER is not set @@ -483,6 +483,7 @@ CONFIG_I2C_HELPER_AUTO=y # CONFIG_I2C_OCORES is not set CONFIG_I2C_SH_MOBILE=y # CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set # # External I2C/SMBus adapter drivers @@ -494,15 +495,9 @@ CONFIG_I2C_SH_MOBILE=y # Other I2C/SMBus bus drivers # # CONFIG_I2C_PCA_PLATFORM is not set - -# -# Miscellaneous I2C Chip support -# -# CONFIG_SENSORS_TSL2550 is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set # CONFIG_SPI is not set # @@ -525,6 +520,7 @@ CONFIG_SSB_POSSIBLE=y # Multifunction device drivers # # CONFIG_MFD_CORE is not set +# CONFIG_MFD_88PM860X is not set # CONFIG_MFD_SM501 is not set # CONFIG_MFD_SH_MOBILE_SDHI is not set # CONFIG_HTC_PASIC3 is not set @@ -532,12 +528,13 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_TMIO is not set # CONFIG_PMIC_DA903X is not set # CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X is not set # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set # CONFIG_MFD_PCF50633 is not set # CONFIG_AB3100_CORE is not set -# CONFIG_MFD_88PM8607 is not set # CONFIG_REGULATOR is not set # CONFIG_MEDIA_SUPPORT is not set @@ -621,8 +618,6 @@ CONFIG_RTC_DRV_SH=y CONFIG_UIO=y # CONFIG_UIO_PDRV is not set CONFIG_UIO_PDRV_GENIRQ=y -# CONFIG_UIO_SMX is not set -# CONFIG_UIO_SERCOS3 is not set # # TI VLYNQ @@ -635,7 +630,6 @@ CONFIG_UIO_PDRV_GENIRQ=y # CONFIG_EXT2_FS is not set # CONFIG_EXT3_FS is not set # CONFIG_EXT4_FS is not set -CONFIG_EXT4_USE_FOR_EXT23=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set @@ -699,15 +693,12 @@ CONFIG_FRAME_WARN=1024 # CONFIG_MAGIC_SYSRQ is not set # CONFIG_STRIP_ASM_SYMS is not set # CONFIG_UNUSED_SYMBOLS is not set -CONFIG_DEBUG_FS=y # CONFIG_HEADERS_CHECK is not set # CONFIG_DEBUG_KERNEL is not set -CONFIG_STACKTRACE=y CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_MEMORY_INIT is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set # CONFIG_LATENCYTOP is not set -CONFIG_NOP_TRACER=y CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y @@ -715,13 +706,9 @@ CONFIG_HAVE_DYNAMIC_FTRACE=y CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y CONFIG_HAVE_SYSCALL_TRACEPOINTS=y CONFIG_RING_BUFFER=y -CONFIG_EVENT_TRACING=y -CONFIG_CONTEXT_SWITCH_TRACER=y CONFIG_RING_BUFFER_ALLOW_SWAP=y -CONFIG_TRACING=y CONFIG_TRACING_SUPPORT=y # CONFIG_FTRACE is not set -# CONFIG_DYNAMIC_DEBUG is not set # CONFIG_DMA_API_DEBUG is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y @@ -739,7 +726,8 @@ CONFIG_HAVE_ARCH_KGDB=y CONFIG_DEFAULT_SECURITY_DAC=y CONFIG_DEFAULT_SECURITY="" # CONFIG_CRYPTO is not set -CONFIG_BINARY_PRINTF=y +# CONFIG_VIRTUALIZATION is not set +# CONFIG_BINARY_PRINTF is not set # # Library routines diff --git a/arch/sh/configs/sh7785lcr_32bit_defconfig b/arch/sh/configs/sh7785lcr_32bit_defconfig index 8330813..e9af616 100644 --- a/arch/sh/configs/sh7785lcr_32bit_defconfig +++ b/arch/sh/configs/sh7785lcr_32bit_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 15:07:40 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 17:22:09 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -33,6 +33,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -48,9 +49,11 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -74,11 +77,6 @@ CONFIG_RCU_FANOUT=32 CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 -CONFIG_GROUP_SCHED=y -CONFIG_FAIR_GROUP_SCHED=y -# CONFIG_RT_GROUP_SCHED is not set -CONFIG_USER_SCHED=y -# CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUPS is not set # CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set @@ -112,7 +110,6 @@ CONFIG_PERF_USE_VMALLOC=y # Kernel Performance Events And Counters # CONFIG_PERF_EVENTS=y -CONFIG_EVENT_PROFILE=y CONFIG_PERF_COUNTERS=y CONFIG_VM_EVENT_COUNTERS=y CONFIG_PCI_QUIRKS=y @@ -126,13 +123,13 @@ CONFIG_OPROFILE=y CONFIG_HAVE_OPROFILE=y CONFIG_KPROBES=y CONFIG_KRETPROBES=y -CONFIG_HAVE_IOREMAP_PROT=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -246,12 +243,9 @@ CONFIG_PAGE_OFFSET=0x80000000 CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_MEMORY_START=0x40000000 CONFIG_MEMORY_SIZE=0x20000000 -# CONFIG_29BIT is not set -CONFIG_32BIT=y -CONFIG_PMB_ENABLE=y +CONFIG_29BIT=y # CONFIG_PMB is not set -CONFIG_PMB_FIXED=y -# CONFIG_X2TLB is not set +CONFIG_X2TLB=y CONFIG_VSYSCALL=y # CONFIG_NUMA is not set CONFIG_ARCH_FLATMEM_ENABLE=y @@ -262,6 +256,8 @@ CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y +CONFIG_IOREMAP_FIXED=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -284,7 +280,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_MIGRATION=y # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -302,6 +298,7 @@ CONFIG_CPU_LITTLE_ENDIAN=y # CONFIG_CPU_BIG_ENDIAN is not set CONFIG_SH_FPU=y CONFIG_SH_STORE_QUEUES=y +# CONFIG_SPECULATIVE_EXECUTION is not set CONFIG_CPU_HAS_INTEVT=y CONFIG_CPU_HAS_SR_RB=y CONFIG_CPU_HAS_FPU=y @@ -311,7 +308,7 @@ CONFIG_CPU_HAS_FPU=y # # CONFIG_SH_HIGHLANDER is not set CONFIG_SH_SH7785LCR=y -# CONFIG_SH_SH7785LCR_PT is not set +CONFIG_SH_SH7785LCR_29BIT_PHYSMAPS=y # # Timer and clock configuration @@ -374,7 +371,7 @@ CONFIG_SECCOMP=y # CONFIG_PREEMPT_VOLUNTARY is not set CONFIG_PREEMPT=y CONFIG_GUSA=y -CONFIG_SPARSE_IRQ=y +# CONFIG_INTC_USERIMASK is not set # # Boot options @@ -389,9 +386,9 @@ CONFIG_ENTRY_OFFSET=0x00001000 # Bus options # CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y # CONFIG_PCIEPORTBUS is not set # CONFIG_ARCH_SUPPORTS_MSI is not set -# CONFIG_PCI_LEGACY is not set # CONFIG_PCI_STUB is not set # CONFIG_PCI_IOV is not set # CONFIG_PCCARD is not set @@ -421,7 +418,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -633,6 +629,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y @@ -706,6 +703,7 @@ CONFIG_SATA_SIL=y # CONFIG_PATA_IT821X is not set # CONFIG_PATA_IT8213 is not set # CONFIG_PATA_JMICRON is not set +# CONFIG_PATA_LEGACY is not set # CONFIG_PATA_TRIFLEX is not set # CONFIG_PATA_MARVELL is not set # CONFIG_PATA_MPIIX is not set @@ -742,7 +740,7 @@ CONFIG_SATA_SIL=y # # -# See the help texts for more information. +# The newer stack is recommended. # # CONFIG_FIREWIRE is not set # CONFIG_IEEE1394 is not set @@ -797,6 +795,7 @@ CONFIG_R8169=y # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set # CONFIG_USB_USBNET is not set +# CONFIG_USB_IPHETH is not set # CONFIG_WAN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set @@ -901,6 +900,7 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y CONFIG_DEVPTS_MULTIPLE_INSTANCES=y # CONFIG_LEGACY_PTYS is not set @@ -947,6 +947,7 @@ CONFIG_I2C_ALGOPCA=y # CONFIG_I2C_OCORES is not set # CONFIG_I2C_SH_MOBILE is not set # CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set # # External I2C/SMBus adapter drivers @@ -960,15 +961,9 @@ CONFIG_I2C_ALGOPCA=y # CONFIG_I2C_PCA_PLATFORM=y # CONFIG_I2C_STUB is not set - -# -# Miscellaneous I2C Chip support -# -# CONFIG_SENSORS_TSL2550 is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set # CONFIG_SPI is not set # @@ -1011,6 +1006,7 @@ CONFIG_SSB_POSSIBLE=y # Multifunction device drivers # # CONFIG_MFD_CORE is not set +# CONFIG_MFD_88PM860X is not set CONFIG_MFD_SM501=y # CONFIG_MFD_SH_MOBILE_SDHI is not set # CONFIG_HTC_PASIC3 is not set @@ -1018,12 +1014,14 @@ CONFIG_MFD_SM501=y # CONFIG_MFD_TMIO is not set # CONFIG_PMIC_DA903X is not set # CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X is not set # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set # CONFIG_MFD_PCF50633 is not set # CONFIG_AB3100_CORE is not set -# CONFIG_MFD_88PM8607 is not set +# CONFIG_LPC_SCH is not set # CONFIG_REGULATOR is not set # CONFIG_MEDIA_SUPPORT is not set @@ -1209,6 +1207,7 @@ CONFIG_SND_CMIPCI=y # CONFIG_SND_SUPERH is not set CONFIG_SND_USB=y # CONFIG_SND_USB_AUDIO is not set +# CONFIG_SND_USB_UA101 is not set # CONFIG_SND_USB_CAIAQ is not set # CONFIG_SND_SOC is not set # CONFIG_SOUND_PRIME is not set @@ -1226,6 +1225,7 @@ CONFIG_USB_HID=y # # Special HID drivers # +# CONFIG_HID_3M_PCT is not set CONFIG_HID_A4TECH=m CONFIG_HID_APPLE=m CONFIG_HID_BELKIN=m @@ -1242,14 +1242,19 @@ CONFIG_HID_KENSINGTON=m CONFIG_HID_LOGITECH=m # CONFIG_LOGITECH_FF is not set # CONFIG_LOGIRUMBLEPAD2_FF is not set +# CONFIG_LOGIG940_FF is not set CONFIG_HID_MICROSOFT=m +# CONFIG_HID_MOSART is not set CONFIG_HID_MONTEREY=m CONFIG_HID_NTRIG=m +# CONFIG_HID_ORTEK is not set CONFIG_HID_PANTHERLORD=m # CONFIG_PANTHERLORD_FF is not set CONFIG_HID_PETALYNX=m +# CONFIG_HID_QUANTA is not set CONFIG_HID_SAMSUNG=m CONFIG_HID_SONY=m +# CONFIG_HID_STANTUM is not set CONFIG_HID_SUNPLUS=m CONFIG_HID_GREENASIA=m # CONFIG_GREENASIA_FF is not set @@ -1273,7 +1278,6 @@ CONFIG_USB=y # CONFIG_USB_DEVICEFS is not set CONFIG_USB_DEVICE_CLASS=y # CONFIG_USB_DYNAMIC_MINORS is not set -# CONFIG_USB_SUSPEND is not set # CONFIG_USB_OTG is not set # CONFIG_USB_OTG_WHITELIST is not set # CONFIG_USB_OTG_BLACKLIST_HUB is not set @@ -1351,7 +1355,6 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set -# CONFIG_USB_BERRY_CHARGE is not set # CONFIG_USB_LED is not set # CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set @@ -1364,7 +1367,6 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set # CONFIG_USB_ISIGHTFW is not set -# CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set # @@ -1390,10 +1392,7 @@ CONFIG_MMC_BLOCK_BOUNCE=y CONFIG_MMC_SDHCI=m # CONFIG_MMC_SDHCI_PCI is not set CONFIG_MMC_SDHCI_PLTFM=m -# CONFIG_MMC_AT91 is not set -# CONFIG_MMC_ATMELMCI is not set # CONFIG_MMC_TIFM_SD is not set -# CONFIG_MMC_TMIO is not set # CONFIG_MMC_CB710 is not set # CONFIG_MMC_VIA_SDMMC is not set # CONFIG_MEMSTICK is not set @@ -1460,6 +1459,7 @@ CONFIG_RTC_DRV_RS5C372=y # CONFIG_RTC_DRV_SH is not set # CONFIG_RTC_DRV_GENERIC is not set CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set # # DMA Devices @@ -1469,10 +1469,10 @@ CONFIG_UIO=m # CONFIG_UIO_CIF is not set # CONFIG_UIO_PDRV is not set # CONFIG_UIO_PDRV_GENIRQ is not set -# CONFIG_UIO_SMX is not set # CONFIG_UIO_AEC is not set # CONFIG_UIO_SERCOS3 is not set # CONFIG_UIO_PCI_GENERIC is not set +# CONFIG_UIO_NETX is not set # # TI VLYNQ @@ -1556,6 +1556,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set # CONFIG_JFFS2_FS is not set +# CONFIG_LOGFS is not set # CONFIG_CRAMFS is not set # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -1586,6 +1587,7 @@ CONFIG_SUNRPC_GSS=y CONFIG_RPCSEC_GSS_KRB5=y # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1660,6 +1662,7 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_MEMORY_INIT is not set CONFIG_FRAME_POINTER=y # CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_LKDTM is not set CONFIG_LATENCYTOP=y CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_NOP_TRACER=y @@ -1690,6 +1693,7 @@ CONFIG_SCHED_TRACER=y CONFIG_BRANCH_PROFILE_NONE=y # CONFIG_PROFILE_ANNOTATED_BRANCHES is not set # CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_KSYM_TRACER is not set CONFIG_STACK_TRACER=y CONFIG_KMEMTRACE=y CONFIG_WORKQUEUE_TRACER=y @@ -1815,6 +1819,7 @@ CONFIG_CRYPTO_DES=y # # CONFIG_CRYPTO_ANSI_CPRNG is not set # CONFIG_CRYPTO_HW is not set +# CONFIG_VIRTUALIZATION is not set CONFIG_BINARY_PRINTF=y # diff --git a/arch/sh/configs/sh7785lcr_defconfig b/arch/sh/configs/sh7785lcr_defconfig index f196e87..30f38c2 100644 --- a/arch/sh/configs/sh7785lcr_defconfig +++ b/arch/sh/configs/sh7785lcr_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 15:09:09 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 17:27:53 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -33,6 +33,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -48,9 +49,11 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -73,11 +76,6 @@ CONFIG_RCU_FANOUT=32 CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 -CONFIG_GROUP_SCHED=y -CONFIG_FAIR_GROUP_SCHED=y -# CONFIG_RT_GROUP_SCHED is not set -CONFIG_USER_SCHED=y -# CONFIG_CGROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -124,13 +122,13 @@ CONFIG_PROFILING=y # CONFIG_OPROFILE is not set CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set -CONFIG_HAVE_IOREMAP_PROT=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -244,8 +242,8 @@ CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_MEMORY_START=0x08000000 CONFIG_MEMORY_SIZE=0x08000000 CONFIG_29BIT=y -# CONFIG_PMB_ENABLE is not set -# CONFIG_X2TLB is not set +# CONFIG_PMB is not set +CONFIG_X2TLB=y CONFIG_VSYSCALL=y # CONFIG_NUMA is not set CONFIG_ARCH_FLATMEM_ENABLE=y @@ -254,6 +252,8 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_IOREMAP_FIXED=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -269,7 +269,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -287,6 +287,7 @@ CONFIG_CPU_LITTLE_ENDIAN=y # CONFIG_CPU_BIG_ENDIAN is not set CONFIG_SH_FPU=y CONFIG_SH_STORE_QUEUES=y +# CONFIG_SPECULATIVE_EXECUTION is not set CONFIG_CPU_HAS_INTEVT=y CONFIG_CPU_HAS_SR_RB=y CONFIG_CPU_HAS_FPU=y @@ -344,7 +345,7 @@ CONFIG_KEXEC=y # CONFIG_PREEMPT_VOLUNTARY is not set CONFIG_PREEMPT=y CONFIG_GUSA=y -# CONFIG_SPARSE_IRQ is not set +# CONFIG_INTC_USERIMASK is not set # # Boot options @@ -359,9 +360,9 @@ CONFIG_ENTRY_OFFSET=0x00001000 # Bus options # CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y # CONFIG_PCIEPORTBUS is not set # CONFIG_ARCH_SUPPORTS_MSI is not set -CONFIG_PCI_LEGACY=y # CONFIG_PCI_DEBUG is not set # CONFIG_PCI_STUB is not set # CONFIG_PCI_IOV is not set @@ -387,7 +388,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -598,6 +598,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y @@ -671,6 +672,7 @@ CONFIG_SATA_SIL=y # CONFIG_PATA_IT821X is not set # CONFIG_PATA_IT8213 is not set # CONFIG_PATA_JMICRON is not set +# CONFIG_PATA_LEGACY is not set # CONFIG_PATA_TRIFLEX is not set # CONFIG_PATA_MARVELL is not set # CONFIG_PATA_MPIIX is not set @@ -707,7 +709,7 @@ CONFIG_SATA_SIL=y # # -# See the help texts for more information. +# The newer stack is recommended. # # CONFIG_FIREWIRE is not set # CONFIG_IEEE1394 is not set @@ -766,6 +768,7 @@ CONFIG_WLAN=y # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set # CONFIG_USB_USBNET is not set +# CONFIG_USB_IPHETH is not set # CONFIG_WAN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set @@ -851,6 +854,7 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y @@ -899,6 +903,7 @@ CONFIG_I2C_ALGOPCA=y # CONFIG_I2C_OCORES is not set # CONFIG_I2C_SH_MOBILE is not set # CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set # # External I2C/SMBus adapter drivers @@ -912,15 +917,9 @@ CONFIG_I2C_ALGOPCA=y # CONFIG_I2C_PCA_PLATFORM=y # CONFIG_I2C_STUB is not set - -# -# Miscellaneous I2C Chip support -# -# CONFIG_SENSORS_TSL2550 is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set # CONFIG_SPI is not set # @@ -943,6 +942,7 @@ CONFIG_SSB_POSSIBLE=y # Multifunction device drivers # # CONFIG_MFD_CORE is not set +# CONFIG_MFD_88PM860X is not set CONFIG_MFD_SM501=y # CONFIG_MFD_SH_MOBILE_SDHI is not set # CONFIG_HTC_PASIC3 is not set @@ -950,12 +950,14 @@ CONFIG_MFD_SM501=y # CONFIG_MFD_TMIO is not set # CONFIG_PMIC_DA903X is not set # CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X is not set # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set # CONFIG_MFD_PCF50633 is not set # CONFIG_AB3100_CORE is not set -# CONFIG_MFD_88PM8607 is not set +# CONFIG_LPC_SCH is not set # CONFIG_REGULATOR is not set # CONFIG_MEDIA_SUPPORT is not set @@ -963,6 +965,7 @@ CONFIG_MFD_SM501=y # Graphics support # CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 # CONFIG_DRM is not set # CONFIG_VGASTATE is not set # CONFIG_VIDEO_OUTPUT_CONTROL is not set @@ -1059,6 +1062,7 @@ CONFIG_USB_HID=y # # Special HID drivers # +# CONFIG_HID_3M_PCT is not set CONFIG_HID_A4TECH=y CONFIG_HID_APPLE=y CONFIG_HID_BELKIN=y @@ -1074,14 +1078,19 @@ CONFIG_HID_GYRATION=y CONFIG_HID_LOGITECH=y # CONFIG_LOGITECH_FF is not set # CONFIG_LOGIRUMBLEPAD2_FF is not set +# CONFIG_LOGIG940_FF is not set CONFIG_HID_MICROSOFT=y +# CONFIG_HID_MOSART is not set CONFIG_HID_MONTEREY=y # CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set CONFIG_HID_PANTHERLORD=y # CONFIG_PANTHERLORD_FF is not set CONFIG_HID_PETALYNX=y +# CONFIG_HID_QUANTA is not set CONFIG_HID_SAMSUNG=y CONFIG_HID_SONY=y +# CONFIG_HID_STANTUM is not set CONFIG_HID_SUNPLUS=y # CONFIG_HID_GREENASIA is not set # CONFIG_HID_SMARTJOYPLUS is not set @@ -1182,7 +1191,6 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set -# CONFIG_USB_BERRY_CHARGE is not set # CONFIG_USB_LED is not set # CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set @@ -1195,7 +1203,6 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_IOWARRIOR is not set CONFIG_USB_TEST=m # CONFIG_USB_ISIGHTFW is not set -# CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set # @@ -1353,6 +1360,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set # CONFIG_JFFS2_FS is not set +# CONFIG_LOGFS is not set # CONFIG_CRAMFS is not set # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -1383,6 +1391,7 @@ CONFIG_SUNRPC_GSS=y CONFIG_RPCSEC_GSS_KRB5=y # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1461,6 +1470,7 @@ CONFIG_SCHED_DEBUG=y # CONFIG_TIMER_STATS is not set # CONFIG_DEBUG_OBJECTS is not set # CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_KMEMLEAK is not set CONFIG_DEBUG_PREEMPT=y # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set @@ -1509,6 +1519,7 @@ CONFIG_FTRACE=y CONFIG_BRANCH_PROFILE_NONE=y # CONFIG_PROFILE_ANNOTATED_BRANCHES is not set # CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_KSYM_TRACER is not set # CONFIG_STACK_TRACER is not set # CONFIG_KMEMTRACE is not set # CONFIG_WORKQUEUE_TRACER is not set @@ -1633,6 +1644,7 @@ CONFIG_CRYPTO_DES=y # # CONFIG_CRYPTO_ANSI_CPRNG is not set # CONFIG_CRYPTO_HW is not set +# CONFIG_VIRTUALIZATION is not set # CONFIG_BINARY_PRINTF is not set # diff --git a/arch/sh/configs/shmin_defconfig b/arch/sh/configs/shmin_defconfig index 45441c0..4ba2705 100644 --- a/arch/sh/configs/shmin_defconfig +++ b/arch/sh/configs/shmin_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 15:10:09 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 17:32:23 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -12,8 +12,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -29,6 +29,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -43,9 +44,11 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set # CONFIG_SWAP is not set # CONFIG_SYSVIPC is not set # CONFIG_POSIX_MQUEUE is not set @@ -65,7 +68,6 @@ CONFIG_RCU_FANOUT=32 # CONFIG_TREE_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set @@ -95,7 +97,7 @@ CONFIG_PERF_USE_VMALLOC=y # # Kernel Performance Events And Counters # -# CONFIG_PERF_EVENTS is not set +CONFIG_PERF_EVENTS=y # CONFIG_PERF_COUNTERS is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_COMPAT_BRK=y @@ -111,6 +113,7 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -222,6 +225,7 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -237,7 +241,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -312,7 +316,6 @@ CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT is not set CONFIG_GUSA=y # CONFIG_GUSA_RB is not set -# CONFIG_SPARSE_IRQ is not set # # Boot options @@ -544,6 +547,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set # CONFIG_SCSI_DMA is not set @@ -625,6 +629,7 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=2 CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y @@ -719,7 +724,6 @@ CONFIG_RTC_LIB=y # CONFIG_EXT2_FS is not set # CONFIG_EXT3_FS is not set # CONFIG_EXT4_FS is not set -CONFIG_EXT4_USE_FOR_EXT23=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set @@ -773,6 +777,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set # CONFIG_JFFS2_FS is not set +# CONFIG_LOGFS is not set CONFIG_CRAMFS=y # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -797,6 +802,7 @@ CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -936,6 +942,7 @@ CONFIG_CRYPTO=y # # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y +# CONFIG_VIRTUALIZATION is not set # CONFIG_BINARY_PRINTF is not set # diff --git a/arch/sh/configs/shx3_defconfig b/arch/sh/configs/shx3_defconfig index ecf50cd..42f6bd3 100644 --- a/arch/sh/configs/shx3_defconfig +++ b/arch/sh/configs/shx3_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 15:10:45 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 18:08:45 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -28,6 +28,7 @@ CONFIG_SYS_SUPPORTS_NUMA=y CONFIG_SYS_SUPPORTS_TMU=y CONFIG_STACKTRACE_SUPPORT=y CONFIG_LOCKDEP_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y # CONFIG_ARCH_HAS_ILOG2_U32 is not set # CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_ARCH_NO_VIRT_TO_BUS=y @@ -35,6 +36,7 @@ CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_COHERENT=y # CONFIG_DMA_NONCOHERENT is not set +# CONFIG_NEED_DMA_MAP_STATE is not set CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -49,9 +51,11 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -73,15 +77,11 @@ CONFIG_TREE_RCU=y CONFIG_RCU_TRACE=y CONFIG_RCU_FANOUT=32 # CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_RCU_FAST_NO_HZ is not set CONFIG_TREE_RCU_TRACE=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 -CONFIG_GROUP_SCHED=y -CONFIG_FAIR_GROUP_SCHED=y -CONFIG_RT_GROUP_SCHED=y -CONFIG_USER_SCHED=y -# CONFIG_CGROUP_SCHED is not set CONFIG_CGROUPS=y # CONFIG_CGROUP_DEBUG is not set CONFIG_CGROUP_NS=y @@ -92,6 +92,7 @@ CONFIG_CGROUP_CPUACCT=y CONFIG_RESOURCE_COUNTERS=y CONFIG_CGROUP_MEM_RES_CTLR=y # CONFIG_CGROUP_MEM_RES_CTLR_SWAP is not set +# CONFIG_CGROUP_SCHED is not set CONFIG_MM_OWNER=y CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -131,7 +132,6 @@ CONFIG_PERF_USE_VMALLOC=y # Kernel Performance Events And Counters # CONFIG_PERF_EVENTS=y -CONFIG_EVENT_PROFILE=y # CONFIG_PERF_COUNTERS is not set # CONFIG_DEBUG_PERF_USE_VMALLOC is not set CONFIG_VM_EVENT_COUNTERS=y @@ -140,12 +140,10 @@ CONFIG_COMPAT_BRK=y # CONFIG_SLUB is not set CONFIG_SLOB=y CONFIG_PROFILING=y -CONFIG_TRACEPOINTS=y CONFIG_OPROFILE=y CONFIG_HAVE_OPROFILE=y CONFIG_KPROBES=y CONFIG_KRETPROBES=y -CONFIG_HAVE_IOREMAP_PROT=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_ARCH_TRACEHOOK=y @@ -153,6 +151,7 @@ CONFIG_HAVE_DMA_ATTRS=y CONFIG_USE_GENERIC_SMP_HELPERS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -173,7 +172,6 @@ CONFIG_BLOCK=y CONFIG_LBDAF=y # CONFIG_BLK_DEV_BSG is not set # CONFIG_BLK_DEV_INTEGRITY is not set -# CONFIG_BLK_CGROUP is not set # # IO Schedulers @@ -269,8 +267,8 @@ CONFIG_FORCE_MAX_ZONEORDER=7 CONFIG_MEMORY_START=0x0c000000 CONFIG_MEMORY_SIZE=0x04000000 CONFIG_29BIT=y -# CONFIG_PMB_ENABLE is not set -# CONFIG_X2TLB is not set +# CONFIG_PMB is not set +CONFIG_X2TLB=y CONFIG_VSYSCALL=y CONFIG_NUMA=y CONFIG_NODES_SHIFT=3 @@ -282,6 +280,8 @@ CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y CONFIG_ARCH_MEMORY_PROBE=y +CONFIG_IOREMAP_FIXED=y +CONFIG_UNCACHED_MAPPING=y # CONFIG_PAGE_SIZE_4KB is not set # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -307,7 +307,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_MIGRATION=y # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 CONFIG_SCHED_MC=y @@ -392,14 +392,14 @@ CONFIG_HZ_250=y CONFIG_HZ=250 CONFIG_SCHED_HRTICK=y CONFIG_KEXEC=y -# CONFIG_CRASH_DUMP is not set CONFIG_SECCOMP=y CONFIG_SMP=y CONFIG_NR_CPUS=4 +# CONFIG_HOTPLUG_CPU is not set # CONFIG_PREEMPT_NONE is not set # CONFIG_PREEMPT_VOLUNTARY is not set CONFIG_PREEMPT=y -# CONFIG_SPARSE_IRQ is not set +# CONFIG_INTC_USERIMASK is not set # # Boot options @@ -518,7 +518,6 @@ CONFIG_IPV6_NDISC_NODETYPE=y # # CONFIG_NET_PKTGEN is not set # CONFIG_NET_TCPPROBE is not set -# CONFIG_NET_DROP_MONITOR is not set # CONFIG_HAMRADIO is not set CONFIG_CAN=m CONFIG_CAN_RAW=m @@ -583,6 +582,7 @@ CONFIG_MISC_DEVICES=y # CONFIG_ICS932S401 is not set # CONFIG_ENCLOSURE_SERVICES is not set # CONFIG_ISL29003 is not set +# CONFIG_SENSORS_TSL2550 is not set # CONFIG_DS1682 is not set # CONFIG_TI_DAC7512 is not set # CONFIG_C2PORT is not set @@ -601,6 +601,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y @@ -693,6 +694,7 @@ CONFIG_WLAN=y # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set # CONFIG_USB_USBNET is not set +# CONFIG_USB_IPHETH is not set # CONFIG_WAN is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -734,6 +736,7 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=2 CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y @@ -760,6 +763,7 @@ CONFIG_I2C_HELPER_AUTO=y # CONFIG_I2C_OCORES is not set # CONFIG_I2C_SH_MOBILE is not set # CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set # # External I2C/SMBus adapter drivers @@ -773,15 +777,9 @@ CONFIG_I2C_HELPER_AUTO=y # # CONFIG_I2C_PCA_PLATFORM is not set # CONFIG_I2C_STUB is not set - -# -# Miscellaneous I2C Chip support -# -# CONFIG_SENSORS_TSL2550 is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set CONFIG_SPI=y # CONFIG_SPI_DEBUG is not set CONFIG_SPI_MASTER=y @@ -838,10 +836,9 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_HTC_PASIC3 is not set # CONFIG_MFD_TMIO is not set # CONFIG_MFD_WM8400 is not set -# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set # CONFIG_MFD_PCF50633 is not set # CONFIG_MFD_MC13783 is not set -# CONFIG_AB3100_CORE is not set # CONFIG_EZX_PCAP is not set # CONFIG_AB4500_CORE is not set # CONFIG_REGULATOR is not set @@ -933,7 +930,6 @@ CONFIG_USB_R8A66597_HCD=m # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set -# CONFIG_USB_BERRY_CHARGE is not set # CONFIG_USB_LED is not set # CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set @@ -945,7 +941,6 @@ CONFIG_USB_R8A66597_HCD=m # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set # CONFIG_USB_ISIGHTFW is not set -# CONFIG_USB_VST is not set CONFIG_USB_GADGET=y # CONFIG_USB_GADGET_DEBUG is not set # CONFIG_USB_GADGET_DEBUG_FILES is not set @@ -983,6 +978,7 @@ CONFIG_USB_GADGET_DUALSPEED=y # CONFIG_USB_MIDI_GADGET is not set # CONFIG_USB_G_PRINTER is not set # CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_G_NOKIA is not set # CONFIG_USB_G_MULTI is not set # @@ -1065,8 +1061,6 @@ CONFIG_RTC_DRV_SH=y CONFIG_UIO=m # CONFIG_UIO_PDRV is not set # CONFIG_UIO_PDRV_GENIRQ is not set -# CONFIG_UIO_SMX is not set -# CONFIG_UIO_SERCOS3 is not set # # TI VLYNQ @@ -1145,6 +1139,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set +# CONFIG_LOGFS is not set # CONFIG_CRAMFS is not set # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -1159,6 +1154,7 @@ CONFIG_NETWORK_FILESYSTEMS=y # CONFIG_NFS_FS is not set # CONFIG_NFSD is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1246,7 +1242,6 @@ CONFIG_DEBUG_PREEMPT=y # CONFIG_LOCK_STAT is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set -CONFIG_STACKTRACE=y # CONFIG_DEBUG_KOBJECT is not set CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_INFO is not set @@ -1266,9 +1261,9 @@ CONFIG_FRAME_POINTER=y # CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set # CONFIG_LKDTM is not set # CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set # CONFIG_SYSCTL_SYSCALL_CHECK is not set # CONFIG_PAGE_POISONING is not set -CONFIG_NOP_TRACER=y CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y @@ -1276,10 +1271,7 @@ CONFIG_HAVE_DYNAMIC_FTRACE=y CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y CONFIG_HAVE_SYSCALL_TRACEPOINTS=y CONFIG_RING_BUFFER=y -CONFIG_EVENT_TRACING=y -CONFIG_CONTEXT_SWITCH_TRACER=y CONFIG_RING_BUFFER_ALLOW_SWAP=y -CONFIG_TRACING=y CONFIG_TRACING_SUPPORT=y CONFIG_FTRACE=y # CONFIG_FUNCTION_TRACER is not set @@ -1292,6 +1284,7 @@ CONFIG_FTRACE=y CONFIG_BRANCH_PROFILE_NONE=y # CONFIG_PROFILE_ANNOTATED_BRANCHES is not set # CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_KSYM_TRACER is not set # CONFIG_STACK_TRACER is not set # CONFIG_KMEMTRACE is not set # CONFIG_WORKQUEUE_TRACER is not set @@ -1329,6 +1322,7 @@ CONFIG_CRYPTO=y # CONFIG_CRYPTO_MANAGER2 is not set # CONFIG_CRYPTO_GF128MUL is not set # CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_PCRYPT is not set # CONFIG_CRYPTO_CRYPTD is not set # CONFIG_CRYPTO_AUTHENC is not set # CONFIG_CRYPTO_TEST is not set @@ -1407,7 +1401,8 @@ CONFIG_CRYPTO=y # # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y -CONFIG_BINARY_PRINTF=y +# CONFIG_VIRTUALIZATION is not set +# CONFIG_BINARY_PRINTF is not set # # Library routines diff --git a/arch/sh/configs/snapgear_defconfig b/arch/sh/configs/snapgear_defconfig index 98352d7..513834d 100644 --- a/arch/sh/configs/snapgear_defconfig +++ b/arch/sh/configs/snapgear_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 15:14:18 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 17:36:53 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -32,6 +32,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -46,9 +47,11 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set # CONFIG_SWAP is not set # CONFIG_SYSVIPC is not set # CONFIG_POSIX_MQUEUE is not set @@ -68,7 +71,6 @@ CONFIG_RCU_FANOUT=32 # CONFIG_TREE_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -79,6 +81,7 @@ CONFIG_INITRAMFS_SOURCE="" CONFIG_RD_GZIP=y # CONFIG_RD_BZIP2 is not set # CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_ANON_INODES=y @@ -105,7 +108,7 @@ CONFIG_PERF_USE_VMALLOC=y # # Kernel Performance Events And Counters # -# CONFIG_PERF_EVENTS is not set +CONFIG_PERF_EVENTS=y # CONFIG_PERF_COUNTERS is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_PCI_QUIRKS=y @@ -122,6 +125,7 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -235,6 +239,7 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -250,7 +255,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -335,7 +340,6 @@ CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT is not set CONFIG_GUSA=y # CONFIG_GUSA_RB is not set -# CONFIG_SPARSE_IRQ is not set # # Boot options @@ -350,9 +354,9 @@ CONFIG_ENTRY_OFFSET=0x00001000 # Bus options # CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y # CONFIG_PCIEPORTBUS is not set # CONFIG_ARCH_SUPPORTS_MSI is not set -CONFIG_PCI_LEGACY=y # CONFIG_PCI_STUB is not set # CONFIG_PCI_IOV is not set @@ -569,6 +573,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set # CONFIG_SCSI_DMA is not set @@ -586,7 +591,7 @@ CONFIG_HAVE_IDE=y # # -# See the help texts for more information. +# The newer stack is recommended. # # CONFIG_FIREWIRE is not set # CONFIG_IEEE1394 is not set @@ -626,6 +631,7 @@ CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set # CONFIG_AMD8111_ETH is not set # CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_KSZ884X_PCI is not set # CONFIG_B44 is not set # CONFIG_FORCEDETH is not set # CONFIG_E100 is not set @@ -726,6 +732,7 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y @@ -764,6 +771,7 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_SH_MOBILE_SDHI is not set # CONFIG_HTC_PASIC3 is not set # CONFIG_MFD_TMIO is not set +# CONFIG_LPC_SCH is not set # CONFIG_REGULATOR is not set # CONFIG_MEDIA_SUPPORT is not set @@ -771,6 +779,7 @@ CONFIG_SSB_POSSIBLE=y # Graphics support # CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 # CONFIG_DRM is not set # CONFIG_VGASTATE is not set # CONFIG_VIDEO_OUTPUT_CONTROL is not set @@ -848,7 +857,6 @@ CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XIP is not set # CONFIG_EXT3_FS is not set # CONFIG_EXT4_FS is not set -CONFIG_EXT4_USE_FOR_EXT23=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set @@ -907,6 +915,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set # CONFIG_JFFS2_FS is not set +# CONFIG_LOGFS is not set CONFIG_CRAMFS=y # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -925,6 +934,7 @@ CONFIG_NETWORK_FILESYSTEMS=y # CONFIG_NFS_FS is not set # CONFIG_NFSD is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -983,6 +993,7 @@ CONFIG_HAVE_ARCH_KGDB=y CONFIG_DEFAULT_SECURITY_DAC=y CONFIG_DEFAULT_SECURITY="" # CONFIG_CRYPTO is not set +# CONFIG_VIRTUALIZATION is not set # CONFIG_BINARY_PRINTF is not set # diff --git a/arch/sh/configs/systemh_defconfig b/arch/sh/configs/systemh_defconfig index 72982e3..14e69a2 100644 --- a/arch/sh/configs/systemh_defconfig +++ b/arch/sh/configs/systemh_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 15:14:50 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 17:39:19 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -31,6 +31,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -46,9 +47,11 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SWAP=y # CONFIG_SYSVIPC is not set # CONFIG_BSD_PROCESS_ACCT is not set @@ -65,7 +68,6 @@ CONFIG_RCU_FANOUT=32 # CONFIG_TREE_RCU_TRACE is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -76,6 +78,7 @@ CONFIG_INITRAMFS_SOURCE="" CONFIG_RD_GZIP=y # CONFIG_RD_BZIP2 is not set # CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SYSCTL=y CONFIG_ANON_INODES=y @@ -102,7 +105,7 @@ CONFIG_PERF_USE_VMALLOC=y # # Kernel Performance Events And Counters # -# CONFIG_PERF_EVENTS is not set +CONFIG_PERF_EVENTS=y # CONFIG_PERF_COUNTERS is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_COMPAT_BRK=y @@ -119,6 +122,7 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -237,6 +241,7 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -252,7 +257,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -332,7 +337,6 @@ CONFIG_HZ=250 CONFIG_PREEMPT=y CONFIG_GUSA=y # CONFIG_GUSA_RB is not set -# CONFIG_SPARSE_IRQ is not set # # Boot options @@ -402,6 +406,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set # CONFIG_SCSI_DMA is not set @@ -442,6 +447,7 @@ CONFIG_DEVKMEM=y # Non-8250 serial port support # # CONFIG_SERIAL_SH_SCI is not set +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y @@ -552,7 +558,6 @@ CONFIG_RTC_LIB=y # CONFIG_EXT2_FS is not set # CONFIG_EXT3_FS is not set # CONFIG_EXT4_FS is not set -CONFIG_EXT4_USE_FOR_EXT23=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set @@ -609,6 +614,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set +# CONFIG_LOGFS is not set CONFIG_CRAMFS=y # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -676,6 +682,7 @@ CONFIG_HAVE_ARCH_KGDB=y CONFIG_DEFAULT_SECURITY_DAC=y CONFIG_DEFAULT_SECURITY="" # CONFIG_CRYPTO is not set +# CONFIG_VIRTUALIZATION is not set # CONFIG_BINARY_PRINTF is not set # diff --git a/arch/sh/configs/titan_defconfig b/arch/sh/configs/titan_defconfig index 78c2570..79196b4 100644 --- a/arch/sh/configs/titan_defconfig +++ b/arch/sh/configs/titan_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 15:17:20 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 17:41:12 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -32,6 +32,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -46,9 +47,11 @@ CONFIG_LOCALVERSION="" CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -71,7 +74,6 @@ CONFIG_RCU_FANOUT=32 CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=16 -# CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -82,6 +84,7 @@ CONFIG_INITRAMFS_SOURCE="" CONFIG_RD_GZIP=y # CONFIG_RD_BZIP2 is not set # CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SYSCTL=y CONFIG_ANON_INODES=y @@ -109,8 +112,9 @@ CONFIG_PERF_USE_VMALLOC=y # # Kernel Performance Events And Counters # -# CONFIG_PERF_EVENTS is not set +CONFIG_PERF_EVENTS=y # CONFIG_PERF_COUNTERS is not set +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set CONFIG_VM_EVENT_COUNTERS=y CONFIG_PCI_QUIRKS=y CONFIG_COMPAT_BRK=y @@ -127,6 +131,7 @@ CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -245,6 +250,7 @@ CONFIG_ARCH_SPARSEMEM_DEFAULT=y CONFIG_MAX_ACTIVE_REGIONS=1 CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -260,7 +266,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -345,7 +351,6 @@ CONFIG_PREEMPT_VOLUNTARY=y # CONFIG_PREEMPT is not set CONFIG_GUSA=y # CONFIG_GUSA_RB is not set -# CONFIG_SPARSE_IRQ is not set # # Boot options @@ -361,9 +366,9 @@ CONFIG_CMDLINE="console=ttySC1,38400N81 root=/dev/nfs ip=:::::eth1:autoconf rw" # Bus options # CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y # CONFIG_PCIEPORTBUS is not set # CONFIG_ARCH_SUPPORTS_MSI is not set -CONFIG_PCI_LEGACY=y # CONFIG_PCI_DEBUG is not set # CONFIG_PCI_STUB is not set # CONFIG_PCI_IOV is not set @@ -392,7 +397,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -561,6 +565,7 @@ CONFIG_IP6_NF_RAW=m # CONFIG_ATM is not set CONFIG_STP=y CONFIG_BRIDGE=y +CONFIG_BRIDGE_IGMP_SNOOPING=y # CONFIG_NET_DSA is not set CONFIG_VLAN_8021Q=y # CONFIG_VLAN_8021Q_GVRP is not set @@ -749,6 +754,7 @@ CONFIG_MTD_NAND_IDS=m # CONFIG_MTD_NAND_CAFE is not set # CONFIG_MTD_NAND_PLATFORM is not set # CONFIG_MTD_ALAUDA is not set +# CONFIG_MTD_NAND_SH_FLCTL is not set # CONFIG_MTD_ONENAND is not set # @@ -768,10 +774,6 @@ CONFIG_BLK_DEV=y # CONFIG_BLK_DEV_COW_COMMON is not set CONFIG_BLK_DEV_LOOP=m CONFIG_BLK_DEV_CRYPTOLOOP=m - -# -# DRBD disabled because PROC_FS, INET or CONNECTOR not selected -# # CONFIG_BLK_DEV_DRBD is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_SX8 is not set @@ -802,6 +804,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y @@ -892,7 +895,7 @@ CONFIG_SCSI_LOWLEVEL=y # # -# See the help texts for more information. +# The newer stack is recommended. # # CONFIG_FIREWIRE is not set # CONFIG_IEEE1394 is not set @@ -951,6 +954,7 @@ CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set # CONFIG_AMD8111_ETH is not set # CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_KSZ884X_PCI is not set # CONFIG_B44 is not set # CONFIG_FORCEDETH is not set # CONFIG_E100 is not set @@ -1002,6 +1006,8 @@ CONFIG_NETDEV_10000=y # CONFIG_CHELSIO_T1 is not set CONFIG_CHELSIO_T3_DEPENDS=y # CONFIG_CHELSIO_T3 is not set +CONFIG_CHELSIO_T4_DEPENDS=y +# CONFIG_CHELSIO_T4 is not set # CONFIG_ENIC is not set # CONFIG_IXGBE is not set # CONFIG_IXGB is not set @@ -1014,6 +1020,7 @@ CONFIG_CHELSIO_T3_DEPENDS=y # CONFIG_MLX4_CORE is not set # CONFIG_TEHUTI is not set # CONFIG_BNX2X is not set +# CONFIG_QLCNIC is not set # CONFIG_QLGE is not set # CONFIG_SFC is not set # CONFIG_BE2NET is not set @@ -1040,6 +1047,7 @@ CONFIG_USB_NET_AX8817X=m CONFIG_USB_NET_CDCETHER=m # CONFIG_USB_NET_CDC_EEM is not set # CONFIG_USB_NET_DM9601 is not set +# CONFIG_USB_NET_SMSC75XX is not set # CONFIG_USB_NET_SMSC95XX is not set # CONFIG_USB_NET_GL620A is not set CONFIG_USB_NET_NET1080=m @@ -1049,6 +1057,7 @@ CONFIG_USB_NET_PLUSB=m # CONFIG_USB_NET_CDC_SUBSET is not set CONFIG_USB_NET_ZAURUS=m # CONFIG_USB_NET_INT51X1 is not set +# CONFIG_USB_IPHETH is not set # CONFIG_WAN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set @@ -1136,6 +1145,7 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y @@ -1215,6 +1225,7 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_SH_MOBILE_SDHI is not set # CONFIG_HTC_PASIC3 is not set # CONFIG_MFD_TMIO is not set +# CONFIG_LPC_SCH is not set # CONFIG_REGULATOR is not set # CONFIG_MEDIA_SUPPORT is not set @@ -1222,6 +1233,7 @@ CONFIG_SSB_POSSIBLE=y # Graphics support # CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 # CONFIG_DRM is not set # CONFIG_VGASTATE is not set # CONFIG_VIDEO_OUTPUT_CONTROL is not set @@ -1372,6 +1384,7 @@ CONFIG_USB_SERIAL_ARK3116=m # CONFIG_USB_SERIAL_NAVMAN is not set CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_SERIAL_OTI6858 is not set +# CONFIG_USB_SERIAL_QCAUX is not set # CONFIG_USB_SERIAL_QUALCOMM is not set # CONFIG_USB_SERIAL_SPCP8X5 is not set # CONFIG_USB_SERIAL_HP4X is not set @@ -1385,6 +1398,7 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_SERIAL_OPTION is not set # CONFIG_USB_SERIAL_OMNINET is not set # CONFIG_USB_SERIAL_OPTICON is not set +# CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set # CONFIG_USB_SERIAL_DEBUG is not set # @@ -1397,7 +1411,6 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set -# CONFIG_USB_BERRY_CHARGE is not set # CONFIG_USB_LED is not set # CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set @@ -1410,7 +1423,6 @@ CONFIG_USB_SERIAL_PL2303=m # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set # CONFIG_USB_ISIGHTFW is not set -# CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set # @@ -1552,6 +1564,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set # CONFIG_JFFS2_FS is not set +# CONFIG_LOGFS is not set # CONFIG_CRAMFS is not set # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -1585,6 +1598,7 @@ CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_SPKM3 is not set CONFIG_SMB_FS=m # CONFIG_SMB_NLS_DEFAULT is not set +# CONFIG_CEPH_FS is not set CONFIG_CIFS=m # CONFIG_CIFS_STATS is not set CONFIG_CIFS_WEAK_PW_HASH=y @@ -1680,6 +1694,7 @@ CONFIG_SCHED_DEBUG=y # CONFIG_TIMER_STATS is not set # CONFIG_DEBUG_OBJECTS is not set # CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_KMEMLEAK is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set @@ -1726,6 +1741,7 @@ CONFIG_FTRACE=y CONFIG_BRANCH_PROFILE_NONE=y # CONFIG_PROFILE_ANNOTATED_BRANCHES is not set # CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_KSYM_TRACER is not set # CONFIG_STACK_TRACER is not set # CONFIG_KMEMTRACE is not set # CONFIG_WORKQUEUE_TRACER is not set @@ -1853,6 +1869,7 @@ CONFIG_CRYPTO_DEFLATE=y # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y # CONFIG_CRYPTO_DEV_HIFN_795X is not set +# CONFIG_VIRTUALIZATION is not set # CONFIG_BINARY_PRINTF is not set # diff --git a/arch/sh/configs/ul2_defconfig b/arch/sh/configs/ul2_defconfig index 4fa03bf..17b7258 100644 --- a/arch/sh/configs/ul2_defconfig +++ b/arch/sh/configs/ul2_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 15:18:53 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 18:10:50 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y # CONFIG_GENERIC_GPIO is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -33,6 +33,7 @@ CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_NONCOHERENT=y +CONFIG_NEED_DMA_MAP_STATE=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -48,9 +49,11 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -73,7 +76,6 @@ CONFIG_RCU_FANOUT=32 CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -84,6 +86,7 @@ CONFIG_INITRAMFS_SOURCE="" CONFIG_RD_GZIP=y # CONFIG_RD_BZIP2 is not set # CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_ANON_INODES=y @@ -122,13 +125,13 @@ CONFIG_PROFILING=y # CONFIG_OPROFILE is not set CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set -CONFIG_HAVE_IOREMAP_PROT=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -244,7 +247,7 @@ CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_MEMORY_START=0x08000000 CONFIG_MEMORY_SIZE=0x01f00000 CONFIG_29BIT=y -# CONFIG_X2TLB is not set +CONFIG_X2TLB=y CONFIG_VSYSCALL=y CONFIG_NUMA=y CONFIG_NODES_SHIFT=1 @@ -255,6 +258,8 @@ CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y +CONFIG_IOREMAP_FIXED=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -278,7 +283,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_MIGRATION is not set # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -352,7 +357,7 @@ CONFIG_KEXEC=y # CONFIG_PREEMPT_VOLUNTARY is not set CONFIG_PREEMPT=y CONFIG_GUSA=y -# CONFIG_SPARSE_IRQ is not set +# CONFIG_INTC_USERIMASK is not set # # Boot options @@ -388,6 +393,7 @@ CONFIG_SUSPEND=y CONFIG_SUSPEND_FREEZER=y # CONFIG_HIBERNATION is not set CONFIG_PM_RUNTIME=y +CONFIG_PM_OPS=y # CONFIG_CPU_IDLE is not set CONFIG_NET=y @@ -395,7 +401,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -473,7 +478,7 @@ CONFIG_CFG80211=y # CONFIG_CFG80211_DEVELOPER_WARNINGS is not set # CONFIG_CFG80211_REG_DEBUG is not set CONFIG_CFG80211_DEFAULT_PS=y -# CONFIG_WIRELESS_OLD_REGULATORY is not set +# CONFIG_CFG80211_INTERNAL_REGDB is not set CONFIG_CFG80211_WEXT=y CONFIG_WIRELESS_EXT_SYSFS=y CONFIG_LIB80211=m @@ -619,6 +624,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y @@ -709,6 +715,7 @@ CONFIG_LIBERTAS=m # CONFIG_LIBERTAS_USB is not set CONFIG_LIBERTAS_SDIO=m CONFIG_LIBERTAS_DEBUG=y +# CONFIG_LIBERTAS_MESH is not set # CONFIG_P54_COMMON is not set # CONFIG_RT2X00 is not set # CONFIG_WL12XX is not set @@ -730,6 +737,7 @@ CONFIG_USB_NET_AX8817X=y CONFIG_USB_NET_CDCETHER=y # CONFIG_USB_NET_CDC_EEM is not set # CONFIG_USB_NET_DM9601 is not set +# CONFIG_USB_NET_SMSC75XX is not set # CONFIG_USB_NET_SMSC95XX is not set # CONFIG_USB_NET_GL620A is not set # CONFIG_USB_NET_NET1080 is not set @@ -739,6 +747,7 @@ CONFIG_USB_NET_CDCETHER=y # CONFIG_USB_NET_CDC_SUBSET is not set # CONFIG_USB_NET_ZAURUS is not set # CONFIG_USB_NET_INT51X1 is not set +# CONFIG_USB_IPHETH is not set # CONFIG_WAN is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -800,6 +809,7 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=1 CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_TIMBERDALE is not set # CONFIG_UNIX98_PTYS is not set # CONFIG_LEGACY_PTYS is not set # CONFIG_IPMI_HANDLER is not set @@ -952,7 +962,6 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set -# CONFIG_USB_BERRY_CHARGE is not set # CONFIG_USB_LED is not set # CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set @@ -964,7 +973,6 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set # CONFIG_USB_ISIGHTFW is not set -# CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set # @@ -987,9 +995,6 @@ CONFIG_MMC_BLOCK_BOUNCE=y # MMC/SD/SDIO Host Controller Drivers # # CONFIG_MMC_SDHCI is not set -# CONFIG_MMC_AT91 is not set -# CONFIG_MMC_ATMELMCI is not set -# CONFIG_MMC_TMIO is not set # CONFIG_MEMSTICK is not set # CONFIG_NEW_LEDS is not set # CONFIG_ACCESSIBILITY is not set @@ -1079,6 +1084,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set # CONFIG_JFFS2_FS is not set +# CONFIG_LOGFS is not set CONFIG_CRAMFS=y # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -1104,6 +1110,7 @@ CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1299,6 +1306,7 @@ CONFIG_CRYPTO_ARC4=y # # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRYPTO_HW=y +# CONFIG_VIRTUALIZATION is not set # CONFIG_BINARY_PRINTF is not set # diff --git a/arch/sh/configs/urquell_defconfig b/arch/sh/configs/urquell_defconfig index 23bda19..28bb19d 100644 --- a/arch/sh/configs/urquell_defconfig +++ b/arch/sh/configs/urquell_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.33-rc2 -# Mon Jan 4 15:27:53 2010 +# Linux kernel version: 2.6.34-rc5 +# Tue May 18 18:13:10 2010 # CONFIG_SUPERH=y CONFIG_SUPERH32=y @@ -13,8 +13,8 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_GENERIC_IRQ_PROBE=y CONFIG_IRQ_PER_CPU=y +CONFIG_SPARSE_IRQ=y CONFIG_GENERIC_GPIO=y CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y @@ -35,6 +35,7 @@ CONFIG_ARCH_HAS_DEFAULT_IDLE=y CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y CONFIG_DMA_COHERENT=y # CONFIG_DMA_NONCOHERENT is not set +# CONFIG_NEED_DMA_MAP_STATE is not set CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -49,9 +50,11 @@ CONFIG_LOCALVERSION_AUTO=y CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_BZIP2=y CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y CONFIG_KERNEL_GZIP=y # CONFIG_KERNEL_BZIP2 is not set # CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y @@ -77,11 +80,6 @@ CONFIG_RCU_FANOUT=32 CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 -CONFIG_GROUP_SCHED=y -CONFIG_FAIR_GROUP_SCHED=y -CONFIG_RT_GROUP_SCHED=y -# CONFIG_USER_SCHED is not set -CONFIG_CGROUP_SCHED=y CONFIG_CGROUPS=y CONFIG_CGROUP_DEBUG=y CONFIG_CGROUP_NS=y @@ -93,6 +91,9 @@ CONFIG_CGROUP_CPUACCT=y CONFIG_RESOURCE_COUNTERS=y CONFIG_CGROUP_MEM_RES_CTLR=y CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y +CONFIG_CGROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_RT_GROUP_SCHED=y CONFIG_MM_OWNER=y # CONFIG_SYSFS_DEPRECATED_V2 is not set # CONFIG_RELAY is not set @@ -102,6 +103,7 @@ CONFIG_INITRAMFS_SOURCE="" CONFIG_RD_GZIP=y # CONFIG_RD_BZIP2 is not set # CONFIG_RD_LZMA is not set +# CONFIG_RD_LZO is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_SYSCTL=y CONFIG_ANON_INODES=y @@ -142,13 +144,13 @@ CONFIG_PROFILING=y # CONFIG_OPROFILE is not set CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set -CONFIG_HAVE_IOREMAP_PROT=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_ARCH_TRACEHOOK=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y # # GCOV-based kernel profiling @@ -169,7 +171,6 @@ CONFIG_BLOCK=y CONFIG_LBDAF=y # CONFIG_BLK_DEV_BSG is not set # CONFIG_BLK_DEV_INTEGRITY is not set -# CONFIG_BLK_CGROUP is not set # # IO Schedulers @@ -265,8 +266,8 @@ CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_MEMORY_START=0x08000000 CONFIG_MEMORY_SIZE=0x08000000 CONFIG_29BIT=y -# CONFIG_PMB_ENABLE is not set -# CONFIG_X2TLB is not set +# CONFIG_PMB is not set +CONFIG_X2TLB=y CONFIG_VSYSCALL=y # CONFIG_NUMA is not set CONFIG_ARCH_FLATMEM_ENABLE=y @@ -277,6 +278,8 @@ CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y +CONFIG_IOREMAP_FIXED=y +CONFIG_UNCACHED_MAPPING=y CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_8KB is not set # CONFIG_PAGE_SIZE_16KB is not set @@ -299,7 +302,7 @@ CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_MIGRATION=y # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=2 +CONFIG_NR_QUICK=1 # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 @@ -317,6 +320,7 @@ CONFIG_CPU_LITTLE_ENDIAN=y # CONFIG_CPU_BIG_ENDIAN is not set CONFIG_SH_FPU=y CONFIG_SH_STORE_QUEUES=y +# CONFIG_SPECULATIVE_EXECUTION is not set CONFIG_CPU_HAS_INTEVT=y CONFIG_CPU_HAS_SR_RB=y CONFIG_CPU_HAS_PTEAEX=y @@ -325,15 +329,14 @@ CONFIG_CPU_HAS_FPU=y # # Board support # +# CONFIG_SH_SDK7786 is not set CONFIG_SH_URQUELL=y # # Timer and clock configuration # CONFIG_SH_TIMER_TMU=y -CONFIG_SH_PCLK_FREQ=33333333 CONFIG_SH_CLK_CPG=y -CONFIG_SH_CLK_CPG_LEGACY=y CONFIG_TICK_ONESHOT=y # CONFIG_NO_HZ is not set CONFIG_HIGH_RES_TIMERS=y @@ -376,7 +379,7 @@ CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set CONFIG_GUSA=y -CONFIG_SPARSE_IRQ=y +# CONFIG_INTC_USERIMASK is not set # # Boot options @@ -391,6 +394,7 @@ CONFIG_ENTRY_OFFSET=0x00001000 # Bus options # CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y CONFIG_PCIEPORTBUS=y CONFIG_PCIEAER=y # CONFIG_PCIE_ECRC is not set @@ -398,7 +402,6 @@ CONFIG_PCIEAER=y CONFIG_PCIEASPM=y CONFIG_PCIEASPM_DEBUG=y # CONFIG_ARCH_SUPPORTS_MSI is not set -# CONFIG_PCI_LEGACY is not set CONFIG_PCI_DEBUG=y # CONFIG_PCI_STUB is not set # CONFIG_PCI_IOV is not set @@ -428,7 +431,6 @@ CONFIG_NET=y # Networking options # CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set @@ -639,6 +641,7 @@ CONFIG_HAVE_IDE=y # # SCSI device support # +CONFIG_SCSI_MOD=y # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y @@ -712,6 +715,7 @@ CONFIG_ATA_SFF=y # CONFIG_PATA_IT821X is not set # CONFIG_PATA_IT8213 is not set # CONFIG_PATA_JMICRON is not set +# CONFIG_PATA_LEGACY is not set # CONFIG_PATA_TRIFLEX is not set # CONFIG_PATA_MARVELL is not set # CONFIG_PATA_MPIIX is not set @@ -748,7 +752,7 @@ CONFIG_ATA_SFF=y # # -# See the help texts for more information. +# The newer stack is recommended. # # CONFIG_FIREWIRE is not set # CONFIG_IEEE1394 is not set @@ -807,6 +811,7 @@ CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set # CONFIG_AMD8111_ETH is not set # CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_KSZ884X_PCI is not set # CONFIG_B44 is not set # CONFIG_FORCEDETH is not set # CONFIG_E100 is not set @@ -871,6 +876,7 @@ CONFIG_WLAN=y # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set # CONFIG_USB_USBNET is not set +# CONFIG_USB_IPHETH is not set # CONFIG_WAN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set @@ -958,6 +964,7 @@ CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_TIMBERDALE is not set CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set CONFIG_LEGACY_PTYS=y @@ -1007,6 +1014,7 @@ CONFIG_I2C_ALGOPCA=y # CONFIG_I2C_OCORES is not set # CONFIG_I2C_SH_MOBILE is not set # CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set # # External I2C/SMBus adapter drivers @@ -1020,15 +1028,9 @@ CONFIG_I2C_ALGOPCA=y # CONFIG_I2C_PCA_PLATFORM=y # CONFIG_I2C_STUB is not set - -# -# Miscellaneous I2C Chip support -# -# CONFIG_SENSORS_TSL2550 is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set # CONFIG_SPI is not set # @@ -1043,13 +1045,17 @@ CONFIG_GPIOLIB=y # # Memory mapped GPIO expanders: # +# CONFIG_GPIO_IT8761E is not set +# CONFIG_GPIO_SCH is not set # # I2C GPIO expanders: # +# CONFIG_GPIO_MAX7300 is not set # CONFIG_GPIO_MAX732X is not set # CONFIG_GPIO_PCA953X is not set # CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_ADP5588 is not set # # PCI GPIO expanders: @@ -1082,10 +1088,11 @@ CONFIG_HWMON=y # CONFIG_SENSORS_ADM1029 is not set # CONFIG_SENSORS_ADM1031 is not set # CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7411 is not set # CONFIG_SENSORS_ADT7462 is not set # CONFIG_SENSORS_ADT7470 is not set -# CONFIG_SENSORS_ADT7473 is not set # CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ASC7621 is not set # CONFIG_SENSORS_ATXP1 is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_I5K_AMB is not set @@ -1123,6 +1130,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_SMSC47M192 is not set # CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_AMC6821 is not set # CONFIG_SENSORS_THMC50 is not set # CONFIG_SENSORS_TMP401 is not set # CONFIG_SENSORS_TMP421 is not set @@ -1151,21 +1159,26 @@ CONFIG_SSB_POSSIBLE=y # Multifunction device drivers # # CONFIG_MFD_CORE is not set +# CONFIG_MFD_88PM860X is not set CONFIG_MFD_SM501=y # CONFIG_MFD_SM501_GPIO is not set # CONFIG_MFD_SH_MOBILE_SDHI is not set # CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set # CONFIG_TPS65010 is not set # CONFIG_TWL4030_CORE is not set # CONFIG_MFD_TMIO is not set # CONFIG_PMIC_DA903X is not set # CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set # CONFIG_MFD_WM8400 is not set # CONFIG_MFD_WM831X is not set # CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set # CONFIG_MFD_PCF50633 is not set # CONFIG_AB3100_CORE is not set -# CONFIG_MFD_88PM8607 is not set +# CONFIG_MFD_TIMBERDALE is not set +# CONFIG_LPC_SCH is not set # CONFIG_REGULATOR is not set CONFIG_MEDIA_SUPPORT=y @@ -1187,6 +1200,7 @@ CONFIG_VIDEO_IR=y # Graphics support # CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 # CONFIG_DRM is not set # CONFIG_VGASTATE is not set # CONFIG_VIDEO_OUTPUT_CONTROL is not set @@ -1283,6 +1297,7 @@ CONFIG_USB_HID=y # # Special HID drivers # +# CONFIG_HID_3M_PCT is not set CONFIG_HID_A4TECH=y CONFIG_HID_APPLE=y CONFIG_HID_BELKIN=y @@ -1298,14 +1313,19 @@ CONFIG_HID_GYRATION=y CONFIG_HID_LOGITECH=y # CONFIG_LOGITECH_FF is not set # CONFIG_LOGIRUMBLEPAD2_FF is not set +# CONFIG_LOGIG940_FF is not set CONFIG_HID_MICROSOFT=y +# CONFIG_HID_MOSART is not set CONFIG_HID_MONTEREY=y # CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set CONFIG_HID_PANTHERLORD=y # CONFIG_PANTHERLORD_FF is not set CONFIG_HID_PETALYNX=y +# CONFIG_HID_QUANTA is not set CONFIG_HID_SAMSUNG=y CONFIG_HID_SONY=y +# CONFIG_HID_STANTUM is not set CONFIG_HID_SUNPLUS=y # CONFIG_HID_GREENASIA is not set # CONFIG_HID_SMARTJOYPLUS is not set @@ -1326,7 +1346,6 @@ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y CONFIG_USB_DEVICEFS=y CONFIG_USB_DEVICE_CLASS=y # CONFIG_USB_DYNAMIC_MINORS is not set -# CONFIG_USB_SUSPEND is not set # CONFIG_USB_OTG is not set # CONFIG_USB_OTG_WHITELIST is not set # CONFIG_USB_OTG_BLACKLIST_HUB is not set @@ -1405,7 +1424,6 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set -# CONFIG_USB_BERRY_CHARGE is not set # CONFIG_USB_LED is not set # CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set @@ -1417,7 +1435,6 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set # CONFIG_USB_ISIGHTFW is not set -# CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set # @@ -1584,6 +1601,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set # CONFIG_JFFS2_FS is not set +# CONFIG_LOGFS is not set # CONFIG_CRAMFS is not set # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set @@ -1610,6 +1628,7 @@ CONFIG_SUNRPC_GSS=y CONFIG_RPCSEC_GSS_KRB5=y # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set +# CONFIG_CEPH_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1688,6 +1707,7 @@ CONFIG_SCHED_DEBUG=y # CONFIG_TIMER_STATS is not set # CONFIG_DEBUG_OBJECTS is not set # CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_KMEMLEAK is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set @@ -1713,6 +1733,7 @@ CONFIG_FRAME_POINTER=y # CONFIG_BACKTRACE_SELF_TEST is not set # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_LKDTM is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set CONFIG_SYSCTL_SYSCALL_CHECK=y @@ -1846,6 +1867,7 @@ CONFIG_CRYPTO_DES=y # # CONFIG_CRYPTO_ANSI_CPRNG is not set # CONFIG_CRYPTO_HW is not set +# CONFIG_VIRTUALIZATION is not set # CONFIG_BINARY_PRINTF is not set # -- cgit v0.10.2 From 05e021f095ffe9c7c1a695a3e2835f39243c6270 Mon Sep 17 00:00:00 2001 From: Maurus Cuelenaere Date: Mon, 17 May 2010 20:17:42 +0200 Subject: ARM: S3C64XX: Add USB external clock definition This adds the xusbxti clock to S3C64XX platform. Signed-off-by: Maurus Cuelenaere Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c64xx/clock.c b/arch/arm/mach-s3c64xx/clock.c index da83595..7a4138b 100644 --- a/arch/arm/mach-s3c64xx/clock.c +++ b/arch/arm/mach-s3c64xx/clock.c @@ -88,6 +88,12 @@ struct clk clk_48m = { .enable = clk_48m_ctrl, }; +struct clk clk_xusbxti = { + .name = "xusbxti", + .id = -1, + .rate = 48000000, +}; + static int inline s3c64xx_gate(void __iomem *reg, struct clk *clk, int enable) @@ -791,6 +797,7 @@ static struct clk *clks[] __initdata = { &clk_27m, &clk_48m, &clk_h2, + &clk_xusbxti, }; /** diff --git a/arch/arm/plat-samsung/include/plat/clock.h b/arch/arm/plat-samsung/include/plat/clock.h index 60b6269..efbc984 100644 --- a/arch/arm/plat-samsung/include/plat/clock.h +++ b/arch/arm/plat-samsung/include/plat/clock.h @@ -74,6 +74,7 @@ extern struct clk clk_ext; extern struct clk clk_h2; extern struct clk clk_27m; extern struct clk clk_48m; +extern struct clk clk_xusbxti; extern int clk_default_setrate(struct clk *clk, unsigned long rate); extern struct clk_ops clk_ops_def_setrate; -- cgit v0.10.2 From fbd6fe73514cf31a07c7b16518930ea84c644463 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 30 Apr 2010 19:08:38 +0900 Subject: ARM: S3C2443: Add initial defines for framebuffer support Add the necessary defines to get the s3c-fb device to compile for s3c2443. Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/include/mach/irqs.h b/arch/arm/mach-s3c2410/include/mach/irqs.h index 877c15e..11bb0f0 100644 --- a/arch/arm/mach-s3c2410/include/mach/irqs.h +++ b/arch/arm/mach-s3c2410/include/mach/irqs.h @@ -187,6 +187,9 @@ #define IRQ_S3CUART_TX3 IRQ_S3C2443_TX3 #define IRQ_S3CUART_ERR3 IRQ_S3C2443_ERR3 +#define IRQ_LCD_VSYNC IRQ_S3C2443_LCD3 +#define IRQ_LCD_SYSTEM IRQ_S3C2443_LCD2 + #ifdef CONFIG_CPU_S3C2440 #define IRQ_S3C244x_AC97 IRQ_S3C2440_AC97 #else diff --git a/arch/arm/mach-s3c2410/include/mach/map.h b/arch/arm/mach-s3c2410/include/mach/map.h index f07d680..091c98a 100644 --- a/arch/arm/mach-s3c2410/include/mach/map.h +++ b/arch/arm/mach-s3c2410/include/mach/map.h @@ -67,6 +67,8 @@ #define S3C2443_PA_HSMMC (0x4A800000) #define S3C2416_PA_HSMMC0 (0x4AC00000) +#define S3C2443_PA_FB (0x4C800000) + /* S3C2412 memory and IO controls */ #define S3C2412_PA_SSMC (0x4F000000) #define S3C2412_VA_SSMC S3C_ADDR_CPU(0x00000000) @@ -106,6 +108,7 @@ #define S3C24XX_PA_SDI S3C2410_PA_SDI #define S3C24XX_PA_NAND S3C2410_PA_NAND +#define S3C_PA_FB S3C2443_PA_FB #define S3C_PA_IIC S3C2410_PA_IIC #define S3C_PA_UART S3C24XX_PA_UART #define S3C_PA_USBHOST S3C2410_PA_USBHOST -- cgit v0.10.2 From dc5d2e8236e2eec461e8c34d302635142e93ab49 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 30 Apr 2010 19:34:25 +0900 Subject: ARM: S3C2443: Fix definition of LCD clock bit Fix the definition of the LCD clock bit, it is the TFT display controller on bit 9, not the older STN on bit 10. Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h b/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h index d87ebe0..08ab9df 100644 --- a/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h +++ b/arch/arm/mach-s3c2410/include/mach/regs-s3c2443-clock.h @@ -83,8 +83,7 @@ #define S3C2443_HCLKCON_DMA4 (1<<4) #define S3C2443_HCLKCON_DMA5 (1<<5) #define S3C2443_HCLKCON_CAMIF (1<<8) -#define S3C2443_HCLKCON_DISP (1<<9) -#define S3C2443_HCLKCON_LCDC (1<<10) +#define S3C2443_HCLKCON_LCDC (1<<9) #define S3C2443_HCLKCON_USBH (1<<11) #define S3C2443_HCLKCON_USBD (1<<12) #define S3C2443_HCLKCON_HSMMC (1<<16) -- cgit v0.10.2 From f077f3fc055b329787783a1ab0efb9a8f8ecc874 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 13 May 2010 14:44:50 +0900 Subject: ARM: SAMSUNG: Set S3C_FB_MAX_WIN in Move the S3C_FB_MAX_WIN to the platform data to avoid having to include the registers with the platform data. Set S3C_FB_MAX_WIN to 5, which is the maximum that any of the current hardware can do and the cost of having it set to this for all is minimal (at least for the platform data case), then always leave this as the maximum for the systems supported. Also remove the inclusion of from the device definition in arch/arm/plat-samsung Signed-off-by: Ben Dooks diff --git a/arch/arm/plat-samsung/dev-fb.c b/arch/arm/plat-samsung/dev-fb.c index 002a15f..bf60204 100644 --- a/arch/arm/plat-samsung/dev-fb.c +++ b/arch/arm/plat-samsung/dev-fb.c @@ -19,7 +19,6 @@ #include #include -#include #include #include diff --git a/arch/arm/plat-samsung/include/plat/fb.h b/arch/arm/plat-samsung/include/plat/fb.h index ffc01a7..1f85649 100644 --- a/arch/arm/plat-samsung/include/plat/fb.h +++ b/arch/arm/plat-samsung/include/plat/fb.h @@ -15,6 +15,13 @@ #ifndef __PLAT_S3C_FB_H #define __PLAT_S3C_FB_H __FILE__ +/* S3C_FB_MAX_WIN + * Set to the maximum number of windows that any of the supported hardware + * can use. Since the platform data uses this for an array size, having it + * set to the maximum of any version of the hardware can do is safe. + */ +#define S3C_FB_MAX_WIN (5) + /** * struct s3c_fb_pd_win - per window setup data * @win_mode: The display parameters to initialise (not for window 0) -- cgit v0.10.2 From f64bea4318a73e833d0a9b8400cc0f6cee957da3 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 3 May 2010 15:29:44 +0900 Subject: ARM: SMDK2416: Add support for framebuffer device and ensure correct setup Add support for the LCD display on the SMDJK2416, and correctly name the framebuffer device. Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2416/Kconfig b/arch/arm/mach-s3c2416/Kconfig index 29103a6..657e4fe 100644 --- a/arch/arm/mach-s3c2416/Kconfig +++ b/arch/arm/mach-s3c2416/Kconfig @@ -30,6 +30,7 @@ menu "S3C2416 Machines" config MACH_SMDK2416 bool "SMDK2416" select CPU_S3C2416 + select S3C_DEV_FB select S3C_DEV_HSMMC select S3C_DEV_HSMMC1 help diff --git a/arch/arm/mach-s3c2416/mach-smdk2416.c b/arch/arm/mach-s3c2416/mach-smdk2416.c index 99d24c4..5fc3f67 100644 --- a/arch/arm/mach-s3c2416/mach-smdk2416.c +++ b/arch/arm/mach-s3c2416/mach-smdk2416.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -36,16 +37,19 @@ #include #include -#include #include #include #include +#include #include #include #include #include +#include +#include + #include static struct map_desc smdk2416_iodesc[] __initdata = { @@ -109,7 +113,54 @@ static struct s3c2410_uartcfg smdk2416_uartcfgs[] __initdata = { } }; +struct s3c_fb_pd_win smdk2416_fb_win[] = { + [0] = { + /* think this is the same as the smdk6410 */ + .win_mode = { + .pixclock = 41094, + .left_margin = 8, + .right_margin = 13, + .upper_margin = 7, + .lower_margin = 5, + .hsync_len = 3, + .vsync_len = 1, + .xres = 800, + .yres = 480, + }, + .default_bpp = 16, + .max_bpp = 32, + }, +}; + +static void s3c2416_fb_gpio_setup_24bpp(void) +{ + unsigned int gpio; + + for (gpio = S3C2410_GPC(1); gpio <= S3C2410_GPC(4); gpio++) { + s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); + s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); + } + + for (gpio = S3C2410_GPC(8); gpio <= S3C2410_GPC(15); gpio++) { + s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); + s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); + } + + for (gpio = S3C2410_GPD(0); gpio <= S3C2410_GPD(15); gpio++) { + s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); + s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); + } +} + +static struct s3c_fb_platdata smdk2416_fb_platdata = { + .win[0] = &smdk2416_fb_win[0], + .setup_gpio = s3c2416_fb_gpio_setup_24bpp, + .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB, + .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC, +}; + static struct platform_device *smdk2416_devices[] __initdata = { + &s3c_device_fb, &s3c_device_wdt, &s3c_device_ohci, &s3c_device_i2c0, @@ -119,20 +170,25 @@ static struct platform_device *smdk2416_devices[] __initdata = { static void __init smdk2416_map_io(void) { - s3c24xx_init_io(smdk2416_iodesc, ARRAY_SIZE(smdk2416_iodesc)); s3c24xx_init_clocks(12000000); s3c24xx_init_uarts(smdk2416_uartcfgs, ARRAY_SIZE(smdk2416_uartcfgs)); - } static void __init smdk2416_machine_init(void) { s3c_i2c0_set_platdata(NULL); + s3c_fb_set_platdata(&smdk2416_fb_platdata); gpio_request(S3C2410_GPB(4), "USBHost Power"); gpio_direction_output(S3C2410_GPB(4), 1); + gpio_request(S3C2410_GPB(3), "Display Power"); + gpio_direction_output(S3C2410_GPB(3), 1); + + gpio_request(S3C2410_GPB(1), "Display Reset"); + gpio_direction_output(S3C2410_GPB(1), 1); + platform_add_devices(smdk2416_devices, ARRAY_SIZE(smdk2416_devices)); smdk_machine_init(); } diff --git a/arch/arm/mach-s3c2416/s3c2416.c b/arch/arm/mach-s3c2416/s3c2416.c index 3bff057..35dabcc 100644 --- a/arch/arm/mach-s3c2416/s3c2416.c +++ b/arch/arm/mach-s3c2416/s3c2416.c @@ -90,6 +90,8 @@ int __init s3c2416_init(void) s3c_i2c0_setname("s3c2440-i2c"); s3c_i2c1_setname("s3c2440-i2c"); + s3c_device_fb.name = "s3c2443-fb"; + return sysdev_register(&s3c2416_sysdev); } -- cgit v0.10.2 From a0026418d3d99b68dbd6c91f277d6f764fe41956 Mon Sep 17 00:00:00 2001 From: Vasily Khoruzhick Date: Wed, 12 May 2010 10:22:41 +0300 Subject: ARM: S3C244X: fix gpiolib port J support Increase GPIOs number for S3C244X, and make S3C_GPIO_END point to BANKJ end, otherwise gpiolib refuses to register BANKJ Signed-off-by: Vasily Khoruzhick [ben-linux@fluff.org: Move pm fix to new patch] Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/include/mach/gpio-track.h b/arch/arm/mach-s3c2410/include/mach/gpio-track.h index acb2591..6371eaa 100644 --- a/arch/arm/mach-s3c2410/include/mach/gpio-track.h +++ b/arch/arm/mach-s3c2410/include/mach/gpio-track.h @@ -23,7 +23,7 @@ static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int pin) { struct s3c_gpio_chip *chip; - if (pin > S3C2410_GPG(10)) + if (pin > S3C_GPIO_END) return NULL; chip = &s3c24xx_gpios[pin/32]; diff --git a/arch/arm/mach-s3c2410/include/mach/gpio.h b/arch/arm/mach-s3c2410/include/mach/gpio.h index 15f0b3e..b649bf2 100644 --- a/arch/arm/mach-s3c2410/include/mach/gpio.h +++ b/arch/arm/mach-s3c2410/include/mach/gpio.h @@ -20,10 +20,18 @@ * devices that need GPIO. */ +#ifdef CONFIG_CPU_S3C244X +#define ARCH_NR_GPIOS (32 * 9 + CONFIG_S3C24XX_GPIO_EXTRA) +#else #define ARCH_NR_GPIOS (256 + CONFIG_S3C24XX_GPIO_EXTRA) +#endif #include #include #include +#ifdef CONFIG_CPU_S3C24XX +#define S3C_GPIO_END (S3C2410_GPIO_BANKJ + 32) +#else #define S3C_GPIO_END (S3C2410_GPIO_BANKH + 32) +#endif -- cgit v0.10.2 From 2c8fcfbf735e2d3b139e4247eb3e73edf64bb23f Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 17 May 2010 14:13:16 +0900 Subject: ARM: S3C24XX: Start cleanup of GPIO numbering Start cleaning up the numbering of GPIO banks by removing the old bank start definitions currently being used by some of the header files. Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h b/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h index f3182ff..ad94e1a 100644 --- a/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h +++ b/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h @@ -16,12 +16,7 @@ #define S3C2410_GPIONO(bank,offset) ((bank) + (offset)) -#define S3C2410_GPIO_BANKA (32*0) -#define S3C2410_GPIO_BANKB (32*1) #define S3C2410_GPIO_BANKC (32*2) -#define S3C2410_GPIO_BANKD (32*3) -#define S3C2410_GPIO_BANKE (32*4) -#define S3C2410_GPIO_BANKF (32*5) #define S3C2410_GPIO_BANKG (32*6) #define S3C2410_GPIO_BANKH (32*7) diff --git a/arch/arm/mach-s3c2412/gpio.c b/arch/arm/mach-s3c2412/gpio.c index f7afece..71c5793 100644 --- a/arch/arm/mach-s3c2412/gpio.c +++ b/arch/arm/mach-s3c2412/gpio.c @@ -33,14 +33,14 @@ int s3c2412_gpio_set_sleepcfg(unsigned int pin, unsigned int state) offs *= 2; - if (pin < S3C2410_GPIO_BANKB) + if (pin < S3C2410_GPB(0)) return -EINVAL; - if (pin >= S3C2410_GPIO_BANKF && - pin <= S3C2410_GPIO_BANKG) + if (pin >= S3C2410_GPF(0) && + pin <= S3C2410_GPG(16)) return -EINVAL; - if (pin > (S3C2410_GPIO_BANKH + 32)) + if (pin > S3C2410_GPH(16)) return -EINVAL; local_irq_save(flags); -- cgit v0.10.2 From 7987bd7a7051c979f7b9b572898f92dbef6aaeb1 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 17 May 2010 14:28:44 +0900 Subject: ARM: S3C24XX: Update missed gpio calls to use gpiolib Update a couple of S3C24XX and S3C2412 files that are still using the GPIO number to register mapping calls to get the s3c_gpio_chip and use the base field from that. Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2412/gpio.c b/arch/arm/mach-s3c2412/gpio.c index 71c5793..3404a87 100644 --- a/arch/arm/mach-s3c2412/gpio.c +++ b/arch/arm/mach-s3c2412/gpio.c @@ -16,18 +16,20 @@ #include #include #include +#include #include #include #include - #include +#include + int s3c2412_gpio_set_sleepcfg(unsigned int pin, unsigned int state) { - void __iomem *base = S3C24XX_GPIO_BASE(pin); - unsigned long offs = S3C2410_GPIO_OFFSET(pin); + struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); + unsigned long offs = pin - chip->chip.base; unsigned long flags; unsigned long slpcon; @@ -45,12 +47,12 @@ int s3c2412_gpio_set_sleepcfg(unsigned int pin, unsigned int state) local_irq_save(flags); - slpcon = __raw_readl(base + 0x0C); + slpcon = __raw_readl(chip->base + 0x0C); slpcon &= ~(3 << offs); slpcon |= state << offs; - __raw_writel(slpcon, base + 0x0C); + __raw_writel(slpcon, chip->base + 0x0C); local_irq_restore(flags); diff --git a/arch/arm/plat-s3c24xx/gpio.c b/arch/arm/plat-s3c24xx/gpio.c index 45126d3..2f3d7c0 100644 --- a/arch/arm/plat-s3c24xx/gpio.c +++ b/arch/arm/plat-s3c24xx/gpio.c @@ -34,6 +34,8 @@ #include +#include + /* gpiolib wrappers until these are totally eliminated */ void s3c2410_gpio_pullup(unsigned int pin, unsigned int to) @@ -68,10 +70,10 @@ EXPORT_SYMBOL(s3c2410_gpio_setpin); unsigned int s3c2410_gpio_getpin(unsigned int pin) { - void __iomem *base = S3C24XX_GPIO_BASE(pin); - unsigned long offs = S3C2410_GPIO_OFFSET(pin); + struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); + unsigned long offs = pin - chip->chip.base; - return __raw_readl(base + 0x04) & (1<< offs); + return __raw_readl(chip->base + 0x04) & (1<< offs); } EXPORT_SYMBOL(s3c2410_gpio_getpin); -- cgit v0.10.2 From 1635ca4aaf835794401da33079e50ce1d6bbb5d0 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 17 May 2010 14:53:48 +0900 Subject: ARM: S3C24XX: Remove macros mapping GPIO number to base As part of the cleanup, remove the old macros mapping GPIO numbers to the base of the register now we have gpiolib to manage the GPIO mappings for us. Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h b/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h index ad94e1a..ad4a04a 100644 --- a/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h +++ b/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h @@ -16,7 +16,6 @@ #define S3C2410_GPIONO(bank,offset) ((bank) + (offset)) -#define S3C2410_GPIO_BANKC (32*2) #define S3C2410_GPIO_BANKG (32*6) #define S3C2410_GPIO_BANKH (32*7) diff --git a/arch/arm/mach-s3c2410/include/mach/gpio-track.h b/arch/arm/mach-s3c2410/include/mach/gpio-track.h index 6371eaa..d67819d 100644 --- a/arch/arm/mach-s3c2410/include/mach/gpio-track.h +++ b/arch/arm/mach-s3c2410/include/mach/gpio-track.h @@ -27,7 +27,7 @@ static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int pin) return NULL; chip = &s3c24xx_gpios[pin/32]; - return (S3C2410_GPIO_OFFSET(pin) < chip->chip.ngpio) ? chip : NULL; + return ((pin - chip->chip.base) < chip->chip.ngpio) ? chip : NULL; } #endif /* __ASM_ARCH_GPIO_CORE_H */ diff --git a/arch/arm/mach-s3c2410/include/mach/regs-gpio.h b/arch/arm/mach-s3c2410/include/mach/regs-gpio.h index 821b966..95e29fe 100644 --- a/arch/arm/mach-s3c2410/include/mach/regs-gpio.h +++ b/arch/arm/mach-s3c2410/include/mach/regs-gpio.h @@ -17,29 +17,11 @@ #include #ifdef CONFIG_CPU_S3C2400 -#define S3C24XX_GPIO_BASE(x) S3C2400_GPIO_BASE(x) -#define S3C24XX_MISCCR S3C2400_MISCCR +#define S3C24XX_MISCCR S3C2400_MISCCR #else -#define S3C24XX_GPIO_BASE(x) S3C2410_GPIO_BASE(x) -#define S3C24XX_MISCCR S3C24XX_GPIOREG2(0x80) +#define S3C24XX_MISCCR S3C24XX_GPIOREG2(0x80) #endif /* CONFIG_CPU_S3C2400 */ - -/* S3C2400 doesn't have a 1:1 mapping to S3C2410 gpio base pins */ - -#define S3C2400_BANKNUM(pin) (((pin) & ~31) / 32) -#define S3C2400_BASEA2B(pin) ((((pin) & ~31) >> 2)) -#define S3C2400_BASEC2H(pin) ((S3C2400_BANKNUM(pin) * 10) + \ - (2 * (S3C2400_BANKNUM(pin)-2))) - -#define S3C2400_GPIO_BASE(pin) (pin < S3C2410_GPIO_BANKC ? \ - S3C2400_BASEA2B(pin)+S3C24XX_VA_GPIO : \ - S3C2400_BASEC2H(pin)+S3C24XX_VA_GPIO) - - -#define S3C2410_GPIO_BASE(pin) ((((pin) & ~31) >> 1) + S3C24XX_VA_GPIO) -#define S3C2410_GPIO_OFFSET(pin) ((pin) & 31) - /* general configuration options */ #define S3C2410_GPIO_LEAVE (0xFFFFFFFF) -- cgit v0.10.2 From 4ac2a39767c2a93c06b654a0bf1c635e03ff75ac Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 17 May 2010 15:12:33 +0900 Subject: ARM: S3C24XX: Add note on GPIO bank sizes Add a table for the GPIO bank sizes for each SoC Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h b/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h index ad4a04a..4f7bf32 100644 --- a/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h +++ b/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h @@ -19,6 +19,25 @@ #define S3C2410_GPIO_BANKG (32*6) #define S3C2410_GPIO_BANKH (32*7) +/* GPIO sizes for various SoCs: + * + * 2442 + * 2410 2412 2440 2443 2416 + * ---- ---- ---- ---- ---- + * A 23 22 25 16 25 + * B 11 11 11 11 9 + * C 16 15 16 16 16 + * D 16 16 16 16 16 + * E 16 16 16 16 16 + * F 8 8 8 8 8 + * G 16 16 16 16 8 + * H 11 11 9 15 15 + * J -- -- 13 16 -- + * K -- -- -- -- 16 + * L -- -- -- 15 7 + * M -- -- -- 2 2 + */ + /* GPIO bank sizes */ #define S3C2410_GPIO_A_NR (32) #define S3C2410_GPIO_B_NR (32) -- cgit v0.10.2 From 32b6cb3872883861f3a2669cce880f3a7ef8979a Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 18 May 2010 19:07:05 +0900 Subject: ARM: SAMSUNG: Fix additional increment when running through gpios The pm-gpio.c code was incrementing the gpio_nr from the nr_gpios field and the bank-bank offset inside the loop, and also in the for() loop with a ++. Remove the ++, as the number is already at the next GPIO, thus ensuring that we don't skip a gpio bank by accident. Signed-off-by: Ben Dooks diff --git a/arch/arm/plat-samsung/pm-gpio.c b/arch/arm/plat-samsung/pm-gpio.c index 69a4c7f..d50ab9d 100644 --- a/arch/arm/plat-samsung/pm-gpio.c +++ b/arch/arm/plat-samsung/pm-gpio.c @@ -329,7 +329,7 @@ void s3c_pm_save_gpios(void) struct s3c_gpio_chip *ourchip; unsigned int gpio_nr; - for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) { + for (gpio_nr = 0; gpio_nr < S3C_GPIO_END;) { ourchip = s3c_gpiolib_getchip(gpio_nr); if (!ourchip) continue; @@ -367,7 +367,7 @@ void s3c_pm_restore_gpios(void) struct s3c_gpio_chip *ourchip; unsigned int gpio_nr; - for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) { + for (gpio_nr = 0; gpio_nr < S3C_GPIO_END;) { ourchip = s3c_gpiolib_getchip(gpio_nr); if (!ourchip) continue; -- cgit v0.10.2 From 602bf0cfbdedfd988e43203d2a26bdbbab639309 Mon Sep 17 00:00:00 2001 From: Jassi Brar Date: Tue, 18 May 2010 16:02:26 +0900 Subject: ARM: S5PV210: Add audio platform devices Define platform devices for all audio devices found on S5PV210 Signed-off-by: Jassi Brar Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5pv210/Makefile b/arch/arm/mach-s5pv210/Makefile index 8ebf51c..e435afe 100644 --- a/arch/arm/mach-s5pv210/Makefile +++ b/arch/arm/mach-s5pv210/Makefile @@ -18,3 +18,7 @@ obj-$(CONFIG_CPU_S5PV210) += cpu.o init.o clock.o obj-$(CONFIG_MACH_SMDKV210) += mach-smdkv210.o obj-$(CONFIG_MACH_SMDKC110) += mach-smdkc110.o + +# device support + +obj-y += dev-audio.o diff --git a/arch/arm/mach-s5pv210/dev-audio.c b/arch/arm/mach-s5pv210/dev-audio.c new file mode 100644 index 0000000..6e21533 --- /dev/null +++ b/arch/arm/mach-s5pv210/dev-audio.c @@ -0,0 +1,327 @@ +/* linux/arch/arm/mach-s5pv210/dev-audio.c + * + * Copyright (c) 2010 Samsung Electronics Co. Ltd + * Jaswinder Singh + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include + +#include +#include + +#include +#include +#include +#include + +static int s5pv210_cfg_i2s(struct platform_device *pdev) +{ + /* configure GPIO for i2s port */ + switch (pdev->id) { + case 1: + s3c_gpio_cfgpin(S5PV210_GPC0(0), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5PV210_GPC0(1), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5PV210_GPC0(2), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5PV210_GPC0(3), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5PV210_GPC0(4), S3C_GPIO_SFN(2)); + break; + + case 2: + s3c_gpio_cfgpin(S5PV210_GPC1(0), S3C_GPIO_SFN(4)); + s3c_gpio_cfgpin(S5PV210_GPC1(1), S3C_GPIO_SFN(4)); + s3c_gpio_cfgpin(S5PV210_GPC1(2), S3C_GPIO_SFN(4)); + s3c_gpio_cfgpin(S5PV210_GPC1(3), S3C_GPIO_SFN(4)); + s3c_gpio_cfgpin(S5PV210_GPC1(4), S3C_GPIO_SFN(4)); + break; + + case -1: + s3c_gpio_cfgpin(S5PV210_GPI(0), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5PV210_GPI(1), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5PV210_GPI(2), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5PV210_GPI(3), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5PV210_GPI(4), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5PV210_GPI(5), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5PV210_GPI(6), S3C_GPIO_SFN(2)); + break; + + default: + printk(KERN_ERR "Invalid Device %d\n", pdev->id); + return -EINVAL; + } + + return 0; +} + +static struct s3c_audio_pdata s3c_i2s_pdata = { + .cfg_gpio = s5pv210_cfg_i2s, +}; + +static struct resource s5pv210_iis0_resource[] = { + [0] = { + .start = S5PV210_PA_IIS0, + .end = S5PV210_PA_IIS0 + 0x100 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = DMACH_I2S0_TX, + .end = DMACH_I2S0_TX, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = DMACH_I2S0_RX, + .end = DMACH_I2S0_RX, + .flags = IORESOURCE_DMA, + }, +}; + +struct platform_device s5pv210_device_iis0 = { + .name = "s3c64xx-iis-v4", + .id = -1, + .num_resources = ARRAY_SIZE(s5pv210_iis0_resource), + .resource = s5pv210_iis0_resource, + .dev = { + .platform_data = &s3c_i2s_pdata, + }, +}; + +static struct resource s5pv210_iis1_resource[] = { + [0] = { + .start = S5PV210_PA_IIS1, + .end = S5PV210_PA_IIS1 + 0x100 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = DMACH_I2S1_TX, + .end = DMACH_I2S1_TX, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = DMACH_I2S1_RX, + .end = DMACH_I2S1_RX, + .flags = IORESOURCE_DMA, + }, +}; + +struct platform_device s5pv210_device_iis1 = { + .name = "s3c64xx-iis", + .id = 1, + .num_resources = ARRAY_SIZE(s5pv210_iis1_resource), + .resource = s5pv210_iis1_resource, + .dev = { + .platform_data = &s3c_i2s_pdata, + }, +}; + +static struct resource s5pv210_iis2_resource[] = { + [0] = { + .start = S5PV210_PA_IIS2, + .end = S5PV210_PA_IIS2 + 0x100 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = DMACH_I2S2_TX, + .end = DMACH_I2S2_TX, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = DMACH_I2S2_RX, + .end = DMACH_I2S2_RX, + .flags = IORESOURCE_DMA, + }, +}; + +struct platform_device s5pv210_device_iis2 = { + .name = "s3c64xx-iis", + .id = 2, + .num_resources = ARRAY_SIZE(s5pv210_iis2_resource), + .resource = s5pv210_iis2_resource, + .dev = { + .platform_data = &s3c_i2s_pdata, + }, +}; + +/* PCM Controller platform_devices */ + +static int s5pv210_pcm_cfg_gpio(struct platform_device *pdev) +{ + switch (pdev->id) { + case 0: + s3c_gpio_cfgpin(S5PV210_GPI(0), S3C_GPIO_SFN(3)); + s3c_gpio_cfgpin(S5PV210_GPI(1), S3C_GPIO_SFN(3)); + s3c_gpio_cfgpin(S5PV210_GPI(2), S3C_GPIO_SFN(3)); + s3c_gpio_cfgpin(S5PV210_GPI(3), S3C_GPIO_SFN(3)); + s3c_gpio_cfgpin(S5PV210_GPI(4), S3C_GPIO_SFN(3)); + break; + case 1: + s3c_gpio_cfgpin(S5PV210_GPC0(0), S3C_GPIO_SFN(3)); + s3c_gpio_cfgpin(S5PV210_GPC0(1), S3C_GPIO_SFN(3)); + s3c_gpio_cfgpin(S5PV210_GPC0(2), S3C_GPIO_SFN(3)); + s3c_gpio_cfgpin(S5PV210_GPC0(3), S3C_GPIO_SFN(3)); + s3c_gpio_cfgpin(S5PV210_GPC0(4), S3C_GPIO_SFN(3)); + break; + case 2: + s3c_gpio_cfgpin(S5PV210_GPC1(0), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5PV210_GPC1(1), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5PV210_GPC1(2), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5PV210_GPC1(3), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5PV210_GPC1(4), S3C_GPIO_SFN(2)); + break; + default: + printk(KERN_DEBUG "Invalid PCM Controller number!"); + return -EINVAL; + } + + return 0; +} + +static struct s3c_audio_pdata s3c_pcm_pdata = { + .cfg_gpio = s5pv210_pcm_cfg_gpio, +}; + +static struct resource s5pv210_pcm0_resource[] = { + [0] = { + .start = S5PV210_PA_PCM0, + .end = S5PV210_PA_PCM0 + 0x100 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = DMACH_PCM0_TX, + .end = DMACH_PCM0_TX, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = DMACH_PCM0_RX, + .end = DMACH_PCM0_RX, + .flags = IORESOURCE_DMA, + }, +}; + +struct platform_device s5pv210_device_pcm0 = { + .name = "samsung-pcm", + .id = 0, + .num_resources = ARRAY_SIZE(s5pv210_pcm0_resource), + .resource = s5pv210_pcm0_resource, + .dev = { + .platform_data = &s3c_pcm_pdata, + }, +}; + +static struct resource s5pv210_pcm1_resource[] = { + [0] = { + .start = S5PV210_PA_PCM1, + .end = S5PV210_PA_PCM1 + 0x100 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = DMACH_PCM1_TX, + .end = DMACH_PCM1_TX, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = DMACH_PCM1_RX, + .end = DMACH_PCM1_RX, + .flags = IORESOURCE_DMA, + }, +}; + +struct platform_device s5pv210_device_pcm1 = { + .name = "samsung-pcm", + .id = 1, + .num_resources = ARRAY_SIZE(s5pv210_pcm1_resource), + .resource = s5pv210_pcm1_resource, + .dev = { + .platform_data = &s3c_pcm_pdata, + }, +}; + +static struct resource s5pv210_pcm2_resource[] = { + [0] = { + .start = S5PV210_PA_PCM2, + .end = S5PV210_PA_PCM2 + 0x100 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = DMACH_PCM2_TX, + .end = DMACH_PCM2_TX, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = DMACH_PCM2_RX, + .end = DMACH_PCM2_RX, + .flags = IORESOURCE_DMA, + }, +}; + +struct platform_device s5pv210_device_pcm2 = { + .name = "samsung-pcm", + .id = 2, + .num_resources = ARRAY_SIZE(s5pv210_pcm2_resource), + .resource = s5pv210_pcm2_resource, + .dev = { + .platform_data = &s3c_pcm_pdata, + }, +}; + +/* AC97 Controller platform devices */ + +static int s5pv210_ac97_cfg_gpio(struct platform_device *pdev) +{ + s3c_gpio_cfgpin(S5PV210_GPC0(0), S3C_GPIO_SFN(4)); + s3c_gpio_cfgpin(S5PV210_GPC0(1), S3C_GPIO_SFN(4)); + s3c_gpio_cfgpin(S5PV210_GPC0(2), S3C_GPIO_SFN(4)); + s3c_gpio_cfgpin(S5PV210_GPC0(3), S3C_GPIO_SFN(4)); + s3c_gpio_cfgpin(S5PV210_GPC0(4), S3C_GPIO_SFN(4)); + + return 0; +} + +static struct resource s5pv210_ac97_resource[] = { + [0] = { + .start = S5PV210_PA_AC97, + .end = S5PV210_PA_AC97 + 0x100 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = DMACH_AC97_PCMOUT, + .end = DMACH_AC97_PCMOUT, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = DMACH_AC97_PCMIN, + .end = DMACH_AC97_PCMIN, + .flags = IORESOURCE_DMA, + }, + [3] = { + .start = DMACH_AC97_MICIN, + .end = DMACH_AC97_MICIN, + .flags = IORESOURCE_DMA, + }, + [4] = { + .start = IRQ_AC97, + .end = IRQ_AC97, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct s3c_audio_pdata s3c_ac97_pdata = { + .cfg_gpio = s5pv210_ac97_cfg_gpio, +}; + +static u64 s5pv210_ac97_dmamask = DMA_BIT_MASK(32); + +struct platform_device s5pv210_device_ac97 = { + .name = "s3c-ac97", + .id = -1, + .num_resources = ARRAY_SIZE(s5pv210_ac97_resource), + .resource = s5pv210_ac97_resource, + .dev = { + .platform_data = &s3c_ac97_pdata, + .dma_mask = &s5pv210_ac97_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, +}; diff --git a/arch/arm/mach-s5pv210/include/mach/map.h b/arch/arm/mach-s5pv210/include/mach/map.h index c22694c..bcd2e82 100644 --- a/arch/arm/mach-s5pv210/include/mach/map.h +++ b/arch/arm/mach-s5pv210/include/mach/map.h @@ -58,6 +58,19 @@ #define S5PV210_PA_SDRAM (0x20000000) #define S5P_PA_SDRAM S5PV210_PA_SDRAM +/* I2S */ +#define S5PV210_PA_IIS0 0xEEE30000 +#define S5PV210_PA_IIS1 0xE2100000 +#define S5PV210_PA_IIS2 0xE2A00000 + +/* PCM */ +#define S5PV210_PA_PCM0 0xE2300000 +#define S5PV210_PA_PCM1 0xE1200000 +#define S5PV210_PA_PCM2 0xE2B00000 + +/* AC97 */ +#define S5PV210_PA_AC97 0xE2200000 + /* compatibiltiy defines. */ #define S3C_PA_UART S5PV210_PA_UART #define S3C_PA_IIC S5PV210_PA_IIC0 diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h index 796d242..d8fda3a 100644 --- a/arch/arm/plat-samsung/include/plat/devs.h +++ b/arch/arm/plat-samsung/include/plat/devs.h @@ -64,6 +64,14 @@ extern struct platform_device s3c_device_nand; extern struct platform_device s3c_device_usbgadget; extern struct platform_device s3c_device_usb_hsotg; +extern struct platform_device s5pv210_device_ac97; +extern struct platform_device s5pv210_device_pcm0; +extern struct platform_device s5pv210_device_pcm1; +extern struct platform_device s5pv210_device_pcm2; +extern struct platform_device s5pv210_device_iis0; +extern struct platform_device s5pv210_device_iis1; +extern struct platform_device s5pv210_device_iis2; + /* s3c2440 specific devices */ #ifdef CONFIG_CPU_S3C2440 -- cgit v0.10.2 From 9b5f1e08c95a9df7de9a96a7a4240362358acd5f Mon Sep 17 00:00:00 2001 From: Jassi Brar Date: Tue, 18 May 2010 16:02:30 +0900 Subject: ARM: SMDKV210: Add audio devices on board Add audio platform devices on the smdk by default. Signed-off-by: Jassi Brar Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c index a278832..3c29e18 100644 --- a/arch/arm/mach-s5pv210/mach-smdkv210.c +++ b/arch/arm/mach-s5pv210/mach-smdkv210.c @@ -72,6 +72,8 @@ static struct s3c2410_uartcfg smdkv210_uartcfgs[] __initdata = { }; static struct platform_device *smdkv210_devices[] __initdata = { + &s5pv210_device_iis0, + &s5pv210_device_ac97, }; static void __init smdkv210_map_io(void) -- cgit v0.10.2 From 95fa6e6cd34d33915504d207a832920d98e4e932 Mon Sep 17 00:00:00 2001 From: Jassi Brar Date: Tue, 18 May 2010 16:02:35 +0900 Subject: ARM: SMDKC110: Add audio devices on board Add audio platform devices on the smdk by default. Signed-off-by: Jassi Brar Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5pv210/mach-smdkc110.c b/arch/arm/mach-s5pv210/mach-smdkc110.c index ab4869d..6f9fd32 100644 --- a/arch/arm/mach-s5pv210/mach-smdkc110.c +++ b/arch/arm/mach-s5pv210/mach-smdkc110.c @@ -72,6 +72,8 @@ static struct s3c2410_uartcfg smdkv210_uartcfgs[] __initdata = { }; static struct platform_device *smdkc110_devices[] __initdata = { + &s5pv210_device_iis0, + &s5pv210_device_ac97, }; static void __init smdkc110_map_io(void) -- cgit v0.10.2 From 070c808546f69bc37db14db96e043a3b8894e0e2 Mon Sep 17 00:00:00 2001 From: Jassi Brar Date: Tue, 18 May 2010 16:02:50 +0900 Subject: ARM: S5P6442: Add audio platform devices Define platform devices for all audio devices found on S5P6442 Signed-off-by: Jassi Brar Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5p6442/Makefile b/arch/arm/mach-s5p6442/Makefile index dde39a6..a43d5da 100644 --- a/arch/arm/mach-s5p6442/Makefile +++ b/arch/arm/mach-s5p6442/Makefile @@ -17,3 +17,6 @@ obj-$(CONFIG_CPU_S5P6442) += cpu.o init.o clock.o # machine support obj-$(CONFIG_MACH_SMDK6442) += mach-smdk6442.o + +# device support +obj-y += dev-audio.o diff --git a/arch/arm/mach-s5p6442/dev-audio.c b/arch/arm/mach-s5p6442/dev-audio.c new file mode 100644 index 0000000..cb801e1 --- /dev/null +++ b/arch/arm/mach-s5p6442/dev-audio.c @@ -0,0 +1,197 @@ +/* linux/arch/arm/mach-s5p6442/dev-audio.c + * + * Copyright (c) 2010 Samsung Electronics Co. Ltd + * Jaswinder Singh + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include + +#include +#include + +#include +#include +#include +#include + +static int s5p6442_cfg_i2s(struct platform_device *pdev) +{ + /* configure GPIO for i2s port */ + switch (pdev->id) { + case 1: + s3c_gpio_cfgpin(S5P6442_GPC1(0), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5P6442_GPC1(1), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5P6442_GPC1(2), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5P6442_GPC1(3), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5P6442_GPC1(4), S3C_GPIO_SFN(2)); + break; + + case -1: + s3c_gpio_cfgpin(S5P6442_GPC0(0), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5P6442_GPC0(1), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5P6442_GPC0(2), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5P6442_GPC0(3), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5P6442_GPC0(4), S3C_GPIO_SFN(2)); + break; + + default: + printk(KERN_ERR "Invalid Device %d\n", pdev->id); + return -EINVAL; + } + + return 0; +} + +static struct s3c_audio_pdata s3c_i2s_pdata = { + .cfg_gpio = s5p6442_cfg_i2s, +}; + +static struct resource s5p6442_iis0_resource[] = { + [0] = { + .start = S5P6442_PA_I2S0, + .end = S5P6442_PA_I2S0 + 0x100 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = DMACH_I2S0_TX, + .end = DMACH_I2S0_TX, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = DMACH_I2S0_RX, + .end = DMACH_I2S0_RX, + .flags = IORESOURCE_DMA, + }, +}; + +struct platform_device s5p6442_device_iis0 = { + .name = "s3c64xx-iis-v4", + .id = -1, + .num_resources = ARRAY_SIZE(s5p6442_iis0_resource), + .resource = s5p6442_iis0_resource, + .dev = { + .platform_data = &s3c_i2s_pdata, + }, +}; + +static struct resource s5p6442_iis1_resource[] = { + [0] = { + .start = S5P6442_PA_I2S1, + .end = S5P6442_PA_I2S1 + 0x100 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = DMACH_I2S1_TX, + .end = DMACH_I2S1_TX, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = DMACH_I2S1_RX, + .end = DMACH_I2S1_RX, + .flags = IORESOURCE_DMA, + }, +}; + +struct platform_device s5p6442_device_iis1 = { + .name = "s3c64xx-iis", + .id = 1, + .num_resources = ARRAY_SIZE(s5p6442_iis1_resource), + .resource = s5p6442_iis1_resource, + .dev = { + .platform_data = &s3c_i2s_pdata, + }, +}; + +/* PCM Controller platform_devices */ + +static int s5p6442_pcm_cfg_gpio(struct platform_device *pdev) +{ + switch (pdev->id) { + case 0: + s3c_gpio_cfgpin(S5P6442_GPC0(0), S3C_GPIO_SFN(3)); + s3c_gpio_cfgpin(S5P6442_GPC0(1), S3C_GPIO_SFN(3)); + s3c_gpio_cfgpin(S5P6442_GPC0(2), S3C_GPIO_SFN(3)); + s3c_gpio_cfgpin(S5P6442_GPC0(3), S3C_GPIO_SFN(3)); + s3c_gpio_cfgpin(S5P6442_GPC0(4), S3C_GPIO_SFN(3)); + break; + + case 1: + s3c_gpio_cfgpin(S5P6442_GPC1(0), S3C_GPIO_SFN(3)); + s3c_gpio_cfgpin(S5P6442_GPC1(1), S3C_GPIO_SFN(3)); + s3c_gpio_cfgpin(S5P6442_GPC1(2), S3C_GPIO_SFN(3)); + s3c_gpio_cfgpin(S5P6442_GPC1(3), S3C_GPIO_SFN(3)); + s3c_gpio_cfgpin(S5P6442_GPC1(4), S3C_GPIO_SFN(3)); + break; + + default: + printk(KERN_DEBUG "Invalid PCM Controller number!"); + return -EINVAL; + } + + return 0; +} + +static struct s3c_audio_pdata s3c_pcm_pdata = { + .cfg_gpio = s5p6442_pcm_cfg_gpio, +}; + +static struct resource s5p6442_pcm0_resource[] = { + [0] = { + .start = S5P6442_PA_PCM0, + .end = S5P6442_PA_PCM0 + 0x100 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = DMACH_PCM0_TX, + .end = DMACH_PCM0_TX, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = DMACH_PCM0_RX, + .end = DMACH_PCM0_RX, + .flags = IORESOURCE_DMA, + }, +}; + +struct platform_device s5p6442_device_pcm0 = { + .name = "samsung-pcm", + .id = 0, + .num_resources = ARRAY_SIZE(s5p6442_pcm0_resource), + .resource = s5p6442_pcm0_resource, + .dev = { + .platform_data = &s3c_pcm_pdata, + }, +}; + +static struct resource s5p6442_pcm1_resource[] = { + [0] = { + .start = S5P6442_PA_PCM1, + .end = S5P6442_PA_PCM1 + 0x100 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = DMACH_PCM1_TX, + .end = DMACH_PCM1_TX, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = DMACH_PCM1_RX, + .end = DMACH_PCM1_RX, + .flags = IORESOURCE_DMA, + }, +}; + +struct platform_device s5p6442_device_pcm1 = { + .name = "samsung-pcm", + .id = 1, + .num_resources = ARRAY_SIZE(s5p6442_pcm1_resource), + .resource = s5p6442_pcm1_resource, + .dev = { + .platform_data = &s3c_pcm_pdata, + }, +}; diff --git a/arch/arm/mach-s5p6442/include/mach/map.h b/arch/arm/mach-s5p6442/include/mach/map.h index 685277d..767c596 100644 --- a/arch/arm/mach-s5p6442/include/mach/map.h +++ b/arch/arm/mach-s5p6442/include/mach/map.h @@ -51,6 +51,14 @@ #define S5P6442_PA_SDRAM (0x20000000) #define S5P_PA_SDRAM S5P6442_PA_SDRAM +/* I2S */ +#define S5P6442_PA_I2S0 0xC0B00000 +#define S5P6442_PA_I2S1 0xF2200000 + +/* PCM */ +#define S5P6442_PA_PCM0 0xF2400000 +#define S5P6442_PA_PCM1 0xF2500000 + /* compatibiltiy defines. */ #define S3C_PA_UART S5P6442_PA_UART #define S3C_PA_IIC S5P6442_PA_IIC0 diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h index d8fda3a..ebf0387 100644 --- a/arch/arm/plat-samsung/include/plat/devs.h +++ b/arch/arm/plat-samsung/include/plat/devs.h @@ -72,6 +72,11 @@ extern struct platform_device s5pv210_device_iis0; extern struct platform_device s5pv210_device_iis1; extern struct platform_device s5pv210_device_iis2; +extern struct platform_device s5p6442_device_pcm0; +extern struct platform_device s5p6442_device_pcm1; +extern struct platform_device s5p6442_device_iis0; +extern struct platform_device s5p6442_device_iis1; + /* s3c2440 specific devices */ #ifdef CONFIG_CPU_S3C2440 -- cgit v0.10.2 From 78a368234f51e54a8878ab00375be91a22e945b3 Mon Sep 17 00:00:00 2001 From: Jassi Brar Date: Tue, 18 May 2010 16:02:58 +0900 Subject: ARM: SMDK6442: Add audio devices on board Add audio platform devices on the smdk by default. Signed-off-by: Jassi Brar Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5p6442/mach-smdk6442.c b/arch/arm/mach-s5p6442/mach-smdk6442.c index 0d63371..ebcf997 100644 --- a/arch/arm/mach-s5p6442/mach-smdk6442.c +++ b/arch/arm/mach-s5p6442/mach-smdk6442.c @@ -65,6 +65,7 @@ static struct s3c2410_uartcfg smdk6442_uartcfgs[] __initdata = { }; static struct platform_device *smdk6442_devices[] __initdata = { + &s5p6442_device_iis0, }; static void __init smdk6442_map_io(void) -- cgit v0.10.2 From 08885d0a4c4fa929c386e17c9682bf0d524146b9 Mon Sep 17 00:00:00 2001 From: Jassi Brar Date: Tue, 18 May 2010 16:03:02 +0900 Subject: ARM: S5P6440: Add audio platform devices Define platform devices for all audio devices found on S5P6440 Signed-off-by: Jassi Brar Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5p6440/Makefile b/arch/arm/mach-s5p6440/Makefile index 1ad894b..a2e99a2 100644 --- a/arch/arm/mach-s5p6440/Makefile +++ b/arch/arm/mach-s5p6440/Makefile @@ -17,3 +17,6 @@ obj-$(CONFIG_CPU_S5P6440) += cpu.o init.o clock.o gpio.o # machine support obj-$(CONFIG_MACH_SMDK6440) += mach-smdk6440.o + +# device support +obj-y += dev-audio.o diff --git a/arch/arm/mach-s5p6440/dev-audio.c b/arch/arm/mach-s5p6440/dev-audio.c new file mode 100644 index 0000000..0c53679 --- /dev/null +++ b/arch/arm/mach-s5p6440/dev-audio.c @@ -0,0 +1,127 @@ +/* linux/arch/arm/mach-s5p6440/dev-audio.c + * + * Copyright (c) 2010 Samsung Electronics Co. Ltd + * Jaswinder Singh + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include + +#include +#include + +#include +#include +#include +#include + +static int s5p6440_cfg_i2s(struct platform_device *pdev) +{ + /* configure GPIO for i2s port */ + switch (pdev->id) { + case -1: + s3c_gpio_cfgpin(S5P6440_GPR(4), S3C_GPIO_SFN(5)); + s3c_gpio_cfgpin(S5P6440_GPR(5), S3C_GPIO_SFN(5)); + s3c_gpio_cfgpin(S5P6440_GPR(6), S3C_GPIO_SFN(5)); + s3c_gpio_cfgpin(S5P6440_GPR(7), S3C_GPIO_SFN(5)); + s3c_gpio_cfgpin(S5P6440_GPR(8), S3C_GPIO_SFN(5)); + s3c_gpio_cfgpin(S5P6440_GPR(13), S3C_GPIO_SFN(5)); + s3c_gpio_cfgpin(S5P6440_GPR(14), S3C_GPIO_SFN(5)); + break; + + default: + printk(KERN_ERR "Invalid Device %d\n", pdev->id); + return -EINVAL; + } + + return 0; +} + +static struct s3c_audio_pdata s3c_i2s_pdata = { + .cfg_gpio = s5p6440_cfg_i2s, +}; + +static struct resource s5p6440_iis0_resource[] = { + [0] = { + .start = S5P6440_PA_I2S, + .end = S5P6440_PA_I2S + 0x100 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = DMACH_I2S0_TX, + .end = DMACH_I2S0_TX, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = DMACH_I2S0_RX, + .end = DMACH_I2S0_RX, + .flags = IORESOURCE_DMA, + }, +}; + +struct platform_device s5p6440_device_iis = { + .name = "s3c64xx-iis-v4", + .id = -1, + .num_resources = ARRAY_SIZE(s5p6440_iis0_resource), + .resource = s5p6440_iis0_resource, + .dev = { + .platform_data = &s3c_i2s_pdata, + }, +}; + +/* PCM Controller platform_devices */ + +static int s5p6440_pcm_cfg_gpio(struct platform_device *pdev) +{ + switch (pdev->id) { + case 0: + s3c_gpio_cfgpin(S5P6440_GPR(7), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5P6440_GPR(13), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5P6440_GPR(14), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5P6440_GPR(8), S3C_GPIO_SFN(2)); + s3c_gpio_cfgpin(S5P6440_GPR(6), S3C_GPIO_SFN(2)); + break; + + default: + printk(KERN_DEBUG "Invalid PCM Controller number!"); + return -EINVAL; + } + + return 0; +} + +static struct s3c_audio_pdata s3c_pcm_pdata = { + .cfg_gpio = s5p6440_pcm_cfg_gpio, +}; + +static struct resource s5p6440_pcm0_resource[] = { + [0] = { + .start = S5P6440_PA_PCM, + .end = S5P6440_PA_PCM + 0x100 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = DMACH_PCM0_TX, + .end = DMACH_PCM0_TX, + .flags = IORESOURCE_DMA, + }, + [2] = { + .start = DMACH_PCM0_RX, + .end = DMACH_PCM0_RX, + .flags = IORESOURCE_DMA, + }, +}; + +struct platform_device s5p6440_device_pcm = { + .name = "samsung-pcm", + .id = 0, + .num_resources = ARRAY_SIZE(s5p6440_pcm0_resource), + .resource = s5p6440_pcm0_resource, + .dev = { + .platform_data = &s3c_pcm_pdata, + }, +}; diff --git a/arch/arm/mach-s5p6440/include/mach/map.h b/arch/arm/mach-s5p6440/include/mach/map.h index 8924e5a..ccbfdae 100644 --- a/arch/arm/mach-s5p6440/include/mach/map.h +++ b/arch/arm/mach-s5p6440/include/mach/map.h @@ -61,6 +61,12 @@ #define S5P6440_PA_SDRAM (0x20000000) #define S5P_PA_SDRAM S5P6440_PA_SDRAM +/* I2S */ +#define S5P6440_PA_I2S 0xF2000000 + +/* PCM */ +#define S5P6440_PA_PCM 0xF2100000 + /* compatibiltiy defines. */ #define S3C_PA_UART S5P6440_PA_UART #define S3C_PA_IIC S5P6440_PA_IIC0 diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h index ebf0387..ef69e56 100644 --- a/arch/arm/plat-samsung/include/plat/devs.h +++ b/arch/arm/plat-samsung/include/plat/devs.h @@ -77,6 +77,9 @@ extern struct platform_device s5p6442_device_pcm1; extern struct platform_device s5p6442_device_iis0; extern struct platform_device s5p6442_device_iis1; +extern struct platform_device s5p6440_device_pcm; +extern struct platform_device s5p6440_device_iis; + /* s3c2440 specific devices */ #ifdef CONFIG_CPU_S3C2440 -- cgit v0.10.2 From 734552072335b00476b626b027ca4a9f57147b6f Mon Sep 17 00:00:00 2001 From: Jassi Brar Date: Tue, 18 May 2010 16:03:07 +0900 Subject: ARM: SMDK6440: Add audio devices on board Add audio platform devices on the smdk by default. Signed-off-by: Jassi Brar Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5p6440/mach-smdk6440.c b/arch/arm/mach-s5p6440/mach-smdk6440.c index 3ae88f2..d7fede9 100644 --- a/arch/arm/mach-s5p6440/mach-smdk6440.c +++ b/arch/arm/mach-s5p6440/mach-smdk6440.c @@ -84,6 +84,7 @@ static struct s3c2410_uartcfg smdk6440_uartcfgs[] __initdata = { }; static struct platform_device *smdk6440_devices[] __initdata = { + &s5p6440_device_iis, }; static void __init smdk6440_map_io(void) -- cgit v0.10.2 From 82b22c887e02fc6ebeebc8ec43fb1d348e2a6a58 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Thu, 6 May 2010 19:36:06 +0200 Subject: [IA64] removing redundant ifdef Pointless to use #ifdef CONFIG_NUMA in code that is already inside another #ifdef CONFIG_NUMA. Signed-off-by: Jiri Olsa Signed-off-by: Tony Luck diff --git a/arch/ia64/include/asm/mmzone.h b/arch/ia64/include/asm/mmzone.h index f2ca320..e0de617 100644 --- a/arch/ia64/include/asm/mmzone.h +++ b/arch/ia64/include/asm/mmzone.h @@ -19,16 +19,12 @@ static inline int pfn_to_nid(unsigned long pfn) { -#ifdef CONFIG_NUMA extern int paddr_to_nid(unsigned long); int nid = paddr_to_nid(pfn << PAGE_SHIFT); if (nid < 0) return 0; else return nid; -#else - return 0; -#endif } #ifdef CONFIG_IA64_DIG /* DIG systems are small */ -- cgit v0.10.2 From 80aa9bf0d8083554967400d48dbec078aa8f128e Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 5 Apr 2010 12:05:31 -0700 Subject: [IA64] arch/ia64/hp/common/sba_iommu.c: Rename dev_info to adi There is a macro called dev_info that prints struct device specific information. Having variables with the same name can be confusing and prevents conversion of the macro to a function. Rename the existing dev_info variables to something else in preparation to converting the dev_info macro to a function. Signed-off-by: Joe Perches Signed-off-by: Tony Luck diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c index e14c492..4ce8d13 100644 --- a/arch/ia64/hp/common/sba_iommu.c +++ b/arch/ia64/hp/common/sba_iommu.c @@ -2046,13 +2046,13 @@ acpi_sba_ioc_add(struct acpi_device *device) struct ioc *ioc; acpi_status status; u64 hpa, length; - struct acpi_device_info *dev_info; + struct acpi_device_info *adi; status = hp_acpi_csr_space(device->handle, &hpa, &length); if (ACPI_FAILURE(status)) return 1; - status = acpi_get_object_info(device->handle, &dev_info); + status = acpi_get_object_info(device->handle, &adi); if (ACPI_FAILURE(status)) return 1; @@ -2060,13 +2060,13 @@ acpi_sba_ioc_add(struct acpi_device *device) * For HWP0001, only SBA appears in ACPI namespace. It encloses the PCI * root bridges, and its CSR space includes the IOC function. */ - if (strncmp("HWP0001", dev_info->hardware_id.string, 7) == 0) { + if (strncmp("HWP0001", adi->hardware_id.string, 7) == 0) { hpa += ZX1_IOC_OFFSET; /* zx1 based systems default to kernel page size iommu pages */ if (!iovp_shift) iovp_shift = min(PAGE_SHIFT, 16); } - kfree(dev_info); + kfree(adi); /* * default anything not caught above or specified on cmdline to 4k -- cgit v0.10.2 From 93f7c93bee6382e01c34ea0c34ff8fb98c648734 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 26 Mar 2010 23:02:47 +0100 Subject: [IA64] Use set_cpus_allowed_ptr Use set_cpus_allowed_ptr rather than set_cpus_allowed. Signed-off-by: Julia Lawall Signed-off-by: Tony Luck diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c index 55ac3c4..f6c1c5f 100644 --- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c +++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c @@ -629,9 +629,9 @@ static int sn_hwperf_op_cpu(struct sn_hwperf_op_info *op_info) else { /* migrate the task before calling SAL */ save_allowed = current->cpus_allowed; - set_cpus_allowed(current, cpumask_of_cpu(cpu)); + set_cpus_allowed_ptr(current, cpumask_of(cpu)); sn_hwperf_call_sal(op_info); - set_cpus_allowed(current, save_allowed); + set_cpus_allowed_ptr(current, &save_allowed); } } r = op_info->ret; -- cgit v0.10.2 From 552dce3a071f0de2a84023fbba7f3b4ac36602cd Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 26 Mar 2010 23:02:23 +0100 Subject: [IA64] Use set_cpus_allowed_ptr Use set_cpus_allowed_ptr rather than set_cpus_allowed. Signed-off-by: Julia Lawall Signed-off-by: Tony Luck diff --git a/arch/ia64/kernel/cpufreq/acpi-cpufreq.c b/arch/ia64/kernel/cpufreq/acpi-cpufreq.c index b0b4e6e..22f6152 100644 --- a/arch/ia64/kernel/cpufreq/acpi-cpufreq.c +++ b/arch/ia64/kernel/cpufreq/acpi-cpufreq.c @@ -113,7 +113,7 @@ processor_get_freq ( dprintk("processor_get_freq\n"); saved_mask = current->cpus_allowed; - set_cpus_allowed(current, cpumask_of_cpu(cpu)); + set_cpus_allowed_ptr(current, cpumask_of(cpu)); if (smp_processor_id() != cpu) goto migrate_end; @@ -121,7 +121,7 @@ processor_get_freq ( ret = processor_get_pstate(&value); if (ret) { - set_cpus_allowed(current, saved_mask); + set_cpus_allowed_ptr(current, &saved_mask); printk(KERN_WARNING "get performance failed with error %d\n", ret); ret = 0; @@ -131,7 +131,7 @@ processor_get_freq ( ret = (clock_freq*1000); migrate_end: - set_cpus_allowed(current, saved_mask); + set_cpus_allowed_ptr(current, &saved_mask); return ret; } @@ -151,7 +151,7 @@ processor_set_freq ( dprintk("processor_set_freq\n"); saved_mask = current->cpus_allowed; - set_cpus_allowed(current, cpumask_of_cpu(cpu)); + set_cpus_allowed_ptr(current, cpumask_of(cpu)); if (smp_processor_id() != cpu) { retval = -EAGAIN; goto migrate_end; @@ -208,7 +208,7 @@ processor_set_freq ( retval = 0; migrate_end: - set_cpus_allowed(current, saved_mask); + set_cpus_allowed_ptr(current, &saved_mask); return (retval); } diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c index e6676fc..aa8b5fa 100644 --- a/arch/ia64/kernel/salinfo.c +++ b/arch/ia64/kernel/salinfo.c @@ -404,10 +404,9 @@ static void call_on_cpu(int cpu, void (*fn)(void *), void *arg) { cpumask_t save_cpus_allowed = current->cpus_allowed; - cpumask_t new_cpus_allowed = cpumask_of_cpu(cpu); - set_cpus_allowed(current, new_cpus_allowed); + set_cpus_allowed_ptr(current, cpumask_of(cpu)); (*fn)(arg); - set_cpus_allowed(current, save_cpus_allowed); + set_cpus_allowed_ptr(current, &save_cpus_allowed); } static void diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c index 28f299d..0baa1bb 100644 --- a/arch/ia64/kernel/topology.c +++ b/arch/ia64/kernel/topology.c @@ -361,12 +361,12 @@ static int __cpuinit cache_add_dev(struct sys_device * sys_dev) return 0; oldmask = current->cpus_allowed; - retval = set_cpus_allowed(current, cpumask_of_cpu(cpu)); + retval = set_cpus_allowed_ptr(current, cpumask_of(cpu)); if (unlikely(retval)) return retval; retval = cpu_cache_sysfs_init(cpu); - set_cpus_allowed(current, oldmask); + set_cpus_allowed_ptr(current, &oldmask); if (unlikely(retval < 0)) return retval; -- cgit v0.10.2 From 7683a3f9748f7adfbe47e33002a4f710ab557293 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sun, 28 Feb 2010 19:58:14 +0900 Subject: [IA64] use __ratelimit Replace open-coded rate limiting logic with __ratelimit(). Signed-off-by: Akinobu Mita Signed-off-by: Tony Luck diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c index 6404793..f14c35f 100644 --- a/arch/ia64/kernel/irq_ia64.c +++ b/arch/ia64/kernel/irq_ia64.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -467,13 +468,9 @@ ia64_handle_irq (ia64_vector vector, struct pt_regs *regs) sp = ia64_getreg(_IA64_REG_SP); if ((sp - bsp) < 1024) { - static unsigned char count; - static long last_time; + static DEFINE_RATELIMIT_STATE(ratelimit, 5 * HZ, 5); - if (time_after(jiffies, last_time + 5 * HZ)) - count = 0; - if (++count < 5) { - last_time = jiffies; + if (__ratelimit(&ratelimit)) { printk("ia64_handle_irq: DANGER: less than " "1KB of free stack space!!\n" "(bsp=0x%lx, sp=%lx)\n", bsp, sp); diff --git a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c index 776dd40..622772b 100644 --- a/arch/ia64/kernel/unaligned.c +++ b/arch/ia64/kernel/unaligned.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -1283,24 +1284,9 @@ emulate_store_float (unsigned long ifa, load_store_t ld, struct pt_regs *regs) /* * Make sure we log the unaligned access, so that user/sysadmin can notice it and * eventually fix the program. However, we don't want to do that for every access so we - * pace it with jiffies. This isn't really MP-safe, but it doesn't really have to be - * either... + * pace it with jiffies. */ -static int -within_logging_rate_limit (void) -{ - static unsigned long count, last_time; - - if (time_after(jiffies, last_time + 5 * HZ)) - count = 0; - if (count < 5) { - last_time = jiffies; - count++; - return 1; - } - return 0; - -} +static DEFINE_RATELIMIT_STATE(logging_rate_limit, 5 * HZ, 5); void ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) @@ -1337,7 +1323,7 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) if (!no_unaligned_warning && !(current->thread.flags & IA64_THREAD_UAC_NOPRINT) && - within_logging_rate_limit()) + __ratelimit(&logging_rate_limit)) { char buf[200]; /* comm[] is at most 16 bytes... */ size_t len; @@ -1370,7 +1356,7 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) } } } else { - if (within_logging_rate_limit()) { + if (__ratelimit(&logging_rate_limit)) { printk(KERN_WARNING "kernel unaligned access to 0x%016lx, ip=0x%016lx\n", ifa, regs->cr_iip + ipsr->ri); if (unaligned_dump_stack) -- cgit v0.10.2 From 0c3b96e44739cdba7a75030107a2b47a15ee5f60 Mon Sep 17 00:00:00 2001 From: "npiggin@suse.de" Date: Fri, 7 May 2010 14:34:33 -0700 Subject: [IA64] invoke oom-killer from page fault As explained in commit 1c0fe6e3bd, we want to call the architecture independent oom killer when getting an unexplained OOM from handle_mm_fault, rather than simply killing current. Acked-by: David Rientjes Signed-off-by: Nick Piggin Signed-off-by: Tony Luck diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c index 19261a9..0799fea 100644 --- a/arch/ia64/mm/fault.c +++ b/arch/ia64/mm/fault.c @@ -148,7 +148,6 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re if ((vma->vm_flags & mask) != mask) goto bad_area; - survive: /* * If for any reason at all we couldn't handle the fault, make * sure we exit gracefully rather than endlessly redo the @@ -276,13 +275,7 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re out_of_memory: up_read(&mm->mmap_sem); - if (is_global_init(current)) { - yield(); - down_read(&mm->mmap_sem); - goto survive; - } - printk(KERN_CRIT "VM: killing process %s\n", current->comm); - if (user_mode(regs)) - do_group_exit(SIGKILL); - goto no_context; + if (!user_mode(regs)) + goto no_context; + pagefault_out_of_memory(); } -- cgit v0.10.2 From 2a2ae2426bba944ce6dbcad35e1580df57aafcf1 Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Wed, 12 May 2010 09:30:27 -0700 Subject: [IA64] Drop duplicated "config IOMMU_HELPER" One entry for this in arch/ia64/Kconfig should be enough. Reported-by: Christoph Egger Signed-off-by: Tony Luck diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 4d4f418..9676100 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -59,9 +59,6 @@ config NEED_DMA_MAP_STATE config SWIOTLB bool -config IOMMU_HELPER - bool - config GENERIC_LOCKBREAK def_bool n -- cgit v0.10.2 From 1131379b48228afb32fa626fb27586a02246acf9 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 14 May 2010 08:18:52 +0200 Subject: ARM: SAMSUNGy: fix broken timer irq base Timer interrupts range was defined as 43-47, what overlaps with VIC0 range (32-64). This was caused probably by a typo while the common interrupts definition was refactored. This patch moves timer interrupt range to safe area of 11-15 (just before uart range). This fixes the commit 87aef30eb3c5dac0491c83fe3b90bc61f1df24ec ("ARM: S5P: Change S5P_TIMER_IRQ based to 11 for SAMSUNG S5P series.") which meant to move these into the old (and previously reserved) ISA space. Signed-off-by: Marek Szyprowski Signed-off-by: Kyungmin Park [ben-linux@fluff.org: update description] Signed-off-by: Ben Dooks diff --git a/arch/arm/plat-s5p/include/plat/irqs.h b/arch/arm/plat-s5p/include/plat/irqs.h index 42e757f..9ff3d71 100644 --- a/arch/arm/plat-s5p/include/plat/irqs.h +++ b/arch/arm/plat-s5p/include/plat/irqs.h @@ -79,7 +79,7 @@ #define S5P_IRQ_VIC2(x) (S5P_VIC2_BASE + (x)) #define S5P_IRQ_VIC3(x) (S5P_VIC3_BASE + (x)) -#define S5P_TIMER_IRQ(x) S5P_IRQ(11 + (x)) +#define S5P_TIMER_IRQ(x) (11 + (x)) #define IRQ_TIMER0 S5P_TIMER_IRQ(0) #define IRQ_TIMER1 S5P_TIMER_IRQ(1) -- cgit v0.10.2 From ea5f50706385b61c1c0d24271bbe7c6e93129fbc Mon Sep 17 00:00:00 2001 From: Pannaga Bhushan Date: Wed, 19 May 2010 17:25:32 +0900 Subject: ARM: S5PV210: Add GPIOlib support This patch adds GPIOlib support for S5PV210. Signed-off-by: Pannaga Bhushan Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5pv210/Makefile b/arch/arm/mach-s5pv210/Makefile index 8ebf51c..0acbdb3 100644 --- a/arch/arm/mach-s5pv210/Makefile +++ b/arch/arm/mach-s5pv210/Makefile @@ -12,7 +12,7 @@ obj- := # Core support for S5PV210 system -obj-$(CONFIG_CPU_S5PV210) += cpu.o init.o clock.o +obj-$(CONFIG_CPU_S5PV210) += cpu.o init.o clock.o gpiolib.o # machine support diff --git a/arch/arm/mach-s5pv210/gpiolib.c b/arch/arm/mach-s5pv210/gpiolib.c new file mode 100644 index 0000000..9ea8972 --- /dev/null +++ b/arch/arm/mach-s5pv210/gpiolib.c @@ -0,0 +1,261 @@ +/* linux/arch/arm/mach-s5pv210/gpiolib.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * S5PV210 - GPIOlib support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static struct s3c_gpio_cfg gpio_cfg = { + .set_config = s3c_gpio_setcfg_s3c64xx_4bit, + .set_pull = s3c_gpio_setpull_updown, + .get_pull = s3c_gpio_getpull_updown, +}; + +static struct s3c_gpio_cfg gpio_cfg_noint = { + .set_config = s3c_gpio_setcfg_s3c64xx_4bit, + .set_pull = s3c_gpio_setpull_updown, + .get_pull = s3c_gpio_getpull_updown, +}; + +/* GPIO bank's base address given the index of the bank in the + * list of all gpio banks. + */ +#define S5PV210_BANK_BASE(bank_nr) (S5P_VA_GPIO + ((bank_nr) * 0x20)) + +/* + * Following are the gpio banks in v210. + * + * The 'config' member when left to NULL, is initialized to the default + * structure gpio_cfg in the init function below. + * + * The 'base' member is also initialized in the init function below. + * Note: The initialization of 'base' member of s3c_gpio_chip structure + * uses the above macro and depends on the banks being listed in order here. + */ +static struct s3c_gpio_chip s5pv210_gpio_4bit[] = { + { + .chip = { + .base = S5PV210_GPA0(0), + .ngpio = S5PV210_GPIO_A0_NR, + .label = "GPA0", + }, + }, { + .chip = { + .base = S5PV210_GPA1(0), + .ngpio = S5PV210_GPIO_A1_NR, + .label = "GPA1", + }, + }, { + .chip = { + .base = S5PV210_GPB(0), + .ngpio = S5PV210_GPIO_B_NR, + .label = "GPB", + }, + }, { + .chip = { + .base = S5PV210_GPC0(0), + .ngpio = S5PV210_GPIO_C0_NR, + .label = "GPC0", + }, + }, { + .chip = { + .base = S5PV210_GPC1(0), + .ngpio = S5PV210_GPIO_C1_NR, + .label = "GPC1", + }, + }, { + .chip = { + .base = S5PV210_GPD0(0), + .ngpio = S5PV210_GPIO_D0_NR, + .label = "GPD0", + }, + }, { + .chip = { + .base = S5PV210_GPD1(0), + .ngpio = S5PV210_GPIO_D1_NR, + .label = "GPD1", + }, + }, { + .chip = { + .base = S5PV210_GPE0(0), + .ngpio = S5PV210_GPIO_E0_NR, + .label = "GPE0", + }, + }, { + .chip = { + .base = S5PV210_GPE1(0), + .ngpio = S5PV210_GPIO_E1_NR, + .label = "GPE1", + }, + }, { + .chip = { + .base = S5PV210_GPF0(0), + .ngpio = S5PV210_GPIO_F0_NR, + .label = "GPF0", + }, + }, { + .chip = { + .base = S5PV210_GPF1(0), + .ngpio = S5PV210_GPIO_F1_NR, + .label = "GPF1", + }, + }, { + .chip = { + .base = S5PV210_GPF2(0), + .ngpio = S5PV210_GPIO_F2_NR, + .label = "GPF2", + }, + }, { + .chip = { + .base = S5PV210_GPF3(0), + .ngpio = S5PV210_GPIO_F3_NR, + .label = "GPF3", + }, + }, { + .chip = { + .base = S5PV210_GPG0(0), + .ngpio = S5PV210_GPIO_G0_NR, + .label = "GPG0", + }, + }, { + .chip = { + .base = S5PV210_GPG1(0), + .ngpio = S5PV210_GPIO_G1_NR, + .label = "GPG1", + }, + }, { + .chip = { + .base = S5PV210_GPG2(0), + .ngpio = S5PV210_GPIO_G2_NR, + .label = "GPG2", + }, + }, { + .chip = { + .base = S5PV210_GPG3(0), + .ngpio = S5PV210_GPIO_G3_NR, + .label = "GPG3", + }, + }, { + .chip = { + .base = S5PV210_GPI(0), + .ngpio = S5PV210_GPIO_I_NR, + .label = "GPI", + }, + }, { + .chip = { + .base = S5PV210_GPJ0(0), + .ngpio = S5PV210_GPIO_J0_NR, + .label = "GPJ0", + }, + }, { + .chip = { + .base = S5PV210_GPJ1(0), + .ngpio = S5PV210_GPIO_J1_NR, + .label = "GPJ1", + }, + }, { + .chip = { + .base = S5PV210_GPJ2(0), + .ngpio = S5PV210_GPIO_J2_NR, + .label = "GPJ2", + }, + }, { + .chip = { + .base = S5PV210_GPJ3(0), + .ngpio = S5PV210_GPIO_J3_NR, + .label = "GPJ3", + }, + }, { + .chip = { + .base = S5PV210_GPJ4(0), + .ngpio = S5PV210_GPIO_J4_NR, + .label = "GPJ4", + }, + }, { + .config = &gpio_cfg_noint, + .chip = { + .base = S5PV210_MP01(0), + .ngpio = S5PV210_GPIO_MP01_NR, + .label = "MP01", + }, + }, { + .config = &gpio_cfg_noint, + .chip = { + .base = S5PV210_MP02(0), + .ngpio = S5PV210_GPIO_MP02_NR, + .label = "MP02", + }, + }, { + .config = &gpio_cfg_noint, + .chip = { + .base = S5PV210_MP03(0), + .ngpio = S5PV210_GPIO_MP03_NR, + .label = "MP03", + }, + }, { + .base = (S5P_VA_GPIO + 0xC00), + .config = &gpio_cfg_noint, + .chip = { + .base = S5PV210_GPH0(0), + .ngpio = S5PV210_GPIO_H0_NR, + .label = "GPH0", + }, + }, { + .base = (S5P_VA_GPIO + 0xC20), + .config = &gpio_cfg_noint, + .chip = { + .base = S5PV210_GPH1(0), + .ngpio = S5PV210_GPIO_H1_NR, + .label = "GPH1", + }, + }, { + .base = (S5P_VA_GPIO + 0xC40), + .config = &gpio_cfg_noint, + .chip = { + .base = S5PV210_GPH2(0), + .ngpio = S5PV210_GPIO_H2_NR, + .label = "GPH2", + }, + }, { + .base = (S5P_VA_GPIO + 0xC60), + .config = &gpio_cfg_noint, + .chip = { + .base = S5PV210_GPH3(0), + .ngpio = S5PV210_GPIO_H3_NR, + .label = "GPH3", + }, + }, +}; + +static __init int s5pv210_gpiolib_init(void) +{ + struct s3c_gpio_chip *chip = s5pv210_gpio_4bit; + int nr_chips = ARRAY_SIZE(s5pv210_gpio_4bit); + int i = 0; + + for (i = 0; i < nr_chips; i++, chip++) { + if (chip->config == NULL) + chip->config = &gpio_cfg; + if (chip->base == NULL) + chip->base = S5PV210_BANK_BASE(i); + } + + samsung_gpiolib_add_4bit_chips(s5pv210_gpio_4bit, nr_chips); + + return 0; +} +core_initcall(s5pv210_gpiolib_init); diff --git a/arch/arm/mach-s5pv210/include/mach/gpio.h b/arch/arm/mach-s5pv210/include/mach/gpio.h index 533b020..d6461ba 100644 --- a/arch/arm/mach-s5pv210/include/mach/gpio.h +++ b/arch/arm/mach-s5pv210/include/mach/gpio.h @@ -18,6 +18,8 @@ #define gpio_cansleep __gpio_cansleep #define gpio_to_irq __gpio_to_irq +/* Practically, GPIO banks upto MP03 are the configurable gpio banks */ + /* GPIO bank sizes */ #define S5PV210_GPIO_A0_NR (8) #define S5PV210_GPIO_A1_NR (4) @@ -47,6 +49,10 @@ #define S5PV210_GPIO_J3_NR (8) #define S5PV210_GPIO_J4_NR (5) +#define S5PV210_GPIO_MP01_NR (8) +#define S5PV210_GPIO_MP02_NR (4) +#define S5PV210_GPIO_MP03_NR (8) + /* GPIO bank numbers */ /* CONFIG_S3C_GPIO_SPACE allows the user to select extra @@ -85,6 +91,9 @@ enum s5p_gpio_number { S5PV210_GPIO_J2_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_J1), S5PV210_GPIO_J3_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_J2), S5PV210_GPIO_J4_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_J3), + S5PV210_GPIO_MP01_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_J4), + S5PV210_GPIO_MP02_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP01), + S5PV210_GPIO_MP03_START = S5PV210_GPIO_NEXT(S5PV210_GPIO_MP02), }; /* S5PV210 GPIO number definitions */ @@ -115,13 +124,16 @@ enum s5p_gpio_number { #define S5PV210_GPJ2(_nr) (S5PV210_GPIO_J2_START + (_nr)) #define S5PV210_GPJ3(_nr) (S5PV210_GPIO_J3_START + (_nr)) #define S5PV210_GPJ4(_nr) (S5PV210_GPIO_J4_START + (_nr)) +#define S5PV210_MP01(_nr) (S5PV210_GPIO_MP01_START + (_nr)) +#define S5PV210_MP02(_nr) (S5PV210_GPIO_MP02_START + (_nr)) +#define S5PV210_MP03(_nr) (S5PV210_GPIO_MP03_START + (_nr)) /* the end of the S5PV210 specific gpios */ -#define S5PV210_GPIO_END (S5PV210_GPJ4(S5PV210_GPIO_J4_NR) + 1) +#define S5PV210_GPIO_END (S5PV210_MP03(S5PV210_GPIO_MP03_NR) + 1) #define S3C_GPIO_END S5PV210_GPIO_END -/* define the number of gpios we need to the one after the GPJ4() range */ -#define ARCH_NR_GPIOS (S5PV210_GPJ4(S5PV210_GPIO_J4_NR) + \ +/* define the number of gpios we need to the one after the MP03() range */ +#define ARCH_NR_GPIOS (S5PV210_MP03(S5PV210_GPIO_MP03_NR) + \ CONFIG_SAMSUNG_GPIO_EXTRA + 1) #include -- cgit v0.10.2 From 838c6d499b780c42fccbbdfecc0f5dcc471d0ef3 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 18 May 2010 12:23:36 +0200 Subject: ARM: SAMSUNG: move driver strength gpio configuration helper to common dir Driver strength parameter can be changed not only on S5PC100 but also on S5PV210/S5PC110 platforms, so move the helper functions to the common plat-samsung directory. Signed-off-by: Marek Szyprowski Signed-off-by: Kyungmin Park Signed-off-by: Ben Dooks diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig index d400a6a..92bd756 100644 --- a/arch/arm/plat-s5p/Kconfig +++ b/arch/arm/plat-s5p/Kconfig @@ -13,6 +13,7 @@ config PLAT_S5P select NO_IOPORT select ARCH_REQUIRE_GPIOLIB select S3C_GPIO_TRACK + select S5P_GPIO_DRVSTR select SAMSUNG_GPIOLIB_4BIT select S3C_GPIO_CFG_S3C64XX select S3C_GPIO_PULL_UPDOWN diff --git a/arch/arm/plat-s5pc1xx/Kconfig b/arch/arm/plat-s5pc1xx/Kconfig index c7ccdf2..79d3be7 100644 --- a/arch/arm/plat-s5pc1xx/Kconfig +++ b/arch/arm/plat-s5pc1xx/Kconfig @@ -16,9 +16,9 @@ config PLAT_S5PC1XX select SAMSUNG_IRQ_VIC_TIMER select S3C_GPIO_TRACK select S3C_GPIO_PULL_UPDOWN + select S5P_GPIO_DRVSTR select S3C_GPIO_CFG_S3C24XX select S3C_GPIO_CFG_S3C64XX - select S5P_GPIO_CFG_S5PC1XX help Base platform code for any Samsung S5PC1XX device diff --git a/arch/arm/plat-s5pc1xx/Makefile b/arch/arm/plat-s5pc1xx/Makefile index 278f268..66a8f3e 100644 --- a/arch/arm/plat-s5pc1xx/Makefile +++ b/arch/arm/plat-s5pc1xx/Makefile @@ -24,7 +24,6 @@ obj-$(CONFIG_CPU_S5PC100_CLOCK) += s5pc100-clock.o # Device setup -obj-$(CONFIG_S5P_GPIO_CFG_S5PC1XX) += gpio-config.o obj-$(CONFIG_S5PC1XX_SETUP_FB_24BPP) += setup-fb-24bpp.o obj-$(CONFIG_S5PC1XX_SETUP_I2C0) += setup-i2c0.o obj-$(CONFIG_S5PC1XX_SETUP_I2C1) += setup-i2c1.o diff --git a/arch/arm/plat-s5pc1xx/gpio-config.c b/arch/arm/plat-s5pc1xx/gpio-config.c deleted file mode 100644 index a4f67e8..0000000 --- a/arch/arm/plat-s5pc1xx/gpio-config.c +++ /dev/null @@ -1,62 +0,0 @@ -/* linux/arch/arm/plat-s5pc1xx/gpio-config.c - * - * Copyright 2009 Samsung Electronics - * - * S5PC1XX GPIO Configuration. - * - * Based on plat-s3c64xx/gpio-config.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#include -#include -#include -#include - -#include -#include - -s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin, unsigned int off) -{ - struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); - void __iomem *reg; - int shift = off * 2; - u32 drvstr; - - if (!chip) - return -EINVAL; - - reg = chip->base + 0x0C; - - drvstr = __raw_readl(reg); - drvstr = 0xffff & (0x3 << shift); - drvstr = drvstr >> shift; - - return (__force s5p_gpio_drvstr_t)drvstr; -} -EXPORT_SYMBOL(s5p_gpio_get_drvstr); - -int s5p_gpio_set_drvstr(unsigned int pin, unsigned int off, - s5p_gpio_drvstr_t drvstr) -{ - struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); - void __iomem *reg; - int shift = off * 2; - u32 tmp; - - if (!chip) - return -EINVAL; - - reg = chip->base + 0x0C; - - tmp = __raw_readl(reg); - tmp |= drvstr << shift; - - __raw_writel(tmp, reg); - - return 0; -} -EXPORT_SYMBOL(s5p_gpio_set_drvstr); diff --git a/arch/arm/plat-s5pc1xx/include/plat/gpio-cfg-s5pc1xx.h b/arch/arm/plat-s5pc1xx/include/plat/gpio-cfg-s5pc1xx.h deleted file mode 100644 index 72ad59f..0000000 --- a/arch/arm/plat-s5pc1xx/include/plat/gpio-cfg-s5pc1xx.h +++ /dev/null @@ -1,32 +0,0 @@ -/* linux/arch/arm/plat-s5pc1xx/include/plat/gpio-cfg.h - * - * Copyright 2009 Samsung Electronic - * - * S5PC1XX Platform - GPIO pin configuration - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -/* This file contains the necessary definitions to get the basic gpio - * pin configuration done such as setting a pin to input or output or - * changing the pull-{up,down} configurations. - */ - -#ifndef __GPIO_CFG_S5PC1XX_H -#define __GPIO_CFG_S5PC1XX_H __FILE__ - -typedef unsigned int __bitwise__ s5p_gpio_drvstr_t; - -#define S5P_GPIO_DRVSTR_LV1 0x00 -#define S5P_GPIO_DRVSTR_LV2 0x01 -#define S5P_GPIO_DRVSTR_LV3 0x10 -#define S5P_GPIO_DRVSTR_LV4 0x11 - -extern s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin, unsigned int off); - -extern int s5p_gpio_set_drvstr(unsigned int pin, unsigned int off, - s5p_gpio_drvstr_t drvstr); - -#endif /* __GPIO_CFG_S5PC1XX_H */ diff --git a/arch/arm/plat-s5pc1xx/setup-fb-24bpp.c b/arch/arm/plat-s5pc1xx/setup-fb-24bpp.c index 1a63768..b02c36f 100644 --- a/arch/arm/plat-s5pc1xx/setup-fb-24bpp.c +++ b/arch/arm/plat-s5pc1xx/setup-fb-24bpp.c @@ -19,7 +19,6 @@ #include #include #include -#include #define DISR_OFFSET 0x7008 diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig index c91c21a..711d5a4 100644 --- a/arch/arm/plat-samsung/Kconfig +++ b/arch/arm/plat-samsung/Kconfig @@ -90,12 +90,6 @@ config S3C_GPIO_CFG_S3C64XX Internal configuration to enable S3C64XX style GPIO configuration functions. -config S5P_GPIO_CFG_S5PC1XX - bool - help - Internal configuration to enable S5PC1XX style GPIO configuration - functions. - config S3C_GPIO_PULL_UPDOWN bool help @@ -111,6 +105,12 @@ config S3C_GPIO_PULL_UP help Internal configuration to enable the correct GPIO pull helper +config S5P_GPIO_DRVSTR + bool + help + Internal configuration to get and set correct GPIO driver strength + helper + config SAMSUNG_GPIO_EXTRA int "Number of additional GPIO pins" default 0 diff --git a/arch/arm/plat-samsung/gpio-config.c b/arch/arm/plat-samsung/gpio-config.c index a76eef5..57b68a5 100644 --- a/arch/arm/plat-samsung/gpio-config.c +++ b/arch/arm/plat-samsung/gpio-config.c @@ -261,3 +261,51 @@ s3c_gpio_pull_t s3c_gpio_getpull_1up(struct s3c_gpio_chip *chip, } #endif /* CONFIG_S3C_GPIO_PULL_UP */ +#ifdef CONFIG_S5P_GPIO_DRVSTR +s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin) +{ + struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); + unsigned int off; + void __iomem *reg; + int shift; + u32 drvstr; + + if (!chip) + return -EINVAL; + + off = chip->chip.base - pin; + shift = off * 2; + reg = chip->base + 0x0C; + + drvstr = __raw_readl(reg); + drvstr = 0xffff & (0x3 << shift); + drvstr = drvstr >> shift; + + return (__force s5p_gpio_drvstr_t)drvstr; +} +EXPORT_SYMBOL(s5p_gpio_get_drvstr); + +int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr) +{ + struct s3c_gpio_chip *chip = s3c_gpiolib_getchip(pin); + unsigned int off; + void __iomem *reg; + int shift; + u32 tmp; + + if (!chip) + return -EINVAL; + + off = chip->chip.base - pin; + shift = off * 2; + reg = chip->base + 0x0C; + + tmp = __raw_readl(reg); + tmp |= drvstr << shift; + + __raw_writel(tmp, reg); + + return 0; +} +EXPORT_SYMBOL(s5p_gpio_set_drvstr); +#endif /* CONFIG_S5P_GPIO_DRVSTR */ diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg.h b/arch/arm/plat-samsung/include/plat/gpio-cfg.h index 8d01e85..34efdd2 100644 --- a/arch/arm/plat-samsung/include/plat/gpio-cfg.h +++ b/arch/arm/plat-samsung/include/plat/gpio-cfg.h @@ -25,6 +25,7 @@ #define __PLAT_GPIO_CFG_H __FILE__ typedef unsigned int __bitwise__ s3c_gpio_pull_t; +typedef unsigned int __bitwise__ s5p_gpio_drvstr_t; /* forward declaration if gpio-core.h hasn't been included */ struct s3c_gpio_chip; @@ -118,4 +119,33 @@ extern int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull); */ extern s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin); +/* Define values for the drvstr available for each gpio pin. + * + * These values control the value of the output signal driver strength, + * configurable on most pins on the S5C series. + */ +#define S5P_GPIO_DRVSTR_LV1 ((__force s5p_gpio_drvstr_t)0x00) +#define S5P_GPIO_DRVSTR_LV2 ((__force s5p_gpio_drvstr_t)0x01) +#define S5P_GPIO_DRVSTR_LV3 ((__force s5p_gpio_drvstr_t)0x10) +#define S5P_GPIO_DRVSTR_LV4 ((__force s5p_gpio_drvstr_t)0x11) + +/** + * s5c_gpio_get_drvstr() - get the driver streght value of a gpio pin + * @pin: The pin number to get the settings for + * + * Read the driver streght value for the specified pin. +*/ +extern s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin); + +/** + * s3c_gpio_set_drvstr() - set the driver streght value of a gpio pin + * @pin: The pin number to configure the driver streght value + * @drvstr: The new value of the driver strength + * + * This function sets the driver strength value for the specified pin. + * It will return 0 if successfull, or a negative error code if the pin + * cannot support the requested setting. +*/ +extern int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr); + #endif /* __PLAT_GPIO_CFG_H */ -- cgit v0.10.2 From a0f735812e9ffb65fa4c8a16975f5b63909fb447 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 18 May 2010 12:23:35 +0200 Subject: ARM: SAMSUNG: Copy common I2C0 device helpers to machine directories Signed-off-by: Marek Szyprowski Signed-off-by: Kyungmin Park Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5p6440/Makefile b/arch/arm/mach-s5p6440/Makefile index 5fd17d3..44facf4 100644 --- a/arch/arm/mach-s5p6440/Makefile +++ b/arch/arm/mach-s5p6440/Makefile @@ -13,6 +13,7 @@ obj- := # Core support for S5P6440 system obj-$(CONFIG_CPU_S5P6440) += cpu.o init.o clock.o gpio.o dma.o +obj-$(CONFIG_CPU_S5P6440) += setup-i2c0.o # machine support diff --git a/arch/arm/mach-s5p6440/setup-i2c0.c b/arch/arm/mach-s5p6440/setup-i2c0.c new file mode 100644 index 0000000..69e8a66 --- /dev/null +++ b/arch/arm/mach-s5p6440/setup-i2c0.c @@ -0,0 +1,25 @@ +/* linux/arch/arm/mach-s5p6440/setup-i2c0.c + * + * Copyright (c) 2009 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * I2C0 GPIO configuration. + * + * Based on plat-s3c64xx/setup-i2c0.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include + +struct platform_device; /* don't need the contents */ + +#include + +void s3c_i2c0_cfg_gpio(struct platform_device *dev) +{ + /* Will be populated later */ +} diff --git a/arch/arm/mach-s5p6442/Makefile b/arch/arm/mach-s5p6442/Makefile index bf30550..e30a7f7 100644 --- a/arch/arm/mach-s5p6442/Makefile +++ b/arch/arm/mach-s5p6442/Makefile @@ -13,6 +13,7 @@ obj- := # Core support for S5P6442 system obj-$(CONFIG_CPU_S5P6442) += cpu.o init.o clock.o dma.o +obj-$(CONFIG_CPU_S5P6442) += setup-i2c0.o # machine support diff --git a/arch/arm/mach-s5p6442/setup-i2c0.c b/arch/arm/mach-s5p6442/setup-i2c0.c new file mode 100644 index 0000000..662695d --- /dev/null +++ b/arch/arm/mach-s5p6442/setup-i2c0.c @@ -0,0 +1,25 @@ +/* linux/arch/arm/mach-s5p6442/setup-i2c0.c + * + * Copyright (c) 2009 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * I2C0 GPIO configuration. + * + * Based on plat-s3c64xx/setup-i2c0.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include + +struct platform_device; /* don't need the contents */ + +#include + +void s3c_i2c0_cfg_gpio(struct platform_device *dev) +{ + /* Will be populated later */ +} diff --git a/arch/arm/mach-s5pv210/Makefile b/arch/arm/mach-s5pv210/Makefile index 1d60b35..9982781 100644 --- a/arch/arm/mach-s5pv210/Makefile +++ b/arch/arm/mach-s5pv210/Makefile @@ -13,6 +13,7 @@ obj- := # Core support for S5PV210 system obj-$(CONFIG_CPU_S5PV210) += cpu.o init.o clock.o dma.o gpiolib.o +obj-$(CONFIG_CPU_S5PV210) += setup-i2c0.o # machine support diff --git a/arch/arm/mach-s5pv210/setup-i2c0.c b/arch/arm/mach-s5pv210/setup-i2c0.c new file mode 100644 index 0000000..9ec6845 --- /dev/null +++ b/arch/arm/mach-s5pv210/setup-i2c0.c @@ -0,0 +1,25 @@ +/* linux/arch/arm/mach-s5pv210/setup-i2c0.c + * + * Copyright (c) 2009 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * I2C0 GPIO configuration. + * + * Based on plat-s3c64xx/setup-i2c0.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include + +struct platform_device; /* don't need the contents */ + +#include + +void s3c_i2c0_cfg_gpio(struct platform_device *dev) +{ + /* Will be populated later */ +} diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile index a7c54b3..0ec09a9 100644 --- a/arch/arm/plat-s5p/Makefile +++ b/arch/arm/plat-s5p/Makefile @@ -16,4 +16,3 @@ obj-y += dev-uart.o obj-y += cpu.o obj-y += clock.o obj-y += irq.o -obj-y += setup-i2c0.o diff --git a/arch/arm/plat-s5p/setup-i2c0.c b/arch/arm/plat-s5p/setup-i2c0.c deleted file mode 100644 index 67a66e0..0000000 --- a/arch/arm/plat-s5p/setup-i2c0.c +++ /dev/null @@ -1,25 +0,0 @@ -/* linux/arch/arm/plat-s5p/setup-i2c0.c - * - * Copyright (c) 2009 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * I2C0 GPIO configuration. - * - * Based on plat-s3c64xx/setup-i2c0.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#include -#include - -struct platform_device; /* don't need the contents */ - -#include - -void s3c_i2c0_cfg_gpio(struct platform_device *dev) -{ - /* Will be populated later */ -} -- cgit v0.10.2 From a443a6373d8527657cfde3d3c515d4a64532c585 Mon Sep 17 00:00:00 2001 From: Thomas Abraham Date: Fri, 14 May 2010 16:27:28 +0900 Subject: ARM: S5PC100: Pre-requisite clock patch for plat-s5pc1xx to plat-s5p move This is a pre-requisite clock patch for the plat-s5pc1xx to plat-s5p movement. The patches that perform the movement of the code from plat-s5pc1xx to plat-s5p (and mach-s5pc100) should also enable the build for the mach-s5pc100/clock.c code. Signed-off-by: Thomas Abraham Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5pc100/clock.c b/arch/arm/mach-s5pc100/clock.c new file mode 100644 index 0000000..e3fed4c --- /dev/null +++ b/arch/arm/mach-s5pc100/clock.c @@ -0,0 +1,1358 @@ +/* linux/arch/arm/mach-s5pc100/clock.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * S5PC100 - Clock support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +static struct clk s5p_clk_otgphy = { + .name = "otg_phy", + .id = -1, +}; + +static struct clk *clk_src_mout_href_list[] = { + [0] = &s5p_clk_27m, + [1] = &clk_fin_hpll, +}; + +static struct clksrc_sources clk_src_mout_href = { + .sources = clk_src_mout_href_list, + .nr_sources = ARRAY_SIZE(clk_src_mout_href_list), +}; + +static struct clksrc_clk clk_mout_href = { + .clk = { + .name = "mout_href", + .id = -1, + }, + .sources = &clk_src_mout_href, + .reg_src = { .reg = S5P_CLK_SRC0, .shift = 20, .size = 1 }, +}; + +static struct clk *clk_src_mout_48m_list[] = { + [0] = &clk_xusbxti, + [1] = &s5p_clk_otgphy, +}; + +static struct clksrc_sources clk_src_mout_48m = { + .sources = clk_src_mout_48m_list, + .nr_sources = ARRAY_SIZE(clk_src_mout_48m_list), +}; + +static struct clksrc_clk clk_mout_48m = { + .clk = { + .name = "mout_48m", + .id = -1, + }, + .sources = &clk_src_mout_48m, + .reg_src = { .reg = S5P_CLK_SRC1, .shift = 24, .size = 1 }, +}; + +static struct clksrc_clk clk_mout_mpll = { + .clk = { + .name = "mout_mpll", + .id = -1, + }, + .sources = &clk_src_mpll, + .reg_src = { .reg = S5P_CLK_SRC0, .shift = 4, .size = 1 }, +}; + + +static struct clksrc_clk clk_mout_apll = { + .clk = { + .name = "mout_apll", + .id = -1, + }, + .sources = &clk_src_apll, + .reg_src = { .reg = S5P_CLK_SRC0, .shift = 0, .size = 1 }, +}; + +static struct clksrc_clk clk_mout_epll = { + .clk = { + .name = "mout_epll", + .id = -1, + }, + .sources = &clk_src_epll, + .reg_src = { .reg = S5P_CLK_SRC0, .shift = 8, .size = 1 }, +}; + +static struct clk *clk_src_mout_hpll_list[] = { + [0] = &s5p_clk_27m, +}; + +static struct clksrc_sources clk_src_mout_hpll = { + .sources = clk_src_mout_hpll_list, + .nr_sources = ARRAY_SIZE(clk_src_mout_hpll_list), +}; + +static struct clksrc_clk clk_mout_hpll = { + .clk = { + .name = "mout_hpll", + .id = -1, + }, + .sources = &clk_src_mout_hpll, + .reg_src = { .reg = S5P_CLK_SRC0, .shift = 12, .size = 1 }, +}; + +static struct clksrc_clk clk_div_apll = { + .clk = { + .name = "div_apll", + .id = -1, + .parent = &clk_mout_apll.clk, + }, + .reg_div = { .reg = S5P_CLK_DIV0, .shift = 0, .size = 1 }, +}; + +static struct clksrc_clk clk_div_arm = { + .clk = { + .name = "div_arm", + .id = -1, + .parent = &clk_div_apll.clk, + }, + .reg_div = { .reg = S5P_CLK_DIV0, .shift = 4, .size = 3 }, +}; + +static struct clksrc_clk clk_div_d0_bus = { + .clk = { + .name = "div_d0_bus", + .id = -1, + .parent = &clk_div_arm.clk, + }, + .reg_div = { .reg = S5P_CLK_DIV0, .shift = 8, .size = 3 }, +}; + +static struct clksrc_clk clk_div_pclkd0 = { + .clk = { + .name = "div_pclkd0", + .id = -1, + .parent = &clk_div_d0_bus.clk, + }, + .reg_div = { .reg = S5P_CLK_DIV0, .shift = 12, .size = 3 }, +}; + +static struct clksrc_clk clk_div_secss = { + .clk = { + .name = "div_secss", + .id = -1, + .parent = &clk_div_d0_bus.clk, + }, + .reg_div = { .reg = S5P_CLK_DIV0, .shift = 16, .size = 3 }, +}; + +static struct clksrc_clk clk_div_apll2 = { + .clk = { + .name = "div_apll2", + .id = -1, + .parent = &clk_mout_apll.clk, + }, + .reg_div = { .reg = S5P_CLK_DIV1, .shift = 0, .size = 3 }, +}; + +static struct clk *clk_src_mout_am_list[] = { + [0] = &clk_mout_mpll.clk, + [1] = &clk_div_apll2.clk, +}; + +struct clksrc_sources clk_src_mout_am = { + .sources = clk_src_mout_am_list, + .nr_sources = ARRAY_SIZE(clk_src_mout_am_list), +}; + +static struct clksrc_clk clk_mout_am = { + .clk = { + .name = "mout_am", + .id = -1, + }, + .sources = &clk_src_mout_am, + .reg_src = { .reg = S5P_CLK_SRC0, .shift = 16, .size = 1 }, +}; + +static struct clksrc_clk clk_div_d1_bus = { + .clk = { + .name = "div_d1_bus", + .id = -1, + .parent = &clk_mout_am.clk, + }, + .reg_div = { .reg = S5P_CLK_DIV1, .shift = 12, .size = 3 }, +}; + +static struct clksrc_clk clk_div_mpll2 = { + .clk = { + .name = "div_mpll2", + .id = -1, + .parent = &clk_mout_am.clk, + }, + .reg_div = { .reg = S5P_CLK_DIV1, .shift = 8, .size = 1 }, +}; + +static struct clksrc_clk clk_div_mpll = { + .clk = { + .name = "div_mpll", + .id = -1, + .parent = &clk_mout_am.clk, + }, + .reg_div = { .reg = S5P_CLK_DIV1, .shift = 4, .size = 2 }, +}; + +static struct clk *clk_src_mout_onenand_list[] = { + [0] = &clk_div_d0_bus.clk, + [1] = &clk_div_d1_bus.clk, +}; + +struct clksrc_sources clk_src_mout_onenand = { + .sources = clk_src_mout_onenand_list, + .nr_sources = ARRAY_SIZE(clk_src_mout_onenand_list), +}; + +static struct clksrc_clk clk_mout_onenand = { + .clk = { + .name = "mout_onenand", + .id = -1, + }, + .sources = &clk_src_mout_onenand, + .reg_src = { .reg = S5P_CLK_SRC0, .shift = 24, .size = 1 }, +}; + +static struct clksrc_clk clk_div_onenand = { + .clk = { + .name = "div_onenand", + .id = -1, + .parent = &clk_mout_onenand.clk, + }, + .reg_div = { .reg = S5P_CLK_DIV1, .shift = 20, .size = 2 }, +}; + +static struct clksrc_clk clk_div_pclkd1 = { + .clk = { + .name = "div_pclkd1", + .id = -1, + .parent = &clk_div_d1_bus.clk, + }, + .reg_div = { .reg = S5P_CLK_DIV1, .shift = 16, .size = 3 }, +}; + +static struct clksrc_clk clk_div_cam = { + .clk = { + .name = "div_cam", + .id = -1, + .parent = &clk_div_mpll2.clk, + }, + .reg_div = { .reg = S5P_CLK_DIV1, .shift = 24, .size = 5 }, +}; + +static struct clksrc_clk clk_div_hdmi = { + .clk = { + .name = "div_hdmi", + .id = -1, + .parent = &clk_mout_hpll.clk, + }, + .reg_div = { .reg = S5P_CLK_DIV3, .shift = 28, .size = 4 }, +}; + +static int s5pc100_epll_enable(struct clk *clk, int enable) +{ + unsigned int ctrlbit = clk->ctrlbit; + unsigned int epll_con = __raw_readl(S5P_EPLL_CON) & ~ctrlbit; + + if (enable) + __raw_writel(epll_con | ctrlbit, S5P_EPLL_CON); + else + __raw_writel(epll_con, S5P_EPLL_CON); + + return 0; +} + +static unsigned long s5pc100_epll_get_rate(struct clk *clk) +{ + return clk->rate; +} + +static u32 epll_div[][4] = { + { 32750000, 131, 3, 4 }, + { 32768000, 131, 3, 4 }, + { 36000000, 72, 3, 3 }, + { 45000000, 90, 3, 3 }, + { 45158000, 90, 3, 3 }, + { 45158400, 90, 3, 3 }, + { 48000000, 96, 3, 3 }, + { 49125000, 131, 4, 3 }, + { 49152000, 131, 4, 3 }, + { 60000000, 120, 3, 3 }, + { 67737600, 226, 5, 3 }, + { 67738000, 226, 5, 3 }, + { 73800000, 246, 5, 3 }, + { 73728000, 246, 5, 3 }, + { 72000000, 144, 3, 3 }, + { 84000000, 168, 3, 3 }, + { 96000000, 96, 3, 2 }, + { 144000000, 144, 3, 2 }, + { 192000000, 96, 3, 1 } +}; + +static int s5pc100_epll_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned int epll_con; + unsigned int i; + + if (clk->rate == rate) /* Return if nothing changed */ + return 0; + + epll_con = __raw_readl(S5P_EPLL_CON); + + epll_con &= ~(PLL65XX_MDIV_MASK | PLL65XX_PDIV_MASK | PLL65XX_SDIV_MASK); + + for (i = 0; i < ARRAY_SIZE(epll_div); i++) { + if (epll_div[i][0] == rate) { + epll_con |= (epll_div[i][1] << PLL65XX_MDIV_SHIFT) | + (epll_div[i][2] << PLL65XX_PDIV_SHIFT) | + (epll_div[i][3] << PLL65XX_SDIV_SHIFT); + break; + } + } + + if (i == ARRAY_SIZE(epll_div)) { + printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n", __func__); + return -EINVAL; + } + + __raw_writel(epll_con, S5P_EPLL_CON); + + clk->rate = rate; + + return 0; +} + +static struct clk_ops s5pc100_epll_ops = { + .get_rate = s5pc100_epll_get_rate, + .set_rate = s5pc100_epll_set_rate, +}; + +static int s5pc100_d0_0_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P_CLKGATE_D00, clk, enable); +} + +static int s5pc100_d0_1_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P_CLKGATE_D01, clk, enable); +} + +static int s5pc100_d0_2_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P_CLKGATE_D02, clk, enable); +} + +static int s5pc100_d1_0_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P_CLKGATE_D10, clk, enable); +} + +static int s5pc100_d1_1_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P_CLKGATE_D11, clk, enable); +} + +static int s5pc100_d1_2_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P_CLKGATE_D12, clk, enable); +} + +static int s5pc100_d1_3_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P_CLKGATE_D13, clk, enable); +} + +static int s5pc100_d1_4_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P_CLKGATE_D14, clk, enable); +} + +static int s5pc100_d1_5_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P_CLKGATE_D15, clk, enable); +} + +static int s5pc100_sclk0_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P_CLKGATE_SCLK0, clk, enable); +} + +static int s5pc100_sclk1_ctrl(struct clk *clk, int enable) +{ + return s5p_gatectrl(S5P_CLKGATE_SCLK1, clk, enable); +} + +/* + * The following clocks will be disabled during clock initialization. It is + * recommended to keep the following clocks disabled until the driver requests + * for enabling the clock. + */ +static struct clk init_clocks_disable[] = { + { + .name = "cssys", + .id = -1, + .parent = &clk_div_d0_bus.clk, + .enable = s5pc100_d0_0_ctrl, + .ctrlbit = (1 << 6), + }, { + .name = "secss", + .id = -1, + .parent = &clk_div_d0_bus.clk, + .enable = s5pc100_d0_0_ctrl, + .ctrlbit = (1 << 5), + }, { + .name = "g2d", + .id = -1, + .parent = &clk_div_d0_bus.clk, + .enable = s5pc100_d0_0_ctrl, + .ctrlbit = (1 << 4), + }, { + .name = "mdma", + .id = -1, + .parent = &clk_div_d0_bus.clk, + .enable = s5pc100_d0_0_ctrl, + .ctrlbit = (1 << 3), + }, { + .name = "cfcon", + .id = -1, + .parent = &clk_div_d0_bus.clk, + .enable = s5pc100_d0_0_ctrl, + .ctrlbit = (1 << 2), + }, { + .name = "nfcon", + .id = -1, + .parent = &clk_div_d0_bus.clk, + .enable = s5pc100_d0_1_ctrl, + .ctrlbit = (1 << 3), + }, { + .name = "onenandc", + .id = -1, + .parent = &clk_div_d0_bus.clk, + .enable = s5pc100_d0_1_ctrl, + .ctrlbit = (1 << 2), + }, { + .name = "sdm", + .id = -1, + .parent = &clk_div_d0_bus.clk, + .enable = s5pc100_d0_2_ctrl, + .ctrlbit = (1 << 2), + }, { + .name = "seckey", + .id = -1, + .parent = &clk_div_d0_bus.clk, + .enable = s5pc100_d0_2_ctrl, + .ctrlbit = (1 << 1), + }, { + .name = "hsmmc", + .id = 2, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_0_ctrl, + .ctrlbit = (1 << 7), + }, { + .name = "hsmmc", + .id = 1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_0_ctrl, + .ctrlbit = (1 << 6), + }, { + .name = "hsmmc", + .id = 0, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_0_ctrl, + .ctrlbit = (1 << 5), + }, { + .name = "modemif", + .id = -1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_0_ctrl, + .ctrlbit = (1 << 4), + }, { + .name = "otg", + .id = -1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_0_ctrl, + .ctrlbit = (1 << 3), + }, { + .name = "usbhost", + .id = -1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_0_ctrl, + .ctrlbit = (1 << 2), + }, { + .name = "pdma", + .id = 1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_0_ctrl, + .ctrlbit = (1 << 1), + }, { + .name = "pdma", + .id = 0, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_0_ctrl, + .ctrlbit = (1 << 0), + }, { + .name = "lcd", + .id = -1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_1_ctrl, + .ctrlbit = (1 << 0), + }, { + .name = "rotator", + .id = -1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_1_ctrl, + .ctrlbit = (1 << 1), + }, { + .name = "fimc", + .id = 0, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_1_ctrl, + .ctrlbit = (1 << 2), + }, { + .name = "fimc", + .id = 1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_1_ctrl, + .ctrlbit = (1 << 3), + }, { + .name = "fimc", + .id = 2, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_1_ctrl, + .ctrlbit = (1 << 4), + }, { + .name = "jpeg", + .id = -1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_1_ctrl, + .ctrlbit = (1 << 5), + }, { + .name = "mipi-dsim", + .id = -1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_1_ctrl, + .ctrlbit = (1 << 6), + }, { + .name = "mipi-csis", + .id = -1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_1_ctrl, + .ctrlbit = (1 << 7), + }, { + .name = "g3d", + .id = 0, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_0_ctrl, + .ctrlbit = (1 << 8), + }, { + .name = "tv", + .id = -1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_2_ctrl, + .ctrlbit = (1 << 0), + }, { + .name = "vp", + .id = -1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_2_ctrl, + .ctrlbit = (1 << 1), + }, { + .name = "mixer", + .id = -1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_2_ctrl, + .ctrlbit = (1 << 2), + }, { + .name = "hdmi", + .id = -1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_2_ctrl, + .ctrlbit = (1 << 3), + }, { + .name = "mfc", + .id = -1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_2_ctrl, + .ctrlbit = (1 << 4), + }, { + .name = "apc", + .id = -1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_3_ctrl, + .ctrlbit = (1 << 2), + }, { + .name = "iec", + .id = -1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_3_ctrl, + .ctrlbit = (1 << 3), + }, { + .name = "systimer", + .id = -1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_3_ctrl, + .ctrlbit = (1 << 7), + }, { + .name = "watchdog", + .id = -1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_3_ctrl, + .ctrlbit = (1 << 8), + }, { + .name = "rtc", + .id = -1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_3_ctrl, + .ctrlbit = (1 << 9), + }, { + .name = "i2c", + .id = 0, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_4_ctrl, + .ctrlbit = (1 << 4), + }, { + .name = "i2c", + .id = 1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_4_ctrl, + .ctrlbit = (1 << 5), + }, { + .name = "spi", + .id = 0, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_4_ctrl, + .ctrlbit = (1 << 6), + }, { + .name = "spi", + .id = 1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_4_ctrl, + .ctrlbit = (1 << 7), + }, { + .name = "spi", + .id = 2, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_4_ctrl, + .ctrlbit = (1 << 8), + }, { + .name = "irda", + .id = -1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_4_ctrl, + .ctrlbit = (1 << 9), + }, { + .name = "ccan", + .id = 0, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_4_ctrl, + .ctrlbit = (1 << 10), + }, { + .name = "ccan", + .id = 1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_4_ctrl, + .ctrlbit = (1 << 11), + }, { + .name = "hsitx", + .id = -1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_4_ctrl, + .ctrlbit = (1 << 12), + }, { + .name = "hsirx", + .id = -1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_4_ctrl, + .ctrlbit = (1 << 13), + }, { + .name = "iis", + .id = 0, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_5_ctrl, + .ctrlbit = (1 << 0), + }, { + .name = "iis", + .id = 1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_5_ctrl, + .ctrlbit = (1 << 1), + }, { + .name = "iis", + .id = 2, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_5_ctrl, + .ctrlbit = (1 << 2), + }, { + .name = "ac97", + .id = -1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_5_ctrl, + .ctrlbit = (1 << 3), + }, { + .name = "pcm", + .id = 0, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_5_ctrl, + .ctrlbit = (1 << 4), + }, { + .name = "pcm", + .id = 1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_5_ctrl, + .ctrlbit = (1 << 5), + }, { + .name = "spdif", + .id = -1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_5_ctrl, + .ctrlbit = (1 << 6), + }, { + .name = "adc", + .id = -1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_5_ctrl, + .ctrlbit = (1 << 7), + }, { + .name = "keyif", + .id = -1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_5_ctrl, + .ctrlbit = (1 << 8), + }, { + .name = "spi_48m", + .id = 0, + .parent = &clk_mout_48m.clk, + .enable = s5pc100_sclk0_ctrl, + .ctrlbit = (1 << 7), + }, { + .name = "spi_48m", + .id = 1, + .parent = &clk_mout_48m.clk, + .enable = s5pc100_sclk0_ctrl, + .ctrlbit = (1 << 8), + }, { + .name = "spi_48m", + .id = 2, + .parent = &clk_mout_48m.clk, + .enable = s5pc100_sclk0_ctrl, + .ctrlbit = (1 << 9), + }, { + .name = "mmc_48m", + .id = 0, + .parent = &clk_mout_48m.clk, + .enable = s5pc100_sclk0_ctrl, + .ctrlbit = (1 << 15), + }, { + .name = "mmc_48m", + .id = 1, + .parent = &clk_mout_48m.clk, + .enable = s5pc100_sclk0_ctrl, + .ctrlbit = (1 << 16), + }, { + .name = "mmc_48m", + .id = 2, + .parent = &clk_mout_48m.clk, + .enable = s5pc100_sclk0_ctrl, + .ctrlbit = (1 << 17), + }, +}; + +static struct clk clk_vclk54m = { + .name = "vclk_54m", + .id = -1, + .rate = 54000000, +}; + +static struct clk clk_i2scdclk0 = { + .name = "i2s_cdclk0", + .id = -1, +}; + +static struct clk clk_i2scdclk1 = { + .name = "i2s_cdclk1", + .id = -1, +}; + +static struct clk clk_i2scdclk2 = { + .name = "i2s_cdclk2", + .id = -1, +}; + +static struct clk clk_pcmcdclk0 = { + .name = "pcm_cdclk0", + .id = -1, +}; + +static struct clk clk_pcmcdclk1 = { + .name = "pcm_cdclk1", + .id = -1, +}; + +static struct clk *clk_src_group1_list[] = { + [0] = &clk_mout_epll.clk, + [1] = &clk_div_mpll2.clk, + [2] = &clk_fin_epll, + [3] = &clk_mout_hpll.clk, +}; + +struct clksrc_sources clk_src_group1 = { + .sources = clk_src_group1_list, + .nr_sources = ARRAY_SIZE(clk_src_group1_list), +}; + +static struct clk *clk_src_group2_list[] = { + [0] = &clk_mout_epll.clk, + [1] = &clk_div_mpll.clk, +}; + +struct clksrc_sources clk_src_group2 = { + .sources = clk_src_group2_list, + .nr_sources = ARRAY_SIZE(clk_src_group2_list), +}; + +static struct clk *clk_src_group3_list[] = { + [0] = &clk_mout_epll.clk, + [1] = &clk_div_mpll.clk, + [2] = &clk_fin_epll, + [3] = &clk_i2scdclk0, + [4] = &clk_pcmcdclk0, + [5] = &clk_mout_hpll.clk, +}; + +struct clksrc_sources clk_src_group3 = { + .sources = clk_src_group3_list, + .nr_sources = ARRAY_SIZE(clk_src_group3_list), +}; + +static struct clk *clk_src_group4_list[] = { + [0] = &clk_mout_epll.clk, + [1] = &clk_div_mpll.clk, + [2] = &clk_fin_epll, + [3] = &clk_i2scdclk1, + [4] = &clk_pcmcdclk1, + [5] = &clk_mout_hpll.clk, +}; + +struct clksrc_sources clk_src_group4 = { + .sources = clk_src_group4_list, + .nr_sources = ARRAY_SIZE(clk_src_group4_list), +}; + +static struct clk *clk_src_group5_list[] = { + [0] = &clk_mout_epll.clk, + [1] = &clk_div_mpll.clk, + [2] = &clk_fin_epll, + [3] = &clk_i2scdclk2, + [4] = &clk_mout_hpll.clk, +}; + +struct clksrc_sources clk_src_group5 = { + .sources = clk_src_group5_list, + .nr_sources = ARRAY_SIZE(clk_src_group5_list), +}; + +static struct clk *clk_src_group6_list[] = { + [0] = &s5p_clk_27m, + [1] = &clk_vclk54m, + [2] = &clk_div_hdmi.clk, +}; + +struct clksrc_sources clk_src_group6 = { + .sources = clk_src_group6_list, + .nr_sources = ARRAY_SIZE(clk_src_group6_list), +}; + +static struct clk *clk_src_group7_list[] = { + [0] = &clk_mout_epll.clk, + [1] = &clk_div_mpll.clk, + [2] = &clk_mout_hpll.clk, + [3] = &clk_vclk54m, +}; + +struct clksrc_sources clk_src_group7 = { + .sources = clk_src_group7_list, + .nr_sources = ARRAY_SIZE(clk_src_group7_list), +}; + +static struct clk *clk_src_mmc0_list[] = { + [0] = &clk_mout_epll.clk, + [1] = &clk_div_mpll.clk, + [2] = &clk_fin_epll, +}; + +struct clksrc_sources clk_src_mmc0 = { + .sources = clk_src_mmc0_list, + .nr_sources = ARRAY_SIZE(clk_src_mmc0_list), +}; + +static struct clk *clk_src_mmc12_list[] = { + [0] = &clk_mout_epll.clk, + [1] = &clk_div_mpll.clk, + [2] = &clk_fin_epll, + [3] = &clk_mout_hpll.clk, +}; + +struct clksrc_sources clk_src_mmc12 = { + .sources = clk_src_mmc12_list, + .nr_sources = ARRAY_SIZE(clk_src_mmc12_list), +}; + +static struct clk *clk_src_irda_usb_list[] = { + [0] = &clk_mout_epll.clk, + [1] = &clk_div_mpll.clk, + [2] = &clk_fin_epll, + [3] = &clk_mout_hpll.clk, +}; + +struct clksrc_sources clk_src_irda_usb = { + .sources = clk_src_irda_usb_list, + .nr_sources = ARRAY_SIZE(clk_src_irda_usb_list), +}; + +static struct clk *clk_src_pwi_list[] = { + [0] = &clk_fin_epll, + [1] = &clk_mout_epll.clk, + [2] = &clk_div_mpll.clk, +}; + +struct clksrc_sources clk_src_pwi = { + .sources = clk_src_pwi_list, + .nr_sources = ARRAY_SIZE(clk_src_pwi_list), +}; + +static struct clksrc_clk clksrcs[] = { + { + .clk = { + .name = "sclk_spi", + .id = 0, + .ctrlbit = (1 << 4), + .enable = s5pc100_sclk0_ctrl, + + }, + .sources = &clk_src_group1, + .reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 2 }, + .reg_div = { .reg = S5P_CLK_DIV2, .shift = 4, .size = 4 }, + }, { + .clk = { + .name = "sclk_spi", + .id = 1, + .ctrlbit = (1 << 5), + .enable = s5pc100_sclk0_ctrl, + + }, + .sources = &clk_src_group1, + .reg_src = { .reg = S5P_CLK_SRC1, .shift = 8, .size = 2 }, + .reg_div = { .reg = S5P_CLK_DIV2, .shift = 8, .size = 4 }, + }, { + .clk = { + .name = "sclk_spi", + .id = 2, + .ctrlbit = (1 << 6), + .enable = s5pc100_sclk0_ctrl, + + }, + .sources = &clk_src_group1, + .reg_src = { .reg = S5P_CLK_SRC1, .shift = 12, .size = 2 }, + .reg_div = { .reg = S5P_CLK_DIV2, .shift = 12, .size = 4 }, + }, { + .clk = { + .name = "uclk1", + .id = -1, + .ctrlbit = (1 << 3), + .enable = s5pc100_sclk0_ctrl, + + }, + .sources = &clk_src_group2, + .reg_src = { .reg = S5P_CLK_SRC1, .shift = 0, .size = 1 }, + .reg_div = { .reg = S5P_CLK_DIV2, .shift = 0, .size = 4 }, + }, { + .clk = { + .name = "sclk_mixer", + .id = -1, + .ctrlbit = (1 << 6), + .enable = s5pc100_sclk0_ctrl, + + }, + .sources = &clk_src_group6, + .reg_src = { .reg = S5P_CLK_SRC2, .shift = 28, .size = 2 }, + }, { + .clk = { + .name = "sclk_audio", + .id = 0, + .ctrlbit = (1 << 8), + .enable = s5pc100_sclk1_ctrl, + + }, + .sources = &clk_src_group3, + .reg_src = { .reg = S5P_CLK_SRC3, .shift = 12, .size = 3 }, + .reg_div = { .reg = S5P_CLK_DIV4, .shift = 12, .size = 4 }, + }, { + .clk = { + .name = "sclk_audio", + .id = 1, + .ctrlbit = (1 << 9), + .enable = s5pc100_sclk1_ctrl, + + }, + .sources = &clk_src_group4, + .reg_src = { .reg = S5P_CLK_SRC3, .shift = 16, .size = 3 }, + .reg_div = { .reg = S5P_CLK_DIV4, .shift = 16, .size = 4 }, + }, { + .clk = { + .name = "sclk_audio", + .id = 2, + .ctrlbit = (1 << 10), + .enable = s5pc100_sclk1_ctrl, + + }, + .sources = &clk_src_group5, + .reg_src = { .reg = S5P_CLK_SRC3, .shift = 20, .size = 3 }, + .reg_div = { .reg = S5P_CLK_DIV4, .shift = 20, .size = 4 }, + }, { + .clk = { + .name = "sclk_lcd", + .id = -1, + .ctrlbit = (1 << 0), + .enable = s5pc100_sclk1_ctrl, + + }, + .sources = &clk_src_group7, + .reg_src = { .reg = S5P_CLK_SRC2, .shift = 12, .size = 2 }, + .reg_div = { .reg = S5P_CLK_DIV3, .shift = 12, .size = 4 }, + }, { + .clk = { + .name = "sclk_fimc", + .id = 0, + .ctrlbit = (1 << 1), + .enable = s5pc100_sclk1_ctrl, + + }, + .sources = &clk_src_group7, + .reg_src = { .reg = S5P_CLK_SRC2, .shift = 16, .size = 2 }, + .reg_div = { .reg = S5P_CLK_DIV3, .shift = 16, .size = 4 }, + }, { + .clk = { + .name = "sclk_fimc", + .id = 1, + .ctrlbit = (1 << 2), + .enable = s5pc100_sclk1_ctrl, + + }, + .sources = &clk_src_group7, + .reg_src = { .reg = S5P_CLK_SRC2, .shift = 20, .size = 2 }, + .reg_div = { .reg = S5P_CLK_DIV3, .shift = 20, .size = 4 }, + }, { + .clk = { + .name = "sclk_fimc", + .id = 2, + .ctrlbit = (1 << 3), + .enable = s5pc100_sclk1_ctrl, + + }, + .sources = &clk_src_group7, + .reg_src = { .reg = S5P_CLK_SRC2, .shift = 24, .size = 2 }, + .reg_div = { .reg = S5P_CLK_DIV3, .shift = 24, .size = 4 }, + }, { + .clk = { + .name = "mmc_bus", + .id = 0, + .ctrlbit = (1 << 12), + .enable = s5pc100_sclk1_ctrl, + + }, + .sources = &clk_src_mmc0, + .reg_src = { .reg = S5P_CLK_SRC2, .shift = 0, .size = 2 }, + .reg_div = { .reg = S5P_CLK_DIV3, .shift = 0, .size = 4 }, + }, { + .clk = { + .name = "mmc_bus", + .id = 1, + .ctrlbit = (1 << 13), + .enable = s5pc100_sclk1_ctrl, + + }, + .sources = &clk_src_mmc12, + .reg_src = { .reg = S5P_CLK_SRC2, .shift = 4, .size = 2 }, + .reg_div = { .reg = S5P_CLK_DIV3, .shift = 4, .size = 4 }, + }, { + .clk = { + .name = "mmc_bus", + .id = 2, + .ctrlbit = (1 << 14), + .enable = s5pc100_sclk1_ctrl, + + }, + .sources = &clk_src_mmc12, + .reg_src = { .reg = S5P_CLK_SRC2, .shift = 8, .size = 2 }, + .reg_div = { .reg = S5P_CLK_DIV3, .shift = 8, .size = 4 }, + }, { + .clk = { + .name = "sclk_irda", + .id = 2, + .ctrlbit = (1 << 10), + .enable = s5pc100_sclk0_ctrl, + + }, + .sources = &clk_src_irda_usb, + .reg_src = { .reg = S5P_CLK_SRC2, .shift = 8, .size = 2 }, + .reg_div = { .reg = S5P_CLK_DIV3, .shift = 8, .size = 4 }, + }, { + .clk = { + .name = "sclk_irda", + .id = -1, + .ctrlbit = (1 << 10), + .enable = s5pc100_sclk0_ctrl, + + }, + .sources = &clk_src_mmc12, + .reg_src = { .reg = S5P_CLK_SRC1, .shift = 16, .size = 2 }, + .reg_div = { .reg = S5P_CLK_DIV2, .shift = 16, .size = 4 }, + }, { + .clk = { + .name = "sclk_pwi", + .id = -1, + .ctrlbit = (1 << 1), + .enable = s5pc100_sclk0_ctrl, + + }, + .sources = &clk_src_pwi, + .reg_src = { .reg = S5P_CLK_SRC3, .shift = 0, .size = 2 }, + .reg_div = { .reg = S5P_CLK_DIV4, .shift = 0, .size = 3 }, + }, { + .clk = { + .name = "sclk_uhost", + .id = -1, + .ctrlbit = (1 << 11), + .enable = s5pc100_sclk0_ctrl, + + }, + .sources = &clk_src_irda_usb, + .reg_src = { .reg = S5P_CLK_SRC1, .shift = 20, .size = 2 }, + .reg_div = { .reg = S5P_CLK_DIV2, .shift = 20, .size = 4 }, + }, +}; + +/* Clock initialisation code */ +static struct clksrc_clk *sysclks[] = { + &clk_mout_apll, + &clk_mout_epll, + &clk_mout_mpll, + &clk_mout_hpll, + &clk_mout_href, + &clk_mout_48m, + &clk_div_apll, + &clk_div_arm, + &clk_div_d0_bus, + &clk_div_pclkd0, + &clk_div_secss, + &clk_div_apll2, + &clk_mout_am, + &clk_div_d1_bus, + &clk_div_mpll2, + &clk_div_mpll, + &clk_mout_onenand, + &clk_div_onenand, + &clk_div_pclkd1, + &clk_div_cam, + &clk_div_hdmi, +}; + +void __init_or_cpufreq s5pc100_setup_clocks(void) +{ + unsigned long xtal; + unsigned long arm; + unsigned long hclkd0; + unsigned long hclkd1; + unsigned long pclkd0; + unsigned long pclkd1; + unsigned long apll; + unsigned long mpll; + unsigned long epll; + unsigned long hpll; + unsigned int ptr; + + /* Set S5PC100 functions for clk_fout_epll */ + clk_fout_epll.enable = s5pc100_epll_enable; + clk_fout_epll.ops = &s5pc100_epll_ops; + + printk(KERN_DEBUG "%s: registering clocks\n", __func__); + + xtal = clk_get_rate(&clk_xtal); + + printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal); + + apll = s5p_get_pll65xx(xtal, __raw_readl(S5P_APLL_CON)); + mpll = s5p_get_pll65xx(xtal, __raw_readl(S5P_MPLL_CON)); + epll = s5p_get_pll65xx(xtal, __raw_readl(S5P_EPLL_CON)); + hpll = s5p_get_pll65xx(xtal, __raw_readl(S5P_HPLL_CON)); + + printk(KERN_INFO "S5PC100: PLL settings, A=%ld.%ldMHz, M=%ld.%ldMHz, E=%ld.%ldMHz, H=%ld.%ldMHz\n", + print_mhz(apll), print_mhz(mpll), print_mhz(epll), print_mhz(hpll)); + + clk_fout_apll.rate = apll; + clk_fout_mpll.rate = mpll; + clk_fout_epll.rate = epll; + clk_mout_hpll.clk.rate = hpll; + + for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++) + s3c_set_clksrc(&clksrcs[ptr], true); + + arm = clk_get_rate(&clk_div_arm.clk); + hclkd0 = clk_get_rate(&clk_div_d0_bus.clk); + pclkd0 = clk_get_rate(&clk_div_pclkd0.clk); + hclkd1 = clk_get_rate(&clk_div_d1_bus.clk); + pclkd1 = clk_get_rate(&clk_div_pclkd1.clk); + + printk(KERN_INFO "S5PC100: HCLKD0=%ld.%ldMHz, HCLKD1=%ld.%ldMHz, PCLKD0=%ld.%ldMHz, PCLKD1=%ld.%ldMHz\n", + print_mhz(hclkd0), print_mhz(hclkd1), print_mhz(pclkd0), print_mhz(pclkd1)); + + clk_f.rate = arm; + clk_h.rate = hclkd1; + clk_p.rate = pclkd1; +} + +/* + * The following clocks will be enabled during clock initialization. + */ +static struct clk init_clocks[] = { + { + .name = "tzic", + .id = -1, + .parent = &clk_div_d0_bus.clk, + .enable = s5pc100_d0_0_ctrl, + .ctrlbit = (1 << 1), + }, { + .name = "intc", + .id = -1, + .parent = &clk_div_d0_bus.clk, + .enable = s5pc100_d0_0_ctrl, + .ctrlbit = (1 << 0), + }, { + .name = "ebi", + .id = -1, + .parent = &clk_div_d0_bus.clk, + .enable = s5pc100_d0_1_ctrl, + .ctrlbit = (1 << 5), + }, { + .name = "intmem", + .id = -1, + .parent = &clk_div_d0_bus.clk, + .enable = s5pc100_d0_1_ctrl, + .ctrlbit = (1 << 4), + }, { + .name = "sromc", + .id = -1, + .parent = &clk_div_d0_bus.clk, + .enable = s5pc100_d0_1_ctrl, + .ctrlbit = (1 << 1), + }, { + .name = "dmc", + .id = -1, + .parent = &clk_div_d0_bus.clk, + .enable = s5pc100_d0_1_ctrl, + .ctrlbit = (1 << 0), + }, { + .name = "chipid", + .id = -1, + .parent = &clk_div_d0_bus.clk, + .enable = s5pc100_d0_1_ctrl, + .ctrlbit = (1 << 0), + }, { + .name = "gpio", + .id = -1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_3_ctrl, + .ctrlbit = (1 << 1), + }, { + .name = "uart", + .id = 0, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_4_ctrl, + .ctrlbit = (1 << 0), + }, { + .name = "uart", + .id = 1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_4_ctrl, + .ctrlbit = (1 << 1), + }, { + .name = "uart", + .id = 2, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_4_ctrl, + .ctrlbit = (1 << 2), + }, { + .name = "uart", + .id = 3, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_4_ctrl, + .ctrlbit = (1 << 3), + }, { + .name = "timers", + .id = -1, + .parent = &clk_div_d1_bus.clk, + .enable = s5pc100_d1_3_ctrl, + .ctrlbit = (1 << 6), + }, +}; + +static struct clk *clks[] __initdata = { + &clk_ext, + &clk_i2scdclk0, + &clk_i2scdclk1, + &clk_i2scdclk2, + &clk_pcmcdclk0, + &clk_pcmcdclk1, +}; + +void __init s5pc100_register_clocks(void) +{ + struct clk *clkp; + int ret; + int ptr; + + s3c24xx_register_clocks(clks, ARRAY_SIZE(clks)); + + for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++) + s3c_register_clksrc(sysclks[ptr], 1); + + s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs)); + s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks)); + + clkp = init_clocks_disable; + for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) { + + ret = s3c24xx_register_clock(clkp); + if (ret < 0) { + printk(KERN_ERR "Failed to register clock %s (%d)\n", + clkp->name, ret); + } + (clkp->enable)(clkp, 0); + } + + s3c_pwmclk_init(); +} diff --git a/arch/arm/mach-s5pc100/include/mach/regs-clock.h b/arch/arm/mach-s5pc100/include/mach/regs-clock.h new file mode 100644 index 0000000..f2283bd --- /dev/null +++ b/arch/arm/mach-s5pc100/include/mach/regs-clock.h @@ -0,0 +1,71 @@ +/* linux/arch/arm/mach-s5pc100/include/mach/regs-clock.h + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * S5PC100 - Clock register definitions + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARCH_REGS_CLOCK_H +#define __ASM_ARCH_REGS_CLOCK_H __FILE__ + +#include + +#define S5P_CLKREG(x) (S3C_VA_SYS + (x)) + +#define S5P_APLL_LOCK S5P_CLKREG(0x00) +#define S5P_MPLL_LOCK S5P_CLKREG(0x04) +#define S5P_EPLL_LOCK S5P_CLKREG(0x08) +#define S5P_HPLL_LOCK S5P_CLKREG(0x0C) + +#define S5P_APLL_CON S5P_CLKREG(0x100) +#define S5P_MPLL_CON S5P_CLKREG(0x104) +#define S5P_EPLL_CON S5P_CLKREG(0x108) +#define S5P_HPLL_CON S5P_CLKREG(0x10C) + +#define S5P_CLK_SRC0 S5P_CLKREG(0x200) +#define S5P_CLK_SRC1 S5P_CLKREG(0x204) +#define S5P_CLK_SRC2 S5P_CLKREG(0x208) +#define S5P_CLK_SRC3 S5P_CLKREG(0x20C) + +#define S5P_CLK_DIV0 S5P_CLKREG(0x300) +#define S5P_CLK_DIV1 S5P_CLKREG(0x304) +#define S5P_CLK_DIV2 S5P_CLKREG(0x308) +#define S5P_CLK_DIV3 S5P_CLKREG(0x30C) +#define S5P_CLK_DIV4 S5P_CLKREG(0x310) + +#define S5P_CLK_OUT S5P_CLKREG(0x400) + +#define S5P_CLKGATE_D00 S5P_CLKREG(0x500) +#define S5P_CLKGATE_D01 S5P_CLKREG(0x504) +#define S5P_CLKGATE_D02 S5P_CLKREG(0x508) + +#define S5P_CLKGATE_D10 S5P_CLKREG(0x520) +#define S5P_CLKGATE_D11 S5P_CLKREG(0x524) +#define S5P_CLKGATE_D12 S5P_CLKREG(0x528) +#define S5P_CLKGATE_D13 S5P_CLKREG(0x52C) +#define S5P_CLKGATE_D14 S5P_CLKREG(0x530) +#define S5P_CLKGATE_D15 S5P_CLKREG(0x534) + +#define S5P_CLKGATE_D20 S5P_CLKREG(0x540) + +#define S5P_CLKGATE_SCLK0 S5P_CLKREG(0x560) +#define S5P_CLKGATE_SCLK1 S5P_CLKREG(0x564) + +/* CLKDIV0 */ +#define S5P_CLKDIV0_D0_MASK (0x7<<8) +#define S5P_CLKDIV0_D0_SHIFT (8) +#define S5P_CLKDIV0_PCLKD0_MASK (0x7<<12) +#define S5P_CLKDIV0_PCLKD0_SHIFT (12) + +/* CLKDIV1 */ +#define S5P_CLKDIV1_D1_MASK (0x7<<12) +#define S5P_CLKDIV1_D1_SHIFT (12) +#define S5P_CLKDIV1_PCLKD1_MASK (0x7<<16) +#define S5P_CLKDIV1_PCLKD1_SHIFT (16) + +#endif /* __ASM_ARCH_REGS_CLOCK_H */ diff --git a/arch/arm/plat-s5p/clock.c b/arch/arm/plat-s5p/clock.c index a8bfabf4..24a931f 100644 --- a/arch/arm/plat-s5p/clock.c +++ b/arch/arm/plat-s5p/clock.c @@ -38,7 +38,7 @@ struct clk clk_xusbxti = { .id = -1, }; -static struct clk s5p_clk_27m = { +struct clk s5p_clk_27m = { .name = "clk_27m", .id = -1, .rate = 27000000, diff --git a/arch/arm/plat-s5p/include/plat/pll.h b/arch/arm/plat-s5p/include/plat/pll.h index d48325b..7db3227 100644 --- a/arch/arm/plat-s5p/include/plat/pll.h +++ b/arch/arm/plat-s5p/include/plat/pll.h @@ -81,3 +81,25 @@ static inline unsigned long s5p_get_pll90xx(unsigned long baseclk, return result; } + +#define PLL65XX_MDIV_MASK (0x3FF) +#define PLL65XX_PDIV_MASK (0x3F) +#define PLL65XX_SDIV_MASK (0x7) +#define PLL65XX_MDIV_SHIFT (16) +#define PLL65XX_PDIV_SHIFT (8) +#define PLL65XX_SDIV_SHIFT (0) + +static inline unsigned long s5p_get_pll65xx(unsigned long baseclk, u32 pll_con) +{ + u32 mdiv, pdiv, sdiv; + u64 fvco = baseclk; + + mdiv = (pll_con >> PLL65XX_MDIV_SHIFT) & PLL65XX_MDIV_MASK; + pdiv = (pll_con >> PLL65XX_PDIV_SHIFT) & PLL65XX_PDIV_MASK; + sdiv = (pll_con >> PLL65XX_SDIV_SHIFT) & PLL65XX_SDIV_MASK; + + fvco *= mdiv; + do_div(fvco, (pdiv << sdiv)); + + return (unsigned long)fvco; +} diff --git a/arch/arm/plat-s5p/include/plat/s5p-clock.h b/arch/arm/plat-s5p/include/plat/s5p-clock.h index aa0447a..09418b1 100644 --- a/arch/arm/plat-s5p/include/plat/s5p-clock.h +++ b/arch/arm/plat-s5p/include/plat/s5p-clock.h @@ -21,10 +21,12 @@ #define clk_fin_mpll clk_ext_xtal_mux #define clk_fin_epll clk_ext_xtal_mux #define clk_fin_vpll clk_ext_xtal_mux +#define clk_fin_hpll clk_ext_xtal_mux extern struct clk clk_ext_xtal_mux; extern struct clk clk_xusbxti; extern struct clk clk_48m; +extern struct clk s5p_clk_27m; extern struct clk clk_fout_apll; extern struct clk clk_fout_mpll; extern struct clk clk_fout_epll; -- cgit v0.10.2 From cb34a67472c3171f350e45bc66eebf480acec792 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 18 May 2010 12:38:39 +0200 Subject: drivers: serial: S5PC100 serial driver cleanup Remove unnecessary Kconfig entry. S5PC100 has exactly the same driver as S3C6400/S3C6410/S5P6440. Signed-off-by: Marek Szyprowski Signed-off-by: Kyungmin Park Signed-off-by: Ben Dooks diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 5f3f03d..302836a 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -534,21 +534,13 @@ config SERIAL_S3C24A0 Serial port support for the Samsung S3C24A0 SoC config SERIAL_S3C6400 - tristate "Samsung S3C6400/S3C6410/S5P6440 Seria port support" - depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410 || CPU_S5P6440) + tristate "Samsung S3C6400/S3C6410/S5P6440/S5PC100 Serial port support" + depends on SERIAL_SAMSUNG && (CPU_S3C6400 || CPU_S3C6410 || CPU_S5P6440 || CPU_S5PC100) select SERIAL_SAMSUNG_UARTS_4 default y help - Serial port support for the Samsung S3C6400, S3C6410 and S5P6440 - SoCs - -config SERIAL_S5PC100 - tristate "Samsung S5PC100 Serial port support" - depends on SERIAL_SAMSUNG && CPU_S5PC100 - select SERIAL_SAMSUNG_UARTS_4 - default y - help - Serial port support for the Samsung S5PC100 SoCs + Serial port support for the Samsung S3C6400, S3C6410, S5P6440 + and S5PC100 SoCs config SERIAL_S5PV210 tristate "Samsung S5PV210 Serial port support" diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 6aa4723..328f107 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -44,7 +44,6 @@ obj-$(CONFIG_SERIAL_S3C2412) += s3c2412.o obj-$(CONFIG_SERIAL_S3C2440) += s3c2440.o obj-$(CONFIG_SERIAL_S3C24A0) += s3c24a0.o obj-$(CONFIG_SERIAL_S3C6400) += s3c6400.o -obj-$(CONFIG_SERIAL_S5PC100) += s3c6400.o obj-$(CONFIG_SERIAL_S5PV210) += s5pv210.o obj-$(CONFIG_SERIAL_MAX3100) += max3100.o obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o -- cgit v0.10.2 From 252b8efeba9cd1e28ade902275b27133114d2382 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 18 May 2010 12:38:40 +0200 Subject: ARM: S5PC100: Use common functions for gpiolib implementation GPIOlib helpers from plat-samsung already have functions for accessing 4bit gpio banks. This patch removes the duplicated functions from plat-s5pc1xx/gpiolib.c. Signed-off-by: Marek Szyprowski Signed-off-by: Kyungmin Park Signed-off-by: Ben Dooks diff --git a/arch/arm/plat-s5pc1xx/Kconfig b/arch/arm/plat-s5pc1xx/Kconfig index 79d3be7..98bbaf9 100644 --- a/arch/arm/plat-s5pc1xx/Kconfig +++ b/arch/arm/plat-s5pc1xx/Kconfig @@ -19,6 +19,7 @@ config PLAT_S5PC1XX select S5P_GPIO_DRVSTR select S3C_GPIO_CFG_S3C24XX select S3C_GPIO_CFG_S3C64XX + select SAMSUNG_GPIOLIB_4BIT help Base platform code for any Samsung S5PC1XX device diff --git a/arch/arm/plat-s5pc1xx/gpiolib.c b/arch/arm/plat-s5pc1xx/gpiolib.c index 1ffc57a..5a97a8f 100644 --- a/arch/arm/plat-s5pc1xx/gpiolib.c +++ b/arch/arm/plat-s5pc1xx/gpiolib.c @@ -61,74 +61,6 @@ * L3 8 4Bit None */ -#define OFF_GPCON (0x00) -#define OFF_GPDAT (0x04) - -#define con_4bit_shift(__off) ((__off) * 4) - -#if 1 -#define gpio_dbg(x...) do { } while (0) -#else -#define gpio_dbg(x...) printk(KERN_DEBUG x) -#endif - -/* The s5pc1xx_gpiolib routines are to control the gpio banks where - * the gpio configuration register (GPxCON) has 4 bits per GPIO, as the - * following example: - * - * base + 0x00: Control register, 4 bits per gpio - * gpio n: 4 bits starting at (4*n) - * 0000 = input, 0001 = output, others mean special-function - * base + 0x04: Data register, 1 bit per gpio - * bit n: data bit n - * - * Note, since the data register is one bit per gpio and is at base + 0x4 - * we can use s3c_gpiolib_get and s3c_gpiolib_set to change the state of - * the output. - */ - -static int s5pc1xx_gpiolib_input(struct gpio_chip *chip, unsigned offset) -{ - struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); - void __iomem *base = ourchip->base; - unsigned long con; - - con = __raw_readl(base + OFF_GPCON); - con &= ~(0xf << con_4bit_shift(offset)); - __raw_writel(con, base + OFF_GPCON); - - gpio_dbg("%s: %p: CON now %08lx\n", __func__, base, con); - - return 0; -} - -static int s5pc1xx_gpiolib_output(struct gpio_chip *chip, - unsigned offset, int value) -{ - struct s3c_gpio_chip *ourchip = to_s3c_gpio(chip); - void __iomem *base = ourchip->base; - unsigned long con; - unsigned long dat; - - con = __raw_readl(base + OFF_GPCON); - con &= ~(0xf << con_4bit_shift(offset)); - con |= 0x1 << con_4bit_shift(offset); - - dat = __raw_readl(base + OFF_GPDAT); - if (value) - dat |= 1 << offset; - else - dat &= ~(1 << offset); - - __raw_writel(dat, base + OFF_GPDAT); - __raw_writel(con, base + OFF_GPCON); - __raw_writel(dat, base + OFF_GPDAT); - - gpio_dbg("%s: %p: CON %08lx, DAT %08lx\n", __func__, base, con, dat); - - return 0; -} - static int s5pc1xx_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset) { return S3C_IRQ_GPIO(chip->base + offset); @@ -452,11 +384,8 @@ static struct s3c_gpio_chip s5pc100_gpio_chips[] = { extern struct irq_chip s5pc1xx_gpioint; extern void s5pc1xx_irq_gpioint_handler(unsigned int irq, struct irq_desc *desc); -static __init void s5pc1xx_gpiolib_link(struct s3c_gpio_chip *chip) +static __init void s5pc100_gpiolib_link(struct s3c_gpio_chip *chip) { - chip->chip.direction_input = s5pc1xx_gpiolib_input; - chip->chip.direction_output = s5pc1xx_gpiolib_output; - chip->pm = __gpio_pm(&s3c_gpio_pm_4bit); /* Interrupt */ if (chip->config == &gpio_cfg) { @@ -475,26 +404,19 @@ static __init void s5pc1xx_gpiolib_link(struct s3c_gpio_chip *chip) chip->chip.to_irq = s5pc1xx_gpiolib_to_eint; } -static __init void s5pc1xx_gpiolib_add(struct s3c_gpio_chip *chips, - int nr_chips, - void (*fn)(struct s3c_gpio_chip *)) -{ - for (; nr_chips > 0; nr_chips--, chips++) { - if (fn) - (fn)(chips); - s3c_gpiolib_add(chips); - } -} - static __init int s5pc1xx_gpiolib_init(void) { - struct s3c_gpio_chip *chips; + struct s3c_gpio_chip *chip; int nr_chips; - chips = s5pc100_gpio_chips; - nr_chips = ARRAY_SIZE(s5pc100_gpio_chips); + chip = s5pc100_gpio_chips; + nr_chips = ARRAY_SIZE(s5pc100_gpio_chips); + + for (; nr_chips > 0; nr_chips--, chip++) + s5pc100_gpiolib_link(chip); - s5pc1xx_gpiolib_add(chips, nr_chips, s5pc1xx_gpiolib_link); + samsung_gpiolib_add_4bit_chips(s5pc100_gpio_chips, + ARRAY_SIZE(s5pc100_gpio_chips)); /* Interrupt */ set_irq_chained_handler(IRQ_GPIOINT, s5pc1xx_irq_gpioint_handler); -- cgit v0.10.2 From 7904449021de399a03ec8a32e536d031a61def5b Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 18 May 2010 12:38:41 +0200 Subject: ARM: S5PC100: Move gpio support from plat-s5pc1xx to mach-s5pc100 Move gpio-lib support from plat-s5pc1xx to mach-s5pc100. Only basic gpio functionality is now supported. Gpio interrupts are disabled temporarly and will be added later. Signed-off-by: Marek Szyprowski Signed-off-by: Kyungmin Park Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5pc100/Makefile b/arch/arm/mach-s5pc100/Makefile index 809ff10..4199ce2 100644 --- a/arch/arm/mach-s5pc100/Makefile +++ b/arch/arm/mach-s5pc100/Makefile @@ -11,7 +11,7 @@ obj- := # Core support for S5PC100 system -obj-$(CONFIG_CPU_S5PC100) += cpu.o +obj-$(CONFIG_CPU_S5PC100) += cpu.o gpiolib.o # Helper and device support diff --git a/arch/arm/mach-s5pc100/gpiolib.c b/arch/arm/mach-s5pc100/gpiolib.c new file mode 100644 index 0000000..c8e8336 --- /dev/null +++ b/arch/arm/mach-s5pc100/gpiolib.c @@ -0,0 +1,428 @@ +/* + * arch/arm/plat-s5pc1xx/gpiolib.c + * + * Copyright 2009 Samsung Electronics Co + * Kyungmin Park + * + * S5PC1XX - GPIOlib support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +/* S5PC100 GPIO bank summary: + * + * Bank GPIOs Style INT Type + * A0 8 4Bit GPIO_INT0 + * A1 5 4Bit GPIO_INT1 + * B 8 4Bit GPIO_INT2 + * C 5 4Bit GPIO_INT3 + * D 7 4Bit GPIO_INT4 + * E0 8 4Bit GPIO_INT5 + * E1 6 4Bit GPIO_INT6 + * F0 8 4Bit GPIO_INT7 + * F1 8 4Bit GPIO_INT8 + * F2 8 4Bit GPIO_INT9 + * F3 4 4Bit GPIO_INT10 + * G0 8 4Bit GPIO_INT11 + * G1 3 4Bit GPIO_INT12 + * G2 7 4Bit GPIO_INT13 + * G3 7 4Bit GPIO_INT14 + * H0 8 4Bit WKUP_INT + * H1 8 4Bit WKUP_INT + * H2 8 4Bit WKUP_INT + * H3 8 4Bit WKUP_INT + * I 8 4Bit GPIO_INT15 + * J0 8 4Bit GPIO_INT16 + * J1 5 4Bit GPIO_INT17 + * J2 8 4Bit GPIO_INT18 + * J3 8 4Bit GPIO_INT19 + * J4 4 4Bit GPIO_INT20 + * K0 8 4Bit None + * K1 6 4Bit None + * K2 8 4Bit None + * K3 8 4Bit None + * L0 8 4Bit None + * L1 8 4Bit None + * L2 8 4Bit None + * L3 8 4Bit None + */ + +#if 0 +static int s5pc1xx_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset) +{ + return S3C_IRQ_GPIO(chip->base + offset); +} + +static int s5pc1xx_gpiolib_to_eint(struct gpio_chip *chip, unsigned int offset) +{ + int base; + + base = chip->base - S5PC100_GPH0(0); + if (base == 0) + return IRQ_EINT(offset); + base = chip->base - S5PC100_GPH1(0); + if (base == 0) + return IRQ_EINT(8 + offset); + base = chip->base - S5PC100_GPH2(0); + if (base == 0) + return IRQ_EINT(16 + offset); + base = chip->base - S5PC100_GPH3(0); + if (base == 0) + return IRQ_EINT(24 + offset); + return -EINVAL; +} +#endif +static struct s3c_gpio_cfg gpio_cfg = { + .set_config = s3c_gpio_setcfg_s3c64xx_4bit, + .set_pull = s3c_gpio_setpull_updown, + .get_pull = s3c_gpio_getpull_updown, +}; + +static struct s3c_gpio_cfg gpio_cfg_eint = { + .cfg_eint = 0xf, + .set_config = s3c_gpio_setcfg_s3c64xx_4bit, + .set_pull = s3c_gpio_setpull_updown, + .get_pull = s3c_gpio_getpull_updown, +}; + +static struct s3c_gpio_cfg gpio_cfg_noint = { + .set_config = s3c_gpio_setcfg_s3c64xx_4bit, + .set_pull = s3c_gpio_setpull_updown, + .get_pull = s3c_gpio_getpull_updown, +}; + +static struct s3c_gpio_chip s5pc100_gpio_chips[] = { + { + .base = S5PC100_GPA0_BASE, + .config = &gpio_cfg, + .chip = { + .base = S5PC100_GPA0(0), + .ngpio = S5PC100_GPIO_A0_NR, + .label = "GPA0", + }, + }, { + .base = S5PC100_GPA1_BASE, + .config = &gpio_cfg, + .chip = { + .base = S5PC100_GPA1(0), + .ngpio = S5PC100_GPIO_A1_NR, + .label = "GPA1", + }, + }, { + .base = S5PC100_GPB_BASE, + .config = &gpio_cfg, + .chip = { + .base = S5PC100_GPB(0), + .ngpio = S5PC100_GPIO_B_NR, + .label = "GPB", + }, + }, { + .base = S5PC100_GPC_BASE, + .config = &gpio_cfg, + .chip = { + .base = S5PC100_GPC(0), + .ngpio = S5PC100_GPIO_C_NR, + .label = "GPC", + }, + }, { + .base = S5PC100_GPD_BASE, + .config = &gpio_cfg, + .chip = { + .base = S5PC100_GPD(0), + .ngpio = S5PC100_GPIO_D_NR, + .label = "GPD", + }, + }, { + .base = S5PC100_GPE0_BASE, + .config = &gpio_cfg, + .chip = { + .base = S5PC100_GPE0(0), + .ngpio = S5PC100_GPIO_E0_NR, + .label = "GPE0", + }, + }, { + .base = S5PC100_GPE1_BASE, + .config = &gpio_cfg, + .chip = { + .base = S5PC100_GPE1(0), + .ngpio = S5PC100_GPIO_E1_NR, + .label = "GPE1", + }, + }, { + .base = S5PC100_GPF0_BASE, + .config = &gpio_cfg, + .chip = { + .base = S5PC100_GPF0(0), + .ngpio = S5PC100_GPIO_F0_NR, + .label = "GPF0", + }, + }, { + .base = S5PC100_GPF1_BASE, + .config = &gpio_cfg, + .chip = { + .base = S5PC100_GPF1(0), + .ngpio = S5PC100_GPIO_F1_NR, + .label = "GPF1", + }, + }, { + .base = S5PC100_GPF2_BASE, + .config = &gpio_cfg, + .chip = { + .base = S5PC100_GPF2(0), + .ngpio = S5PC100_GPIO_F2_NR, + .label = "GPF2", + }, + }, { + .base = S5PC100_GPF3_BASE, + .config = &gpio_cfg, + .chip = { + .base = S5PC100_GPF3(0), + .ngpio = S5PC100_GPIO_F3_NR, + .label = "GPF3", + }, + }, { + .base = S5PC100_GPG0_BASE, + .config = &gpio_cfg, + .chip = { + .base = S5PC100_GPG0(0), + .ngpio = S5PC100_GPIO_G0_NR, + .label = "GPG0", + }, + }, { + .base = S5PC100_GPG1_BASE, + .config = &gpio_cfg, + .chip = { + .base = S5PC100_GPG1(0), + .ngpio = S5PC100_GPIO_G1_NR, + .label = "GPG1", + }, + }, { + .base = S5PC100_GPG2_BASE, + .config = &gpio_cfg, + .chip = { + .base = S5PC100_GPG2(0), + .ngpio = S5PC100_GPIO_G2_NR, + .label = "GPG2", + }, + }, { + .base = S5PC100_GPG3_BASE, + .config = &gpio_cfg, + .chip = { + .base = S5PC100_GPG3(0), + .ngpio = S5PC100_GPIO_G3_NR, + .label = "GPG3", + }, + }, { + .base = S5PC100_GPH0_BASE, + .config = &gpio_cfg_eint, + .chip = { + .base = S5PC100_GPH0(0), + .ngpio = S5PC100_GPIO_H0_NR, + .label = "GPH0", + }, + }, { + .base = S5PC100_GPH1_BASE, + .config = &gpio_cfg_eint, + .chip = { + .base = S5PC100_GPH1(0), + .ngpio = S5PC100_GPIO_H1_NR, + .label = "GPH1", + }, + }, { + .base = S5PC100_GPH2_BASE, + .config = &gpio_cfg_eint, + .chip = { + .base = S5PC100_GPH2(0), + .ngpio = S5PC100_GPIO_H2_NR, + .label = "GPH2", + }, + }, { + .base = S5PC100_GPH3_BASE, + .config = &gpio_cfg_eint, + .chip = { + .base = S5PC100_GPH3(0), + .ngpio = S5PC100_GPIO_H3_NR, + .label = "GPH3", + }, + }, { + .base = S5PC100_GPI_BASE, + .config = &gpio_cfg, + .chip = { + .base = S5PC100_GPI(0), + .ngpio = S5PC100_GPIO_I_NR, + .label = "GPI", + }, + }, { + .base = S5PC100_GPJ0_BASE, + .config = &gpio_cfg, + .chip = { + .base = S5PC100_GPJ0(0), + .ngpio = S5PC100_GPIO_J0_NR, + .label = "GPJ0", + }, + }, { + .base = S5PC100_GPJ1_BASE, + .config = &gpio_cfg, + .chip = { + .base = S5PC100_GPJ1(0), + .ngpio = S5PC100_GPIO_J1_NR, + .label = "GPJ1", + }, + }, { + .base = S5PC100_GPJ2_BASE, + .config = &gpio_cfg, + .chip = { + .base = S5PC100_GPJ2(0), + .ngpio = S5PC100_GPIO_J2_NR, + .label = "GPJ2", + }, + }, { + .base = S5PC100_GPJ3_BASE, + .config = &gpio_cfg, + .chip = { + .base = S5PC100_GPJ3(0), + .ngpio = S5PC100_GPIO_J3_NR, + .label = "GPJ3", + }, + }, { + .base = S5PC100_GPJ4_BASE, + .config = &gpio_cfg, + .chip = { + .base = S5PC100_GPJ4(0), + .ngpio = S5PC100_GPIO_J4_NR, + .label = "GPJ4", + }, + }, { + .base = S5PC100_GPK0_BASE, + .config = &gpio_cfg_noint, + .chip = { + .base = S5PC100_GPK0(0), + .ngpio = S5PC100_GPIO_K0_NR, + .label = "GPK0", + }, + }, { + .base = S5PC100_GPK1_BASE, + .config = &gpio_cfg_noint, + .chip = { + .base = S5PC100_GPK1(0), + .ngpio = S5PC100_GPIO_K1_NR, + .label = "GPK1", + }, + }, { + .base = S5PC100_GPK2_BASE, + .config = &gpio_cfg_noint, + .chip = { + .base = S5PC100_GPK2(0), + .ngpio = S5PC100_GPIO_K2_NR, + .label = "GPK2", + }, + }, { + .base = S5PC100_GPK3_BASE, + .config = &gpio_cfg_noint, + .chip = { + .base = S5PC100_GPK3(0), + .ngpio = S5PC100_GPIO_K3_NR, + .label = "GPK3", + }, + }, { + .base = S5PC100_GPL0_BASE, + .config = &gpio_cfg_noint, + .chip = { + .base = S5PC100_GPL0(0), + .ngpio = S5PC100_GPIO_L0_NR, + .label = "GPL0", + }, + }, { + .base = S5PC100_GPL1_BASE, + .config = &gpio_cfg_noint, + .chip = { + .base = S5PC100_GPL1(0), + .ngpio = S5PC100_GPIO_L1_NR, + .label = "GPL1", + }, + }, { + .base = S5PC100_GPL2_BASE, + .config = &gpio_cfg_noint, + .chip = { + .base = S5PC100_GPL2(0), + .ngpio = S5PC100_GPIO_L2_NR, + .label = "GPL2", + }, + }, { + .base = S5PC100_GPL3_BASE, + .config = &gpio_cfg_noint, + .chip = { + .base = S5PC100_GPL3(0), + .ngpio = S5PC100_GPIO_L3_NR, + .label = "GPL3", + }, + }, { + .base = S5PC100_GPL4_BASE, + .config = &gpio_cfg_noint, + .chip = { + .base = S5PC100_GPL4(0), + .ngpio = S5PC100_GPIO_L4_NR, + .label = "GPL4", + }, + }, +}; + +/* FIXME move from irq-gpio.c */ +extern struct irq_chip s5pc1xx_gpioint; +extern void s5pc1xx_irq_gpioint_handler(unsigned int irq, struct irq_desc *desc); + +static __init void s5pc100_gpiolib_link(struct s3c_gpio_chip *chip) +{ +#if 0 + /* Interrupt */ + if (chip->config == &gpio_cfg) { + int i, irq; + + chip->chip.to_irq = s5pc1xx_gpiolib_to_irq; + + for (i = 0; i < chip->chip.ngpio; i++) { + irq = S3C_IRQ_GPIO_BASE + chip->chip.base + i; + set_irq_chip(irq, &s5pc1xx_gpioint); + set_irq_data(irq, &chip->chip); + set_irq_handler(irq, handle_level_irq); + set_irq_flags(irq, IRQF_VALID); + } + } else if (chip->config == &gpio_cfg_eint) + chip->chip.to_irq = s5pc1xx_gpiolib_to_eint; +#endif +} + +static __init int s5pc1xx_gpiolib_init(void) +{ + struct s3c_gpio_chip *chip; + int nr_chips; + + chip = s5pc100_gpio_chips; + nr_chips = ARRAY_SIZE(s5pc100_gpio_chips); + + for (; nr_chips > 0; nr_chips--, chip++) + s5pc100_gpiolib_link(chip); + + samsung_gpiolib_add_4bit_chips(s5pc100_gpio_chips, + ARRAY_SIZE(s5pc100_gpio_chips)); +#if 0 + /* Interrupt */ + set_irq_chained_handler(IRQ_GPIOINT, s5pc1xx_irq_gpioint_handler); +#endif + return 0; +} +core_initcall(s5pc1xx_gpiolib_init); diff --git a/arch/arm/mach-s5pc100/include/mach/regs-gpio.h b/arch/arm/mach-s5pc100/include/mach/regs-gpio.h new file mode 100644 index 0000000..43c7bc8 --- /dev/null +++ b/arch/arm/mach-s5pc100/include/mach/regs-gpio.h @@ -0,0 +1,70 @@ +/* linux/arch/arm/plat-s5pc1xx/include/plat/regs-gpio.h + * + * Copyright 2009 Samsung Electronics Co. + * Byungho Min + * + * S5PC1XX - GPIO register definitions + */ + +#ifndef __ASM_PLAT_S5PC1XX_REGS_GPIO_H +#define __ASM_PLAT_S5PC1XX_REGS_GPIO_H __FILE__ + +#include + +/* S5PC100 */ +#define S5PC100_GPIO_BASE S5PC1XX_VA_GPIO +#define S5PC100_GPA0_BASE (S5PC100_GPIO_BASE + 0x0000) +#define S5PC100_GPA1_BASE (S5PC100_GPIO_BASE + 0x0020) +#define S5PC100_GPB_BASE (S5PC100_GPIO_BASE + 0x0040) +#define S5PC100_GPC_BASE (S5PC100_GPIO_BASE + 0x0060) +#define S5PC100_GPD_BASE (S5PC100_GPIO_BASE + 0x0080) +#define S5PC100_GPE0_BASE (S5PC100_GPIO_BASE + 0x00A0) +#define S5PC100_GPE1_BASE (S5PC100_GPIO_BASE + 0x00C0) +#define S5PC100_GPF0_BASE (S5PC100_GPIO_BASE + 0x00E0) +#define S5PC100_GPF1_BASE (S5PC100_GPIO_BASE + 0x0100) +#define S5PC100_GPF2_BASE (S5PC100_GPIO_BASE + 0x0120) +#define S5PC100_GPF3_BASE (S5PC100_GPIO_BASE + 0x0140) +#define S5PC100_GPG0_BASE (S5PC100_GPIO_BASE + 0x0160) +#define S5PC100_GPG1_BASE (S5PC100_GPIO_BASE + 0x0180) +#define S5PC100_GPG2_BASE (S5PC100_GPIO_BASE + 0x01A0) +#define S5PC100_GPG3_BASE (S5PC100_GPIO_BASE + 0x01C0) +#define S5PC100_GPH0_BASE (S5PC100_GPIO_BASE + 0x0C00) +#define S5PC100_GPH1_BASE (S5PC100_GPIO_BASE + 0x0C20) +#define S5PC100_GPH2_BASE (S5PC100_GPIO_BASE + 0x0C40) +#define S5PC100_GPH3_BASE (S5PC100_GPIO_BASE + 0x0C60) +#define S5PC100_GPI_BASE (S5PC100_GPIO_BASE + 0x01E0) +#define S5PC100_GPJ0_BASE (S5PC100_GPIO_BASE + 0x0200) +#define S5PC100_GPJ1_BASE (S5PC100_GPIO_BASE + 0x0220) +#define S5PC100_GPJ2_BASE (S5PC100_GPIO_BASE + 0x0240) +#define S5PC100_GPJ3_BASE (S5PC100_GPIO_BASE + 0x0260) +#define S5PC100_GPJ4_BASE (S5PC100_GPIO_BASE + 0x0280) +#define S5PC100_GPK0_BASE (S5PC100_GPIO_BASE + 0x02A0) +#define S5PC100_GPK1_BASE (S5PC100_GPIO_BASE + 0x02C0) +#define S5PC100_GPK2_BASE (S5PC100_GPIO_BASE + 0x02E0) +#define S5PC100_GPK3_BASE (S5PC100_GPIO_BASE + 0x0300) +#define S5PC100_GPL0_BASE (S5PC100_GPIO_BASE + 0x0320) +#define S5PC100_GPL1_BASE (S5PC100_GPIO_BASE + 0x0340) +#define S5PC100_GPL2_BASE (S5PC100_GPIO_BASE + 0x0360) +#define S5PC100_GPL3_BASE (S5PC100_GPIO_BASE + 0x0380) +#define S5PC100_GPL4_BASE (S5PC100_GPIO_BASE + 0x03A0) +#define S5PC100_EINT_BASE (S5PC100_GPIO_BASE + 0x0E00) + +#define S5PC100_UHOST (S5PC100_GPIO_BASE + 0x0B68) +#define S5PC100_PDNEN (S5PC100_GPIO_BASE + 0x0F80) + +/* PDNEN */ +#define S5PC100_PDNEN_CFG_PDNEN (1 << 1) +#define S5PC100_PDNEN_CFG_AUTO (0 << 1) +#define S5PC100_PDNEN_POWERDOWN (1 << 0) +#define S5PC100_PDNEN_NORMAL (0 << 0) + +/* Common part */ +/* External interrupt base is same at both s5pc100 and s5pc110 */ +#define S5PC1XX_EINT_BASE (S5PC100_EINT_BASE) + +#define S5PC100_GPx_INPUT(__gpio) (0x0 << ((__gpio) * 4)) +#define S5PC100_GPx_OUTPUT(__gpio) (0x1 << ((__gpio) * 4)) +#define S5PC100_GPx_CONMASK(__gpio) (0xf << ((__gpio) * 4)) + +#endif /* __ASM_PLAT_S5PC1XX_REGS_GPIO_H */ + diff --git a/arch/arm/mach-s5pc100/mach-smdkc100.c b/arch/arm/mach-s5pc100/mach-smdkc100.c index ae3c52c..bfe67db 100644 --- a/arch/arm/mach-s5pc100/mach-smdkc100.c +++ b/arch/arm/mach-s5pc100/mach-smdkc100.c @@ -35,7 +35,6 @@ #include #include -#include #include #include diff --git a/arch/arm/plat-s5pc1xx/Makefile b/arch/arm/plat-s5pc1xx/Makefile index 66a8f3e..540fca5 100644 --- a/arch/arm/plat-s5pc1xx/Makefile +++ b/arch/arm/plat-s5pc1xx/Makefile @@ -13,9 +13,8 @@ obj- := obj-y += dev-uart.o obj-y += cpu.o -obj-y += irq.o irq-gpio.o irq-eint.o +obj-y += irq.o obj-y += clock.o -obj-y += gpiolib.o # CPU support diff --git a/arch/arm/plat-s5pc1xx/gpiolib.c b/arch/arm/plat-s5pc1xx/gpiolib.c deleted file mode 100644 index 5a97a8f..0000000 --- a/arch/arm/plat-s5pc1xx/gpiolib.c +++ /dev/null @@ -1,425 +0,0 @@ -/* - * arch/arm/plat-s5pc1xx/gpiolib.c - * - * Copyright 2009 Samsung Electronics Co - * Kyungmin Park - * - * S5PC1XX - GPIOlib support - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -/* S5PC100 GPIO bank summary: - * - * Bank GPIOs Style INT Type - * A0 8 4Bit GPIO_INT0 - * A1 5 4Bit GPIO_INT1 - * B 8 4Bit GPIO_INT2 - * C 5 4Bit GPIO_INT3 - * D 7 4Bit GPIO_INT4 - * E0 8 4Bit GPIO_INT5 - * E1 6 4Bit GPIO_INT6 - * F0 8 4Bit GPIO_INT7 - * F1 8 4Bit GPIO_INT8 - * F2 8 4Bit GPIO_INT9 - * F3 4 4Bit GPIO_INT10 - * G0 8 4Bit GPIO_INT11 - * G1 3 4Bit GPIO_INT12 - * G2 7 4Bit GPIO_INT13 - * G3 7 4Bit GPIO_INT14 - * H0 8 4Bit WKUP_INT - * H1 8 4Bit WKUP_INT - * H2 8 4Bit WKUP_INT - * H3 8 4Bit WKUP_INT - * I 8 4Bit GPIO_INT15 - * J0 8 4Bit GPIO_INT16 - * J1 5 4Bit GPIO_INT17 - * J2 8 4Bit GPIO_INT18 - * J3 8 4Bit GPIO_INT19 - * J4 4 4Bit GPIO_INT20 - * K0 8 4Bit None - * K1 6 4Bit None - * K2 8 4Bit None - * K3 8 4Bit None - * L0 8 4Bit None - * L1 8 4Bit None - * L2 8 4Bit None - * L3 8 4Bit None - */ - -static int s5pc1xx_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset) -{ - return S3C_IRQ_GPIO(chip->base + offset); -} - -static int s5pc1xx_gpiolib_to_eint(struct gpio_chip *chip, unsigned int offset) -{ - int base; - - base = chip->base - S5PC100_GPH0(0); - if (base == 0) - return IRQ_EINT(offset); - base = chip->base - S5PC100_GPH1(0); - if (base == 0) - return IRQ_EINT(8 + offset); - base = chip->base - S5PC100_GPH2(0); - if (base == 0) - return IRQ_EINT(16 + offset); - base = chip->base - S5PC100_GPH3(0); - if (base == 0) - return IRQ_EINT(24 + offset); - return -EINVAL; -} - -static struct s3c_gpio_cfg gpio_cfg = { - .set_config = s3c_gpio_setcfg_s3c64xx_4bit, - .set_pull = s3c_gpio_setpull_updown, - .get_pull = s3c_gpio_getpull_updown, -}; - -static struct s3c_gpio_cfg gpio_cfg_eint = { - .cfg_eint = 0xf, - .set_config = s3c_gpio_setcfg_s3c64xx_4bit, - .set_pull = s3c_gpio_setpull_updown, - .get_pull = s3c_gpio_getpull_updown, -}; - -static struct s3c_gpio_cfg gpio_cfg_noint = { - .set_config = s3c_gpio_setcfg_s3c64xx_4bit, - .set_pull = s3c_gpio_setpull_updown, - .get_pull = s3c_gpio_getpull_updown, -}; - -static struct s3c_gpio_chip s5pc100_gpio_chips[] = { - { - .base = S5PC100_GPA0_BASE, - .config = &gpio_cfg, - .chip = { - .base = S5PC100_GPA0(0), - .ngpio = S5PC100_GPIO_A0_NR, - .label = "GPA0", - }, - }, { - .base = S5PC100_GPA1_BASE, - .config = &gpio_cfg, - .chip = { - .base = S5PC100_GPA1(0), - .ngpio = S5PC100_GPIO_A1_NR, - .label = "GPA1", - }, - }, { - .base = S5PC100_GPB_BASE, - .config = &gpio_cfg, - .chip = { - .base = S5PC100_GPB(0), - .ngpio = S5PC100_GPIO_B_NR, - .label = "GPB", - }, - }, { - .base = S5PC100_GPC_BASE, - .config = &gpio_cfg, - .chip = { - .base = S5PC100_GPC(0), - .ngpio = S5PC100_GPIO_C_NR, - .label = "GPC", - }, - }, { - .base = S5PC100_GPD_BASE, - .config = &gpio_cfg, - .chip = { - .base = S5PC100_GPD(0), - .ngpio = S5PC100_GPIO_D_NR, - .label = "GPD", - }, - }, { - .base = S5PC100_GPE0_BASE, - .config = &gpio_cfg, - .chip = { - .base = S5PC100_GPE0(0), - .ngpio = S5PC100_GPIO_E0_NR, - .label = "GPE0", - }, - }, { - .base = S5PC100_GPE1_BASE, - .config = &gpio_cfg, - .chip = { - .base = S5PC100_GPE1(0), - .ngpio = S5PC100_GPIO_E1_NR, - .label = "GPE1", - }, - }, { - .base = S5PC100_GPF0_BASE, - .config = &gpio_cfg, - .chip = { - .base = S5PC100_GPF0(0), - .ngpio = S5PC100_GPIO_F0_NR, - .label = "GPF0", - }, - }, { - .base = S5PC100_GPF1_BASE, - .config = &gpio_cfg, - .chip = { - .base = S5PC100_GPF1(0), - .ngpio = S5PC100_GPIO_F1_NR, - .label = "GPF1", - }, - }, { - .base = S5PC100_GPF2_BASE, - .config = &gpio_cfg, - .chip = { - .base = S5PC100_GPF2(0), - .ngpio = S5PC100_GPIO_F2_NR, - .label = "GPF2", - }, - }, { - .base = S5PC100_GPF3_BASE, - .config = &gpio_cfg, - .chip = { - .base = S5PC100_GPF3(0), - .ngpio = S5PC100_GPIO_F3_NR, - .label = "GPF3", - }, - }, { - .base = S5PC100_GPG0_BASE, - .config = &gpio_cfg, - .chip = { - .base = S5PC100_GPG0(0), - .ngpio = S5PC100_GPIO_G0_NR, - .label = "GPG0", - }, - }, { - .base = S5PC100_GPG1_BASE, - .config = &gpio_cfg, - .chip = { - .base = S5PC100_GPG1(0), - .ngpio = S5PC100_GPIO_G1_NR, - .label = "GPG1", - }, - }, { - .base = S5PC100_GPG2_BASE, - .config = &gpio_cfg, - .chip = { - .base = S5PC100_GPG2(0), - .ngpio = S5PC100_GPIO_G2_NR, - .label = "GPG2", - }, - }, { - .base = S5PC100_GPG3_BASE, - .config = &gpio_cfg, - .chip = { - .base = S5PC100_GPG3(0), - .ngpio = S5PC100_GPIO_G3_NR, - .label = "GPG3", - }, - }, { - .base = S5PC100_GPH0_BASE, - .config = &gpio_cfg_eint, - .chip = { - .base = S5PC100_GPH0(0), - .ngpio = S5PC100_GPIO_H0_NR, - .label = "GPH0", - }, - }, { - .base = S5PC100_GPH1_BASE, - .config = &gpio_cfg_eint, - .chip = { - .base = S5PC100_GPH1(0), - .ngpio = S5PC100_GPIO_H1_NR, - .label = "GPH1", - }, - }, { - .base = S5PC100_GPH2_BASE, - .config = &gpio_cfg_eint, - .chip = { - .base = S5PC100_GPH2(0), - .ngpio = S5PC100_GPIO_H2_NR, - .label = "GPH2", - }, - }, { - .base = S5PC100_GPH3_BASE, - .config = &gpio_cfg_eint, - .chip = { - .base = S5PC100_GPH3(0), - .ngpio = S5PC100_GPIO_H3_NR, - .label = "GPH3", - }, - }, { - .base = S5PC100_GPI_BASE, - .config = &gpio_cfg, - .chip = { - .base = S5PC100_GPI(0), - .ngpio = S5PC100_GPIO_I_NR, - .label = "GPI", - }, - }, { - .base = S5PC100_GPJ0_BASE, - .config = &gpio_cfg, - .chip = { - .base = S5PC100_GPJ0(0), - .ngpio = S5PC100_GPIO_J0_NR, - .label = "GPJ0", - }, - }, { - .base = S5PC100_GPJ1_BASE, - .config = &gpio_cfg, - .chip = { - .base = S5PC100_GPJ1(0), - .ngpio = S5PC100_GPIO_J1_NR, - .label = "GPJ1", - }, - }, { - .base = S5PC100_GPJ2_BASE, - .config = &gpio_cfg, - .chip = { - .base = S5PC100_GPJ2(0), - .ngpio = S5PC100_GPIO_J2_NR, - .label = "GPJ2", - }, - }, { - .base = S5PC100_GPJ3_BASE, - .config = &gpio_cfg, - .chip = { - .base = S5PC100_GPJ3(0), - .ngpio = S5PC100_GPIO_J3_NR, - .label = "GPJ3", - }, - }, { - .base = S5PC100_GPJ4_BASE, - .config = &gpio_cfg, - .chip = { - .base = S5PC100_GPJ4(0), - .ngpio = S5PC100_GPIO_J4_NR, - .label = "GPJ4", - }, - }, { - .base = S5PC100_GPK0_BASE, - .config = &gpio_cfg_noint, - .chip = { - .base = S5PC100_GPK0(0), - .ngpio = S5PC100_GPIO_K0_NR, - .label = "GPK0", - }, - }, { - .base = S5PC100_GPK1_BASE, - .config = &gpio_cfg_noint, - .chip = { - .base = S5PC100_GPK1(0), - .ngpio = S5PC100_GPIO_K1_NR, - .label = "GPK1", - }, - }, { - .base = S5PC100_GPK2_BASE, - .config = &gpio_cfg_noint, - .chip = { - .base = S5PC100_GPK2(0), - .ngpio = S5PC100_GPIO_K2_NR, - .label = "GPK2", - }, - }, { - .base = S5PC100_GPK3_BASE, - .config = &gpio_cfg_noint, - .chip = { - .base = S5PC100_GPK3(0), - .ngpio = S5PC100_GPIO_K3_NR, - .label = "GPK3", - }, - }, { - .base = S5PC100_GPL0_BASE, - .config = &gpio_cfg_noint, - .chip = { - .base = S5PC100_GPL0(0), - .ngpio = S5PC100_GPIO_L0_NR, - .label = "GPL0", - }, - }, { - .base = S5PC100_GPL1_BASE, - .config = &gpio_cfg_noint, - .chip = { - .base = S5PC100_GPL1(0), - .ngpio = S5PC100_GPIO_L1_NR, - .label = "GPL1", - }, - }, { - .base = S5PC100_GPL2_BASE, - .config = &gpio_cfg_noint, - .chip = { - .base = S5PC100_GPL2(0), - .ngpio = S5PC100_GPIO_L2_NR, - .label = "GPL2", - }, - }, { - .base = S5PC100_GPL3_BASE, - .config = &gpio_cfg_noint, - .chip = { - .base = S5PC100_GPL3(0), - .ngpio = S5PC100_GPIO_L3_NR, - .label = "GPL3", - }, - }, { - .base = S5PC100_GPL4_BASE, - .config = &gpio_cfg_noint, - .chip = { - .base = S5PC100_GPL4(0), - .ngpio = S5PC100_GPIO_L4_NR, - .label = "GPL4", - }, - }, -}; - -/* FIXME move from irq-gpio.c */ -extern struct irq_chip s5pc1xx_gpioint; -extern void s5pc1xx_irq_gpioint_handler(unsigned int irq, struct irq_desc *desc); - -static __init void s5pc100_gpiolib_link(struct s3c_gpio_chip *chip) -{ - - /* Interrupt */ - if (chip->config == &gpio_cfg) { - int i, irq; - - chip->chip.to_irq = s5pc1xx_gpiolib_to_irq; - - for (i = 0; i < chip->chip.ngpio; i++) { - irq = S3C_IRQ_GPIO_BASE + chip->chip.base + i; - set_irq_chip(irq, &s5pc1xx_gpioint); - set_irq_data(irq, &chip->chip); - set_irq_handler(irq, handle_level_irq); - set_irq_flags(irq, IRQF_VALID); - } - } else if (chip->config == &gpio_cfg_eint) - chip->chip.to_irq = s5pc1xx_gpiolib_to_eint; -} - -static __init int s5pc1xx_gpiolib_init(void) -{ - struct s3c_gpio_chip *chip; - int nr_chips; - - chip = s5pc100_gpio_chips; - nr_chips = ARRAY_SIZE(s5pc100_gpio_chips); - - for (; nr_chips > 0; nr_chips--, chip++) - s5pc100_gpiolib_link(chip); - - samsung_gpiolib_add_4bit_chips(s5pc100_gpio_chips, - ARRAY_SIZE(s5pc100_gpio_chips)); - /* Interrupt */ - set_irq_chained_handler(IRQ_GPIOINT, s5pc1xx_irq_gpioint_handler); - - return 0; -} -core_initcall(s5pc1xx_gpiolib_init); diff --git a/arch/arm/plat-s5pc1xx/include/plat/regs-gpio.h b/arch/arm/plat-s5pc1xx/include/plat/regs-gpio.h deleted file mode 100644 index 43c7bc8..0000000 --- a/arch/arm/plat-s5pc1xx/include/plat/regs-gpio.h +++ /dev/null @@ -1,70 +0,0 @@ -/* linux/arch/arm/plat-s5pc1xx/include/plat/regs-gpio.h - * - * Copyright 2009 Samsung Electronics Co. - * Byungho Min - * - * S5PC1XX - GPIO register definitions - */ - -#ifndef __ASM_PLAT_S5PC1XX_REGS_GPIO_H -#define __ASM_PLAT_S5PC1XX_REGS_GPIO_H __FILE__ - -#include - -/* S5PC100 */ -#define S5PC100_GPIO_BASE S5PC1XX_VA_GPIO -#define S5PC100_GPA0_BASE (S5PC100_GPIO_BASE + 0x0000) -#define S5PC100_GPA1_BASE (S5PC100_GPIO_BASE + 0x0020) -#define S5PC100_GPB_BASE (S5PC100_GPIO_BASE + 0x0040) -#define S5PC100_GPC_BASE (S5PC100_GPIO_BASE + 0x0060) -#define S5PC100_GPD_BASE (S5PC100_GPIO_BASE + 0x0080) -#define S5PC100_GPE0_BASE (S5PC100_GPIO_BASE + 0x00A0) -#define S5PC100_GPE1_BASE (S5PC100_GPIO_BASE + 0x00C0) -#define S5PC100_GPF0_BASE (S5PC100_GPIO_BASE + 0x00E0) -#define S5PC100_GPF1_BASE (S5PC100_GPIO_BASE + 0x0100) -#define S5PC100_GPF2_BASE (S5PC100_GPIO_BASE + 0x0120) -#define S5PC100_GPF3_BASE (S5PC100_GPIO_BASE + 0x0140) -#define S5PC100_GPG0_BASE (S5PC100_GPIO_BASE + 0x0160) -#define S5PC100_GPG1_BASE (S5PC100_GPIO_BASE + 0x0180) -#define S5PC100_GPG2_BASE (S5PC100_GPIO_BASE + 0x01A0) -#define S5PC100_GPG3_BASE (S5PC100_GPIO_BASE + 0x01C0) -#define S5PC100_GPH0_BASE (S5PC100_GPIO_BASE + 0x0C00) -#define S5PC100_GPH1_BASE (S5PC100_GPIO_BASE + 0x0C20) -#define S5PC100_GPH2_BASE (S5PC100_GPIO_BASE + 0x0C40) -#define S5PC100_GPH3_BASE (S5PC100_GPIO_BASE + 0x0C60) -#define S5PC100_GPI_BASE (S5PC100_GPIO_BASE + 0x01E0) -#define S5PC100_GPJ0_BASE (S5PC100_GPIO_BASE + 0x0200) -#define S5PC100_GPJ1_BASE (S5PC100_GPIO_BASE + 0x0220) -#define S5PC100_GPJ2_BASE (S5PC100_GPIO_BASE + 0x0240) -#define S5PC100_GPJ3_BASE (S5PC100_GPIO_BASE + 0x0260) -#define S5PC100_GPJ4_BASE (S5PC100_GPIO_BASE + 0x0280) -#define S5PC100_GPK0_BASE (S5PC100_GPIO_BASE + 0x02A0) -#define S5PC100_GPK1_BASE (S5PC100_GPIO_BASE + 0x02C0) -#define S5PC100_GPK2_BASE (S5PC100_GPIO_BASE + 0x02E0) -#define S5PC100_GPK3_BASE (S5PC100_GPIO_BASE + 0x0300) -#define S5PC100_GPL0_BASE (S5PC100_GPIO_BASE + 0x0320) -#define S5PC100_GPL1_BASE (S5PC100_GPIO_BASE + 0x0340) -#define S5PC100_GPL2_BASE (S5PC100_GPIO_BASE + 0x0360) -#define S5PC100_GPL3_BASE (S5PC100_GPIO_BASE + 0x0380) -#define S5PC100_GPL4_BASE (S5PC100_GPIO_BASE + 0x03A0) -#define S5PC100_EINT_BASE (S5PC100_GPIO_BASE + 0x0E00) - -#define S5PC100_UHOST (S5PC100_GPIO_BASE + 0x0B68) -#define S5PC100_PDNEN (S5PC100_GPIO_BASE + 0x0F80) - -/* PDNEN */ -#define S5PC100_PDNEN_CFG_PDNEN (1 << 1) -#define S5PC100_PDNEN_CFG_AUTO (0 << 1) -#define S5PC100_PDNEN_POWERDOWN (1 << 0) -#define S5PC100_PDNEN_NORMAL (0 << 0) - -/* Common part */ -/* External interrupt base is same at both s5pc100 and s5pc110 */ -#define S5PC1XX_EINT_BASE (S5PC100_EINT_BASE) - -#define S5PC100_GPx_INPUT(__gpio) (0x0 << ((__gpio) * 4)) -#define S5PC100_GPx_OUTPUT(__gpio) (0x1 << ((__gpio) * 4)) -#define S5PC100_GPx_CONMASK(__gpio) (0xf << ((__gpio) * 4)) - -#endif /* __ASM_PLAT_S5PC1XX_REGS_GPIO_H */ - -- cgit v0.10.2 From c8bb9635f926aaf15987450c57af05e422874b92 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 18 May 2010 12:38:42 +0200 Subject: ARM: S5PC100: gpio.h cleanup This patch renames gpio related registers from s5pc1xx to s5pc100 to better match the plat-s5p framework style. GPIO_MP* defines now used anywhere thus has been removed. Signed-off-by: Marek Szyprowski Signed-off-by: Kyungmin Park Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5pc100/include/mach/gpio.h b/arch/arm/mach-s5pc100/include/mach/gpio.h index 2c4cbe8..29a8a12 100644 --- a/arch/arm/mach-s5pc100/include/mach/gpio.h +++ b/arch/arm/mach-s5pc100/include/mach/gpio.h @@ -12,6 +12,9 @@ * published by the Free Software Foundation. */ +#ifndef __ASM_ARCH_GPIO_H +#define __ASM_ARCH_GPIO_H __FILE__ + #define gpio_get_value __gpio_get_value #define gpio_set_value __gpio_set_value #define gpio_cansleep __gpio_cansleep @@ -52,11 +55,6 @@ #define S5PC100_GPIO_L2_NR (8) #define S5PC100_GPIO_L3_NR (8) #define S5PC100_GPIO_L4_NR (8) -#define S5PC100_GPIO_MP00_NR (8) -#define S5PC100_GPIO_MP01_NR (8) -#define S5PC100_GPIO_MP02_NR (8) -#define S5PC100_GPIO_MP03_NR (8) -#define S5PC100_GPIO_MP04_NR (5) /* GPIO bank numbes */ @@ -65,50 +63,45 @@ * change from one gpio bank to another can be caught. */ -#define S5PC1XX_GPIO_NEXT(__gpio) \ +#define S5PC100_GPIO_NEXT(__gpio) \ ((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1) -enum s3c_gpio_number { +enum s5p_gpio_number { S5PC100_GPIO_A0_START = 0, - S5PC100_GPIO_A1_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_A0), - S5PC100_GPIO_B_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_A1), - S5PC100_GPIO_C_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_B), - S5PC100_GPIO_D_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_C), - S5PC100_GPIO_E0_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_D), - S5PC100_GPIO_E1_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_E0), - S5PC100_GPIO_F0_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_E1), - S5PC100_GPIO_F1_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_F0), - S5PC100_GPIO_F2_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_F1), - S5PC100_GPIO_F3_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_F2), - S5PC100_GPIO_G0_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_F3), - S5PC100_GPIO_G1_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_G0), - S5PC100_GPIO_G2_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_G1), - S5PC100_GPIO_G3_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_G2), - S5PC100_GPIO_H0_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_G3), - S5PC100_GPIO_H1_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_H0), - S5PC100_GPIO_H2_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_H1), - S5PC100_GPIO_H3_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_H2), - S5PC100_GPIO_I_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_H3), - S5PC100_GPIO_J0_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_I), - S5PC100_GPIO_J1_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_J0), - S5PC100_GPIO_J2_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_J1), - S5PC100_GPIO_J3_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_J2), - S5PC100_GPIO_J4_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_J3), - S5PC100_GPIO_K0_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_J4), - S5PC100_GPIO_K1_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_K0), - S5PC100_GPIO_K2_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_K1), - S5PC100_GPIO_K3_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_K2), - S5PC100_GPIO_L0_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_K3), - S5PC100_GPIO_L1_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_L0), - S5PC100_GPIO_L2_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_L1), - S5PC100_GPIO_L3_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_L2), - S5PC100_GPIO_L4_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_L3), - S5PC100_GPIO_MP00_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_L4), - S5PC100_GPIO_MP01_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_MP00), - S5PC100_GPIO_MP02_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_MP01), - S5PC100_GPIO_MP03_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_MP02), - S5PC100_GPIO_MP04_START = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_MP03), - S5PC100_GPIO_END = S5PC1XX_GPIO_NEXT(S5PC100_GPIO_MP04), + S5PC100_GPIO_A1_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_A0), + S5PC100_GPIO_B_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_A1), + S5PC100_GPIO_C_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_B), + S5PC100_GPIO_D_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_C), + S5PC100_GPIO_E0_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_D), + S5PC100_GPIO_E1_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_E0), + S5PC100_GPIO_F0_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_E1), + S5PC100_GPIO_F1_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_F0), + S5PC100_GPIO_F2_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_F1), + S5PC100_GPIO_F3_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_F2), + S5PC100_GPIO_G0_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_F3), + S5PC100_GPIO_G1_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_G0), + S5PC100_GPIO_G2_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_G1), + S5PC100_GPIO_G3_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_G2), + S5PC100_GPIO_H0_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_G3), + S5PC100_GPIO_H1_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_H0), + S5PC100_GPIO_H2_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_H1), + S5PC100_GPIO_H3_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_H2), + S5PC100_GPIO_I_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_H3), + S5PC100_GPIO_J0_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_I), + S5PC100_GPIO_J1_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_J0), + S5PC100_GPIO_J2_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_J1), + S5PC100_GPIO_J3_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_J2), + S5PC100_GPIO_J4_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_J3), + S5PC100_GPIO_K0_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_J4), + S5PC100_GPIO_K1_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_K0), + S5PC100_GPIO_K2_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_K1), + S5PC100_GPIO_K3_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_K2), + S5PC100_GPIO_L0_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_K3), + S5PC100_GPIO_L1_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_L0), + S5PC100_GPIO_L2_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_L1), + S5PC100_GPIO_L3_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_L2), + S5PC100_GPIO_L4_START = S5PC100_GPIO_NEXT(S5PC100_GPIO_L3), + S5PC100_GPIO_END = S5PC100_GPIO_NEXT(S5PC100_GPIO_L4), }; /* S5PC100 GPIO number definitions. */ @@ -146,17 +139,13 @@ enum s3c_gpio_number { #define S5PC100_GPL2(_nr) (S5PC100_GPIO_L2_START + (_nr)) #define S5PC100_GPL3(_nr) (S5PC100_GPIO_L3_START + (_nr)) #define S5PC100_GPL4(_nr) (S5PC100_GPIO_L4_START + (_nr)) -#define S5PC100_MP00(_nr) (S5PC100_GPIO_MP00_START + (_nr)) -#define S5PC100_MP01(_nr) (S5PC100_GPIO_MP01_START + (_nr)) -#define S5PC100_MP02(_nr) (S5PC100_GPIO_MP02_START + (_nr)) -#define S5PC100_MP03(_nr) (S5PC100_GPIO_MP03_START + (_nr)) -#define S5PC100_MP04(_nr) (S5PC100_GPIO_MP04_START + (_nr)) -#define S5PC100_MP05(_nr) (S5PC100_GPIO_MP05_START + (_nr)) -/* It used the end of the S5PC1XX gpios */ +/* It used the end of the S5PC100 gpios */ #define S3C_GPIO_END S5PC100_GPIO_END /* define the number of gpios we need to the one after the MP04() range */ #define ARCH_NR_GPIOS (S5PC100_GPIO_END + 1) #include + +#endif /* __ASM_ARCH_GPIO_H */ diff --git a/arch/arm/mach-s5pc100/include/mach/regs-gpio.h b/arch/arm/mach-s5pc100/include/mach/regs-gpio.h index 43c7bc8..6866691 100644 --- a/arch/arm/mach-s5pc100/include/mach/regs-gpio.h +++ b/arch/arm/mach-s5pc100/include/mach/regs-gpio.h @@ -3,11 +3,11 @@ * Copyright 2009 Samsung Electronics Co. * Byungho Min * - * S5PC1XX - GPIO register definitions + * S5PC100 - GPIO register definitions */ -#ifndef __ASM_PLAT_S5PC1XX_REGS_GPIO_H -#define __ASM_PLAT_S5PC1XX_REGS_GPIO_H __FILE__ +#ifndef __ASM_MACH_S5PC100_REGS_GPIO_H +#define __ASM_MACH_S5PC100_REGS_GPIO_H __FILE__ #include @@ -66,5 +66,5 @@ #define S5PC100_GPx_OUTPUT(__gpio) (0x1 << ((__gpio) * 4)) #define S5PC100_GPx_CONMASK(__gpio) (0xf << ((__gpio) * 4)) -#endif /* __ASM_PLAT_S5PC1XX_REGS_GPIO_H */ +#endif /* __ASM_MACH_S5PC100_REGS_GPIO_H */ -- cgit v0.10.2 From b884c0e07058478bff82b8edcecff4e2919fa361 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 18 May 2010 12:38:43 +0200 Subject: ARM: S5PC100: Move frame buffer helpers from plat-s5pc1xx to mach-s5pc100 Move frame buffer helpers from plat-s5pc1xx to mach-s5pc100. Signed-off-by: Marek Szyprowski Signed-off-by: Kyungmin Park Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5pc100/Kconfig b/arch/arm/mach-s5pc100/Kconfig index 27ec167..7d9b68c 100644 --- a/arch/arm/mach-s5pc100/Kconfig +++ b/arch/arm/mach-s5pc100/Kconfig @@ -12,6 +12,11 @@ config CPU_S5PC100 help Enable S5PC100 CPU support +config S5PC100_SETUP_FB_24BPP + bool + help + Common setup code for S5PC1XX with an 24bpp RGB display helper. + config S5PC100_SETUP_SDHCI bool select S5PC1XX_SETUP_SDHCI_GPIO @@ -28,7 +33,7 @@ config MACH_SMDKC100 select S3C_DEV_HSMMC2 select S5PC1XX_SETUP_I2C0 select S5PC1XX_SETUP_I2C1 - select S5PC1XX_SETUP_FB_24BPP + select S5PC100_SETUP_FB_24BPP select S5PC100_SETUP_SDHCI help Machine support for the Samsung SMDKC100 diff --git a/arch/arm/mach-s5pc100/Makefile b/arch/arm/mach-s5pc100/Makefile index 4199ce2..1d1276c 100644 --- a/arch/arm/mach-s5pc100/Makefile +++ b/arch/arm/mach-s5pc100/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_CPU_S5PC100) += cpu.o gpiolib.o # Helper and device support +obj-$(CONFIG_S5PC100_SETUP_FB_24BPP) += setup-fb-24bpp.o obj-$(CONFIG_S5PC100_SETUP_SDHCI) += setup-sdhci.o # machine support diff --git a/arch/arm/mach-s5pc100/setup-fb-24bpp.c b/arch/arm/mach-s5pc100/setup-fb-24bpp.c new file mode 100644 index 0000000..6eba6cb --- /dev/null +++ b/arch/arm/mach-s5pc100/setup-fb-24bpp.c @@ -0,0 +1,48 @@ +/* + * linux/arch/arm/mach-s5pc100/setup-fb-24bpp.c + * + * Copyright 2009 Samsung Electronics + * + * Base S5PC100 setup information for 24bpp LCD framebuffer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#define DISR_OFFSET 0x7008 + +void s5pc100_fb_gpio_setup_24bpp(void) +{ + unsigned int gpio = 0; + + for (gpio = S5PC100_GPF0(0); gpio <= S5PC100_GPF0(7); gpio++) { + s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); + s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); + } + + for (gpio = S5PC100_GPF1(0); gpio <= S5PC100_GPF1(7); gpio++) { + s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); + s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); + } + + for (gpio = S5PC100_GPF2(0); gpio <= S5PC100_GPF2(7); gpio++) { + s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); + s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); + } + + for (gpio = S5PC100_GPF3(0); gpio <= S5PC100_GPF3(3); gpio++) { + s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); + s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); + } +} diff --git a/arch/arm/plat-s5pc1xx/Kconfig b/arch/arm/plat-s5pc1xx/Kconfig index 98bbaf9..708f7a0 100644 --- a/arch/arm/plat-s5pc1xx/Kconfig +++ b/arch/arm/plat-s5pc1xx/Kconfig @@ -39,11 +39,6 @@ config CPU_S5PC100_CLOCK # platform specific device setup -config S5PC1XX_SETUP_FB_24BPP - bool - help - Common setup code for S5PC1XX with an 24bpp RGB display helper. - config S5PC1XX_SETUP_I2C0 bool default y diff --git a/arch/arm/plat-s5pc1xx/Makefile b/arch/arm/plat-s5pc1xx/Makefile index 540fca5..a5b90c0 100644 --- a/arch/arm/plat-s5pc1xx/Makefile +++ b/arch/arm/plat-s5pc1xx/Makefile @@ -23,7 +23,6 @@ obj-$(CONFIG_CPU_S5PC100_CLOCK) += s5pc100-clock.o # Device setup -obj-$(CONFIG_S5PC1XX_SETUP_FB_24BPP) += setup-fb-24bpp.o obj-$(CONFIG_S5PC1XX_SETUP_I2C0) += setup-i2c0.o obj-$(CONFIG_S5PC1XX_SETUP_I2C1) += setup-i2c1.o obj-$(CONFIG_S5PC1XX_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o diff --git a/arch/arm/plat-s5pc1xx/setup-fb-24bpp.c b/arch/arm/plat-s5pc1xx/setup-fb-24bpp.c deleted file mode 100644 index b02c36f..0000000 --- a/arch/arm/plat-s5pc1xx/setup-fb-24bpp.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * linux/arch/arm/plat-s5pc100/setup-fb-24bpp.c - * - * Copyright 2009 Samsung Electronics - * - * Base S5PC1XX setup information for 24bpp LCD framebuffer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#define DISR_OFFSET 0x7008 - -void s5pc100_fb_gpio_setup_24bpp(void) -{ - unsigned int gpio = 0; - - for (gpio = S5PC100_GPF0(0); gpio <= S5PC100_GPF0(7); gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } - - for (gpio = S5PC100_GPF1(0); gpio <= S5PC100_GPF1(7); gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } - - for (gpio = S5PC100_GPF2(0); gpio <= S5PC100_GPF2(7); gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } - - for (gpio = S5PC100_GPF3(0); gpio <= S5PC100_GPF3(3); gpio++) { - s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)); - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); - } -} -- cgit v0.10.2 From 51ffd971edb2d5187007967c14712a8ed956c092 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Tue, 18 May 2010 12:38:44 +0200 Subject: ARM: S5PC100: Move i2c helpers from plat-s5pc1xx to mach-s5pc100 Move i2c helpers from plat-s5pc1xx to mach-s5pc100. Signed-off-by: Marek Szyprowski Signed-off-by: Kyungmin Park Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s5pc100/Kconfig b/arch/arm/mach-s5pc100/Kconfig index 7d9b68c..8593337 100644 --- a/arch/arm/mach-s5pc100/Kconfig +++ b/arch/arm/mach-s5pc100/Kconfig @@ -23,6 +23,11 @@ config S5PC100_SETUP_SDHCI help Internal helper functions for S5PC100 based SDHCI systems +config S5PC100_SETUP_I2C1 + bool + help + Common setup code for i2c bus 1. + config MACH_SMDKC100 bool "SMDKC100" select CPU_S5PC100 @@ -31,9 +36,8 @@ config MACH_SMDKC100 select S3C_DEV_HSMMC select S3C_DEV_HSMMC1 select S3C_DEV_HSMMC2 - select S5PC1XX_SETUP_I2C0 - select S5PC1XX_SETUP_I2C1 select S5PC100_SETUP_FB_24BPP + select S5PC100_SETUP_I2C1 select S5PC100_SETUP_SDHCI help Machine support for the Samsung SMDKC100 diff --git a/arch/arm/mach-s5pc100/Makefile b/arch/arm/mach-s5pc100/Makefile index 1d1276c..373bc54 100644 --- a/arch/arm/mach-s5pc100/Makefile +++ b/arch/arm/mach-s5pc100/Makefile @@ -12,10 +12,12 @@ obj- := # Core support for S5PC100 system obj-$(CONFIG_CPU_S5PC100) += cpu.o gpiolib.o +obj-$(CONFIG_CPU_S5PC100) += setup-i2c0.o # Helper and device support obj-$(CONFIG_S5PC100_SETUP_FB_24BPP) += setup-fb-24bpp.o +obj-$(CONFIG_S5PC100_SETUP_I2C1) += setup-i2c1.o obj-$(CONFIG_S5PC100_SETUP_SDHCI) += setup-sdhci.o # machine support diff --git a/arch/arm/mach-s5pc100/setup-i2c0.c b/arch/arm/mach-s5pc100/setup-i2c0.c new file mode 100644 index 0000000..dd3174e --- /dev/null +++ b/arch/arm/mach-s5pc100/setup-i2c0.c @@ -0,0 +1,30 @@ +/* linux/arch/arm/mach-s5pc100/setup-i2c0.c + * + * Copyright 2009 Samsung Electronics Co. + * Byungho Min + * + * Base S5PC100 I2C bus 0 gpio configuration + * + * Based on plat-s3c64xx/setup-i2c0.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include + +struct platform_device; /* don't need the contents */ + +#include +#include +#include + +void s3c_i2c0_cfg_gpio(struct platform_device *dev) +{ + s3c_gpio_cfgpin(S5PC100_GPD(3), S3C_GPIO_SFN(2)); + s3c_gpio_setpull(S5PC100_GPD(3), S3C_GPIO_PULL_UP); + s3c_gpio_cfgpin(S5PC100_GPD(4), S3C_GPIO_SFN(2)); + s3c_gpio_setpull(S5PC100_GPD(4), S3C_GPIO_PULL_UP); +} diff --git a/arch/arm/mach-s5pc100/setup-i2c1.c b/arch/arm/mach-s5pc100/setup-i2c1.c new file mode 100644 index 0000000..d1fec26 --- /dev/null +++ b/arch/arm/mach-s5pc100/setup-i2c1.c @@ -0,0 +1,30 @@ +/* linux/arch/arm/mach-s5pc100/setup-i2c1.c + * + * Copyright 2009 Samsung Electronics Co. + * Byungho Min + * + * Base S5PC100 I2C bus 1 gpio configuration + * + * Based on plat-s3c64xx/setup-i2c1.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include + +struct platform_device; /* don't need the contents */ + +#include +#include +#include + +void s3c_i2c1_cfg_gpio(struct platform_device *dev) +{ + s3c_gpio_cfgpin(S5PC100_GPD(5), S3C_GPIO_SFN(2)); + s3c_gpio_setpull(S5PC100_GPD(5), S3C_GPIO_PULL_UP); + s3c_gpio_cfgpin(S5PC100_GPD(6), S3C_GPIO_SFN(2)); + s3c_gpio_setpull(S5PC100_GPD(6), S3C_GPIO_PULL_UP); +} diff --git a/arch/arm/plat-s5pc1xx/Kconfig b/arch/arm/plat-s5pc1xx/Kconfig index 708f7a0..c7bd2bb 100644 --- a/arch/arm/plat-s5pc1xx/Kconfig +++ b/arch/arm/plat-s5pc1xx/Kconfig @@ -39,20 +39,6 @@ config CPU_S5PC100_CLOCK # platform specific device setup -config S5PC1XX_SETUP_I2C0 - bool - default y - help - Common setup code for i2c bus 0. - - Note, currently since i2c0 is always compiled, this setup helper - is always compiled with it. - -config S5PC1XX_SETUP_I2C1 - bool - help - Common setup code for i2c bus 1. - config S5PC1XX_SETUP_SDHCI_GPIO bool help diff --git a/arch/arm/plat-s5pc1xx/Makefile b/arch/arm/plat-s5pc1xx/Makefile index a5b90c0..9ce6409 100644 --- a/arch/arm/plat-s5pc1xx/Makefile +++ b/arch/arm/plat-s5pc1xx/Makefile @@ -23,6 +23,4 @@ obj-$(CONFIG_CPU_S5PC100_CLOCK) += s5pc100-clock.o # Device setup -obj-$(CONFIG_S5PC1XX_SETUP_I2C0) += setup-i2c0.o -obj-$(CONFIG_S5PC1XX_SETUP_I2C1) += setup-i2c1.o obj-$(CONFIG_S5PC1XX_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o diff --git a/arch/arm/plat-s5pc1xx/setup-i2c0.c b/arch/arm/plat-s5pc1xx/setup-i2c0.c deleted file mode 100644 index 5e4a7c3..0000000 --- a/arch/arm/plat-s5pc1xx/setup-i2c0.c +++ /dev/null @@ -1,30 +0,0 @@ -/* linux/arch/arm/plat-s5pc1xx/setup-i2c0.c - * - * Copyright 2009 Samsung Electronics Co. - * Byungho Min - * - * Base S5PC1XX I2C bus 0 gpio configuration - * - * Based on plat-s3c64xx/setup-i2c0.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#include -#include - -struct platform_device; /* don't need the contents */ - -#include -#include -#include - -void s3c_i2c0_cfg_gpio(struct platform_device *dev) -{ - s3c_gpio_cfgpin(S5PC100_GPD(3), S3C_GPIO_SFN(2)); - s3c_gpio_setpull(S5PC100_GPD(3), S3C_GPIO_PULL_UP); - s3c_gpio_cfgpin(S5PC100_GPD(4), S3C_GPIO_SFN(2)); - s3c_gpio_setpull(S5PC100_GPD(4), S3C_GPIO_PULL_UP); -} diff --git a/arch/arm/plat-s5pc1xx/setup-i2c1.c b/arch/arm/plat-s5pc1xx/setup-i2c1.c deleted file mode 100644 index a0a8b4a..0000000 --- a/arch/arm/plat-s5pc1xx/setup-i2c1.c +++ /dev/null @@ -1,30 +0,0 @@ -/* linux/arch/arm/plat-s3c64xx/setup-i2c1.c - * - * Copyright 2009 Samsung Electronics Co. - * Byungho Min - * - * Base S5PC1XX I2C bus 1 gpio configuration - * - * Based on plat-s3c64xx/setup-i2c1.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#include -#include - -struct platform_device; /* don't need the contents */ - -#include -#include -#include - -void s3c_i2c1_cfg_gpio(struct platform_device *dev) -{ - s3c_gpio_cfgpin(S5PC100_GPD(5), S3C_GPIO_SFN(2)); - s3c_gpio_setpull(S5PC100_GPD(5), S3C_GPIO_PULL_UP); - s3c_gpio_cfgpin(S5PC100_GPD(6), S3C_GPIO_SFN(2)); - s3c_gpio_setpull(S5PC100_GPD(6), S3C_GPIO_PULL_UP); -} -- cgit v0.10.2 From 73e59b1d6b69f5ae02e3be5e2b3259c46d8bb27a Mon Sep 17 00:00:00 2001 From: Maurus Cuelenaere Date: Tue, 4 May 2010 13:12:41 +0200 Subject: ARM: SAMSUNG: Move mach/ts.h to plat/ts.h This moves mach-s3c2410/include/mach/ts.h to plat-samsung/include/plat/ts.h in order to prepare for s3c64xx support in the touchscreen driver. Signed-off-by: Maurus Cuelenaere Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/include/mach/ts.h b/arch/arm/mach-s3c2410/include/mach/ts.h deleted file mode 100644 index dc36170..0000000 --- a/arch/arm/mach-s3c2410/include/mach/ts.h +++ /dev/null @@ -1,21 +0,0 @@ -/* linux/include/asm/arch-s3c2410/ts.h - * - * Copyright (c) 2005 Arnaud Patard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#ifndef __ASM_ARM_TS_H -#define __ASM_ARM_TS_H - -struct s3c2410_ts_mach_info { - int delay; - int presc; - int oversampling_shift; -}; - -extern void s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *); - -#endif /* __ASM_ARM_TS_H */ diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c index d2a2fad..b1f7dbb 100644 --- a/arch/arm/mach-s3c2410/mach-h1940.c +++ b/arch/arm/mach-s3c2410/mach-h1940.c @@ -46,7 +46,6 @@ #include #include #include -#include #include #include @@ -57,6 +56,7 @@ #include #include #include +#include static struct map_desc h1940_iodesc[] __initdata = { [0] = { diff --git a/arch/arm/plat-s3c24xx/devs.c b/arch/arm/plat-s3c24xx/devs.c index cd5b41d..5858373 100644 --- a/arch/arm/plat-s3c24xx/devs.c +++ b/arch/arm/plat-s3c24xx/devs.c @@ -39,8 +39,7 @@ #include #include #include - -#include +#include /* Serial port registrations */ diff --git a/arch/arm/plat-samsung/include/plat/ts.h b/arch/arm/plat-samsung/include/plat/ts.h new file mode 100644 index 0000000..8a51675 --- /dev/null +++ b/arch/arm/plat-samsung/include/plat/ts.h @@ -0,0 +1,21 @@ +/* arch/arm/plat-samsung/include/plat/ts.h + * + * Copyright (c) 2005 Arnaud Patard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARM_TS_H +#define __ASM_ARM_TS_H + +struct s3c2410_ts_mach_info { + int delay; + int presc; + int oversampling_shift; +}; + +extern void s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *); + +#endif /* __ASM_ARM_TS_H */ diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c index 98a7d12..a2e1228 100644 --- a/drivers/input/touchscreen/s3c2410_ts.c +++ b/drivers/input/touchscreen/s3c2410_ts.c @@ -37,9 +37,9 @@ #include #include +#include #include -#include #define TSC_SLEEP (S3C2410_ADCTSC_PULL_UP_DISABLE | S3C2410_ADCTSC_XY_PST(0)) -- cgit v0.10.2 From 909de0d67dbd9488d5f77bdcadcd34264fea3c02 Mon Sep 17 00:00:00 2001 From: Maurus Cuelenaere Date: Tue, 4 May 2010 13:12:44 +0200 Subject: ARM: S3C64XX: Add touchscreen platform device definition This patch adds the touchscreen platform device definition for S3C64XX boards. Signed-off-by: Maurus Cuelenaere Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c64xx/Makefile b/arch/arm/mach-s3c64xx/Makefile index d78c3dd..a10f1fc 100644 --- a/arch/arm/mach-s3c64xx/Makefile +++ b/arch/arm/mach-s3c64xx/Makefile @@ -58,3 +58,4 @@ obj-$(CONFIG_MACH_HMT) += mach-hmt.o obj-y += dev-uart.o obj-y += dev-audio.o obj-$(CONFIG_S3C64XX_DEV_SPI) += dev-spi.o +obj-$(CONFIG_S3C64XX_DEV_TS) += dev-ts.o diff --git a/arch/arm/mach-s3c64xx/dev-ts.c b/arch/arm/mach-s3c64xx/dev-ts.c new file mode 100644 index 0000000..17cc793 --- /dev/null +++ b/arch/arm/mach-s3c64xx/dev-ts.c @@ -0,0 +1,61 @@ +/* linux/arch/arm/mach-s3c64xx/dev-ts.c + * + * Copyright (c) 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks , + * + * Adapted by Maurus Cuelenaere for s3c64xx + * + * S3C64XX series device definition for touchscreen device + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include +#include + +#include +#include + +#include +#include + +static struct resource s3c_ts_resource[] = { + [0] = { + .start = S3C64XX_PA_ADC, + .end = S3C64XX_PA_ADC + SZ_256 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_TC, + .end = IRQ_TC, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device s3c_device_ts = { + .name = "s3c64xx-ts", + .id = -1, + .num_resources = ARRAY_SIZE(s3c_ts_resource), + .resource = s3c_ts_resource, +}; + +void __init s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *pd) +{ + struct s3c2410_ts_mach_info *npd; + + if (!pd) { + printk(KERN_ERR "%s: no platform data\n", __func__); + return; + } + + npd = kmemdup(pd, sizeof(struct s3c2410_ts_mach_info), GFP_KERNEL); + if (!npd) + printk(KERN_ERR "%s: no memory for platform data\n", __func__); + + s3c_device_ts.dev.platform_data = npd; +} +EXPORT_SYMBOL(s3c24xx_ts_set_platdata); diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig index 711d5a4..896b171 100644 --- a/arch/arm/plat-samsung/Kconfig +++ b/arch/arm/plat-samsung/Kconfig @@ -206,6 +206,12 @@ config S3C64XX_DEV_SPI Compile in platform device definitions for S3C64XX's type SPI controllers. +config S3C64XX_DEV_TS + bool + help + Common in platform device definitions for S3C64XX touchscreen + device + # DMA config S3C_DMA -- cgit v0.10.2 From 5bfdca146edc558ae6b3bac6b05dc5b1f094fbf3 Mon Sep 17 00:00:00 2001 From: Naveen Krishna Date: Tue, 18 May 2010 20:44:27 +0900 Subject: ARM: SAMSUNG: Implements cfg_gpio function for Samsung touchscreen This patch implements cfg_gpio function for Samsung touchscreen. And also modifies the H1940 machine respectively. Signed-off-by: Naveen Krishna Ch Signed-off-by: Kukjin Kim Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig index a4c0b3f..7245a55 100644 --- a/arch/arm/mach-s3c2410/Kconfig +++ b/arch/arm/mach-s3c2410/Kconfig @@ -77,6 +77,7 @@ config ARCH_H1940 select PM_H1940 if PM select S3C_DEV_USB_HOST select S3C_DEV_NAND + select S3C2410_SETUP_TS help Say Y here if you are using the HP IPAQ H1940 diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c index b1f7dbb..779b45b 100644 --- a/arch/arm/mach-s3c2410/mach-h1940.c +++ b/arch/arm/mach-s3c2410/mach-h1940.c @@ -146,6 +146,7 @@ static struct s3c2410_ts_mach_info h1940_ts_cfg __initdata = { .delay = 10000, .presc = 49, .oversampling_shift = 2, + .cfg_gpio = s3c24xx_ts_cfg_gpio, }; /** diff --git a/arch/arm/plat-s3c24xx/Kconfig b/arch/arm/plat-s3c24xx/Kconfig index 3ce8f01..984bf66 100644 --- a/arch/arm/plat-s3c24xx/Kconfig +++ b/arch/arm/plat-s3c24xx/Kconfig @@ -164,4 +164,9 @@ config S3C24XX_SIMTEC_AUDIO help Add audio devices for common Simtec S3C24XX boards +config S3C2410_SETUP_TS + bool + help + Compile in platform device definition for Samsung TouchScreen. + endif diff --git a/arch/arm/plat-s3c24xx/Makefile b/arch/arm/plat-s3c24xx/Makefile index 44aea88..c2064c3 100644 --- a/arch/arm/plat-s3c24xx/Makefile +++ b/arch/arm/plat-s3c24xx/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_S3C2410_CPUFREQ_UTILS) += s3c2410-cpufreq-utils.o # device specific setup and/or initialisation obj-$(CONFIG_ARCH_S3C2410) += setup-i2c.o +obj-$(CONFIG_S3C2410_SETUP_TS) += setup-ts.o # SPI gpio central GPIO functions diff --git a/arch/arm/plat-s3c24xx/setup-ts.c b/arch/arm/plat-s3c24xx/setup-ts.c new file mode 100644 index 0000000..ed26386 --- /dev/null +++ b/arch/arm/plat-s3c24xx/setup-ts.c @@ -0,0 +1,34 @@ +/* linux/arch/arm/plat-s3c24xx/setup-ts.c + * + * Copyright (c) 2010 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Based on S3C24XX setup for i2c device + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include + +struct platform_device; /* don't need the contents */ + +#include +#include + +/** + * s3c24xx_ts_cfg_gpio - configure gpio for s3c2410 systems + * + * Configure the GPIO for the S3C2410 system, where we have external FETs + * connected to the device (later systems such as the S3C2440 integrate + * these into the device). + */ +void s3c24xx_ts_cfg_gpio(struct platform_device *dev) +{ + s3c2410_gpio_cfgpin(S3C2410_GPG(12), S3C2410_GPG12_XMON); + s3c2410_gpio_cfgpin(S3C2410_GPG(13), S3C2410_GPG13_nXPON); + s3c2410_gpio_cfgpin(S3C2410_GPG(14), S3C2410_GPG14_YMON); + s3c2410_gpio_cfgpin(S3C2410_GPG(15), S3C2410_GPG15_nYPON); +} diff --git a/arch/arm/plat-samsung/include/plat/ts.h b/arch/arm/plat-samsung/include/plat/ts.h index 8a51675..26fdb22 100644 --- a/arch/arm/plat-samsung/include/plat/ts.h +++ b/arch/arm/plat-samsung/include/plat/ts.h @@ -14,8 +14,12 @@ struct s3c2410_ts_mach_info { int delay; int presc; int oversampling_shift; + void (*cfg_gpio)(struct platform_device *dev); }; extern void s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *); +/* defined by architecture to configure gpio */ +extern void s3c24xx_ts_cfg_gpio(struct platform_device *dev); + #endif /* __ASM_ARM_TS_H */ -- cgit v0.10.2 From 2b6c02abca5a04bf8d9f8a3b1976a5b10d317603 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 19 May 2010 14:36:28 +0900 Subject: ARM: SAMSUNG: Move s3c64xx dev-ts.c to plat-samsung and rename configuration Move the arch/arm/mach-s3c64xx/dev-ts.c file to arch/arm/plat-samsung and rename the Kconfig entry appropriately. Signed-off-by: Ben Dooks diff --git a/arch/arm/mach-s3c64xx/dev-ts.c b/arch/arm/mach-s3c64xx/dev-ts.c deleted file mode 100644 index 17cc793..0000000 --- a/arch/arm/mach-s3c64xx/dev-ts.c +++ /dev/null @@ -1,61 +0,0 @@ -/* linux/arch/arm/mach-s3c64xx/dev-ts.c - * - * Copyright (c) 2008 Simtec Electronics - * http://armlinux.simtec.co.uk/ - * Ben Dooks , - * - * Adapted by Maurus Cuelenaere for s3c64xx - * - * S3C64XX series device definition for touchscreen device - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#include -#include -#include - -#include -#include - -#include -#include - -static struct resource s3c_ts_resource[] = { - [0] = { - .start = S3C64XX_PA_ADC, - .end = S3C64XX_PA_ADC + SZ_256 - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_TC, - .end = IRQ_TC, - .flags = IORESOURCE_IRQ, - }, -}; - -struct platform_device s3c_device_ts = { - .name = "s3c64xx-ts", - .id = -1, - .num_resources = ARRAY_SIZE(s3c_ts_resource), - .resource = s3c_ts_resource, -}; - -void __init s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *pd) -{ - struct s3c2410_ts_mach_info *npd; - - if (!pd) { - printk(KERN_ERR "%s: no platform data\n", __func__); - return; - } - - npd = kmemdup(pd, sizeof(struct s3c2410_ts_mach_info), GFP_KERNEL); - if (!npd) - printk(KERN_ERR "%s: no memory for platform data\n", __func__); - - s3c_device_ts.dev.platform_data = npd; -} -EXPORT_SYMBOL(s3c24xx_ts_set_platdata); diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig index 896b171..229919e 100644 --- a/arch/arm/plat-samsung/Kconfig +++ b/arch/arm/plat-samsung/Kconfig @@ -206,11 +206,10 @@ config S3C64XX_DEV_SPI Compile in platform device definitions for S3C64XX's type SPI controllers. -config S3C64XX_DEV_TS +config SAMSUNG_DEV_TS bool help - Common in platform device definitions for S3C64XX touchscreen - device + Common in platform device definitions for touchscreen device # DMA diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile index 7068af3..4828849 100644 --- a/arch/arm/plat-samsung/Makefile +++ b/arch/arm/plat-samsung/Makefile @@ -44,6 +44,7 @@ obj-$(CONFIG_S3C_DEV_NAND) += dev-nand.o obj-$(CONFIG_S3C_DEV_RTC) += dev-rtc.o obj-$(CONFIG_SAMSUNG_DEV_ADC) += dev-adc.o +obj-$(CONFIG_SAMSUNG_DEV_TS) += dev-ts.o # DMA support diff --git a/arch/arm/plat-samsung/dev-ts.c b/arch/arm/plat-samsung/dev-ts.c new file mode 100644 index 0000000..236ef84 --- /dev/null +++ b/arch/arm/plat-samsung/dev-ts.c @@ -0,0 +1,61 @@ +/* linux/arch/arm/mach-s3c64xx/dev-ts.c + * + * Copyright (c) 2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks , + * + * Adapted by Maurus Cuelenaere for s3c64xx + * + * S3C64XX series device definition for touchscreen device + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include +#include + +#include +#include + +#include +#include + +static struct resource s3c_ts_resource[] = { + [0] = { + .start = SAMSUNG_PA_ADC, + .end = SAMSUNG_PA_ADC + SZ_256 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_TC, + .end = IRQ_TC, + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device s3c_device_ts = { + .name = "s3c64xx-ts", + .id = -1, + .num_resources = ARRAY_SIZE(s3c_ts_resource), + .resource = s3c_ts_resource, +}; + +void __init s3c24xx_ts_set_platdata(struct s3c2410_ts_mach_info *pd) +{ + struct s3c2410_ts_mach_info *npd; + + if (!pd) { + printk(KERN_ERR "%s: no platform data\n", __func__); + return; + } + + npd = kmemdup(pd, sizeof(struct s3c2410_ts_mach_info), GFP_KERNEL); + if (!npd) + printk(KERN_ERR "%s: no memory for platform data\n", __func__); + + s3c_device_ts.dev.platform_data = npd; +} +EXPORT_SYMBOL(s3c24xx_ts_set_platdata); -- cgit v0.10.2 From 658ad39ea91d8f0597654032a768930497161a58 Mon Sep 17 00:00:00 2001 From: Naveen Krishna Date: Tue, 18 May 2010 20:44:38 +0900 Subject: Input: s3c24xx_ts - Implement generic GPIO configuration callback This patch implements generic GPIO configuration function in Samsung touchscreen driver. And makes the touchscreen driver s3c24xx-ts.c generic to all the Samsung SoCs. Signed-off-by: Naveen Krishna Ch Signed-off-by: Kukjin Kim [ben-linux@fluff.org: fixed title ] Signed-off-by: Ben Dooks Acked-by: Dmitry Torokhov diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c index a2e1228..86086a4 100644 --- a/drivers/input/touchscreen/s3c2410_ts.c +++ b/drivers/input/touchscreen/s3c2410_ts.c @@ -39,8 +39,6 @@ #include #include -#include - #define TSC_SLEEP (S3C2410_ADCTSC_PULL_UP_DISABLE | S3C2410_ADCTSC_XY_PST(0)) #define INT_DOWN (0) @@ -88,21 +86,6 @@ struct s3c2410ts { static struct s3c2410ts ts; /** - * s3c2410_ts_connect - configure gpio for s3c2410 systems - * - * Configure the GPIO for the S3C2410 system, where we have external FETs - * connected to the device (later systems such as the S3C2440 integrate - * these into the device). -*/ -static inline void s3c2410_ts_connect(void) -{ - s3c2410_gpio_cfgpin(S3C2410_GPG(12), S3C2410_GPG12_XMON); - s3c2410_gpio_cfgpin(S3C2410_GPG(13), S3C2410_GPG13_nXPON); - s3c2410_gpio_cfgpin(S3C2410_GPG(14), S3C2410_GPG14_YMON); - s3c2410_gpio_cfgpin(S3C2410_GPG(15), S3C2410_GPG15_nYPON); -} - -/** * get_down - return the down state of the pen * @data0: The data read from ADCDAT0 register. * @data1: The data read from ADCDAT1 register. @@ -296,9 +279,9 @@ static int __devinit s3c2410ts_probe(struct platform_device *pdev) goto err_clk; } - /* Configure the touchscreen external FETs on the S3C2410 */ - if (!platform_get_device_id(pdev)->driver_data) - s3c2410_ts_connect(); + /* inititalise the gpio */ + if (info->cfg_gpio) + info->cfg_gpio(to_platform_device(ts.dev)); ts.client = s3c_adc_register(pdev, s3c24xx_ts_select, s3c24xx_ts_conversion, 1); -- cgit v0.10.2 From 91df77d7b550d3c8167c97c6e3b97f2ca4d9f3af Mon Sep 17 00:00:00 2001 From: Naveen Krishna Date: Tue, 18 May 2010 20:44:45 +0900 Subject: Input: s3c24xx_ts - Add FEAT for Samsung touchscreen support This patch adds a feature bit field in the touchscreen driver for Samsung SoCs. Which can be used to distinguish the TSADC module features. Signed-off-by: Naveen Krishna Ch Signed-off-by: Kukjin Kim [ben-linux@fluff.org: minor fix to title] Signed-off-by: Ben Dooks Acked-by: Dmitry Torokhov diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c index 86086a4..e0b7c83 100644 --- a/drivers/input/touchscreen/s3c2410_ts.c +++ b/drivers/input/touchscreen/s3c2410_ts.c @@ -55,6 +55,8 @@ S3C2410_ADCTSC_AUTO_PST | \ S3C2410_ADCTSC_XY_PST(0)) +#define FEAT_PEN_IRQ (1 << 0) /* HAS ADCCLRINTPNDNUP */ + /* Per-touchscreen data. */ /** @@ -69,6 +71,7 @@ * @irq_tc: The interrupt number for pen up/down interrupt * @count: The number of samples collected. * @shift: The log2 of the maximum count to read in one go. + * @features: The features supported by the TSADC MOdule. */ struct s3c2410ts { struct s3c_adc_client *client; @@ -81,6 +84,7 @@ struct s3c2410ts { int irq_tc; int count; int shift; + int features; }; static struct s3c2410ts ts; @@ -171,6 +175,11 @@ static irqreturn_t stylus_irq(int irq, void *dev_id) else dev_info(ts.dev, "%s: count=%d\n", __func__, ts.count); + if (ts.features & FEAT_PEN_IRQ) { + /* Clear pen down/up interrupt */ + writel(0x0, ts.io + S3C64XX_ADCCLRINTPNDNUP); + } + return IRQ_HANDLED; } @@ -317,6 +326,7 @@ static int __devinit s3c2410ts_probe(struct platform_device *pdev) ts.input->id.version = 0x0102; ts.shift = info->oversampling_shift; + ts.features = platform_get_device_id(pdev)->driver_data; ret = request_irq(ts.irq_tc, stylus_irq, IRQF_DISABLED, "s3c2410_ts_pen", ts.input); @@ -403,15 +413,14 @@ static struct dev_pm_ops s3c_ts_pmops = { #endif static struct platform_device_id s3cts_driver_ids[] = { - { "s3c2410-ts", 0 }, - { "s3c2440-ts", 1 }, + { "s3c64xx-ts", FEAT_PEN_IRQ }, { } }; MODULE_DEVICE_TABLE(platform, s3cts_driver_ids); static struct platform_driver s3c_ts_driver = { .driver = { - .name = "s3c24xx-ts", + .name = "samsung-ts", .owner = THIS_MODULE, #ifdef CONFIG_PM .pm = &s3c_ts_pmops, -- cgit v0.10.2 From 504d36e91ac12ccdb0e1193cee7bef9831a1c99e Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 19 May 2010 14:45:01 +0900 Subject: Input: s3c24xx_ts - depend on SAMSUNG_DEV_TS and update menu entry Make the driver depend on either ARCH_S3C2410 (as legacy) or the new device selection of SAMSUNG_DEV_TS. Change the menuconfig name to reflect this driver is now handling more devices that just the s3c2410. Signed-off-by: Ben Dooks Acked-by: Dmitry Torokhov diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 8a8fa4d..77a50d9 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -158,8 +158,8 @@ config TOUCHSCREEN_FUJITSU module will be called fujitsu-ts. config TOUCHSCREEN_S3C2410 - tristate "Samsung S3C2410 touchscreen input driver" - depends on ARCH_S3C2410 + tristate "Samsung S3C2410/generic touchscreen input driver" + depends on ARCH_S3C2410 || SAMSUNG_DEV_TS select S3C24XX_ADC help Say Y here if you have the s3c2410 touchscreen. -- cgit v0.10.2 From 5e682ef825302f2378726e44257291eaeadbfd50 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Wed, 19 May 2010 11:37:20 -0700 Subject: Revert "rtc: omap: let device wakeup capability be configured from chip init logic" This reverts commit 9c0a342c45b2d98209ac473ea7a429ddd5c1b473 because it was included without proper signoffs from RTC maintainers. diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index 73377b0..64d9727 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -34,8 +34,7 @@ * Board-specific wiring options include using split power mode with * RTC_OFF_NOFF used as the reset signal (so the RTC won't be reset), * and wiring RTC_WAKE_INT (so the RTC alarm can wake the system from - * low power modes) for OMAP1 boards (OMAP-L138 has this built into - * the SoC). See the BOARD-SPECIFIC CUSTOMIZATION comment. + * low power modes). See the BOARD-SPECIFIC CUSTOMIZATION comment. */ #define OMAP_RTC_BASE 0xfffb4800 @@ -402,17 +401,16 @@ static int __init omap_rtc_probe(struct platform_device *pdev) /* BOARD-SPECIFIC CUSTOMIZATION CAN GO HERE: * - * - Device wake-up capability setting should come through chip - * init logic. OMAP1 boards should initialize the "wakeup capable" - * flag in the platform device if the board is wired right for - * being woken up by RTC alarm. For OMAP-L138, this capability - * is built into the SoC by the "Deep Sleep" capability. + * - Boards wired so that RTC_WAKE_INT does something, and muxed + * right (W13_1610_RTC_WAKE_INT is the default after chip reset), + * should initialize the device wakeup flag appropriately. * * - Boards wired so RTC_ON_nOFF is used as the reset signal, * rather than nPWRON_RESET, should forcibly enable split * power mode. (Some chip errata report that RTC_CTRL_SPLIT * is write-only, and always reads as zero...) */ + device_init_wakeup(&pdev->dev, 0); if (new_ctrl & (u8) OMAP_RTC_CTRL_SPLIT) pr_info("%s: split power mode\n", pdev->name); -- cgit v0.10.2 From fa9dc265ace9774e62f0e31108e5f47911124bda Mon Sep 17 00:00:00 2001 From: KOSAKI Motohiro Date: Wed, 19 May 2010 09:37:41 +0900 Subject: cpumask: fix compat getaffinity Commit a45185d2d "cpumask: convert kernel/compat.c" broke libnuma, which abuses sched_getaffinity to find out NR_CPUS in order to parse /sys/devices/system/node/node*/cpumap. On NUMA systems with less than 32 possibly CPUs, the current compat_sys_sched_getaffinity now returns '4' instead of the actual NR_CPUS/8, which makes libnuma bail out when parsing the cpumap. The libnuma call sched_getaffinity(0, bitmap, 4096) at first. It mean the libnuma expect the return value of sched_getaffinity() is either len argument or NR_CPUS. But it doesn't expect to return nr_cpu_ids. Strictly speaking, userland requirement are 1) Glibc assume the return value mean the lengh of initialized of mask argument. E.g. if sched_getaffinity(1024) return 128, glibc make zero fill rest 896 byte. 2) Libnuma assume the return value can be used to guess NR_CPUS in kernel. It assume len-arg Acked-by: Rusty Russell Acked-by: Arnd Bergmann Reported-by: Ken Werner Cc: stable@kernel.org Cc: Andi Kleen Signed-off-by: Linus Torvalds diff --git a/kernel/compat.c b/kernel/compat.c index 7f40e92..5adab05 100644 --- a/kernel/compat.c +++ b/kernel/compat.c @@ -495,29 +495,26 @@ asmlinkage long compat_sys_sched_getaffinity(compat_pid_t pid, unsigned int len, { int ret; cpumask_var_t mask; - unsigned long *k; - unsigned int min_length = cpumask_size(); - - if (nr_cpu_ids <= BITS_PER_COMPAT_LONG) - min_length = sizeof(compat_ulong_t); - if (len < min_length) + if ((len * BITS_PER_BYTE) < nr_cpu_ids) + return -EINVAL; + if (len & (sizeof(compat_ulong_t)-1)) return -EINVAL; if (!alloc_cpumask_var(&mask, GFP_KERNEL)) return -ENOMEM; ret = sched_getaffinity(pid, mask); - if (ret < 0) - goto out; + if (ret == 0) { + size_t retlen = min_t(size_t, len, cpumask_size()); - k = cpumask_bits(mask); - ret = compat_put_bitmap(user_mask_ptr, k, min_length * 8); - if (ret == 0) - ret = min_length; - -out: + if (compat_put_bitmap(user_mask_ptr, cpumask_bits(mask), retlen * 8)) + ret = -EFAULT; + else + ret = retlen; + } free_cpumask_var(mask); + return ret; } -- cgit v0.10.2 From 1bc2962e530527de829bf4b1eb99f24dc25d1828 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 2 Apr 2010 14:15:09 +0100 Subject: i2c-s3c2410: Remove unconditional 1ms delay on each transfer The S3C I2C controller indicates completion of I2C transfers before the bus has a stop condition on it. In order to ensure that we do not attempt to start a new transfer before the bus is idle the driver currently inserts a 1ms delay. This is vastly larger than is generally required and has a visible effect on performance under load, such as when bringing up audio CODECs or reading back status information with non-bulk I2C reads. Replace the sleep with a spin on the IIC status register for up to 1ms. This will busy wait but testing on my SMDK6410 system indicates that the overwhelming majority of transactions complete on the first spin, with maximum latencies of less than 10 spins so the absolute overhead of busy waiting should be at worst comprable to msleep(), and the overall system performance is dramatically improved. The main risk is poor interaction with multimaster systems where we may miss the bus going idle before the next transaction. Defend against this by falling back to the original 1ms delay after 20 spins. The overall effect in my testing is an approximately 20% improvement in kernel startup time. Signed-off-by: Mark Brown Signed-off-by: Ben Dooks diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index d27072b..ec3256c 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -482,7 +482,8 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c) static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg *msgs, int num) { - unsigned long timeout; + unsigned long iicstat, timeout; + int spins = 20; int ret; if (i2c->suspended) @@ -521,7 +522,21 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, /* ensure the stop has been through the bus */ - msleep(1); + dev_dbg(i2c->dev, "waiting for bus idle\n"); + + /* first, try busy waiting briefly */ + do { + iicstat = readl(i2c->regs + S3C2410_IICSTAT); + } while ((iicstat & S3C2410_IICSTAT_START) && --spins); + + /* if that timed out sleep */ + if (!spins) { + msleep(1); + iicstat = readl(i2c->regs + S3C2410_IICSTAT); + } + + if (iicstat & S3C2410_IICSTAT_START) + dev_warn(i2c->dev, "timeout waiting for bus idle\n"); out: return ret; -- cgit v0.10.2 From dd7319a5289deb4e17beb8851d343e7930b32c3b Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Mon, 22 Mar 2010 03:23:16 -0400 Subject: i2c-bfin-twi: integrate timeout timer with completion interface There isn't much point in managing our own custom timeout timer when the completion interface already includes support for it. This makes the resulting code much simpler and robust. Signed-off-by: Sonic Zhang Signed-off-by: Mike Frysinger Signed-off-by: Ben Dooks diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c index f1e14dd..441134a 100644 --- a/drivers/i2c/busses/i2c-bfin-twi.c +++ b/drivers/i2c/busses/i2c-bfin-twi.c @@ -25,8 +25,6 @@ #include #include -#define POLL_TIMEOUT (2 * HZ) - /* SMBus mode*/ #define TWI_I2C_MODE_STANDARD 1 #define TWI_I2C_MODE_STANDARDSUB 2 @@ -44,8 +42,6 @@ struct bfin_twi_iface { int cur_mode; int manual_stop; int result; - int timeout_count; - struct timer_list timeout_timer; struct i2c_adapter adap; struct completion complete; struct i2c_msg *pmsg; @@ -169,16 +165,13 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface) write_INT_MASK(iface, 0); write_MASTER_CTL(iface, 0); SSYNC(); - /* If it is a quick transfer, only address bug no data, + /* If it is a quick transfer, only address without data, * not an err, return 1. + * If address is acknowledged return 1. */ - if (iface->writeNum == 0 && (mast_stat & BUFRDERR)) + if ((iface->writeNum == 0 && (mast_stat & BUFRDERR)) + || !(mast_stat & ANAK)) iface->result = 1; - /* If address not acknowledged return -1, - * else return 0. - */ - else if (!(mast_stat & ANAK)) - iface->result = 0; } complete(&iface->complete); return; @@ -250,9 +243,9 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface) write_INT_MASK(iface, 0); write_MASTER_CTL(iface, 0); SSYNC(); - complete(&iface->complete); } } + complete(&iface->complete); } /* Interrupt handler */ @@ -262,36 +255,15 @@ static irqreturn_t bfin_twi_interrupt_entry(int irq, void *dev_id) unsigned long flags; spin_lock_irqsave(&iface->lock, flags); - del_timer(&iface->timeout_timer); bfin_twi_handle_interrupt(iface); spin_unlock_irqrestore(&iface->lock, flags); return IRQ_HANDLED; } -static void bfin_twi_timeout(unsigned long data) -{ - struct bfin_twi_iface *iface = (struct bfin_twi_iface *)data; - unsigned long flags; - - spin_lock_irqsave(&iface->lock, flags); - bfin_twi_handle_interrupt(iface); - if (iface->result == 0) { - iface->timeout_count--; - if (iface->timeout_count > 0) { - iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; - add_timer(&iface->timeout_timer); - } else { - iface->result = -1; - complete(&iface->complete); - } - } - spin_unlock_irqrestore(&iface->lock, flags); -} - /* - * Generic i2c master transfer entrypoint + * One i2c master transfer */ -static int bfin_twi_master_xfer(struct i2c_adapter *adap, +static int bfin_twi_do_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { struct bfin_twi_iface *iface = adap->algo_data; @@ -319,7 +291,6 @@ static int bfin_twi_master_xfer(struct i2c_adapter *adap, iface->transPtr = pmsg->buf; iface->writeNum = iface->readNum = pmsg->len; iface->result = 0; - iface->timeout_count = 10; init_completion(&(iface->complete)); /* Set Transmit device address */ write_MASTER_ADDR(iface, pmsg->addr); @@ -358,30 +329,49 @@ static int bfin_twi_master_xfer(struct i2c_adapter *adap, iface->manual_stop = 1; } - iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; - add_timer(&iface->timeout_timer); - /* Master enable */ write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN | ((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) | ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ > 100) ? FAST : 0)); SSYNC(); - wait_for_completion(&iface->complete); - - rc = iface->result; + while (!iface->result) { + if (!wait_for_completion_timeout(&iface->complete, + adap->timeout)) { + iface->result = -1; + dev_err(&adap->dev, "master transfer timeout\n"); + } + } - if (rc == 1) - return num; + if (iface->result == 1) + rc = iface->cur_msg + 1; else - return rc; + rc = iface->result; + + return rc; } /* - * SMBus type transfer entrypoint + * Generic i2c master transfer entrypoint */ +static int bfin_twi_master_xfer(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num) +{ + int i, ret = 0; -int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr, + for (i = 0; i < adap->retries; i++) { + ret = bfin_twi_do_master_xfer(adap, msgs, num); + if (ret > 0) + break; + } + + return ret; +} + +/* + * One I2C SMBus transfer + */ +int bfin_twi_do_smbus_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data) { @@ -469,7 +459,6 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr, iface->manual_stop = 0; iface->read_write = read_write; iface->command = command; - iface->timeout_count = 10; init_completion(&(iface->complete)); /* FIFO Initiation. Data in FIFO should be discarded before @@ -486,9 +475,6 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr, write_MASTER_ADDR(iface, addr); SSYNC(); - iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; - add_timer(&iface->timeout_timer); - switch (iface->cur_mode) { case TWI_I2C_MODE_STANDARDSUB: write_XMT_DATA8(iface, iface->command); @@ -550,10 +536,8 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr, else if (iface->readNum > 255) { write_MASTER_CTL(iface, 0xff << 6); iface->manual_stop = 1; - } else { - del_timer(&iface->timeout_timer); + } else break; - } } } write_INT_MASK(iface, MCOMP | MERR | @@ -569,7 +553,13 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr, } SSYNC(); - wait_for_completion(&iface->complete); + while (!iface->result) { + if (!wait_for_completion_timeout(&iface->complete, + adap->timeout)) { + iface->result = -1; + dev_err(&adap->dev, "smbus transfer timeout\n"); + } + } rc = (iface->result >= 0) ? 0 : -1; @@ -577,6 +567,25 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr, } /* + * Generic I2C SMBus transfer entrypoint + */ +int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr, + unsigned short flags, char read_write, + u8 command, int size, union i2c_smbus_data *data) +{ + int i, ret = 0; + + for (i = 0; i < adap->retries; i++) { + ret = bfin_twi_do_smbus_xfer(adap, addr, flags, + read_write, command, size, data); + if (ret == 0) + break; + } + + return ret; +} + +/* * Return what the adapter supports */ static u32 bfin_twi_functionality(struct i2c_adapter *adap) @@ -667,10 +676,6 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev) goto out_error_no_irq; } - init_timer(&(iface->timeout_timer)); - iface->timeout_timer.function = bfin_twi_timeout; - iface->timeout_timer.data = (unsigned long)iface; - p_adap = &iface->adap; p_adap->nr = pdev->id; strlcpy(p_adap->name, pdev->name, sizeof(p_adap->name)); @@ -678,6 +683,8 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev) p_adap->algo_data = iface; p_adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; p_adap->dev.parent = &pdev->dev; + p_adap->timeout = 5 * HZ; + p_adap->retries = 3; rc = peripheral_request_list(pin_req[pdev->id], "i2c-bfin-twi"); if (rc) { -- cgit v0.10.2 From 5cfafc18f38aa6701f581bee875fb0b19f3b3b4b Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Mon, 22 Mar 2010 03:23:17 -0400 Subject: i2c-bfin-twi: add debug output for error status Add some debug() code to decode the error register. Signed-off-by: Michael Hennerich Signed-off-by: Mike Frysinger Signed-off-by: Ben Dooks diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c index 441134a..0279a7a 100644 --- a/drivers/i2c/busses/i2c-bfin-twi.c +++ b/drivers/i2c/busses/i2c-bfin-twi.c @@ -157,6 +157,18 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface) write_MASTER_CTL(iface, 0); SSYNC(); iface->result = -EIO; + + if (mast_stat & LOSTARB) + dev_dbg(&iface->adap.dev, "Lost Arbitration\n"); + if (mast_stat & ANAK) + dev_dbg(&iface->adap.dev, "Address Not Acknowledged\n"); + if (mast_stat & DNAK) + dev_dbg(&iface->adap.dev, "Data Not Acknowledged\n"); + if (mast_stat & BUFRDERR) + dev_dbg(&iface->adap.dev, "Buffer Read Error\n"); + if (mast_stat & BUFWRERR) + dev_dbg(&iface->adap.dev, "Buffer Write Error\n"); + /* if both err and complete int stats are set, return proper * results. */ -- cgit v0.10.2 From 5481d0753e7a78bff7550a8165b7924baa74e9cf Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Mon, 22 Mar 2010 03:23:18 -0400 Subject: i2c-bfin-twi: fix lost interrupts at high speeds i2c event of next read/write byte may trigger before current int state is cleared in the interrupt handler. So, this should be done at the beginning of interrupt handler to avoid losing new i2c events. Signed-off-by: Sonic Zhang Signed-off-by: Mike Frysinger Signed-off-by: Ben Dooks diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c index 0279a7a..ff61c4b 100644 --- a/drivers/i2c/busses/i2c-bfin-twi.c +++ b/drivers/i2c/busses/i2c-bfin-twi.c @@ -81,14 +81,15 @@ static const u16 pin_req[2][3] = { {P_TWI1_SCL, P_TWI1_SDA, 0}, }; -static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface) +static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface, + unsigned short twi_int_status) { - unsigned short twi_int_status = read_INT_STAT(iface); unsigned short mast_stat = read_MASTER_STAT(iface); if (twi_int_status & XMTSERV) { /* Transmit next data */ if (iface->writeNum > 0) { + SSYNC(); write_XMT_DATA8(iface, *(iface->transPtr++)); iface->writeNum--; } @@ -110,10 +111,6 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface) write_MASTER_CTL(iface, (read_MASTER_CTL(iface) | RSTART) & ~MDIR); } - SSYNC(); - /* Clear status */ - write_INT_STAT(iface, XMTSERV); - SSYNC(); } if (twi_int_status & RCVSERV) { if (iface->readNum > 0) { @@ -135,7 +132,6 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface) } else if (iface->manual_stop) { write_MASTER_CTL(iface, read_MASTER_CTL(iface) | STOP); - SSYNC(); } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT && iface->cur_msg + 1 < iface->msg_num) { if (iface->pmsg[iface->cur_msg + 1].flags & I2C_M_RD) @@ -144,18 +140,12 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface) else write_MASTER_CTL(iface, (read_MASTER_CTL(iface) | RSTART) & ~MDIR); - SSYNC(); } - /* Clear interrupt source */ - write_INT_STAT(iface, RCVSERV); - SSYNC(); } if (twi_int_status & MERR) { - write_INT_STAT(iface, MERR); write_INT_MASK(iface, 0); write_MASTER_STAT(iface, 0x3e); write_MASTER_CTL(iface, 0); - SSYNC(); iface->result = -EIO; if (mast_stat & LOSTARB) @@ -173,10 +163,6 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface) * results. */ if (twi_int_status & MCOMP) { - write_INT_STAT(iface, MCOMP); - write_INT_MASK(iface, 0); - write_MASTER_CTL(iface, 0); - SSYNC(); /* If it is a quick transfer, only address without data, * not an err, return 1. * If address is acknowledged return 1. @@ -189,8 +175,6 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface) return; } if (twi_int_status & MCOMP) { - write_INT_STAT(iface, MCOMP); - SSYNC(); if (iface->cur_mode == TWI_I2C_MODE_COMBINED) { if (iface->readNum == 0) { /* set the read number to 1 and ask for manual @@ -212,7 +196,6 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface) /* remove restart bit and enable master receive */ write_MASTER_CTL(iface, read_MASTER_CTL(iface) & ~RSTART); - SSYNC(); } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT && iface->cur_msg+1 < iface->msg_num) { iface->cur_msg++; @@ -231,7 +214,6 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface) write_XMT_DATA8(iface, *(iface->transPtr++)); iface->writeNum--; - SSYNC(); } } @@ -249,12 +231,10 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface) /* remove restart bit and enable master receive */ write_MASTER_CTL(iface, read_MASTER_CTL(iface) & ~RSTART); - SSYNC(); } else { iface->result = 1; write_INT_MASK(iface, 0); write_MASTER_CTL(iface, 0); - SSYNC(); } } complete(&iface->complete); @@ -265,9 +245,18 @@ static irqreturn_t bfin_twi_interrupt_entry(int irq, void *dev_id) { struct bfin_twi_iface *iface = dev_id; unsigned long flags; + unsigned short twi_int_status; spin_lock_irqsave(&iface->lock, flags); - bfin_twi_handle_interrupt(iface); + while (1) { + twi_int_status = read_INT_STAT(iface); + if (!twi_int_status) + break; + /* Clear interrupt status */ + write_INT_STAT(iface, twi_int_status); + bfin_twi_handle_interrupt(iface, twi_int_status); + SSYNC(); + } spin_unlock_irqrestore(&iface->lock, flags); return IRQ_HANDLED; } -- cgit v0.10.2 From be2f80f0a3a333c0c00b2c8a7c2d74fcd66b75a2 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Mon, 22 Mar 2010 03:23:19 -0400 Subject: i2c-bfin-twi: remove redundant retry Signed-off-by: Sonic Zhang Signed-off-by: Mike Frysinger Signed-off-by: Ben Dooks diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c index ff61c4b..dabfa80 100644 --- a/drivers/i2c/busses/i2c-bfin-twi.c +++ b/drivers/i2c/busses/i2c-bfin-twi.c @@ -358,15 +358,7 @@ static int bfin_twi_do_master_xfer(struct i2c_adapter *adap, static int bfin_twi_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { - int i, ret = 0; - - for (i = 0; i < adap->retries; i++) { - ret = bfin_twi_do_master_xfer(adap, msgs, num); - if (ret > 0) - break; - } - - return ret; + return bfin_twi_do_master_xfer(adap, msgs, num); } /* @@ -574,16 +566,8 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data) { - int i, ret = 0; - - for (i = 0; i < adap->retries; i++) { - ret = bfin_twi_do_smbus_xfer(adap, addr, flags, + return bfin_twi_do_smbus_xfer(adap, addr, flags, read_write, command, size, data); - if (ret == 0) - break; - } - - return ret; } /* -- cgit v0.10.2 From f0ac131a21ed13e8baaa9df6f0420f2c4b45e807 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Mon, 22 Mar 2010 03:23:20 -0400 Subject: i2c-bfin-twi: return completion in interrupt for smbus quick transfers A smbus quick transfer has no data after the address byte. Signed-off-by: Sonic Zhang Signed-off-by: Mike Frysinger Signed-off-by: Ben Dooks diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c index dabfa80..fb26e5c 100644 --- a/drivers/i2c/busses/i2c-bfin-twi.c +++ b/drivers/i2c/busses/i2c-bfin-twi.c @@ -159,18 +159,14 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface, if (mast_stat & BUFWRERR) dev_dbg(&iface->adap.dev, "Buffer Write Error\n"); - /* if both err and complete int stats are set, return proper - * results. + /* If it is a quick transfer, only address without data, + * not an err, return 1. */ - if (twi_int_status & MCOMP) { - /* If it is a quick transfer, only address without data, - * not an err, return 1. - * If address is acknowledged return 1. - */ - if ((iface->writeNum == 0 && (mast_stat & BUFRDERR)) - || !(mast_stat & ANAK)) - iface->result = 1; - } + if (iface->cur_mode == TWI_I2C_MODE_STANDARD && + iface->transPtr == NULL && + (twi_int_status & MCOMP) && (mast_stat & DNAK)) + iface->result = 1; + complete(&iface->complete); return; } -- cgit v0.10.2 From f38e66e0077659e5d2ca3858fdb26fc9b1765b9f Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Tue, 11 May 2010 11:35:04 -0700 Subject: omap: i2c: Add i2c support on omap4 platform This patch is rebased version of earlier post to add I2C driver support to OMAP4 platform. On OMAP4, all I2C register address offsets are changed from OMAP1/2/3 I2C. In order to not have #ifdef's at various places in code, as well as to support multi-OMAP build, an array is created to hold the register addresses with it's offset. This patch was submitted, reviewed and acked on mailing list already. For more details refer below link http://www.mail-archive.com/linux-i2c@vger.kernel.org/msg02281.html This updated verion has a depedancy on "Add support for 16-bit registers" posted on linux-omap. Below is the patch-works link for the same http://patchwork.kernel.org/patch/72295/ Signed-off-by: Syed Rafiuddin Signed-off-by: Santosh Shilimkar Acked-by: Kevin Hilman Reviewed-by: Paul Walmsley Cc: Cory Maccarrone Signed-off-by: Tony Lindgren Signed-off-by: Ben Dooks diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 389ac60..46111ff 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -45,29 +45,37 @@ /* I2C controller revisions present on specific hardware */ #define OMAP_I2C_REV_ON_2430 0x36 #define OMAP_I2C_REV_ON_3430 0x3C +#define OMAP_I2C_REV_ON_4430 0x40 /* timeout waiting for the controller to respond */ #define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000)) -#define OMAP_I2C_REV_REG 0x00 -#define OMAP_I2C_IE_REG 0x01 -#define OMAP_I2C_STAT_REG 0x02 -#define OMAP_I2C_IV_REG 0x03 /* For OMAP3 I2C_IV has changed to I2C_WE (wakeup enable) */ -#define OMAP_I2C_WE_REG 0x03 -#define OMAP_I2C_SYSS_REG 0x04 -#define OMAP_I2C_BUF_REG 0x05 -#define OMAP_I2C_CNT_REG 0x06 -#define OMAP_I2C_DATA_REG 0x07 -#define OMAP_I2C_SYSC_REG 0x08 -#define OMAP_I2C_CON_REG 0x09 -#define OMAP_I2C_OA_REG 0x0a -#define OMAP_I2C_SA_REG 0x0b -#define OMAP_I2C_PSC_REG 0x0c -#define OMAP_I2C_SCLL_REG 0x0d -#define OMAP_I2C_SCLH_REG 0x0e -#define OMAP_I2C_SYSTEST_REG 0x0f -#define OMAP_I2C_BUFSTAT_REG 0x10 +enum { + OMAP_I2C_REV_REG = 0, + OMAP_I2C_IE_REG, + OMAP_I2C_STAT_REG, + OMAP_I2C_IV_REG, + OMAP_I2C_WE_REG, + OMAP_I2C_SYSS_REG, + OMAP_I2C_BUF_REG, + OMAP_I2C_CNT_REG, + OMAP_I2C_DATA_REG, + OMAP_I2C_SYSC_REG, + OMAP_I2C_CON_REG, + OMAP_I2C_OA_REG, + OMAP_I2C_SA_REG, + OMAP_I2C_PSC_REG, + OMAP_I2C_SCLL_REG, + OMAP_I2C_SCLH_REG, + OMAP_I2C_SYSTEST_REG, + OMAP_I2C_BUFSTAT_REG, + OMAP_I2C_REVNB_LO, + OMAP_I2C_REVNB_HI, + OMAP_I2C_IRQSTATUS_RAW, + OMAP_I2C_IRQENABLE_SET, + OMAP_I2C_IRQENABLE_CLR, +}; /* I2C Interrupt Enable Register (OMAP_I2C_IE): */ #define OMAP_I2C_IE_XDR (1 << 14) /* TX Buffer drain int enable */ @@ -170,6 +178,7 @@ struct omap_i2c_dev { u32 speed; /* Speed of bus in Khz */ u16 cmd_err; u8 *buf; + u8 *regs; size_t buf_len; struct i2c_adapter adapter; u8 fifo_size; /* use as flag and value @@ -188,15 +197,64 @@ struct omap_i2c_dev { u16 westate; }; +const static u8 reg_map[] = { + [OMAP_I2C_REV_REG] = 0x00, + [OMAP_I2C_IE_REG] = 0x01, + [OMAP_I2C_STAT_REG] = 0x02, + [OMAP_I2C_IV_REG] = 0x03, + [OMAP_I2C_WE_REG] = 0x03, + [OMAP_I2C_SYSS_REG] = 0x04, + [OMAP_I2C_BUF_REG] = 0x05, + [OMAP_I2C_CNT_REG] = 0x06, + [OMAP_I2C_DATA_REG] = 0x07, + [OMAP_I2C_SYSC_REG] = 0x08, + [OMAP_I2C_CON_REG] = 0x09, + [OMAP_I2C_OA_REG] = 0x0a, + [OMAP_I2C_SA_REG] = 0x0b, + [OMAP_I2C_PSC_REG] = 0x0c, + [OMAP_I2C_SCLL_REG] = 0x0d, + [OMAP_I2C_SCLH_REG] = 0x0e, + [OMAP_I2C_SYSTEST_REG] = 0x0f, + [OMAP_I2C_BUFSTAT_REG] = 0x10, +}; + +const static u8 omap4_reg_map[] = { + [OMAP_I2C_REV_REG] = 0x04, + [OMAP_I2C_IE_REG] = 0x2c, + [OMAP_I2C_STAT_REG] = 0x28, + [OMAP_I2C_IV_REG] = 0x34, + [OMAP_I2C_WE_REG] = 0x34, + [OMAP_I2C_SYSS_REG] = 0x90, + [OMAP_I2C_BUF_REG] = 0x94, + [OMAP_I2C_CNT_REG] = 0x98, + [OMAP_I2C_DATA_REG] = 0x9c, + [OMAP_I2C_SYSC_REG] = 0x20, + [OMAP_I2C_CON_REG] = 0xa4, + [OMAP_I2C_OA_REG] = 0xa8, + [OMAP_I2C_SA_REG] = 0xac, + [OMAP_I2C_PSC_REG] = 0xb0, + [OMAP_I2C_SCLL_REG] = 0xb4, + [OMAP_I2C_SCLH_REG] = 0xb8, + [OMAP_I2C_SYSTEST_REG] = 0xbC, + [OMAP_I2C_BUFSTAT_REG] = 0xc0, + [OMAP_I2C_REVNB_LO] = 0x00, + [OMAP_I2C_REVNB_HI] = 0x04, + [OMAP_I2C_IRQSTATUS_RAW] = 0x24, + [OMAP_I2C_IRQENABLE_SET] = 0x2c, + [OMAP_I2C_IRQENABLE_CLR] = 0x30, +}; + static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev, int reg, u16 val) { - __raw_writew(val, i2c_dev->base + (reg << i2c_dev->reg_shift)); + __raw_writew(val, i2c_dev->base + + (i2c_dev->regs[reg] << i2c_dev->reg_shift)); } static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg) { - return __raw_readw(i2c_dev->base + (reg << i2c_dev->reg_shift)); + return __raw_readw(i2c_dev->base + + (i2c_dev->regs[reg] << i2c_dev->reg_shift)); } static int __init omap_i2c_get_clocks(struct omap_i2c_dev *dev) @@ -265,7 +323,11 @@ static void omap_i2c_idle(struct omap_i2c_dev *dev) WARN_ON(dev->idle); dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG); - omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0); + if (dev->rev >= OMAP_I2C_REV_ON_4430) + omap_i2c_write_reg(dev, OMAP_I2C_IRQENABLE_CLR, 1); + else + omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0); + if (dev->rev < OMAP_I2C_REV_2) { iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */ } else { @@ -330,7 +392,9 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) * REVISIT: Some wkup sources might not be needed. */ dev->westate = OMAP_I2C_WE_ALL; - omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate); + if (dev->rev < OMAP_I2C_REV_ON_4430) + omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, + dev->westate); } } omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); @@ -357,7 +421,7 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) psc = fclk_rate / 12000000; } - if (cpu_is_omap2430() || cpu_is_omap34xx()) { + if (!(cpu_class_is_omap1() || cpu_is_omap2420())) { /* * HSI2C controller internal clk rate should be 19.2 Mhz for @@ -747,9 +811,12 @@ complete: if (dev->buf_len) { *dev->buf++ = w; dev->buf_len--; - /* Data reg from 2430 is 8 bit wide */ - if (!cpu_is_omap2430() && - !cpu_is_omap34xx()) { + /* + * Data reg in 2430, omap3 and + * omap4 is 8 bit wide + */ + if (cpu_class_is_omap1() || + cpu_is_omap2420()) { if (dev->buf_len) { *dev->buf++ = w >> 8; dev->buf_len--; @@ -787,9 +854,12 @@ complete: if (dev->buf_len) { w = *dev->buf++; dev->buf_len--; - /* Data reg from 2430 is 8 bit wide */ - if (!cpu_is_omap2430() && - !cpu_is_omap34xx()) { + /* + * Data reg in 2430, omap3 and + * omap4 is 8 bit wide + */ + if (cpu_class_is_omap1() || + cpu_is_omap2420()) { if (dev->buf_len) { w |= *dev->buf++ << 8; dev->buf_len--; @@ -905,17 +975,24 @@ omap_i2c_probe(struct platform_device *pdev) if (cpu_is_omap7xx()) dev->reg_shift = 1; + else if (cpu_is_omap44xx()) + dev->reg_shift = 0; else dev->reg_shift = 2; if ((r = omap_i2c_get_clocks(dev)) != 0) goto err_iounmap; + if (cpu_is_omap44xx()) + dev->regs = (u8 *) omap4_reg_map; + else + dev->regs = (u8 *) reg_map; + omap_i2c_unidle(dev); dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff; - if (cpu_is_omap2430() || cpu_is_omap34xx()) { + if (!(cpu_class_is_omap1() || cpu_is_omap2420())) { u16 s; /* Set up the fifo size - Get total size */ @@ -927,8 +1004,13 @@ omap_i2c_probe(struct platform_device *pdev) * size. This is to ensure that we can handle the status on int * call back latencies. */ - dev->fifo_size = (dev->fifo_size / 2); - dev->b_hw = 1; /* Enable hardware fixes */ + if (dev->rev >= OMAP_I2C_REV_ON_4430) { + dev->fifo_size = 0; + dev->b_hw = 0; /* Disable hardware fixes */ + } else { + dev->fifo_size = (dev->fifo_size / 2); + dev->b_hw = 1; /* Enable hardware fixes */ + } } /* reset ASAP, clearing any IRQs */ -- cgit v0.10.2 From 20c9d2c4ab8243a1c311248232954b2c1da3ba75 Mon Sep 17 00:00:00 2001 From: Kalle Jokiniemi Date: Tue, 11 May 2010 11:35:08 -0700 Subject: i2c-omap: add mpu wake up latency constraint in i2c While waiting for completion of the i2c transfer, the MPU could hit OFF mode and cause several msecs of delay that made i2c transfers fail more often. The extra delays and subsequent re-trys cause i2c clocks to be active more often. This has also an negative effect on power consumption. Created a mechanism for passing and using the constraint setting function in driver code. The used mpu wake up latency constraints are now set individually per bus, and they are calculated based on clock rate and fifo size. Thanks to Jarkko Nikula, Moiz Sonasath, Paul Walmsley, and Nishanth Menon for tuning out the details of this patch. Updates by Kevin as requested by Tony: - Remove omap_set_i2c_constraint_func() in favor of conditionally adding the flag in omap_i2c_add_bus() in order to keep all the OMAP conditional checking in a single location. - Update set_mpu_wkup_lat prototypes to match OMAP PM layer so OMAP PM function can be used directly in pdata. Cc: Moiz Sonasath Cc: Jarkko Nikula Cc: Paul Walmsley Cc: Nishanth Menon Signed-off-by: Kalle Jokiniemi Signed-off-by: Kevin Hilman Signed-off-by: Tony Lindgren Signed-off-by: Ben Dooks diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c index 624e262..f044b59 100644 --- a/arch/arm/plat-omap/i2c.c +++ b/arch/arm/plat-omap/i2c.c @@ -26,9 +26,12 @@ #include #include #include +#include + #include #include #include +#include #define OMAP_I2C_SIZE 0x3f #define OMAP1_I2C_BASE 0xfffb3800 @@ -70,14 +73,14 @@ static struct resource i2c_resources[][2] = { }, \ } -static u32 i2c_rate[ARRAY_SIZE(i2c_resources)]; +static struct omap_i2c_bus_platform_data i2c_pdata[ARRAY_SIZE(i2c_resources)]; static struct platform_device omap_i2c_devices[] = { - I2C_DEV_BUILDER(1, i2c_resources[0], &i2c_rate[0]), + I2C_DEV_BUILDER(1, i2c_resources[0], &i2c_pdata[0]), #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) - I2C_DEV_BUILDER(2, i2c_resources[1], &i2c_rate[1]), + I2C_DEV_BUILDER(2, i2c_resources[1], &i2c_pdata[1]), #endif #if defined(CONFIG_ARCH_OMAP3) - I2C_DEV_BUILDER(3, i2c_resources[2], &i2c_rate[2]), + I2C_DEV_BUILDER(3, i2c_resources[2], &i2c_pdata[2]), #endif }; @@ -100,10 +103,12 @@ static int __init omap_i2c_nr_ports(void) static int __init omap_i2c_add_bus(int bus_id) { struct platform_device *pdev; + struct omap_i2c_bus_platform_data *pd; struct resource *res; resource_size_t base, irq; pdev = &omap_i2c_devices[bus_id - 1]; + pd = pdev->dev.platform_data; if (bus_id == 1) { res = pdev->resource; if (cpu_class_is_omap1()) { @@ -123,6 +128,15 @@ static int __init omap_i2c_add_bus(int bus_id) if (cpu_class_is_omap2()) omap2_i2c_mux_pins(bus_id); + /* + * When waiting for completion of a i2c transfer, we need to + * set a wake up latency constraint for the MPU. This is to + * ensure quick enough wakeup from idle, when transfer + * completes. + */ + if (cpu_is_omap34xx()) + pd->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat; + return platform_device_register(pdev); } @@ -146,8 +160,8 @@ static int __init omap_i2c_bus_setup(char *str) get_options(str, 3, ints); if (ints[0] < 2 || ints[1] < 1 || ints[1] > ports) return 0; - i2c_rate[ints[1] - 1] = ints[2]; - i2c_rate[ints[1] - 1] |= OMAP_I2C_CMDLINE_SETUP; + i2c_pdata[ints[1] - 1].clkrate = ints[2]; + i2c_pdata[ints[1] - 1].clkrate |= OMAP_I2C_CMDLINE_SETUP; return 1; } @@ -161,9 +175,9 @@ static int __init omap_register_i2c_bus_cmdline(void) { int i, err = 0; - for (i = 0; i < ARRAY_SIZE(i2c_rate); i++) - if (i2c_rate[i] & OMAP_I2C_CMDLINE_SETUP) { - i2c_rate[i] &= ~OMAP_I2C_CMDLINE_SETUP; + for (i = 0; i < ARRAY_SIZE(i2c_pdata); i++) + if (i2c_pdata[i].clkrate & OMAP_I2C_CMDLINE_SETUP) { + i2c_pdata[i].clkrate &= ~OMAP_I2C_CMDLINE_SETUP; err = omap_i2c_add_bus(i + 1); if (err) goto out; @@ -197,9 +211,10 @@ int __init omap_register_i2c_bus(int bus_id, u32 clkrate, return err; } - if (!i2c_rate[bus_id - 1]) - i2c_rate[bus_id - 1] = clkrate; - i2c_rate[bus_id - 1] &= ~OMAP_I2C_CMDLINE_SETUP; + if (!i2c_pdata[bus_id - 1].clkrate) + i2c_pdata[bus_id - 1].clkrate = clkrate; + + i2c_pdata[bus_id - 1].clkrate &= ~OMAP_I2C_CMDLINE_SETUP; return omap_i2c_add_bus(bus_id); } diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 46111ff..42c0b91 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -38,6 +38,7 @@ #include #include #include +#include /* I2C controller revisions */ #define OMAP_I2C_REV_2 0x20 @@ -175,6 +176,9 @@ struct omap_i2c_dev { struct clk *fclk; /* Functional clock */ struct completion cmd_complete; struct resource *ioarea; + u32 latency; /* maximum mpu wkup latency */ + void (*set_mpu_wkup_lat)(struct device *dev, + long latency); u32 speed; /* Speed of bus in Khz */ u16 cmd_err; u8 *buf; @@ -603,8 +607,12 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, * REVISIT: We should abort the transfer on signals, but the bus goes * into arbitration and we're currently unable to recover from it. */ + if (dev->set_mpu_wkup_lat != NULL) + dev->set_mpu_wkup_lat(dev->dev, dev->latency); r = wait_for_completion_timeout(&dev->cmd_complete, OMAP_I2C_TIMEOUT); + if (dev->set_mpu_wkup_lat != NULL) + dev->set_mpu_wkup_lat(dev->dev, -1); dev->buf_len = 0; if (r < 0) return r; @@ -927,6 +935,7 @@ omap_i2c_probe(struct platform_device *pdev) struct omap_i2c_dev *dev; struct i2c_adapter *adap; struct resource *mem, *irq, *ioarea; + struct omap_i2c_bus_platform_data *pdata = pdev->dev.platform_data; irq_handler_t isr; int r; u32 speed = 0; @@ -956,10 +965,13 @@ omap_i2c_probe(struct platform_device *pdev) goto err_release_region; } - if (pdev->dev.platform_data != NULL) - speed = *(u32 *)pdev->dev.platform_data; - else - speed = 100; /* Defualt speed */ + if (pdata != NULL) { + speed = pdata->clkrate; + dev->set_mpu_wkup_lat = pdata->set_mpu_wkup_lat; + } else { + speed = 100; /* Default speed */ + dev->set_mpu_wkup_lat = NULL; + } dev->speed = speed; dev->idle = 1; @@ -1011,6 +1023,10 @@ omap_i2c_probe(struct platform_device *pdev) dev->fifo_size = (dev->fifo_size / 2); dev->b_hw = 1; /* Enable hardware fixes */ } + /* calculate wakeup latency constraint for MPU */ + if (dev->set_mpu_wkup_lat != NULL) + dev->latency = (1000000 * dev->fifo_size) / + (1000 * speed / 8); } /* reset ASAP, clearing any IRQs */ diff --git a/include/linux/i2c-omap.h b/include/linux/i2c-omap.h new file mode 100644 index 0000000..78ebf50 --- /dev/null +++ b/include/linux/i2c-omap.h @@ -0,0 +1,9 @@ +#ifndef __I2C_OMAP_H__ +#define __I2C_OMAP_H__ + +struct omap_i2c_bus_platform_data { + u32 clkrate; + void (*set_mpu_wkup_lat)(struct device *dev, long set); +}; + +#endif -- cgit v0.10.2 From b32dd41ed645c22ac3ce4e25bcbd7eee30297292 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 20 May 2010 11:36:43 -0700 Subject: omap: Fix i2c platform init code for omap4 Add separate omap_i2c_add_bus functions for mach-omap1 and mach-omap2. Make the mach-omap2 init set the interrupt dynamically to support. This is needed to add support for omap4 in a way that works with multi-omap builds. This will eventually get fixed in a generic way with the omap hwmods. Signed-off-by: Tony Lindgren diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c index f044b59..78d1cea 100644 --- a/arch/arm/plat-omap/i2c.c +++ b/arch/arm/plat-omap/i2c.c @@ -100,33 +100,44 @@ static int __init omap_i2c_nr_ports(void) return ports; } -static int __init omap_i2c_add_bus(int bus_id) +/* Shared between omap2 and 3 */ +static resource_size_t omap2_i2c_irq[3] __initdata = { + INT_24XX_I2C1_IRQ, + INT_24XX_I2C2_IRQ, + INT_34XX_I2C3_IRQ, +}; + +static inline int omap1_i2c_add_bus(struct platform_device *pdev, int bus_id) { - struct platform_device *pdev; struct omap_i2c_bus_platform_data *pd; struct resource *res; - resource_size_t base, irq; - pdev = &omap_i2c_devices[bus_id - 1]; pd = pdev->dev.platform_data; + res = pdev->resource; + res[0].start = OMAP1_I2C_BASE; + res[0].end = res[0].start + OMAP_I2C_SIZE; + res[1].start = INT_I2C; + omap1_i2c_mux_pins(bus_id); + + return platform_device_register(pdev); +} + +static inline int omap2_i2c_add_bus(struct platform_device *pdev, int bus_id) +{ + struct resource *res; + resource_size_t *irq; + + res = pdev->resource; + + irq = omap2_i2c_irq; + if (bus_id == 1) { - res = pdev->resource; - if (cpu_class_is_omap1()) { - base = OMAP1_I2C_BASE; - irq = INT_I2C; - } else { - base = OMAP2_I2C_BASE1; - irq = INT_24XX_I2C1_IRQ; - } - res[0].start = base; - res[0].end = base + OMAP_I2C_SIZE; - res[1].start = irq; + res[0].start = OMAP2_I2C_BASE1; + res[0].end = res[0].start + OMAP_I2C_SIZE; } - if (cpu_class_is_omap1()) - omap1_i2c_mux_pins(bus_id); - if (cpu_class_is_omap2()) - omap2_i2c_mux_pins(bus_id); + res[1].start = irq[bus_id - 1]; + omap2_i2c_mux_pins(bus_id); /* * When waiting for completion of a i2c transfer, we need to @@ -134,12 +145,28 @@ static int __init omap_i2c_add_bus(int bus_id) * ensure quick enough wakeup from idle, when transfer * completes. */ - if (cpu_is_omap34xx()) + if (cpu_is_omap34xx()) { + struct omap_i2c_bus_platform_data *pd; + + pd = pdev->dev.platform_data; pd->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat; + } return platform_device_register(pdev); } +static int __init omap_i2c_add_bus(int bus_id) +{ + struct platform_device *pdev; + + pdev = &omap_i2c_devices[bus_id - 1]; + + if (cpu_class_is_omap1()) + return omap1_i2c_add_bus(pdev, bus_id); + else + return omap2_i2c_add_bus(pdev, bus_id); +} + /** * omap_i2c_bus_setup - Process command line options for the I2C bus speed * @str: String of options -- cgit v0.10.2 From 6daa642d9b8ec762b3c5641cd5e5fa855a5405bf Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 20 May 2010 11:36:43 -0700 Subject: omap4: Add support for i2c init Add support for i2c init for omap4. This patch is based on and earlier patch by Santosh Shilimkar . Signed-off-by: Tony Lindgren diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c index 78d1cea..eec2b49 100644 --- a/arch/arm/plat-omap/i2c.c +++ b/arch/arm/plat-omap/i2c.c @@ -38,6 +38,7 @@ #define OMAP2_I2C_BASE1 0x48070000 #define OMAP2_I2C_BASE2 0x48072000 #define OMAP2_I2C_BASE3 0x48060000 +#define OMAP4_I2C_BASE4 0x48350000 static const char name[] = "i2c_omap"; @@ -54,11 +55,14 @@ static const char name[] = "i2c_omap"; static struct resource i2c_resources[][2] = { { I2C_RESOURCE_BUILDER(0, 0) }, -#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) - { I2C_RESOURCE_BUILDER(OMAP2_I2C_BASE2, INT_24XX_I2C2_IRQ) }, +#if defined(CONFIG_ARCH_OMAP2PLUS) + { I2C_RESOURCE_BUILDER(OMAP2_I2C_BASE2, 0) }, #endif -#if defined(CONFIG_ARCH_OMAP3) - { I2C_RESOURCE_BUILDER(OMAP2_I2C_BASE3, INT_34XX_I2C3_IRQ) }, +#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) + { I2C_RESOURCE_BUILDER(OMAP2_I2C_BASE3, 0) }, +#endif +#if defined(CONFIG_ARCH_OMAP4) + { I2C_RESOURCE_BUILDER(OMAP4_I2C_BASE4, 0) }, #endif }; @@ -76,12 +80,15 @@ static struct resource i2c_resources[][2] = { static struct omap_i2c_bus_platform_data i2c_pdata[ARRAY_SIZE(i2c_resources)]; static struct platform_device omap_i2c_devices[] = { I2C_DEV_BUILDER(1, i2c_resources[0], &i2c_pdata[0]), -#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) +#if defined(CONFIG_ARCH_OMAP2PLUS) I2C_DEV_BUILDER(2, i2c_resources[1], &i2c_pdata[1]), #endif -#if defined(CONFIG_ARCH_OMAP3) +#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) I2C_DEV_BUILDER(3, i2c_resources[2], &i2c_pdata[2]), #endif +#if defined(CONFIG_ARCH_OMAP4) + I2C_DEV_BUILDER(4, i2c_resources[3], &i2c_pdata[3]), +#endif }; #define OMAP_I2C_CMDLINE_SETUP (BIT(31)) @@ -96,6 +103,8 @@ static int __init omap_i2c_nr_ports(void) ports = 2; else if (cpu_is_omap34xx()) ports = 3; + else if (cpu_is_omap44xx()) + ports = 4; return ports; } @@ -107,6 +116,13 @@ static resource_size_t omap2_i2c_irq[3] __initdata = { INT_34XX_I2C3_IRQ, }; +static resource_size_t omap4_i2c_irq[4] __initdata = { + OMAP44XX_IRQ_I2C1, + OMAP44XX_IRQ_I2C2, + OMAP44XX_IRQ_I2C3, + OMAP44XX_IRQ_I2C4, +}; + static inline int omap1_i2c_add_bus(struct platform_device *pdev, int bus_id) { struct omap_i2c_bus_platform_data *pd; @@ -129,7 +145,10 @@ static inline int omap2_i2c_add_bus(struct platform_device *pdev, int bus_id) res = pdev->resource; - irq = omap2_i2c_irq; + if (!cpu_is_omap44xx()) + irq = omap2_i2c_irq; + else + irq = omap4_i2c_irq; if (bus_id == 1) { res[0].start = OMAP2_I2C_BASE1; -- cgit v0.10.2