From 9e6f8ed7c3a303d37eb119847dd3029701e37e28 Mon Sep 17 00:00:00 2001 From: Balaji Rao Date: Wed, 14 Jan 2009 13:02:00 +0100 Subject: [PATCH 001/111] mfd: Remove non exported references from pcf50633 Remove references to set_irq_type and handle_level_irq which are not exported to modules Signed-off-by: Balaji Rao Signed-off-by: Samuel Ortiz --- drivers/mfd/pcf50633-core.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c index 24508e28e3fb..ea9488e7ad6d 100644 --- a/drivers/mfd/pcf50633-core.c +++ b/drivers/mfd/pcf50633-core.c @@ -626,7 +626,6 @@ static int __devinit pcf50633_probe(struct i2c_client *client, } if (client->irq) { - set_irq_handler(client->irq, handle_level_irq); ret = request_irq(client->irq, pcf50633_irq, IRQF_TRIGGER_LOW, "pcf50633", pcf); From dedb0d48a9d4d57086526b94a4b64da789a646e4 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 9 Jan 2009 21:02:37 +0200 Subject: [PATCH 002/111] UBIFS: do not commit twice VFS calls '->sync_fs()' twice - first time with @wait = 0, second time with @wait = 1. As a result, we may commit and synchronize write-buffers twice. Avoid doing this by returning immediatelly if @wait = 0. Signed-off-by: Artem Bityutskiy --- fs/ubifs/super.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 89556ee72518..a7fc97f4d9de 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -432,18 +432,19 @@ static int ubifs_sync_fs(struct super_block *sb, int wait) int i, err; struct ubifs_info *c = sb->s_fs_info; struct writeback_control wbc = { - .sync_mode = wait ? WB_SYNC_ALL : WB_SYNC_NONE, + .sync_mode = WB_SYNC_ALL, .range_start = 0, .range_end = LLONG_MAX, .nr_to_write = LONG_MAX, }; /* - * Note by akpm about WB_SYNC_NONE used above: zero @wait is just an - * advisory thing to help the file system shove lots of data into the - * queues. If some gets missed then it'll be picked up on the second + * Zero @wait is just an advisory thing to help the file system shove + * lots of data into the queues, and there will be the second * '->sync_fs()' call, with non-zero @wait. */ + if (!wait) + return 0; if (sb->s_flags & MS_RDONLY) return 0; From e8b815663b1bfd9c255af5176604ec0eafdf6ed7 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Thu, 15 Jan 2009 17:43:23 +0200 Subject: [PATCH 003/111] UBIFS: constify operations Mark super, file, and inode operation structcutes with 'const'. Signed-off-by: Artem Bityutskiy --- fs/ubifs/dir.c | 4 ++-- fs/ubifs/file.c | 8 ++++---- fs/ubifs/super.c | 2 +- fs/ubifs/ubifs.h | 14 +++++++------- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index f448ab1f9c38..d29b771cce45 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c @@ -1199,7 +1199,7 @@ int ubifs_getattr(struct vfsmount *mnt, struct dentry *dentry, return 0; } -struct inode_operations ubifs_dir_inode_operations = { +const struct inode_operations ubifs_dir_inode_operations = { .lookup = ubifs_lookup, .create = ubifs_create, .link = ubifs_link, @@ -1219,7 +1219,7 @@ struct inode_operations ubifs_dir_inode_operations = { #endif }; -struct file_operations ubifs_dir_operations = { +const struct file_operations ubifs_dir_operations = { .llseek = ubifs_dir_llseek, .release = ubifs_dir_release, .read = generic_read_dir, diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index bf37374567fa..17443d97e6f1 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c @@ -1541,7 +1541,7 @@ static int ubifs_file_mmap(struct file *file, struct vm_area_struct *vma) return 0; } -struct address_space_operations ubifs_file_address_operations = { +const struct address_space_operations ubifs_file_address_operations = { .readpage = ubifs_readpage, .writepage = ubifs_writepage, .write_begin = ubifs_write_begin, @@ -1551,7 +1551,7 @@ struct address_space_operations ubifs_file_address_operations = { .releasepage = ubifs_releasepage, }; -struct inode_operations ubifs_file_inode_operations = { +const struct inode_operations ubifs_file_inode_operations = { .setattr = ubifs_setattr, .getattr = ubifs_getattr, #ifdef CONFIG_UBIFS_FS_XATTR @@ -1562,14 +1562,14 @@ struct inode_operations ubifs_file_inode_operations = { #endif }; -struct inode_operations ubifs_symlink_inode_operations = { +const struct inode_operations ubifs_symlink_inode_operations = { .readlink = generic_readlink, .follow_link = ubifs_follow_link, .setattr = ubifs_setattr, .getattr = ubifs_getattr, }; -struct file_operations ubifs_file_operations = { +const struct file_operations ubifs_file_operations = { .llseek = generic_file_llseek, .read = do_sync_read, .write = do_sync_write, diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index a7fc97f4d9de..53811e567a69 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1778,7 +1778,7 @@ static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data) return 0; } -struct super_operations ubifs_super_operations = { +const struct super_operations ubifs_super_operations = { .alloc_inode = ubifs_alloc_inode, .destroy_inode = ubifs_destroy_inode, .put_super = ubifs_put_super, diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index fc2a4cc66d03..0881897a4208 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -1405,13 +1405,13 @@ extern struct list_head ubifs_infos; extern spinlock_t ubifs_infos_lock; extern atomic_long_t ubifs_clean_zn_cnt; extern struct kmem_cache *ubifs_inode_slab; -extern struct super_operations ubifs_super_operations; -extern struct address_space_operations ubifs_file_address_operations; -extern struct file_operations ubifs_file_operations; -extern struct inode_operations ubifs_file_inode_operations; -extern struct file_operations ubifs_dir_operations; -extern struct inode_operations ubifs_dir_inode_operations; -extern struct inode_operations ubifs_symlink_inode_operations; +extern const struct super_operations ubifs_super_operations; +extern const struct address_space_operations ubifs_file_address_operations; +extern const struct file_operations ubifs_file_operations; +extern const struct inode_operations ubifs_file_inode_operations; +extern const struct file_operations ubifs_dir_operations; +extern const struct inode_operations ubifs_dir_inode_operations; +extern const struct inode_operations ubifs_symlink_inode_operations; extern struct backing_dev_info ubifs_backing_dev_info; extern struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT]; From a50412e3f8ce95d7ed558370d7dde5171fd04283 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Tue, 6 Jan 2009 19:54:02 +0200 Subject: [PATCH 004/111] UBIFS: do not treat all data as short term UBIFS wrongly tells UBI that all data is short term. Use proper hints instead. Thanks to Xiaochuan-Xu for noticing this. Signed-off-by: Artem Bityutskiy --- fs/ubifs/journal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c index 9b7c54e0cd2a..a11ca0958a23 100644 --- a/fs/ubifs/journal.c +++ b/fs/ubifs/journal.c @@ -208,7 +208,7 @@ static int reserve_space(struct ubifs_info *c, int jhead, int len) offs = 0; out: - err = ubifs_wbuf_seek_nolock(wbuf, lnum, offs, UBI_SHORTTERM); + err = ubifs_wbuf_seek_nolock(wbuf, lnum, offs, wbuf->dtype); if (err) goto out_unlock; From 7078202e55b565582fcbd831a8dd3069bdc72610 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 19 Jan 2009 19:57:27 +0200 Subject: [PATCH 005/111] UBIFS: document dark_wm and dead_wm better Just add more commentaries. Also some commentary fixes for lprops flags. Signed-off-by: Artem Bityutskiy --- fs/ubifs/gc.c | 20 ++++++++++++++++++++ fs/ubifs/super.c | 11 ++--------- fs/ubifs/ubifs.h | 4 ++-- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c index 9832f9abe28e..b2e5f1133377 100644 --- a/fs/ubifs/gc.c +++ b/fs/ubifs/gc.c @@ -31,6 +31,26 @@ * to be reused. Garbage collection will cause the number of dirty index nodes * to grow, however sufficient space is reserved for the index to ensure the * commit will never run out of space. + * + * Notes about dead watermark. At current UBIFS implementation we assume that + * LEBs which have less than @c->dead_wm bytes of free + dirty space are full + * and not worth garbage-collecting. The dead watermark is one min. I/O unit + * size, or min. UBIFS node size, depending on what is greater. Indeed, UBIFS + * Garbage Collector has to synchronize the GC head's write buffer before + * returning, so this is about wasting one min. I/O unit. However, UBIFS GC can + * actually reclaim even very small pieces of dirty space by garbage collecting + * enough dirty LEBs, but we do not bother doing this at this implementation. + * + * Notes about dark watermark. The results of GC work depends on how big are + * the UBIFS nodes GC deals with. Large nodes make GC waste more space. Indeed, + * if GC move data from LEB A to LEB B and nodes in LEB A are large, GC would + * have to waste large pieces of free space at the end of LEB B, because nodes + * from LEB A would not fit. And the worst situation is when all nodes are of + * maximum size. So dark watermark is the amount of free + dirty space in LEB + * which are guaranteed to be reclaimable. If LEB has less space, the GC migh + * be unable to reclaim it. So, LEBs with free + dirty greater than dark + * watermark are "good" LEBs from GC's point of few. The other LEBs are not so + * good, and GC takes extra care when moving them. */ #include diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 53811e567a69..da99da098efd 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -573,15 +573,8 @@ static int init_constants_early(struct ubifs_info *c) c->ranges[UBIFS_IDX_NODE].max_len = INT_MAX; /* - * Initialize dead and dark LEB space watermarks. - * - * Dead space is the space which cannot be used. Its watermark is - * equivalent to min. I/O unit or minimum node size if it is greater - * then min. I/O unit. - * - * Dark space is the space which might be used, or might not, depending - * on which node should be written to the LEB. Its watermark is - * equivalent to maximum UBIFS node size. + * Initialize dead and dark LEB space watermarks. See gc.c for comments + * about these values. */ c->dead_wm = ALIGN(MIN_WRITE_SZ, c->min_io_size); c->dark_wm = ALIGN(UBIFS_MAX_NODE_SZ, c->min_io_size); diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 0881897a4208..2e78d6ac007e 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -426,9 +426,9 @@ struct ubifs_unclean_leb { * LEB properties flags. * * LPROPS_UNCAT: not categorized - * LPROPS_DIRTY: dirty > 0, not index + * LPROPS_DIRTY: dirty > free, dirty >= @c->dead_wm, not index * LPROPS_DIRTY_IDX: dirty + free > @c->min_idx_node_sze and index - * LPROPS_FREE: free > 0, not empty, not index + * LPROPS_FREE: free > 0, dirty < @c->dead_wm, not empty, not index * LPROPS_HEAP_CNT: number of heaps used for storing categorized LEBs * LPROPS_EMPTY: LEB is empty, not taken * LPROPS_FREEABLE: free + dirty == leb_size, not index, not taken From 82c1593cad3dfc97661764c8bc62aa1a416e9ea8 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Tue, 20 Jan 2009 16:46:02 +0200 Subject: [PATCH 006/111] UBIFS: simplify locking This patch simplifies lock_[23]_inodes functions. We do not have to care about locking order, because UBIFS does this for @i_mutex and this is enough. Thanks to Al Viro for suggesting this. Signed-off-by: Artem Bityutskiy --- fs/ubifs/dir.c | 92 ++++++++++++++++++++------------------------------ 1 file changed, 36 insertions(+), 56 deletions(-) diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index d29b771cce45..f55d523c52bb 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c @@ -482,30 +482,29 @@ static int ubifs_dir_release(struct inode *dir, struct file *file) } /** - * lock_2_inodes - lock two UBIFS inodes. + * lock_2_inodes - a wrapper for locking two UBIFS inodes. * @inode1: first inode * @inode2: second inode + * + * We do not implement any tricks to guarantee strict lock ordering, because + * VFS has already done it for us on the @i_mutex. So this is just a simple + * wrapper function. */ static void lock_2_inodes(struct inode *inode1, struct inode *inode2) { - if (inode1->i_ino < inode2->i_ino) { - mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_2); - mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_3); - } else { - mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_2); - mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_3); - } + mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_1); + mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_2); } /** - * unlock_2_inodes - unlock two UBIFS inodes inodes. + * unlock_2_inodes - a wrapper for unlocking two UBIFS inodes. * @inode1: first inode * @inode2: second inode */ static void unlock_2_inodes(struct inode *inode1, struct inode *inode2) { - mutex_unlock(&ubifs_inode(inode1)->ui_mutex); mutex_unlock(&ubifs_inode(inode2)->ui_mutex); + mutex_unlock(&ubifs_inode(inode1)->ui_mutex); } static int ubifs_link(struct dentry *old_dentry, struct inode *dir, @@ -527,6 +526,8 @@ static int ubifs_link(struct dentry *old_dentry, struct inode *dir, dbg_gen("dent '%.*s' to ino %lu (nlink %d) in dir ino %lu", dentry->d_name.len, dentry->d_name.name, inode->i_ino, inode->i_nlink, dir->i_ino); + ubifs_assert(mutex_is_locked(&dir->i_mutex)); + ubifs_assert(mutex_is_locked(&inode->i_mutex)); err = dbg_check_synced_i_size(inode); if (err) return err; @@ -580,6 +581,8 @@ static int ubifs_unlink(struct inode *dir, struct dentry *dentry) dbg_gen("dent '%.*s' from ino %lu (nlink %d) in dir ino %lu", dentry->d_name.len, dentry->d_name.name, inode->i_ino, inode->i_nlink, dir->i_ino); + ubifs_assert(mutex_is_locked(&dir->i_mutex)); + ubifs_assert(mutex_is_locked(&inode->i_mutex)); err = dbg_check_synced_i_size(inode); if (err) return err; @@ -667,7 +670,8 @@ static int ubifs_rmdir(struct inode *dir, struct dentry *dentry) dbg_gen("directory '%.*s', ino %lu in dir ino %lu", dentry->d_name.len, dentry->d_name.name, inode->i_ino, dir->i_ino); - + ubifs_assert(mutex_is_locked(&dir->i_mutex)); + ubifs_assert(mutex_is_locked(&inode->i_mutex)); err = check_dir_empty(c, dentry->d_inode); if (err) return err; @@ -922,59 +926,30 @@ static int ubifs_symlink(struct inode *dir, struct dentry *dentry, } /** - * lock_3_inodes - lock three UBIFS inodes for rename. + * lock_3_inodes - a wrapper for locking three UBIFS inodes. * @inode1: first inode * @inode2: second inode * @inode3: third inode * - * For 'ubifs_rename()', @inode1 may be the same as @inode2 whereas @inode3 may - * be null. + * This function is used for 'ubifs_rename()' and @inode1 may be the same as + * @inode2 whereas @inode3 may be %NULL. + * + * We do not implement any tricks to guarantee strict lock ordering, because + * VFS has already done it for us on the @i_mutex. So this is just a simple + * wrapper function. */ static void lock_3_inodes(struct inode *inode1, struct inode *inode2, struct inode *inode3) { - struct inode *i1, *i2, *i3; - - if (!inode3) { - if (inode1 != inode2) { - lock_2_inodes(inode1, inode2); - return; - } - mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_1); - return; - } - - if (inode1 == inode2) { - lock_2_inodes(inode1, inode3); - return; - } - - /* 3 different inodes */ - if (inode1 < inode2) { - i3 = inode2; - if (inode1 < inode3) { - i1 = inode1; - i2 = inode3; - } else { - i1 = inode3; - i2 = inode1; - } - } else { - i3 = inode1; - if (inode2 < inode3) { - i1 = inode2; - i2 = inode3; - } else { - i1 = inode3; - i2 = inode2; - } - } - mutex_lock_nested(&ubifs_inode(i1)->ui_mutex, WB_MUTEX_1); - lock_2_inodes(i2, i3); + mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_1); + if (inode2 != inode1) + mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_2); + if (inode3) + mutex_lock_nested(&ubifs_inode(inode3)->ui_mutex, WB_MUTEX_3); } /** - * unlock_3_inodes - unlock three UBIFS inodes for rename. + * unlock_3_inodes - a wrapper for unlocking three UBIFS inodes for rename. * @inode1: first inode * @inode2: second inode * @inode3: third inode @@ -982,11 +957,11 @@ static void lock_3_inodes(struct inode *inode1, struct inode *inode2, static void unlock_3_inodes(struct inode *inode1, struct inode *inode2, struct inode *inode3) { - mutex_unlock(&ubifs_inode(inode1)->ui_mutex); - if (inode1 != inode2) - mutex_unlock(&ubifs_inode(inode2)->ui_mutex); if (inode3) mutex_unlock(&ubifs_inode(inode3)->ui_mutex); + if (inode1 != inode2) + mutex_unlock(&ubifs_inode(inode2)->ui_mutex); + mutex_unlock(&ubifs_inode(inode1)->ui_mutex); } static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry, @@ -1020,6 +995,11 @@ static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry, "dir ino %lu", old_dentry->d_name.len, old_dentry->d_name.name, old_inode->i_ino, old_dir->i_ino, new_dentry->d_name.len, new_dentry->d_name.name, new_dir->i_ino); + ubifs_assert(mutex_is_locked(&old_dir->i_mutex)); + ubifs_assert(mutex_is_locked(&new_dir->i_mutex)); + if (unlink) + ubifs_assert(mutex_is_locked(&new_inode->i_mutex)); + if (unlink && is_dir) { err = check_dir_empty(c, new_inode); From e4d9b6cbfc98d696a28d2c24a3d49768695811ee Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 23 Jan 2009 14:17:36 +0200 Subject: [PATCH 007/111] UBIFS: fix LEB list freeing When freeing the c->idx_lebs list, we have to release the LEBs as well, because we might be called from mount to read-only mode code. Otherwise the LEBs stay taken forever, which may cause problems when we re-mount back ro RW mode. Signed-off-by: Artem Bityutskiy --- fs/ubifs/gc.c | 16 ++++++++++++---- fs/ubifs/lprops.c | 8 ++++++++ fs/ubifs/super.c | 42 +++++++++++++++++++++++++++--------------- fs/ubifs/ubifs.h | 2 +- 4 files changed, 48 insertions(+), 20 deletions(-) diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c index b2e5f1133377..9760154d874b 100644 --- a/fs/ubifs/gc.c +++ b/fs/ubifs/gc.c @@ -830,21 +830,29 @@ int ubifs_gc_end_commit(struct ubifs_info *c) * ubifs_destroy_idx_gc - destroy idx_gc list. * @c: UBIFS file-system description object * - * This function destroys the idx_gc list. It is called when unmounting or - * remounting read-only so locks are not needed. + * This function destroys the @c->idx_gc list. It is called when unmounting or + * remounting read-only so locks are not needed. Returns zero in case of + * success and a negative error code in case of failure. */ -void ubifs_destroy_idx_gc(struct ubifs_info *c) +int ubifs_destroy_idx_gc(struct ubifs_info *c) { + int ret = 0; + while (!list_empty(&c->idx_gc)) { + int err; struct ubifs_gced_idx_leb *idx_gc; idx_gc = list_entry(c->idx_gc.next, struct ubifs_gced_idx_leb, list); - c->idx_gc_cnt -= 1; + err = ubifs_change_one_lp(c, idx_gc->lnum, LPROPS_NC, + LPROPS_NC, 0, LPROPS_TAKEN, -1); + if (err && !ret) + ret = err; list_del(&idx_gc->list); kfree(idx_gc); } + return ret; } /** diff --git a/fs/ubifs/lprops.c b/fs/ubifs/lprops.c index dfd2bcece27a..68328c59762b 100644 --- a/fs/ubifs/lprops.c +++ b/fs/ubifs/lprops.c @@ -678,6 +678,9 @@ int ubifs_change_one_lp(struct ubifs_info *c, int lnum, int free, int dirty, out: ubifs_release_lprops(c); + if (err) + ubifs_err("cannot change properties of LEB %d, error %d", + lnum, err); return err; } @@ -714,6 +717,9 @@ int ubifs_update_one_lp(struct ubifs_info *c, int lnum, int free, int dirty, out: ubifs_release_lprops(c); + if (err) + ubifs_err("cannot update properties of LEB %d, error %d", + lnum, err); return err; } @@ -737,6 +743,8 @@ int ubifs_read_one_lp(struct ubifs_info *c, int lnum, struct ubifs_lprops *lp) lpp = ubifs_lpt_lookup(c, lnum); if (IS_ERR(lpp)) { err = PTR_ERR(lpp); + ubifs_err("cannot read properties of LEB %d, error %d", + lnum, err); goto out; } diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index da99da098efd..807bbd3c8b4b 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1469,9 +1469,6 @@ static int ubifs_remount_rw(struct ubifs_info *c) { int err, lnum; - if (c->ro_media) - return -EINVAL; - mutex_lock(&c->umount_mutex); c->remounting_rw = 1; c->always_chk_crc = 1; @@ -1605,9 +1602,13 @@ static int ubifs_remount_rw(struct ubifs_info *c) */ static void commit_on_unmount(struct ubifs_info *c) { - struct super_block *sb = c->vfs_sb; long long bud_bytes; + if (!c->fast_unmount) { + dbg_gen("skip committing - fast unmount enabled"); + return; + } + /* * This function is called before the background thread is stopped, so * we may race with ongoing commit, which means we have to take @@ -1617,8 +1618,11 @@ static void commit_on_unmount(struct ubifs_info *c) bud_bytes = c->bud_bytes; spin_unlock(&c->buds_lock); - if (!c->fast_unmount && !(sb->s_flags & MS_RDONLY) && bud_bytes) + if (bud_bytes) { + dbg_gen("run commit"); ubifs_run_commit(c); + } else + dbg_gen("journal is empty, do not run commit"); } /** @@ -1633,6 +1637,8 @@ static void ubifs_remount_ro(struct ubifs_info *c) int i, err; ubifs_assert(!c->need_recovery); + ubifs_assert(!c->ro_media); + commit_on_unmount(c); mutex_lock(&c->umount_mutex); @@ -1646,16 +1652,17 @@ static void ubifs_remount_ro(struct ubifs_info *c) del_timer_sync(&c->jheads[i].wbuf.timer); } - if (!c->ro_media) { - c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY); - c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS); - c->mst_node->gc_lnum = cpu_to_le32(c->gc_lnum); - err = ubifs_write_master(c); - if (err) - ubifs_ro_mode(c, err); - } + c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY); + c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS); + c->mst_node->gc_lnum = cpu_to_le32(c->gc_lnum); + err = ubifs_write_master(c); + if (err) + ubifs_ro_mode(c, err); + + err = ubifs_destroy_idx_gc(c); + if (err) + ubifs_ro_mode(c, err); - ubifs_destroy_idx_gc(c); free_wbufs(c); vfree(c->orph_buf); c->orph_buf = NULL; @@ -1754,6 +1761,11 @@ static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data) } if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) { + if (c->ro_media) { + ubifs_msg("cannot re-mount R/W, UBIFS is working in " + "R/O mode"); + return -EINVAL; + } err = ubifs_remount_rw(c); if (err) return err; @@ -2044,7 +2056,7 @@ static void ubifs_kill_sb(struct super_block *sb) * We do 'commit_on_unmount()' here instead of 'ubifs_put_super()' * in order to be outside BKL. */ - if (sb->s_root) + if (sb->s_root && !(sb->s_flags & MS_RDONLY)) commit_on_unmount(c); /* The un-mount routine is actually done in put_super() */ generic_shutdown_super(sb); diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 2e78d6ac007e..ee9517a7b024 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -1593,7 +1593,7 @@ int ubifs_replay_journal(struct ubifs_info *c); int ubifs_garbage_collect(struct ubifs_info *c, int anyway); int ubifs_gc_start_commit(struct ubifs_info *c); int ubifs_gc_end_commit(struct ubifs_info *c); -void ubifs_destroy_idx_gc(struct ubifs_info *c); +int ubifs_destroy_idx_gc(struct ubifs_info *c); int ubifs_get_idx_gc_leb(struct ubifs_info *c); int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp); From 84abf972ccff5c13d10b672972949eba431a6e0e Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 23 Jan 2009 14:54:59 +0200 Subject: [PATCH 008/111] UBIFS: add re-mount debugging checks We observe space corrupted accounting when re-mounting. So add some debbugging checks to catch problems like this. Signed-off-by: Artem Bityutskiy --- fs/ubifs/budget.c | 35 ++++++++++---- fs/ubifs/debug.c | 120 +++++++++++++++++++++++++++++++++------------- fs/ubifs/debug.h | 36 ++++++++------ fs/ubifs/file.c | 1 - fs/ubifs/lprops.c | 4 +- fs/ubifs/super.c | 14 ++++-- fs/ubifs/ubifs.h | 3 +- 7 files changed, 148 insertions(+), 65 deletions(-) diff --git a/fs/ubifs/budget.c b/fs/ubifs/budget.c index 175f9c590b77..f393620890ee 100644 --- a/fs/ubifs/budget.c +++ b/fs/ubifs/budget.c @@ -689,7 +689,7 @@ long long ubifs_reported_space(const struct ubifs_info *c, long long free) } /** - * ubifs_get_free_space - return amount of free space. + * ubifs_get_free_space_nolock - return amount of free space. * @c: UBIFS file-system description object * * This function calculates amount of free space to report to user-space. @@ -704,16 +704,14 @@ long long ubifs_reported_space(const struct ubifs_info *c, long long free) * traditional file-systems, because they have way less overhead than UBIFS. * So, to keep users happy, UBIFS tries to take the overhead into account. */ -long long ubifs_get_free_space(struct ubifs_info *c) +long long ubifs_get_free_space_nolock(struct ubifs_info *c) { - int min_idx_lebs, rsvd_idx_lebs, lebs; + int rsvd_idx_lebs, lebs; long long available, outstanding, free; - spin_lock(&c->space_lock); - min_idx_lebs = c->min_idx_lebs; - ubifs_assert(min_idx_lebs == ubifs_calc_min_idx_lebs(c)); + ubifs_assert(c->min_idx_lebs == ubifs_calc_min_idx_lebs(c)); outstanding = c->budg_data_growth + c->budg_dd_growth; - available = ubifs_calc_available(c, min_idx_lebs); + available = ubifs_calc_available(c, c->min_idx_lebs); /* * When reporting free space to user-space, UBIFS guarantees that it is @@ -726,15 +724,14 @@ long long ubifs_get_free_space(struct ubifs_info *c) * Note, the calculations below are similar to what we have in * 'do_budget_space()', so refer there for comments. */ - if (min_idx_lebs > c->lst.idx_lebs) - rsvd_idx_lebs = min_idx_lebs - c->lst.idx_lebs; + if (c->min_idx_lebs > c->lst.idx_lebs) + rsvd_idx_lebs = c->min_idx_lebs - c->lst.idx_lebs; else rsvd_idx_lebs = 0; lebs = c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt - c->lst.taken_empty_lebs; lebs -= rsvd_idx_lebs; available += lebs * (c->dark_wm - c->leb_overhead); - spin_unlock(&c->space_lock); if (available > outstanding) free = ubifs_reported_space(c, available - outstanding); @@ -742,3 +739,21 @@ long long ubifs_get_free_space(struct ubifs_info *c) free = 0; return free; } + +/** + * ubifs_get_free_space - return amount of free space. + * @c: UBIFS file-system description object + * + * This function calculates and retuns amount of free space to report to + * user-space. + */ +long long ubifs_get_free_space(struct ubifs_info *c) +{ + long long free; + + spin_lock(&c->space_lock); + free = ubifs_get_free_space_nolock(c); + spin_unlock(&c->space_lock); + + return free; +} diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index 792c5a16c182..9a41f6f245b7 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -620,9 +620,11 @@ void dbg_dump_budg(struct ubifs_info *c) c->dark_wm, c->dead_wm, c->max_idx_node_sz); printk(KERN_DEBUG "\tgc_lnum %d, ihead_lnum %d\n", c->gc_lnum, c->ihead_lnum); - for (i = 0; i < c->jhead_cnt; i++) - printk(KERN_DEBUG "\tjhead %d\t LEB %d\n", - c->jheads[i].wbuf.jhead, c->jheads[i].wbuf.lnum); + /* If we are in R/O mode, journal heads do not exist */ + if (c->jheads) + for (i = 0; i < c->jhead_cnt; i++) + printk(KERN_DEBUG "\tjhead %d\t LEB %d\n", + c->jheads[i].wbuf.jhead, c->jheads[i].wbuf.lnum); for (rb = rb_first(&c->buds); rb; rb = rb_next(rb)) { bud = rb_entry(rb, struct ubifs_bud, rb); printk(KERN_DEBUG "\tbud LEB %d\n", bud->lnum); @@ -637,10 +639,7 @@ void dbg_dump_budg(struct ubifs_info *c) /* Print budgeting predictions */ available = ubifs_calc_available(c, c->min_idx_lebs); outstanding = c->budg_data_growth + c->budg_dd_growth; - if (available > outstanding) - free = ubifs_reported_space(c, available - outstanding); - else - free = 0; + free = ubifs_get_free_space_nolock(c); printk(KERN_DEBUG "Budgeting predictions:\n"); printk(KERN_DEBUG "\tavailable: %lld, outstanding %lld, free %lld\n", available, outstanding, free); @@ -860,6 +859,65 @@ void dbg_dump_index(struct ubifs_info *c) dbg_walk_index(c, NULL, dump_znode, NULL); } +/** + * dbg_save_space_info - save information about flash space. + * @c: UBIFS file-system description object + * + * This function saves information about UBIFS free space, dirty space, etc, in + * order to check it later. + */ +void dbg_save_space_info(struct ubifs_info *c) +{ + struct ubifs_debug_info *d = c->dbg; + + ubifs_get_lp_stats(c, &d->saved_lst); + + spin_lock(&c->space_lock); + d->saved_free = ubifs_get_free_space_nolock(c); + spin_unlock(&c->space_lock); +} + +/** + * dbg_check_space_info - check flash space information. + * @c: UBIFS file-system description object + * + * This function compares current flash space information with the information + * which was saved when the 'dbg_save_space_info()' function was called. + * Returns zero if the information has not changed, and %-EINVAL it it has + * changed. + */ +int dbg_check_space_info(struct ubifs_info *c) +{ + struct ubifs_debug_info *d = c->dbg; + struct ubifs_lp_stats lst; + long long avail, free; + + spin_lock(&c->space_lock); + avail = ubifs_calc_available(c, c->min_idx_lebs); + spin_unlock(&c->space_lock); + free = ubifs_get_free_space(c); + + if (free != d->saved_free) { + ubifs_err("free space changed from %lld to %lld", + d->saved_free, free); + goto out; + } + + return 0; + +out: + ubifs_msg("saved lprops statistics dump"); + dbg_dump_lstats(&d->saved_lst); + ubifs_get_lp_stats(c, &lst); + ubifs_msg("current lprops statistics dump"); + dbg_dump_lstats(&d->saved_lst); + spin_lock(&c->space_lock); + dbg_dump_budg(c); + spin_unlock(&c->space_lock); + dump_stack(); + return -EINVAL; +} + /** * dbg_check_synced_i_size - check synchronized inode size. * @inode: inode to check @@ -2409,7 +2467,7 @@ void ubifs_debugging_exit(struct ubifs_info *c) * Root directory for UBIFS stuff in debugfs. Contains sub-directories which * contain the stuff specific to particular file-system mounts. */ -static struct dentry *debugfs_rootdir; +static struct dentry *dfs_rootdir; /** * dbg_debugfs_init - initialize debugfs file-system. @@ -2421,9 +2479,9 @@ static struct dentry *debugfs_rootdir; */ int dbg_debugfs_init(void) { - debugfs_rootdir = debugfs_create_dir("ubifs", NULL); - if (IS_ERR(debugfs_rootdir)) { - int err = PTR_ERR(debugfs_rootdir); + dfs_rootdir = debugfs_create_dir("ubifs", NULL); + if (IS_ERR(dfs_rootdir)) { + int err = PTR_ERR(dfs_rootdir); ubifs_err("cannot create \"ubifs\" debugfs directory, " "error %d\n", err); return err; @@ -2437,7 +2495,7 @@ int dbg_debugfs_init(void) */ void dbg_debugfs_exit(void) { - debugfs_remove(debugfs_rootdir); + debugfs_remove(dfs_rootdir); } static int open_debugfs_file(struct inode *inode, struct file *file) @@ -2452,13 +2510,13 @@ static ssize_t write_debugfs_file(struct file *file, const char __user *buf, struct ubifs_info *c = file->private_data; struct ubifs_debug_info *d = c->dbg; - if (file->f_path.dentry == d->dump_lprops) + if (file->f_path.dentry == d->dfs_dump_lprops) dbg_dump_lprops(c); - else if (file->f_path.dentry == d->dump_budg) { + else if (file->f_path.dentry == d->dfs_dump_budg) { spin_lock(&c->space_lock); dbg_dump_budg(c); spin_unlock(&c->space_lock); - } else if (file->f_path.dentry == d->dump_tnc) { + } else if (file->f_path.dentry == d->dfs_dump_tnc) { mutex_lock(&c->tnc_mutex); dbg_dump_tnc(c); mutex_unlock(&c->tnc_mutex); @@ -2469,7 +2527,7 @@ static ssize_t write_debugfs_file(struct file *file, const char __user *buf, return count; } -static const struct file_operations debugfs_fops = { +static const struct file_operations dfs_fops = { .open = open_debugfs_file, .write = write_debugfs_file, .owner = THIS_MODULE, @@ -2494,36 +2552,32 @@ int dbg_debugfs_init_fs(struct ubifs_info *c) struct dentry *dent; struct ubifs_debug_info *d = c->dbg; - sprintf(d->debugfs_dir_name, "ubi%d_%d", c->vi.ubi_num, c->vi.vol_id); - d->debugfs_dir = debugfs_create_dir(d->debugfs_dir_name, - debugfs_rootdir); - if (IS_ERR(d->debugfs_dir)) { - err = PTR_ERR(d->debugfs_dir); + sprintf(d->dfs_dir_name, "ubi%d_%d", c->vi.ubi_num, c->vi.vol_id); + d->dfs_dir = debugfs_create_dir(d->dfs_dir_name, dfs_rootdir); + if (IS_ERR(d->dfs_dir)) { + err = PTR_ERR(d->dfs_dir); ubifs_err("cannot create \"%s\" debugfs directory, error %d\n", - d->debugfs_dir_name, err); + d->dfs_dir_name, err); goto out; } fname = "dump_lprops"; - dent = debugfs_create_file(fname, S_IWUGO, d->debugfs_dir, c, - &debugfs_fops); + dent = debugfs_create_file(fname, S_IWUGO, d->dfs_dir, c, &dfs_fops); if (IS_ERR(dent)) goto out_remove; - d->dump_lprops = dent; + d->dfs_dump_lprops = dent; fname = "dump_budg"; - dent = debugfs_create_file(fname, S_IWUGO, d->debugfs_dir, c, - &debugfs_fops); + dent = debugfs_create_file(fname, S_IWUGO, d->dfs_dir, c, &dfs_fops); if (IS_ERR(dent)) goto out_remove; - d->dump_budg = dent; + d->dfs_dump_budg = dent; fname = "dump_tnc"; - dent = debugfs_create_file(fname, S_IWUGO, d->debugfs_dir, c, - &debugfs_fops); + dent = debugfs_create_file(fname, S_IWUGO, d->dfs_dir, c, &dfs_fops); if (IS_ERR(dent)) goto out_remove; - d->dump_tnc = dent; + d->dfs_dump_tnc = dent; return 0; @@ -2531,7 +2585,7 @@ int dbg_debugfs_init_fs(struct ubifs_info *c) err = PTR_ERR(dent); ubifs_err("cannot create \"%s\" debugfs directory, error %d\n", fname, err); - debugfs_remove_recursive(d->debugfs_dir); + debugfs_remove_recursive(d->dfs_dir); out: return err; } @@ -2542,7 +2596,7 @@ int dbg_debugfs_init_fs(struct ubifs_info *c) */ void dbg_debugfs_exit_fs(struct ubifs_info *c) { - debugfs_remove_recursive(c->dbg->debugfs_dir); + debugfs_remove_recursive(c->dbg->dfs_dir); } #endif /* CONFIG_UBIFS_FS_DEBUG */ diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h index 9820d6999f7e..c1cd73b2e06e 100644 --- a/fs/ubifs/debug.h +++ b/fs/ubifs/debug.h @@ -41,15 +41,17 @@ * @chk_lpt_wastage: used by LPT tree size checker * @chk_lpt_lebs: used by LPT tree size checker * @new_nhead_offs: used by LPT tree size checker - * @new_ihead_lnum: used by debugging to check ihead_lnum - * @new_ihead_offs: used by debugging to check ihead_offs + * @new_ihead_lnum: used by debugging to check @c->ihead_lnum + * @new_ihead_offs: used by debugging to check @c->ihead_offs * - * debugfs_dir_name: name of debugfs directory containing this file-system's - * files - * debugfs_dir: direntry object of the file-system debugfs directory - * dump_lprops: "dump lprops" debugfs knob - * dump_budg: "dump budgeting information" debugfs knob - * dump_tnc: "dump TNC" debugfs knob + * @saved_lst: saved lprops statistics (used by 'dbg_save_space_info()') + * @saved_free: saved free space (used by 'dbg_save_space_info()') + * + * dfs_dir_name: name of debugfs directory containing this file-system's files + * dfs_dir: direntry object of the file-system debugfs directory + * dfs_dump_lprops: "dump lprops" debugfs knob + * dfs_dump_budg: "dump budgeting information" debugfs knob + * dfs_dump_tnc: "dump TNC" debugfs knob */ struct ubifs_debug_info { void *buf; @@ -69,11 +71,14 @@ struct ubifs_debug_info { int new_ihead_lnum; int new_ihead_offs; - char debugfs_dir_name[100]; - struct dentry *debugfs_dir; - struct dentry *dump_lprops; - struct dentry *dump_budg; - struct dentry *dump_tnc; + struct ubifs_lp_stats saved_lst; + long long saved_free; + + char dfs_dir_name[100]; + struct dentry *dfs_dir; + struct dentry *dfs_dump_lprops; + struct dentry *dfs_dump_budg; + struct dentry *dfs_dump_tnc; }; #define ubifs_assert(expr) do { \ @@ -297,7 +302,8 @@ int dbg_walk_index(struct ubifs_info *c, dbg_leaf_callback leaf_cb, dbg_znode_callback znode_cb, void *priv); /* Checking functions */ - +void dbg_save_space_info(struct ubifs_info *c); +int dbg_check_space_info(struct ubifs_info *c); int dbg_check_lprops(struct ubifs_info *c); int dbg_old_index_check_init(struct ubifs_info *c, struct ubifs_zbranch *zroot); int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot); @@ -439,6 +445,8 @@ void dbg_debugfs_exit_fs(struct ubifs_info *c); #define dbg_walk_index(c, leaf_cb, znode_cb, priv) 0 #define dbg_old_index_check_init(c, zroot) 0 +#define dbg_save_space_info(c) ({}) +#define dbg_check_space_info(c) 0 #define dbg_check_old_index(c, zroot) 0 #define dbg_check_cats(c) 0 #define dbg_check_ltab(c) 0 diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index 17443d97e6f1..93b6de51f261 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c @@ -432,7 +432,6 @@ static int ubifs_write_begin(struct file *file, struct address_space *mapping, int uninitialized_var(err), appending = !!(pos + len > inode->i_size); struct page *page; - ubifs_assert(ubifs_inode(inode)->ui_size == inode->i_size); if (unlikely(c->ro_media)) diff --git a/fs/ubifs/lprops.c b/fs/ubifs/lprops.c index 68328c59762b..4cdd284dea56 100644 --- a/fs/ubifs/lprops.c +++ b/fs/ubifs/lprops.c @@ -635,10 +635,10 @@ const struct ubifs_lprops *ubifs_change_lp(struct ubifs_info *c, * @c: UBIFS file-system description object * @st: return statistics */ -void ubifs_get_lp_stats(struct ubifs_info *c, struct ubifs_lp_stats *st) +void ubifs_get_lp_stats(struct ubifs_info *c, struct ubifs_lp_stats *lst) { spin_lock(&c->space_lock); - memcpy(st, &c->lst, sizeof(struct ubifs_lp_stats)); + memcpy(lst, &c->lst, sizeof(struct ubifs_lp_stats)); spin_unlock(&c->space_lock); } diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 807bbd3c8b4b..5c814a71f33a 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1470,6 +1470,7 @@ static int ubifs_remount_rw(struct ubifs_info *c) int err, lnum; mutex_lock(&c->umount_mutex); + dbg_save_space_info(c); c->remounting_rw = 1; c->always_chk_crc = 1; @@ -1573,8 +1574,9 @@ static int ubifs_remount_rw(struct ubifs_info *c) c->vfs_sb->s_flags &= ~MS_RDONLY; c->remounting_rw = 0; c->always_chk_crc = 0; + err = dbg_check_space_info(c); mutex_unlock(&c->umount_mutex); - return 0; + return err; out: vfree(c->orph_buf); @@ -1629,8 +1631,8 @@ static void commit_on_unmount(struct ubifs_info *c) * ubifs_remount_ro - re-mount in read-only mode. * @c: UBIFS file-system description object * - * We rely on VFS to have stopped writing. Possibly the background thread could - * be running a commit, however kthread_stop will wait in that case. + * We assume VFS has stopped writing. Possibly the background thread could be + * running a commit, however kthread_stop will wait in that case. */ static void ubifs_remount_ro(struct ubifs_info *c) { @@ -1640,13 +1642,14 @@ static void ubifs_remount_ro(struct ubifs_info *c) ubifs_assert(!c->ro_media); commit_on_unmount(c); - mutex_lock(&c->umount_mutex); if (c->bgt) { kthread_stop(c->bgt); c->bgt = NULL; } + dbg_save_space_info(c); + for (i = 0; i < c->jhead_cnt; i++) { ubifs_wbuf_sync(&c->jheads[i].wbuf); del_timer_sync(&c->jheads[i].wbuf.timer); @@ -1669,6 +1672,9 @@ static void ubifs_remount_ro(struct ubifs_info *c) vfree(c->ileb_buf); c->ileb_buf = NULL; ubifs_lpt_free(c, 1); + err = dbg_check_space_info(c); + if (err) + ubifs_ro_mode(c, err); mutex_unlock(&c->umount_mutex); } diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index ee9517a7b024..f1754354029f 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -1495,6 +1495,7 @@ void ubifs_release_ino_dirty(struct ubifs_info *c, struct inode *inode, void ubifs_cancel_ino_op(struct ubifs_info *c, struct inode *inode, struct ubifs_budget_req *req); long long ubifs_get_free_space(struct ubifs_info *c); +long long ubifs_get_free_space_nolock(struct ubifs_info *c); int ubifs_calc_min_idx_lebs(struct ubifs_info *c); void ubifs_convert_page_budget(struct ubifs_info *c); long long ubifs_reported_space(const struct ubifs_info *c, long long free); @@ -1646,7 +1647,7 @@ const struct ubifs_lprops *ubifs_change_lp(struct ubifs_info *c, const struct ubifs_lprops *lp, int free, int dirty, int flags, int idx_gc_cnt); -void ubifs_get_lp_stats(struct ubifs_info *c, struct ubifs_lp_stats *stats); +void ubifs_get_lp_stats(struct ubifs_info *c, struct ubifs_lp_stats *lst); void ubifs_add_to_cat(struct ubifs_info *c, struct ubifs_lprops *lprops, int cat); void ubifs_replace_cat(struct ubifs_info *c, struct ubifs_lprops *old_lprops, From b4978e949104844224ecf786170c9263efa601f3 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 23 Jan 2009 18:23:03 +0200 Subject: [PATCH 009/111] UBIFS: always clean up GC LEB space When we mount UBIFS, GC LEB may contain out-of-date information, and UBIFS should update lprops and set free space for thei LEB. Currently UBIFS does this only if mounted R/W. But for R/O mount we have to do the same, because otherwise we will have incorrect FS free space reported to user-space. Signed-off-by: Artem Bityutskiy --- fs/ubifs/super.c | 47 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 5c814a71f33a..336073e4c391 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -397,6 +397,7 @@ static int ubifs_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_namelen = UBIFS_MAX_NLEN; buf->f_fsid.val[0] = le32_to_cpu(uuid[0]) ^ le32_to_cpu(uuid[2]); buf->f_fsid.val[1] = le32_to_cpu(uuid[1]) ^ le32_to_cpu(uuid[3]); + ubifs_assert(buf->f_bfree <= c->block_cnt); return 0; } @@ -735,12 +736,12 @@ static void init_constants_master(struct ubifs_info *c) * take_gc_lnum - reserve GC LEB. * @c: UBIFS file-system description object * - * This function ensures that the LEB reserved for garbage collection is - * unmapped and is marked as "taken" in lprops. We also have to set free space - * to LEB size and dirty space to zero, because lprops may contain out-of-date - * information if the file-system was un-mounted before it has been committed. - * This function returns zero in case of success and a negative error code in - * case of failure. + * This function ensures that the LEB reserved for garbage collection is marked + * as "taken" in lprops. We also have to set free space to LEB size and dirty + * space to zero, because lprops may contain out-of-date information if the + * file-system was un-mounted before it has been committed. This function + * returns zero in case of success and a negative error code in case of + * failure. */ static int take_gc_lnum(struct ubifs_info *c) { @@ -751,10 +752,6 @@ static int take_gc_lnum(struct ubifs_info *c) return -EINVAL; } - err = ubifs_leb_unmap(c, c->gc_lnum); - if (err) - return err; - /* And we have to tell lprops that this LEB is taken */ err = ubifs_change_one_lp(c, c->gc_lnum, c->leb_size, 0, LPROPS_TAKEN, 0, 0); @@ -1280,10 +1277,19 @@ static int mount_ubifs(struct ubifs_info *c) if (err) goto out_orphans; err = ubifs_rcvry_gc_commit(c); - } else + } else { err = take_gc_lnum(c); - if (err) - goto out_orphans; + if (err) + goto out_orphans; + + /* + * GC LEB may contain garbage if there was an unclean + * reboot, and it should be un-mapped. + */ + err = ubifs_leb_unmap(c, c->gc_lnum); + if (err) + return err; + } err = dbg_check_lprops(c); if (err) @@ -1292,6 +1298,16 @@ static int mount_ubifs(struct ubifs_info *c) err = ubifs_recover_size(c); if (err) goto out_orphans; + } else { + /* + * Even if we mount read-only, we have to set space in GC LEB + * to proper value because this affects UBIFS free space + * reporting. We do not want to have a situation when + * re-mounting from R/O to R/W changes amount of free space. + */ + err = take_gc_lnum(c); + if (err) + goto out_orphans; } spin_lock(&ubifs_infos_lock); @@ -1316,6 +1332,8 @@ static int mount_ubifs(struct ubifs_info *c) goto out_infos; c->always_chk_crc = 0; + /* GC LEB has to be empty and taken at this point */ + ubifs_assert(c->lst.taken_empty_lebs == 1); ubifs_msg("mounted UBI device %d, volume %d, name \"%s\"", c->vi.ubi_num, c->vi.vol_id, c->vi.name); @@ -1561,7 +1579,7 @@ static int ubifs_remount_rw(struct ubifs_info *c) if (c->need_recovery) err = ubifs_rcvry_gc_commit(c); else - err = take_gc_lnum(c); + err = ubifs_leb_unmap(c, c->gc_lnum); if (err) goto out; @@ -1786,6 +1804,7 @@ static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data) c->bu.buf = NULL; } + ubifs_assert(c->lst.taken_empty_lebs == 1); return 0; } From 49d128aa60751a010640f4763d11577e2f508853 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Mon, 26 Jan 2009 10:55:40 +0200 Subject: [PATCH 010/111] UBIFS: ensure orphan area head is initialized When mounting read-only the orphan area head is not initialized. It must be initialized when remounting read/write, but it was not. This patch fixes that. [Artem: sorry, added comment tweaking noise] Signed-off-by: Adrian Hunter Signed-off-by: Artem Bityutskiy --- fs/ubifs/orphan.c | 38 +++++++++++++++++++------------------- fs/ubifs/super.c | 6 ++++++ fs/ubifs/ubifs.h | 1 + 3 files changed, 26 insertions(+), 19 deletions(-) diff --git a/fs/ubifs/orphan.c b/fs/ubifs/orphan.c index 9e6f403f170e..152a7b34a141 100644 --- a/fs/ubifs/orphan.c +++ b/fs/ubifs/orphan.c @@ -46,7 +46,7 @@ * Orphans are accumulated in a rb-tree. When an inode's link count drops to * zero, the inode number is added to the rb-tree. It is removed from the tree * when the inode is deleted. Any new orphans that are in the orphan tree when - * the commit is run, are written to the orphan area in 1 or more orph nodes. + * the commit is run, are written to the orphan area in 1 or more orphan nodes. * If the orphan area is full, it is consolidated to make space. There is * always enough space because validation prevents the user from creating more * than the maximum number of orphans allowed. @@ -231,7 +231,7 @@ static int tot_avail_orphs(struct ubifs_info *c) } /** - * do_write_orph_node - write a node + * do_write_orph_node - write a node to the orphan head. * @c: UBIFS file-system description object * @len: length of node * @atomic: write atomically @@ -264,11 +264,11 @@ static int do_write_orph_node(struct ubifs_info *c, int len, int atomic) } /** - * write_orph_node - write an orph node + * write_orph_node - write an orphan node. * @c: UBIFS file-system description object * @atomic: write atomically * - * This function builds an orph node from the cnext list and writes it to the + * This function builds an orphan node from the cnext list and writes it to the * orphan head. On success, %0 is returned, otherwise a negative error code * is returned. */ @@ -326,11 +326,11 @@ static int write_orph_node(struct ubifs_info *c, int atomic) } /** - * write_orph_nodes - write orph nodes until there are no more to commit + * write_orph_nodes - write orphan nodes until there are no more to commit. * @c: UBIFS file-system description object * @atomic: write atomically * - * This function writes orph nodes for all the orphans to commit. On success, + * This function writes orphan nodes for all the orphans to commit. On success, * %0 is returned, otherwise a negative error code is returned. */ static int write_orph_nodes(struct ubifs_info *c, int atomic) @@ -478,14 +478,14 @@ int ubifs_orphan_end_commit(struct ubifs_info *c) } /** - * clear_orphans - erase all LEBs used for orphans. + * ubifs_clear_orphans - erase all LEBs used for orphans. * @c: UBIFS file-system description object * * If recovery is not required, then the orphans from the previous session * are not needed. This function locates the LEBs used to record * orphans, and un-maps them. */ -static int clear_orphans(struct ubifs_info *c) +int ubifs_clear_orphans(struct ubifs_info *c) { int lnum, err; @@ -547,9 +547,9 @@ static int insert_dead_orphan(struct ubifs_info *c, ino_t inum) * do_kill_orphans - remove orphan inodes from the index. * @c: UBIFS file-system description object * @sleb: scanned LEB - * @last_cmt_no: cmt_no of last orph node read is passed and returned here + * @last_cmt_no: cmt_no of last orphan node read is passed and returned here * @outofdate: whether the LEB is out of date is returned here - * @last_flagged: whether the end orph node is encountered + * @last_flagged: whether the end orphan node is encountered * * This function is a helper to the 'kill_orphans()' function. It goes through * every orphan node in a LEB and for every inode number recorded, removes @@ -580,8 +580,8 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb, /* * The commit number on the master node may be less, because * of a failed commit. If there are several failed commits in a - * row, the commit number written on orph nodes will continue to - * increase (because the commit number is adjusted here) even + * row, the commit number written on orphan nodes will continue + * to increase (because the commit number is adjusted here) even * though the commit number on the master node stays the same * because the master node has not been re-written. */ @@ -589,9 +589,9 @@ static int do_kill_orphans(struct ubifs_info *c, struct ubifs_scan_leb *sleb, c->cmt_no = cmt_no; if (cmt_no < *last_cmt_no && *last_flagged) { /* - * The last orph node had a higher commit number and was - * flagged as the last written for that commit number. - * That makes this orph node, out of date. + * The last orphan node had a higher commit number and + * was flagged as the last written for that commit + * number. That makes this orphan node, out of date. */ if (!first) { ubifs_err("out of order commit number %llu in " @@ -658,10 +658,10 @@ static int kill_orphans(struct ubifs_info *c) /* * Orph nodes always start at c->orph_first and are written to each * successive LEB in turn. Generally unused LEBs will have been unmapped - * but may contain out of date orph nodes if the unmap didn't go - * through. In addition, the last orph node written for each commit is + * but may contain out of date orphan nodes if the unmap didn't go + * through. In addition, the last orphan node written for each commit is * marked (top bit of orph->cmt_no is set to 1). It is possible that - * there are orph nodes from the next commit (i.e. the commit did not + * there are orphan nodes from the next commit (i.e. the commit did not * complete successfully). In that case, no orphans will have been lost * due to the way that orphans are written, and any orphans added will * be valid orphans anyway and so can be deleted. @@ -718,7 +718,7 @@ int ubifs_mount_orphans(struct ubifs_info *c, int unclean, int read_only) if (unclean) err = kill_orphans(c); else if (!read_only) - err = clear_orphans(c); + err = ubifs_clear_orphans(c); return err; } diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 336073e4c391..fd7fc7f3b7a6 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1524,6 +1524,12 @@ static int ubifs_remount_rw(struct ubifs_info *c) err = ubifs_recover_inl_heads(c, c->sbuf); if (err) goto out; + } else { + /* A readonly mount is not allowed to have orphans */ + ubifs_assert(c->tot_orphans == 0); + err = ubifs_clear_orphans(c); + if (err) + goto out; } if (!(c->mst_node->flags & cpu_to_le32(UBIFS_MST_DIRTY))) { diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index f1754354029f..9999ff0aaa43 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -1604,6 +1604,7 @@ void ubifs_delete_orphan(struct ubifs_info *c, ino_t inum); int ubifs_orphan_start_commit(struct ubifs_info *c); int ubifs_orphan_end_commit(struct ubifs_info *c); int ubifs_mount_orphans(struct ubifs_info *c, int unclean, int read_only); +int ubifs_clear_orphans(struct ubifs_info *c); /* lpt.c */ int ubifs_calc_lpt_geom(struct ubifs_info *c); From 6ba87c9b920bea8c2703308d31eb7de925242c30 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 26 Jan 2009 16:12:20 +0200 Subject: [PATCH 011/111] UBIFS: fix assertions I introduce wrong assertions in one of the previous commits, this patch fixes them. Also, initialize debugfs after the debugging check. This is a little nicer because we want the FS data to be accessible to external users after everything has been initialized. Signed-off-by: Artem Bityutskiy --- fs/ubifs/super.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index fd7fc7f3b7a6..dbfc88714716 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1320,20 +1320,21 @@ static int mount_ubifs(struct ubifs_info *c) else { c->need_recovery = 0; ubifs_msg("recovery completed"); + /* GC LEB has to be empty and taken at this point */ + ubifs_assert(c->lst.taken_empty_lebs == 1); } - } - - err = dbg_debugfs_init_fs(c); - if (err) - goto out_infos; + } else + ubifs_assert(c->lst.taken_empty_lebs == 1); err = dbg_check_filesystem(c); if (err) goto out_infos; + err = dbg_debugfs_init_fs(c); + if (err) + goto out_infos; + c->always_chk_crc = 0; - /* GC LEB has to be empty and taken at this point */ - ubifs_assert(c->lst.taken_empty_lebs == 1); ubifs_msg("mounted UBI device %d, volume %d, name \"%s\"", c->vi.ubi_num, c->vi.vol_id, c->vi.name); @@ -1663,7 +1664,7 @@ static void ubifs_remount_ro(struct ubifs_info *c) int i, err; ubifs_assert(!c->need_recovery); - ubifs_assert(!c->ro_media); + ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY)); commit_on_unmount(c); mutex_lock(&c->umount_mutex); From 6f7ab6d458bbfc2f55d295fa3e6b9e69cdb1d517 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Tue, 27 Jan 2009 16:12:31 +0200 Subject: [PATCH 012/111] UBIFS: fix no_chk_data_crc When data CRC checking is disabled, UBIFS returns incorrect return code from the 'try_read_node()' function (0 instead of 1, which means CRC error), which make the caller re-read the data node again, but using a different code patch, so the second read is fine. Thus, we read the same node twice. And the result of this is that UBIFS is slower with no_chk_data_crc option than it is with chk_data_crc option. This patches fixes the problem. Reported-by: Reuben Dowle Signed-off-by: Artem Bityutskiy --- fs/ubifs/io.c | 22 ++++++++++++++-------- fs/ubifs/tnc.c | 12 ++++++++---- fs/ubifs/ubifs.h | 2 +- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c index 01682713af69..e8e632a1dcdf 100644 --- a/fs/ubifs/io.c +++ b/fs/ubifs/io.c @@ -29,7 +29,7 @@ * would have been wasted for padding to the nearest minimal I/O unit boundary. * Instead, data first goes to the write-buffer and is flushed when the * buffer is full or when it is not used for some time (by timer). This is - * similarto the mechanism is used by JFFS2. + * similar to the mechanism is used by JFFS2. * * Write-buffers are defined by 'struct ubifs_wbuf' objects and protected by * mutexes defined inside these objects. Since sometimes upper-level code @@ -75,7 +75,7 @@ void ubifs_ro_mode(struct ubifs_info *c, int err) * @lnum: logical eraseblock number * @offs: offset within the logical eraseblock * @quiet: print no messages - * @chk_crc: indicates whether to always check the CRC + * @must_chk_crc: indicates whether to always check the CRC * * This function checks node magic number and CRC checksum. This function also * validates node length to prevent UBIFS from becoming crazy when an attacker @@ -83,11 +83,17 @@ void ubifs_ro_mode(struct ubifs_info *c, int err) * node length in the common header could cause UBIFS to read memory outside of * allocated buffer when checking the CRC checksum. * - * This function returns zero in case of success %-EUCLEAN in case of bad CRC - * or magic. + * This function may skip data nodes CRC checking if @c->no_chk_data_crc is + * true, which is controlled by corresponding UBIFS mount option. However, if + * @must_chk_crc is true, then @c->no_chk_data_crc is ignored and CRC is + * checked. Similarly, if @c->always_chk_crc is true, @c->no_chk_data_crc is + * ignored and CRC is checked. + * + * This function returns zero in case of success and %-EUCLEAN in case of bad + * CRC or magic. */ int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum, - int offs, int quiet, int chk_crc) + int offs, int quiet, int must_chk_crc) { int err = -EINVAL, type, node_len; uint32_t crc, node_crc, magic; @@ -123,9 +129,9 @@ int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum, node_len > c->ranges[type].max_len) goto out_len; - if (!chk_crc && type == UBIFS_DATA_NODE && !c->always_chk_crc) - if (c->no_chk_data_crc) - return 0; + if (!must_chk_crc && type == UBIFS_DATA_NODE && !c->always_chk_crc && + c->no_chk_data_crc) + return 0; crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8); node_crc = le32_to_cpu(ch->crc); diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c index f7e36f545527..fa28a84c6a1b 100644 --- a/fs/ubifs/tnc.c +++ b/fs/ubifs/tnc.c @@ -443,6 +443,11 @@ static int tnc_read_node_nm(struct ubifs_info *c, struct ubifs_zbranch *zbr, * This function performs that same function as ubifs_read_node except that * it does not require that there is actually a node present and instead * the return code indicates if a node was read. + * + * Note, this function does not check CRC of data nodes if @c->no_chk_data_crc + * is true (it is controlled by corresponding mount option). However, if + * @c->always_chk_crc is true, @c->no_chk_data_crc is ignored and CRC is always + * checked. */ static int try_read_node(const struct ubifs_info *c, void *buf, int type, int len, int lnum, int offs) @@ -470,9 +475,8 @@ static int try_read_node(const struct ubifs_info *c, void *buf, int type, if (node_len != len) return 0; - if (type == UBIFS_DATA_NODE && !c->always_chk_crc) - if (c->no_chk_data_crc) - return 0; + if (type == UBIFS_DATA_NODE && !c->always_chk_crc && c->no_chk_data_crc) + return 1; crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8); node_crc = le32_to_cpu(ch->crc); @@ -1506,7 +1510,7 @@ int ubifs_tnc_locate(struct ubifs_info *c, const union ubifs_key *key, * * Note, if the bulk-read buffer length (@bu->buf_len) is known, this function * makes sure bulk-read nodes fit the buffer. Otherwise, this function prepares - * maxumum possible amount of nodes for bulk-read. + * maximum possible amount of nodes for bulk-read. */ int ubifs_tnc_get_bu_keys(struct ubifs_info *c, struct bu_info *bu) { diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 9999ff0aaa43..29dfa816077b 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -1428,7 +1428,7 @@ int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len, int ubifs_write_node(struct ubifs_info *c, void *node, int len, int lnum, int offs, int dtype); int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum, - int offs, int quiet, int chk_crc); + int offs, int quiet, int must_chk_crc); void ubifs_prepare_node(struct ubifs_info *c, void *buf, int len, int pad); void ubifs_prep_grp_node(struct ubifs_info *c, void *node, int len, int last); int ubifs_io_init(struct ubifs_info *c); From f0e0059b9c18426cffdcc04161062251a8f9741e Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Sun, 25 Jan 2009 20:53:00 -0600 Subject: [PATCH 013/111] don't reallocate sxp variable passed into xfs_swapext fixes kernel.org bugzilla 12538, xfs_fsr fails on 2.6.29-rc kernels Regression caused by 743bb4650da9e2595d6cedd01c680b5b9398c74a This was an embarrasing mistake, reallocating the sxp pointer passed in from the main ioctl switch. Signed-off-by: Eric Sandeen Tested-by: Paul Martin Reviewed-by: Felix Blyakher Signed-off-by: Felix Blyakher --- fs/xfs/xfs_dfrag.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c index b4c1ee713492..f8278cfcc1d3 100644 --- a/fs/xfs/xfs_dfrag.c +++ b/fs/xfs/xfs_dfrag.c @@ -55,17 +55,11 @@ xfs_swapext( struct file *file, *target_file; int error = 0; - sxp = kmem_alloc(sizeof(xfs_swapext_t), KM_MAYFAIL); - if (!sxp) { - error = XFS_ERROR(ENOMEM); - goto out; - } - /* Pull information for the target fd */ file = fget((int)sxp->sx_fdtarget); if (!file) { error = XFS_ERROR(EINVAL); - goto out_free_sxp; + goto out; } if (!(file->f_mode & FMODE_WRITE) || (file->f_flags & O_APPEND)) { @@ -109,8 +103,6 @@ xfs_swapext( fput(target_file); out_put_file: fput(file); - out_free_sxp: - kmem_free(sxp); out: return error; } From a71558d0eca1bbb23737f832297926666f9b36db Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 27 Jan 2009 22:32:29 +0000 Subject: [PATCH 014/111] [ARM] etherh: continue fixing build failure Further to 483a2b3a3182abcb7fcea986d7ea13e793bb00b1, also fix: drivers/net/arm/etherh.c:649: error: 'eth_set_mac_addr' undeclared here (not in a function) Signed-off-by: Russell King --- drivers/net/arm/etherh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c index d15d8b79d8e5..54b52e5b1821 100644 --- a/drivers/net/arm/etherh.c +++ b/drivers/net/arm/etherh.c @@ -646,7 +646,7 @@ static const struct net_device_ops etherh_netdev_ops = { .ndo_get_stats = ei_get_stats, .ndo_set_multicast_list = ei_set_multicast_list, .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = eth_set_mac_addr, + .ndo_set_mac_address = eth_mac_addr, .ndo_change_mtu = eth_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = ei_poll, From 9ce8bb55e32d11bb82e19e76bdd2cf1c2ed32fd1 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 27 Jan 2009 22:44:12 +0000 Subject: [PATCH 015/111] [ARM] msm: fix build errors arch/arm/mach-msm/board-halibut.c:45: error: implicit declaration of function 'MSM_GPIO_TO_INT' arch/arm/mach-msm/board-halibut.c:45: error: initializer element is not constant arch/arm/mach-msm/board-halibut.c:45: error: (near initialization for 'smc91x_resources[1].start') arch/arm/mach-msm/board-halibut.c:46: error: initializer element is not constant arch/arm/mach-msm/board-halibut.c:46: error: (near initialization for 'smc91x_resources[1].end') Signed-off-by: Russell King --- arch/arm/mach-msm/board-halibut.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-msm/board-halibut.c b/arch/arm/mach-msm/board-halibut.c index c2a96e3965a6..e61967dde9a1 100644 --- a/arch/arm/mach-msm/board-halibut.c +++ b/arch/arm/mach-msm/board-halibut.c @@ -27,6 +27,7 @@ #include #include +#include #include #include From ecbab71c521819716e204659dfe72fc39d00630a Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 27 Jan 2009 23:20:00 +0000 Subject: [PATCH 016/111] [ARM] call undefined instruction exception handler with irqs enabled Aaro says: > With spinlock debugs enabled I get might_sleep() warnings when using > ptrace. tracked down to a missing enable_irq before calling do_undefinstr(). Reported-by: Aaro Koskinen Tested-by: Aaro Koskinen Signed-off-by: Russell King --- arch/arm/kernel/entry-armv.S | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 77b047475539..85040cfeb5e5 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -650,6 +650,7 @@ ENTRY(fp_enter) no_fp: mov pc, lr __und_usr_unknown: + enable_irq mov r0, sp adr lr, ret_from_exception b do_undefinstr From 4a29d2005b0f28d018d36d209c47f3973a725df5 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 27 Jan 2009 15:22:54 +0200 Subject: [PATCH 017/111] UBIFS: fix LPT out-of-space bug (again) The function to traverse and dirty the LPT was still not dirtying all nodes, with the result that the LPT could run out of space. Signed-off-by: Adrian Hunter Signed-off-by: Artem Bityutskiy --- fs/ubifs/lpt_commit.c | 44 +++++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/fs/ubifs/lpt_commit.c b/fs/ubifs/lpt_commit.c index 96ca95707175..3216a1f277f8 100644 --- a/fs/ubifs/lpt_commit.c +++ b/fs/ubifs/lpt_commit.c @@ -556,23 +556,23 @@ static int write_cnodes(struct ubifs_info *c) } /** - * next_pnode - find next pnode. + * next_pnode_to_dirty - find next pnode to dirty. * @c: UBIFS file-system description object * @pnode: pnode * - * This function returns the next pnode or %NULL if there are no more pnodes. + * This function returns the next pnode to dirty or %NULL if there are no more + * pnodes. Note that pnodes that have never been written (lnum == 0) are + * skipped. */ -static struct ubifs_pnode *next_pnode(struct ubifs_info *c, - struct ubifs_pnode *pnode) +static struct ubifs_pnode *next_pnode_to_dirty(struct ubifs_info *c, + struct ubifs_pnode *pnode) { struct ubifs_nnode *nnode; int iip; /* Try to go right */ nnode = pnode->parent; - iip = pnode->iip + 1; - if (iip < UBIFS_LPT_FANOUT) { - /* We assume here that LEB zero is never an LPT LEB */ + for (iip = pnode->iip + 1; iip < UBIFS_LPT_FANOUT; iip++) { if (nnode->nbranch[iip].lnum) return ubifs_get_pnode(c, nnode, iip); } @@ -583,8 +583,11 @@ static struct ubifs_pnode *next_pnode(struct ubifs_info *c, nnode = nnode->parent; if (!nnode) return NULL; - /* We assume here that LEB zero is never an LPT LEB */ - } while (iip >= UBIFS_LPT_FANOUT || !nnode->nbranch[iip].lnum); + for (; iip < UBIFS_LPT_FANOUT; iip++) { + if (nnode->nbranch[iip].lnum) + break; + } + } while (iip >= UBIFS_LPT_FANOUT); /* Go right */ nnode = ubifs_get_nnode(c, nnode, iip); @@ -593,12 +596,29 @@ static struct ubifs_pnode *next_pnode(struct ubifs_info *c, /* Go down to level 1 */ while (nnode->level > 1) { - nnode = ubifs_get_nnode(c, nnode, 0); + for (iip = 0; iip < UBIFS_LPT_FANOUT; iip++) { + if (nnode->nbranch[iip].lnum) + break; + } + if (iip >= UBIFS_LPT_FANOUT) { + /* + * Should not happen, but we need to keep going + * if it does. + */ + iip = 0; + } + nnode = ubifs_get_nnode(c, nnode, iip); if (IS_ERR(nnode)) return (void *)nnode; } - return ubifs_get_pnode(c, nnode, 0); + for (iip = 0; iip < UBIFS_LPT_FANOUT; iip++) + if (nnode->nbranch[iip].lnum) + break; + if (iip >= UBIFS_LPT_FANOUT) + /* Should not happen, but we need to keep going if it does */ + iip = 0; + return ubifs_get_pnode(c, nnode, iip); } /** @@ -688,7 +708,7 @@ static int make_tree_dirty(struct ubifs_info *c) pnode = pnode_lookup(c, 0); while (pnode) { do_make_pnode_dirty(c, pnode); - pnode = next_pnode(c, pnode); + pnode = next_pnode_to_dirty(c, pnode); if (IS_ERR(pnode)) return PTR_ERR(pnode); } From 08e445bd6a98fa09befe0cf6d67705324f913fc6 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Fri, 16 Jan 2009 23:02:54 +0100 Subject: [PATCH 018/111] [ARM] 5366/1: fix shared memory coherency with VIVT L1 + L2 caches When there are multiple L1-aliasing userland mappings of the same physical page, we currently remap each of them uncached, to prevent VIVT cache aliasing issues. (E.g. writes to one of the mappings not being immediately visible via another mapping.) However, when we do this remapping, there could still be stale data in the L2 cache, and an uncached mapping might bypass L2 and go straight to RAM. This would cause reads from such mappings to see old data (until the dirty L2 line is eventually evicted.) This issue is solved by forcing a L2 cache flush whenever the shared page is made L1 uncacheable. Ideally, we would make L1 uncacheable and L2 cacheable as L2 is PIPT. But Feroceon does not support that combination, and the TEX=5 C=0 B=0 encoding for XSc3 doesn't appear to work in practice. Signed-off-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/mm/fault-armv.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c index 81d0b8772de3..bc0099d5ae85 100644 --- a/arch/arm/mm/fault-armv.c +++ b/arch/arm/mm/fault-armv.c @@ -66,7 +66,10 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address) * fault (ie, is old), we can safely ignore any issues. */ if (ret && (pte_val(entry) & L_PTE_MT_MASK) != shared_pte_mask) { - flush_cache_page(vma, address, pte_pfn(entry)); + unsigned long pfn = pte_pfn(entry); + flush_cache_page(vma, address, pfn); + outer_flush_range((pfn << PAGE_SHIFT), + (pfn << PAGE_SHIFT) + PAGE_SIZE); pte_val(entry) &= ~L_PTE_MT_MASK; pte_val(entry) |= shared_pte_mask; set_pte_at(vma->vm_mm, address, pte, entry); From 3eb8057bbafc64dbf09d5c18513aa80c1b7f2fcb Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 21 Jan 2009 21:30:23 -0800 Subject: [PATCH 019/111] sparc64: Move generic PCR support code to seperate file. It all lives in the oprofile support code currently and we will need to share this stuff with NMI watchdog and perf_counter support. Signed-off-by: David S. Miller --- arch/sparc/include/asm/pcr.h | 30 ++++++++ arch/sparc/include/asm/pil.h | 1 + arch/sparc/kernel/Makefile | 1 + arch/sparc/kernel/pcr.c | 140 +++++++++++++++++++++++++++++++++++ arch/sparc/kernel/ttable.S | 3 +- arch/sparc/oprofile/init.c | 110 +-------------------------- 6 files changed, 177 insertions(+), 108 deletions(-) create mode 100644 arch/sparc/include/asm/pcr.h create mode 100644 arch/sparc/kernel/pcr.c diff --git a/arch/sparc/include/asm/pcr.h b/arch/sparc/include/asm/pcr.h new file mode 100644 index 000000000000..4249bb523ef1 --- /dev/null +++ b/arch/sparc/include/asm/pcr.h @@ -0,0 +1,30 @@ +#ifndef __PCR_H +#define __PCR_H + +struct pcr_ops { + u64 (*read)(void); + void (*write)(u64); +}; +extern const struct pcr_ops *pcr_ops; + +extern void deferred_pcr_work_irq(int irq, struct pt_regs *regs); +extern void schedule_deferred_pcr_work(void); + +#define PCR_PIC_PRIV 0x00000001 /* PIC access is privileged */ +#define PCR_STRACE 0x00000002 /* Trace supervisor events */ +#define PCR_UTRACE 0x00000004 /* Trace user events */ +#define PCR_N2_HTRACE 0x00000008 /* Trace hypervisor events */ +#define PCR_N2_TOE_OV0 0x00000010 /* Trap if PIC 0 overflows */ +#define PCR_N2_TOE_OV1 0x00000020 /* Trap if PIC 1 overflows */ +#define PCR_N2_MASK0 0x00003fc0 +#define PCR_N2_MASK0_SHIFT 6 +#define PCR_N2_SL0 0x0003c000 +#define PCR_N2_SL0_SHIFT 14 +#define PCR_N2_OV0 0x00040000 +#define PCR_N2_MASK1 0x07f80000 +#define PCR_N2_MASK1_SHIFT 19 +#define PCR_N2_SL1 0x78000000 +#define PCR_N2_SL1_SHIFT 27 +#define PCR_N2_OV1 0x80000000 + +#endif /* __PCR_H */ diff --git a/arch/sparc/include/asm/pil.h b/arch/sparc/include/asm/pil.h index d573820c0ff4..32a7efe76d00 100644 --- a/arch/sparc/include/asm/pil.h +++ b/arch/sparc/include/asm/pil.h @@ -23,6 +23,7 @@ #define PIL_SMP_CTX_NEW_VERSION 4 #define PIL_DEVICE_IRQ 5 #define PIL_SMP_CALL_FUNC_SNGL 6 +#define PIL_DEFERRED_PCR_WORK 7 #define PIL_NORMAL_MAX 14 #define PIL_NMI 15 diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index 53adcaa0348b..cb182d9c2f2b 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -52,6 +52,7 @@ obj-$(CONFIG_SPARC64) += visemul.o obj-$(CONFIG_SPARC64) += hvapi.o obj-$(CONFIG_SPARC64) += sstate.o obj-$(CONFIG_SPARC64) += mdesc.o +obj-$(CONFIG_SPARC64) += pcr.o # sparc32 do not use GENERIC_HARDIRQS but uses the generic devres implementation obj-$(CONFIG_SPARC32) += devres.o diff --git a/arch/sparc/kernel/pcr.c b/arch/sparc/kernel/pcr.c new file mode 100644 index 000000000000..c4f24703b165 --- /dev/null +++ b/arch/sparc/kernel/pcr.c @@ -0,0 +1,140 @@ +/* pcr.c: Generic sparc64 performance counter infrastructure. + * + * Copyright (C) 2009 David S. Miller (davem@davemloft.net) + */ +#include +#include +#include +#include + +#include +#include + +/* This code is shared between various users of the performance + * counters. Users will be oprofile, pseudo-NMI watchdog, and the + * perf_counter support layer. + */ + +/* Performance counter interrupts run unmasked at PIL level 15. + * Therefore we can't do things like wakeups and other work + * that expects IRQ disabling to be adhered to in locking etc. + * + * Therefore in such situations we defer the work by signalling + * a lower level cpu IRQ. + */ +void deferred_pcr_work_irq(int irq, struct pt_regs *regs) +{ + clear_softint(1 << PIL_DEFERRED_PCR_WORK); +} + +void schedule_deferred_pcr_work(void) +{ + set_softint(1 << PIL_DEFERRED_PCR_WORK); +} + +const struct pcr_ops *pcr_ops; +EXPORT_SYMBOL_GPL(pcr_ops); + +static u64 direct_pcr_read(void) +{ + u64 val; + + read_pcr(val); + return val; +} + +static void direct_pcr_write(u64 val) +{ + write_pcr(val); +} + +static const struct pcr_ops direct_pcr_ops = { + .read = direct_pcr_read, + .write = direct_pcr_write, +}; + +static void n2_pcr_write(u64 val) +{ + unsigned long ret; + + ret = sun4v_niagara2_setperf(HV_N2_PERF_SPARC_CTL, val); + if (val != HV_EOK) + write_pcr(val); +} + +static const struct pcr_ops n2_pcr_ops = { + .read = direct_pcr_read, + .write = n2_pcr_write, +}; + +static unsigned long perf_hsvc_group; +static unsigned long perf_hsvc_major; +static unsigned long perf_hsvc_minor; + +static int __init register_perf_hsvc(void) +{ + if (tlb_type == hypervisor) { + switch (sun4v_chip_type) { + case SUN4V_CHIP_NIAGARA1: + perf_hsvc_group = HV_GRP_NIAG_PERF; + break; + + case SUN4V_CHIP_NIAGARA2: + perf_hsvc_group = HV_GRP_N2_CPU; + break; + + default: + return -ENODEV; + } + + + perf_hsvc_major = 1; + perf_hsvc_minor = 0; + if (sun4v_hvapi_register(perf_hsvc_group, + perf_hsvc_major, + &perf_hsvc_minor)) { + printk("perfmon: Could not register hvapi.\n"); + return -ENODEV; + } + } + return 0; +} + +static void __init unregister_perf_hsvc(void) +{ + if (tlb_type != hypervisor) + return; + sun4v_hvapi_unregister(perf_hsvc_group); +} + +int __init pcr_arch_init(void) +{ + int err = register_perf_hsvc(); + + if (err) + return err; + + switch (tlb_type) { + case hypervisor: + pcr_ops = &n2_pcr_ops; + break; + + case spitfire: + case cheetah: + case cheetah_plus: + pcr_ops = &direct_pcr_ops; + break; + + default: + err = -ENODEV; + goto out_unregister; + } + + return 0; + +out_unregister: + unregister_perf_hsvc(); + return err; +} + +arch_initcall(pcr_arch_init); diff --git a/arch/sparc/kernel/ttable.S b/arch/sparc/kernel/ttable.S index ea925503b42e..d9bdfb9d5c18 100644 --- a/arch/sparc/kernel/ttable.S +++ b/arch/sparc/kernel/ttable.S @@ -63,7 +63,8 @@ tl0_irq6: TRAP_IRQ(smp_call_function_single_client, 6) #else tl0_irq6: BTRAP(0x46) #endif -tl0_irq7: BTRAP(0x47) BTRAP(0x48) BTRAP(0x49) +tl0_irq7: TRAP_IRQ(deferred_pcr_work_irq, 7) +tl0_irq8: BTRAP(0x48) BTRAP(0x49) tl0_irq10: BTRAP(0x4a) BTRAP(0x4b) BTRAP(0x4c) BTRAP(0x4d) tl0_irq14: TRAP_IRQ(timer_interrupt, 14) tl0_irq15: TRAP_NMI_IRQ(perfctr_irq, 15) diff --git a/arch/sparc/oprofile/init.c b/arch/sparc/oprofile/init.c index d6e170c074fc..c8877a5202b0 100644 --- a/arch/sparc/oprofile/init.c +++ b/arch/sparc/oprofile/init.c @@ -17,47 +17,10 @@ #include #include #include +#include static int nmi_enabled; -struct pcr_ops { - u64 (*read)(void); - void (*write)(u64); -}; -static const struct pcr_ops *pcr_ops; - -static u64 direct_pcr_read(void) -{ - u64 val; - - read_pcr(val); - return val; -} - -static void direct_pcr_write(u64 val) -{ - write_pcr(val); -} - -static const struct pcr_ops direct_pcr_ops = { - .read = direct_pcr_read, - .write = direct_pcr_write, -}; - -static void n2_pcr_write(u64 val) -{ - unsigned long ret; - - ret = sun4v_niagara2_setperf(HV_N2_PERF_SPARC_CTL, val); - if (val != HV_EOK) - write_pcr(val); -} - -static const struct pcr_ops n2_pcr_ops = { - .read = direct_pcr_read, - .write = n2_pcr_write, -}; - /* In order to commonize as much of the implementation as * possible, we use PICH as our counter. Mostly this is * to accomodate Niagara-1 which can only count insn cycles @@ -70,30 +33,13 @@ static u64 picl_value(void) return ((u64)((0 - delta) & 0xffffffff)) << 32; } -#define PCR_PIC_PRIV 0x00000001 /* PIC access is privileged */ -#define PCR_STRACE 0x00000002 /* Trace supervisor events */ -#define PCR_UTRACE 0x00000004 /* Trace user events */ -#define PCR_N2_HTRACE 0x00000008 /* Trace hypervisor events */ -#define PCR_N2_TOE_OV0 0x00000010 /* Trap if PIC 0 overflows */ -#define PCR_N2_TOE_OV1 0x00000020 /* Trap if PIC 1 overflows */ -#define PCR_N2_MASK0 0x00003fc0 -#define PCR_N2_MASK0_SHIFT 6 -#define PCR_N2_SL0 0x0003c000 -#define PCR_N2_SL0_SHIFT 14 -#define PCR_N2_OV0 0x00040000 -#define PCR_N2_MASK1 0x07f80000 -#define PCR_N2_MASK1_SHIFT 19 -#define PCR_N2_SL1 0x78000000 -#define PCR_N2_SL1_SHIFT 27 -#define PCR_N2_OV1 0x80000000 - #define PCR_SUN4U_ENABLE (PCR_PIC_PRIV | PCR_STRACE | PCR_UTRACE) #define PCR_N2_ENABLE (PCR_PIC_PRIV | PCR_STRACE | PCR_UTRACE | \ PCR_N2_TOE_OV1 | \ (2 << PCR_N2_SL1_SHIFT) | \ (0xff << PCR_N2_MASK1_SHIFT)) -static u64 pcr_enable = PCR_SUN4U_ENABLE; +static u64 pcr_enable; static void nmi_handler(struct pt_regs *regs) { @@ -153,62 +99,16 @@ static void nmi_stop(void) synchronize_sched(); } -static unsigned long perf_hsvc_group; -static unsigned long perf_hsvc_major; -static unsigned long perf_hsvc_minor; - -static int __init register_perf_hsvc(void) -{ - if (tlb_type == hypervisor) { - switch (sun4v_chip_type) { - case SUN4V_CHIP_NIAGARA1: - perf_hsvc_group = HV_GRP_NIAG_PERF; - break; - - case SUN4V_CHIP_NIAGARA2: - perf_hsvc_group = HV_GRP_N2_CPU; - break; - - default: - return -ENODEV; - } - - - perf_hsvc_major = 1; - perf_hsvc_minor = 0; - if (sun4v_hvapi_register(perf_hsvc_group, - perf_hsvc_major, - &perf_hsvc_minor)) { - printk("perfmon: Could not register N2 hvapi.\n"); - return -ENODEV; - } - } - return 0; -} - -static void unregister_perf_hsvc(void) -{ - if (tlb_type != hypervisor) - return; - sun4v_hvapi_unregister(perf_hsvc_group); -} - static int oprofile_nmi_init(struct oprofile_operations *ops) { - int err = register_perf_hsvc(); - - if (err) - return err; - switch (tlb_type) { case hypervisor: - pcr_ops = &n2_pcr_ops; pcr_enable = PCR_N2_ENABLE; break; case cheetah: case cheetah_plus: - pcr_ops = &direct_pcr_ops; + pcr_enable = PCR_SUN4U_ENABLE; break; default: @@ -241,10 +141,6 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) return ret; } - void oprofile_arch_exit(void) { -#ifdef CONFIG_SPARC64 - unregister_perf_hsvc(); -#endif } From c3cf5e8cc56d272f828a66610bb78bbb727b2ce1 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 21 Jan 2009 23:16:40 -0800 Subject: [PATCH 020/111] sparc: Probe PMU type and record in sparc_pmu_type. Signed-off-by: David S. Miller --- arch/sparc/kernel/cpu.c | 33 ++++++++++++++++++++++----------- arch/sparc/kernel/kernel.h | 1 + arch/sparc/kernel/setup_64.c | 2 ++ 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/arch/sparc/kernel/cpu.c b/arch/sparc/kernel/cpu.c index 32d32b4824f5..d85c3dc4953a 100644 --- a/arch/sparc/kernel/cpu.c +++ b/arch/sparc/kernel/cpu.c @@ -26,6 +26,7 @@ EXPORT_PER_CPU_SYMBOL(__cpu_data); struct cpu_info { int psr_vers; const char *name; + const char *pmu_name; }; struct fpu_info { @@ -45,6 +46,9 @@ struct manufacturer_info { #define CPU(ver, _name) \ { .psr_vers = ver, .name = _name } +#define CPU_PMU(ver, _name, _pmu_name) \ +{ .psr_vers = ver, .name = _name, .pmu_name = _pmu_name } + #define FPU(ver, _name) \ { .fp_vers = ver, .name = _name } @@ -183,10 +187,10 @@ static const struct manufacturer_info __initconst manufacturer_info[] = { },{ 0x17, .cpu_info = { - CPU(0x10, "TI UltraSparc I (SpitFire)"), - CPU(0x11, "TI UltraSparc II (BlackBird)"), - CPU(0x12, "TI UltraSparc IIi (Sabre)"), - CPU(0x13, "TI UltraSparc IIe (Hummingbird)"), + CPU_PMU(0x10, "TI UltraSparc I (SpitFire)", "ultra12"), + CPU_PMU(0x11, "TI UltraSparc II (BlackBird)", "ultra12"), + CPU_PMU(0x12, "TI UltraSparc IIi (Sabre)", "ultra12"), + CPU_PMU(0x13, "TI UltraSparc IIe (Hummingbird)", "ultra12"), CPU(-1, NULL) }, .fpu_info = { @@ -199,7 +203,7 @@ static const struct manufacturer_info __initconst manufacturer_info[] = { },{ 0x22, .cpu_info = { - CPU(0x10, "TI UltraSparc I (SpitFire)"), + CPU_PMU(0x10, "TI UltraSparc I (SpitFire)", "ultra12"), CPU(-1, NULL) }, .fpu_info = { @@ -209,12 +213,12 @@ static const struct manufacturer_info __initconst manufacturer_info[] = { },{ 0x3e, .cpu_info = { - CPU(0x14, "TI UltraSparc III (Cheetah)"), - CPU(0x15, "TI UltraSparc III+ (Cheetah+)"), - CPU(0x16, "TI UltraSparc IIIi (Jalapeno)"), - CPU(0x18, "TI UltraSparc IV (Jaguar)"), - CPU(0x19, "TI UltraSparc IV+ (Panther)"), - CPU(0x22, "TI UltraSparc IIIi+ (Serrano)"), + CPU_PMU(0x14, "TI UltraSparc III (Cheetah)", "ultra3"), + CPU_PMU(0x15, "TI UltraSparc III+ (Cheetah+)", "ultra3+"), + CPU_PMU(0x16, "TI UltraSparc IIIi (Jalapeno)", "ultra3i"), + CPU_PMU(0x18, "TI UltraSparc IV (Jaguar)", "ultra3+"), + CPU_PMU(0x19, "TI UltraSparc IV+ (Panther)", "ultra4+"), + CPU_PMU(0x22, "TI UltraSparc IIIi+ (Serrano)", "ultra3i"), CPU(-1, NULL) }, .fpu_info = { @@ -234,6 +238,7 @@ static const struct manufacturer_info __initconst manufacturer_info[] = { const char *sparc_cpu_type; const char *sparc_fpu_type; +const char *sparc_pmu_type; unsigned int fsr_storage; @@ -244,6 +249,7 @@ static void set_cpu_and_fpu(int psr_impl, int psr_vers, int fpu_vers) sparc_cpu_type = NULL; sparc_fpu_type = NULL; + sparc_pmu_type = NULL; manuf = NULL; for (i = 0; i < ARRAY_SIZE(manufacturer_info); i++) @@ -263,6 +269,7 @@ static void set_cpu_and_fpu(int psr_impl, int psr_vers, int fpu_vers) { if (cpu->psr_vers == psr_vers) { sparc_cpu_type = cpu->name; + sparc_pmu_type = cpu->pmu_name; sparc_fpu_type = "No FPU"; break; } @@ -290,6 +297,8 @@ static void set_cpu_and_fpu(int psr_impl, int psr_vers, int fpu_vers) psr_impl, fpu_vers); sparc_fpu_type = "Unknown FPU"; } + if (sparc_pmu_type == NULL) + sparc_pmu_type = "Unknown PMU"; } #ifdef CONFIG_SPARC32 @@ -315,11 +324,13 @@ static void __init sun4v_cpu_probe(void) case SUN4V_CHIP_NIAGARA1: sparc_cpu_type = "UltraSparc T1 (Niagara)"; sparc_fpu_type = "UltraSparc T1 integrated FPU"; + sparc_pmu_type = "niagara"; break; case SUN4V_CHIP_NIAGARA2: sparc_cpu_type = "UltraSparc T2 (Niagara2)"; sparc_fpu_type = "UltraSparc T2 integrated FPU"; + sparc_pmu_type = "niagara2"; break; default: diff --git a/arch/sparc/kernel/kernel.h b/arch/sparc/kernel/kernel.h index 81a972e8d8ea..15d8a3f645c9 100644 --- a/arch/sparc/kernel/kernel.h +++ b/arch/sparc/kernel/kernel.h @@ -5,6 +5,7 @@ /* cpu.c */ extern const char *sparc_cpu_type; +extern const char *sparc_pmu_type; extern const char *sparc_fpu_type; extern unsigned int fsr_storage; diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c index 49d061f4ae9d..f2bcfd2967d7 100644 --- a/arch/sparc/kernel/setup_64.c +++ b/arch/sparc/kernel/setup_64.c @@ -354,6 +354,7 @@ static int show_cpuinfo(struct seq_file *m, void *__unused) seq_printf(m, "cpu\t\t: %s\n" "fpu\t\t: %s\n" + "pmu\t\t: %s\n" "prom\t\t: %s\n" "type\t\t: %s\n" "ncpus probed\t: %d\n" @@ -366,6 +367,7 @@ static int show_cpuinfo(struct seq_file *m, void *__unused) , sparc_cpu_type, sparc_fpu_type, + sparc_pmu_type, prom_version, ((tlb_type == hypervisor) ? "sun4v" : From 3eb14297c4b85af0c5e6605e18d93b6031330d71 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 29 Jan 2009 11:17:24 +0200 Subject: [PATCH 021/111] UBIFS: sync wbufs after syncing inodes and pages All writes go through wbufs so they must be sync'd after syncing inodes and pages. Signed-off-by: Adrian Hunter Signed-off-by: Artem Bityutskiy --- fs/ubifs/super.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index dbfc88714716..3ddd754262b4 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -450,16 +450,6 @@ static int ubifs_sync_fs(struct super_block *sb, int wait) if (sb->s_flags & MS_RDONLY) return 0; - /* - * Synchronize write buffers, because 'ubifs_run_commit()' does not - * do this if it waits for an already running commit. - */ - for (i = 0; i < c->jhead_cnt; i++) { - err = ubifs_wbuf_sync(&c->jheads[i].wbuf); - if (err) - return err; - } - /* * VFS calls '->sync_fs()' before synchronizing all dirty inodes and * pages, so synchronize them first, then commit the journal. Strictly @@ -471,6 +461,16 @@ static int ubifs_sync_fs(struct super_block *sb, int wait) */ generic_sync_sb_inodes(sb, &wbc); + /* + * Synchronize write buffers, because 'ubifs_run_commit()' does not + * do this if it waits for an already running commit. + */ + for (i = 0; i < c->jhead_cnt; i++) { + err = ubifs_wbuf_sync(&c->jheads[i].wbuf); + if (err) + return err; + } + err = ubifs_run_commit(c); if (err) return err; From 227c75c91dbfa037d109ab7ef45b7f5ba9cab6d0 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 29 Jan 2009 11:53:51 +0200 Subject: [PATCH 022/111] UBIFS: spelling fix 'date' -> 'data' Signed-off-by: Adrian Hunter Signed-off-by: Artem Bityutskiy --- fs/ubifs/debug.c | 2 +- fs/ubifs/gc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index 9a41f6f245b7..e975bd82f38b 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -1407,7 +1407,7 @@ int dbg_check_tnc(struct ubifs_info *c, int extra) * @c: UBIFS file-system description object * @leaf_cb: called for each leaf node * @znode_cb: called for each indexing node - * @priv: private date which is passed to callbacks + * @priv: private data which is passed to callbacks * * This function walks the UBIFS index and calls the @leaf_cb for each leaf * node and @znode_cb for each indexing node. Returns zero in case of success diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c index 9760154d874b..bad3339a800d 100644 --- a/fs/ubifs/gc.c +++ b/fs/ubifs/gc.c @@ -401,7 +401,7 @@ int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp) /* * Don't release the LEB until after the next commit, because - * it may contain date which is needed for recovery. So + * it may contain data which is needed for recovery. So * although we freed this LEB, it will become usable only after * the commit. */ From b466f17d780c5b72427f36aef22ecdec9f1d0689 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 29 Jan 2009 12:59:33 +0200 Subject: [PATCH 023/111] UBIFS: remount ro fixes - preserve the idx_gc list - it will be needed in the same state, should UBIFS be remounted rw again - prevent remounting ro if we have switched to read only mode (due to a fatal error) Signed-off-by: Adrian Hunter Signed-off-by: Artem Bityutskiy --- fs/ubifs/gc.c | 18 +++++------------- fs/ubifs/super.c | 14 +++++++------- fs/ubifs/ubifs.h | 2 +- 3 files changed, 13 insertions(+), 21 deletions(-) diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c index bad3339a800d..a711d33b3d3e 100644 --- a/fs/ubifs/gc.c +++ b/fs/ubifs/gc.c @@ -830,29 +830,21 @@ int ubifs_gc_end_commit(struct ubifs_info *c) * ubifs_destroy_idx_gc - destroy idx_gc list. * @c: UBIFS file-system description object * - * This function destroys the @c->idx_gc list. It is called when unmounting or - * remounting read-only so locks are not needed. Returns zero in case of - * success and a negative error code in case of failure. + * This function destroys the @c->idx_gc list. It is called when unmounting + * so locks are not needed. Returns zero in case of success and a negative + * error code in case of failure. */ -int ubifs_destroy_idx_gc(struct ubifs_info *c) +void ubifs_destroy_idx_gc(struct ubifs_info *c) { - int ret = 0; - while (!list_empty(&c->idx_gc)) { - int err; struct ubifs_gced_idx_leb *idx_gc; idx_gc = list_entry(c->idx_gc.next, struct ubifs_gced_idx_leb, list); - err = ubifs_change_one_lp(c, idx_gc->lnum, LPROPS_NC, - LPROPS_NC, 0, LPROPS_TAKEN, -1); - if (err && !ret) - ret = err; + c->idx_gc_cnt -= 1; list_del(&idx_gc->list); kfree(idx_gc); } - - return ret; } /** diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 3ddd754262b4..daa679d3a03e 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1687,10 +1687,6 @@ static void ubifs_remount_ro(struct ubifs_info *c) if (err) ubifs_ro_mode(c, err); - err = ubifs_destroy_idx_gc(c); - if (err) - ubifs_ro_mode(c, err); - free_wbufs(c); vfree(c->orph_buf); c->orph_buf = NULL; @@ -1793,15 +1789,19 @@ static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data) if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) { if (c->ro_media) { - ubifs_msg("cannot re-mount R/W, UBIFS is working in " - "R/O mode"); + ubifs_msg("cannot re-mount due to prior errors"); return -EINVAL; } err = ubifs_remount_rw(c); if (err) return err; - } else if (!(sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY)) + } else if (!(sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY)) { + if (c->ro_media) { + ubifs_msg("cannot re-mount due to prior errors"); + return -EINVAL; + } ubifs_remount_ro(c); + } if (c->bulk_read == 1) bu_init(c); diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 29dfa816077b..535f87426791 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -1594,7 +1594,7 @@ int ubifs_replay_journal(struct ubifs_info *c); int ubifs_garbage_collect(struct ubifs_info *c, int anyway); int ubifs_gc_start_commit(struct ubifs_info *c); int ubifs_gc_end_commit(struct ubifs_info *c); -int ubifs_destroy_idx_gc(struct ubifs_info *c); +void ubifs_destroy_idx_gc(struct ubifs_info *c); int ubifs_get_idx_gc_leb(struct ubifs_info *c); int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp); From a2b9df3ff691db8e5e521dccd231a8098bbf7416 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Thu, 29 Jan 2009 16:22:54 +0200 Subject: [PATCH 024/111] UBIFS: return sensible error codes When mounting/re-mounting, UBIFS returns EINVAL even if the ENOSPC or EROFS codes are are much better, just because we have not found references to ENOSPC/EROFS in mount (2) man pages. This patch changes this behaviour and makes UBIFS return real error code, because: 1. It is just less confusing and more logical 2. mount is not described in SuSv3, so it seems to be not really well-standartized 3. we do not cover all cases, and any random undocumented in man pages error code may be returned anyway Signed-off-by: Artem Bityutskiy --- fs/ubifs/master.c | 2 +- fs/ubifs/super.c | 11 +++-------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/fs/ubifs/master.c b/fs/ubifs/master.c index 71d5493bf565..a88f33801b98 100644 --- a/fs/ubifs/master.c +++ b/fs/ubifs/master.c @@ -354,7 +354,7 @@ int ubifs_write_master(struct ubifs_info *c) int err, lnum, offs, len; if (c->ro_media) - return -EINVAL; + return -EROFS; lnum = UBIFS_MST_LNUM; offs = c->mst_offs + c->mst_node_alsz; diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index daa679d3a03e..ab85eb8cce79 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1085,12 +1085,7 @@ static int check_free_space(struct ubifs_info *c) ubifs_err("insufficient free space to mount in read/write mode"); dbg_dump_budg(c); dbg_dump_lprops(c); - /* - * We return %-EINVAL instead of %-ENOSPC because it seems to - * be the closest error code mentioned in the mount function - * documentation. - */ - return -EINVAL; + return -ENOSPC; } return 0; } @@ -1790,7 +1785,7 @@ static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data) if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) { if (c->ro_media) { ubifs_msg("cannot re-mount due to prior errors"); - return -EINVAL; + return -EROFS; } err = ubifs_remount_rw(c); if (err) @@ -1798,7 +1793,7 @@ static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data) } else if (!(sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY)) { if (c->ro_media) { ubifs_msg("cannot re-mount due to prior errors"); - return -EINVAL; + return -EROFS; } ubifs_remount_ro(c); } From 27ad27993313312a4ad0047d0a944c425cd511a5 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Thu, 29 Jan 2009 16:34:30 +0200 Subject: [PATCH 025/111] UBIFS: remove fast unmounting This UBIFS feature has never worked properly, and it was a mistake to add it because we simply have no use-cases. So, lets still accept the fast_unmount mount option, but ignore it. This does not change much, because UBIFS commit in sync_fs anyway, and sync_fs is called while unmounting. Signed-off-by: Artem Bityutskiy --- Documentation/filesystems/ubifs.txt | 7 ---- fs/ubifs/super.c | 50 +++-------------------------- fs/ubifs/ubifs.h | 2 -- 3 files changed, 5 insertions(+), 54 deletions(-) diff --git a/Documentation/filesystems/ubifs.txt b/Documentation/filesystems/ubifs.txt index 84da2a4ba25a..12fedb7834c6 100644 --- a/Documentation/filesystems/ubifs.txt +++ b/Documentation/filesystems/ubifs.txt @@ -79,13 +79,6 @@ Mount options (*) == default. -norm_unmount (*) commit on unmount; the journal is committed - when the file-system is unmounted so that the - next mount does not have to replay the journal - and it becomes very fast; -fast_unmount do not commit on unmount; this option makes - unmount faster, but the next mount slower - because of the need to replay the journal. bulk_read read more in one go to take advantage of flash media that read faster sequentially no_bulk_read (*) do not bulk-read diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index ab85eb8cce79..1182b66a5491 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -957,13 +957,16 @@ static int ubifs_parse_options(struct ubifs_info *c, char *options, token = match_token(p, tokens, args); switch (token) { + /* + * %Opt_fast_unmount and %Opt_norm_unmount options are ignored. + * We accepte them in order to be backware-compatible. But this + * should be removed at some point. + */ case Opt_fast_unmount: c->mount_opts.unmount_mode = 2; - c->fast_unmount = 1; break; case Opt_norm_unmount: c->mount_opts.unmount_mode = 1; - c->fast_unmount = 0; break; case Opt_bulk_read: c->mount_opts.bulk_read = 2; @@ -1359,7 +1362,6 @@ static int mount_ubifs(struct ubifs_info *c) c->uuid[4], c->uuid[5], c->uuid[6], c->uuid[7], c->uuid[8], c->uuid[9], c->uuid[10], c->uuid[11], c->uuid[12], c->uuid[13], c->uuid[14], c->uuid[15]); - dbg_msg("fast unmount: %d", c->fast_unmount); dbg_msg("big_lpt %d", c->big_lpt); dbg_msg("log LEBs: %d (%d - %d)", c->log_lebs, UBIFS_LOG_LNUM, c->log_last); @@ -1615,38 +1617,6 @@ static int ubifs_remount_rw(struct ubifs_info *c) return err; } -/** - * commit_on_unmount - commit the journal when un-mounting. - * @c: UBIFS file-system description object - * - * This function is called during un-mounting and re-mounting, and it commits - * the journal unless the "fast unmount" mode is enabled. - */ -static void commit_on_unmount(struct ubifs_info *c) -{ - long long bud_bytes; - - if (!c->fast_unmount) { - dbg_gen("skip committing - fast unmount enabled"); - return; - } - - /* - * This function is called before the background thread is stopped, so - * we may race with ongoing commit, which means we have to take - * @c->bud_lock to access @c->bud_bytes. - */ - spin_lock(&c->buds_lock); - bud_bytes = c->bud_bytes; - spin_unlock(&c->buds_lock); - - if (bud_bytes) { - dbg_gen("run commit"); - ubifs_run_commit(c); - } else - dbg_gen("journal is empty, do not run commit"); -} - /** * ubifs_remount_ro - re-mount in read-only mode. * @c: UBIFS file-system description object @@ -1661,7 +1631,6 @@ static void ubifs_remount_ro(struct ubifs_info *c) ubifs_assert(!c->need_recovery); ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY)); - commit_on_unmount(c); mutex_lock(&c->umount_mutex); if (c->bgt) { kthread_stop(c->bgt); @@ -2077,15 +2046,6 @@ static int ubifs_get_sb(struct file_system_type *fs_type, int flags, static void ubifs_kill_sb(struct super_block *sb) { - struct ubifs_info *c = sb->s_fs_info; - - /* - * We do 'commit_on_unmount()' here instead of 'ubifs_put_super()' - * in order to be outside BKL. - */ - if (sb->s_root && !(sb->s_flags & MS_RDONLY)) - commit_on_unmount(c); - /* The un-mount routine is actually done in put_super() */ generic_shutdown_super(sb); } diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 535f87426791..039a68bee29a 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -961,7 +961,6 @@ struct ubifs_debug_info; * @cs_lock: commit state lock * @cmt_wq: wait queue to sleep on if the log is full and a commit is running * - * @fast_unmount: do not run journal commit before un-mounting * @big_lpt: flag that LPT is too big to write whole during commit * @no_chk_data_crc: do not check CRCs when reading data nodes (except during * recovery) @@ -1202,7 +1201,6 @@ struct ubifs_info { spinlock_t cs_lock; wait_queue_head_t cmt_wq; - unsigned int fast_unmount:1; unsigned int big_lpt:1; unsigned int no_chk_data_crc:1; unsigned int bulk_read:1; From 06151158f2da4764479b4ec01688dc4bade6ce9d Mon Sep 17 00:00:00 2001 From: "Stanley.Miao" Date: Thu, 29 Jan 2009 08:57:12 -0800 Subject: [PATCH 026/111] ARM: OMAP: Fix McBSP spin_lock deadlock A spin_lock deadlock will occur when omap_mcbsp_request() is invoked. omap_mcbsp_request() \- clk_enable(mcbsp->clk) [takes and holds clockfw_lock] \- omap2_clk_enable() \- _omap2_clk_enable() \- omap_mcbsp_clk_enable() \- clk_enable(child clock) [tries for clockfw_lock again] mcbsp_clk is a virtual clock and it comprises several child clocks. when enable mcbsp_clk in omap_mcbsp_request(), the enable function of mcbsp_clk will enable its child clocks, then the deadlock occurs. The solution is to remove the virtual clock and enable these child clocks in omap_mcbsp_request() directly. Signed-off-by: Stanley.Miao Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/mcbsp.c | 98 ++-------------- arch/arm/mach-omap2/mcbsp.c | 145 ++++-------------------- arch/arm/plat-omap/include/mach/mcbsp.h | 6 +- arch/arm/plat-omap/mcbsp.c | 52 ++++++--- 4 files changed, 78 insertions(+), 223 deletions(-) diff --git a/arch/arm/mach-omap1/mcbsp.c b/arch/arm/mach-omap1/mcbsp.c index ca7a0cc1707c..575ba31295cf 100644 --- a/arch/arm/mach-omap1/mcbsp.c +++ b/arch/arm/mach-omap1/mcbsp.c @@ -28,81 +28,8 @@ #define DPS_RSTCT2_PER_EN (1 << 0) #define DSP_RSTCT2_WD_PER_EN (1 << 1) -struct mcbsp_internal_clk { - struct clk clk; - struct clk **childs; - int n_childs; -}; - #if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) -static void omap_mcbsp_clk_init(struct mcbsp_internal_clk *mclk) -{ - const char *clk_names[] = { "dsp_ck", "api_ck", "dspxor_ck" }; - int i; - - mclk->n_childs = ARRAY_SIZE(clk_names); - mclk->childs = kzalloc(mclk->n_childs * sizeof(struct clk *), - GFP_KERNEL); - - for (i = 0; i < mclk->n_childs; i++) { - /* We fake a platform device to get correct device id */ - struct platform_device pdev; - - pdev.dev.bus = &platform_bus_type; - pdev.id = mclk->clk.id; - mclk->childs[i] = clk_get(&pdev.dev, clk_names[i]); - if (IS_ERR(mclk->childs[i])) - printk(KERN_ERR "Could not get clock %s (%d).\n", - clk_names[i], mclk->clk.id); - } -} - -static int omap_mcbsp_clk_enable(struct clk *clk) -{ - struct mcbsp_internal_clk *mclk = container_of(clk, - struct mcbsp_internal_clk, clk); - int i; - - for (i = 0; i < mclk->n_childs; i++) - clk_enable(mclk->childs[i]); - return 0; -} - -static void omap_mcbsp_clk_disable(struct clk *clk) -{ - struct mcbsp_internal_clk *mclk = container_of(clk, - struct mcbsp_internal_clk, clk); - int i; - - for (i = 0; i < mclk->n_childs; i++) - clk_disable(mclk->childs[i]); -} - -static struct mcbsp_internal_clk omap_mcbsp_clks[] = { - { - .clk = { - .name = "mcbsp_clk", - .id = 1, - .enable = omap_mcbsp_clk_enable, - .disable = omap_mcbsp_clk_disable, - }, - }, - { - .clk = { - .name = "mcbsp_clk", - .id = 3, - .enable = omap_mcbsp_clk_enable, - .disable = omap_mcbsp_clk_disable, - }, - }, -}; - -#define omap_mcbsp_clks_size ARRAY_SIZE(omap_mcbsp_clks) -#else -#define omap_mcbsp_clks_size 0 -static struct mcbsp_internal_clk __initdata *omap_mcbsp_clks; -static inline void omap_mcbsp_clk_init(struct mcbsp_internal_clk *mclk) -{ } +const char *clk_names[] = { "dsp_ck", "api_ck", "dspxor_ck" }; #endif static void omap1_mcbsp_request(unsigned int id) @@ -167,8 +94,9 @@ static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = { .rx_irq = INT_McBSP1RX, .tx_irq = INT_McBSP1TX, .ops = &omap1_mcbsp_ops, - .clk_name = "mcbsp_clk", - }, + .clk_names = clk_names, + .num_clks = 3, + }, { .phys_base = OMAP1510_MCBSP2_BASE, .dma_rx_sync = OMAP_DMA_MCBSP2_RX, @@ -184,7 +112,8 @@ static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = { .rx_irq = INT_McBSP3RX, .tx_irq = INT_McBSP3TX, .ops = &omap1_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 3, }, }; #define OMAP15XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap15xx_mcbsp_pdata) @@ -202,7 +131,8 @@ static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = { .rx_irq = INT_McBSP1RX, .tx_irq = INT_McBSP1TX, .ops = &omap1_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 3, }, { .phys_base = OMAP1610_MCBSP2_BASE, @@ -219,7 +149,8 @@ static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = { .rx_irq = INT_McBSP3RX, .tx_irq = INT_McBSP3TX, .ops = &omap1_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 3, }, }; #define OMAP16XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap16xx_mcbsp_pdata) @@ -230,15 +161,6 @@ static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = { int __init omap1_mcbsp_init(void) { - int i; - - for (i = 0; i < omap_mcbsp_clks_size; i++) { - if (cpu_is_omap15xx() || cpu_is_omap16xx()) { - omap_mcbsp_clk_init(&omap_mcbsp_clks[i]); - clk_register(&omap_mcbsp_clks[i].clk); - } - } - if (cpu_is_omap730()) omap_mcbsp_count = OMAP730_MCBSP_PDATA_SZ; if (cpu_is_omap15xx()) diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c index e20023c9d15d..a9e631fc1134 100644 --- a/arch/arm/mach-omap2/mcbsp.c +++ b/arch/arm/mach-omap2/mcbsp.c @@ -24,106 +24,7 @@ #include #include -struct mcbsp_internal_clk { - struct clk clk; - struct clk **childs; - int n_childs; -}; - -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) -static void omap_mcbsp_clk_init(struct mcbsp_internal_clk *mclk) -{ - const char *clk_names[] = { "mcbsp_ick", "mcbsp_fck" }; - int i; - - mclk->n_childs = ARRAY_SIZE(clk_names); - mclk->childs = kzalloc(mclk->n_childs * sizeof(struct clk *), - GFP_KERNEL); - - for (i = 0; i < mclk->n_childs; i++) { - /* We fake a platform device to get correct device id */ - struct platform_device pdev; - - pdev.dev.bus = &platform_bus_type; - pdev.id = mclk->clk.id; - mclk->childs[i] = clk_get(&pdev.dev, clk_names[i]); - if (IS_ERR(mclk->childs[i])) - printk(KERN_ERR "Could not get clock %s (%d).\n", - clk_names[i], mclk->clk.id); - } -} - -static int omap_mcbsp_clk_enable(struct clk *clk) -{ - struct mcbsp_internal_clk *mclk = container_of(clk, - struct mcbsp_internal_clk, clk); - int i; - - for (i = 0; i < mclk->n_childs; i++) - clk_enable(mclk->childs[i]); - return 0; -} - -static void omap_mcbsp_clk_disable(struct clk *clk) -{ - struct mcbsp_internal_clk *mclk = container_of(clk, - struct mcbsp_internal_clk, clk); - int i; - - for (i = 0; i < mclk->n_childs; i++) - clk_disable(mclk->childs[i]); -} - -static struct mcbsp_internal_clk omap_mcbsp_clks[] = { - { - .clk = { - .name = "mcbsp_clk", - .id = 1, - .enable = omap_mcbsp_clk_enable, - .disable = omap_mcbsp_clk_disable, - }, - }, - { - .clk = { - .name = "mcbsp_clk", - .id = 2, - .enable = omap_mcbsp_clk_enable, - .disable = omap_mcbsp_clk_disable, - }, - }, - { - .clk = { - .name = "mcbsp_clk", - .id = 3, - .enable = omap_mcbsp_clk_enable, - .disable = omap_mcbsp_clk_disable, - }, - }, - { - .clk = { - .name = "mcbsp_clk", - .id = 4, - .enable = omap_mcbsp_clk_enable, - .disable = omap_mcbsp_clk_disable, - }, - }, - { - .clk = { - .name = "mcbsp_clk", - .id = 5, - .enable = omap_mcbsp_clk_enable, - .disable = omap_mcbsp_clk_disable, - }, - }, -}; - -#define omap_mcbsp_clks_size ARRAY_SIZE(omap_mcbsp_clks) -#else -#define omap_mcbsp_clks_size 0 -static struct mcbsp_internal_clk __initdata *omap_mcbsp_clks; -static inline void omap_mcbsp_clk_init(struct clk *clk) -{ } -#endif +const char *clk_names[] = { "mcbsp_ick", "mcbsp_fck" }; static void omap2_mcbsp2_mux_setup(void) { @@ -156,7 +57,8 @@ static struct omap_mcbsp_platform_data omap2420_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP1_IRQ_RX, .tx_irq = INT_24XX_MCBSP1_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, { .phys_base = OMAP24XX_MCBSP2_BASE, @@ -165,7 +67,8 @@ static struct omap_mcbsp_platform_data omap2420_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP2_IRQ_RX, .tx_irq = INT_24XX_MCBSP2_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, }; #define OMAP2420_MCBSP_PDATA_SZ ARRAY_SIZE(omap2420_mcbsp_pdata) @@ -183,7 +86,8 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP1_IRQ_RX, .tx_irq = INT_24XX_MCBSP1_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, { .phys_base = OMAP24XX_MCBSP2_BASE, @@ -192,7 +96,8 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP2_IRQ_RX, .tx_irq = INT_24XX_MCBSP2_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, { .phys_base = OMAP2430_MCBSP3_BASE, @@ -201,7 +106,8 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP3_IRQ_RX, .tx_irq = INT_24XX_MCBSP3_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, { .phys_base = OMAP2430_MCBSP4_BASE, @@ -210,7 +116,8 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP4_IRQ_RX, .tx_irq = INT_24XX_MCBSP4_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, { .phys_base = OMAP2430_MCBSP5_BASE, @@ -219,7 +126,8 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP5_IRQ_RX, .tx_irq = INT_24XX_MCBSP5_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, }; #define OMAP2430_MCBSP_PDATA_SZ ARRAY_SIZE(omap2430_mcbsp_pdata) @@ -237,7 +145,8 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP1_IRQ_RX, .tx_irq = INT_24XX_MCBSP1_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, { .phys_base = OMAP34XX_MCBSP2_BASE, @@ -246,7 +155,8 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP2_IRQ_RX, .tx_irq = INT_24XX_MCBSP2_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, { .phys_base = OMAP34XX_MCBSP3_BASE, @@ -255,7 +165,8 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP3_IRQ_RX, .tx_irq = INT_24XX_MCBSP3_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, { .phys_base = OMAP34XX_MCBSP4_BASE, @@ -264,7 +175,8 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP4_IRQ_RX, .tx_irq = INT_24XX_MCBSP4_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, { .phys_base = OMAP34XX_MCBSP5_BASE, @@ -273,7 +185,8 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP5_IRQ_RX, .tx_irq = INT_24XX_MCBSP5_IRQ_TX, .ops = &omap2_mcbsp_ops, - .clk_name = "mcbsp_clk", + .clk_names = clk_names, + .num_clks = 2, }, }; #define OMAP34XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap34xx_mcbsp_pdata) @@ -284,14 +197,6 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { static int __init omap2_mcbsp_init(void) { - int i; - - for (i = 0; i < omap_mcbsp_clks_size; i++) { - /* Once we call clk_get inside init, we do not register it */ - omap_mcbsp_clk_init(&omap_mcbsp_clks[i]); - clk_register(&omap_mcbsp_clks[i].clk); - } - if (cpu_is_omap2420()) omap_mcbsp_count = OMAP2420_MCBSP_PDATA_SZ; if (cpu_is_omap2430()) diff --git a/arch/arm/plat-omap/include/mach/mcbsp.h b/arch/arm/plat-omap/include/mach/mcbsp.h index eef873db3d48..113c2466c86a 100644 --- a/arch/arm/plat-omap/include/mach/mcbsp.h +++ b/arch/arm/plat-omap/include/mach/mcbsp.h @@ -344,7 +344,8 @@ struct omap_mcbsp_platform_data { u8 dma_rx_sync, dma_tx_sync; u16 rx_irq, tx_irq; struct omap_mcbsp_ops *ops; - char const *clk_name; + char const **clk_names; + int num_clks; }; struct omap_mcbsp { @@ -376,7 +377,8 @@ struct omap_mcbsp { /* Protect the field .free, while checking if the mcbsp is in use */ spinlock_t lock; struct omap_mcbsp_platform_data *pdata; - struct clk *clk; + struct clk **clks; + int num_clks; }; extern struct omap_mcbsp **mcbsp_ptr; extern int omap_mcbsp_count; diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index f2401a831f99..e5842e30e534 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c @@ -214,6 +214,7 @@ EXPORT_SYMBOL(omap_mcbsp_set_io_type); int omap_mcbsp_request(unsigned int id) { struct omap_mcbsp *mcbsp; + int i; int err; if (!omap_mcbsp_check_valid_id(id)) { @@ -225,7 +226,8 @@ int omap_mcbsp_request(unsigned int id) if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->request) mcbsp->pdata->ops->request(id); - clk_enable(mcbsp->clk); + for (i = 0; i < mcbsp->num_clks; i++) + clk_enable(mcbsp->clks[i]); spin_lock(&mcbsp->lock); if (!mcbsp->free) { @@ -276,6 +278,7 @@ EXPORT_SYMBOL(omap_mcbsp_request); void omap_mcbsp_free(unsigned int id) { struct omap_mcbsp *mcbsp; + int i; if (!omap_mcbsp_check_valid_id(id)) { printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); @@ -286,7 +289,8 @@ void omap_mcbsp_free(unsigned int id) if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free) mcbsp->pdata->ops->free(id); - clk_disable(mcbsp->clk); + for (i = mcbsp->num_clks - 1; i >= 0; i--) + clk_disable(mcbsp->clks[i]); spin_lock(&mcbsp->lock); if (mcbsp->free) { @@ -872,6 +876,7 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev) struct omap_mcbsp_platform_data *pdata = pdev->dev.platform_data; struct omap_mcbsp *mcbsp; int id = pdev->id - 1; + int i; int ret = 0; if (!pdata) { @@ -916,14 +921,25 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev) mcbsp->dma_rx_sync = pdata->dma_rx_sync; mcbsp->dma_tx_sync = pdata->dma_tx_sync; - if (pdata->clk_name) - mcbsp->clk = clk_get(&pdev->dev, pdata->clk_name); - if (IS_ERR(mcbsp->clk)) { - dev_err(&pdev->dev, - "Invalid clock configuration for McBSP%d.\n", - mcbsp->id); - ret = PTR_ERR(mcbsp->clk); - goto err_clk; + if (pdata->num_clks) { + mcbsp->num_clks = pdata->num_clks; + mcbsp->clks = kzalloc(mcbsp->num_clks * sizeof(struct clk *), + GFP_KERNEL); + if (!mcbsp->clks) { + ret = -ENOMEM; + goto exit; + } + for (i = 0; i < mcbsp->num_clks; i++) { + mcbsp->clks[i] = clk_get(&pdev->dev, pdata->clk_names[i]); + if (IS_ERR(mcbsp->clks[i])) { + dev_err(&pdev->dev, + "Invalid %s configuration for McBSP%d.\n", + pdata->clk_names[i], mcbsp->id); + ret = PTR_ERR(mcbsp->clks[i]); + goto err_clk; + } + } + } mcbsp->pdata = pdata; @@ -932,6 +948,9 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev) return 0; err_clk: + while (i--) + clk_put(mcbsp->clks[i]); + kfree(mcbsp->clks); iounmap(mcbsp->io_base); err_ioremap: mcbsp->free = 0; @@ -942,6 +961,7 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev) static int __devexit omap_mcbsp_remove(struct platform_device *pdev) { struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev); + int i; platform_set_drvdata(pdev, NULL); if (mcbsp) { @@ -950,12 +970,18 @@ static int __devexit omap_mcbsp_remove(struct platform_device *pdev) mcbsp->pdata->ops->free) mcbsp->pdata->ops->free(mcbsp->id); - clk_disable(mcbsp->clk); - clk_put(mcbsp->clk); + for (i = mcbsp->num_clks - 1; i >= 0; i--) { + clk_disable(mcbsp->clks[i]); + clk_put(mcbsp->clks[i]); + } iounmap(mcbsp->io_base); - mcbsp->clk = NULL; + if (mcbsp->num_clks) { + kfree(mcbsp->clks); + mcbsp->clks = NULL; + mcbsp->num_clks = 0; + } mcbsp->free = 0; mcbsp->dev = NULL; } From 320ce6f6fb3d95e02a183709e51d8a16a8b00e0a Mon Sep 17 00:00:00 2001 From: Juha Yrjola Date: Thu, 29 Jan 2009 08:57:12 -0800 Subject: [PATCH 027/111] ARM: OMAP: Fix race in OMAP2/3 DMA IRQ handling CSR must be cleared before invoking the callback. If the callback function starts a new, fast DMA transfer on the same channel, the completion status might lost if CSR is cleared after the callback invocation. Signed-off-by: Juha Yrjola Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/dma.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index e77373c39f8c..bec8e363d545 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -1888,11 +1888,11 @@ static int omap2_dma_handle_ch(int ch) status = dma_read(CSR(ch)); } + dma_write(status, CSR(ch)); + if (likely(dma_chan[ch].callback != NULL)) dma_chan[ch].callback(ch, status, dma_chan[ch].data); - dma_write(status, CSR(ch)); - return 0; } From a92fda194d31d26c1fecd191a03d2dbc5b6ac230 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Thu, 29 Jan 2009 08:57:12 -0800 Subject: [PATCH 028/111] ARM: OMAP: DMA: Fix uninitialized channel flags This has similar symptoms than 66c23551b1b774e2be3c7bdf91c0ebf2c7a3519e where just omap_request_dma, omap_dma_link_lch and omap_dma_unlink_lch can cause incorrect dump_stack(). Here it can happen if channel has been used before and the channel flags variable holds old status. Signed-off-by: Jarkko Nikula Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/dma.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index bec8e363d545..47ec77af4ccb 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -709,6 +709,7 @@ int omap_request_dma(int dev_id, const char *dev_name, chan->dev_name = dev_name; chan->callback = callback; chan->data = data; + chan->flags = 0; #ifndef CONFIG_ARCH_OMAP1 if (cpu_class_is_omap2()) { From 187e688d237a6df11a2d32e8ac480b6d1fbd40b9 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 29 Jan 2009 08:57:16 -0800 Subject: [PATCH 029/111] ARM: OMAP: Fix omap34xx revision detection for ES3.1 Fix omap34xx revision detection for ES3.1 Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/id.c | 6 +++++- arch/arm/plat-omap/include/mach/cpu.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c index b0f8e7d62798..b52a02fc7cd6 100644 --- a/arch/arm/mach-omap2/id.c +++ b/arch/arm/mach-omap2/id.c @@ -172,9 +172,13 @@ void __init omap34xx_check_revision(void) omap_revision = OMAP3430_REV_ES3_0; rev_name = "ES3.0"; break; + case 4: + omap_revision = OMAP3430_REV_ES3_1; + rev_name = "ES3.1"; + break; default: /* Use the latest known revision as default */ - omap_revision = OMAP3430_REV_ES3_0; + omap_revision = OMAP3430_REV_ES3_1; rev_name = "Unknown revision\n"; } } diff --git a/arch/arm/plat-omap/include/mach/cpu.h b/arch/arm/plat-omap/include/mach/cpu.h index b2062f1175de..a8e1178a9468 100644 --- a/arch/arm/plat-omap/include/mach/cpu.h +++ b/arch/arm/plat-omap/include/mach/cpu.h @@ -339,6 +339,7 @@ IS_OMAP_TYPE(3430, 0x3430) #define OMAP3430_REV_ES2_0 0x34301034 #define OMAP3430_REV_ES2_1 0x34302034 #define OMAP3430_REV_ES3_0 0x34303034 +#define OMAP3430_REV_ES3_1 0x34304034 /* * omap_chip bits From 0dffb5c57a1d76532e2f2c7398579bfce81c3e5c Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 29 Jan 2009 08:57:16 -0800 Subject: [PATCH 030/111] ARM: OMAP: Fix hsmmc init, v2 The naming accidentally broke while changing the name for the driver to not to conflict with the other mmc driver. Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/devices.c | 2 +- arch/arm/mach-omap2/devices.c | 11 +++++++---- arch/arm/plat-omap/devices.c | 7 ++++--- arch/arm/plat-omap/include/mach/mmc.h | 10 ++++++---- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c index 77382d8b6b2f..ba5d7c08dc17 100644 --- a/arch/arm/mach-omap1/devices.c +++ b/arch/arm/mach-omap1/devices.c @@ -181,7 +181,7 @@ void __init omap1_init_mmc(struct omap_mmc_platform_data **mmc_data, } size = OMAP1_MMC_SIZE; - omap_mmc_add(i, base, size, irq, mmc_data[i]); + omap_mmc_add("mmci-omap", i, base, size, irq, mmc_data[i]); }; } diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 9d7216ff6c9f..ce03fa750775 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -421,6 +421,7 @@ void __init omap2_init_mmc(struct omap_mmc_platform_data **mmc_data, int nr_controllers) { int i; + char *name; for (i = 0; i < nr_controllers; i++) { unsigned long base, size; @@ -450,12 +451,14 @@ void __init omap2_init_mmc(struct omap_mmc_platform_data **mmc_data, continue; } - if (cpu_is_omap2420()) + if (cpu_is_omap2420()) { size = OMAP2420_MMC_SIZE; - else + name = "mmci-omap"; + } else { size = HSMMC_SIZE; - - omap_mmc_add(i, base, size, irq, mmc_data[i]); + name = "mmci-omap-hs"; + } + omap_mmc_add(name, i, base, size, irq, mmc_data[i]); }; } diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c index ac15c23fd5da..208dbb121f47 100644 --- a/arch/arm/plat-omap/devices.c +++ b/arch/arm/plat-omap/devices.c @@ -200,14 +200,15 @@ void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config, /* * Register MMC devices. Called from mach-omap1 and mach-omap2 device init. */ -int __init omap_mmc_add(int id, unsigned long base, unsigned long size, - unsigned int irq, struct omap_mmc_platform_data *data) +int __init omap_mmc_add(const char *name, int id, unsigned long base, + unsigned long size, unsigned int irq, + struct omap_mmc_platform_data *data) { struct platform_device *pdev; struct resource res[OMAP_MMC_NR_RES]; int ret; - pdev = platform_device_alloc("mmci-omap", id); + pdev = platform_device_alloc(name, id); if (!pdev) return -ENOMEM; diff --git a/arch/arm/plat-omap/include/mach/mmc.h b/arch/arm/plat-omap/include/mach/mmc.h index 031250f02805..73a9e15031b1 100644 --- a/arch/arm/plat-omap/include/mach/mmc.h +++ b/arch/arm/plat-omap/include/mach/mmc.h @@ -115,8 +115,9 @@ void omap1_init_mmc(struct omap_mmc_platform_data **mmc_data, int nr_controllers); void omap2_init_mmc(struct omap_mmc_platform_data **mmc_data, int nr_controllers); -int omap_mmc_add(int id, unsigned long base, unsigned long size, - unsigned int irq, struct omap_mmc_platform_data *data); +int omap_mmc_add(const char *name, int id, unsigned long base, + unsigned long size, unsigned int irq, + struct omap_mmc_platform_data *data); #else static inline void omap1_init_mmc(struct omap_mmc_platform_data **mmc_data, int nr_controllers) @@ -126,8 +127,9 @@ static inline void omap2_init_mmc(struct omap_mmc_platform_data **mmc_data, int nr_controllers) { } -static inline int omap_mmc_add(int id, unsigned long base, unsigned long size, - unsigned int irq, struct omap_mmc_platform_data *data) +static inline int omap_mmc_add(const char *name, int id, unsigned long base, + unsigned long size, unsigned int irq, + struct omap_mmc_platform_data *data) { return 0; } From df88acbbdc48d0bfe2a46bf2561d984b6d87a9ac Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Thu, 29 Jan 2009 08:57:17 -0800 Subject: [PATCH 031/111] ARM: OMAP: gptimer min_delta_ns corrected When 32 kHz timer is used the min_delta_ns should be initialized so that it reflects the timer programming cost. A write to the timer device will be usually posted, but it takes roughly 3 cycles before it is effective. If the timer is reprogrammed before that, the CPU will stall until the previous write completes. This was pointed out by Richard Woodruff. Since the lower bound for min_delta_ns is 1000, the change is visible only with tick rates less than 3 MHz. Also note that the old value is incorrect for 32 kHz also due to a rounding error, and it can cause the timer queue to hang (due to clockevent code trying to program the timer with zero ticks). Signed-off-by: Aaro Koskinen Reviewed-by: Richard Woodruff Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/timer-gp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c index ae6036300f60..9fc13a2cc3f4 100644 --- a/arch/arm/mach-omap2/timer-gp.c +++ b/arch/arm/mach-omap2/timer-gp.c @@ -118,7 +118,8 @@ static void __init omap2_gp_clockevent_init(void) clockevent_gpt.max_delta_ns = clockevent_delta2ns(0xffffffff, &clockevent_gpt); clockevent_gpt.min_delta_ns = - clockevent_delta2ns(1, &clockevent_gpt); + clockevent_delta2ns(3, &clockevent_gpt); + /* Timer internal resynch latency. */ clockevent_gpt.cpumask = cpumask_of(0); clockevents_register_device(&clockevent_gpt); From 5461af5af5c6a7fee78978aafe720541bf3a2f55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EA=B7=9C=EC=9B=90?= Date: Thu, 29 Jan 2009 08:57:17 -0800 Subject: [PATCH 032/111] ARM: OMAP: Mask interrupts when disabling interrupts, v2 By Ingo Molnar, interrupts are not masked by default. (refer to 76d2160147f43f982dfe881404cfde9fd0a9da21) But if interrupts are not masked, the processor can wake up while in Suspend-to-RAM state by an external interrupt. For example, if an OMAP3 board is connected to Host PC by USB and entered to Suspend-to-RAM state, it wake up automatically by M_IRQ_92. The disable_irq() function can't disable the interrupt in H/W level, So I modified arch/arm/mach-omap2/irq.c Signed-off-by: Kim Kyuwon Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/irq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c index 636e2821af7d..9ba20d985dda 100644 --- a/arch/arm/mach-omap2/irq.c +++ b/arch/arm/mach-omap2/irq.c @@ -134,6 +134,7 @@ static struct irq_chip omap_irq_chip = { .ack = omap_mask_ack_irq, .mask = omap_mask_irq, .unmask = omap_unmask_irq, + .disable = omap_mask_irq, }; static void __init omap_irq_bank_init_one(struct omap_irq_bank *bank) From 0dc23d704874e892c3fb5f2c0e4dfbef3c9c6edf Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Thu, 29 Jan 2009 08:57:18 -0800 Subject: [PATCH 033/111] ARM: OMAP: fix fault in enter_full_retention() In omap24xx_cpu_suspend assembly routine, the r2 register which holds the address of the SDRC_POWER reg is set to zero before the value is written back triggering a fault due to writing to address zero. It's hard to tell where this change was introduced since this file has been moved and merged. While this fix prevents a crash, suspend on my n810 is broken with current kernels. I never come out of suspend. Signed-off-by: Kevin Hilman Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/sleep24xx.S | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/sleep24xx.S b/arch/arm/mach-omap2/sleep24xx.S index 43336b93b21c..bf9e96105e11 100644 --- a/arch/arm/mach-omap2/sleep24xx.S +++ b/arch/arm/mach-omap2/sleep24xx.S @@ -93,9 +93,8 @@ ENTRY(omap24xx_cpu_suspend) orr r4, r4, #0x40 @ enable self refresh on idle req mov r5, #0x2000 @ set delay (DPLL relock + DLL relock) str r4, [r2] @ make it so - mov r2, #0 nop - mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt + mcr p15, 0, r3, c7, c0, 4 @ wait for interrupt nop loop: subs r5, r5, #0x1 @ awake, wait just a bit From e5553a6d04421eec326a629571d696e8e745a0e4 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 29 Jan 2009 21:22:47 -0800 Subject: [PATCH 034/111] sparc64: Implement NMI watchdog on capable cpus. Signed-off-by: David S. Miller --- arch/sparc/include/asm/cpudata_64.h | 2 +- arch/sparc/include/asm/irq_64.h | 4 +- arch/sparc/include/asm/kdebug_64.h | 2 + arch/sparc/include/asm/nmi.h | 10 ++ arch/sparc/include/asm/pcr.h | 16 ++ arch/sparc/kernel/Makefile | 1 + arch/sparc/kernel/irq_64.c | 68 +-------- arch/sparc/kernel/nmi.c | 224 ++++++++++++++++++++++++++++ arch/sparc/kernel/pcr.c | 17 ++- arch/sparc/oprofile/init.c | 148 ++++++------------ 10 files changed, 319 insertions(+), 173 deletions(-) create mode 100644 arch/sparc/include/asm/nmi.h create mode 100644 arch/sparc/kernel/nmi.c diff --git a/arch/sparc/include/asm/cpudata_64.h b/arch/sparc/include/asm/cpudata_64.h index 7da7c13d23c4..a11b89ee9ef8 100644 --- a/arch/sparc/include/asm/cpudata_64.h +++ b/arch/sparc/include/asm/cpudata_64.h @@ -17,7 +17,7 @@ typedef struct { /* Dcache line 1 */ unsigned int __softirq_pending; /* must be 1st, see rtrap.S */ - unsigned int __pad0; + unsigned int __nmi_count; unsigned long clock_tick; /* %tick's per second */ unsigned long __pad; unsigned int __pad1; diff --git a/arch/sparc/include/asm/irq_64.h b/arch/sparc/include/asm/irq_64.h index d47d4a1955a9..1934f2cbf513 100644 --- a/arch/sparc/include/asm/irq_64.h +++ b/arch/sparc/include/asm/irq_64.h @@ -66,9 +66,6 @@ extern void virt_irq_free(unsigned int virt_irq); extern void __init init_IRQ(void); extern void fixup_irqs(void); -extern int register_perfctr_intr(void (*handler)(struct pt_regs *)); -extern void release_perfctr_intr(void (*handler)(struct pt_regs *)); - static inline void set_softint(unsigned long bits) { __asm__ __volatile__("wr %0, 0x0, %%set_softint" @@ -98,5 +95,6 @@ void __trigger_all_cpu_backtrace(void); extern void *hardirq_stack[NR_CPUS]; extern void *softirq_stack[NR_CPUS]; #define __ARCH_HAS_DO_SOFTIRQ +#define ARCH_HAS_NMI_WATCHDOG #endif diff --git a/arch/sparc/include/asm/kdebug_64.h b/arch/sparc/include/asm/kdebug_64.h index f905b773235a..feb3578e12c4 100644 --- a/arch/sparc/include/asm/kdebug_64.h +++ b/arch/sparc/include/asm/kdebug_64.h @@ -14,6 +14,8 @@ enum die_val { DIE_TRAP, DIE_TRAP_TL1, DIE_CALL, + DIE_NMI, + DIE_NMIWATCHDOG, }; #endif diff --git a/arch/sparc/include/asm/nmi.h b/arch/sparc/include/asm/nmi.h new file mode 100644 index 000000000000..fbd546dd4feb --- /dev/null +++ b/arch/sparc/include/asm/nmi.h @@ -0,0 +1,10 @@ +#ifndef __NMI_H +#define __NMI_H + +extern int __init nmi_init(void); +extern void perfctr_irq(int irq, struct pt_regs *regs); +extern void nmi_adjust_hz(unsigned int new_hz); + +extern int nmi_usable; + +#endif /* __NMI_H */ diff --git a/arch/sparc/include/asm/pcr.h b/arch/sparc/include/asm/pcr.h index 4249bb523ef1..a2f5c61f924e 100644 --- a/arch/sparc/include/asm/pcr.h +++ b/arch/sparc/include/asm/pcr.h @@ -27,4 +27,20 @@ extern void schedule_deferred_pcr_work(void); #define PCR_N2_SL1_SHIFT 27 #define PCR_N2_OV1 0x80000000 +extern unsigned int picl_shift; + +/* In order to commonize as much of the implementation as + * possible, we use PICH as our counter. Mostly this is + * to accomodate Niagara-1 which can only count insn cycles + * in PICH. + */ +static inline u64 picl_value(unsigned int nmi_hz) +{ + u32 delta = local_cpu_data().clock_tick / (nmi_hz << picl_shift); + + return ((u64)((0 - delta) & 0xffffffff)) << 32; +} + +extern u64 pcr_enable; + #endif /* __PCR_H */ diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index cb182d9c2f2b..54742e58831c 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -53,6 +53,7 @@ obj-$(CONFIG_SPARC64) += hvapi.o obj-$(CONFIG_SPARC64) += sstate.o obj-$(CONFIG_SPARC64) += mdesc.o obj-$(CONFIG_SPARC64) += pcr.o +obj-$(CONFIG_SPARC64) += nmi.o # sparc32 do not use GENERIC_HARDIRQS but uses the generic devres implementation obj-$(CONFIG_SPARC32) += devres.o diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c index cab8e0286871..e289376198eb 100644 --- a/arch/sparc/kernel/irq_64.c +++ b/arch/sparc/kernel/irq_64.c @@ -196,6 +196,11 @@ int show_interrupts(struct seq_file *p, void *v) seq_putc(p, '\n'); skip: spin_unlock_irqrestore(&irq_desc[i].lock, flags); + } else if (i == NR_IRQS) { + seq_printf(p, "NMI: "); + for_each_online_cpu(j) + seq_printf(p, "%10u ", cpu_data(j).__nmi_count); + seq_printf(p, " Non-maskable interrupts\n"); } return 0; } @@ -778,69 +783,6 @@ void do_softirq(void) local_irq_restore(flags); } -static void unhandled_perf_irq(struct pt_regs *regs) -{ - unsigned long pcr, pic; - - read_pcr(pcr); - read_pic(pic); - - write_pcr(0); - - printk(KERN_EMERG "CPU %d: Got unexpected perf counter IRQ.\n", - smp_processor_id()); - printk(KERN_EMERG "CPU %d: PCR[%016lx] PIC[%016lx]\n", - smp_processor_id(), pcr, pic); -} - -/* Almost a direct copy of the powerpc PMC code. */ -static DEFINE_SPINLOCK(perf_irq_lock); -static void *perf_irq_owner_caller; /* mostly for debugging */ -static void (*perf_irq)(struct pt_regs *regs) = unhandled_perf_irq; - -/* Invoked from level 15 PIL handler in trap table. */ -void perfctr_irq(int irq, struct pt_regs *regs) -{ - clear_softint(1 << irq); - perf_irq(regs); -} - -int register_perfctr_intr(void (*handler)(struct pt_regs *)) -{ - int ret; - - if (!handler) - return -EINVAL; - - spin_lock(&perf_irq_lock); - if (perf_irq != unhandled_perf_irq) { - printk(KERN_WARNING "register_perfctr_intr: " - "perf IRQ busy (reserved by caller %p)\n", - perf_irq_owner_caller); - ret = -EBUSY; - goto out; - } - - perf_irq_owner_caller = __builtin_return_address(0); - perf_irq = handler; - - ret = 0; -out: - spin_unlock(&perf_irq_lock); - - return ret; -} -EXPORT_SYMBOL_GPL(register_perfctr_intr); - -void release_perfctr_intr(void (*handler)(struct pt_regs *)) -{ - spin_lock(&perf_irq_lock); - perf_irq_owner_caller = NULL; - perf_irq = unhandled_perf_irq; - spin_unlock(&perf_irq_lock); -} -EXPORT_SYMBOL_GPL(release_perfctr_intr); - #ifdef CONFIG_HOTPLUG_CPU void fixup_irqs(void) { diff --git a/arch/sparc/kernel/nmi.c b/arch/sparc/kernel/nmi.c new file mode 100644 index 000000000000..ffc690093343 --- /dev/null +++ b/arch/sparc/kernel/nmi.c @@ -0,0 +1,224 @@ +/* Pseudo NMI support on sparc64 systems. + * + * Copyright (C) 2009 David S. Miller + * + * The NMI watchdog support and infrastructure is based almost + * entirely upon the x86 NMI support code. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* We don't have a real NMI on sparc64, but we can fake one + * up using profiling counter overflow interrupts and interrupt + * levels. + * + * The profile overflow interrupts at level 15, so we use + * level 14 as our IRQ off level. + */ + +static int nmi_watchdog_active; +static int panic_on_timeout; + +int nmi_usable; +EXPORT_SYMBOL_GPL(nmi_usable); + +static unsigned int nmi_hz = HZ; + +static DEFINE_PER_CPU(unsigned int, last_irq_sum); +static DEFINE_PER_CPU(local_t, alert_counter); +static DEFINE_PER_CPU(int, nmi_touch); + +void touch_nmi_watchdog(void) +{ + if (nmi_watchdog_active) { + int cpu; + + for_each_present_cpu(cpu) { + if (per_cpu(nmi_touch, cpu) != 1) + per_cpu(nmi_touch, cpu) = 1; + } + } + + touch_softlockup_watchdog(); +} +EXPORT_SYMBOL(touch_nmi_watchdog); + +static void die_nmi(const char *str, struct pt_regs *regs, int do_panic) +{ + if (notify_die(DIE_NMIWATCHDOG, str, regs, 0, + pt_regs_trap_type(regs), SIGINT) == NOTIFY_STOP) + return; + + console_verbose(); + bust_spinlocks(1); + + printk(KERN_EMERG "%s", str); + printk(" on CPU%d, ip %08lx, registers:\n", + smp_processor_id(), regs->tpc); + show_regs(regs); + + bust_spinlocks(0); + + if (do_panic || panic_on_oops) + panic("Non maskable interrupt"); + + local_irq_enable(); + do_exit(SIGBUS); +} + +notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs) +{ + unsigned int sum, touched = 0; + int cpu = smp_processor_id(); + + clear_softint(1 << irq); + pcr_ops->write(PCR_PIC_PRIV); + + local_cpu_data().__nmi_count++; + + if (notify_die(DIE_NMI, "nmi", regs, 0, + pt_regs_trap_type(regs), SIGINT) == NOTIFY_STOP) + touched = 1; + + sum = kstat_cpu(cpu).irqs[0]; + if (__get_cpu_var(nmi_touch)) { + __get_cpu_var(nmi_touch) = 0; + touched = 1; + } + if (!touched && __get_cpu_var(last_irq_sum) == sum) { + local_inc(&__get_cpu_var(alert_counter)); + if (local_read(&__get_cpu_var(alert_counter)) == 5 * nmi_hz) + die_nmi("BUG: NMI Watchdog detected LOCKUP", + regs, panic_on_timeout); + } else { + __get_cpu_var(last_irq_sum) = sum; + local_set(&__get_cpu_var(alert_counter), 0); + } + if (nmi_usable) { + write_pic(picl_value(nmi_hz)); + pcr_ops->write(pcr_enable); + } +} + +static inline unsigned int get_nmi_count(int cpu) +{ + return cpu_data(cpu).__nmi_count; +} + +static int endflag __initdata; + +static __init void nmi_cpu_busy(void *data) +{ + local_irq_enable_in_hardirq(); + while (endflag == 0) + mb(); +} + +static void report_broken_nmi(int cpu, int *prev_nmi_count) +{ + printk(KERN_CONT "\n"); + + printk(KERN_WARNING + "WARNING: CPU#%d: NMI appears to be stuck (%d->%d)!\n", + cpu, prev_nmi_count[cpu], get_nmi_count(cpu)); + + printk(KERN_WARNING + "Please report this to bugzilla.kernel.org,\n"); + printk(KERN_WARNING + "and attach the output of the 'dmesg' command.\n"); + + nmi_usable = 0; +} + +static void stop_watchdog(void *unused) +{ + pcr_ops->write(PCR_PIC_PRIV); +} + +static int __init check_nmi_watchdog(void) +{ + unsigned int *prev_nmi_count; + int cpu, err; + + prev_nmi_count = kmalloc(nr_cpu_ids * sizeof(unsigned int), GFP_KERNEL); + if (!prev_nmi_count) { + err = -ENOMEM; + goto error; + } + + printk(KERN_INFO "Testing NMI watchdog ... "); + + smp_call_function(nmi_cpu_busy, (void *)&endflag, 0); + + for_each_possible_cpu(cpu) + prev_nmi_count[cpu] = get_nmi_count(cpu); + local_irq_enable(); + mdelay((20 * 1000) / nmi_hz); /* wait 20 ticks */ + + for_each_online_cpu(cpu) { + if (get_nmi_count(cpu) - prev_nmi_count[cpu] <= 5) + report_broken_nmi(cpu, prev_nmi_count); + } + endflag = 1; + if (!nmi_usable) { + kfree(prev_nmi_count); + err = -ENODEV; + goto error; + } + printk("OK.\n"); + + nmi_hz = 1; + + kfree(prev_nmi_count); + return 0; +error: + on_each_cpu(stop_watchdog, NULL, 1); + return err; +} + +static void start_watchdog(void *unused) +{ + pcr_ops->write(PCR_PIC_PRIV); + write_pic(picl_value(nmi_hz)); + + pcr_ops->write(pcr_enable); +} + +void nmi_adjust_hz(unsigned int new_hz) +{ + nmi_hz = new_hz; + on_each_cpu(start_watchdog, NULL, 1); +} +EXPORT_SYMBOL_GPL(nmi_adjust_hz); + +int __init nmi_init(void) +{ + nmi_usable = 1; + + on_each_cpu(start_watchdog, NULL, 1); + + return check_nmi_watchdog(); +} + +static int __init setup_nmi_watchdog(char *str) +{ + if (!strncmp(str, "panic", 5)) + panic_on_timeout = 1; + + return 0; +} +__setup("nmi_watchdog=", setup_nmi_watchdog); diff --git a/arch/sparc/kernel/pcr.c b/arch/sparc/kernel/pcr.c index c4f24703b165..92e0dda141a4 100644 --- a/arch/sparc/kernel/pcr.c +++ b/arch/sparc/kernel/pcr.c @@ -9,12 +9,22 @@ #include #include +#include /* This code is shared between various users of the performance * counters. Users will be oprofile, pseudo-NMI watchdog, and the * perf_counter support layer. */ +#define PCR_SUN4U_ENABLE (PCR_PIC_PRIV | PCR_STRACE | PCR_UTRACE) +#define PCR_N2_ENABLE (PCR_PIC_PRIV | PCR_STRACE | PCR_UTRACE | \ + PCR_N2_TOE_OV1 | \ + (2 << PCR_N2_SL1_SHIFT) | \ + (0xff << PCR_N2_MASK1_SHIFT)) + +u64 pcr_enable; +unsigned int picl_shift; + /* Performance counter interrupts run unmasked at PIL level 15. * Therefore we can't do things like wakeups and other work * that expects IRQ disabling to be adhered to in locking etc. @@ -117,12 +127,15 @@ int __init pcr_arch_init(void) switch (tlb_type) { case hypervisor: pcr_ops = &n2_pcr_ops; + pcr_enable = PCR_N2_ENABLE; + picl_shift = 2; break; - case spitfire: case cheetah: case cheetah_plus: + case spitfire: pcr_ops = &direct_pcr_ops; + pcr_enable = PCR_SUN4U_ENABLE; break; default: @@ -130,7 +143,7 @@ int __init pcr_arch_init(void) goto out_unregister; } - return 0; + return nmi_init(); out_unregister: unregister_perf_hsvc(); diff --git a/arch/sparc/oprofile/init.c b/arch/sparc/oprofile/init.c index c8877a5202b0..d172f86439b1 100644 --- a/arch/sparc/oprofile/init.c +++ b/arch/sparc/oprofile/init.c @@ -13,117 +13,57 @@ #include #ifdef CONFIG_SPARC64 -#include -#include -#include -#include -#include +#include +#include +#include +#include -static int nmi_enabled; - -/* In order to commonize as much of the implementation as - * possible, we use PICH as our counter. Mostly this is - * to accomodate Niagara-1 which can only count insn cycles - * in PICH. - */ -static u64 picl_value(void) +static int profile_timer_exceptions_notify(struct notifier_block *self, + unsigned long val, void *data) { - u32 delta = local_cpu_data().clock_tick / HZ; + struct die_args *args = (struct die_args *)data; + int ret = NOTIFY_DONE; - return ((u64)((0 - delta) & 0xffffffff)) << 32; -} - -#define PCR_SUN4U_ENABLE (PCR_PIC_PRIV | PCR_STRACE | PCR_UTRACE) -#define PCR_N2_ENABLE (PCR_PIC_PRIV | PCR_STRACE | PCR_UTRACE | \ - PCR_N2_TOE_OV1 | \ - (2 << PCR_N2_SL1_SHIFT) | \ - (0xff << PCR_N2_MASK1_SHIFT)) - -static u64 pcr_enable; - -static void nmi_handler(struct pt_regs *regs) -{ - pcr_ops->write(PCR_PIC_PRIV); - - if (nmi_enabled) { - oprofile_add_sample(regs, 0); - - write_pic(picl_value()); - pcr_ops->write(pcr_enable); - } -} - -/* We count "clock cycle" events in the lower 32-bit PIC. - * Then configure it such that it overflows every HZ, and thus - * generates a level 15 interrupt at that frequency. - */ -static void cpu_nmi_start(void *_unused) -{ - pcr_ops->write(PCR_PIC_PRIV); - write_pic(picl_value()); - - pcr_ops->write(pcr_enable); -} - -static void cpu_nmi_stop(void *_unused) -{ - pcr_ops->write(PCR_PIC_PRIV); -} - -static int nmi_start(void) -{ - int err = register_perfctr_intr(nmi_handler); - - if (!err) { - nmi_enabled = 1; - wmb(); - err = on_each_cpu(cpu_nmi_start, NULL, 1); - if (err) { - nmi_enabled = 0; - wmb(); - on_each_cpu(cpu_nmi_stop, NULL, 1); - release_perfctr_intr(nmi_handler); - } - } - - return err; -} - -static void nmi_stop(void) -{ - nmi_enabled = 0; - wmb(); - - on_each_cpu(cpu_nmi_stop, NULL, 1); - release_perfctr_intr(nmi_handler); - synchronize_sched(); -} - -static int oprofile_nmi_init(struct oprofile_operations *ops) -{ - switch (tlb_type) { - case hypervisor: - pcr_enable = PCR_N2_ENABLE; + switch (val) { + case DIE_NMI: + oprofile_add_sample(args->regs, 0); + ret = NOTIFY_STOP; break; - - case cheetah: - case cheetah_plus: - pcr_enable = PCR_SUN4U_ENABLE; - break; - default: - return -ENODEV; + break; } + return ret; +} - ops->create_files = NULL; - ops->setup = NULL; - ops->shutdown = NULL; - ops->start = nmi_start; - ops->stop = nmi_stop; +static struct notifier_block profile_timer_exceptions_nb = { + .notifier_call = profile_timer_exceptions_notify, +}; + +static int timer_start(void) +{ + if (register_die_notifier(&profile_timer_exceptions_nb)) + return 1; + nmi_adjust_hz(HZ); + return 0; +} + + +static void timer_stop(void) +{ + nmi_adjust_hz(1); + unregister_die_notifier(&profile_timer_exceptions_nb); + synchronize_sched(); /* Allow already-started NMIs to complete. */ +} + +static int op_nmi_timer_init(struct oprofile_operations *ops) +{ + if (!nmi_usable) + return -ENODEV; + + ops->start = timer_start; + ops->stop = timer_stop; ops->cpu_type = "timer"; - - printk(KERN_INFO "oprofile: Using perfctr based NMI timer interrupt.\n"); - + printk(KERN_INFO "oprofile: Using perfctr NMI timer interrupt.\n"); return 0; } #endif @@ -133,7 +73,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) int ret = -ENODEV; #ifdef CONFIG_SPARC64 - ret = oprofile_nmi_init(ops); + ret = op_nmi_timer_init(ops); if (!ret) return ret; #endif From 6fd7ad96d6c51ba15479cb74dcb189b666422394 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sat, 31 Jan 2009 01:21:55 +0100 Subject: [PATCH 035/111] Use __SPIN_LOCK_UNLOCKED to initialize bad_irq_desc.lock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SPIN_LOCK_UNLOCKED is deprecated as lockdep cannot properly work with locks initialized with it. This fix is necessary to compile the linux-rt tree for ARM. Signed-off-by: Uwe Kleine-König Cc: Steven Rostedt --- arch/arm/kernel/irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c index 7141cee1fab7..363db186cb93 100644 --- a/arch/arm/kernel/irq.c +++ b/arch/arm/kernel/irq.c @@ -101,7 +101,7 @@ int show_interrupts(struct seq_file *p, void *v) /* Handle bad interrupts */ static struct irq_desc bad_irq_desc = { .handle_irq = handle_bad_irq, - .lock = SPIN_LOCK_UNLOCKED + .lock = __SPIN_LOCK_UNLOCKED(bad_irq_desc.lock), }; /* From b3c960b277c440c8a7788d338c9f494ad62e46ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sat, 31 Jan 2009 01:21:56 +0100 Subject: [PATCH 036/111] annotate that [fp, #-4] is the saved lr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König --- arch/arm/kernel/entry-common.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 06269ea375c5..49a6ba926c2b 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -136,7 +136,7 @@ ENTRY(mcount) ldmia sp!, {r0-r3, pc} trace: - ldr r1, [fp, #-4] + ldr r1, [fp, #-4] @ lr of instrumented routine mov r0, lr sub r0, r0, #MCOUNT_INSN_SIZE mov lr, pc From bcc8f3e01facc51b9d4f6351cd866f19eac0b5ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sat, 31 Jan 2009 01:21:58 +0100 Subject: [PATCH 037/111] rename platform_driver name "flash" to "sa1100-mtd" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "flash" is a very generic name for a platform_driver that is only available on SA11x0. Signed-off-by: Uwe Kleine-König Cc: Nicolas Pitre --- arch/arm/mach-sa1100/generic.c | 2 +- drivers/mtd/maps/sa1100-flash.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c index c1fbd5b5f9c4..23cfdd593954 100644 --- a/arch/arm/mach-sa1100/generic.c +++ b/arch/arm/mach-sa1100/generic.c @@ -289,7 +289,7 @@ static struct platform_device sa11x0pcmcia_device = { }; static struct platform_device sa11x0mtd_device = { - .name = "flash", + .name = "sa1100-mtd", .id = -1, }; diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c index 7df6bbf0e4d9..6f6a0f6dafd6 100644 --- a/drivers/mtd/maps/sa1100-flash.c +++ b/drivers/mtd/maps/sa1100-flash.c @@ -453,7 +453,7 @@ static struct platform_driver sa1100_mtd_driver = { .resume = sa1100_mtd_resume, .shutdown = sa1100_mtd_shutdown, .driver = { - .name = "flash", + .name = "sa1100-mtd", .owner = THIS_MODULE, }, }; @@ -474,4 +474,4 @@ module_exit(sa1100_mtd_exit); MODULE_AUTHOR("Nicolas Pitre"); MODULE_DESCRIPTION("SA1100 CFI map driver"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:flash"); +MODULE_ALIAS("platform:sa1100-mtd"); From 807a96cd0e5f5311e7f7a1030b43aab624cd7d9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Sat, 31 Jan 2009 01:21:59 +0100 Subject: [PATCH 038/111] NVRAM depends on RTC_DRV_CMOS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/char/nvram.c uses rtc_lock, that (on ARM) is only defined if RTC_DRV_CMOS is enabled. Signed-off-by: Uwe Kleine-König --- drivers/char/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index f5be8081cd81..735bbe2be51a 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -761,7 +761,7 @@ source "drivers/char/hw_random/Kconfig" config NVRAM tristate "/dev/nvram support" - depends on ATARI || X86 || ARM || GENERIC_NVRAM + depends on ATARI || X86 || (ARM && RTC_DRV_CMOS) || GENERIC_NVRAM ---help--- If you say Y here and create a character special file /dev/nvram with major number 10 and minor number 144 using mknod ("man mknod"), From ea455f8ab68338ba69f5d3362b342c115bea8e13 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 12 Jan 2009 23:20:31 +0100 Subject: [PATCH 039/111] ocfs2: Push out dropping of dentry lock to ocfs2_wq Dropping of last reference to dentry lock is a complicated operation involving dropping of reference to inode. This can get complicated and quota code in particular needs to obtain some quota locks which leads to potential deadlock. Thus we defer dropping of inode reference to ocfs2_wq. Signed-off-by: Jan Kara Signed-off-by: Mark Fasheh --- fs/ocfs2/dcache.c | 42 +++++++++++++++++++++++++++++++++++++++--- fs/ocfs2/dcache.h | 9 ++++++++- fs/ocfs2/ocfs2.h | 6 ++++++ fs/ocfs2/super.c | 3 +++ 4 files changed, 56 insertions(+), 4 deletions(-) diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c index b1cc7c381e88..e9d7c2038c0f 100644 --- a/fs/ocfs2/dcache.c +++ b/fs/ocfs2/dcache.c @@ -38,6 +38,7 @@ #include "dlmglue.h" #include "file.h" #include "inode.h" +#include "super.h" static int ocfs2_dentry_revalidate(struct dentry *dentry, @@ -294,6 +295,34 @@ int ocfs2_dentry_attach_lock(struct dentry *dentry, return ret; } +static DEFINE_SPINLOCK(dentry_list_lock); + +/* We limit the number of dentry locks to drop in one go. We have + * this limit so that we don't starve other users of ocfs2_wq. */ +#define DL_INODE_DROP_COUNT 64 + +/* Drop inode references from dentry locks */ +void ocfs2_drop_dl_inodes(struct work_struct *work) +{ + struct ocfs2_super *osb = container_of(work, struct ocfs2_super, + dentry_lock_work); + struct ocfs2_dentry_lock *dl; + int drop_count = DL_INODE_DROP_COUNT; + + spin_lock(&dentry_list_lock); + while (osb->dentry_lock_list && drop_count--) { + dl = osb->dentry_lock_list; + osb->dentry_lock_list = dl->dl_next; + spin_unlock(&dentry_list_lock); + iput(dl->dl_inode); + kfree(dl); + spin_lock(&dentry_list_lock); + } + if (osb->dentry_lock_list) + queue_work(ocfs2_wq, &osb->dentry_lock_work); + spin_unlock(&dentry_list_lock); +} + /* * ocfs2_dentry_iput() and friends. * @@ -318,16 +347,23 @@ int ocfs2_dentry_attach_lock(struct dentry *dentry, static void ocfs2_drop_dentry_lock(struct ocfs2_super *osb, struct ocfs2_dentry_lock *dl) { - iput(dl->dl_inode); ocfs2_simple_drop_lockres(osb, &dl->dl_lockres); ocfs2_lock_res_free(&dl->dl_lockres); - kfree(dl); + + /* We leave dropping of inode reference to ocfs2_wq as that can + * possibly lead to inode deletion which gets tricky */ + spin_lock(&dentry_list_lock); + if (!osb->dentry_lock_list) + queue_work(ocfs2_wq, &osb->dentry_lock_work); + dl->dl_next = osb->dentry_lock_list; + osb->dentry_lock_list = dl; + spin_unlock(&dentry_list_lock); } void ocfs2_dentry_lock_put(struct ocfs2_super *osb, struct ocfs2_dentry_lock *dl) { - int unlock = 0; + int unlock; BUG_ON(dl->dl_count == 0); diff --git a/fs/ocfs2/dcache.h b/fs/ocfs2/dcache.h index c091c34d9883..d06e16c06640 100644 --- a/fs/ocfs2/dcache.h +++ b/fs/ocfs2/dcache.h @@ -29,8 +29,13 @@ extern struct dentry_operations ocfs2_dentry_ops; struct ocfs2_dentry_lock { + /* Use count of dentry lock */ unsigned int dl_count; - u64 dl_parent_blkno; + union { + /* Linked list of dentry locks to release */ + struct ocfs2_dentry_lock *dl_next; + u64 dl_parent_blkno; + }; /* * The ocfs2_dentry_lock keeps an inode reference until @@ -47,6 +52,8 @@ int ocfs2_dentry_attach_lock(struct dentry *dentry, struct inode *inode, void ocfs2_dentry_lock_put(struct ocfs2_super *osb, struct ocfs2_dentry_lock *dl); +void ocfs2_drop_dl_inodes(struct work_struct *work); + struct dentry *ocfs2_find_local_alias(struct inode *inode, u64 parent_blkno, int skip_unhashed); diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index ad5c24a29edd..077384135f4e 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h @@ -210,6 +210,7 @@ struct ocfs2_journal; struct ocfs2_slot_info; struct ocfs2_recovery_map; struct ocfs2_quota_recovery; +struct ocfs2_dentry_lock; struct ocfs2_super { struct task_struct *commit_task; @@ -325,6 +326,11 @@ struct ocfs2_super struct list_head blocked_lock_list; unsigned long blocked_lock_count; + /* List of dentry locks to release. Anyone can add locks to + * the list, ocfs2_wq processes the list */ + struct ocfs2_dentry_lock *dentry_lock_list; + struct work_struct dentry_lock_work; + wait_queue_head_t osb_mount_event; /* Truncate log info */ diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 43ed11345b59..b1cb38fbe807 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -1887,6 +1887,9 @@ static int ocfs2_initialize_super(struct super_block *sb, INIT_WORK(&journal->j_recovery_work, ocfs2_complete_recovery); journal->j_state = OCFS2_JOURNAL_FREE; + INIT_WORK(&osb->dentry_lock_work, ocfs2_drop_dl_inodes); + osb->dentry_lock_list = NULL; + /* get some pseudo constants for clustersize bits */ osb->s_clustersize_bits = le32_to_cpu(di->id2.i_super.s_clustersize_bits); From f8afead7169f0f28a4b421bcbdb510e52a2d094d Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 12 Jan 2009 23:20:32 +0100 Subject: [PATCH 040/111] ocfs2: Fix possible deadlock in ocfs2_write_dquot() It could happen that some limit has been set via quotactl() and in parallel ->mark_dirty() is called from another thread doing e.g. dquot_alloc_space(). In such case ocfs2_write_dquot() must not try to sync the dquot because that needs global quota lock but that ranks above transaction start. Signed-off-by: Jan Kara Signed-off-by: Mark Fasheh --- fs/ocfs2/quota_global.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c index f4efa89baee5..1ed0f7c86869 100644 --- a/fs/ocfs2/quota_global.c +++ b/fs/ocfs2/quota_global.c @@ -754,7 +754,9 @@ static int ocfs2_mark_dquot_dirty(struct dquot *dquot) if (dquot->dq_flags & mask) sync = 1; spin_unlock(&dq_data_lock); - if (!sync) { + /* This is a slight hack but we can't afford getting global quota + * lock if we already have a transaction started. */ + if (!sync || journal_current_handle()) { status = ocfs2_write_dquot(dquot); goto out; } From 0e0333429a6280e6eb3c98845e4eed90d5f8078a Mon Sep 17 00:00:00 2001 From: Joel Becker Date: Wed, 17 Dec 2008 14:23:52 -0800 Subject: [PATCH 041/111] configfs: Silence lockdep on mkdir(), rmdir() and configfs_depend_item() When attaching default groups (subdirs) of a new group (in mkdir() or in configfs_register()), configfs recursively takes inode's mutexes along the path from the parent of the new group to the default subdirs. This is needed to ensure that the VFS will not race with operations on these sub-dirs. This is safe for the following reasons: - the VFS allows one to lock first an inode and second one of its children (The lock subclasses for this pattern are respectively I_MUTEX_PARENT and I_MUTEX_CHILD); - from this rule any inode path can be recursively locked in descending order as long as it stays under a single mountpoint and does not follow symlinks. Unfortunately lockdep does not know (yet?) how to handle such recursion. I've tried to use Peter Zijlstra's lock_set_subclass() helper to upgrade i_mutexes from I_MUTEX_CHILD to I_MUTEX_PARENT when we know that we might recursively lock some of their descendant, but this usage does not seem to fit the purpose of lock_set_subclass() because it leads to several i_mutex locked with subclass I_MUTEX_PARENT by the same task. >From inside configfs it is not possible to serialize those recursive locking with a top-level one, because mkdir() and rmdir() are already called with inodes locked by the VFS. So using some mutex_lock_nest_lock() is not an option. I am proposing two solutions: 1) one that wraps recursive mutex_lock()s with lockdep_off()/lockdep_on(). 2) (as suggested earlier by Peter Zijlstra) one that puts the i_mutexes recursively locked in different classes based on their depth from the top-level config_group created. This induces an arbitrary limit (MAX_LOCK_DEPTH - 2 == 46) on the nesting of configfs default groups whenever lockdep is activated but this limit looks reasonably high. Unfortunately, this alos isolates VFS operations on configfs default groups from the others and thus lowers the chances to detect locking issues. This patch implements solution 1). Solution 2) looks better from lockdep's point of view, but fails with configfs_depend_item(). This needs to rework the locking scheme of configfs_depend_item() by removing the variable lock recursion depth, and I think that it's doable thanks to the configfs_dirent_lock. For now, let's stick to solution 1). Signed-off-by: Louis Rilling Acked-by: Joel Becker Signed-off-by: Mark Fasheh --- fs/configfs/dir.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index 8e93341f3e82..9c2358391147 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c @@ -553,12 +553,24 @@ static void detach_groups(struct config_group *group) child = sd->s_dentry; + /* + * Note: we hide this from lockdep since we have no way + * to teach lockdep about recursive + * I_MUTEX_PARENT -> I_MUTEX_CHILD patterns along a path + * in an inode tree, which are valid as soon as + * I_MUTEX_PARENT -> I_MUTEX_CHILD is valid from a + * parent inode to one of its children. + */ + lockdep_off(); mutex_lock(&child->d_inode->i_mutex); + lockdep_on(); configfs_detach_group(sd->s_element); child->d_inode->i_flags |= S_DEAD; + lockdep_off(); mutex_unlock(&child->d_inode->i_mutex); + lockdep_on(); d_delete(child); dput(child); @@ -748,11 +760,22 @@ static int configfs_attach_item(struct config_item *parent_item, * We are going to remove an inode and its dentry but * the VFS may already have hit and used them. Thus, * we must lock them as rmdir() would. + * + * Note: we hide this from lockdep since we have no way + * to teach lockdep about recursive + * I_MUTEX_PARENT -> I_MUTEX_CHILD patterns along a path + * in an inode tree, which are valid as soon as + * I_MUTEX_PARENT -> I_MUTEX_CHILD is valid from a + * parent inode to one of its children. */ + lockdep_off(); mutex_lock(&dentry->d_inode->i_mutex); + lockdep_on(); configfs_remove_dir(item); dentry->d_inode->i_flags |= S_DEAD; + lockdep_off(); mutex_unlock(&dentry->d_inode->i_mutex); + lockdep_on(); d_delete(dentry); } } @@ -787,14 +810,25 @@ static int configfs_attach_group(struct config_item *parent_item, * * We must also lock the inode to remove it safely in case of * error, as rmdir() would. + * + * Note: we hide this from lockdep since we have no way + * to teach lockdep about recursive + * I_MUTEX_PARENT -> I_MUTEX_CHILD patterns along a path + * in an inode tree, which are valid as soon as + * I_MUTEX_PARENT -> I_MUTEX_CHILD is valid from a + * parent inode to one of its children. */ + lockdep_off(); mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD); + lockdep_on(); ret = populate_groups(to_config_group(item)); if (ret) { configfs_detach_item(item); dentry->d_inode->i_flags |= S_DEAD; } + lockdep_off(); mutex_unlock(&dentry->d_inode->i_mutex); + lockdep_on(); if (ret) d_delete(dentry); } @@ -956,7 +990,17 @@ static int configfs_depend_prep(struct dentry *origin, BUG_ON(!origin || !sd); /* Lock this guy on the way down */ + /* + * Note: we hide this from lockdep since we have no way + * to teach lockdep about recursive + * I_MUTEX_PARENT -> I_MUTEX_CHILD patterns along a path + * in an inode tree, which are valid as soon as + * I_MUTEX_PARENT -> I_MUTEX_CHILD is valid from a + * parent inode to one of its children. + */ + lockdep_off(); mutex_lock(&sd->s_dentry->d_inode->i_mutex); + lockdep_on(); if (sd->s_element == target) /* Boo-yah */ goto out; @@ -970,7 +1014,9 @@ static int configfs_depend_prep(struct dentry *origin, } /* We looped all our children and didn't find target */ + lockdep_off(); mutex_unlock(&sd->s_dentry->d_inode->i_mutex); + lockdep_on(); ret = -ENOENT; out: @@ -990,11 +1036,16 @@ static void configfs_depend_rollback(struct dentry *origin, struct dentry *dentry = item->ci_dentry; while (dentry != origin) { + /* See comments in configfs_depend_prep() */ + lockdep_off(); mutex_unlock(&dentry->d_inode->i_mutex); + lockdep_on(); dentry = dentry->d_parent; } + lockdep_off(); mutex_unlock(&origin->d_inode->i_mutex); + lockdep_on(); } int configfs_depend_item(struct configfs_subsystem *subsys, @@ -1329,8 +1380,16 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry) } /* Wait until the racing operation terminates */ + /* + * Note: we hide this from lockdep since we are locked + * with subclass I_MUTEX_NORMAL from vfs_rmdir() (why + * not I_MUTEX_CHILD?), and I_MUTEX_XATTR or + * I_MUTEX_QUOTA are not relevant for the locked inode. + */ + lockdep_off(); mutex_lock(wait_mutex); mutex_unlock(wait_mutex); + lockdep_on(); } } while (ret == -EAGAIN); From 554e7f9e043e29da79c044f7a55efe4fad40701e Mon Sep 17 00:00:00 2001 From: Tao Ma Date: Thu, 8 Jan 2009 08:21:43 +0800 Subject: [PATCH 042/111] ocfs2: Access the xattr bucket only before modifying it. In ocfs2_xattr_value_truncate, we may call b-tree codes which will extend the journal transaction. It has a potential problem that it may let the already-accessed-but-not-dirtied buffers gone. So we'd better access the bucket after we call ocfs2_xattr_value_truncate. And as for the root buffer for the xattr value, b-tree code will acess and dirty it, so we don't need to worry about it. Signed-off-by: Tao Ma Signed-off-by: Mark Fasheh --- fs/ocfs2/xattr.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index e1d638af6ac3..915039fffe6e 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c @@ -4729,13 +4729,6 @@ static int ocfs2_xattr_bucket_value_truncate(struct inode *inode, vb.vb_xv = (struct ocfs2_xattr_value_root *) (vb.vb_bh->b_data + offset % blocksize); - ret = ocfs2_xattr_bucket_journal_access(ctxt->handle, bucket, - OCFS2_JOURNAL_ACCESS_WRITE); - if (ret) { - mlog_errno(ret); - goto out; - } - /* * From here on out we have to dirty the bucket. The generic * value calls only modify one of the bucket's bhs, but we need @@ -4748,12 +4741,18 @@ static int ocfs2_xattr_bucket_value_truncate(struct inode *inode, ret = ocfs2_xattr_value_truncate(inode, &vb, len, ctxt); if (ret) { mlog_errno(ret); - goto out_dirty; + goto out; + } + + ret = ocfs2_xattr_bucket_journal_access(ctxt->handle, bucket, + OCFS2_JOURNAL_ACCESS_WRITE); + if (ret) { + mlog_errno(ret); + goto out; } xe->xe_value_size = cpu_to_le64(len); -out_dirty: ocfs2_xattr_bucket_journal_dirty(ctxt->handle, bucket); out: From a4b91965d39d5d53b470d6aa62cba155a6f3ffe1 Mon Sep 17 00:00:00 2001 From: Sunil Mushran Date: Thu, 29 Jan 2009 17:12:31 -0800 Subject: [PATCH 043/111] ocfs2: Wakeup the downconvert thread after a successful cancel convert When two nodes holding PR locks on a resource concurrently attempt to upconvert the locks to EX, the master sends a BAST to one of the nodes. This message tells that node to first cancel convert the upconvert request, followed by downconvert to a NL. Only when this lock is downconverted to NL, can the master upconvert the first node's lock to EX. While the fs was doing the cancel convert, it was forgetting to wake up the dc thread after a successful cancel, leading to a deadlock. Reported-and-Tested-by: David Teigland Signed-off-by: Sunil Mushran Signed-off-by: Mark Fasheh --- fs/ocfs2/dlmglue.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index b0c4cadd4c45..206a2370876a 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -2860,6 +2860,10 @@ static void ocfs2_unlock_ast(void *opaque, int error) case OCFS2_UNLOCK_CANCEL_CONVERT: mlog(0, "Cancel convert success for %s\n", lockres->l_name); lockres->l_action = OCFS2_AST_INVALID; + /* Downconvert thread may have requeued this lock, we + * need to wake it. */ + if (lockres->l_flags & OCFS2_LOCK_BLOCKED) + ocfs2_wake_downconvert_thread(ocfs2_get_lockres_osb(lockres)); break; case OCFS2_UNLOCK_DROP_LOCK: lockres->l_level = DLM_LOCK_IV; From fd4ef231962ab44fd1004e87f9d7c6809f00cd64 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Thu, 29 Jan 2009 15:06:21 -0800 Subject: [PATCH 044/111] ocfs2: add quota call to ocfs2_remove_btree_range() We weren't reclaiming the clusters which get free'd from this function, so any user punching holes in a file would still have those bytes accounted against him/her. Add the call to vfs_dq_free_space_nodirty() to fix this. Interestingly enough, the journal credits calculation already took this into account. Signed-off-by: Mark Fasheh Acked-by: Jan Kara --- fs/ocfs2/alloc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index d861096c9d81..60fe74035db5 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c @@ -5390,6 +5390,9 @@ int ocfs2_remove_btree_range(struct inode *inode, goto out; } + vfs_dq_free_space_nodirty(inode, + ocfs2_clusters_to_bytes(inode->i_sb, len)); + ret = ocfs2_remove_extent(inode, et, cpos, len, handle, meta_ac, dealloc); if (ret) { From 41137aa61c1ccb7cd06981807113b7e2d0ad89ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pasi=20K=C3=A4rkk=C3=A4inen?= Date: Mon, 2 Feb 2009 21:47:14 +0200 Subject: [PATCH 045/111] [libata] sata_sil: Fix compilation error with libata debugging enabled I tried compiling 2.6.29-rc1 and 2.6.29-rc3 with libata debugging enabled and got the following error: CC [M] drivers/ata/sata_sil.o drivers/ata/sata_sil.c: In function 'sil_fill_sg': drivers/ata/sata_sil.c:327: error: 'pi' undeclared (first use in this function) drivers/ata/sata_sil.c:327: error: (Each undeclared identifier is reported only once drivers/ata/sata_sil.c:327: error: for each function it appears in.) make[2]: *** [drivers/ata/sata_sil.o] Error 1 make[1]: *** [drivers/ata] Error 2 make: *** [drivers] Error 2 include/linux/libata.h has the following enabled: #define ATA_DEBUG #define ATA_VERBOSE_DEBUG #define ATA_IRQ_TRAP This fixes the compilation. Signed-off-by: Jeff Garzik --- drivers/ata/sata_sil.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index 9f029595f454..d0091609e210 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c @@ -324,7 +324,7 @@ static void sil_fill_sg(struct ata_queued_cmd *qc) prd->addr = cpu_to_le32(addr); prd->flags_len = cpu_to_le32(sg_len); - VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", pi, addr, sg_len); + VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", si, addr, sg_len); last_prd = prd; prd++; From 4462254ac6be9150aae87d54d388fc348d6fcead Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Tue, 27 Jan 2009 16:33:13 -0500 Subject: [PATCH 046/111] sata_mv: Fix chip type for Hightpoint RocketRaid 1740/1742 Fix chip type for the Highpoint RocketRAID 1740 and 1742 PCI cards. These really do have Marvell 6042 chips on them, rather than the 5081 chip. Confirmed by multiple (two) users (for the 1740), and by examining the product photographs from Highpoint's web site. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index f2d8a020ea53..4ae1a4138b47 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -663,8 +663,8 @@ static const struct pci_device_id mv_pci_tbl[] = { { PCI_VDEVICE(MARVELL, 0x5081), chip_508x }, /* RocketRAID 1720/174x have different identifiers */ { PCI_VDEVICE(TTI, 0x1720), chip_6042 }, - { PCI_VDEVICE(TTI, 0x1740), chip_508x }, - { PCI_VDEVICE(TTI, 0x1742), chip_508x }, + { PCI_VDEVICE(TTI, 0x1740), chip_6042 }, + { PCI_VDEVICE(TTI, 0x1742), chip_6042 }, { PCI_VDEVICE(MARVELL, 0x6040), chip_604x }, { PCI_VDEVICE(MARVELL, 0x6041), chip_604x }, From f3d7f23f87723a0947164ec88fc40e08254a64d6 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Mon, 26 Jan 2009 02:05:44 -0800 Subject: [PATCH 047/111] ahci: add a module parameter to ignore the SSS flags for async scanning The SSS flag, which directs the OS to spin up one disk at a time to not have the PSU blow out, sometimes gets set even when not needed. The effect of this is a longer-than-needed boot time. This patch adds a module parameter that makes the driver ignore SSS at least as far as the parallel scan during boot is concerned... Signed-off-by: Arjan van de Ven Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 77bba4c083cb..a603bbf9b1b7 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -61,9 +61,14 @@ #define EM_MSG_LED_VALUE_ON 0x00010000 static int ahci_skip_host_reset; +static int ahci_ignore_sss; + module_param_named(skip_host_reset, ahci_skip_host_reset, int, 0444); MODULE_PARM_DESC(skip_host_reset, "skip global host reset (0=don't skip, 1=skip)"); +module_param_named(ignore_sss, ahci_ignore_sss, int, 0444); +MODULE_PARM_DESC(ignore_sss, "Ignore staggered spinup flag (0=don't ignore, 1=ignore)"); + static int ahci_enable_alpm(struct ata_port *ap, enum link_pm policy); static void ahci_disable_alpm(struct ata_port *ap); @@ -2692,8 +2697,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) host->iomap = pcim_iomap_table(pdev); host->private_data = hpriv; - if (!(hpriv->cap & HOST_CAP_SSS)) + if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss) host->flags |= ATA_HOST_PARALLEL_SCAN; + else + printk(KERN_INFO "ahci: SSS flag set, parallel bus scan disabled\n"); if (pi.flags & ATA_FLAG_EM) ahci_reset_em(host); From 5eb66fe05f08d515a7377787473bc4e4b1ed5b59 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 20 Jan 2009 16:28:59 -0800 Subject: [PATCH 048/111] libata: fix kernel-doc warnings Fix libata kernel-doc warnings: Warning(linux-next-20090120//drivers/ata/libata-core.c:4720): Excess function parameter 'dev' description in 'ata_qc_new' Warning(linux-next-20090120//drivers/ata/libata-scsi.c:428): No description found for parameter 'ap' Signed-off-by: Randy Dunlap Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 3 +-- drivers/ata/libata-scsi.c | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 88c242856dae..574715d0b0fc 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4709,8 +4709,7 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words) /** * ata_qc_new - Request an available ATA command, for queueing - * @ap: Port associated with device @dev - * @dev: Device from whom we request an available command structure + * @ap: target port * * LOCKING: * None. diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 3c4c5ae277ba..b9747fa59e54 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -415,6 +415,7 @@ int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev, /** * ata_get_identity - Handler for HDIO_GET_IDENTITY ioctl + * @ap: target port * @sdev: SCSI device to get identify data for * @arg: User buffer area for identify data * From 2999b58b795ad81f10e34bdbbfd2742172f247e4 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sun, 1 Feb 2009 20:46:39 +0400 Subject: [PATCH 049/111] ide/libata: fix ata_id_is_cfa() (take 4) When checking for the CFA feature set support, ata_id_is_cfa() tests bit 2 in word 82 of the identify data instead the word 83; it also checks the ATA/PI version support in the word 80 (which the CompactFlash specifications have as reserved), this having no slightest chance to work on the modern CF cards that don't have 0x848A in the word 0... Signed-off-by: Sergei Shtylyov Signed-off-by: Jeff Garzik --- include/linux/ata.h | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/include/linux/ata.h b/include/linux/ata.h index a53318b8cbd0..08a86d5cdf1b 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -731,12 +731,17 @@ static inline int ata_id_current_chs_valid(const u16 *id) static inline int ata_id_is_cfa(const u16 *id) { - if (id[ATA_ID_CONFIG] == 0x848A) /* Standard CF */ + if (id[ATA_ID_CONFIG] == 0x848A) /* Traditional CF */ return 1; - /* Could be CF hiding as standard ATA */ - if (ata_id_major_version(id) >= 3 && - id[ATA_ID_COMMAND_SET_1] != 0xFFFF && - (id[ATA_ID_COMMAND_SET_1] & (1 << 2))) + /* + * CF specs don't require specific value in the word 0 anymore and yet + * they forbid to report the ATA version in the word 80 and require the + * CFA feature set support to be indicated in the word 83 in this case. + * Unfortunately, some cards only follow either of this requirements, + * and while those that don't indicate CFA feature support need some + * sort of quirk list, it seems impractical for the ones that do... + */ + if ((id[ATA_ID_COMMAND_SET_2] & 0xC004) == 0x4004) return 1; return 0; } From 8d993eaa9c3c61b8a5929a7f695078a1fcfb4869 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Sun, 1 Feb 2009 10:56:31 +0900 Subject: [PATCH 050/111] sata_nv: ck804 has borked hardreset too While playing with nvraid, I found out that rmmoding and insmoding often trigger hardreset failure on the first port (the second one was always okay). Seriously, how diverse can you get with hardreset behaviors? Anyways, make ck804 use noclassify variant too. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/sata_nv.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index c49ad0e61b6f..444af0415ca1 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -436,11 +436,16 @@ static struct ata_port_operations nv_nf2_ops = { .hardreset = nv_noclassify_hardreset, }; -/* CK804 finally gets hardreset right */ +/* For initial probing after boot and hot plugging, hardreset mostly + * works fine on CK804 but curiously, reprobing on the initial port by + * rescanning or rmmod/insmod fails to acquire the initial D2H Reg FIS + * in somewhat undeterministic way. Use noclassify hardreset. + */ static struct ata_port_operations nv_ck804_ops = { .inherits = &nv_common_ops, .freeze = nv_ck804_freeze, .thaw = nv_ck804_thaw, + .hardreset = nv_noclassify_hardreset, .host_stop = nv_ck804_host_stop, }; From d89293abd95bfd7dd9229087d6c30c1464c5ac83 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 29 Jan 2009 20:31:29 +0900 Subject: [PATCH 051/111] libata: fix EH device failure handling The dev->pio_mode > XFER_PIO_0 test is there to avoid unnecessary speed down warning messages but it accidentally disabled SATA link spd down during configuration phase after reset where PIO mode is always zero. This patch fixes the problem by moving the test where it belongs. This makes libata probing sequence behave better when the connection is flaky at higher link speeds which isn't too uncommon for eSATA devices. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-eh.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 8147a8386370..c15572d22a3b 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2979,12 +2979,13 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err) /* give it just one more chance */ ehc->tries[dev->devno] = min(ehc->tries[dev->devno], 1); case -EIO: - if (ehc->tries[dev->devno] == 1 && dev->pio_mode > XFER_PIO_0) { + if (ehc->tries[dev->devno] == 1) { /* This is the last chance, better to slow * down than lose it. */ sata_down_spd_limit(ata_dev_phys_link(dev)); - ata_down_xfermask_limit(dev, ATA_DNXFER_PIO); + if (dev->pio_mode > XFER_PIO_0) + ata_down_xfermask_limit(dev, ATA_DNXFER_PIO); } } From 678afac678061ee41bc3007885003c125912a8e2 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 29 Jan 2009 20:31:30 +0900 Subject: [PATCH 052/111] libata: move ata_dev_disable() to libata-eh.c ata_dev_disable() is about to be more tightly integrated into EH logic. Move it to libata-eh.c. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 12 ------------ drivers/ata/libata-eh.c | 21 +++++++++++++++++++++ drivers/ata/libata.h | 2 +- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 574715d0b0fc..af60d2715825 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1015,18 +1015,6 @@ static const char *sata_spd_string(unsigned int spd) return spd_str[spd - 1]; } -void ata_dev_disable(struct ata_device *dev) -{ - if (ata_dev_enabled(dev)) { - if (ata_msg_drv(dev->link->ap)) - ata_dev_printk(dev, KERN_WARNING, "disabled\n"); - ata_acpi_on_disable(dev); - ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO0 | - ATA_DNXFER_QUIET); - dev->class++; - } -} - static int ata_dev_set_dipm(struct ata_device *dev, enum link_pm policy) { struct ata_link *link = dev->link; diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index c15572d22a3b..aafe82bf5e2e 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1175,6 +1175,27 @@ void ata_eh_qc_retry(struct ata_queued_cmd *qc) __ata_eh_qc_complete(qc); } +/** + * ata_dev_disable - disable ATA device + * @dev: ATA device to disable + * + * Disable @dev. + * + * Locking: + * EH context. + */ +void ata_dev_disable(struct ata_device *dev) +{ + if (!ata_dev_enabled(dev)) + return; + + if (ata_msg_drv(dev->link->ap)) + ata_dev_printk(dev, KERN_WARNING, "disabled\n"); + ata_acpi_on_disable(dev); + ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO0 | ATA_DNXFER_QUIET); + dev->class++; +} + /** * ata_eh_detach_dev - detach ATA device * @dev: ATA device to detach diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index fe2839e58774..0a6f5be15112 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -79,7 +79,6 @@ extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev, u64 block, u32 n_block, unsigned int tf_flags, unsigned int tag); extern u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev); -extern void ata_dev_disable(struct ata_device *dev); extern void ata_pio_queue_task(struct ata_port *ap, void *data, unsigned long delay); extern void ata_port_flush_task(struct ata_port *ap); @@ -160,6 +159,7 @@ extern void ata_scsi_error(struct Scsi_Host *host); extern void ata_port_wait_eh(struct ata_port *ap); extern void ata_eh_fastdrain_timerfn(unsigned long arg); extern void ata_qc_schedule_eh(struct ata_queued_cmd *qc); +extern void ata_dev_disable(struct ata_device *dev); extern void ata_eh_detach_dev(struct ata_device *dev); extern void ata_eh_about_to_do(struct ata_link *link, struct ata_device *dev, unsigned int action); From 9913ff8abf1c70a8d52560dc931e1901d025ad27 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 29 Jan 2009 20:31:31 +0900 Subject: [PATCH 053/111] libata: check onlineness before using SPD in sata_down_spd_limit() sata_down_spd_limit() should check whether the link is online before using the SPD value to determine how to limit the link speed. Factor out onlineness test and test it from sata_down_spd_limit(). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index af60d2715825..d006e5c4768c 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -164,6 +164,11 @@ MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); +static bool ata_sstatus_online(u32 sstatus) +{ + return (sstatus & 0xf) == 0x3; +} + /** * ata_link_next - link iteration helper * @link: the previous link, NULL to start @@ -2891,7 +2896,7 @@ int sata_down_spd_limit(struct ata_link *link) * If not, use cached value in link->sata_spd. */ rc = sata_scr_read(link, SCR_STATUS, &sstatus); - if (rc == 0) + if (rc == 0 && ata_sstatus_online(sstatus)) spd = (sstatus >> 4) & 0xf; else spd = link->sata_spd; @@ -5162,7 +5167,7 @@ bool ata_phys_link_online(struct ata_link *link) u32 sstatus; if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0 && - (sstatus & 0xf) == 0x3) + ata_sstatus_online(sstatus)) return true; return false; } @@ -5186,7 +5191,7 @@ bool ata_phys_link_offline(struct ata_link *link) u32 sstatus; if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0 && - (sstatus & 0xf) != 0x3) + !ata_sstatus_online(sstatus)) return true; return false; } From 99cf610aa4840d822cdc67d194b23b55010ca9bd Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 29 Jan 2009 20:31:32 +0900 Subject: [PATCH 054/111] libata: clear dev->ering in smarter way dev->ering used to be cleared together with the rest of ata_device in ata_dev_init() which is called whenever a probing event occurs. dev->ering is about to be used to track probing failures so it needs to remain persistent over multiple porbing events. This patch achieves this by doing the following. * Instead of CLEAR_OFFSET, define CLEAR_BEGIN and CLEAR_END and only clear between BEGIN and END. ering is moved after END. The split of persistent area is to allow hotter items remain at the head. * ering is explicitly cleared on ata_dev_disable() and when device attach succeeds. So, ering is persistent throug a device's life time (unless explicitly cleared of course) and also through periods inbetween disablement of an attached device and successful detection of the next one. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 4 ++-- drivers/ata/libata-eh.c | 7 +++++++ include/linux/libata.h | 18 ++++++++++-------- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index d006e5c4768c..564c03c4ebb3 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -5404,8 +5404,8 @@ void ata_dev_init(struct ata_device *dev) dev->horkage = 0; spin_unlock_irqrestore(ap->lock, flags); - memset((void *)dev + ATA_DEVICE_CLEAR_OFFSET, 0, - sizeof(*dev) - ATA_DEVICE_CLEAR_OFFSET); + memset((void *)dev + ATA_DEVICE_CLEAR_BEGIN, 0, + ATA_DEVICE_CLEAR_END - ATA_DEVICE_CLEAR_BEGIN); dev->pio_mask = UINT_MAX; dev->mwdma_mask = UINT_MAX; dev->udma_mask = UINT_MAX; diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index aafe82bf5e2e..90092c1aae53 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1194,6 +1194,11 @@ void ata_dev_disable(struct ata_device *dev) ata_acpi_on_disable(dev); ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO0 | ATA_DNXFER_QUIET); dev->class++; + + /* From now till the next successful probe, ering is used to + * track probe failures. Clear accumulated device error info. + */ + ata_ering_clear(&dev->ering); } /** @@ -2765,6 +2770,8 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link, readid_flags, dev->id); switch (rc) { case 0: + /* clear error info accumulated during probe */ + ata_ering_clear(&dev->ering); new_mask |= 1 << dev->devno; break; case -ENOENT: diff --git a/include/linux/libata.h b/include/linux/libata.h index bca3ba25f52a..9dcefee5843c 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -580,7 +580,7 @@ struct ata_device { acpi_handle acpi_handle; union acpi_object *gtf_cache; #endif - /* n_sector is used as CLEAR_OFFSET, read comment above CLEAR_OFFSET */ + /* n_sector is CLEAR_BEGIN, read comment above CLEAR_BEGIN */ u64 n_sectors; /* size of device, if ATA */ unsigned int class; /* ATA_DEV_xxx */ unsigned long unpark_deadline; @@ -605,20 +605,22 @@ struct ata_device { u16 heads; /* Number of heads */ u16 sectors; /* Number of sectors per track */ - /* error history */ - int spdn_cnt; - struct ata_ering ering; - union { u16 id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */ u32 gscr[SATA_PMP_GSCR_DWORDS]; /* PMP GSCR block */ }; + + /* error history */ + int spdn_cnt; + /* ering is CLEAR_END, read comment above CLEAR_END */ + struct ata_ering ering; }; -/* Offset into struct ata_device. Fields above it are maintained - * acress device init. Fields below are zeroed. +/* Fields between ATA_DEVICE_CLEAR_BEGIN and ATA_DEVICE_CLEAR_END are + * cleared to zero on ata_dev_init(). */ -#define ATA_DEVICE_CLEAR_OFFSET offsetof(struct ata_device, n_sectors) +#define ATA_DEVICE_CLEAR_BEGIN offsetof(struct ata_device, n_sectors) +#define ATA_DEVICE_CLEAR_END offsetof(struct ata_device, ering) struct ata_eh_info { struct ata_device *dev; /* offending device */ From a07d499b4759881db1359dd8812eecd00b0e0a28 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 29 Jan 2009 20:31:33 +0900 Subject: [PATCH 055/111] libata: add @spd_limit to sata_down_spd_limit() Add @spd_limit to sata_down_spd_limit() so that the caller can specify the SPD limit it wants. This parameter doesn't get in the way even when it's too low. The closest possible limit is applied. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 25 ++++++++++++++++++++----- drivers/ata/libata-eh.c | 10 +++++----- drivers/ata/libata-pmp.c | 2 +- drivers/ata/libata.h | 2 +- 4 files changed, 27 insertions(+), 12 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 564c03c4ebb3..3c5965d56c47 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2777,7 +2777,7 @@ int ata_bus_probe(struct ata_port *ap) /* This is the last chance, better to slow * down than lose it. */ - sata_down_spd_limit(&ap->link); + sata_down_spd_limit(&ap->link, 0); ata_down_xfermask_limit(dev, ATA_DNXFER_PIO); } } @@ -2873,21 +2873,27 @@ void ata_port_disable(struct ata_port *ap) /** * sata_down_spd_limit - adjust SATA spd limit downward * @link: Link to adjust SATA spd limit for + * @spd_limit: Additional limit * * Adjust SATA spd limit of @link downward. Note that this * function only adjusts the limit. The change must be applied * using sata_set_spd(). * + * If @spd_limit is non-zero, the speed is limited to equal to or + * lower than @spd_limit if such speed is supported. If + * @spd_limit is slower than any supported speed, only the lowest + * supported speed is allowed. + * * LOCKING: * Inherited from caller. * * RETURNS: * 0 on success, negative errno on failure */ -int sata_down_spd_limit(struct ata_link *link) +int sata_down_spd_limit(struct ata_link *link, u32 spd_limit) { u32 sstatus, spd, mask; - int rc, highbit; + int rc, bit; if (!sata_scr_valid(link)) return -EOPNOTSUPP; @@ -2906,8 +2912,8 @@ int sata_down_spd_limit(struct ata_link *link) return -EINVAL; /* unconditionally mask off the highest bit */ - highbit = fls(mask) - 1; - mask &= ~(1 << highbit); + bit = fls(mask) - 1; + mask &= ~(1 << bit); /* Mask off all speeds higher than or equal to the current * one. Force 1.5Gbps if current SPD is not available. @@ -2921,6 +2927,15 @@ int sata_down_spd_limit(struct ata_link *link) if (!mask) return -EINVAL; + if (spd_limit) { + if (mask & ((1 << spd_limit) - 1)) + mask &= (1 << spd_limit) - 1; + else { + bit = ffs(mask) - 1; + mask = 1 << bit; + } + } + link->sata_spd_limit = mask; ata_link_printk(link, KERN_WARNING, "limiting SATA link speed to %s\n", diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 90092c1aae53..685509bc7ff0 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1875,7 +1875,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev, /* speed down? */ if (verdict & ATA_EH_SPDN_SPEED_DOWN) { /* speed down SATA link speed if possible */ - if (sata_down_spd_limit(link) == 0) { + if (sata_down_spd_limit(link, 0) == 0) { action |= ATA_EH_RESET; goto done; } @@ -2627,11 +2627,11 @@ int ata_eh_reset(struct ata_link *link, int classify, } if (try == max_tries - 1) { - sata_down_spd_limit(link); + sata_down_spd_limit(link, 0); if (slave) - sata_down_spd_limit(slave); + sata_down_spd_limit(slave, 0); } else if (rc == -EPIPE) - sata_down_spd_limit(failed_link); + sata_down_spd_limit(failed_link, 0); if (hardreset) reset = hardreset; @@ -3011,7 +3011,7 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err) /* This is the last chance, better to slow * down than lose it. */ - sata_down_spd_limit(ata_dev_phys_link(dev)); + sata_down_spd_limit(ata_dev_phys_link(dev), 0); if (dev->pio_mode > XFER_PIO_0) ata_down_xfermask_limit(dev, ATA_DNXFER_PIO); } diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c index 98ca07a2db87..619f2c33950e 100644 --- a/drivers/ata/libata-pmp.c +++ b/drivers/ata/libata-pmp.c @@ -729,7 +729,7 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap, if (tries) { /* consecutive revalidation failures? speed down */ if (reval_failed) - sata_down_spd_limit(link); + sata_down_spd_limit(link, 0); else reval_failed = 1; diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 0a6f5be15112..cea8014cd87e 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -99,7 +99,7 @@ extern int ata_dev_reread_id(struct ata_device *dev, unsigned int readid_flags); extern int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class, unsigned int readid_flags); extern int ata_dev_configure(struct ata_device *dev); -extern int sata_down_spd_limit(struct ata_link *link); +extern int sata_down_spd_limit(struct ata_link *link, u32 spd_limit); extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel); extern void ata_sg_clean(struct ata_queued_cmd *qc); extern void ata_qc_free(struct ata_queued_cmd *qc); From c2c7a89c5eabaea8c0c2aa0c1069e510144513ab Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 29 Jan 2009 20:31:34 +0900 Subject: [PATCH 056/111] libata: improve probe failure handling When link is flaky at high speed, it isn't uncommon for a device to repeatedly fail probing sequence early after successfully negotiating high link speed. This often leads to consecutive hotplug events without successful probing. This patch improves libata EH such that it remembers probing trials and if there have been more than two unsuccessful trials in the past 60 seconds, slows down link speed to 1.5Gbps. As link speed negotiation is the duty of the PHY layer proper, the goal of this fallback mechanism is to provide the last resort when everything else fails, which unfortunately happens not too infrequently, so no fancy 6->3->1.5 speeding down or highest successful transmission speed seen kind of logics (yet). Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-eh.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 685509bc7ff0..caa1e9fde3c9 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -82,6 +82,10 @@ enum { ATA_EH_FASTDRAIN_INTERVAL = 3000, ATA_EH_UA_TRIES = 5, + + /* probe speed down parameters, see ata_eh_schedule_probe() */ + ATA_EH_PROBE_TRIAL_INTERVAL = 60000, /* 1 min */ + ATA_EH_PROBE_TRIALS = 2, }; /* The following table determines how we sequence resets. Each entry @@ -2975,9 +2979,24 @@ static int ata_eh_skip_recovery(struct ata_link *link) return 1; } +static int ata_count_probe_trials_cb(struct ata_ering_entry *ent, void *void_arg) +{ + u64 interval = msecs_to_jiffies(ATA_EH_PROBE_TRIAL_INTERVAL); + u64 now = get_jiffies_64(); + int *trials = void_arg; + + if (ent->timestamp < now - min(now, interval)) + return -1; + + (*trials)++; + return 0; +} + static int ata_eh_schedule_probe(struct ata_device *dev) { struct ata_eh_context *ehc = &dev->link->eh_context; + struct ata_link *link = ata_dev_phys_link(dev); + int trials = 0; if (!(ehc->i.probe_mask & (1 << dev->devno)) || (ehc->did_probe_mask & (1 << dev->devno))) @@ -2990,6 +3009,25 @@ static int ata_eh_schedule_probe(struct ata_device *dev) ehc->saved_xfer_mode[dev->devno] = 0; ehc->saved_ncq_enabled &= ~(1 << dev->devno); + /* Record and count probe trials on the ering. The specific + * error mask used is irrelevant. Because a successful device + * detection clears the ering, this count accumulates only if + * there are consecutive failed probes. + * + * If the count is equal to or higher than ATA_EH_PROBE_TRIALS + * in the last ATA_EH_PROBE_TRIAL_INTERVAL, link speed is + * forced to 1.5Gbps. + * + * This is to work around cases where failed link speed + * negotiation results in device misdetection leading to + * infinite DEVXCHG or PHRDY CHG events. + */ + ata_ering_record(&dev->ering, 0, AC_ERR_OTHER); + ata_ering_map(&dev->ering, ata_count_probe_trials_cb, &trials); + + if (trials > ATA_EH_PROBE_TRIALS) + sata_down_spd_limit(link, 1); + return 1; } From cf9a590a9eae3b99ca77d8db17afd2d7dbdd0986 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 29 Jan 2009 20:31:35 +0900 Subject: [PATCH 057/111] libata: add no penalty retry request for EH device handling routines Let -EAGAIN from EH device handling routines trigger EH retry without consuming its tries count. This will be used to implement link SPD horkage which requires hardreset to adjust SPD without affecting other EH decisions. As it bypasses the forward progress guarantee provided by the tries count, the requester is responsible for ensuring forward progress. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-eh.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index caa1e9fde3c9..ce2ef0475339 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -3035,7 +3035,11 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err) { struct ata_eh_context *ehc = &dev->link->eh_context; - ehc->tries[dev->devno]--; + /* -EAGAIN from EH routine indicates retry without prejudice. + * The requester is responsible for ensuring forward progress. + */ + if (err != -EAGAIN) + ehc->tries[dev->devno]--; switch (err) { case -ENODEV: From 9062712fa9ed13b531dfc2228086650b8bd6a255 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 29 Jan 2009 20:31:36 +0900 Subject: [PATCH 058/111] libata: implement HORKAGE_1_5_GBPS and apply it to WD My Book 3Gbps is often much more prone to transmission failures. It's usually okay to let EH handle speed down after transmission failures but some WD My Book drives completely shutdown after certain transmission failures and after it only power cycling can revive them. Combined with the fact that external drives often end up with cable assembly which is longer than usual and more likely to have intervening gender, this makes these drives very likely to shutdown under certain configurations virtually rendering them unusable. This patch implements HOARKGE_1_5_GBPS and applies it to WD My Book such that 1.5Gbps is forced once the device is identified. Please take a look at the following bz for related reports. http://bugzilla.kernel.org/show_bug.cgi?id=9913 Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 41 +++++++++++++++++++++++++++++++++++++++ include/linux/libata.h | 1 + 2 files changed, 42 insertions(+) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 3c5965d56c47..9fbf0595f3d4 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2232,6 +2232,40 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, return rc; } +static int ata_do_link_spd_horkage(struct ata_device *dev) +{ + struct ata_link *plink = ata_dev_phys_link(dev); + u32 target, target_limit; + + if (!sata_scr_valid(plink)) + return 0; + + if (dev->horkage & ATA_HORKAGE_1_5_GBPS) + target = 1; + else + return 0; + + target_limit = (1 << target) - 1; + + /* if already on stricter limit, no need to push further */ + if (plink->sata_spd_limit <= target_limit) + return 0; + + plink->sata_spd_limit = target_limit; + + /* Request another EH round by returning -EAGAIN if link is + * going faster than the target speed. Forward progress is + * guaranteed by setting sata_spd_limit to target_limit above. + */ + if (plink->sata_spd > target) { + ata_dev_printk(dev, KERN_INFO, + "applying link speed limit horkage to %s\n", + sata_spd_string(target)); + return -EAGAIN; + } + return 0; +} + static inline u8 ata_dev_knobble(struct ata_device *dev) { struct ata_port *ap = dev->link->ap; @@ -2322,6 +2356,10 @@ int ata_dev_configure(struct ata_device *dev) return 0; } + rc = ata_do_link_spd_horkage(dev); + if (rc) + return rc; + /* let ACPI work its magic */ rc = ata_acpi_on_devcfg(dev); if (rc) @@ -4223,6 +4261,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { /* Devices that do not need bridging limits applied */ { "MTRON MSP-SATA*", NULL, ATA_HORKAGE_BRIDGE_OK, }, + /* Devices which aren't very happy with higher link speeds */ + { "WD My Book", NULL, ATA_HORKAGE_1_5_GBPS, }, + /* End Marker */ { } }; diff --git a/include/linux/libata.h b/include/linux/libata.h index 9dcefee5843c..5d87bc09a1f5 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -380,6 +380,7 @@ enum { ATA_HORKAGE_ATAPI_MOD16_DMA = (1 << 11), /* use ATAPI DMA for commands not multiple of 16 bytes */ ATA_HORKAGE_FIRMWARE_WARN = (1 << 12), /* firwmare update warning */ + ATA_HORKAGE_1_5_GBPS = (1 << 13), /* force 1.5 Gbps */ /* DMA mask for user DMA control: User visible values; DO NOT renumber */ From 802c64b310e5b9dfda6cb50b850b962ed96a9e81 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 2 Feb 2009 21:57:48 -0800 Subject: [PATCH 059/111] sparc64: On non-Niagara, need to touch NMI watchdog in NOHZ mode. When we're idling in NOHZ mode, timer interrupts are not running. Evidence of processing timer interrupts is what the NMI watchdog uses to determine if the CPU is stuck. On Niagara, we'll yield the cpu. This will make the cpu, at worst, hang out in the hypervisor until an interrupt arrives. This will prevent the NMI watchdog timer from firing. However on non-Niagara we just loop executing instructions which will cause the NMI watchdog to keep firing. It won't see timer interrupts happening so it will think the cpu is stuck. Fix this by touching the NMI watchdog in the cpu idle loop on non-Niagara machines. Signed-off-by: David S. Miller --- arch/sparc/kernel/process_64.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c index cc8b5604442c..a73954b87f0a 100644 --- a/arch/sparc/kernel/process_64.c +++ b/arch/sparc/kernel/process_64.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -52,8 +53,10 @@ static void sparc64_yield(int cpu) { - if (tlb_type != hypervisor) + if (tlb_type != hypervisor) { + touch_nmi_watchdog(); return; + } clear_thread_flag(TIF_POLLING_NRFLAG); smp_mb__after_clear_bit(); From eeabac7386ca13bfe1a58afeb04326a9e1a3a20e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 2 Feb 2009 22:08:15 -0800 Subject: [PATCH 060/111] sparc64: Validate kernel generated fault addresses on sparc64. In order to handle all of the cases of address calculation overflow properly, we run sparc 32-bit processes in "address masking" mode when running on a 64-bit kernel. Address masking mode zeros out the top 32-bits of the address calculated for every load and store instruction. However, when we're in privileged mode we have to run with that address masking mode disabled even when accessing userspace from the kernel. To "simulate" the address masking mode we clear the top-bits by hand for 32-bit processes in the fault handler. It is the responsibility of code in the compat layer to properly zero extend addresses used to access userspace. If this isn't followed properly we can get into a fault loop. Say that the user address is 0xf0000000 but for whatever reason the kernel code sign extends this to 64-bit, and then the kernel tries to access the result. In such a case we'll fault on address 0xfffffffff0000000 but the fault handler will process that fault as if it were to address 0xf0000000. We'll loop faulting forever because the fault never gets satisfied. So add a check specifically for this case, when the kernel is faulting on a user address access and the addresses don't match up. This code path is sufficiently slow path, and this bug is sufficiently painful to diagnose, that this kind of bug check is warranted. Signed-off-by: David S. Miller --- arch/sparc/mm/fault_64.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c index a9e474bf6385..1a786abdada3 100644 --- a/arch/sparc/mm/fault_64.c +++ b/arch/sparc/mm/fault_64.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -244,8 +245,14 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) (fault_code & FAULT_CODE_DTLB)) BUG(); + if (test_thread_flag(TIF_32BIT)) { + if (!(regs->tstate & TSTATE_PRIV)) + regs->tpc &= 0xffffffff; + address &= 0xffffffff; + } + if (regs->tstate & TSTATE_PRIV) { - unsigned long tpc = regs->tpc; + unsigned long eaddr, tpc = regs->tpc; /* Sanity check the PC. */ if ((tpc >= KERNBASE && tpc < (unsigned long) __init_end) || @@ -255,6 +262,16 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) bad_kernel_pc(regs, address); return; } + + insn = get_fault_insn(regs, insn); + eaddr = compute_effective_address(regs, insn, 0); + if (WARN_ON_ONCE((eaddr & PAGE_MASK) != (address & PAGE_MASK))){ + printk(KERN_ERR "FAULT: Mismatch kernel fault " + "address: addr[%lx] eaddr[%lx] TPC[%lx]\n", + address, eaddr, tpc); + show_regs(regs); + goto handle_kernel_fault; + } } /* @@ -264,12 +281,6 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) if (in_atomic() || !mm) goto intr_or_no_mm; - if (test_thread_flag(TIF_32BIT)) { - if (!(regs->tstate & TSTATE_PRIV)) - regs->tpc &= 0xffffffff; - address &= 0xffffffff; - } - if (!down_read_trylock(&mm->mmap_sem)) { if ((regs->tstate & TSTATE_PRIV) && !search_exception_tables(regs->tpc)) { From 47a4a0e766e3152dee667ea8fcca8465c8a0759f Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Mon, 2 Feb 2009 22:14:28 -0800 Subject: [PATCH 061/111] sparc: fixup for sparseirq changes Signed-off-by: Stephen Rothwell Signed-off-by: David S. Miller --- arch/sparc/kernel/nmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sparc/kernel/nmi.c b/arch/sparc/kernel/nmi.c index ffc690093343..09f088ed4a64 100644 --- a/arch/sparc/kernel/nmi.c +++ b/arch/sparc/kernel/nmi.c @@ -94,7 +94,7 @@ notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs) pt_regs_trap_type(regs), SIGINT) == NOTIFY_STOP) touched = 1; - sum = kstat_cpu(cpu).irqs[0]; + sum = kstat_irqs_cpu(0, cpu); if (__get_cpu_var(nmi_touch)) { __get_cpu_var(nmi_touch) = 0; touched = 1; From 6139a2360987f55e4490a7813cf69df74ec8b93a Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Thu, 22 Jan 2009 15:37:47 +1100 Subject: [PATCH 062/111] xfs: Check buffer lengths in log recovery Before trying to obtain, read or write a buffer, check that the buffer length is actually valid. If it is not valid, then something read in the recovery process has been corrupted and we should abort recovery. Reported-by: Eric Sesterhenn Tested-by: Eric Sesterhenn Reviewed-by: Christoph Hellwig Reviewed-by: Felix Blyakher Signed-off-by: Dave Chinner Signed-off-by: Felix Blyakher --- fs/xfs/xfs_log_recover.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 35cca98bd94c..b1047de2fffd 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -70,16 +70,21 @@ STATIC void xlog_recover_check_summary(xlog_t *); xfs_buf_t * xlog_get_bp( xlog_t *log, - int num_bblks) + int nbblks) { - ASSERT(num_bblks > 0); + if (nbblks <= 0 || nbblks > log->l_logBBsize) { + xlog_warn("XFS: Invalid block length (0x%x) given for buffer", nbblks); + XFS_ERROR_REPORT("xlog_get_bp(1)", + XFS_ERRLEVEL_HIGH, log->l_mp); + return NULL; + } if (log->l_sectbb_log) { - if (num_bblks > 1) - num_bblks += XLOG_SECTOR_ROUNDUP_BBCOUNT(log, 1); - num_bblks = XLOG_SECTOR_ROUNDUP_BBCOUNT(log, num_bblks); + if (nbblks > 1) + nbblks += XLOG_SECTOR_ROUNDUP_BBCOUNT(log, 1); + nbblks = XLOG_SECTOR_ROUNDUP_BBCOUNT(log, nbblks); } - return xfs_buf_get_noaddr(BBTOB(num_bblks), log->l_mp->m_logdev_targp); + return xfs_buf_get_noaddr(BBTOB(nbblks), log->l_mp->m_logdev_targp); } void @@ -102,6 +107,13 @@ xlog_bread( { int error; + if (nbblks <= 0 || nbblks > log->l_logBBsize) { + xlog_warn("XFS: Invalid block length (0x%x) given for buffer", nbblks); + XFS_ERROR_REPORT("xlog_bread(1)", + XFS_ERRLEVEL_HIGH, log->l_mp); + return EFSCORRUPTED; + } + if (log->l_sectbb_log) { blk_no = XLOG_SECTOR_ROUNDDOWN_BLKNO(log, blk_no); nbblks = XLOG_SECTOR_ROUNDUP_BBCOUNT(log, nbblks); @@ -139,6 +151,13 @@ xlog_bwrite( { int error; + if (nbblks <= 0 || nbblks > log->l_logBBsize) { + xlog_warn("XFS: Invalid block length (0x%x) given for buffer", nbblks); + XFS_ERROR_REPORT("xlog_bwrite(1)", + XFS_ERRLEVEL_HIGH, log->l_mp); + return EFSCORRUPTED; + } + if (log->l_sectbb_log) { blk_no = XLOG_SECTOR_ROUNDDOWN_BLKNO(log, blk_no); nbblks = XLOG_SECTOR_ROUNDUP_BBCOUNT(log, nbblks); From 43f3f057c56d030546145696627f13f95735be95 Mon Sep 17 00:00:00 2001 From: Felix Blyakher Date: Thu, 22 Jan 2009 21:34:05 -0600 Subject: [PATCH 063/111] [XFS] Warn on transaction in flight on read-only remount Till VFS can correctly support read-only remount without racing, use WARN_ON instead of BUG_ON on detecting transaction in flight after quiescing filesystem. Signed-off-by: Felix Blyakher Reviewed-by: Christoph Hellwig --- fs/xfs/linux-2.6/xfs_sync.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c index 2ed035354c26..a608e72fa405 100644 --- a/fs/xfs/linux-2.6/xfs_sync.c +++ b/fs/xfs/linux-2.6/xfs_sync.c @@ -371,7 +371,11 @@ xfs_quiesce_attr( /* flush inodes and push all remaining buffers out to disk */ xfs_quiesce_fs(mp); - ASSERT_ALWAYS(atomic_read(&mp->m_active_trans) == 0); + /* + * Just warn here till VFS can correctly support + * read-only remount without racing. + */ + WARN_ON(atomic_read(&mp->m_active_trans) != 0); /* Push the superblock and write an unmount record */ error = xfs_log_sbcount(mp, 1); From 67dd82462d553c35bef14de1bf8afcb1095e041d Mon Sep 17 00:00:00 2001 From: Filip Aben Date: Tue, 3 Feb 2009 15:13:26 -0800 Subject: [PATCH 064/111] hso: add new device id's This patch adds a few device ID's. It also removes an ID that was used in an internal engineering version of a device and will never see commercial light. Even if this ID will be 'recycled' in the future, which is very unlikely, we don't know what kind of device will be behind it. Therefore it's safer to remove it. Signed-off-by: Filip Aben Signed-off-by: David S. Miller --- drivers/net/usb/hso.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 0d0fa91c0251..fe98acaead97 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -455,6 +455,7 @@ static const struct usb_device_id hso_ids[] = { {icon321_port_device(0x0af0, 0xd033)}, /* Icon-322 */ {USB_DEVICE(0x0af0, 0x7301)}, /* GE40x */ {USB_DEVICE(0x0af0, 0x7361)}, /* GE40x */ + {USB_DEVICE(0x0af0, 0x7381)}, /* GE40x */ {USB_DEVICE(0x0af0, 0x7401)}, /* GI 0401 */ {USB_DEVICE(0x0af0, 0x7501)}, /* GTM 382 */ {USB_DEVICE(0x0af0, 0x7601)}, /* GE40x */ @@ -462,7 +463,8 @@ static const struct usb_device_id hso_ids[] = { {USB_DEVICE(0x0af0, 0x7801)}, {USB_DEVICE(0x0af0, 0x7901)}, {USB_DEVICE(0x0af0, 0x7361)}, - {icon321_port_device(0x0af0, 0xd051)}, + {USB_DEVICE(0x0af0, 0xd057)}, + {USB_DEVICE(0x0af0, 0xd055)}, {} }; MODULE_DEVICE_TABLE(usb, hso_ids); From a9d3a146923d374b945aa388dc884df69564a818 Mon Sep 17 00:00:00 2001 From: Cord Walter Date: Tue, 3 Feb 2009 15:14:05 -0800 Subject: [PATCH 065/111] pcnet_cs: Fix misuse of the equality operator. Signed-off-by: Cord Walter Signed-off-by: Komuro Signed-off-by: David S. Miller --- drivers/net/pcmcia/pcnet_cs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index c38ed777f0a8..a6999403f37b 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -586,7 +586,7 @@ static int pcnet_config(struct pcmcia_device *link) } if ((link->conf.ConfigBase == 0x03c0) - && (link->manf_id == 0x149) && (link->card_id = 0xc1ab)) { + && (link->manf_id == 0x149) && (link->card_id == 0xc1ab)) { printk(KERN_INFO "pcnet_cs: this is an AX88190 card!\n"); printk(KERN_INFO "pcnet_cs: use axnet_cs instead.\n"); goto failed; From 714c48f1bb553a2e5dd8d6ff66accc7c51218ac9 Mon Sep 17 00:00:00 2001 From: Dean Nelson Date: Tue, 3 Feb 2009 15:16:17 -0800 Subject: [PATCH 066/111] sgi-xp: link XPNET's net_device_ops to its net_device structure A recent patch by Stephen Hemminger to convert XPNET to use net_device_ops and internal net_device_stats failed to link the net_device_ops structure to the net_device structure. See commit e8ac9c55f28482f5b2f497a8e7eb90985db237c2 ("xpnet: convert devices to new API"). Signed-off-by: Dean Nelson Signed-off-by: David S. Miller --- drivers/misc/sgi-xp/xpnet.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/misc/sgi-xp/xpnet.c b/drivers/misc/sgi-xp/xpnet.c index 7957f525b2f4..6faefcffcb53 100644 --- a/drivers/misc/sgi-xp/xpnet.c +++ b/drivers/misc/sgi-xp/xpnet.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1999-2008 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 1999-2009 Silicon Graphics, Inc. All rights reserved. */ /* @@ -551,6 +551,7 @@ xpnet_init(void) netif_carrier_off(xpnet_device); + xpnet_device->netdev_ops = &xpnet_netdev_ops; xpnet_device->mtu = XPNET_DEF_MTU; /* From 4d7155b932b8129c72e2f2714890e20b2a05e0b7 Mon Sep 17 00:00:00 2001 From: Karsten Keil Date: Tue, 3 Feb 2009 15:18:01 -0800 Subject: [PATCH 067/111] e1000: Fix PCI enable to honor the need_ioport flag On machine were no IO ports are assigned the call to pci_enable_device() will fail, even if need_ioport is false, we need to use pci_enable_device_mem() here. Signed-off-by: Karsten Keil Signed-off-by: David S. Miller --- drivers/net/e1000/e1000_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index c986978ce761..6bd63cc67b3e 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -940,7 +940,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, err = pci_enable_device(pdev); } else { bars = pci_select_bars(pdev, IORESOURCE_MEM); - err = pci_enable_device(pdev); + err = pci_enable_device_mem(pdev); } if (err) return err; From 55128bc23e9ab44e97f81f6cd349035230ee59a6 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 3 Feb 2009 15:20:13 -0800 Subject: [PATCH 068/111] sunrpc: fix rdma dependencies Fix sunrpc/rdma build dependencies. Survives 12 build combinations of INET, IPV6, SUNRPC, INFINIBAND, and INFINIBAND_ADDR_TRANS. ERROR: "rdma_destroy_id" [net/sunrpc/xprtrdma/xprtrdma.ko] undefined! ERROR: "rdma_connect" [net/sunrpc/xprtrdma/xprtrdma.ko] undefined! ERROR: "rdma_destroy_qp" [net/sunrpc/xprtrdma/xprtrdma.ko] undefined! ERROR: "rdma_create_id" [net/sunrpc/xprtrdma/xprtrdma.ko] undefined! ERROR: "rdma_create_qp" [net/sunrpc/xprtrdma/xprtrdma.ko] undefined! ERROR: "rdma_resolve_route" [net/sunrpc/xprtrdma/xprtrdma.ko] undefined! ERROR: "rdma_disconnect" [net/sunrpc/xprtrdma/xprtrdma.ko] undefined! ERROR: "rdma_resolve_addr" [net/sunrpc/xprtrdma/xprtrdma.ko] undefined! ERROR: "rdma_accept" [net/sunrpc/xprtrdma/svcrdma.ko] undefined! ERROR: "rdma_destroy_id" [net/sunrpc/xprtrdma/svcrdma.ko] undefined! ERROR: "rdma_listen" [net/sunrpc/xprtrdma/svcrdma.ko] undefined! ERROR: "rdma_create_id" [net/sunrpc/xprtrdma/svcrdma.ko] undefined! ERROR: "rdma_create_qp" [net/sunrpc/xprtrdma/svcrdma.ko] undefined! ERROR: "rdma_bind_addr" [net/sunrpc/xprtrdma/svcrdma.ko] undefined! ERROR: "rdma_disconnect" [net/sunrpc/xprtrdma/svcrdma.ko] undefined! Signed-off-by: Randy Dunlap Signed-off-by: David S. Miller --- net/sunrpc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig index dcef600d0bf5..5592883e1e4a 100644 --- a/net/sunrpc/Kconfig +++ b/net/sunrpc/Kconfig @@ -6,7 +6,7 @@ config SUNRPC_GSS config SUNRPC_XPRT_RDMA tristate - depends on SUNRPC && INFINIBAND && EXPERIMENTAL + depends on SUNRPC && INFINIBAND && INFINIBAND_ADDR_TRANS && EXPERIMENTAL default SUNRPC && INFINIBAND help This option allows the NFS client and server to support From 9b02605826903203d5301049c1f52e722584785c Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 3 Feb 2009 16:28:23 -0800 Subject: [PATCH 069/111] sparc64: Kill bogus TPC/address truncation during 32-bit faults. This builds upon eeabac7386ca13bfe1a58afeb04326a9e1a3a20e ("sparc64: Validate kernel generated fault addresses on sparc64.") Upon further consideration, we actually should never see any fault addresses for 32-bit tasks with the upper 32-bits set. If it does every happen, by definition it's a bug. Whatever context created that fault would only have that fault satisfied if we used the full 64-bit address. If we truncate it, we'll always fault the wrong address and we'll always loop faulting forever. So catch such conditions and mark them as errors always. Log the error and fail the fault. Signed-off-by: David S. Miller --- arch/sparc/mm/fault_64.c | 49 ++++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c index 1a786abdada3..4ab8993b0863 100644 --- a/arch/sparc/mm/fault_64.c +++ b/arch/sparc/mm/fault_64.c @@ -225,6 +225,30 @@ static void do_kernel_fault(struct pt_regs *regs, int si_code, int fault_code, unhandled_fault (address, current, regs); } +static void noinline bogus_32bit_fault_tpc(struct pt_regs *regs) +{ + static int times; + + if (times++ < 10) + printk(KERN_ERR "FAULT[%s:%d]: 32-bit process reports " + "64-bit TPC [%lx]\n", + current->comm, current->pid, + regs->tpc); + show_regs(regs); +} + +static void noinline bogus_32bit_fault_address(struct pt_regs *regs, + unsigned long addr) +{ + static int times; + + if (times++ < 10) + printk(KERN_ERR "FAULT[%s:%d]: 32-bit process " + "reports 64-bit fault address [%lx]\n", + current->comm, current->pid, addr); + show_regs(regs); +} + asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) { struct mm_struct *mm = current->mm; @@ -246,13 +270,20 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) BUG(); if (test_thread_flag(TIF_32BIT)) { - if (!(regs->tstate & TSTATE_PRIV)) - regs->tpc &= 0xffffffff; - address &= 0xffffffff; + if (!(regs->tstate & TSTATE_PRIV)) { + if (unlikely((regs->tpc >> 32) != 0)) { + bogus_32bit_fault_tpc(regs); + goto intr_or_no_mm; + } + } + if (unlikely((address >> 32) != 0)) { + bogus_32bit_fault_address(regs, address); + goto intr_or_no_mm; + } } if (regs->tstate & TSTATE_PRIV) { - unsigned long eaddr, tpc = regs->tpc; + unsigned long tpc = regs->tpc; /* Sanity check the PC. */ if ((tpc >= KERNBASE && tpc < (unsigned long) __init_end) || @@ -262,16 +293,6 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) bad_kernel_pc(regs, address); return; } - - insn = get_fault_insn(regs, insn); - eaddr = compute_effective_address(regs, insn, 0); - if (WARN_ON_ONCE((eaddr & PAGE_MASK) != (address & PAGE_MASK))){ - printk(KERN_ERR "FAULT: Mismatch kernel fault " - "address: addr[%lx] eaddr[%lx] TPC[%lx]\n", - address, eaddr, tpc); - show_regs(regs); - goto handle_kernel_fault; - } } /* From 5193535517825f9a07967e4868a1103013d0a99d Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Tue, 3 Feb 2009 13:12:58 +0100 Subject: [PATCH 070/111] Fix my email address in qd65xx.[ch]/pata_qdi.c The @fnac.net will be shut down within a couple of months, so fix my email address. Signed-off-by: Samuel Thibault Signed-off-by: Linus Torvalds --- drivers/ata/pata_qdi.c | 2 +- drivers/ide/qd65xx.c | 2 +- drivers/ide/qd65xx.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/ata/pata_qdi.c b/drivers/ata/pata_qdi.c index 3080f371222c..f1b26f7c8e4d 100644 --- a/drivers/ata/pata_qdi.c +++ b/drivers/ata/pata_qdi.c @@ -12,7 +12,7 @@ * * Probe code based on drivers/ide/legacy/qd65xx.c * Rewritten from the work of Colten Edwards by - * Samuel Thibault + * Samuel Thibault */ #include diff --git a/drivers/ide/qd65xx.c b/drivers/ide/qd65xx.c index 5b2e3af43c4b..08c4fa35e9b1 100644 --- a/drivers/ide/qd65xx.c +++ b/drivers/ide/qd65xx.c @@ -16,7 +16,7 @@ /* * Rewritten from the work of Colten Edwards by - * Samuel Thibault + * Samuel Thibault */ #include diff --git a/drivers/ide/qd65xx.h b/drivers/ide/qd65xx.h index 6636f9665d16..d7e67a1a1dcc 100644 --- a/drivers/ide/qd65xx.h +++ b/drivers/ide/qd65xx.h @@ -4,7 +4,7 @@ /* * Authors: Petr Soucek - * Samuel Thibault + * Samuel Thibault */ /* truncates a in [b,c] */ From dcf6a79dda5cc2a2bec183e50d829030c0972aaa Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 2 Feb 2009 18:33:49 +0200 Subject: [PATCH 071/111] write-back: fix nr_to_write counter Commit 05fe478dd04e02fa230c305ab9b5616669821dd3 introduced some @wbc->nr_to_write breakage. It made the following changes: 1. Decrement wbc->nr_to_write instead of nr_to_write 2. Decrement wbc->nr_to_write _only_ if wbc->sync_mode == WB_SYNC_NONE 3. If synced nr_to_write pages, stop only if if wbc->sync_mode == WB_SYNC_NONE, otherwise keep going. However, according to the commit message, the intention was to only make change 3. Change 1 is a bug. Change 2 does not seem to be necessary, and it breaks UBIFS expectations, so if needed, it should be done separately later. And change 2 does not seem to be documented in the commit message. This patch does the following: 1. Undo changes 1 and 2 2. Add a comment explaining change 3 (it very useful to have comments in _code_, not only in the commit). Signed-off-by: Artem Bityutskiy Acked-by: Nick Piggin Cc: Andrew Morton Signed-off-by: Linus Torvalds --- mm/page-writeback.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/mm/page-writeback.c b/mm/page-writeback.c index b493db7841dc..dc32dae01e5f 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -1051,13 +1051,22 @@ int write_cache_pages(struct address_space *mapping, } } - if (wbc->sync_mode == WB_SYNC_NONE) { - wbc->nr_to_write--; - if (wbc->nr_to_write <= 0) { - done = 1; - break; - } + if (nr_to_write > 0) + nr_to_write--; + else if (wbc->sync_mode == WB_SYNC_NONE) { + /* + * We stop writing back only if we are not + * doing integrity sync. In case of integrity + * sync we have to keep going because someone + * may be concurrently dirtying pages, and we + * might have synced a lot of newly appeared + * dirty pages, but have not synced all of the + * old dirty pages. + */ + done = 1; + break; } + if (wbc->nonblocking && bdi_write_congested(bdi)) { wbc->encountered_congestion = 1; done = 1; From d3522648676d4c8869e5539bca081820e69e24a4 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 072/111] Blackfin arch: scrub comments/whitespace/cvs keywords Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/include/asm/kgdb.h | 53 +++++++++----------------------- 1 file changed, 15 insertions(+), 38 deletions(-) diff --git a/arch/blackfin/include/asm/kgdb.h b/arch/blackfin/include/asm/kgdb.h index 26ebac6646d8..c8b256d2ea30 100644 --- a/arch/blackfin/include/asm/kgdb.h +++ b/arch/blackfin/include/asm/kgdb.h @@ -1,32 +1,8 @@ -/* - * File: include/asm-blackfin/kgdb.h - * Based on: - * Author: Sonic Zhang +/* Blackfin KGDB header * - * Created: - * Description: + * Copyright 2005-2009 Analog Devices Inc. * - * Rev: $Id: kgdb_bfin_linux-2.6.x.patch 4934 2007-02-13 09:32:11Z sonicz $ - * - * Modified: - * Copyright 2005-2006 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * 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, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * Licensed under the GPL-2 or later. */ #ifndef __ASM_BLACKFIN_KGDB_H__ @@ -37,17 +13,18 @@ /* gdb locks */ #define KGDB_MAX_NO_CPUS 8 -/************************************************************************/ -/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/ -/* at least NUMREGBYTES*2 are needed for register packets */ -/* Longer buffer is needed to list all threads */ +/* + * BUFMAX defines the maximum number of characters in inbound/outbound buffers. + * At least NUMREGBYTES*2 are needed for register packets. + * Longer buffer is needed to list all threads. + */ #define BUFMAX 2048 /* - * Note that this register image is different from - * the register image that Linux produces at interrupt time. - * - * Linux's register image is defined by struct pt_regs in ptrace.h. + * Note that this register image is different from + * the register image that Linux produces at interrupt time. + * + * Linux's register image is defined by struct pt_regs in ptrace.h. */ enum regnames { /* Core Registers */ @@ -104,14 +81,14 @@ enum regnames { BFIN_RETX, BFIN_RETN, BFIN_RETE, - + /* Pseudo Registers */ BFIN_PC, BFIN_CC, BFIN_EXTRA1, /* Address of .text section. */ BFIN_EXTRA2, /* Address of .data section. */ BFIN_EXTRA3, /* Address of .bss section. */ - BFIN_FDPIC_EXEC, + BFIN_FDPIC_EXEC, BFIN_FDPIC_INTERP, /* MMRs */ @@ -126,7 +103,7 @@ enum regnames { static inline void arch_kgdb_breakpoint(void) { - asm(" EXCPT 2;"); + asm("EXCPT 2;"); } #define BREAK_INSTR_SIZE 2 #define CACHE_FLUSH_IS_SAFE 1 From 2f89c0632f6e27cc3e5eb66605490ddf67ef4953 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 073/111] Blackfin arch: add support for mobile ddr bf54x parts Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/Kconfig | 52 +++++++++++++++---- arch/blackfin/Makefile | 10 ++++ arch/blackfin/mach-bf548/include/mach/bf548.h | 12 +++++ 3 files changed, 63 insertions(+), 11 deletions(-) diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index a949c4fbbddd..8f1f97d56e1e 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -169,26 +169,51 @@ config BF542 help BF542 Processor Support. +config BF542M + bool "BF542m" + help + BF542 Processor Support. + config BF544 bool "BF544" help BF544 Processor Support. +config BF544M + bool "BF544m" + help + BF544 Processor Support. + config BF547 bool "BF547" help BF547 Processor Support. +config BF547M + bool "BF547m" + help + BF547 Processor Support. + config BF548 bool "BF548" help BF548 Processor Support. +config BF548M + bool "BF548m" + help + BF548 Processor Support. + config BF549 bool "BF549" help BF549 Processor Support. +config BF549M + bool "BF549m" + help + BF549 Processor Support. + config BF561 bool "BF561" help @@ -224,39 +249,39 @@ config TICK_SOURCE_SYSTMR0 config BF_REV_MIN int - default 0 if (BF51x || BF52x || BF54x) + default 0 if (BF51x || BF52x || (BF54x && !BF54xM)) default 2 if (BF537 || BF536 || BF534) - default 3 if (BF561 ||BF533 || BF532 || BF531) + default 3 if (BF561 || BF533 || BF532 || BF531 || BF54xM) default 4 if (BF538 || BF539) config BF_REV_MAX int - default 2 if (BF51x || BF52x || BF54x) - default 3 if (BF537 || BF536 || BF534) + default 2 if (BF51x || BF52x || (BF54x && !BF54xM)) + default 3 if (BF537 || BF536 || BF534 || BF54xM) default 5 if (BF561 || BF538 || BF539) default 6 if (BF533 || BF532 || BF531) choice prompt "Silicon Rev" - default BF_REV_0_1 if (BF51x || BF52x || BF54x) + default BF_REV_0_1 if (BF51x || BF52x || (BF54x && !BF54xM)) default BF_REV_0_2 if (BF534 || BF536 || BF537) - default BF_REV_0_3 if (BF531 || BF532 || BF533 || BF561) + default BF_REV_0_3 if (BF531 || BF532 || BF533 || BF54xM || BF561) config BF_REV_0_0 bool "0.0" - depends on (BF51x || BF52x || BF54x) + depends on (BF51x || BF52x || (BF54x && !BF54xM)) config BF_REV_0_1 bool "0.1" - depends on (BF52x || BF54x) + depends on (BF52x || (BF54x && !BF54xM)) config BF_REV_0_2 bool "0.2" - depends on (BF52x || BF537 || BF536 || BF534 || BF54x) + depends on (BF52x || BF537 || BF536 || BF534 || (BF54x && !BF54xM)) config BF_REV_0_3 bool "0.3" - depends on (BF561 || BF537 || BF536 || BF534 || BF533 || BF532 || BF531) + depends on (BF54xM || BF561 || BF537 || BF536 || BF534 || BF533 || BF532 || BF531) config BF_REV_0_4 bool "0.4" @@ -293,9 +318,14 @@ config BF53x depends on (BF531 || BF532 || BF533 || BF534 || BF536 || BF537) default y +config BF54xM + bool + depends on (BF542M || BF544M || BF547M || BF548M || BF549M) + default y + config BF54x bool - depends on (BF542 || BF544 || BF547 || BF548 || BF549) + depends on (BF542 || BF544 || BF547 || BF548 || BF549 || BF54xM) default y config MEM_GENERIC_BOARD diff --git a/arch/blackfin/Makefile b/arch/blackfin/Makefile index e550c8d46066..8dd003b1aa8e 100644 --- a/arch/blackfin/Makefile +++ b/arch/blackfin/Makefile @@ -40,10 +40,15 @@ machine-$(CONFIG_BF537) := bf537 machine-$(CONFIG_BF538) := bf538 machine-$(CONFIG_BF539) := bf538 machine-$(CONFIG_BF542) := bf548 +machine-$(CONFIG_BF542M) := bf548 machine-$(CONFIG_BF544) := bf548 +machine-$(CONFIG_BF544M) := bf548 machine-$(CONFIG_BF547) := bf548 +machine-$(CONFIG_BF547M) := bf548 machine-$(CONFIG_BF548) := bf548 +machine-$(CONFIG_BF548M) := bf548 machine-$(CONFIG_BF549) := bf548 +machine-$(CONFIG_BF549M) := bf548 machine-$(CONFIG_BF561) := bf561 MACHINE := $(machine-y) export MACHINE @@ -67,10 +72,15 @@ cpu-$(CONFIG_BF537) := bf537 cpu-$(CONFIG_BF538) := bf538 cpu-$(CONFIG_BF539) := bf539 cpu-$(CONFIG_BF542) := bf542 +cpu-$(CONFIG_BF542M) := bf542m cpu-$(CONFIG_BF544) := bf544 +cpu-$(CONFIG_BF544M) := bf544m cpu-$(CONFIG_BF547) := bf547 +cpu-$(CONFIG_BF547M) := bf547m cpu-$(CONFIG_BF548) := bf548 +cpu-$(CONFIG_BF548M) := bf548m cpu-$(CONFIG_BF549) := bf549 +cpu-$(CONFIG_BF549M) := bf549m cpu-$(CONFIG_BF561) := bf561 rev-$(CONFIG_BF_REV_0_0) := 0.0 diff --git a/arch/blackfin/mach-bf548/include/mach/bf548.h b/arch/blackfin/mach-bf548/include/mach/bf548.h index f0e569984810..cd31f72bdd82 100644 --- a/arch/blackfin/mach-bf548/include/mach/bf548.h +++ b/arch/blackfin/mach-bf548/include/mach/bf548.h @@ -104,6 +104,18 @@ #define AMGCTLVAL (V_AMBEN | V_AMCKEN) +#if defined(CONFIG_BF542M) +# define CONFIG_BF542 +#elif defined(CONFIG_BF544M) +# define CONFIG_BF544 +#elif defined(CONFIG_BF547M) +# define CONFIG_BF547 +#elif defined(CONFIG_BF548M) +# define CONFIG_BF548 +#elif defined(CONFIG_BF549M) +# define CONFIG_BF549 +#endif + #if defined(CONFIG_BF542) # define CPU "BF542" # define CPUID 0x27de From 4c4073d49f578422537ce16f6d42ebeb4f741e6d Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 074/111] Blackfin arch: line up machine-/cpu- vars after BF54xM addition Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/Makefile | 96 +++++++++++++++++++++--------------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/arch/blackfin/Makefile b/arch/blackfin/Makefile index 8dd003b1aa8e..d54c8283825c 100644 --- a/arch/blackfin/Makefile +++ b/arch/blackfin/Makefile @@ -21,67 +21,67 @@ KALLSYMS += --symbol-prefix=_ KBUILD_DEFCONFIG := BF537-STAMP_defconfig # setup the machine name and the machine dependent settings -machine-$(CONFIG_BF512) := bf518 -machine-$(CONFIG_BF514) := bf518 -machine-$(CONFIG_BF516) := bf518 -machine-$(CONFIG_BF518) := bf518 -machine-$(CONFIG_BF522) := bf527 -machine-$(CONFIG_BF523) := bf527 -machine-$(CONFIG_BF524) := bf527 -machine-$(CONFIG_BF525) := bf527 -machine-$(CONFIG_BF526) := bf527 -machine-$(CONFIG_BF527) := bf527 -machine-$(CONFIG_BF531) := bf533 -machine-$(CONFIG_BF532) := bf533 -machine-$(CONFIG_BF533) := bf533 -machine-$(CONFIG_BF534) := bf537 -machine-$(CONFIG_BF536) := bf537 -machine-$(CONFIG_BF537) := bf537 -machine-$(CONFIG_BF538) := bf538 -machine-$(CONFIG_BF539) := bf538 -machine-$(CONFIG_BF542) := bf548 +machine-$(CONFIG_BF512) := bf518 +machine-$(CONFIG_BF514) := bf518 +machine-$(CONFIG_BF516) := bf518 +machine-$(CONFIG_BF518) := bf518 +machine-$(CONFIG_BF522) := bf527 +machine-$(CONFIG_BF523) := bf527 +machine-$(CONFIG_BF524) := bf527 +machine-$(CONFIG_BF525) := bf527 +machine-$(CONFIG_BF526) := bf527 +machine-$(CONFIG_BF527) := bf527 +machine-$(CONFIG_BF531) := bf533 +machine-$(CONFIG_BF532) := bf533 +machine-$(CONFIG_BF533) := bf533 +machine-$(CONFIG_BF534) := bf537 +machine-$(CONFIG_BF536) := bf537 +machine-$(CONFIG_BF537) := bf537 +machine-$(CONFIG_BF538) := bf538 +machine-$(CONFIG_BF539) := bf538 +machine-$(CONFIG_BF542) := bf548 machine-$(CONFIG_BF542M) := bf548 -machine-$(CONFIG_BF544) := bf548 +machine-$(CONFIG_BF544) := bf548 machine-$(CONFIG_BF544M) := bf548 -machine-$(CONFIG_BF547) := bf548 +machine-$(CONFIG_BF547) := bf548 machine-$(CONFIG_BF547M) := bf548 -machine-$(CONFIG_BF548) := bf548 +machine-$(CONFIG_BF548) := bf548 machine-$(CONFIG_BF548M) := bf548 -machine-$(CONFIG_BF549) := bf548 +machine-$(CONFIG_BF549) := bf548 machine-$(CONFIG_BF549M) := bf548 -machine-$(CONFIG_BF561) := bf561 +machine-$(CONFIG_BF561) := bf561 MACHINE := $(machine-y) export MACHINE -cpu-$(CONFIG_BF512) := bf512 -cpu-$(CONFIG_BF514) := bf514 -cpu-$(CONFIG_BF516) := bf516 -cpu-$(CONFIG_BF518) := bf518 -cpu-$(CONFIG_BF522) := bf522 -cpu-$(CONFIG_BF523) := bf523 -cpu-$(CONFIG_BF524) := bf524 -cpu-$(CONFIG_BF525) := bf525 -cpu-$(CONFIG_BF526) := bf526 -cpu-$(CONFIG_BF527) := bf527 -cpu-$(CONFIG_BF531) := bf531 -cpu-$(CONFIG_BF532) := bf532 -cpu-$(CONFIG_BF533) := bf533 -cpu-$(CONFIG_BF534) := bf534 -cpu-$(CONFIG_BF536) := bf536 -cpu-$(CONFIG_BF537) := bf537 -cpu-$(CONFIG_BF538) := bf538 -cpu-$(CONFIG_BF539) := bf539 -cpu-$(CONFIG_BF542) := bf542 +cpu-$(CONFIG_BF512) := bf512 +cpu-$(CONFIG_BF514) := bf514 +cpu-$(CONFIG_BF516) := bf516 +cpu-$(CONFIG_BF518) := bf518 +cpu-$(CONFIG_BF522) := bf522 +cpu-$(CONFIG_BF523) := bf523 +cpu-$(CONFIG_BF524) := bf524 +cpu-$(CONFIG_BF525) := bf525 +cpu-$(CONFIG_BF526) := bf526 +cpu-$(CONFIG_BF527) := bf527 +cpu-$(CONFIG_BF531) := bf531 +cpu-$(CONFIG_BF532) := bf532 +cpu-$(CONFIG_BF533) := bf533 +cpu-$(CONFIG_BF534) := bf534 +cpu-$(CONFIG_BF536) := bf536 +cpu-$(CONFIG_BF537) := bf537 +cpu-$(CONFIG_BF538) := bf538 +cpu-$(CONFIG_BF539) := bf539 +cpu-$(CONFIG_BF542) := bf542 cpu-$(CONFIG_BF542M) := bf542m -cpu-$(CONFIG_BF544) := bf544 +cpu-$(CONFIG_BF544) := bf544 cpu-$(CONFIG_BF544M) := bf544m -cpu-$(CONFIG_BF547) := bf547 +cpu-$(CONFIG_BF547) := bf547 cpu-$(CONFIG_BF547M) := bf547m -cpu-$(CONFIG_BF548) := bf548 +cpu-$(CONFIG_BF548) := bf548 cpu-$(CONFIG_BF548M) := bf548m -cpu-$(CONFIG_BF549) := bf549 +cpu-$(CONFIG_BF549) := bf549 cpu-$(CONFIG_BF549M) := bf549m -cpu-$(CONFIG_BF561) := bf561 +cpu-$(CONFIG_BF561) := bf561 rev-$(CONFIG_BF_REV_0_0) := 0.0 rev-$(CONFIG_BF_REV_0_1) := 0.1 From c6bbd8ac54742f657bd223e03b5b70e73ba092cd Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 075/111] Blackfin arch: enable bfin_eth in bf51x by default Signed-off-by: Sonic Zhang Signed-off-by: Bryan Wu --- arch/blackfin/configs/BF518F-EZBRD_defconfig | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/blackfin/configs/BF518F-EZBRD_defconfig b/arch/blackfin/configs/BF518F-EZBRD_defconfig index defb9785c65b..18e9784376f2 100644 --- a/arch/blackfin/configs/BF518F-EZBRD_defconfig +++ b/arch/blackfin/configs/BF518F-EZBRD_defconfig @@ -1,6 +1,7 @@ # # Automatically generated make config: don't edit # Linux kernel version: 2.6.28-rc2 +# Fri Jan 9 17:58:41 2009 # # CONFIG_MMU is not set # CONFIG_FPU is not set @@ -149,6 +150,7 @@ CONFIG_BF_REV_0_0=y # CONFIG_BF_REV_ANY is not set # CONFIG_BF_REV_NONE is not set CONFIG_BF51x=y +CONFIG_MEM_MT48LC32M8A2_75=y CONFIG_BFIN518F_EZBRD=y # @@ -598,7 +600,10 @@ CONFIG_PHYLIB=y # CONFIG_MDIO_BITBANG is not set CONFIG_NET_ETHERNET=y CONFIG_MII=y -# CONFIG_BFIN_MAC is not set +CONFIG_BFIN_MAC=y +CONFIG_BFIN_TX_DESC_NUM=10 +CONFIG_BFIN_RX_DESC_NUM=20 +# CONFIG_BFIN_MAC_RMII is not set # CONFIG_SMC91X is not set # CONFIG_SMSC911X is not set # CONFIG_DM9000 is not set From 41245ac5952e5b05e6fbb7c188eae0947f640189 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 076/111] Blackfin arch: fix bug - Dmacopy failed in BF537-STAMP Dmacopy failed in BF537-STAMP when copy from SRAM to SDRAM and kernel will reboot automatically. Fixing by doing a SSYNC before mucking with DMA registers Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/kernel/bfin_dma_5xx.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c index 07e02c0d1c07..8531693fb48d 100644 --- a/arch/blackfin/kernel/bfin_dma_5xx.c +++ b/arch/blackfin/kernel/bfin_dma_5xx.c @@ -249,6 +249,13 @@ static void __dma_memcpy(u32 daddr, s16 dmod, u32 saddr, s16 smod, size_t cnt, u spin_lock_irqsave(&mdma_lock, flags); + /* Force a sync in case a previous config reset on this channel + * occurred. This is needed so subsequent writes to DMA registers + * are not spuriously lost/corrupted. Do it under irq lock and + * without the anomaly version (because we are atomic already). + */ + __builtin_bfin_ssync(); + if (bfin_read_MDMA_S0_CONFIG()) while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)) continue; From 331693129d1764e38b15561e5712347fd591b2a9 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 077/111] Blackfin arch: Fix Bug - Kernel does not boot if re-program clocks On BF561 EBIU_SDGCTL bit 31 controls the SDRAM external data path width, typically set 0 for a 32-bit bus width. On other Blackfin derivatives this bit should be set by default. Signed-off-by: Michael Hennerich Signed-off-by: Bryan Wu --- arch/blackfin/include/asm/mem_init.h | 2 +- arch/blackfin/mach-common/clocks-init.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/blackfin/include/asm/mem_init.h b/arch/blackfin/include/asm/mem_init.h index 255a9316ad36..61f7487fbf12 100644 --- a/arch/blackfin/include/asm/mem_init.h +++ b/arch/blackfin/include/asm/mem_init.h @@ -115,7 +115,7 @@ #define mem_SDRRC (((CONFIG_SCLK_HZ / 1000) * SDRAM_Tref) / SDRAM_NRA) - (SDRAM_tRAS_num + SDRAM_tRP_num) /* Enable SCLK Out */ -#define mem_SDGCTL (0x80000000 | SCTLE | SDRAM_CL | SDRAM_tRAS | SDRAM_tRP | SDRAM_tRCD | SDRAM_tWR | PSS) +#define mem_SDGCTL (SCTLE | SDRAM_CL | SDRAM_tRAS | SDRAM_tRP | SDRAM_tRCD | SDRAM_tWR | PSS) #else #define mem_SDRRC CONFIG_MEM_SDRRC #define mem_SDGCTL CONFIG_MEM_SDGCTL diff --git a/arch/blackfin/mach-common/clocks-init.c b/arch/blackfin/mach-common/clocks-init.c index 5d182abefc7b..9dddb6f8cc85 100644 --- a/arch/blackfin/mach-common/clocks-init.c +++ b/arch/blackfin/mach-common/clocks-init.c @@ -14,6 +14,7 @@ #include #include +#define SDGCTL_WIDTH (1 << 31) /* SDRAM external data path width */ #define PLL_CTL_VAL \ (((CONFIG_VCO_MULT & 63) << 9) | CLKIN_HALF | \ (PLL_BYPASS << 8) | (ANOMALY_05000265 ? 0x8000 : 0)) @@ -76,7 +77,7 @@ void init_clocks(void) bfin_write_PLL_DIV(CONFIG_CCLK_ACT_DIV | CONFIG_SCLK_DIV); #ifdef EBIU_SDGCTL bfin_write_EBIU_SDRRC(mem_SDRRC); - bfin_write_EBIU_SDGCTL(mem_SDGCTL); + bfin_write_EBIU_SDGCTL((bfin_read_EBIU_SDGCTL() & SDGCTL_WIDTH) | mem_SDGCTL); #else bfin_write_EBIU_RSTCTL(bfin_read_EBIU_RSTCTL() & ~(SRREQ)); do_sync(); From 5e7bb132bbed2088b8b103e410d143b341dcb837 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 078/111] Blackfin arch: Fix Bug - request lines with peripheral_request_list, but don't get freed with peripheral_free_list Remove erroneous check_gpio(ident) in peripheral_free() Reported-by: Michael McTernan Signed-off-by: Michael Hennerich Signed-off-by: Bryan Wu --- arch/blackfin/kernel/bfin_gpio.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c index 4c14331978f6..ea67ae5b033e 100644 --- a/arch/blackfin/kernel/bfin_gpio.c +++ b/arch/blackfin/kernel/bfin_gpio.c @@ -977,9 +977,6 @@ void peripheral_free(unsigned short per) if (!(per & P_DEFINED)) return; - if (check_gpio(ident) < 0) - return; - local_irq_save_hw(flags); if (unlikely(!(reserved_peri_map[gpio_bank(ident)] & gpio_bit(ident)))) { From a2be3931144b8fab73c3d876c148ada7a3c09066 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 079/111] Blackfin arch: reset POLAR setting when acquiring a gpio for the first time when requesting a GPIO for the first time, the POLAR setting is not set to a sane state. this can lead to indeterminate behavior that cannot be resolved without an explicit write to the Blackfin port POLAR register. when requesting a GPIO for the first time via gpio_request(), the POLAR setting for the GPIO in question should be set to sane state. this should occur if the GPIO has not been allocated in any other way. some examples: - when doing something like "request_irq(); gpio_request();" on the same GPIO, the POLAR setting should not be reset. - when doing "gpio_request(); gpio_request();" on the same GPIO, the POLAR setting should be reset only the first time and not the second. Signed-off-by: Michael Hennerich Signed-off-by: Bryan Wu --- arch/blackfin/kernel/bfin_gpio.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c index ea67ae5b033e..0c4fc31029c2 100644 --- a/arch/blackfin/kernel/bfin_gpio.c +++ b/arch/blackfin/kernel/bfin_gpio.c @@ -1053,9 +1053,15 @@ int bfin_gpio_request(unsigned gpio, const char *label) local_irq_restore_hw(flags); return -EBUSY; } - if (unlikely(reserved_gpio_irq_map[gpio_bank(gpio)] & gpio_bit(gpio))) + if (unlikely(reserved_gpio_irq_map[gpio_bank(gpio)] & gpio_bit(gpio))) { printk(KERN_NOTICE "bfin-gpio: GPIO %d is already reserved as gpio-irq!" " (Documentation/blackfin/bfin-gpio-notes.txt)\n", gpio); + } +#ifndef BF548_FAMILY + else { /* Reset POLAR setting when acquiring a gpio for the first time */ + set_gpio_polar(gpio, 0); + } +#endif reserved_gpio_map[gpio_bank(gpio)] |= gpio_bit(gpio); set_label(gpio, label); From 76e8fe4da652b020e08089415c684a365bb5b6a9 Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 080/111] Blackfin arch: Print out where the bootmode is coming from (for easier debugging). Signed-off-by: Robin Getz Signed-off-by: Bryan Wu --- arch/blackfin/kernel/setup.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index b2a811347b65..a23fec573c0a 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -824,6 +824,8 @@ void __init setup_arch(char **cmdline_p) flash_probe(); #endif + printk(KERN_INFO "Boot Mode: %i\n", bfin_read_SYSCR() & 0xF); + _bfin_swrst = bfin_read_SWRST(); #ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT From 2f95d5bd84bfbe8cf62cb1c4306354cfc139370b Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 081/111] Blackfin arch: don't accidently re-enable interrupts Make sure we don't accidently re-enable interrupts if we are being called in atomic context Signed-off-by: Robin Getz Signed-off-by: Bryan Wu --- arch/blackfin/kernel/traps.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index 5b0667da8d05..f18c2481e9b7 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -1052,8 +1052,9 @@ void show_regs(struct pt_regs *fp) char buf [150]; struct irqaction *action; unsigned int i; - unsigned long flags; + unsigned long flags = 0; unsigned int cpu = smp_processor_id(); + unsigned char in_atomic = (bfin_read_IPEND() & 0x10) || in_atomic(); verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\t\t%s\n", print_tainted()); verbose_printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n", @@ -1073,17 +1074,22 @@ void show_regs(struct pt_regs *fp) } verbose_printk(KERN_NOTICE " EXCAUSE : 0x%lx\n", fp->seqstat & SEQSTAT_EXCAUSE); - for (i = 6; i <= 15 ; i++) { + for (i = 2; i <= 15 ; i++) { if (fp->ipend & (1 << i)) { - decode_address(buf, bfin_read32(EVT0 + 4*i)); - verbose_printk(KERN_NOTICE " physical IVG%i asserted : %s\n", i, buf); + if (i != 4) { + decode_address(buf, bfin_read32(EVT0 + 4*i)); + verbose_printk(KERN_NOTICE " physical IVG%i asserted : %s\n", i, buf); + } else + verbose_printk(KERN_NOTICE " interrupts disabled\n"); } } /* if no interrupts are going off, don't print this out */ if (fp->ipend & ~0x3F) { for (i = 0; i < (NR_IRQS - 1); i++) { - spin_lock_irqsave(&irq_desc[i].lock, flags); + if (!in_atomic) + spin_lock_irqsave(&irq_desc[i].lock, flags); + action = irq_desc[i].action; if (!action) goto unlock; @@ -1096,7 +1102,8 @@ void show_regs(struct pt_regs *fp) } verbose_printk("\n"); unlock: - spin_unlock_irqrestore(&irq_desc[i].lock, flags); + if (!in_atomic) + spin_unlock_irqrestore(&irq_desc[i].lock, flags); } } From 45c4f2a0b6c6302c5617534b8189c0e9b5a4a048 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-Koenig Date: Wed, 4 Feb 2009 17:02:30 +0800 Subject: [PATCH 082/111] Blackfin arch: explicit add a might sleep to gpio_free According to the documentation gpio_free should only be called from task context only. To make this more explicit add a might sleep to all implementations. This patch changes the gpio_free implementations for the blackfin architecture. Signed-off-by: Uwe Kleine-Koenig Cc: David Brownell Acked-by: Bryan Wu Signed-off-by: Andrew Morton --- arch/blackfin/kernel/bfin_gpio.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c index 0c4fc31029c2..05bf85ba7443 100644 --- a/arch/blackfin/kernel/bfin_gpio.c +++ b/arch/blackfin/kernel/bfin_gpio.c @@ -1081,6 +1081,8 @@ void bfin_gpio_free(unsigned gpio) if (check_gpio(gpio) < 0) return; + might_sleep(); + local_irq_save_hw(flags); if (unlikely(!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio)))) { From 881eb621fc191e58fa638c533073683be2b63c24 Mon Sep 17 00:00:00 2001 From: Jie Zhang Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 083/111] Blackfin arch: Add one more check on `fp' to prevent double fault Signed-off-by: Jie Zhang Signed-off-by: Bryan Wu --- arch/blackfin/kernel/traps.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index f18c2481e9b7..79926413c0eb 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -820,11 +820,8 @@ void show_stack(struct task_struct *task, unsigned long *stack) decode_address(buf, (unsigned int)stack); printk(KERN_NOTICE " SP: [0x%p] %s\n", stack, buf); - addr = (unsigned int *)((unsigned int)stack & ~0x3F); - /* First thing is to look for a frame pointer */ - for (addr = (unsigned int *)((unsigned int)stack & ~0xF), i = 0; - addr < endstack; addr++, i++) { + for (addr = (unsigned int *)((unsigned int)stack & ~0xF); addr < endstack; addr++) { if (*addr & 0x1) continue; ins_addr = (unsigned short *)*addr; @@ -834,7 +831,8 @@ void show_stack(struct task_struct *task, unsigned long *stack) if (fp) { /* Let's check to see if it is a frame pointer */ - while (fp >= (addr - 1) && fp < endstack && fp) + while (fp >= (addr - 1) && fp < endstack + && fp && ((unsigned int) fp & 0x3) == 0) fp = (unsigned int *)*fp; if (fp == 0 || fp == endstack) { fp = addr - 1; From f556309ea0d6a4adb0ad9775e5a18aa3564a0e4f Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 084/111] Blackfin arch: cleanup bf54x ifdef mess in gpio code merge more of the bf54x and !bf54x gpio code together to cut down on #ifdef mess Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/include/asm/gpio.h | 58 -- arch/blackfin/kernel/bfin_gpio.c | 577 +++++++------------ arch/blackfin/mach-bf548/include/mach/gpio.h | 12 +- 3 files changed, 223 insertions(+), 424 deletions(-) diff --git a/arch/blackfin/include/asm/gpio.h b/arch/blackfin/include/asm/gpio.h index 9477d82fcad2..d4a082ef75b4 100644 --- a/arch/blackfin/include/asm/gpio.h +++ b/arch/blackfin/include/asm/gpio.h @@ -27,60 +27,6 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -/* -* Number BF537/6/4 BF561 BF533/2/1 -* BF527/5/2 -* -* GPIO_0 PF0 PF0 PF0 -* GPIO_1 PF1 PF1 PF1 -* GPIO_2 PF2 PF2 PF2 -* GPIO_3 PF3 PF3 PF3 -* GPIO_4 PF4 PF4 PF4 -* GPIO_5 PF5 PF5 PF5 -* GPIO_6 PF6 PF6 PF6 -* GPIO_7 PF7 PF7 PF7 -* GPIO_8 PF8 PF8 PF8 -* GPIO_9 PF9 PF9 PF9 -* GPIO_10 PF10 PF10 PF10 -* GPIO_11 PF11 PF11 PF11 -* GPIO_12 PF12 PF12 PF12 -* GPIO_13 PF13 PF13 PF13 -* GPIO_14 PF14 PF14 PF14 -* GPIO_15 PF15 PF15 PF15 -* GPIO_16 PG0 PF16 -* GPIO_17 PG1 PF17 -* GPIO_18 PG2 PF18 -* GPIO_19 PG3 PF19 -* GPIO_20 PG4 PF20 -* GPIO_21 PG5 PF21 -* GPIO_22 PG6 PF22 -* GPIO_23 PG7 PF23 -* GPIO_24 PG8 PF24 -* GPIO_25 PG9 PF25 -* GPIO_26 PG10 PF26 -* GPIO_27 PG11 PF27 -* GPIO_28 PG12 PF28 -* GPIO_29 PG13 PF29 -* GPIO_30 PG14 PF30 -* GPIO_31 PG15 PF31 -* GPIO_32 PH0 PF32 -* GPIO_33 PH1 PF33 -* GPIO_34 PH2 PF34 -* GPIO_35 PH3 PF35 -* GPIO_36 PH4 PF36 -* GPIO_37 PH5 PF37 -* GPIO_38 PH6 PF38 -* GPIO_39 PH7 PF39 -* GPIO_40 PH8 PF40 -* GPIO_41 PH9 PF41 -* GPIO_42 PH10 PF42 -* GPIO_43 PH11 PF43 -* GPIO_44 PH12 PF44 -* GPIO_45 PH13 PF45 -* GPIO_46 PH14 PF46 -* GPIO_47 PH15 PF47 -*/ - #ifndef __ARCH_BLACKFIN_GPIO_H__ #define __ARCH_BLACKFIN_GPIO_H__ @@ -295,10 +241,6 @@ int bfin_gpio_direction_output(unsigned gpio, int value); int bfin_gpio_get_value(unsigned gpio); void bfin_gpio_set_value(unsigned gpio, int value); -#ifndef BF548_FAMILY -#define bfin_gpio_set_value(gpio, value) set_gpio_data(gpio, value) -#endif - #ifdef CONFIG_GPIOLIB #include /* cansleep wrappers */ diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c index 05bf85ba7443..7f69f43be987 100644 --- a/arch/blackfin/kernel/bfin_gpio.c +++ b/arch/blackfin/kernel/bfin_gpio.c @@ -27,59 +27,6 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -/* -* Number BF537/6/4 BF561 BF533/2/1 BF549/8/4/2 -* -* GPIO_0 PF0 PF0 PF0 PA0...PJ13 -* GPIO_1 PF1 PF1 PF1 -* GPIO_2 PF2 PF2 PF2 -* GPIO_3 PF3 PF3 PF3 -* GPIO_4 PF4 PF4 PF4 -* GPIO_5 PF5 PF5 PF5 -* GPIO_6 PF6 PF6 PF6 -* GPIO_7 PF7 PF7 PF7 -* GPIO_8 PF8 PF8 PF8 -* GPIO_9 PF9 PF9 PF9 -* GPIO_10 PF10 PF10 PF10 -* GPIO_11 PF11 PF11 PF11 -* GPIO_12 PF12 PF12 PF12 -* GPIO_13 PF13 PF13 PF13 -* GPIO_14 PF14 PF14 PF14 -* GPIO_15 PF15 PF15 PF15 -* GPIO_16 PG0 PF16 -* GPIO_17 PG1 PF17 -* GPIO_18 PG2 PF18 -* GPIO_19 PG3 PF19 -* GPIO_20 PG4 PF20 -* GPIO_21 PG5 PF21 -* GPIO_22 PG6 PF22 -* GPIO_23 PG7 PF23 -* GPIO_24 PG8 PF24 -* GPIO_25 PG9 PF25 -* GPIO_26 PG10 PF26 -* GPIO_27 PG11 PF27 -* GPIO_28 PG12 PF28 -* GPIO_29 PG13 PF29 -* GPIO_30 PG14 PF30 -* GPIO_31 PG15 PF31 -* GPIO_32 PH0 PF32 -* GPIO_33 PH1 PF33 -* GPIO_34 PH2 PF34 -* GPIO_35 PH3 PF35 -* GPIO_36 PH4 PF36 -* GPIO_37 PH5 PF37 -* GPIO_38 PH6 PF38 -* GPIO_39 PH7 PF39 -* GPIO_40 PH8 PF40 -* GPIO_41 PH9 PF41 -* GPIO_42 PH10 PF42 -* GPIO_43 PH11 PF43 -* GPIO_44 PH12 PF44 -* GPIO_45 PH13 PF45 -* GPIO_46 PH14 PF46 -* GPIO_47 PH15 PF47 -*/ - #include #include #include @@ -119,28 +66,42 @@ enum { #define AWA_DUMMY_READ(...) do { } while (0) #endif +static struct gpio_port_t * const gpio_array[] = { #if defined(BF533_FAMILY) || defined(BF538_FAMILY) -static struct gpio_port_t *gpio_bankb[] = { (struct gpio_port_t *) FIO_FLAG_D, -}; -#endif - -#if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY) -static struct gpio_port_t *gpio_bankb[] = { +#elif defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY) (struct gpio_port_t *) PORTFIO, (struct gpio_port_t *) PORTGIO, (struct gpio_port_t *) PORTHIO, +#elif defined(BF561_FAMILY) + (struct gpio_port_t *) FIO0_FLAG_D, + (struct gpio_port_t *) FIO1_FLAG_D, + (struct gpio_port_t *) FIO2_FLAG_D, +#elif defined(BF548_FAMILY) + (struct gpio_port_t *)PORTA_FER, + (struct gpio_port_t *)PORTB_FER, + (struct gpio_port_t *)PORTC_FER, + (struct gpio_port_t *)PORTD_FER, + (struct gpio_port_t *)PORTE_FER, + (struct gpio_port_t *)PORTF_FER, + (struct gpio_port_t *)PORTG_FER, + (struct gpio_port_t *)PORTH_FER, + (struct gpio_port_t *)PORTI_FER, + (struct gpio_port_t *)PORTJ_FER, +#else +# error no gpio arrays defined +#endif }; -static unsigned short *port_fer[] = { +#if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY) +static unsigned short * const port_fer[] = { (unsigned short *) PORTF_FER, (unsigned short *) PORTG_FER, (unsigned short *) PORTH_FER, }; -#endif -#if defined(BF527_FAMILY) || defined(BF518_FAMILY) -static unsigned short *port_mux[] = { +# if !defined(BF537_FAMILY) +static unsigned short * const port_mux[] = { (unsigned short *) PORTF_MUX, (unsigned short *) PORTG_MUX, (unsigned short *) PORTH_MUX, @@ -152,29 +113,7 @@ u8 pmux_offset[][16] = { 0, 0, 0, 0, 0, 2, 2, 4, 4, 6, 8, 10, 10, 10, 12, 12 }, /* PORTG */ { 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 4, 4, 4, 4, 4 }, /* PORTH */ }; -#endif - -#ifdef BF561_FAMILY -static struct gpio_port_t *gpio_bankb[] = { - (struct gpio_port_t *) FIO0_FLAG_D, - (struct gpio_port_t *) FIO1_FLAG_D, - (struct gpio_port_t *) FIO2_FLAG_D, -}; -#endif - -#ifdef BF548_FAMILY -static struct gpio_port_t *gpio_array[] = { - (struct gpio_port_t *)PORTA_FER, - (struct gpio_port_t *)PORTB_FER, - (struct gpio_port_t *)PORTC_FER, - (struct gpio_port_t *)PORTD_FER, - (struct gpio_port_t *)PORTE_FER, - (struct gpio_port_t *)PORTF_FER, - (struct gpio_port_t *)PORTG_FER, - (struct gpio_port_t *)PORTH_FER, - (struct gpio_port_t *)PORTI_FER, - (struct gpio_port_t *)PORTJ_FER, -}; +# endif #endif static unsigned short reserved_gpio_map[GPIO_BANK_NUM]; @@ -188,35 +127,9 @@ static struct str_ident { } str_ident[MAX_RESOURCES]; #if defined(CONFIG_PM) -#if defined(CONFIG_BF54x) static struct gpio_port_s gpio_bank_saved[GPIO_BANK_NUM]; -#else -static unsigned short wakeup_map[GPIO_BANK_NUM]; -static unsigned char wakeup_flags_map[MAX_BLACKFIN_GPIOS]; -static struct gpio_port_s gpio_bank_saved[GPIO_BANK_NUM]; - -#ifdef BF533_FAMILY -static unsigned int sic_iwr_irqs[] = {IRQ_PROG_INTB}; #endif -#ifdef BF537_FAMILY -static unsigned int sic_iwr_irqs[] = {IRQ_PROG_INTB, IRQ_PORTG_INTB, IRQ_MAC_TX}; -#endif - -#ifdef BF538_FAMILY -static unsigned int sic_iwr_irqs[] = {IRQ_PORTF_INTB}; -#endif - -#if defined(BF527_FAMILY) || defined(BF518_FAMILY) -static unsigned int sic_iwr_irqs[] = {IRQ_PORTF_INTB, IRQ_PORTG_INTB, IRQ_PORTH_INTB}; -#endif - -#ifdef BF561_FAMILY -static unsigned int sic_iwr_irqs[] = {IRQ_PROG0_INTB, IRQ_PROG1_INTB, IRQ_PROG2_INTB}; -#endif -#endif -#endif /* CONFIG_PM */ - inline int check_gpio(unsigned gpio) { #if defined(BF548_FAMILY) @@ -330,9 +243,10 @@ static struct { {.res = P_SPI0_SSEL3, .offset = 0}, }; -static void portmux_setup(unsigned short per, unsigned short function) +static void portmux_setup(unsigned short per) { u16 y, offset, muxreg; + u16 function = P_FUNCT2MUX(per); for (y = 0; y < ARRAY_SIZE(port_mux_lut); y++) { if (port_mux_lut[y].res == per) { @@ -353,30 +267,33 @@ static void portmux_setup(unsigned short per, unsigned short function) } } #elif defined(BF548_FAMILY) -inline void portmux_setup(unsigned short portno, unsigned short function) +inline void portmux_setup(unsigned short per) { u32 pmux; + u16 ident = P_IDENT(per); + u16 function = P_FUNCT2MUX(per); - pmux = gpio_array[gpio_bank(portno)]->port_mux; + pmux = gpio_array[gpio_bank(ident)]->port_mux; - pmux &= ~(0x3 << (2 * gpio_sub_n(portno))); - pmux |= (function & 0x3) << (2 * gpio_sub_n(portno)); + pmux &= ~(0x3 << (2 * gpio_sub_n(ident))); + pmux |= (function & 0x3) << (2 * gpio_sub_n(ident)); - gpio_array[gpio_bank(portno)]->port_mux = pmux; + gpio_array[gpio_bank(ident)]->port_mux = pmux; } -inline u16 get_portmux(unsigned short portno) +inline u16 get_portmux(unsigned short per) { u32 pmux; + u16 ident = P_IDENT(per); - pmux = gpio_array[gpio_bank(portno)]->port_mux; + pmux = gpio_array[gpio_bank(ident)]->port_mux; - return (pmux >> (2 * gpio_sub_n(portno)) & 0x3); + return (pmux >> (2 * gpio_sub_n(ident)) & 0x3); } #elif defined(BF527_FAMILY) || defined(BF518_FAMILY) -inline void portmux_setup(unsigned short portno, unsigned short function) +inline void portmux_setup(unsigned short per) { - u16 pmux, ident = P_IDENT(portno); + u16 pmux, ident = P_IDENT(per), function = P_FUNCT2MUX(per); u8 offset = pmux_offset[gpio_bank(ident)][gpio_sub_n(ident)]; pmux = *port_mux[gpio_bank(ident)]; @@ -424,90 +341,71 @@ void set_gpio_ ## name(unsigned gpio, unsigned short arg) \ unsigned long flags; \ local_irq_save_hw(flags); \ if (arg) \ - gpio_bankb[gpio_bank(gpio)]->name |= gpio_bit(gpio); \ + gpio_array[gpio_bank(gpio)]->name |= gpio_bit(gpio); \ else \ - gpio_bankb[gpio_bank(gpio)]->name &= ~gpio_bit(gpio); \ + gpio_array[gpio_bank(gpio)]->name &= ~gpio_bit(gpio); \ AWA_DUMMY_READ(name); \ local_irq_restore_hw(flags); \ } \ EXPORT_SYMBOL(set_gpio_ ## name); -SET_GPIO(dir) -SET_GPIO(inen) -SET_GPIO(polar) -SET_GPIO(edge) -SET_GPIO(both) +SET_GPIO(dir) /* set_gpio_dir() */ +SET_GPIO(inen) /* set_gpio_inen() */ +SET_GPIO(polar) /* set_gpio_polar() */ +SET_GPIO(edge) /* set_gpio_edge() */ +SET_GPIO(both) /* set_gpio_both() */ -#if ANOMALY_05000311 || ANOMALY_05000323 #define SET_GPIO_SC(name) \ void set_gpio_ ## name(unsigned gpio, unsigned short arg) \ { \ unsigned long flags; \ - local_irq_save_hw(flags); \ + if (ANOMALY_05000311 || ANOMALY_05000323) \ + local_irq_save_hw(flags); \ if (arg) \ - gpio_bankb[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \ + gpio_array[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \ else \ - gpio_bankb[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \ - AWA_DUMMY_READ(name); \ - local_irq_restore_hw(flags); \ + gpio_array[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \ + if (ANOMALY_05000311 || ANOMALY_05000323) { \ + AWA_DUMMY_READ(name); \ + local_irq_restore_hw(flags); \ + } \ } \ EXPORT_SYMBOL(set_gpio_ ## name); -#else -#define SET_GPIO_SC(name) \ -void set_gpio_ ## name(unsigned gpio, unsigned short arg) \ -{ \ - if (arg) \ - gpio_bankb[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \ - else \ - gpio_bankb[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \ -} \ -EXPORT_SYMBOL(set_gpio_ ## name); -#endif SET_GPIO_SC(maska) SET_GPIO_SC(maskb) SET_GPIO_SC(data) -#if ANOMALY_05000311 || ANOMALY_05000323 void set_gpio_toggle(unsigned gpio) { unsigned long flags; - local_irq_save_hw(flags); - gpio_bankb[gpio_bank(gpio)]->toggle = gpio_bit(gpio); - AWA_DUMMY_READ(toggle); - local_irq_restore_hw(flags); + if (ANOMALY_05000311 || ANOMALY_05000323) + local_irq_save_hw(flags); + gpio_array[gpio_bank(gpio)]->toggle = gpio_bit(gpio); + if (ANOMALY_05000311 || ANOMALY_05000323) { + AWA_DUMMY_READ(toggle); + local_irq_restore_hw(flags); + } } -#else -void set_gpio_toggle(unsigned gpio) -{ - gpio_bankb[gpio_bank(gpio)]->toggle = gpio_bit(gpio); -} -#endif EXPORT_SYMBOL(set_gpio_toggle); /*Set current PORT date (16-bit word)*/ -#if ANOMALY_05000311 || ANOMALY_05000323 #define SET_GPIO_P(name) \ void set_gpiop_ ## name(unsigned gpio, unsigned short arg) \ { \ unsigned long flags; \ - local_irq_save_hw(flags); \ - gpio_bankb[gpio_bank(gpio)]->name = arg; \ - AWA_DUMMY_READ(name); \ - local_irq_restore_hw(flags); \ + if (ANOMALY_05000311 || ANOMALY_05000323) \ + local_irq_save_hw(flags); \ + gpio_array[gpio_bank(gpio)]->name = arg; \ + if (ANOMALY_05000311 || ANOMALY_05000323) { \ + AWA_DUMMY_READ(name); \ + local_irq_restore_hw(flags); \ + } \ } \ EXPORT_SYMBOL(set_gpiop_ ## name); -#else -#define SET_GPIO_P(name) \ -void set_gpiop_ ## name(unsigned gpio, unsigned short arg) \ -{ \ - gpio_bankb[gpio_bank(gpio)]->name = arg; \ -} \ -EXPORT_SYMBOL(set_gpiop_ ## name); -#endif SET_GPIO_P(data) SET_GPIO_P(dir) @@ -519,27 +417,21 @@ SET_GPIO_P(maska) SET_GPIO_P(maskb) /* Get a specific bit */ -#if ANOMALY_05000311 || ANOMALY_05000323 #define GET_GPIO(name) \ unsigned short get_gpio_ ## name(unsigned gpio) \ { \ unsigned long flags; \ unsigned short ret; \ - local_irq_save_hw(flags); \ - ret = 0x01 & (gpio_bankb[gpio_bank(gpio)]->name >> gpio_sub_n(gpio)); \ - AWA_DUMMY_READ(name); \ - local_irq_restore_hw(flags); \ + if (ANOMALY_05000311 || ANOMALY_05000323) \ + local_irq_save_hw(flags); \ + ret = 0x01 & (gpio_array[gpio_bank(gpio)]->name >> gpio_sub_n(gpio)); \ + if (ANOMALY_05000311 || ANOMALY_05000323) { \ + AWA_DUMMY_READ(name); \ + local_irq_restore_hw(flags); \ + } \ return ret; \ } \ EXPORT_SYMBOL(get_gpio_ ## name); -#else -#define GET_GPIO(name) \ -unsigned short get_gpio_ ## name(unsigned gpio) \ -{ \ - return (0x01 & (gpio_bankb[gpio_bank(gpio)]->name >> gpio_sub_n(gpio))); \ -} \ -EXPORT_SYMBOL(get_gpio_ ## name); -#endif GET_GPIO(data) GET_GPIO(dir) @@ -552,27 +444,21 @@ GET_GPIO(maskb) /*Get current PORT date (16-bit word)*/ -#if ANOMALY_05000311 || ANOMALY_05000323 #define GET_GPIO_P(name) \ unsigned short get_gpiop_ ## name(unsigned gpio) \ { \ unsigned long flags; \ unsigned short ret; \ - local_irq_save_hw(flags); \ - ret = (gpio_bankb[gpio_bank(gpio)]->name); \ - AWA_DUMMY_READ(name); \ - local_irq_restore_hw(flags); \ + if (ANOMALY_05000311 || ANOMALY_05000323) \ + local_irq_save_hw(flags); \ + ret = (gpio_array[gpio_bank(gpio)]->name); \ + if (ANOMALY_05000311 || ANOMALY_05000323) { \ + AWA_DUMMY_READ(name); \ + local_irq_restore_hw(flags); \ + } \ return ret; \ } \ EXPORT_SYMBOL(get_gpiop_ ## name); -#else -#define GET_GPIO_P(name) \ -unsigned short get_gpiop_ ## name(unsigned gpio) \ -{ \ - return (gpio_bankb[gpio_bank(gpio)]->name);\ -} \ -EXPORT_SYMBOL(get_gpiop_ ## name); -#endif GET_GPIO_P(data) GET_GPIO_P(dir) @@ -585,6 +471,26 @@ GET_GPIO_P(maskb) #ifdef CONFIG_PM + +static unsigned short wakeup_map[GPIO_BANK_NUM]; +static unsigned char wakeup_flags_map[MAX_BLACKFIN_GPIOS]; + +static const unsigned int sic_iwr_irqs[] = { +#if defined(BF533_FAMILY) + IRQ_PROG_INTB +#elif defined(BF537_FAMILY) + IRQ_PROG_INTB, IRQ_PORTG_INTB, IRQ_MAC_TX +#elif defined(BF538_FAMILY) + IRQ_PORTF_INTB +#elif defined(BF527_FAMILY) || defined(BF518_FAMILY) + IRQ_PORTF_INTB, IRQ_PORTG_INTB, IRQ_PORTH_INTB +#elif defined(BF561_FAMILY) + IRQ_PROG0_INTB, IRQ_PROG1_INTB, IRQ_PROG2_INTB +#else +# error no SIC_IWR defined +#endif +}; + /*********************************************************** * * FUNCTIONS: Blackfin PM Setup API @@ -669,18 +575,18 @@ u32 bfin_pm_standby_setup(void) mask = wakeup_map[gpio_bank(i)]; bank = gpio_bank(i); - gpio_bank_saved[bank].maskb = gpio_bankb[bank]->maskb; - gpio_bankb[bank]->maskb = 0; + gpio_bank_saved[bank].maskb = gpio_array[bank]->maskb; + gpio_array[bank]->maskb = 0; if (mask) { #if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY) gpio_bank_saved[bank].fer = *port_fer[bank]; #endif - gpio_bank_saved[bank].inen = gpio_bankb[bank]->inen; - gpio_bank_saved[bank].polar = gpio_bankb[bank]->polar; - gpio_bank_saved[bank].dir = gpio_bankb[bank]->dir; - gpio_bank_saved[bank].edge = gpio_bankb[bank]->edge; - gpio_bank_saved[bank].both = gpio_bankb[bank]->both; + gpio_bank_saved[bank].inen = gpio_array[bank]->inen; + gpio_bank_saved[bank].polar = gpio_array[bank]->polar; + gpio_bank_saved[bank].dir = gpio_array[bank]->dir; + gpio_bank_saved[bank].edge = gpio_array[bank]->edge; + gpio_bank_saved[bank].both = gpio_array[bank]->both; gpio_bank_saved[bank].reserved = reserved_gpio_map[bank]; @@ -700,7 +606,7 @@ u32 bfin_pm_standby_setup(void) } bfin_internal_set_wake(sic_iwr_irqs[bank], 1); - gpio_bankb[bank]->maskb_set = wakeup_map[gpio_bank(i)]; + gpio_array[bank]->maskb_set = wakeup_map[gpio_bank(i)]; } } @@ -721,18 +627,18 @@ void bfin_pm_standby_restore(void) #if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY) *port_fer[bank] = gpio_bank_saved[bank].fer; #endif - gpio_bankb[bank]->inen = gpio_bank_saved[bank].inen; - gpio_bankb[bank]->dir = gpio_bank_saved[bank].dir; - gpio_bankb[bank]->polar = gpio_bank_saved[bank].polar; - gpio_bankb[bank]->edge = gpio_bank_saved[bank].edge; - gpio_bankb[bank]->both = gpio_bank_saved[bank].both; + gpio_array[bank]->inen = gpio_bank_saved[bank].inen; + gpio_array[bank]->dir = gpio_bank_saved[bank].dir; + gpio_array[bank]->polar = gpio_bank_saved[bank].polar; + gpio_array[bank]->edge = gpio_bank_saved[bank].edge; + gpio_array[bank]->both = gpio_bank_saved[bank].both; reserved_gpio_map[bank] = gpio_bank_saved[bank].reserved; bfin_internal_set_wake(sic_iwr_irqs[bank], 0); } - gpio_bankb[bank]->maskb = gpio_bank_saved[bank].maskb; + gpio_array[bank]->maskb = gpio_bank_saved[bank].maskb; } AWA_DUMMY_READ(maskb); } @@ -745,21 +651,21 @@ void bfin_gpio_pm_hibernate_suspend(void) bank = gpio_bank(i); #if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY) - gpio_bank_saved[bank].fer = *port_fer[bank]; + gpio_bank_saved[bank].fer = *port_fer[bank]; #if defined(BF527_FAMILY) || defined(BF518_FAMILY) - gpio_bank_saved[bank].mux = *port_mux[bank]; + gpio_bank_saved[bank].mux = *port_mux[bank]; #else - if (bank == 0) - gpio_bank_saved[bank].mux = bfin_read_PORT_MUX(); + if (bank == 0) + gpio_bank_saved[bank].mux = bfin_read_PORT_MUX(); #endif #endif - gpio_bank_saved[bank].data = gpio_bankb[bank]->data; - gpio_bank_saved[bank].inen = gpio_bankb[bank]->inen; - gpio_bank_saved[bank].polar = gpio_bankb[bank]->polar; - gpio_bank_saved[bank].dir = gpio_bankb[bank]->dir; - gpio_bank_saved[bank].edge = gpio_bankb[bank]->edge; - gpio_bank_saved[bank].both = gpio_bankb[bank]->both; - gpio_bank_saved[bank].maska = gpio_bankb[bank]->maska; + gpio_bank_saved[bank].data = gpio_array[bank]->data; + gpio_bank_saved[bank].inen = gpio_array[bank]->inen; + gpio_bank_saved[bank].polar = gpio_array[bank]->polar; + gpio_bank_saved[bank].dir = gpio_array[bank]->dir; + gpio_bank_saved[bank].edge = gpio_array[bank]->edge; + gpio_bank_saved[bank].both = gpio_array[bank]->both; + gpio_bank_saved[bank].maska = gpio_array[bank]->maska; } AWA_DUMMY_READ(maska); @@ -770,27 +676,27 @@ void bfin_gpio_pm_hibernate_restore(void) int i, bank; for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) { - bank = gpio_bank(i); + bank = gpio_bank(i); #if defined(BF527_FAMILY) || defined(BF537_FAMILY) || defined(BF518_FAMILY) #if defined(BF527_FAMILY) || defined(BF518_FAMILY) - *port_mux[bank] = gpio_bank_saved[bank].mux; + *port_mux[bank] = gpio_bank_saved[bank].mux; #else - if (bank == 0) - bfin_write_PORT_MUX(gpio_bank_saved[bank].mux); + if (bank == 0) + bfin_write_PORT_MUX(gpio_bank_saved[bank].mux); #endif - *port_fer[bank] = gpio_bank_saved[bank].fer; + *port_fer[bank] = gpio_bank_saved[bank].fer; #endif - gpio_bankb[bank]->inen = gpio_bank_saved[bank].inen; - gpio_bankb[bank]->dir = gpio_bank_saved[bank].dir; - gpio_bankb[bank]->polar = gpio_bank_saved[bank].polar; - gpio_bankb[bank]->edge = gpio_bank_saved[bank].edge; - gpio_bankb[bank]->both = gpio_bank_saved[bank].both; + gpio_array[bank]->inen = gpio_bank_saved[bank].inen; + gpio_array[bank]->dir = gpio_bank_saved[bank].dir; + gpio_array[bank]->polar = gpio_bank_saved[bank].polar; + gpio_array[bank]->edge = gpio_bank_saved[bank].edge; + gpio_array[bank]->both = gpio_bank_saved[bank].both; - gpio_bankb[bank]->data_set = gpio_bank_saved[bank].data - | gpio_bank_saved[bank].dir; + gpio_array[bank]->data_set = gpio_bank_saved[bank].data + | gpio_bank_saved[bank].dir; - gpio_bankb[bank]->maska = gpio_bank_saved[bank].maska; + gpio_array[bank]->maska = gpio_bank_saved[bank].maska; } AWA_DUMMY_READ(maska); } @@ -817,12 +723,12 @@ void bfin_gpio_pm_hibernate_suspend(void) for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) { bank = gpio_bank(i); - gpio_bank_saved[bank].fer = gpio_array[bank]->port_fer; - gpio_bank_saved[bank].mux = gpio_array[bank]->port_mux; - gpio_bank_saved[bank].data = gpio_array[bank]->port_data; - gpio_bank_saved[bank].data = gpio_array[bank]->port_data; - gpio_bank_saved[bank].inen = gpio_array[bank]->port_inen; - gpio_bank_saved[bank].dir = gpio_array[bank]->port_dir_set; + gpio_bank_saved[bank].fer = gpio_array[bank]->port_fer; + gpio_bank_saved[bank].mux = gpio_array[bank]->port_mux; + gpio_bank_saved[bank].data = gpio_array[bank]->data; + gpio_bank_saved[bank].data = gpio_array[bank]->data; + gpio_bank_saved[bank].inen = gpio_array[bank]->inen; + gpio_bank_saved[bank].dir = gpio_array[bank]->dir_set; } } @@ -831,21 +737,21 @@ void bfin_gpio_pm_hibernate_restore(void) int i, bank; for (i = 0; i < MAX_BLACKFIN_GPIOS; i += GPIO_BANKSIZE) { - bank = gpio_bank(i); + bank = gpio_bank(i); - gpio_array[bank]->port_mux = gpio_bank_saved[bank].mux; - gpio_array[bank]->port_fer = gpio_bank_saved[bank].fer; - gpio_array[bank]->port_inen = gpio_bank_saved[bank].inen; - gpio_array[bank]->port_dir_set = gpio_bank_saved[bank].dir; - gpio_array[bank]->port_set = gpio_bank_saved[bank].data - | gpio_bank_saved[bank].dir; + gpio_array[bank]->port_mux = gpio_bank_saved[bank].mux; + gpio_array[bank]->port_fer = gpio_bank_saved[bank].fer; + gpio_array[bank]->inen = gpio_bank_saved[bank].inen; + gpio_array[bank]->dir_set = gpio_bank_saved[bank].dir; + gpio_array[bank]->data_set = gpio_bank_saved[bank].data + | gpio_bank_saved[bank].dir; } } #endif unsigned short get_gpio_dir(unsigned gpio) { - return (0x01 & (gpio_array[gpio_bank(gpio)]->port_dir_clear >> gpio_sub_n(gpio))); + return (0x01 & (gpio_array[gpio_bank(gpio)]->dir_clear >> gpio_sub_n(gpio))); } EXPORT_SYMBOL(get_gpio_dir); @@ -905,9 +811,7 @@ int peripheral_request(unsigned short per, const char *label) */ #ifdef BF548_FAMILY - u16 funct = get_portmux(ident); - - if (!((per & P_MAYSHARE) && (funct == P_FUNCT2MUX(per)))) { + if (!((per & P_MAYSHARE) && get_portmux(per) == P_FUNCT2MUX(per))) { #else if (!(per & P_MAYSHARE)) { #endif @@ -931,11 +835,7 @@ int peripheral_request(unsigned short per, const char *label) anyway: reserved_peri_map[gpio_bank(ident)] |= gpio_bit(ident); -#ifdef BF548_FAMILY - portmux_setup(ident, P_FUNCT2MUX(per)); -#else - portmux_setup(per, P_FUNCT2MUX(per)); -#endif + portmux_setup(per); port_setup(ident, PERIPHERAL_USAGE); local_irq_restore_hw(flags); @@ -1163,92 +1063,15 @@ void bfin_gpio_irq_free(unsigned gpio) local_irq_restore_hw(flags); } - +static inline void __bfin_gpio_direction_input(unsigned gpio) +{ #ifdef BF548_FAMILY -int bfin_gpio_direction_input(unsigned gpio) -{ - unsigned long flags; - - if (!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) { - gpio_error(gpio); - return -EINVAL; - } - - local_irq_save_hw(flags); - gpio_array[gpio_bank(gpio)]->port_dir_clear = gpio_bit(gpio); - gpio_array[gpio_bank(gpio)]->port_inen |= gpio_bit(gpio); - local_irq_restore_hw(flags); - - return 0; -} -EXPORT_SYMBOL(bfin_gpio_direction_input); - -int bfin_gpio_direction_output(unsigned gpio, int value) -{ - unsigned long flags; - - if (!(reserved_gpio_map[gpio_bank(gpio)] & gpio_bit(gpio))) { - gpio_error(gpio); - return -EINVAL; - } - - local_irq_save_hw(flags); - gpio_array[gpio_bank(gpio)]->port_inen &= ~gpio_bit(gpio); - gpio_set_value(gpio, value); - gpio_array[gpio_bank(gpio)]->port_dir_set = gpio_bit(gpio); - local_irq_restore_hw(flags); - - return 0; -} -EXPORT_SYMBOL(bfin_gpio_direction_output); - -void bfin_gpio_set_value(unsigned gpio, int arg) -{ - if (arg) - gpio_array[gpio_bank(gpio)]->port_set = gpio_bit(gpio); - else - gpio_array[gpio_bank(gpio)]->port_clear = gpio_bit(gpio); -} -EXPORT_SYMBOL(bfin_gpio_set_value); - -int bfin_gpio_get_value(unsigned gpio) -{ - return (1 & (gpio_array[gpio_bank(gpio)]->port_data >> gpio_sub_n(gpio))); -} -EXPORT_SYMBOL(bfin_gpio_get_value); - -void bfin_gpio_irq_prepare(unsigned gpio) -{ - unsigned long flags; - - port_setup(gpio, GPIO_USAGE); - - local_irq_save_hw(flags); - gpio_array[gpio_bank(gpio)]->port_dir_clear = gpio_bit(gpio); - gpio_array[gpio_bank(gpio)]->port_inen |= gpio_bit(gpio); - local_irq_restore_hw(flags); -} - + gpio_array[gpio_bank(gpio)]->dir_clear = gpio_bit(gpio); #else - -int bfin_gpio_get_value(unsigned gpio) -{ - unsigned long flags; - int ret; - - if (unlikely(get_gpio_edge(gpio))) { - local_irq_save_hw(flags); - set_gpio_edge(gpio, 0); - ret = get_gpio_data(gpio); - set_gpio_edge(gpio, 1); - local_irq_restore_hw(flags); - - return ret; - } else - return get_gpio_data(gpio); + gpio_array[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio); +#endif + gpio_array[gpio_bank(gpio)]->inen |= gpio_bit(gpio); } -EXPORT_SYMBOL(bfin_gpio_get_value); - int bfin_gpio_direction_input(unsigned gpio) { @@ -1260,8 +1083,7 @@ int bfin_gpio_direction_input(unsigned gpio) } local_irq_save_hw(flags); - gpio_bankb[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio); - gpio_bankb[gpio_bank(gpio)]->inen |= gpio_bit(gpio); + __bfin_gpio_direction_input(gpio); AWA_DUMMY_READ(inen); local_irq_restore_hw(flags); @@ -1269,6 +1091,30 @@ int bfin_gpio_direction_input(unsigned gpio) } EXPORT_SYMBOL(bfin_gpio_direction_input); +void bfin_gpio_irq_prepare(unsigned gpio) +{ +#ifdef BF548_FAMILY + unsigned long flags; +#endif + + port_setup(gpio, GPIO_USAGE); + +#ifdef BF548_FAMILY + local_irq_save_hw(flags); + __bfin_gpio_direction_input(gpio); + local_irq_restore_hw(flags); +#endif +} + +void bfin_gpio_set_value(unsigned gpio, int arg) +{ + if (arg) + gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio); + else + gpio_array[gpio_bank(gpio)]->data_clear = gpio_bit(gpio); +} +EXPORT_SYMBOL(bfin_gpio_set_value); + int bfin_gpio_direction_output(unsigned gpio, int value) { unsigned long flags; @@ -1279,14 +1125,15 @@ int bfin_gpio_direction_output(unsigned gpio, int value) } local_irq_save_hw(flags); - gpio_bankb[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio); - if (value) - gpio_bankb[gpio_bank(gpio)]->data_set = gpio_bit(gpio); - else - gpio_bankb[gpio_bank(gpio)]->data_clear = gpio_bit(gpio); + gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio); + gpio_set_value(gpio, value); +#ifdef BF548_FAMILY + gpio_array[gpio_bank(gpio)]->dir_set = gpio_bit(gpio); +#else + gpio_array[gpio_bank(gpio)]->dir |= gpio_bit(gpio); +#endif - gpio_bankb[gpio_bank(gpio)]->dir |= gpio_bit(gpio); AWA_DUMMY_READ(dir); local_irq_restore_hw(flags); @@ -1294,6 +1141,27 @@ int bfin_gpio_direction_output(unsigned gpio, int value) } EXPORT_SYMBOL(bfin_gpio_direction_output); +int bfin_gpio_get_value(unsigned gpio) +{ +#ifdef BF548_FAMILY + return (1 & (gpio_array[gpio_bank(gpio)]->data >> gpio_sub_n(gpio))); +#else + unsigned long flags; + + if (unlikely(get_gpio_edge(gpio))) { + int ret; + local_irq_save_hw(flags); + set_gpio_edge(gpio, 0); + ret = get_gpio_data(gpio); + set_gpio_edge(gpio, 1); + local_irq_restore_hw(flags); + return ret; + } else + return get_gpio_data(gpio); +#endif +} +EXPORT_SYMBOL(bfin_gpio_get_value); + /* If we are booting from SPI and our board lacks a strong enough pull up, * the core can reset and execute the bootrom faster than the resistor can * pull the signal logically high. To work around this (common) error in @@ -1309,18 +1177,11 @@ void bfin_gpio_reset_spi0_ssel1(void) u16 gpio = P_IDENT(P_SPI0_SSEL1); port_setup(gpio, GPIO_USAGE); - gpio_bankb[gpio_bank(gpio)]->data_set = gpio_bit(gpio); + gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio); AWA_DUMMY_READ(data_set); udelay(1); } -void bfin_gpio_irq_prepare(unsigned gpio) -{ - port_setup(gpio, GPIO_USAGE); -} - -#endif /*BF548_FAMILY */ - #if defined(CONFIG_PROC_FS) static int gpio_proc_read(char *buf, char **start, off_t offset, int len, int *unused_i, void *unused_v) @@ -1374,11 +1235,7 @@ int bfin_gpiolib_get_value(struct gpio_chip *chip, unsigned gpio) void bfin_gpiolib_set_value(struct gpio_chip *chip, unsigned gpio, int value) { -#ifdef BF548_FAMILY return bfin_gpio_set_value(gpio, value); -#else - return set_gpio_data(gpio, value); -#endif } int bfin_gpiolib_gpio_request(struct gpio_chip *chip, unsigned gpio) diff --git a/arch/blackfin/mach-bf548/include/mach/gpio.h b/arch/blackfin/mach-bf548/include/mach/gpio.h index bba82dc75f16..3a2051709787 100644 --- a/arch/blackfin/mach-bf548/include/mach/gpio.h +++ b/arch/blackfin/mach-bf548/include/mach/gpio.h @@ -195,17 +195,17 @@ struct gpio_port_t { unsigned short port_fer; unsigned short dummy1; - unsigned short port_data; + unsigned short data; unsigned short dummy2; - unsigned short port_set; + unsigned short data_set; unsigned short dummy3; - unsigned short port_clear; + unsigned short data_clear; unsigned short dummy4; - unsigned short port_dir_set; + unsigned short dir_set; unsigned short dummy5; - unsigned short port_dir_clear; + unsigned short dir_clear; unsigned short dummy6; - unsigned short port_inen; + unsigned short inen; unsigned short dummy7; unsigned int port_mux; }; From e48df47c1adabece6823395657ea6c677eb653db Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 085/111] Blackfin arch: Fix URL Signed-off-by: Robin Getz Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/interrupt.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/blackfin/mach-common/interrupt.S b/arch/blackfin/mach-common/interrupt.S index 473df0f7fa78..43c4eb9acb65 100644 --- a/arch/blackfin/mach-common/interrupt.S +++ b/arch/blackfin/mach-common/interrupt.S @@ -195,7 +195,7 @@ ENDPROC(_evt_ivhw) /* Interrupt routine for evt2 (NMI). * We don't actually use this, so just return. * For inner circle type details, please see: - * http://docs.blackfin.uclinux.org/doku.php?id=linux:nmi + * http://docs.blackfin.uclinux.org/doku.php?id=linux-kernel:nmi */ ENTRY(_evt_nmi) .weak _evt_nmi From 0be58939146f28394a04b61fec7e0676cdafa47e Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 086/111] Blackfin arch: Add a few more instructions that can cause the trace buffer to be discontiguous Signed-off-by: Robin Getz Signed-off-by: Bryan Wu --- arch/blackfin/kernel/traps.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index 79926413c0eb..ffe7fb53eccb 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -673,6 +673,14 @@ static void decode_instruction(unsigned short *address) verbose_printk("RTI"); else if (opcode == 0x0012) verbose_printk("RTX"); + else if (opcode == 0x0013) + verbose_printk("RTN"); + else if (opcode == 0x0014) + verbose_printk("RTE"); + else if (opcode == 0x0025) + verbose_printk("EMUEXCPT"); + else if (opcode == 0x0040 && opcode <= 0x0047) + verbose_printk("STI R%i", opcode & 7); else if (opcode >= 0x0050 && opcode <= 0x0057) verbose_printk("JUMP (P%i)", opcode & 7); else if (opcode >= 0x0060 && opcode <= 0x0067) @@ -681,6 +689,10 @@ static void decode_instruction(unsigned short *address) verbose_printk("CALL (PC+P%i)", opcode & 7); else if (opcode >= 0x0080 && opcode <= 0x0087) verbose_printk("JUMP (PC+P%i)", opcode & 7); + else if (opcode >= 0x0090 && opcode <= 0x009F) + verbose_printk("RAISE 0x%x", opcode & 0xF); + else if (opcode >= 0x00A0 && opcode <= 0x00AF) + verbose_printk("EXCPT 0x%x", opcode & 0xF); else if ((opcode >= 0x1000 && opcode <= 0x13FF) || (opcode >= 0x1800 && opcode <= 0x1BFF)) verbose_printk("IF !CC JUMP"); else if ((opcode >= 0x1400 && opcode <= 0x17ff) || (opcode >= 0x1c00 && opcode <= 0x1fff)) From 3605fb09652beeb2e8244c52a9db5b76cc12295e Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 087/111] Blackfin arch: Add ability to count and display number of NMI interrupts Signed-off-by: Robin Getz Signed-off-by: Bryan Wu --- arch/blackfin/include/asm/pda.h | 1 + arch/blackfin/kernel/irqchip.c | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/blackfin/include/asm/pda.h b/arch/blackfin/include/asm/pda.h index bd8d4a7efeb2..a67142740df0 100644 --- a/arch/blackfin/include/asm/pda.h +++ b/arch/blackfin/include/asm/pda.h @@ -59,6 +59,7 @@ struct blackfin_pda { /* Per-processor Data Area */ unsigned long icplb_fault_addr; unsigned long retx; unsigned long seqstat; + unsigned int __nmi_count; /* number of times NMI asserted on this CPU */ }; extern struct blackfin_pda cpu_pda[]; diff --git a/arch/blackfin/kernel/irqchip.c b/arch/blackfin/kernel/irqchip.c index ab8209cbbad0..75724eee6494 100644 --- a/arch/blackfin/kernel/irqchip.c +++ b/arch/blackfin/kernel/irqchip.c @@ -35,6 +35,7 @@ #include #include #include +#include static atomic_t irq_err_count; static spinlock_t irq_controller_lock; @@ -91,8 +92,13 @@ int show_interrupts(struct seq_file *p, void *v) seq_putc(p, '\n'); skip: spin_unlock_irqrestore(&irq_desc[i].lock, flags); - } else if (i == NR_IRQS) + } else if (i == NR_IRQS) { + seq_printf(p, "NMI: "); + for_each_online_cpu(j) + seq_printf(p, "%10u ", cpu_pda[j].__nmi_count); + seq_printf(p, " CORE Non Maskable Interrupt\n"); seq_printf(p, "Err: %10u\n", atomic_read(&irq_err_count)); + } return 0; } From 5b93e13ffa8b06ff80eaa8e0ae92e44ebf61cde9 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 088/111] MAINTIANERS: Blackfin: remove subscribers-only marking remove subscribers-only marking as the list is automatically & silently moderated for people Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 474ec0c53272..5bff376d297c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -911,7 +911,7 @@ S: Maintained BLACKFIN ARCHITECTURE P: Bryan Wu M: cooloney@kernel.org -L: uclinux-dist-devel@blackfin.uclinux.org (subscribers-only) +L: uclinux-dist-devel@blackfin.uclinux.org W: http://blackfin.uclinux.org S: Supported From b52dae3139066765a7d96563e9cd33d9e60efe33 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 089/111] Blackfin arch: Fix bug - Run "reboot" hangs bf518-ezbrd [Mike Frysinger : - setup P_DEFAULT_BOOT_SPI_CS for every arch based on the default bootrom behavior and convert all our boards to it - revert previous anomaly change ... bf51x is not affected by anomaly 05000353] Signed-off-by: Sonic Zhang Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/include/asm/reboot.h | 2 +- arch/blackfin/kernel/bfin_gpio.c | 5 ++--- arch/blackfin/mach-bf518/boards/ezbrd.c | 2 +- arch/blackfin/mach-bf518/include/mach/portmux.h | 2 ++ arch/blackfin/mach-bf527/boards/cm_bf527.c | 2 +- arch/blackfin/mach-bf527/boards/ezbrd.c | 2 +- arch/blackfin/mach-bf527/boards/ezkit.c | 2 +- arch/blackfin/mach-bf527/include/mach/portmux.h | 2 ++ arch/blackfin/mach-bf533/include/mach/portmux.h | 5 +---- arch/blackfin/mach-bf537/boards/generic_board.c | 2 +- arch/blackfin/mach-bf537/boards/minotaur.c | 2 +- arch/blackfin/mach-bf537/boards/stamp.c | 2 +- arch/blackfin/mach-bf537/include/mach/portmux.h | 1 + arch/blackfin/mach-bf538/include/mach/portmux.h | 1 + arch/blackfin/mach-bf548/include/mach/portmux.h | 1 + arch/blackfin/mach-bf561/include/mach/portmux.h | 1 + 16 files changed, 19 insertions(+), 15 deletions(-) diff --git a/arch/blackfin/include/asm/reboot.h b/arch/blackfin/include/asm/reboot.h index 4856d62b7467..ae1e36329bec 100644 --- a/arch/blackfin/include/asm/reboot.h +++ b/arch/blackfin/include/asm/reboot.h @@ -15,6 +15,6 @@ extern void native_machine_halt(void); extern void native_machine_power_off(void); /* common reboot workarounds */ -extern void bfin_gpio_reset_spi0_ssel1(void); +extern void bfin_reset_boot_spi_cs(unsigned short pin); #endif diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c index 7f69f43be987..44b6c9da6c35 100644 --- a/arch/blackfin/kernel/bfin_gpio.c +++ b/arch/blackfin/kernel/bfin_gpio.c @@ -1172,10 +1172,9 @@ EXPORT_SYMBOL(bfin_gpio_get_value); * lives here as we need to force all the GPIO states w/out going through * BUG() checks and such. */ -void bfin_gpio_reset_spi0_ssel1(void) +void bfin_reset_boot_spi_cs(unsigned short pin) { - u16 gpio = P_IDENT(P_SPI0_SSEL1); - + unsigned short gpio = P_IDENT(pin); port_setup(gpio, GPIO_USAGE); gpio_array[gpio_bank(gpio)]->data_set = gpio_bit(gpio); AWA_DUMMY_READ(data_set); diff --git a/arch/blackfin/mach-bf518/boards/ezbrd.c b/arch/blackfin/mach-bf518/boards/ezbrd.c index 15f1351c8645..ee003f47a824 100644 --- a/arch/blackfin/mach-bf518/boards/ezbrd.c +++ b/arch/blackfin/mach-bf518/boards/ezbrd.c @@ -649,7 +649,7 @@ void native_machine_restart(char *cmd) { /* workaround reboot hang when booting from SPI */ if ((bfin_read_SYSCR() & 0x7) == 0x3) - bfin_gpio_reset_spi0_ssel1(); + bfin_reset_boot_spi_cs(P_DEFAULT_BOOT_SPI_CS); } void bfin_get_ether_addr(char *addr) diff --git a/arch/blackfin/mach-bf518/include/mach/portmux.h b/arch/blackfin/mach-bf518/include/mach/portmux.h index ac16d54734d4..f618b487b2b0 100644 --- a/arch/blackfin/mach-bf518/include/mach/portmux.h +++ b/arch/blackfin/mach-bf518/include/mach/portmux.h @@ -103,6 +103,8 @@ #define P_SPI1_SSEL4 (P_DEFINED | P_IDENT(GPIO_PF8) | P_FUNCT(2)) #define P_SPI1_SSEL5 (P_DEFINED | P_IDENT(GPIO_PG11) | P_FUNCT(2)) +#define P_DEFAULT_BOOT_SPI_CS P_SPI0_SSEL2 + /* SPORT Port Mux */ #define P_SPORT0_DRPRI (P_DEFINED | P_IDENT(GPIO_PG3) | P_FUNCT(0)) #define P_SPORT0_RSCLK (P_DEFINED | P_IDENT(GPIO_PG4) | P_FUNCT(0)) diff --git a/arch/blackfin/mach-bf527/boards/cm_bf527.c b/arch/blackfin/mach-bf527/boards/cm_bf527.c index a2c3578f4b6c..0281159b1c9b 100644 --- a/arch/blackfin/mach-bf527/boards/cm_bf527.c +++ b/arch/blackfin/mach-bf527/boards/cm_bf527.c @@ -988,7 +988,7 @@ void native_machine_restart(char *cmd) { /* workaround reboot hang when booting from SPI */ if ((bfin_read_SYSCR() & 0x7) == 0x3) - bfin_gpio_reset_spi0_ssel1(); + bfin_reset_boot_spi_cs(P_DEFAULT_BOOT_SPI_CS); } void bfin_get_ether_addr(char *addr) diff --git a/arch/blackfin/mach-bf527/boards/ezbrd.c b/arch/blackfin/mach-bf527/boards/ezbrd.c index 0314bd3355eb..521b25363815 100644 --- a/arch/blackfin/mach-bf527/boards/ezbrd.c +++ b/arch/blackfin/mach-bf527/boards/ezbrd.c @@ -784,7 +784,7 @@ void native_machine_restart(char *cmd) { /* workaround reboot hang when booting from SPI */ if ((bfin_read_SYSCR() & 0x7) == 0x3) - bfin_gpio_reset_spi0_ssel1(); + bfin_reset_boot_spi_cs(P_DEFAULT_BOOT_SPI_CS); } void bfin_get_ether_addr(char *addr) diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c index 9454fb7b18c3..60fd9743ebc1 100644 --- a/arch/blackfin/mach-bf527/boards/ezkit.c +++ b/arch/blackfin/mach-bf527/boards/ezkit.c @@ -1068,7 +1068,7 @@ void native_machine_restart(char *cmd) { /* workaround reboot hang when booting from SPI */ if ((bfin_read_SYSCR() & 0x7) == 0x3) - bfin_gpio_reset_spi0_ssel1(); + bfin_reset_boot_spi_cs(P_DEFAULT_BOOT_SPI_CS); } void bfin_get_ether_addr(char *addr) diff --git a/arch/blackfin/mach-bf527/include/mach/portmux.h b/arch/blackfin/mach-bf527/include/mach/portmux.h index 7f6da2c386bb..72b1652be4da 100644 --- a/arch/blackfin/mach-bf527/include/mach/portmux.h +++ b/arch/blackfin/mach-bf527/include/mach/portmux.h @@ -73,6 +73,8 @@ #define P_HWAIT (P_DONTCARE) +#define P_DEFAULT_BOOT_SPI_CS P_SPI0_SSEL1 + #define P_SPI0_SS (P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(0)) #define P_SPI0_SSEL1 (P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(2)) #define P_SPI0_SCK (P_DEFINED | P_IDENT(GPIO_PG2) | P_FUNCT(2)) diff --git a/arch/blackfin/mach-bf533/include/mach/portmux.h b/arch/blackfin/mach-bf533/include/mach/portmux.h index 685a2651dcda..2f59ce0b0cb5 100644 --- a/arch/blackfin/mach-bf533/include/mach/portmux.h +++ b/arch/blackfin/mach-bf533/include/mach/portmux.h @@ -54,14 +54,11 @@ #define P_SPI0_SSEL2 (P_DEFINED | P_IDENT(GPIO_PF2)) #define P_SPI0_SSEL1 (P_DEFINED | P_IDENT(GPIO_PF1)) #define P_SPI0_SS (P_DEFINED | P_IDENT(GPIO_PF0)) +#define P_DEFAULT_BOOT_SPI_CS P_SPI0_SSEL2 #define P_TMR2 (P_DONTCARE) #define P_TMR1 (P_DONTCARE) #define P_TMR0 (P_DONTCARE) #define P_TMRCLK (P_DEFINED | P_IDENT(GPIO_PF1)) - - - - #endif /* _MACH_PORTMUX_H_ */ diff --git a/arch/blackfin/mach-bf537/boards/generic_board.c b/arch/blackfin/mach-bf537/boards/generic_board.c index dd6e6bfb98ea..d12ddf155102 100644 --- a/arch/blackfin/mach-bf537/boards/generic_board.c +++ b/arch/blackfin/mach-bf537/boards/generic_board.c @@ -726,7 +726,7 @@ void native_machine_restart(char *cmd) { /* workaround reboot hang when booting from SPI */ if ((bfin_read_SYSCR() & 0x7) == 0x3) - bfin_gpio_reset_spi0_ssel1(); + bfin_reset_boot_spi_cs(P_DEFAULT_BOOT_SPI_CS); } #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) diff --git a/arch/blackfin/mach-bf537/boards/minotaur.c b/arch/blackfin/mach-bf537/boards/minotaur.c index bb795341cb17..8f36d260aee2 100644 --- a/arch/blackfin/mach-bf537/boards/minotaur.c +++ b/arch/blackfin/mach-bf537/boards/minotaur.c @@ -377,5 +377,5 @@ void native_machine_restart(char *cmd) { /* workaround reboot hang when booting from SPI */ if ((bfin_read_SYSCR() & 0x7) == 0x3) - bfin_gpio_reset_spi0_ssel1(); + bfin_reset_boot_spi_cs(P_DEFAULT_BOOT_SPI_CS); } diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c index d812e2514a2f..447d6d40361b 100644 --- a/arch/blackfin/mach-bf537/boards/stamp.c +++ b/arch/blackfin/mach-bf537/boards/stamp.c @@ -1307,7 +1307,7 @@ void native_machine_restart(char *cmd) { /* workaround reboot hang when booting from SPI */ if ((bfin_read_SYSCR() & 0x7) == 0x3) - bfin_gpio_reset_spi0_ssel1(); + bfin_reset_boot_spi_cs(P_DEFAULT_BOOT_SPI_CS); } /* diff --git a/arch/blackfin/mach-bf537/include/mach/portmux.h b/arch/blackfin/mach-bf537/include/mach/portmux.h index 78fee6e0f237..87285e75e903 100644 --- a/arch/blackfin/mach-bf537/include/mach/portmux.h +++ b/arch/blackfin/mach-bf537/include/mach/portmux.h @@ -31,6 +31,7 @@ #define P_PPI0_FS1 (P_DEFINED | P_IDENT(GPIO_PF9) | P_FUNCT(1)) #define P_TACLK0 (P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(1)) #define P_TMRCLK (P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(1)) +#define P_DEFAULT_BOOT_SPI_CS P_SPI0_SSEL1 #define P_PPI0_D0 (P_DEFINED | P_IDENT(GPIO_PG0) | P_FUNCT(0)) #define P_PPI0_D1 (P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(0)) diff --git a/arch/blackfin/mach-bf538/include/mach/portmux.h b/arch/blackfin/mach-bf538/include/mach/portmux.h index 1e031b588b47..c8db264e3e4d 100644 --- a/arch/blackfin/mach-bf538/include/mach/portmux.h +++ b/arch/blackfin/mach-bf538/include/mach/portmux.h @@ -102,5 +102,6 @@ #define P_SPI0_SSEL2 (P_DEFINED | P_IDENT(GPIO_PF2)) #define P_SPI0_SSEL1 (P_DEFINED | P_IDENT(GPIO_PF1)) #define P_SPI0_SS (P_DEFINED | P_IDENT(GPIO_PF0)) +#define P_DEFAULT_BOOT_SPI_CS P_SPI0_SSEL2 #endif /* _MACH_PORTMUX_H_ */ diff --git a/arch/blackfin/mach-bf548/include/mach/portmux.h b/arch/blackfin/mach-bf548/include/mach/portmux.h index 8177a567dcdb..ffb1d0a44b4d 100644 --- a/arch/blackfin/mach-bf548/include/mach/portmux.h +++ b/arch/blackfin/mach-bf548/include/mach/portmux.h @@ -125,6 +125,7 @@ #define P_KEY_COL2 (P_DEFINED | P_IDENT(GPIO_PD14) | P_FUNCT(3)) #define P_KEY_COL3 (P_DEFINED | P_IDENT(GPIO_PD15) | P_FUNCT(3)) +#define P_DEFAULT_BOOT_SPI_CS P_SPI0_SSEL1 #define P_SPI0_SCK (P_DEFINED | P_IDENT(GPIO_PE0) | P_FUNCT(0)) #define P_SPI0_MISO (P_DEFINED | P_IDENT(GPIO_PE1) | P_FUNCT(0)) #define P_SPI0_MOSI (P_DEFINED | P_IDENT(GPIO_PE2) | P_FUNCT(0)) diff --git a/arch/blackfin/mach-bf561/include/mach/portmux.h b/arch/blackfin/mach-bf561/include/mach/portmux.h index a6ee8206efb6..2e5ad6347dea 100644 --- a/arch/blackfin/mach-bf561/include/mach/portmux.h +++ b/arch/blackfin/mach-bf561/include/mach/portmux.h @@ -85,5 +85,6 @@ #define P_SPI0_MOSI (P_DONTCARE) #define P_SPI0_MISO (P_DONTCARE) #define P_SPI0_SCK (P_DONTCARE) +#define P_DEFAULT_BOOT_SPI_CS P_SPI0_SSEL2 #endif /* _MACH_PORTMUX_H_ */ From 047481f348668340fab7164b12be130ca2ad2522 Mon Sep 17 00:00:00 2001 From: Grace Pan Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 090/111] Blackfin arch: Add in cflag to support mlong-calls for kgdb_test Signed-off-by: Grace Pan Signed-off-by: Bryan Wu --- arch/blackfin/kernel/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile index 38a233374f07..4a92a86824b7 100644 --- a/arch/blackfin/kernel/Makefile +++ b/arch/blackfin/kernel/Makefile @@ -15,6 +15,8 @@ else obj-y += time.o endif +CFLAGS_kgdb_test.o := -mlong-calls -O0 + obj-$(CONFIG_IPIPE) += ipipe.o obj-$(CONFIG_IPIPE_TRACE_MCOUNT) += mcount.o obj-$(CONFIG_BFIN_GPTIMERS) += gptimers.o From 0ce5eaf8ec156926a29313de877d9d5e0a692054 Mon Sep 17 00:00:00 2001 From: Graf Yang Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 091/111] Blackfin arch: Fix bug - BF518 port F, G, and H have different mux offset compare to BF527 [Mike Frysinger : keep the ifdef nest down] Signed-off-by: Graf Yang Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/kernel/bfin_gpio.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c index 44b6c9da6c35..51dac55c524a 100644 --- a/arch/blackfin/kernel/bfin_gpio.c +++ b/arch/blackfin/kernel/bfin_gpio.c @@ -108,12 +108,19 @@ static unsigned short * const port_mux[] = { }; static const -u8 pmux_offset[][16] = - {{ 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 4, 6, 8, 8, 10, 10 }, /* PORTF */ - { 0, 0, 0, 0, 0, 2, 2, 4, 4, 6, 8, 10, 10, 10, 12, 12 }, /* PORTG */ - { 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 4, 4, 4, 4, 4 }, /* PORTH */ - }; +u8 pmux_offset[][16] = { +# if defined(BF527_FAMILY) + { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 4, 6, 8, 8, 10, 10 }, /* PORTF */ + { 0, 0, 0, 0, 0, 2, 2, 4, 4, 6, 8, 10, 10, 10, 12, 12 }, /* PORTG */ + { 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 4, 4, 4, 4, 4 }, /* PORTH */ +# elif defined(BF518_FAMILY) + { 0, 2, 2, 2, 2, 2, 2, 4, 6, 6, 6, 8, 8, 8, 8, 10 }, /* PORTF */ + { 0, 0, 0, 2, 4, 6, 6, 6, 8, 10, 10, 12, 14, 14, 14, 14 }, /* PORTG */ + { 0, 0, 0, 0, 2, 2, 4, 6, 10, 10, 10, 10, 10, 10, 10, 10 }, /* PORTH */ +# endif +}; # endif + #endif static unsigned short reserved_gpio_map[GPIO_BANK_NUM]; From aa9c33b496ca9434f26beaa1b447a6e2e5d8ad6a Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 092/111] Blackfin arch: Faster Implementation of csum_tcpudp_nofold() Avoid conditional branch instructions during carry bit additions. Special thanks to Bernd. Simplify: Use ((len + proto) << 8) like every other __LITTLE_ENDIAN__ machine Cc: Bernd Schmidt Signed-off-by: Michael Hennerich Signed-off-by: Bryan Wu --- arch/blackfin/include/asm/checksum.h | 32 ++++++++++++++-------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/arch/blackfin/include/asm/checksum.h b/arch/blackfin/include/asm/checksum.h index f67289a0d8d2..793581fc9556 100644 --- a/arch/blackfin/include/asm/checksum.h +++ b/arch/blackfin/include/asm/checksum.h @@ -63,23 +63,23 @@ static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, unsigned short proto, __wsum sum) { + unsigned int carry; - __asm__ ("%0 = %0 + %1;\n\t" - "CC = AC0;\n\t" - "if !CC jump 4;\n\t" - "%0 = %0 + %4;\n\t" - "%0 = %0 + %2;\n\t" - "CC = AC0;\n\t" - "if !CC jump 4;\n\t" - "%0 = %0 + %4;\n\t" - "%0 = %0 + %3;\n\t" - "CC = AC0;\n\t" - "if !CC jump 4;\n\t" - "%0 = %0 + %4;\n\t" - "NOP;\n\t" - : "=d" (sum) - : "d" (daddr), "d" (saddr), "d" ((ntohs(len)<<16)+proto*256), "d" (1), "0"(sum) - : "CC"); + __asm__ ("%0 = %0 + %2;\n\t" + "CC = AC0;\n\t" + "%1 = CC;\n\t" + "%0 = %0 + %1;\n\t" + "%0 = %0 + %3;\n\t" + "CC = AC0;\n\t" + "%1 = CC;\n\t" + "%0 = %0 + %1;\n\t" + "%0 = %0 + %4;\n\t" + "CC = AC0;\n\t" + "%1 = CC;\n\t" + "%0 = %0 + %1;\n\t" + : "=d" (sum), "=&d" (carry) + : "d" (daddr), "d" (saddr), "d" ((len + proto) << 8), "0"(sum) + : "CC"); return (sum); } From adab7eb883a0b0fb7f13b1d7b30b596139f6f40d Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 093/111] Blackfin arch: sync reboot handler with version in u-boot Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/kernel/reboot.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/arch/blackfin/kernel/reboot.c b/arch/blackfin/kernel/reboot.c index eeee8cb43360..f7ca5789cccf 100644 --- a/arch/blackfin/kernel/reboot.c +++ b/arch/blackfin/kernel/reboot.c @@ -20,7 +20,7 @@ * reset while the Core B bit (on dual core parts) is cleared by * the core reset. */ -__attribute__((l1_text)) +__attribute__ ((__l1_text__, __noreturn__)) static void _bfin_reset(void) { /* Wait for completion of "system" events such as cache line @@ -30,7 +30,11 @@ static void _bfin_reset(void) */ __builtin_bfin_ssync(); - while (1) { + /* The bootrom checks to see how it was reset and will + * automatically perform a software reset for us when + * it starts executing after the core reset. + */ + if (ANOMALY_05000353 || ANOMALY_05000386) { /* Initiate System software reset. */ bfin_write_SWRST(0x7); @@ -50,6 +54,11 @@ static void _bfin_reset(void) /* Clear System software reset */ bfin_write_SWRST(0); + /* The BF526 ROM will crash during reset */ +#if defined(__ADSPBF522__) || defined(__ADSPBF524__) || defined(__ADSPBF526__) + bfin_read_SWRST(); +#endif + /* Wait for the SWRST write to complete. Cannot rely on SSYNC * though as the System state is all reset now. */ @@ -60,22 +69,17 @@ static void _bfin_reset(void) : "a" (15 * 1) : "LC1", "LB1", "LT1" ); + } + while (1) /* Issue core reset */ asm("raise 1"); - } } +__attribute__ ((__noreturn__)) static void bfin_reset(void) { - if (ANOMALY_05000353 || ANOMALY_05000386) - _bfin_reset(); - else - /* the bootrom checks to see how it was reset and will - * automatically perform a software reset for us when - * it starts executing boot - */ - asm("raise 1;"); + _bfin_reset(); } __attribute__((weak)) From a6595bf04b9cc9a4997e6d849b62d69439dd1eff Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 094/111] Blackfin arch: bfin_reset->_bfin_reset redirection no longer needed Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/kernel/reboot.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/arch/blackfin/kernel/reboot.c b/arch/blackfin/kernel/reboot.c index f7ca5789cccf..53d08dee8531 100644 --- a/arch/blackfin/kernel/reboot.c +++ b/arch/blackfin/kernel/reboot.c @@ -21,7 +21,7 @@ * the core reset. */ __attribute__ ((__l1_text__, __noreturn__)) -static void _bfin_reset(void) +static void bfin_reset(void) { /* Wait for completion of "system" events such as cache line * line fills so that we avoid infinite stalls later on as @@ -76,12 +76,6 @@ static void _bfin_reset(void) asm("raise 1"); } -__attribute__ ((__noreturn__)) -static void bfin_reset(void) -{ - _bfin_reset(); -} - __attribute__((weak)) void native_machine_restart(char *cmd) { From 2678479c33774f297ea2a5d232cad11c4d56ef6c Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 095/111] Blackfin arch: drop CONFIG_I2C_BOARDINFO ifdefs Drop CONFIG_I2C_BOARDINFO ifdefs as the common i2c header handles this already by stubbing things out Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/mach-bf518/boards/ezbrd.c | 6 ------ arch/blackfin/mach-bf527/boards/cm_bf527.c | 6 ------ arch/blackfin/mach-bf527/boards/ezbrd.c | 6 ------ arch/blackfin/mach-bf527/boards/ezkit.c | 6 ------ arch/blackfin/mach-bf533/boards/blackstamp.c | 4 ---- arch/blackfin/mach-bf533/boards/stamp.c | 4 ---- arch/blackfin/mach-bf537/boards/stamp.c | 6 ------ arch/blackfin/mach-bf548/boards/ezkit.c | 4 ---- 8 files changed, 42 deletions(-) diff --git a/arch/blackfin/mach-bf518/boards/ezbrd.c b/arch/blackfin/mach-bf518/boards/ezbrd.c index ee003f47a824..b23108bcbf59 100644 --- a/arch/blackfin/mach-bf518/boards/ezbrd.c +++ b/arch/blackfin/mach-bf518/boards/ezbrd.c @@ -473,7 +473,6 @@ static struct platform_device i2c_bfin_twi_device = { }; #endif -#ifdef CONFIG_I2C_BOARDINFO static struct i2c_board_info __initdata bfin_i2c_board_info[] = { #if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE) { @@ -487,7 +486,6 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = { }, #endif }; -#endif #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE) static struct platform_device bfin_sport0_uart_device = { @@ -632,12 +630,8 @@ static struct platform_device *stamp_devices[] __initdata = { static int __init ezbrd_init(void) { printk(KERN_INFO "%s(): registering device resources\n", __func__); - -#ifdef CONFIG_I2C_BOARDINFO i2c_register_board_info(0, bfin_i2c_board_info, ARRAY_SIZE(bfin_i2c_board_info)); -#endif - platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices)); spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info)); return 0; diff --git a/arch/blackfin/mach-bf527/boards/cm_bf527.c b/arch/blackfin/mach-bf527/boards/cm_bf527.c index 0281159b1c9b..638cfcddbae8 100644 --- a/arch/blackfin/mach-bf527/boards/cm_bf527.c +++ b/arch/blackfin/mach-bf527/boards/cm_bf527.c @@ -793,7 +793,6 @@ static struct platform_device i2c_bfin_twi_device = { }; #endif -#ifdef CONFIG_I2C_BOARDINFO static struct i2c_board_info __initdata bfin_i2c_board_info[] = { #if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE) { @@ -809,7 +808,6 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = { }, #endif }; -#endif #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE) static struct platform_device bfin_sport0_uart_device = { @@ -971,12 +969,8 @@ static struct platform_device *stamp_devices[] __initdata = { static int __init stamp_init(void) { printk(KERN_INFO "%s(): registering device resources\n", __func__); - -#ifdef CONFIG_I2C_BOARDINFO i2c_register_board_info(0, bfin_i2c_board_info, ARRAY_SIZE(bfin_i2c_board_info)); -#endif - platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices)); spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info)); return 0; diff --git a/arch/blackfin/mach-bf527/boards/ezbrd.c b/arch/blackfin/mach-bf527/boards/ezbrd.c index 521b25363815..f2b7a5482017 100644 --- a/arch/blackfin/mach-bf527/boards/ezbrd.c +++ b/arch/blackfin/mach-bf527/boards/ezbrd.c @@ -590,7 +590,6 @@ static struct platform_device i2c_bfin_twi_device = { }; #endif -#ifdef CONFIG_I2C_BOARDINFO static struct i2c_board_info __initdata bfin_i2c_board_info[] = { #if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE) { @@ -604,7 +603,6 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = { }, #endif }; -#endif #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE) static struct platform_device bfin_sport0_uart_device = { @@ -767,12 +765,8 @@ static struct platform_device *stamp_devices[] __initdata = { static int __init stamp_init(void) { printk(KERN_INFO "%s(): registering device resources\n", __func__); - -#ifdef CONFIG_I2C_BOARDINFO i2c_register_board_info(0, bfin_i2c_board_info, ARRAY_SIZE(bfin_i2c_board_info)); -#endif - platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices)); spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info)); return 0; diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c index 60fd9743ebc1..dc9bdb9cd752 100644 --- a/arch/blackfin/mach-bf527/boards/ezkit.c +++ b/arch/blackfin/mach-bf527/boards/ezkit.c @@ -830,7 +830,6 @@ static struct platform_device i2c_bfin_twi_device = { }; #endif -#ifdef CONFIG_I2C_BOARDINFO static struct i2c_board_info __initdata bfin_i2c_board_info[] = { #if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE) { @@ -844,7 +843,6 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = { }, #endif }; -#endif #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE) static struct platform_device bfin_sport0_uart_device = { @@ -1051,12 +1049,8 @@ static struct platform_device *stamp_devices[] __initdata = { static int __init stamp_init(void) { printk(KERN_INFO "%s(): registering device resources\n", __func__); - -#ifdef CONFIG_I2C_BOARDINFO i2c_register_board_info(0, bfin_i2c_board_info, ARRAY_SIZE(bfin_i2c_board_info)); -#endif - platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices)); spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info)); return 0; diff --git a/arch/blackfin/mach-bf533/boards/blackstamp.c b/arch/blackfin/mach-bf533/boards/blackstamp.c index 6ee607c259ac..015c18f85e7f 100644 --- a/arch/blackfin/mach-bf533/boards/blackstamp.c +++ b/arch/blackfin/mach-bf533/boards/blackstamp.c @@ -309,10 +309,8 @@ static struct platform_device i2c_gpio_device = { }; #endif -#ifdef CONFIG_I2C_BOARDINFO static struct i2c_board_info __initdata bfin_i2c_board_info[] = { }; -#endif static const unsigned int cclk_vlev_datasheet[] = { @@ -390,10 +388,8 @@ static int __init blackstamp_init(void) printk(KERN_INFO "%s(): registering device resources\n", __func__); -#ifdef CONFIG_I2C_BOARDINFO i2c_register_board_info(0, bfin_i2c_board_info, ARRAY_SIZE(bfin_i2c_board_info)); -#endif ret = platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices)); if (ret < 0) diff --git a/arch/blackfin/mach-bf533/boards/stamp.c b/arch/blackfin/mach-bf533/boards/stamp.c index 07f9ad1e189c..db96f33f72e2 100644 --- a/arch/blackfin/mach-bf533/boards/stamp.c +++ b/arch/blackfin/mach-bf533/boards/stamp.c @@ -441,7 +441,6 @@ static struct platform_device i2c_gpio_device = { }; #endif -#ifdef CONFIG_I2C_BOARDINFO static struct i2c_board_info __initdata bfin_i2c_board_info[] = { #if defined(CONFIG_JOYSTICK_AD7142) || defined(CONFIG_JOYSTICK_AD7142_MODULE) { @@ -461,7 +460,6 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = { }, #endif }; -#endif static const unsigned int cclk_vlev_datasheet[] = { @@ -550,10 +548,8 @@ static int __init stamp_init(void) printk(KERN_INFO "%s(): registering device resources\n", __func__); -#ifdef CONFIG_I2C_BOARDINFO i2c_register_board_info(0, bfin_i2c_board_info, ARRAY_SIZE(bfin_i2c_board_info)); -#endif ret = platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices)); if (ret < 0) diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c index 447d6d40361b..2300ed4ec601 100644 --- a/arch/blackfin/mach-bf537/boards/stamp.c +++ b/arch/blackfin/mach-bf537/boards/stamp.c @@ -1068,7 +1068,6 @@ static struct adp5588_kpad_platform_data adp5588_kpad_data = { }; #endif -#ifdef CONFIG_I2C_BOARDINFO static struct i2c_board_info __initdata bfin_i2c_board_info[] = { #if defined(CONFIG_JOYSTICK_AD7142) || defined(CONFIG_JOYSTICK_AD7142_MODULE) { @@ -1102,7 +1101,6 @@ static struct i2c_board_info __initdata bfin_i2c_board_info[] = { }, #endif }; -#endif #if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE) static struct platform_device bfin_sport0_uart_device = { @@ -1284,12 +1282,8 @@ static struct platform_device *stamp_devices[] __initdata = { static int __init stamp_init(void) { printk(KERN_INFO "%s(): registering device resources\n", __func__); - -#ifdef CONFIG_I2C_BOARDINFO i2c_register_board_info(0, bfin_i2c_board_info, ARRAY_SIZE(bfin_i2c_board_info)); -#endif - bfin_plat_nand_init(); platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices)); spi_register_board_info(bfin_spi_board_info, ARRAY_SIZE(bfin_spi_board_info)); diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c index 309c16014cae..096e661700a7 100644 --- a/arch/blackfin/mach-bf548/boards/ezkit.c +++ b/arch/blackfin/mach-bf548/boards/ezkit.c @@ -781,7 +781,6 @@ static struct platform_device i2c_bfin_twi1_device = { #endif #endif -#ifdef CONFIG_I2C_BOARDINFO static struct i2c_board_info __initdata bfin_i2c_board_info0[] = { }; @@ -800,7 +799,6 @@ static struct i2c_board_info __initdata bfin_i2c_board_info1[] = { #endif }; #endif -#endif #if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE) #include @@ -956,13 +954,11 @@ static int __init ezkit_init(void) { printk(KERN_INFO "%s(): registering device resources\n", __func__); -#ifdef CONFIG_I2C_BOARDINFO i2c_register_board_info(0, bfin_i2c_board_info0, ARRAY_SIZE(bfin_i2c_board_info0)); #if !defined(CONFIG_BF542) /* The BF542 only has 1 TWI */ i2c_register_board_info(1, bfin_i2c_board_info1, ARRAY_SIZE(bfin_i2c_board_info1)); -#endif #endif platform_add_devices(ezkit_devices, ARRAY_SIZE(ezkit_devices)); From 7f6678c52fea7ff3e7eb6a5f0e0b705c1991eaa2 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 096/111] Blackfin arch: fixup board init function name Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/mach-bf527/boards/cm_bf527.c | 4 ++-- arch/blackfin/mach-bf527/boards/ezbrd.c | 4 ++-- arch/blackfin/mach-bf527/boards/ezkit.c | 4 ++-- arch/blackfin/mach-bf537/boards/generic_board.c | 4 ++-- arch/blackfin/mach-bf537/boards/pnav10.c | 4 ++-- arch/blackfin/mach-bf537/boards/tcm_bf537.c | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/arch/blackfin/mach-bf527/boards/cm_bf527.c b/arch/blackfin/mach-bf527/boards/cm_bf527.c index 638cfcddbae8..98ab8bc28304 100644 --- a/arch/blackfin/mach-bf527/boards/cm_bf527.c +++ b/arch/blackfin/mach-bf527/boards/cm_bf527.c @@ -966,7 +966,7 @@ static struct platform_device *stamp_devices[] __initdata = { &bfin_gpios_device, }; -static int __init stamp_init(void) +static int __init cm_init(void) { printk(KERN_INFO "%s(): registering device resources\n", __func__); i2c_register_board_info(0, bfin_i2c_board_info, @@ -976,7 +976,7 @@ static int __init stamp_init(void) return 0; } -arch_initcall(stamp_init); +arch_initcall(cm_init); void native_machine_restart(char *cmd) { diff --git a/arch/blackfin/mach-bf527/boards/ezbrd.c b/arch/blackfin/mach-bf527/boards/ezbrd.c index f2b7a5482017..d0f29870f1a4 100644 --- a/arch/blackfin/mach-bf527/boards/ezbrd.c +++ b/arch/blackfin/mach-bf527/boards/ezbrd.c @@ -762,7 +762,7 @@ static struct platform_device *stamp_devices[] __initdata = { &bfin_gpios_device, }; -static int __init stamp_init(void) +static int __init ezbrd_init(void) { printk(KERN_INFO "%s(): registering device resources\n", __func__); i2c_register_board_info(0, bfin_i2c_board_info, @@ -772,7 +772,7 @@ static int __init stamp_init(void) return 0; } -arch_initcall(stamp_init); +arch_initcall(ezbrd_init); void native_machine_restart(char *cmd) { diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c index dc9bdb9cd752..1f7a249d6926 100644 --- a/arch/blackfin/mach-bf527/boards/ezkit.c +++ b/arch/blackfin/mach-bf527/boards/ezkit.c @@ -1046,7 +1046,7 @@ static struct platform_device *stamp_devices[] __initdata = { &bfin_gpios_device, }; -static int __init stamp_init(void) +static int __init ezkit_init(void) { printk(KERN_INFO "%s(): registering device resources\n", __func__); i2c_register_board_info(0, bfin_i2c_board_info, @@ -1056,7 +1056,7 @@ static int __init stamp_init(void) return 0; } -arch_initcall(stamp_init); +arch_initcall(ezkit_init); void native_machine_restart(char *cmd) { diff --git a/arch/blackfin/mach-bf537/boards/generic_board.c b/arch/blackfin/mach-bf537/boards/generic_board.c index d12ddf155102..fb0368ec2aff 100644 --- a/arch/blackfin/mach-bf537/boards/generic_board.c +++ b/arch/blackfin/mach-bf537/boards/generic_board.c @@ -708,7 +708,7 @@ static struct platform_device *stamp_devices[] __initdata = { #endif }; -static int __init stamp_init(void) +static int __init generic_init(void) { printk(KERN_INFO "%s(): registering device resources\n", __func__); platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices)); @@ -720,7 +720,7 @@ static int __init stamp_init(void) return 0; } -arch_initcall(stamp_init); +arch_initcall(generic_init); void native_machine_restart(char *cmd) { diff --git a/arch/blackfin/mach-bf537/boards/pnav10.c b/arch/blackfin/mach-bf537/boards/pnav10.c index 89de94f4545d..8835c58cfaec 100644 --- a/arch/blackfin/mach-bf537/boards/pnav10.c +++ b/arch/blackfin/mach-bf537/boards/pnav10.c @@ -558,7 +558,7 @@ static struct platform_device *stamp_devices[] __initdata = { #endif }; -static int __init stamp_init(void) +static int __init pnav_init(void) { printk(KERN_INFO "%s(): registering device resources\n", __func__); platform_add_devices(stamp_devices, ARRAY_SIZE(stamp_devices)); @@ -569,7 +569,7 @@ static int __init stamp_init(void) return 0; } -arch_initcall(stamp_init); +arch_initcall(pnav_init); void bfin_get_ether_addr(char *addr) { diff --git a/arch/blackfin/mach-bf537/boards/tcm_bf537.c b/arch/blackfin/mach-bf537/boards/tcm_bf537.c index 2f4b066153c5..2e60bbad73ee 100644 --- a/arch/blackfin/mach-bf537/boards/tcm_bf537.c +++ b/arch/blackfin/mach-bf537/boards/tcm_bf537.c @@ -615,7 +615,7 @@ static struct platform_device *cm_bf537_devices[] __initdata = { &bfin_gpios_device, }; -static int __init cm_bf537_init(void) +static int __init tcm_bf537_init(void) { printk(KERN_INFO "%s(): registering device resources\n", __func__); platform_add_devices(cm_bf537_devices, ARRAY_SIZE(cm_bf537_devices)); @@ -629,7 +629,7 @@ static int __init cm_bf537_init(void) return 0; } -arch_initcall(cm_bf537_init); +arch_initcall(tcm_bf537_init); void bfin_get_ether_addr(char *addr) { From ed1fb6048c3eef68df5fe19e9022fdad6e53357d Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 097/111] Blackfin arch: read SYSCR on newer parts that mirror the bits of SWRST in it Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/kernel/setup.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index a23fec573c0a..86feb4274218 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -826,7 +826,13 @@ void __init setup_arch(char **cmdline_p) printk(KERN_INFO "Boot Mode: %i\n", bfin_read_SYSCR() & 0xF); + /* Newer parts mirror SWRST bits in SYSCR */ +#if defined(CONFIG_BF53x) || defined(CONFIG_BF561) || \ + defined(CONFIG_BF538) || defined(CONFIG_BF539) _bfin_swrst = bfin_read_SWRST(); +#else + _bfin_swrst = bfin_read_SYSCR(); +#endif #ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT bfin_write_SWRST(_bfin_swrst & ~DOUBLE_FAULT); From be1d8543a82d3a8f466509bbd355a5861193135f Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 098/111] Blackfin arch: base SIC_IWR# programming on whether the MMR exists base SIC_IWR# programming on whether the MMR exists rather than having to maintain another list of processors Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/ints-priority.c | 11 ++++------- arch/blackfin/mach-common/pm.c | 11 ++++------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index 1bba6030dce9..202494568c6c 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -1101,10 +1101,9 @@ int __init init_arch_irq(void) IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 | IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW; -#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) \ - || defined(BF538_FAMILY) || defined(CONFIG_BF51x) +#ifdef SIC_IWR0 bfin_write_SIC_IWR0(IWR_DISABLE_ALL); -#if defined(CONFIG_BF52x) || defined(CONFIG_BF51x) +# ifdef SIC_IWR1 /* BF52x/BF51x system reset does not properly reset SIC_IWR1 which * will screw up the bootrom as it relies on MDMA0/1 waking it * up from IDLE instructions. See this report for more info: @@ -1114,10 +1113,8 @@ int __init init_arch_irq(void) bfin_write_SIC_IWR1(IWR_ENABLE(10) | IWR_ENABLE(11)); else bfin_write_SIC_IWR1(IWR_DISABLE_ALL); -#else - bfin_write_SIC_IWR1(IWR_DISABLE_ALL); -#endif -# ifdef CONFIG_BF54x +# endif +# ifdef SIC_IWR2 bfin_write_SIC_IWR2(IWR_DISABLE_ALL); # endif #else diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c index d3d70fd67c16..f48a6aebb49b 100644 --- a/arch/blackfin/mach-common/pm.c +++ b/arch/blackfin/mach-common/pm.c @@ -82,10 +82,9 @@ void bfin_pm_suspend_standby_enter(void) bfin_pm_standby_restore(); -#if defined(CONFIG_BF54x) || defined(CONFIG_BF52x) || defined(CONFIG_BF561) || \ - defined(CONFIG_BF538) || defined(CONFIG_BF539) || defined(CONFIG_BF51x) +#ifdef SIC_IWR0 bfin_write_SIC_IWR0(IWR_DISABLE_ALL); -#if defined(CONFIG_BF52x) || defined(CONFIG_BF51x) +# ifdef SIC_IWR1 /* BF52x system reset does not properly reset SIC_IWR1 which * will screw up the bootrom as it relies on MDMA0/1 waking it * up from IDLE instructions. See this report for more info: @@ -95,10 +94,8 @@ void bfin_pm_suspend_standby_enter(void) bfin_write_SIC_IWR1(IWR_ENABLE(10) | IWR_ENABLE(11)); else bfin_write_SIC_IWR1(IWR_DISABLE_ALL); -#else - bfin_write_SIC_IWR1(IWR_DISABLE_ALL); -#endif -# ifdef CONFIG_BF54x +# endif +# ifdef SIC_IWR2 bfin_write_SIC_IWR2(IWR_DISABLE_ALL); # endif #else From 9960aa6a07bc41223a3bf2df1dfd284698486eb0 Mon Sep 17 00:00:00 2001 From: Graf Yang Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 099/111] Blackfin arch: Fix bug - 561 SMP kernel can't boot from jffs2 bss_l2 section is garbage when the data in this section is used by _bfin_relocate_l1_mem, so move the zero out function ahead. Signed-off-by: Graf Yang Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/head.S | 84 ++++++++++++++++---------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/arch/blackfin/mach-common/head.S b/arch/blackfin/mach-common/head.S index e1e42c029e15..698d4c05947e 100644 --- a/arch/blackfin/mach-common/head.S +++ b/arch/blackfin/mach-common/head.S @@ -17,6 +17,19 @@ __INIT +ENTRY(__init_clear_bss) + r2 = r2 - r1; + cc = r2 == 0; + if cc jump .L_bss_done; + r2 >>= 2; + p1 = r1; + p2 = r2; + lsetup (1f, 1f) lc0 = p2; +1: [p1++] = r0; +.L_bss_done: + rts; +ENDPROC(__init_clear_bss) + #define INITIAL_STACK (L1_SCRATCH_START + L1_SCRATCH_LENGTH - 12) ENTRY(__start) @@ -144,6 +157,35 @@ ENTRY(__start) call _init_early_exception_vectors; #endif + r0 = 0 (x); + /* Zero out all of the fun bss regions */ +#if L1_DATA_A_LENGTH > 0 + r1.l = __sbss_l1; + r1.h = __sbss_l1; + r2.l = __ebss_l1; + r2.h = __ebss_l1; + call __init_clear_bss +#endif +#if L1_DATA_B_LENGTH > 0 + r1.l = __sbss_b_l1; + r1.h = __sbss_b_l1; + r2.l = __ebss_b_l1; + r2.h = __ebss_b_l1; + call __init_clear_bss +#endif +#if L2_LENGTH > 0 + r1.l = __sbss_l2; + r1.h = __sbss_l2; + r2.l = __ebss_l2; + r2.h = __ebss_l2; + call __init_clear_bss +#endif + r1.l = ___bss_start; + r1.h = ___bss_start; + r2.l = ___bss_stop; + r2.h = ___bss_stop; + call __init_clear_bss + /* Put The Code for PLL Programming and SDRAM Programming in L1 ISRAM */ call _bfin_relocate_l1_mem; #ifdef CONFIG_BFIN_KERNEL_CLOCK @@ -185,19 +227,6 @@ ENDPROC(__start) # define WDOG_CTL WDOGA_CTL #endif -ENTRY(__init_clear_bss) - r2 = r2 - r1; - cc = r2 == 0; - if cc jump .L_bss_done; - r2 >>= 2; - p1 = r1; - p2 = r2; - lsetup (1f, 1f) lc0 = p2; -1: [p1++] = r0; -.L_bss_done: - rts; -ENDPROC(__init_clear_bss) - ENTRY(_real_start) /* Enable nested interrupts */ [--sp] = reti; @@ -209,35 +238,6 @@ ENTRY(_real_start) w[p0] = r0; ssync; - r0 = 0 (x); - /* Zero out all of the fun bss regions */ -#if L1_DATA_A_LENGTH > 0 - r1.l = __sbss_l1; - r1.h = __sbss_l1; - r2.l = __ebss_l1; - r2.h = __ebss_l1; - call __init_clear_bss -#endif -#if L1_DATA_B_LENGTH > 0 - r1.l = __sbss_b_l1; - r1.h = __sbss_b_l1; - r2.l = __ebss_b_l1; - r2.h = __ebss_b_l1; - call __init_clear_bss -#endif -#if L2_LENGTH > 0 - r1.l = __sbss_l2; - r1.h = __sbss_l2; - r2.l = __ebss_l2; - r2.h = __ebss_l2; - call __init_clear_bss -#endif - r1.l = ___bss_start; - r1.h = ___bss_start; - r2.l = ___bss_stop; - r2.h = ___bss_stop; - call __init_clear_bss - /* Pass the u-boot arguments to the global value command line */ R0 = R7; call _cmdline_init; From 1c302b6ccb1296bda3754708099233290f6cf689 Mon Sep 17 00:00:00 2001 From: Bryan Wu Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 100/111] Blackfin arch: Add ANOMALY_05000380 to BF54x to kill the compile warning Signed-off-by: Bryan Wu --- arch/blackfin/mach-bf548/include/mach/anomaly.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/blackfin/mach-bf548/include/mach/anomaly.h b/arch/blackfin/mach-bf548/include/mach/anomaly.h index 3b5430999f4f..23d03c52f4b4 100644 --- a/arch/blackfin/mach-bf548/include/mach/anomaly.h +++ b/arch/blackfin/mach-bf548/include/mach/anomaly.h @@ -175,6 +175,7 @@ #define ANOMALY_05000311 (0) #define ANOMALY_05000323 (0) #define ANOMALY_05000363 (0) +#define ANOMALY_05000380 (0) #define ANOMALY_05000412 (0) #define ANOMALY_05000432 (0) #define ANOMALY_05000435 (0) From 3aee91bafef01bd5c59853346f1fcb85f701fdc1 Mon Sep 17 00:00:00 2001 From: Jie Zhang Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 101/111] Blackfin arch: fix 2 bugs related to debug - unable to single step over emuexcpt instruction - gdbproxy goes into infinite loop when doing gdb does "next" over "emuexcpt" Don't decrement PC after software breakpoint. Signed-off-by: Jie Zhang Signed-off-by: Bryan Wu --- arch/blackfin/mach-common/entry.S | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index fae774651374..88de053bbe8e 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -151,13 +151,6 @@ ENTRY(_ex_syscall) jump.s _bfin_return_from_exception; ENDPROC(_ex_syscall) -ENTRY(_ex_soft_bp) - r7 = retx; - r7 += -2; - retx = r7; - jump.s _ex_trap_c; -ENDPROC(_ex_soft_bp) - ENTRY(_ex_single_step) /* If we just returned from an interrupt, the single step event is for the RTI instruction. */ @@ -1087,7 +1080,7 @@ ENTRY(_ex_table) * EXCPT instruction can provide 4 bits of EXCAUSE, allowing 16 to be user defined */ .long _ex_syscall /* 0x00 - User Defined - Linux Syscall */ - .long _ex_soft_bp /* 0x01 - User Defined - Software breakpoint */ + .long _ex_trap_c /* 0x01 - User Defined - Software breakpoint */ #ifdef CONFIG_KGDB .long _ex_trap_c /* 0x02 - User Defined - KGDB initial connection and break signal trap */ From 583947c6bc397854a3a57d45539654c9d8223966 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 102/111] Blackfin arch: build jtag tty driver as a module by default Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/configs/BF518F-EZBRD_defconfig | 2 +- arch/blackfin/configs/BF526-EZBRD_defconfig | 2 +- arch/blackfin/configs/BF527-EZKIT_defconfig | 2 +- arch/blackfin/configs/BF533-EZKIT_defconfig | 2 +- arch/blackfin/configs/BF533-STAMP_defconfig | 2 +- arch/blackfin/configs/BF537-STAMP_defconfig | 2 +- arch/blackfin/configs/BF538-EZKIT_defconfig | 2 +- arch/blackfin/configs/BF548-EZKIT_defconfig | 2 +- arch/blackfin/configs/BF561-EZKIT_defconfig | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/blackfin/configs/BF518F-EZBRD_defconfig b/arch/blackfin/configs/BF518F-EZBRD_defconfig index 18e9784376f2..4fdb9e04759f 100644 --- a/arch/blackfin/configs/BF518F-EZBRD_defconfig +++ b/arch/blackfin/configs/BF518F-EZBRD_defconfig @@ -684,7 +684,7 @@ CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y # CONFIG_VT_HW_CONSOLE_BINDING is not set # CONFIG_DEVKMEM is not set -# CONFIG_BFIN_JTAG_COMM is not set +CONFIG_BFIN_JTAG_COMM=m # CONFIG_SERIAL_NONSTANDARD is not set # diff --git a/arch/blackfin/configs/BF526-EZBRD_defconfig b/arch/blackfin/configs/BF526-EZBRD_defconfig index 992424ff3153..8e2b855b8db7 100644 --- a/arch/blackfin/configs/BF526-EZBRD_defconfig +++ b/arch/blackfin/configs/BF526-EZBRD_defconfig @@ -723,7 +723,7 @@ CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y # CONFIG_VT_HW_CONSOLE_BINDING is not set # CONFIG_DEVKMEM is not set -# CONFIG_BFIN_JTAG_COMM is not set +CONFIG_BFIN_JTAG_COMM=m # CONFIG_SERIAL_NONSTANDARD is not set # diff --git a/arch/blackfin/configs/BF527-EZKIT_defconfig b/arch/blackfin/configs/BF527-EZKIT_defconfig index 21e3c1af55ba..833128b39724 100644 --- a/arch/blackfin/configs/BF527-EZKIT_defconfig +++ b/arch/blackfin/configs/BF527-EZKIT_defconfig @@ -767,7 +767,7 @@ CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y # CONFIG_VT_HW_CONSOLE_BINDING is not set # CONFIG_DEVKMEM is not set -# CONFIG_BFIN_JTAG_COMM is not set +CONFIG_BFIN_JTAG_COMM=m # CONFIG_SERIAL_NONSTANDARD is not set # diff --git a/arch/blackfin/configs/BF533-EZKIT_defconfig b/arch/blackfin/configs/BF533-EZKIT_defconfig index 0bdf20a1af61..334c94b51c40 100644 --- a/arch/blackfin/configs/BF533-EZKIT_defconfig +++ b/arch/blackfin/configs/BF533-EZKIT_defconfig @@ -672,7 +672,7 @@ CONFIG_BFIN_DMA_INTERFACE=m CONFIG_SIMPLE_GPIO=m # CONFIG_VT is not set # CONFIG_DEVKMEM is not set -# CONFIG_BFIN_JTAG_COMM is not set +CONFIG_BFIN_JTAG_COMM=m # CONFIG_SERIAL_NONSTANDARD is not set # diff --git a/arch/blackfin/configs/BF533-STAMP_defconfig b/arch/blackfin/configs/BF533-STAMP_defconfig index 2f747d6e97e2..9d733436e300 100644 --- a/arch/blackfin/configs/BF533-STAMP_defconfig +++ b/arch/blackfin/configs/BF533-STAMP_defconfig @@ -679,7 +679,7 @@ CONFIG_BFIN_DMA_INTERFACE=m CONFIG_SIMPLE_GPIO=m # CONFIG_VT is not set # CONFIG_DEVKMEM is not set -# CONFIG_BFIN_JTAG_COMM is not set +CONFIG_BFIN_JTAG_COMM=m # CONFIG_SERIAL_NONSTANDARD is not set # diff --git a/arch/blackfin/configs/BF537-STAMP_defconfig b/arch/blackfin/configs/BF537-STAMP_defconfig index 8b0a81294e65..4fb4108d3103 100644 --- a/arch/blackfin/configs/BF537-STAMP_defconfig +++ b/arch/blackfin/configs/BF537-STAMP_defconfig @@ -722,7 +722,7 @@ CONFIG_BFIN_DMA_INTERFACE=m CONFIG_SIMPLE_GPIO=m # CONFIG_VT is not set # CONFIG_DEVKMEM is not set -# CONFIG_BFIN_JTAG_COMM is not set +CONFIG_BFIN_JTAG_COMM=m # CONFIG_SERIAL_NONSTANDARD is not set # diff --git a/arch/blackfin/configs/BF538-EZKIT_defconfig b/arch/blackfin/configs/BF538-EZKIT_defconfig index a1f766bf7d9b..cb32f5624a1b 100644 --- a/arch/blackfin/configs/BF538-EZKIT_defconfig +++ b/arch/blackfin/configs/BF538-EZKIT_defconfig @@ -726,7 +726,7 @@ CONFIG_BFIN_DMA_INTERFACE=m CONFIG_SIMPLE_GPIO=m # CONFIG_VT is not set # CONFIG_DEVKMEM is not set -# CONFIG_BFIN_JTAG_COMM is not set +CONFIG_BFIN_JTAG_COMM=m # CONFIG_SERIAL_NONSTANDARD is not set # diff --git a/arch/blackfin/configs/BF548-EZKIT_defconfig b/arch/blackfin/configs/BF548-EZKIT_defconfig index cd2da6b7692c..0f8697618aa5 100644 --- a/arch/blackfin/configs/BF548-EZKIT_defconfig +++ b/arch/blackfin/configs/BF548-EZKIT_defconfig @@ -856,7 +856,7 @@ CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y # CONFIG_VT_HW_CONSOLE_BINDING is not set # CONFIG_DEVKMEM is not set -# CONFIG_BFIN_JTAG_COMM is not set +CONFIG_BFIN_JTAG_COMM=m # CONFIG_SERIAL_NONSTANDARD is not set # diff --git a/arch/blackfin/configs/BF561-EZKIT_defconfig b/arch/blackfin/configs/BF561-EZKIT_defconfig index b398ca202dbd..042c7adfccfa 100644 --- a/arch/blackfin/configs/BF561-EZKIT_defconfig +++ b/arch/blackfin/configs/BF561-EZKIT_defconfig @@ -709,7 +709,7 @@ CONFIG_BFIN_DMA_INTERFACE=m CONFIG_SIMPLE_GPIO=m # CONFIG_VT is not set # CONFIG_DEVKMEM is not set -# CONFIG_BFIN_JTAG_COMM is not set +CONFIG_BFIN_JTAG_COMM=m # CONFIG_SERIAL_NONSTANDARD is not set # From 65319628db2c7a630daadfeec4d371aaca788482 Mon Sep 17 00:00:00 2001 From: Graf Yang Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 103/111] Blackfin arch: add platform device bfin_mii-bus and KSZ8893M switch driver platform resources to board files Signed-off-by: Graf Yang Signed-off-by: Bryan Wu --- arch/blackfin/mach-bf518/boards/ezbrd.c | 51 +++++++++++++++++++ arch/blackfin/mach-bf527/boards/cm_bf527.c | 6 +++ arch/blackfin/mach-bf527/boards/ezbrd.c | 6 +++ arch/blackfin/mach-bf527/boards/ezkit.c | 6 +++ arch/blackfin/mach-bf537/boards/cm_bf537.c | 6 +++ .../mach-bf537/boards/generic_board.c | 6 +++ arch/blackfin/mach-bf537/boards/minotaur.c | 6 +++ arch/blackfin/mach-bf537/boards/pnav10.c | 6 +++ arch/blackfin/mach-bf537/boards/stamp.c | 6 +++ arch/blackfin/mach-bf537/boards/tcm_bf537.c | 6 +++ 10 files changed, 105 insertions(+) diff --git a/arch/blackfin/mach-bf518/boards/ezbrd.c b/arch/blackfin/mach-bf518/boards/ezbrd.c index b23108bcbf59..0e175342112e 100644 --- a/arch/blackfin/mach-bf518/boards/ezbrd.c +++ b/arch/blackfin/mach-bf518/boards/ezbrd.c @@ -46,6 +46,7 @@ #include #include #include +#include /* * Name the Board for the /proc/cpuinfo @@ -104,8 +105,31 @@ static struct platform_device rtc_device = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) +static struct platform_device bfin_mii_bus = { + .name = "bfin_mii_bus", +}; + static struct platform_device bfin_mac_device = { .name = "bfin_mac", + .dev.platform_data = &bfin_mii_bus, +}; +#endif + +#if defined(CONFIG_NET_DSA_KSZ8893M) || defined(CONFIG_NET_DSA_KSZ8893M_MODULE) +static struct dsa_platform_data ksz8893m_switch_data = { + .mii_bus = &bfin_mii_bus.dev, + .netdev = &bfin_mac_device.dev, + .port_names[0] = NULL, + .port_names[1] = "eth%d", + .port_names[2] = "eth%d", + .port_names[3] = "cpu", +}; + +static struct platform_device ksz8893m_switch_device = { + .name = "dsa", + .id = 0, + .num_resources = 0, + .dev.platform_data = &ksz8893m_switch_data, }; #endif @@ -147,6 +171,15 @@ static struct bfin5xx_spi_chip spi_adc_chip_info = { }; #endif +#if defined(CONFIG_NET_DSA_KSZ8893M) \ + || defined(CONFIG_NET_DSA_KSZ8893M_MODULE) +/* SPI SWITCH CHIP */ +static struct bfin5xx_spi_chip spi_switch_info = { + .enable_dma = 0, + .bits_per_word = 8, +}; +#endif + #if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE) static struct bfin5xx_spi_chip spi_mmc_chip_info = { .enable_dma = 1, @@ -226,6 +259,19 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = { }, #endif +#if defined(CONFIG_NET_DSA_KSZ8893M) \ + || defined(CONFIG_NET_DSA_KSZ8893M_MODULE) + { + .modalias = "ksz8893m", + .max_speed_hz = 5000000, + .bus_num = 0, + .chip_select = 1, + .platform_data = NULL, + .controller_data = &spi_switch_info, + .mode = SPI_MODE_3, + }, +#endif + #if defined(CONFIG_SPI_MMC) || defined(CONFIG_SPI_MMC_MODULE) { .modalias = "spi_mmc_dummy", @@ -582,9 +628,14 @@ static struct platform_device *stamp_devices[] __initdata = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) + &bfin_mii_bus, &bfin_mac_device, #endif +#if defined(CONFIG_NET_DSA_KSZ8893M) || defined(CONFIG_NET_DSA_KSZ8893M_MODULE) + &ksz8893m_switch_device, +#endif + #if defined(CONFIG_SPI_BFIN) || defined(CONFIG_SPI_BFIN_MODULE) &bfin_spi0_device, &bfin_spi1_device, diff --git a/arch/blackfin/mach-bf527/boards/cm_bf527.c b/arch/blackfin/mach-bf527/boards/cm_bf527.c index 98ab8bc28304..856c097b5317 100644 --- a/arch/blackfin/mach-bf527/boards/cm_bf527.c +++ b/arch/blackfin/mach-bf527/boards/cm_bf527.c @@ -403,8 +403,13 @@ static struct platform_device isp1362_hcd_device = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) +static struct platform_device bfin_mii_bus = { + .name = "bfin_mii_bus", +}; + static struct platform_device bfin_mac_device = { .name = "bfin_mac", + .dev.platform_data = &bfin_mii_bus, }; #endif @@ -918,6 +923,7 @@ static struct platform_device *stamp_devices[] __initdata = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) + &bfin_mii_bus, &bfin_mac_device, #endif diff --git a/arch/blackfin/mach-bf527/boards/ezbrd.c b/arch/blackfin/mach-bf527/boards/ezbrd.c index d0f29870f1a4..83606fcdde27 100644 --- a/arch/blackfin/mach-bf527/boards/ezbrd.c +++ b/arch/blackfin/mach-bf527/boards/ezbrd.c @@ -208,8 +208,13 @@ static struct platform_device rtc_device = { #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) +static struct platform_device bfin_mii_bus = { + .name = "bfin_mii_bus", +}; + static struct platform_device bfin_mac_device = { .name = "bfin_mac", + .dev.platform_data = &bfin_mii_bus, }; #endif @@ -718,6 +723,7 @@ static struct platform_device *stamp_devices[] __initdata = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) + &bfin_mii_bus, &bfin_mac_device, #endif diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c index 1f7a249d6926..d0864111ef59 100644 --- a/arch/blackfin/mach-bf527/boards/ezkit.c +++ b/arch/blackfin/mach-bf527/boards/ezkit.c @@ -425,8 +425,13 @@ static struct platform_device isp1362_hcd_device = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) +static struct platform_device bfin_mii_bus = { + .name = "bfin_mii_bus", +}; + static struct platform_device bfin_mac_device = { .name = "bfin_mac", + .dev.platform_data = &bfin_mii_bus, }; #endif @@ -986,6 +991,7 @@ static struct platform_device *stamp_devices[] __initdata = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) + &bfin_mii_bus, &bfin_mac_device, #endif diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537.c b/arch/blackfin/mach-bf537/boards/cm_bf537.c index 6ac8e4d5bd38..9cd8fb2a30d3 100644 --- a/arch/blackfin/mach-bf537/boards/cm_bf537.c +++ b/arch/blackfin/mach-bf537/boards/cm_bf537.c @@ -479,8 +479,13 @@ static struct platform_device bfin_sport1_uart_device = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) +static struct platform_device bfin_mii_bus = { + .name = "bfin_mii_bus", +}; + static struct platform_device bfin_mac_device = { .name = "bfin_mac", + .dev.platform_data = &bfin_mii_bus, }; #endif @@ -591,6 +596,7 @@ static struct platform_device *cm_bf537_devices[] __initdata = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) + &bfin_mii_bus, &bfin_mac_device, #endif diff --git a/arch/blackfin/mach-bf537/boards/generic_board.c b/arch/blackfin/mach-bf537/boards/generic_board.c index fb0368ec2aff..da710fdc4569 100644 --- a/arch/blackfin/mach-bf537/boards/generic_board.c +++ b/arch/blackfin/mach-bf537/boards/generic_board.c @@ -262,8 +262,13 @@ static struct platform_device isp1362_hcd_device = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) +static struct platform_device bfin_mii_bus = { + .name = "bfin_mii_bus", +}; + static struct platform_device bfin_mac_device = { .name = "bfin_mac", + .dev.platform_data = &bfin_mii_bus, }; #endif @@ -662,6 +667,7 @@ static struct platform_device *stamp_devices[] __initdata = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) + &bfin_mii_bus, &bfin_mac_device, #endif diff --git a/arch/blackfin/mach-bf537/boards/minotaur.c b/arch/blackfin/mach-bf537/boards/minotaur.c index 8f36d260aee2..db7d3a385e4b 100644 --- a/arch/blackfin/mach-bf537/boards/minotaur.c +++ b/arch/blackfin/mach-bf537/boards/minotaur.c @@ -61,8 +61,13 @@ static struct platform_device rtc_device = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) +static struct platform_device bfin_mii_bus = { + .name = "bfin_mii_bus", +}; + static struct platform_device bfin_mac_device = { .name = "bfin_mac", + .dev.platform_data = &bfin_mii_bus, }; #endif @@ -324,6 +329,7 @@ static struct platform_device *minotaur_devices[] __initdata = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) + &bfin_mii_bus, &bfin_mac_device, #endif diff --git a/arch/blackfin/mach-bf537/boards/pnav10.c b/arch/blackfin/mach-bf537/boards/pnav10.c index 8835c58cfaec..590eb3a139b7 100644 --- a/arch/blackfin/mach-bf537/boards/pnav10.c +++ b/arch/blackfin/mach-bf537/boards/pnav10.c @@ -198,8 +198,13 @@ static struct platform_device isp1362_hcd_device = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) +static struct platform_device bfin_mii_bus = { + .name = "bfin_mii_bus", +}; + static struct platform_device bfin_mac_device = { .name = "bfin_mac", + .dev.platform_data = &bfin_mii_bus, }; #endif @@ -529,6 +534,7 @@ static struct platform_device *stamp_devices[] __initdata = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) + &bfin_mii_bus, &bfin_mac_device, #endif diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c index 2300ed4ec601..cd04c5e44878 100644 --- a/arch/blackfin/mach-bf537/boards/stamp.c +++ b/arch/blackfin/mach-bf537/boards/stamp.c @@ -321,8 +321,13 @@ static struct platform_device isp1362_hcd_device = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) +static struct platform_device bfin_mii_bus = { + .name = "bfin_mii_bus", +}; + static struct platform_device bfin_mac_device = { .name = "bfin_mac", + .dev.platform_data = &bfin_mii_bus, }; #endif @@ -1215,6 +1220,7 @@ static struct platform_device *stamp_devices[] __initdata = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) + &bfin_mii_bus, &bfin_mac_device, #endif diff --git a/arch/blackfin/mach-bf537/boards/tcm_bf537.c b/arch/blackfin/mach-bf537/boards/tcm_bf537.c index 2e60bbad73ee..3f4f203a06ec 100644 --- a/arch/blackfin/mach-bf537/boards/tcm_bf537.c +++ b/arch/blackfin/mach-bf537/boards/tcm_bf537.c @@ -481,8 +481,13 @@ static struct platform_device bfin_sport1_uart_device = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) +static struct platform_device bfin_mii_bus = { + .name = "bfin_mii_bus", +}; + static struct platform_device bfin_mac_device = { .name = "bfin_mac", + .dev.platform_data = &bfin_mii_bus, }; #endif @@ -593,6 +598,7 @@ static struct platform_device *cm_bf537_devices[] __initdata = { #endif #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE) + &bfin_mii_bus, &bfin_mac_device, #endif From bf324cb81a2f7da357eba00b6b1ef1cf38c264b8 Mon Sep 17 00:00:00 2001 From: Bernd Schmidt Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 104/111] Blackfin arch: fix bug - traps test case 19 for exception 0x2d fails Enable null pointer checking for ICPLBs. The code was there but for some reason I had commented it out at some stage during development. Should restrict this to 1K since atomic ops start there. Signed-off-by: Bernd Schmidt Signed-off-by: Bryan Wu --- arch/blackfin/kernel/cplb-mpu/cplbinit.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/blackfin/kernel/cplb-mpu/cplbinit.c b/arch/blackfin/kernel/cplb-mpu/cplbinit.c index bdb958486e76..3e329a6ce041 100644 --- a/arch/blackfin/kernel/cplb-mpu/cplbinit.c +++ b/arch/blackfin/kernel/cplb-mpu/cplbinit.c @@ -63,10 +63,8 @@ void __init generate_cplb_tables_cpu(unsigned int cpu) dcplb_tbl[cpu][i_d].addr = 0; dcplb_tbl[cpu][i_d++].data = SDRAM_OOPS | PAGE_SIZE_1KB; -#if 0 icplb_tbl[cpu][i_i].addr = 0; - icplb_tbl[cpu][i_i++].data = i_cache | CPLB_USER_RD | PAGE_SIZE_4KB; -#endif + icplb_tbl[cpu][i_i++].data = i_cache | CPLB_USER_RD | PAGE_SIZE_1KB; /* Cover kernel memory with 4M pages. */ addr = 0; From d04dfc4c0e6056350175edc36b900a69703e9467 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 105/111] Blackfin arch: cplb mananger: use a do...while loop rather than a for loop use a do...while loop rather than a for loop to get slightly better optimization and to avoid gcc "may be used uninitialized" warnings ... we know that the [id]cplb_nr_bounds variables will never be 0, so this is OK Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/kernel/cplb-nompu/cplbmgr.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/arch/blackfin/kernel/cplb-nompu/cplbmgr.c b/arch/blackfin/kernel/cplb-nompu/cplbmgr.c index 376249ab2694..8cbb47c7b663 100644 --- a/arch/blackfin/kernel/cplb-nompu/cplbmgr.c +++ b/arch/blackfin/kernel/cplb-nompu/cplbmgr.c @@ -163,12 +163,14 @@ MGR_ATTR static int icplb_miss(int cpu) nr_icplb_supv_miss[cpu]++; base = 0; - for (idx = 0; idx < icplb_nr_bounds; idx++) { + idx = 0; + do { eaddr = icplb_bounds[idx].eaddr; if (addr < eaddr) break; base = eaddr; - } + } while (++idx < icplb_nr_bounds); + if (unlikely(idx == icplb_nr_bounds)) return CPLB_NO_ADDR_MATCH; @@ -208,12 +210,14 @@ MGR_ATTR static int dcplb_miss(int cpu) nr_dcplb_supv_miss[cpu]++; base = 0; - for (idx = 0; idx < dcplb_nr_bounds; idx++) { + idx = 0; + do { eaddr = dcplb_bounds[idx].eaddr; if (addr < eaddr) break; base = eaddr; - } + } while (++idx < dcplb_nr_bounds); + if (unlikely(idx == dcplb_nr_bounds)) return CPLB_NO_ADDR_MATCH; From af4c7d4b4eddc297bbb516abdd6154bffc8e05e5 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 106/111] Blackfin arch: define bfin_memmap as static since it is only used here Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu --- arch/blackfin/kernel/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index 86feb4274218..39bdedcb9233 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -60,7 +60,7 @@ void __initdata *init_retx, *init_saved_retx, *init_saved_seqstat, #define BFIN_MEMMAP_MAX 128 /* number of entries in bfin_memmap */ #define BFIN_MEMMAP_RAM 1 #define BFIN_MEMMAP_RESERVED 2 -struct bfin_memmap { +static struct bfin_memmap { int nr_map; struct bfin_memmap_entry { unsigned long long addr; /* start of memory segment */ From dfd700baf2ddab395cc059ce9f294306bf56a735 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 107/111] Blackfin arch: Update CM-BF527 kernel config Signed-off-by: Michael Hennerich Signed-off-by: Bryan Wu --- arch/blackfin/configs/CM-BF527_defconfig | 449 ++++++++++++++++------- 1 file changed, 323 insertions(+), 126 deletions(-) diff --git a/arch/blackfin/configs/CM-BF527_defconfig b/arch/blackfin/configs/CM-BF527_defconfig index 95146948166f..865ed85a5760 100644 --- a/arch/blackfin/configs/CM-BF527_defconfig +++ b/arch/blackfin/configs/CM-BF527_defconfig @@ -1,7 +1,6 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.24.7 -# Fri Jul 18 18:00:41 2008 +# Linux kernel version: 2.6.28 # # CONFIG_MMU is not set # CONFIG_FPU is not set @@ -9,7 +8,6 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set CONFIG_BLACKFIN=y CONFIG_ZONE_DMA=y -CONFIG_SEMAPHORE_SLEEPERS=y CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_HARDIRQS=y @@ -32,18 +30,16 @@ CONFIG_SYSVIPC_SYSCTL=y # CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set -# CONFIG_USER_NS is not set -# CONFIG_PID_NS is not set # CONFIG_AUDIT is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CGROUPS is not set -CONFIG_FAIR_GROUP_SCHED=y -CONFIG_FAIR_USER_SCHED=y -# CONFIG_FAIR_CGROUP_SCHED is not set -# CONFIG_SYSFS_DEPRECATED is not set +# CONFIG_GROUP_SCHED is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y # CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set @@ -52,26 +48,35 @@ CONFIG_EMBEDDED=y CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y # CONFIG_ELF_CORE is not set +CONFIG_COMPAT_BRK=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y CONFIG_EVENTFD=y +CONFIG_AIO=y CONFIG_VM_EVENT_COUNTERS=y CONFIG_SLAB=y # CONFIG_SLUB is not set # CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y CONFIG_TINY_SHMEM=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 @@ -82,6 +87,7 @@ CONFIG_BLOCK=y # CONFIG_BLK_DEV_IO_TRACE is not set # CONFIG_LSF is not set # CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set # # IO Schedulers @@ -95,9 +101,11 @@ CONFIG_IOSCHED_CFQ=y CONFIG_DEFAULT_CFQ=y # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_CLASSIC_RCU=y # CONFIG_PREEMPT_NONE is not set CONFIG_PREEMPT_VOLUNTARY=y # CONFIG_PREEMPT is not set +# CONFIG_FREEZER is not set # # Blackfin Processor Options @@ -106,6 +114,10 @@ CONFIG_PREEMPT_VOLUNTARY=y # # Processor and Board Settings # +# CONFIG_BF512 is not set +# CONFIG_BF514 is not set +# CONFIG_BF516 is not set +# CONFIG_BF518 is not set # CONFIG_BF522 is not set # CONFIG_BF523 is not set # CONFIG_BF524 is not set @@ -118,48 +130,32 @@ CONFIG_BF527=y # CONFIG_BF534 is not set # CONFIG_BF536 is not set # CONFIG_BF537 is not set +# CONFIG_BF538 is not set +# CONFIG_BF539 is not set # CONFIG_BF542 is not set +# CONFIG_BF542M is not set # CONFIG_BF544 is not set +# CONFIG_BF544M is not set # CONFIG_BF547 is not set +# CONFIG_BF547M is not set # CONFIG_BF548 is not set +# CONFIG_BF548M is not set # CONFIG_BF549 is not set +# CONFIG_BF549M is not set # CONFIG_BF561 is not set +CONFIG_BF_REV_MIN=0 +CONFIG_BF_REV_MAX=2 # CONFIG_BF_REV_0_0 is not set CONFIG_BF_REV_0_1=y # CONFIG_BF_REV_0_2 is not set # CONFIG_BF_REV_0_3 is not set # CONFIG_BF_REV_0_4 is not set # CONFIG_BF_REV_0_5 is not set +# CONFIG_BF_REV_0_6 is not set # CONFIG_BF_REV_ANY is not set # CONFIG_BF_REV_NONE is not set CONFIG_BF52x=y CONFIG_MEM_MT48LC16M16A2TG_75=y -# CONFIG_BFIN527_EZKIT is not set -CONFIG_BFIN527_BLUETECHNIX_CM=y - -# -# BF527 Specific Configuration -# - -# -# Alternative Multiplexing Scheme -# -# CONFIG_BF527_SPORT0_PORTF is not set -CONFIG_BF527_SPORT0_PORTG=y -CONFIG_BF527_SPORT0_TSCLK_PG10=y -# CONFIG_BF527_SPORT0_TSCLK_PG14 is not set -CONFIG_BF527_UART1_PORTF=y -# CONFIG_BF527_UART1_PORTG is not set -# CONFIG_BF527_NAND_D_PORTF is not set -CONFIG_BF527_NAND_D_PORTH=y - -# -# Interrupt Priority Assignment -# - -# -# Priority -# CONFIG_IRQ_PLL_WAKEUP=7 CONFIG_IRQ_DMA0_ERROR=7 CONFIG_IRQ_DMAR0_BLK=7 @@ -179,7 +175,6 @@ CONFIG_IRQ_SPORT0_TX=9 CONFIG_IRQ_SPORT1_RX=9 CONFIG_IRQ_SPORT1_TX=9 CONFIG_IRQ_TWI=10 -CONFIG_IRQ_SPI=10 CONFIG_IRQ_UART0_RX=10 CONFIG_IRQ_UART0_TX=10 CONFIG_IRQ_UART1_RX=10 @@ -205,6 +200,34 @@ CONFIG_IRQ_MEM_DMA1=13 CONFIG_IRQ_WATCH=13 CONFIG_IRQ_PORTF_INTA=13 CONFIG_IRQ_PORTF_INTB=13 +# CONFIG_BFIN527_EZKIT is not set +CONFIG_BFIN527_BLUETECHNIX_CM=y +# CONFIG_BFIN526_EZBRD is not set + +# +# BF527 Specific Configuration +# + +# +# Alternative Multiplexing Scheme +# +# CONFIG_BF527_SPORT0_PORTF is not set +CONFIG_BF527_SPORT0_PORTG=y +CONFIG_BF527_SPORT0_TSCLK_PG10=y +# CONFIG_BF527_SPORT0_TSCLK_PG14 is not set +CONFIG_BF527_UART1_PORTF=y +# CONFIG_BF527_UART1_PORTG is not set +# CONFIG_BF527_NAND_D_PORTF is not set +CONFIG_BF527_NAND_D_PORTH=y + +# +# Interrupt Priority Assignment +# + +# +# Priority +# +CONFIG_IRQ_SPI=10 CONFIG_IRQ_SPI_ERROR=7 CONFIG_IRQ_NFC_ERROR=7 CONFIG_IRQ_HDMA_ERROR=7 @@ -226,7 +249,6 @@ CONFIG_BOOT_LOAD=0x1000 # CONFIG_CLKIN_HZ=25000000 # CONFIG_BFIN_KERNEL_CLOCK is not set -CONFIG_MAX_MEM_SIZE=512 CONFIG_MAX_VCO_HZ=600000000 CONFIG_MIN_VCO_HZ=50000000 CONFIG_MAX_SCLK_HZ=133333333 @@ -240,10 +262,10 @@ CONFIG_HZ_250=y # CONFIG_HZ_300 is not set # CONFIG_HZ_1000 is not set CONFIG_HZ=250 +# CONFIG_SCHED_HRTICK is not set CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y # CONFIG_CYCLES_CLOCKSOURCE is not set -# CONFIG_TICK_ONESHOT is not set # CONFIG_NO_HZ is not set # CONFIG_HIGH_RES_TIMERS is not set CONFIG_GENERIC_CLOCKEVENTS_BUILD=y @@ -277,6 +299,12 @@ CONFIG_ACCESS_OK_L1=y CONFIG_CACHELINE_ALIGNED_L1=y # CONFIG_SYSCALL_TAB_L1 is not set # CONFIG_CPLB_SWITCH_TAB_L1 is not set +CONFIG_APP_STACK_L1=y + +# +# Speed Optimizations +# +CONFIG_BFIN_INS_LOWOVERHEAD=y CONFIG_RAMKERNEL=y # CONFIG_ROMKERNEL is not set CONFIG_SELECT_MEMORY_MODEL=y @@ -285,10 +313,10 @@ CONFIG_FLATMEM_MANUAL=y # CONFIG_SPARSEMEM_MANUAL is not set CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y -# CONFIG_SPARSEMEM_STATIC is not set -# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set +CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_RESOURCES_64BIT is not set +# CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=1 CONFIG_VIRT_TO_BUS=y CONFIG_BFIN_GPTIMERS=y @@ -334,7 +362,6 @@ CONFIG_BANK_3=0xFFC0 # # Bus options (PCI, PCMCIA, EISA, MCA, ISA) # -# CONFIG_PCI is not set # CONFIG_ARCH_SUPPORTS_MSI is not set # CONFIG_PCCARD is not set @@ -345,25 +372,20 @@ CONFIG_BINFMT_ELF_FDPIC=y CONFIG_BINFMT_FLAT=y CONFIG_BINFMT_ZFLAT=y # CONFIG_BINFMT_SHARED_FLAT is not set +# CONFIG_HAVE_AOUT is not set # CONFIG_BINFMT_MISC is not set # # Power management options # # CONFIG_PM is not set -CONFIG_SUSPEND_UP_POSSIBLE=y -# CONFIG_PM_BFIN_SLEEP_DEEPER is not set -# CONFIG_PM_BFIN_SLEEP is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y # CONFIG_PM_WAKEUP_BY_GPIO is not set # # CPU Frequency scaling # # CONFIG_CPU_FREQ is not set - -# -# Networking -# CONFIG_NET=y # @@ -376,6 +398,7 @@ CONFIG_XFRM=y # CONFIG_XFRM_USER is not set # CONFIG_XFRM_SUB_POLICY is not set # CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set # CONFIG_NET_KEY is not set CONFIG_INET=y # CONFIG_IP_MULTICAST is not set @@ -405,8 +428,6 @@ CONFIG_TCP_CONG_CUBIC=y CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_TCP_MD5SIG is not set # CONFIG_IPV6 is not set -# CONFIG_INET6_XFRM_TUNNEL is not set -# CONFIG_INET6_TUNNEL is not set # CONFIG_NETLABEL is not set # CONFIG_NETWORK_SECMARK is not set # CONFIG_NETFILTER is not set @@ -415,6 +436,7 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # 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 @@ -431,14 +453,14 @@ CONFIG_DEFAULT_TCP_CONG="cubic" # # 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 - -# -# Wireless -# +# CONFIG_PHONET is not set +CONFIG_WIRELESS=y # CONFIG_CFG80211 is not set +CONFIG_WIRELESS_OLD_REGULATORY=y # CONFIG_WIRELESS_EXT is not set # CONFIG_MAC80211 is not set # CONFIG_IEEE80211 is not set @@ -456,6 +478,8 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set # CONFIG_SYS_HYPERVISOR is not set # CONFIG_CONNECTOR is not set CONFIG_MTD=y @@ -464,6 +488,7 @@ CONFIG_MTD=y CONFIG_MTD_PARTITIONS=y # CONFIG_MTD_REDBOOT_PARTS is not set # CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set # # User Modules And Translation Layers @@ -507,6 +532,7 @@ CONFIG_MTD_ROM=m # CONFIG_MTD_COMPLEX_MAPPINGS=y # CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_GPIO_ADDR is not set # CONFIG_MTD_UCLINUX is not set # CONFIG_MTD_PLATRAM is not set @@ -542,10 +568,12 @@ CONFIG_BLK_DEV=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +# CONFIG_BLK_DEV_XIP is not set # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set +# CONFIG_BLK_DEV_HD is not set # CONFIG_MISC_DEVICES is not set +CONFIG_HAVE_IDE=y # CONFIG_IDE is not set # @@ -558,7 +586,6 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 # CONFIG_ATA is not set # CONFIG_MD is not set CONFIG_NETDEVICES=y -# CONFIG_NETDEVICES_MULTIQUEUE is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_MACVLAN is not set @@ -579,6 +606,7 @@ CONFIG_PHYLIB=y # 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_FIXED_PHY is not set # CONFIG_MDIO_BITBANG is not set CONFIG_NET_ETHERNET=y @@ -591,11 +619,14 @@ CONFIG_BFIN_MAC_RMII=y # CONFIG_SMC91X is not set # CONFIG_SMSC911X is not set # CONFIG_DM9000 is not set +# CONFIG_ENC28J60 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_B44 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_NETDEV_1000 is not set # CONFIG_NETDEV_10000 is not set @@ -604,6 +635,7 @@ CONFIG_BFIN_MAC_RMII=y # # CONFIG_WLAN_PRE80211 is not set # CONFIG_WLAN_80211 is not set +# CONFIG_IWLWIFI_LEDS is not set # # USB Network Adapters @@ -616,7 +648,6 @@ CONFIG_BFIN_MAC_RMII=y # CONFIG_WAN is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set -# CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set @@ -642,14 +673,15 @@ CONFIG_BFIN_MAC_RMII=y # CONFIG_BF5xx_PPIFCD is not set # CONFIG_BFIN_SIMPLE_TIMER is not set # CONFIG_BF5xx_PPI is not set -CONFIG_BFIN_OTP=y -# CONFIG_BFIN_OTP_WRITE_ENABLE is not set +# CONFIG_BF5xx_EPPI is not set # CONFIG_BFIN_SPORT is not set # CONFIG_BFIN_TIMER_LATENCY is not set # CONFIG_TWI_LCD is not set +CONFIG_BFIN_DMA_INTERFACE=m CONFIG_SIMPLE_GPIO=m # CONFIG_VT is not set # CONFIG_DEVKMEM is not set +# CONFIG_BFIN_JTAG_COMM is not set # CONFIG_SERIAL_NONSTANDARD is not set # @@ -673,6 +705,8 @@ CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_BFIN_SPORT is not set CONFIG_UNIX98_PTYS=y # CONFIG_LEGACY_PTYS is not set +CONFIG_BFIN_OTP=y +# CONFIG_BFIN_OTP_WRITE_ENABLE is not set # # CAN, the car bus and industrial fieldbus @@ -680,44 +714,49 @@ CONFIG_UNIX98_PTYS=y # CONFIG_CAN4LINUX is not set # CONFIG_IPMI_HANDLER is not set # CONFIG_HW_RANDOM is not set -# CONFIG_GEN_RTC 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_CHARDEV=m - -# -# I2C Algorithms -# -# CONFIG_I2C_ALGOBIT is not set -# CONFIG_I2C_ALGOPCF is not set -# CONFIG_I2C_ALGOPCA is not set +CONFIG_I2C_HELPER_AUTO=y # # I2C Hardware Bus support # + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# CONFIG_I2C_BLACKFIN_TWI=m CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=100 # CONFIG_I2C_GPIO is not set # CONFIG_I2C_OCORES is not set -# CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_TAOS_EVM is not set -# CONFIG_I2C_STUB 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_DS1337 is not set -# CONFIG_SENSORS_DS1374 is not set # CONFIG_DS1682 is not set +# CONFIG_AT24 is not set # CONFIG_SENSORS_AD5252 is not set -# CONFIG_EEPROM_LEGACY is not set +# CONFIG_SENSORS_EEPROM is not set # CONFIG_SENSORS_PCF8574 is not set -# CONFIG_SENSORS_PCF8575 is not set +# CONFIG_PCF8575 is not set # CONFIG_SENSORS_PCA9539 is not set # CONFIG_SENSORS_PCF8591 is not set # CONFIG_SENSORS_MAX6875 is not set @@ -726,37 +765,41 @@ CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=100 # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set # CONFIG_I2C_DEBUG_CHIP is not set - -# -# SPI support -# CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set CONFIG_SPI_MASTER=y # # SPI Master Controller Drivers # CONFIG_SPI_BFIN=y +# CONFIG_SPI_BFIN_LOCK is not set # CONFIG_SPI_BITBANG is not set # # SPI Protocol Masters # -# CONFIG_EEPROM_AT25 is not set +# CONFIG_SPI_AT25 is not set # CONFIG_SPI_SPIDEV is not set # CONFIG_SPI_TLE62X0 is not set +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +# CONFIG_GPIOLIB is not set # CONFIG_W1 is not set # CONFIG_POWER_SUPPLY is not set CONFIG_HWMON=y # CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_AD7414 is not set # CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADCXX is not set # CONFIG_SENSORS_ADM1021 is not set # CONFIG_SENSORS_ADM1025 is not set # CONFIG_SENSORS_ADM1026 is not set # CONFIG_SENSORS_ADM1029 is not set # CONFIG_SENSORS_ADM1031 is not set # CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7462 is not set # CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7473 is not set # CONFIG_SENSORS_ATXP1 is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_F71805F is not set @@ -777,6 +820,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_LM90 is not set # CONFIG_SENSORS_LM92 is not set # CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_MAX1111 is not set # CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_MAX6650 is not set # CONFIG_SENSORS_PC87360 is not set @@ -785,6 +829,7 @@ CONFIG_HWMON=y # CONFIG_SENSORS_SMSC47M1 is not set # CONFIG_SENSORS_SMSC47M192 is not set # CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_ADS7828 is not set # CONFIG_SENSORS_THMC50 is not set # CONFIG_SENSORS_VT1211 is not set # CONFIG_SENSORS_W83781D is not set @@ -792,9 +837,12 @@ CONFIG_HWMON=y # CONFIG_SENSORS_W83792D is not set # CONFIG_SENSORS_W83793 is not set # CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set # CONFIG_SENSORS_W83627HF is not set # CONFIG_SENSORS_W83627EHF is not set # CONFIG_HWMON_DEBUG_CHIP is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set CONFIG_WATCHDOG=y # CONFIG_WATCHDOG_NOWAYOUT is not set @@ -809,22 +857,32 @@ CONFIG_BFIN_WDT=y # # CONFIG_USBPCWATCHDOG is not set -# -# Sonics Silicon Backplane -# -CONFIG_SSB_POSSIBLE=y -# 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_PMIC_DA903X is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_REGULATOR is not set # # Multimedia devices # + +# +# Multimedia core support +# # CONFIG_VIDEO_DEV is not set # CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# # CONFIG_DAB is not set # @@ -839,10 +897,6 @@ CONFIG_SSB_POSSIBLE=y # Display device support # # CONFIG_DISPLAY_SUPPORT is not set - -# -# Sound -# # CONFIG_SOUND is not set CONFIG_USB_SUPPORT=y CONFIG_USB_ARCH_HAS_HCD=y @@ -850,6 +904,7 @@ CONFIG_USB_ARCH_HAS_HCD=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 @@ -860,40 +915,48 @@ CONFIG_USB_DEVICE_CLASS=y # CONFIG_USB_OTG is not set # CONFIG_USB_OTG_WHITELIST is not set CONFIG_USB_OTG_BLACKLIST_HUB=y +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_ISP116X_HCD is not set -# CONFIG_USB_ISP1362_HCD is not set # CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set # 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=y CONFIG_USB_MUSB_SOC=y # -# Blackfin high speed USB support +# Blackfin high speed USB Support # CONFIG_USB_MUSB_HOST=y # CONFIG_USB_MUSB_PERIPHERAL is not set # CONFIG_USB_MUSB_OTG is not set CONFIG_USB_MUSB_HDRC_HCD=y CONFIG_MUSB_PIO_ONLY=y -CONFIG_USB_MUSB_LOGLEVEL=0 +CONFIG_MUSB_DMA_POLL=y +# CONFIG_USB_MUSB_DEBUG 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 enables SCSI, and 'SCSI disk support' +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; # # -# may also be needed; see USB_STORAGE Help for more information +# see USB_STORAGE Help for more information # # CONFIG_USB_LIBUSUAL is not set @@ -901,15 +964,10 @@ CONFIG_USB_MUSB_LOGLEVEL=0 # USB Imaging devices # # CONFIG_USB_MDC800 is not set -CONFIG_USB_MON=y # # USB port drivers # - -# -# USB Serial Converter support -# # CONFIG_USB_SERIAL is not set # @@ -918,7 +976,7 @@ CONFIG_USB_MON=y # CONFIG_USB_EMI62 is not set # CONFIG_USB_EMI26 is not set # CONFIG_USB_ADUTUX is not set -# CONFIG_USB_AUERSWALD 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 @@ -934,17 +992,13 @@ CONFIG_USB_MON=y # CONFIG_USB_LD is not set # CONFIG_USB_TRANCEVIBRATOR is not set # CONFIG_USB_IOWARRIOR is not set - -# -# USB DSL modem support -# - -# -# USB Gadget Support -# +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_VST is not set # CONFIG_USB_GADGET 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=y CONFIG_RTC_HCTOSYS=y @@ -973,51 +1027,59 @@ CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_DRV_PCF8563 is not set # CONFIG_RTC_DRV_PCF8583 is not set # CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set # # SPI RTC drivers # -# CONFIG_RTC_DRV_RS5C348 is not set +# 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 # # Platform RTC drivers # +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set # CONFIG_RTC_DRV_DS1553 is not set -# CONFIG_RTC_DRV_STK17TA8 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_BQ4802 is not set # CONFIG_RTC_DRV_V3020 is not set # # on-CPU RTC drivers # CONFIG_RTC_DRV_BFIN=y - -# -# Userspace I/O -# +# CONFIG_DMADEVICES is not set # CONFIG_UIO is not set +# CONFIG_STAGING is not set # # File systems # # CONFIG_EXT2_FS is not set # CONFIG_EXT3_FS is not set -# CONFIG_EXT4DEV_FS is not set +# CONFIG_EXT4_FS is not set # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y # CONFIG_XFS_FS is not set -# CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set +# CONFIG_DNOTIFY is not set CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set -# CONFIG_DNOTIFY is not set # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set # CONFIG_FUSE_FS is not set @@ -1059,8 +1121,11 @@ CONFIG_SYSFS=y # CONFIG_JFFS2_FS is not set # CONFIG_CRAMFS 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 @@ -1068,13 +1133,12 @@ CONFIG_NFS_FS=m CONFIG_NFS_V3=y # CONFIG_NFS_V3_ACL is not set # CONFIG_NFS_V4 is not set -# CONFIG_NFS_DIRECTIO is not set # CONFIG_NFSD is not set CONFIG_LOCKD=m CONFIG_LOCKD_V4=y CONFIG_NFS_COMMON=y CONFIG_SUNRPC=m -# CONFIG_SUNRPC_BIND34 is not set +# CONFIG_SUNRPC_REGISTER_V4 is not set # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set CONFIG_SMB_FS=m @@ -1130,7 +1194,6 @@ CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_NLS_KOI8_U is not set # CONFIG_NLS_UTF8 is not set # CONFIG_DLM is not set -# CONFIG_INSTRUMENTATION is not set # # Kernel hacking @@ -1138,14 +1201,61 @@ CONFIG_NLS_DEFAULT="iso8859-1" # 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_UNUSED_SYMBOLS is not set CONFIG_DEBUG_FS=y # CONFIG_HEADERS_CHECK is not set -# CONFIG_DEBUG_KERNEL 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_SCHED_DEBUG is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_FRAME_POINTER is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set + +# +# Tracers +# +# CONFIG_SCHED_TRACER is not set +# CONFIG_CONTEXT_SWITCH_TRACER is not set +# CONFIG_BOOT_TRACER is not set +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set # CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_DEBUG_STACKOVERFLOW is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_KGDB_TESTCASE is not set +CONFIG_DEBUG_VERBOSE=y CONFIG_DEBUG_MMRS=y +# CONFIG_DEBUG_HWERR is not set +# CONFIG_DEBUG_DOUBLEFAULT is not set CONFIG_DEBUG_HUNT_FOR_ZERO=y CONFIG_DEBUG_BFIN_HWTRACE_ON=y CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y @@ -1154,7 +1264,7 @@ CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_OFF=y CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION=0 # CONFIG_DEBUG_BFIN_HWTRACE_EXPAND is not set # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set -CONFIG_EARLY_PRINTK=y +# CONFIG_EARLY_PRINTK is not set # CONFIG_CPLB_INFO is not set CONFIG_ACCESS_CHECK=y @@ -1163,10 +1273,96 @@ CONFIG_ACCESS_CHECK=y # # CONFIG_KEYS is not set CONFIG_SECURITY=y +# CONFIG_SECURITYFS is not set # CONFIG_SECURITY_NETWORK is not set -# CONFIG_SECURITY_CAPABILITIES is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set # CONFIG_SECURITY_ROOTPLUG is not set -# CONFIG_CRYPTO is not set +CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR=0 +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# 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_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRYPTO_HW=y # # Library routines @@ -1174,6 +1370,7 @@ CONFIG_SECURITY=y CONFIG_BITREVERSE=y CONFIG_CRC_CCITT=m # 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 From 772c258fd056a77fd808385a1c551dcd141cf8a3 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 108/111] Blackfin arch: Add BF561 PPI POLS, POLC Masks Signed-off-by: Michael Hennerich Signed-off-by: Bryan Wu --- arch/blackfin/mach-bf561/include/mach/defBF561.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/blackfin/mach-bf561/include/mach/defBF561.h b/arch/blackfin/mach-bf561/include/mach/defBF561.h index d7c509759659..cf922295f4ce 100644 --- a/arch/blackfin/mach-bf561/include/mach/defBF561.h +++ b/arch/blackfin/mach-bf561/include/mach/defBF561.h @@ -1106,6 +1106,8 @@ #define DLEN_8 0x0 /* PPI Data Length mask for DLEN=8 */ #define DLEN(x) (((x-9) & 0x07) << 11) /* PPI Data Length (only works for x=10-->x=16) */ #define POL 0x0000C000 /* PPI Signal Polarities */ +#define POLC 0x4000 /* PPI Clock Polarity */ +#define POLS 0x8000 /* PPI Frame Sync Polarity */ /* PPI_STATUS Masks */ #define FLD 0x00000400 /* Field Indicator */ From 972de7d9292439c9429c301cf377fbf56b6e654e Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 109/111] Blackfin arch: Update Copyright information Signed-off-by: Michael Hennerich Signed-off-by: Bryan Wu --- arch/blackfin/kernel/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index 39bdedcb9233..e5c116230800 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -861,7 +861,7 @@ void __init setup_arch(char **cmdline_p) else if (_bfin_swrst & RESET_SOFTWARE) printk(KERN_NOTICE "Reset caused by Software reset\n"); - printk(KERN_INFO "Blackfin support (C) 2004-2008 Analog Devices, Inc.\n"); + printk(KERN_INFO "Blackfin support (C) 2004-2009 Analog Devices, Inc.\n"); if (bfin_compiled_revid() == 0xffff) printk(KERN_INFO "Compiled for ADSP-%s Rev any\n", CPU); else if (bfin_compiled_revid() == -1) From 4e653e04cc1c3553af539ffc81fb56d83d83c733 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 110/111] Blackfin arch: Fix udelay implementation Avoid possible overflow during 32*32->32 multiplies. Reported-by: Marco Reppenhagen Signed-off-by: Michael Hennerich Signed-off-by: Bryan Wu --- arch/blackfin/include/asm/delay.h | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/arch/blackfin/include/asm/delay.h b/arch/blackfin/include/asm/delay.h index 0889c3abb593..47f98c5067b5 100644 --- a/arch/blackfin/include/asm/delay.h +++ b/arch/blackfin/include/asm/delay.h @@ -47,16 +47,15 @@ static inline void __delay(unsigned long loops) #include /* needed for HZ */ /* - * Use only for very small delays ( < 1 msec). Should probably use a - * lookup table, really, as the multiplications take much too long with - * short delays. This is a "reasonable" implementation, though (and the - * first constant multiplications gets optimized away if the delay is - * a constant) + * close approximation borrowed from m68knommu to avoid 64-bit math */ + +#define HZSCALE (268435456 / (1000000/HZ)) + static inline void udelay(unsigned long usecs) { extern unsigned long loops_per_jiffy; - __delay(usecs * loops_per_jiffy / (1000000 / HZ)); + __delay((((usecs * HZSCALE) >> 11) * (loops_per_jiffy >> 11)) >> 6); } #endif From c8e674125e03c5f36ccfd61d83b933e6956074b0 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Wed, 4 Feb 2009 16:49:45 +0800 Subject: [PATCH 111/111] Blackfin arch: Remove outdated code The removed version with the loop registers saved on the stack was originally intended to workaround the missing toolchain support for LoopReg Clobbers. Since our toolchain now supports these there is no point in keeping this workaround. And since we don't touch LoopRegs anymore we're no longer subject for ANOMALY_05000312. Signed-off-by: Michael Hennerich Signed-off-by: Bryan Wu --- arch/blackfin/include/asm/delay.h | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/arch/blackfin/include/asm/delay.h b/arch/blackfin/include/asm/delay.h index 47f98c5067b5..c31f91cc1d5d 100644 --- a/arch/blackfin/include/asm/delay.h +++ b/arch/blackfin/include/asm/delay.h @@ -13,29 +13,7 @@ static inline void __delay(unsigned long loops) { - if (ANOMALY_05000312) { - /* Interrupted loads to loop registers -> bad */ - unsigned long tmp; - __asm__ __volatile__( - "[--SP] = LC0;" - "[--SP] = LT0;" - "[--SP] = LB0;" - "LSETUP (1f,1f) LC0 = %1;" - "1: NOP;" - /* We take advantage of the fact that LC0 is 0 at - * the end of the loop. Otherwise we'd need some - * NOPs after the CLI here. - */ - "CLI %0;" - "LB0 = [SP++];" - "LT0 = [SP++];" - "LC0 = [SP++];" - "STI %0;" - : "=d" (tmp) - : "a" (loops) - ); - } else - __asm__ __volatile__ ( +__asm__ __volatile__ ( "LSETUP(1f, 1f) LC0 = %0;" "1: NOP;" :