From bd33d12fba60dea3b8f944478c54ac3ba18d2c4d Mon Sep 17 00:00:00 2001 From: Harry Wei Date: Sat, 16 Jul 2011 16:45:13 +0800 Subject: debugfs: Fix a comment mistake The file is fs/debugfs/inode.c but the comment says it is file.c. This patch can fix this little mistake. Signed-off-by: Harry Wei Signed-off-by: Greg Kroah-Hartman --- fs/debugfs/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index e7a7a2f07324..f3a257d7a985 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -1,5 +1,5 @@ /* - * file.c - part of debugfs, a tiny little debug file system + * inode.c - part of debugfs, a tiny little debug file system * * Copyright (C) 2004 Greg Kroah-Hartman * Copyright (C) 2004 IBM Inc. -- cgit v1.2.3 From 86028619b9f653a30f5aa0d331fdedd899a1eea5 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 16 Aug 2011 18:42:22 +0200 Subject: docs/sysfs: Specify ABI documentation requirements Although it is expected nowadays that every new sysfs attribute is documented under Documentation/ABI, this is not yet mentioned in the kernel documentation. This patch adds a note in the sysfs documentation about that requirement. Signed-off-by: Bart Van Assche Cc: Andrew Morton Cc: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- Documentation/filesystems/sysfs.txt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt index 597f728e7b4e..07235caec22c 100644 --- a/Documentation/filesystems/sysfs.txt +++ b/Documentation/filesystems/sysfs.txt @@ -4,7 +4,7 @@ sysfs - _The_ filesystem for exporting kernel objects. Patrick Mochel Mike Murphy -Revised: 15 July 2010 +Revised: 16 August 2011 Original: 10 January 2003 @@ -370,3 +370,11 @@ int driver_create_file(struct device_driver *, const struct driver_attribute *); void driver_remove_file(struct device_driver *, const struct driver_attribute *); +Documentation +~~~~~~~~~~~~~ + +The sysfs directory structure and the attributes in each directory define an +ABI between the kernel and user space. As for any ABI, it is important that +this ABI is stable and properly documented. All new sysfs attributes must be +documented in Documentation/ABI. See also Documentation/ABI/README for more +information. -- cgit v1.2.3 From 7f9838fd01833ffb30177d964983076924344c9e Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Thu, 21 Jul 2011 19:59:22 -0400 Subject: sysfs: count subdirectories sysfs: count subdirectories This patch introduces a subdirectory counter for each sysfs directory. Without the patch, sysfs_refresh_inode would walk all entries of the directory to calculate the number of subdirectories. This patch improves time of "ls -la /sys/block" when there are 10000 block devices from 9 seconds to 0.19 seconds. Signed-off-by: Mikulas Patocka Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 6 ++++++ fs/sysfs/inode.c | 14 +------------- fs/sysfs/sysfs.h | 2 ++ 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index ea9120a830d8..7d240e6b7176 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -47,6 +47,9 @@ static void sysfs_link_sibling(struct sysfs_dirent *sd) BUG_ON(sd->s_sibling); + if (sysfs_type(sd) == SYSFS_DIR) + parent_sd->s_dir.subdirs++; + /* Store directory entries in order by ino. This allows * readdir to properly restart without having to add a * cursor into the s_dir.children list. @@ -73,6 +76,9 @@ static void sysfs_unlink_sibling(struct sysfs_dirent *sd) { struct sysfs_dirent **pos; + if (sysfs_type(sd) == SYSFS_DIR) + sd->s_parent->s_dir.subdirs--; + for (pos = &sd->s_parent->s_dir.children; *pos; pos = &(*pos)->s_sibling) { if (*pos == sd) { diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index e3f091a81c72..1ee18c81df78 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -202,18 +202,6 @@ static inline void set_inode_attr(struct inode * inode, struct iattr * iattr) inode->i_ctime = iattr->ia_ctime; } -static int sysfs_count_nlink(struct sysfs_dirent *sd) -{ - struct sysfs_dirent *child; - int nr = 0; - - for (child = sd->s_dir.children; child; child = child->s_sibling) - if (sysfs_type(child) == SYSFS_DIR) - nr++; - - return nr + 2; -} - static void sysfs_refresh_inode(struct sysfs_dirent *sd, struct inode *inode) { struct sysfs_inode_attrs *iattrs = sd->s_iattr; @@ -230,7 +218,7 @@ static void sysfs_refresh_inode(struct sysfs_dirent *sd, struct inode *inode) } if (sysfs_type(sd) == SYSFS_DIR) - inode->i_nlink = sysfs_count_nlink(sd); + inode->i_nlink = sd->s_dir.subdirs + 2; } int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 845ab3ad229d..6348e2c753f6 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -19,6 +19,8 @@ struct sysfs_elem_dir { struct kobject *kobj; /* children list starts here and goes through sd->s_sibling */ struct sysfs_dirent *children; + + unsigned long subdirs; }; struct sysfs_elem_symlink { -- cgit v1.2.3 From 4f72c0cab40536a0be501d85ea4918467ab82ad5 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Mon, 25 Jul 2011 17:55:57 -0400 Subject: sysfs: use rb-tree for name lookups sysfs: use rb-tree for name lookups Use red-black tree for name lookups. Signed-off-by: Mikulas Patocka Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++------- fs/sysfs/sysfs.h | 5 +++++ 2 files changed, 55 insertions(+), 7 deletions(-) diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 7d240e6b7176..3e937da224d4 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -45,6 +45,9 @@ static void sysfs_link_sibling(struct sysfs_dirent *sd) struct sysfs_dirent *parent_sd = sd->s_parent; struct sysfs_dirent **pos; + struct rb_node **p; + struct rb_node *parent; + BUG_ON(sd->s_sibling); if (sysfs_type(sd) == SYSFS_DIR) @@ -60,6 +63,23 @@ static void sysfs_link_sibling(struct sysfs_dirent *sd) } sd->s_sibling = *pos; *pos = sd; + + p = &parent_sd->s_dir.name_tree.rb_node; + parent = NULL; + while (*p) { + int c; + parent = *p; +#define node rb_entry(parent, struct sysfs_dirent, name_node) + c = strcmp(sd->s_name, node->s_name); + if (c < 0) { + p = &node->name_node.rb_left; + } else { + p = &node->name_node.rb_right; + } +#undef node + } + rb_link_node(&sd->name_node, parent, p); + rb_insert_color(&sd->name_node, &parent_sd->s_dir.name_tree); } /** @@ -87,6 +107,8 @@ static void sysfs_unlink_sibling(struct sysfs_dirent *sd) break; } } + + rb_erase(&sd->name_node, &sd->s_parent->s_dir.name_tree); } /** @@ -546,15 +568,36 @@ struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, const void *ns, const unsigned char *name) { - struct sysfs_dirent *sd; + struct rb_node *p = parent_sd->s_dir.name_tree.rb_node; + struct sysfs_dirent *found = NULL; + + while (p) { + int c; +#define node rb_entry(p, struct sysfs_dirent, name_node) + c = strcmp(name, node->s_name); + if (c < 0) { + p = node->name_node.rb_left; + } else if (c > 0) { + p = node->name_node.rb_right; + } else { + found = node; + p = node->name_node.rb_left; + } +#undef node + } - for (sd = parent_sd->s_dir.children; sd; sd = sd->s_sibling) { - if (ns && sd->s_ns && (sd->s_ns != ns)) - continue; - if (!strcmp(sd->s_name, name)) - return sd; + if (found && ns) { + while (found->s_ns && found->s_ns != ns) { + p = rb_next(&found->name_node); + if (!p) + return NULL; + found = rb_entry(p, struct sysfs_dirent, name_node); + if (strcmp(name, found->s_name)) + return NULL; + } } - return NULL; + + return found; } /** diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 6348e2c753f6..fe1a9e8650bf 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -11,6 +11,7 @@ #include #include #include +#include struct sysfs_open_dirent; @@ -21,6 +22,8 @@ struct sysfs_elem_dir { struct sysfs_dirent *children; unsigned long subdirs; + + struct rb_root name_tree; }; struct sysfs_elem_symlink { @@ -61,6 +64,8 @@ struct sysfs_dirent { struct sysfs_dirent *s_sibling; const char *s_name; + struct rb_node name_node; + const void *s_ns; /* namespace tag */ union { struct sysfs_elem_dir s_dir; -- cgit v1.2.3 From 58f2a4c7932d8bec866d0394f806004146cde827 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Thu, 21 Jul 2011 20:01:12 -0400 Subject: sysfs: remove s_sibling hacks sysfs: remove s_sibling hacks s_sibling was used for three different purposes: 1) as a linked list of entries in the directory 2) as a linked list of entries to be deleted 3) as a pointer to "struct completion" This patch removes the hack and introduces new union u which holds pointers for cases 2) and 3). This change is needed for the following patch that removes s_sibling at all and replaces it with a rb tree. Signed-off-by: Mikulas Patocka Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 19 +++++++------------ fs/sysfs/sysfs.h | 5 +++++ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 3e937da224d4..a4846979d4e8 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -154,7 +154,6 @@ struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd) */ void sysfs_put_active(struct sysfs_dirent *sd) { - struct completion *cmpl; int v; if (unlikely(!sd)) @@ -166,10 +165,9 @@ void sysfs_put_active(struct sysfs_dirent *sd) return; /* atomic_dec_return() is a mb(), we'll always see the updated - * sd->s_sibling. + * sd->u.completion. */ - cmpl = (void *)sd->s_sibling; - complete(cmpl); + complete(sd->u.completion); } /** @@ -183,16 +181,16 @@ static void sysfs_deactivate(struct sysfs_dirent *sd) DECLARE_COMPLETION_ONSTACK(wait); int v; - BUG_ON(sd->s_sibling || !(sd->s_flags & SYSFS_FLAG_REMOVED)); + BUG_ON(!(sd->s_flags & SYSFS_FLAG_REMOVED)); if (!(sysfs_type(sd) & SYSFS_ACTIVE_REF)) return; - sd->s_sibling = (void *)&wait; + sd->u.completion = (void *)&wait; rwsem_acquire(&sd->dep_map, 0, 0, _RET_IP_); /* atomic_add_return() is a mb(), put_active() will always see - * the updated sd->s_sibling. + * the updated sd->u.completion. */ v = atomic_add_return(SD_DEACTIVATED_BIAS, &sd->s_active); @@ -201,8 +199,6 @@ static void sysfs_deactivate(struct sysfs_dirent *sd) wait_for_completion(&wait); } - sd->s_sibling = NULL; - lock_acquired(&sd->dep_map, _RET_IP_); rwsem_release(&sd->dep_map, 1, _RET_IP_); } @@ -518,7 +514,7 @@ void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) } sd->s_flags |= SYSFS_FLAG_REMOVED; - sd->s_sibling = acxt->removed; + sd->u.removed_list = acxt->removed; acxt->removed = sd; } @@ -542,8 +538,7 @@ void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt) while (acxt->removed) { struct sysfs_dirent *sd = acxt->removed; - acxt->removed = sd->s_sibling; - sd->s_sibling = NULL; + acxt->removed = sd->u.removed_list; sysfs_deactivate(sd); unmap_bin_file(sd); diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index fe1a9e8650bf..3c261681713b 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -66,6 +66,11 @@ struct sysfs_dirent { struct rb_node name_node; + union { + struct completion *completion; + struct sysfs_dirent *removed_list; + } u; + const void *s_ns; /* namespace tag */ union { struct sysfs_elem_dir s_dir; -- cgit v1.2.3 From a406f75840e15afbabd98cb64ae36b51424a8033 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Mon, 25 Jul 2011 17:57:03 -0400 Subject: sysfs: use rb-tree for inode number lookup sysfs: use rb-tree for inode number lookup This patch makes sysfs use red-black tree for inode number lookup. Together with a previous patch to use red-black tree for name lookup, this patch makes all sysfs lookups to have O(log n) complexity. Signed-off-by: Mikulas Patocka Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/dir.c | 89 +++++++++++++++++++++++++++++++------------------------- fs/sysfs/sysfs.h | 5 ++-- 2 files changed, 52 insertions(+), 42 deletions(-) diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index a4846979d4e8..c3646d93a032 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -43,26 +43,30 @@ static DEFINE_IDA(sysfs_ino_ida); static void sysfs_link_sibling(struct sysfs_dirent *sd) { struct sysfs_dirent *parent_sd = sd->s_parent; - struct sysfs_dirent **pos; struct rb_node **p; struct rb_node *parent; - BUG_ON(sd->s_sibling); - if (sysfs_type(sd) == SYSFS_DIR) parent_sd->s_dir.subdirs++; - /* Store directory entries in order by ino. This allows - * readdir to properly restart without having to add a - * cursor into the s_dir.children list. - */ - for (pos = &parent_sd->s_dir.children; *pos; pos = &(*pos)->s_sibling) { - if (sd->s_ino < (*pos)->s_ino) - break; + p = &parent_sd->s_dir.inode_tree.rb_node; + parent = NULL; + while (*p) { + parent = *p; +#define node rb_entry(parent, struct sysfs_dirent, inode_node) + if (sd->s_ino < node->s_ino) { + p = &node->inode_node.rb_left; + } else if (sd->s_ino > node->s_ino) { + p = &node->inode_node.rb_right; + } else { + printk(KERN_CRIT "sysfs: inserting duplicate inode '%lx'\n", sd->s_ino); + BUG(); + } +#undef node } - sd->s_sibling = *pos; - *pos = sd; + rb_link_node(&sd->inode_node, parent, p); + rb_insert_color(&sd->inode_node, &parent_sd->s_dir.inode_tree); p = &parent_sd->s_dir.name_tree.rb_node; parent = NULL; @@ -94,20 +98,10 @@ static void sysfs_link_sibling(struct sysfs_dirent *sd) */ static void sysfs_unlink_sibling(struct sysfs_dirent *sd) { - struct sysfs_dirent **pos; - if (sysfs_type(sd) == SYSFS_DIR) sd->s_parent->s_dir.subdirs--; - for (pos = &sd->s_parent->s_dir.children; *pos; - pos = &(*pos)->s_sibling) { - if (*pos == sd) { - *pos = sd->s_sibling; - sd->s_sibling = NULL; - break; - } - } - + rb_erase(&sd->inode_node, &sd->s_parent->s_dir.inode_tree); rb_erase(&sd->name_node, &sd->s_parent->s_dir.name_tree); } @@ -788,21 +782,19 @@ void sysfs_remove_subdir(struct sysfs_dirent *sd) static void __sysfs_remove_dir(struct sysfs_dirent *dir_sd) { struct sysfs_addrm_cxt acxt; - struct sysfs_dirent **pos; + struct rb_node *pos; if (!dir_sd) return; pr_debug("sysfs %s: removing dir\n", dir_sd->s_name); sysfs_addrm_start(&acxt, dir_sd); - pos = &dir_sd->s_dir.children; - while (*pos) { - struct sysfs_dirent *sd = *pos; - + pos = rb_first(&dir_sd->s_dir.inode_tree); + while (pos) { + struct sysfs_dirent *sd = rb_entry(pos, struct sysfs_dirent, inode_node); + pos = rb_next(pos); if (sysfs_type(sd) != SYSFS_DIR) sysfs_remove_one(&acxt, sd); - else - pos = &(*pos)->s_sibling; } sysfs_addrm_finish(&acxt); @@ -925,12 +917,28 @@ static struct sysfs_dirent *sysfs_dir_pos(const void *ns, pos = NULL; } if (!pos && (ino > 1) && (ino < INT_MAX)) { - pos = parent_sd->s_dir.children; - while (pos && (ino > pos->s_ino)) - pos = pos->s_sibling; + struct rb_node *p = parent_sd->s_dir.inode_tree.rb_node; + while (p) { +#define node rb_entry(p, struct sysfs_dirent, inode_node) + if (ino < node->s_ino) { + pos = node; + p = node->inode_node.rb_left; + } else if (ino > node->s_ino) { + p = node->inode_node.rb_right; + } else { + pos = node; + break; + } +#undef node + } + } + while (pos && pos->s_ns && pos->s_ns != ns) { + struct rb_node *p = rb_next(&pos->inode_node); + if (!p) + pos = NULL; + else + pos = rb_entry(p, struct sysfs_dirent, inode_node); } - while (pos && pos->s_ns && pos->s_ns != ns) - pos = pos->s_sibling; return pos; } @@ -938,10 +946,13 @@ static struct sysfs_dirent *sysfs_dir_next_pos(const void *ns, struct sysfs_dirent *parent_sd, ino_t ino, struct sysfs_dirent *pos) { pos = sysfs_dir_pos(ns, parent_sd, ino, pos); - if (pos) - pos = pos->s_sibling; - while (pos && pos->s_ns && pos->s_ns != ns) - pos = pos->s_sibling; + if (pos) do { + struct rb_node *p = rb_next(&pos->inode_node); + if (!p) + pos = NULL; + else + pos = rb_entry(p, struct sysfs_dirent, inode_node); + } while (pos && pos->s_ns && pos->s_ns != ns); return pos; } diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 3c261681713b..ce29e28b766d 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -18,11 +18,10 @@ struct sysfs_open_dirent; /* type-specific structures for sysfs_dirent->s_* union members */ struct sysfs_elem_dir { struct kobject *kobj; - /* children list starts here and goes through sd->s_sibling */ - struct sysfs_dirent *children; unsigned long subdirs; + struct rb_root inode_tree; struct rb_root name_tree; }; @@ -61,9 +60,9 @@ struct sysfs_dirent { struct lockdep_map dep_map; #endif struct sysfs_dirent *s_parent; - struct sysfs_dirent *s_sibling; const char *s_name; + struct rb_node inode_node; struct rb_node name_node; union { -- cgit v1.2.3 From 4e0b72fd7444e07e2870d193ce8fb6b0b00f5a89 Mon Sep 17 00:00:00 2001 From: "Hans J. Koch" Date: Tue, 9 Aug 2011 20:53:41 +0200 Subject: uio: uio_pci_generic: Remove useless spin_lock The spin_lock in uio_pci_generic.c is only used in the interrupt handler, which cannot be executed twice at the same time. That makes the lock rather pointless. This patch removes it. Cc: "Michael S. Tsirkin" Cc: Chris Wright Cc: Jesse Barnes Cc: Sebastian Andrzej Siewior Cc: Anthony Foiani Reported-by: Anthony Foiani Reported-by: Sebastian Andrzej Siewior Signed-off-by: Hans J. Koch Acked-by: Michael S. Tsirkin Signed-off-by: Greg Kroah-Hartman --- drivers/uio/uio_pci_generic.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/uio/uio_pci_generic.c b/drivers/uio/uio_pci_generic.c index fc22e1e6f215..02bd47bdee1c 100644 --- a/drivers/uio/uio_pci_generic.c +++ b/drivers/uio/uio_pci_generic.c @@ -24,7 +24,6 @@ #include #include #include -#include #define DRIVER_VERSION "0.01.0" #define DRIVER_AUTHOR "Michael S. Tsirkin " @@ -33,7 +32,6 @@ struct uio_pci_generic_dev { struct uio_info info; struct pci_dev *pdev; - spinlock_t lock; /* guards command register accesses */ }; static inline struct uio_pci_generic_dev * @@ -57,7 +55,6 @@ static irqreturn_t irqhandler(int irq, struct uio_info *info) BUILD_BUG_ON(PCI_COMMAND % 4); BUILD_BUG_ON(PCI_COMMAND + 2 != PCI_STATUS); - spin_lock_irq(&gdev->lock); pci_block_user_cfg_access(pdev); /* Read both command and status registers in a single 32-bit operation. @@ -83,7 +80,6 @@ static irqreturn_t irqhandler(int irq, struct uio_info *info) done: pci_unblock_user_cfg_access(pdev); - spin_unlock_irq(&gdev->lock); return ret; } @@ -158,7 +154,6 @@ static int __devinit probe(struct pci_dev *pdev, gdev->info.irq_flags = IRQF_SHARED; gdev->info.handler = irqhandler; gdev->pdev = pdev; - spin_lock_init(&gdev->lock); if (uio_register_device(&pdev->dev, &gdev->info)) goto err_register; -- cgit v1.2.3 From d80df1cea036ce8b6064b3b08dd58ad3eb55a6e9 Mon Sep 17 00:00:00 2001 From: Wanlong Gao Date: Sat, 20 Aug 2011 12:12:08 +0800 Subject: drivers:uio:change the goto label to consistent with others Remove one *goto* label in uio.c. Signed-off-by: Wanlong Gao Signed-off-by: "Hans J. Koch" Signed-off-by: Greg Kroah-Hartman --- drivers/uio/uio.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c index d2efe823c20d..c89f12a8b116 100644 --- a/drivers/uio/uio.c +++ b/drivers/uio/uio.c @@ -750,14 +750,13 @@ static int uio_major_init(void) uio_major = MAJOR(uio_dev); uio_cdev = cdev; - result = 0; -out: - return result; + return 0; out_put: kobject_put(&cdev->kobj); out_unregister: unregister_chrdev_region(uio_dev, UIO_MAX_DEVICES); - goto out; +out: + return result; } static void uio_major_cleanup(void) -- cgit v1.2.3 From 9245acd20d58d5a9a3ed5ebf8c486e0609027817 Mon Sep 17 00:00:00 2001 From: Wanlong Gao Date: Sat, 20 Aug 2011 12:12:07 +0800 Subject: drivers:uio:fix section mismatch in uio_pdrv_genirq.c Remove the __devinitconst to fix the section mismatch. WARNING: drivers/uio/built-in.o(.data+0x2e8): Section mismatch in reference from the variable uio_pdrv_genirq to the variable .devinit.rodata:uio_of_genirq_match The variable uio_pdrv_genirq references the variable __devinitconst uio_of_genirq_match If the reference is valid then annotate the variable with __init* or __refdata (see linux/init.h) or name the variable: *driver, *_template, *_timer, *_sht, *_ops, *_probe, *_probe_one, *_console Signed-off-by: Wanlong Gao Signed-off-by: Greg Kroah-Hartman --- drivers/uio/uio_pdrv_genirq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/uio/uio_pdrv_genirq.c b/drivers/uio/uio_pdrv_genirq.c index bae96d246760..0b2ed71e3bfa 100644 --- a/drivers/uio/uio_pdrv_genirq.c +++ b/drivers/uio/uio_pdrv_genirq.c @@ -253,7 +253,7 @@ static const struct dev_pm_ops uio_pdrv_genirq_dev_pm_ops = { }; #ifdef CONFIG_OF -static const struct of_device_id __devinitconst uio_of_genirq_match[] = { +static const struct of_device_id uio_of_genirq_match[] = { { /* empty for now */ }, }; MODULE_DEVICE_TABLE(of, uio_of_genirq_match); -- cgit v1.2.3 From 0a26813c9f528f17901b2f2394fba8557d2c9485 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 15 Aug 2011 16:51:22 +0200 Subject: drivers_base: platform: use always ->name for uevent If id_entry is available then it is used. However if we remove first the driver followed by the device, then the id_entry is pointing to driver's memory which is long gone. Since id->name and plat->name are equal there is no point in distinguishing them. Cc: Grant Likely Cc: linux-kernel@vger.kernel.org Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 0cad9c7f6bb5..cd7157575e58 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -614,7 +614,7 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env) return rc; add_uevent_var(env, "MODALIAS=%s%s", PLATFORM_MODULE_PREFIX, - (pdev->id_entry) ? pdev->id_entry->name : pdev->name); + pdev->name); return 0; } -- cgit v1.2.3 From dd7d7fea29c18b818e94f252a76f495490d399c3 Mon Sep 17 00:00:00 2001 From: Tomoya MORINAGA Date: Thu, 21 Jul 2011 17:07:08 +0900 Subject: pch_phub: Care FUNCSEL register in PM Only ML7213/ML7223(Bus-n) has this register. Currently,this driver doesn't care register "FUNCSEL" in suspend/resume. This patch saves/restores FUNCSEL register only when the device is ML7213 or ML7223(Bus-n). Signed-off-by: Tomoya MORINAGA Signed-off-by: Greg Kroah-Hartman --- drivers/misc/pch_phub.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c index 0fd7e77bee29..61ece53f2f41 100644 --- a/drivers/misc/pch_phub.c +++ b/drivers/misc/pch_phub.c @@ -90,6 +90,7 @@ #define PCH_PHUB_INTPIN_REG_WPERMIT_REG3 0x002C #define PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE 0x0040 #define CLKCFG_REG_OFFSET 0x500 +#define FUNCSEL_REG_OFFSET 0x508 #define PCH_PHUB_OROM_SIZE 15360 @@ -108,6 +109,7 @@ * @intpin_reg_wpermit_reg3: INTPIN_REG_WPERMIT register 3 val * @int_reduce_control_reg: INT_REDUCE_CONTROL registers val * @clkcfg_reg: CLK CFG register val + * @funcsel_reg: Function select register value * @pch_phub_base_address: Register base address * @pch_phub_extrom_base_address: external rom base address * @pch_mac_start_address: MAC address area start address @@ -128,6 +130,7 @@ struct pch_phub_reg { u32 intpin_reg_wpermit_reg3; u32 int_reduce_control_reg[MAX_NUM_INT_REDUCE_CONTROL_REG]; u32 clkcfg_reg; + u32 funcsel_reg; void __iomem *pch_phub_base_address; void __iomem *pch_phub_extrom_base_address; u32 pch_mac_start_address; @@ -211,6 +214,8 @@ static void pch_phub_save_reg_conf(struct pci_dev *pdev) __func__, i, chip->int_reduce_control_reg[i]); } chip->clkcfg_reg = ioread32(p + CLKCFG_REG_OFFSET); + if ((chip->ioh_type == 2) || (chip->ioh_type == 4)) + chip->funcsel_reg = ioread32(p + FUNCSEL_REG_OFFSET); } /* pch_phub_restore_reg_conf - restore register configuration */ @@ -271,6 +276,8 @@ static void pch_phub_restore_reg_conf(struct pci_dev *pdev) } iowrite32(chip->clkcfg_reg, p + CLKCFG_REG_OFFSET); + if ((chip->ioh_type == 2) || (chip->ioh_type == 4)) + iowrite32(chip->funcsel_reg, p + FUNCSEL_REG_OFFSET); } /** -- cgit v1.2.3 From 25b8a88c10770e8c3f14bf2e222691dc6e79de78 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 18 Jul 2011 11:22:06 +0300 Subject: pch_phub: use kernel's '%pM' format option to print MAC Signed-off-by: Andy Shevchenko Cc: Greg Kroah-Hartman Signed-off-by: Greg Kroah-Hartman --- drivers/misc/pch_phub.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c index 61ece53f2f41..dee33addcaeb 100644 --- a/drivers/misc/pch_phub.c +++ b/drivers/misc/pch_phub.c @@ -601,8 +601,7 @@ static ssize_t show_pch_mac(struct device *dev, struct device_attribute *attr, pch_phub_read_gbe_mac_addr(chip, mac); - return sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + return sprintf(buf, "%pM\n", mac); } static ssize_t store_pch_mac(struct device *dev, struct device_attribute *attr, -- cgit v1.2.3 From cbc4663552ee476f57933920d782222d94878e7e Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 11 Aug 2011 14:36:21 -0400 Subject: dynamic_debug: Add __dynamic_dev_dbg Unlike dynamic_pr_debug, dynamic uses of dev_dbg can not currently add task_pid/KBUILD_MODNAME/__func__/__LINE__ to selected debug output. Add a new function similar to dynamic_pr_debug to optionally emit these prefixes. Cc: Aloisio Almeida Noticed-by: Aloisio Almeida Signed-off-by: Joe Perches Signed-off-by: Jason Baron Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 5 +++-- include/linux/device.h | 5 +++++ include/linux/dynamic_debug.h | 10 ++++++++-- lib/dynamic_debug.c | 38 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 54 insertions(+), 4 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index bc8729d603a7..82c865452c70 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1764,8 +1764,8 @@ void device_shutdown(void) #ifdef CONFIG_PRINTK -static int __dev_printk(const char *level, const struct device *dev, - struct va_format *vaf) +int __dev_printk(const char *level, const struct device *dev, + struct va_format *vaf) { if (!dev) return printk("%s(NULL device *): %pV", level, vaf); @@ -1773,6 +1773,7 @@ static int __dev_printk(const char *level, const struct device *dev, return printk("%s%s %s: %pV", level, dev_driver_string(dev), dev_name(dev), vaf); } +EXPORT_SYMBOL(__dev_printk); int dev_printk(const char *level, const struct device *dev, const char *fmt, ...) diff --git a/include/linux/device.h b/include/linux/device.h index c20dfbfc49b4..4639419522da 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -785,6 +785,8 @@ extern const char *dev_driver_string(const struct device *dev); #ifdef CONFIG_PRINTK +extern int __dev_printk(const char *level, const struct device *dev, + struct va_format *vaf); extern int dev_printk(const char *level, const struct device *dev, const char *fmt, ...) __attribute__ ((format (printf, 3, 4))); @@ -805,6 +807,9 @@ extern int _dev_info(const struct device *dev, const char *fmt, ...) #else +static inline int __dev_printk(const char *level, const struct device *dev, + struct va_format *vaf) + { return 0; } static inline int dev_printk(const char *level, const struct device *dev, const char *fmt, ...) __attribute__ ((format (printf, 3, 4))); diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h index e747ecd48e1c..bdf15319944e 100644 --- a/include/linux/dynamic_debug.h +++ b/include/linux/dynamic_debug.h @@ -47,6 +47,13 @@ extern int ddebug_remove_module(const char *mod_name); extern int __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); +struct device; + +extern int __dynamic_dev_dbg(struct _ddebug *descriptor, + const struct device *dev, + const char *fmt, ...) + __attribute__ ((format (printf, 3, 4))); + #define dynamic_pr_debug(fmt, ...) do { \ static struct _ddebug descriptor \ __used \ @@ -57,7 +64,6 @@ extern int __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...) __dynamic_pr_debug(&descriptor, pr_fmt(fmt), ##__VA_ARGS__); \ } while (0) - #define dynamic_dev_dbg(dev, fmt, ...) do { \ static struct _ddebug descriptor \ __used \ @@ -65,7 +71,7 @@ extern int __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...) { KBUILD_MODNAME, __func__, __FILE__, fmt, __LINE__, \ _DPRINTK_FLAGS_DEFAULT }; \ if (unlikely(descriptor.enabled)) \ - dev_printk(KERN_DEBUG, dev, fmt, ##__VA_ARGS__); \ + __dynamic_dev_dbg(&descriptor, dev, fmt, ##__VA_ARGS__); \ } while (0) #else diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c index 75ca78f3a8c9..63b6f95ac552 100644 --- a/lib/dynamic_debug.c +++ b/lib/dynamic_debug.c @@ -30,6 +30,7 @@ #include #include #include +#include extern struct _ddebug __start___verbose[]; extern struct _ddebug __stop___verbose[]; @@ -456,6 +457,43 @@ int __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...) } EXPORT_SYMBOL(__dynamic_pr_debug); +int __dynamic_dev_dbg(struct _ddebug *descriptor, + const struct device *dev, const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + int res; + + BUG_ON(!descriptor); + BUG_ON(!fmt); + + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + res = printk(KERN_DEBUG); + if (descriptor->flags & _DPRINTK_FLAGS_INCL_TID) { + if (in_interrupt()) + res += printk(KERN_CONT " "); + else + res += printk(KERN_CONT "[%d] ", task_pid_vnr(current)); + } + if (descriptor->flags & _DPRINTK_FLAGS_INCL_MODNAME) + res += printk(KERN_CONT "%s:", descriptor->modname); + if (descriptor->flags & _DPRINTK_FLAGS_INCL_FUNCNAME) + res += printk(KERN_CONT "%s:", descriptor->function); + if (descriptor->flags & _DPRINTK_FLAGS_INCL_LINENO) + res += printk(KERN_CONT "%d ", descriptor->lineno); + + res += __dev_printk(KERN_CONT, dev, &vaf); + + va_end(args); + + return res; +} +EXPORT_SYMBOL(__dynamic_dev_dbg); + static __initdata char ddebug_setup_string[1024]; static __init int ddebug_setup_query(char *str) { -- cgit v1.2.3 From 6c2140ee0ebf91258f93d3019922b5f520a18d88 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 11 Aug 2011 14:36:25 -0400 Subject: dynamic_debug: Consolidate prefix output to single routine Adding dynamic_dev_dbg duplicated prefix output. Consolidate that output to a single routine. Signed-off-by: Joe Perches Signed-off-by: Jason Baron Signed-off-by: Greg Kroah-Hartman --- lib/dynamic_debug.c | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c index 63b6f95ac552..37217090aacf 100644 --- a/lib/dynamic_debug.c +++ b/lib/dynamic_debug.c @@ -428,15 +428,10 @@ static int ddebug_exec_query(char *query_string) return 0; } -int __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...) +static int dynamic_emit_prefix(const struct _ddebug *descriptor) { - va_list args; int res; - BUG_ON(!descriptor); - BUG_ON(!fmt); - - va_start(args, fmt); res = printk(KERN_DEBUG); if (descriptor->flags & _DPRINTK_FLAGS_INCL_TID) { if (in_interrupt()) @@ -450,7 +445,23 @@ int __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...) res += printk(KERN_CONT "%s:", descriptor->function); if (descriptor->flags & _DPRINTK_FLAGS_INCL_LINENO) res += printk(KERN_CONT "%d ", descriptor->lineno); + + return res; +} + +int __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...) +{ + va_list args; + int res; + + BUG_ON(!descriptor); + BUG_ON(!fmt); + + va_start(args, fmt); + + res = dynamic_emit_prefix(descriptor); res += vprintk(fmt, args); + va_end(args); return res; @@ -472,20 +483,7 @@ int __dynamic_dev_dbg(struct _ddebug *descriptor, vaf.fmt = fmt; vaf.va = &args; - res = printk(KERN_DEBUG); - if (descriptor->flags & _DPRINTK_FLAGS_INCL_TID) { - if (in_interrupt()) - res += printk(KERN_CONT " "); - else - res += printk(KERN_CONT "[%d] ", task_pid_vnr(current)); - } - if (descriptor->flags & _DPRINTK_FLAGS_INCL_MODNAME) - res += printk(KERN_CONT "%s:", descriptor->modname); - if (descriptor->flags & _DPRINTK_FLAGS_INCL_FUNCNAME) - res += printk(KERN_CONT "%s:", descriptor->function); - if (descriptor->flags & _DPRINTK_FLAGS_INCL_LINENO) - res += printk(KERN_CONT "%d ", descriptor->lineno); - + res = dynamic_emit_prefix(descriptor); res += __dev_printk(KERN_CONT, dev, &vaf); va_end(args); -- cgit v1.2.3 From 5b2ebce4821c66dd33d15d076ee264b4eb86fea3 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 11 Aug 2011 14:36:29 -0400 Subject: dynamic_debug: Remove uses of KERN_CONT in dynamic_emit_prefix Multiple printks with KERN_CONT can be interleaved by other printks. Reduce the likelihood of that interleaving by consolidating multiple calls to printk. Signed-off-by: Joe Perches Signed-off-by: Jason Baron Signed-off-by: Greg Kroah-Hartman --- lib/dynamic_debug.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c index 37217090aacf..a3eb6ab074a6 100644 --- a/lib/dynamic_debug.c +++ b/lib/dynamic_debug.c @@ -430,23 +430,35 @@ static int ddebug_exec_query(char *query_string) static int dynamic_emit_prefix(const struct _ddebug *descriptor) { - int res; + char tid[sizeof(int) + sizeof(int)/2 + 4]; + char lineno[sizeof(int) + sizeof(int)/2]; - res = printk(KERN_DEBUG); if (descriptor->flags & _DPRINTK_FLAGS_INCL_TID) { if (in_interrupt()) - res += printk(KERN_CONT " "); + snprintf(tid, sizeof(tid), "%s", " "); else - res += printk(KERN_CONT "[%d] ", task_pid_vnr(current)); + snprintf(tid, sizeof(tid), "[%d] ", + task_pid_vnr(current)); + } else { + tid[0] = 0; } - if (descriptor->flags & _DPRINTK_FLAGS_INCL_MODNAME) - res += printk(KERN_CONT "%s:", descriptor->modname); - if (descriptor->flags & _DPRINTK_FLAGS_INCL_FUNCNAME) - res += printk(KERN_CONT "%s:", descriptor->function); - if (descriptor->flags & _DPRINTK_FLAGS_INCL_LINENO) - res += printk(KERN_CONT "%d ", descriptor->lineno); - return res; + if (descriptor->flags & _DPRINTK_FLAGS_INCL_LINENO) + snprintf(lineno, sizeof(lineno), "%d", descriptor->lineno); + else + lineno[0] = 0; + + return printk(KERN_DEBUG "%s%s%s%s%s%s", + tid, + (descriptor->flags & _DPRINTK_FLAGS_INCL_MODNAME) ? + descriptor->modname : "", + (descriptor->flags & _DPRINTK_FLAGS_INCL_MODNAME) ? + ":" : "", + (descriptor->flags & _DPRINTK_FLAGS_INCL_FUNCNAME) ? + descriptor->function : "", + (descriptor->flags & _DPRINTK_FLAGS_INCL_FUNCNAME) ? + ":" : "", + lineno); } int __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...) -- cgit v1.2.3 From 4ad275e5cb576fa4e3e12597cb81eed0d500416d Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 11 Aug 2011 14:36:33 -0400 Subject: dynamic_debug: Convert printks to pr_ Add pr_fmt(fmt) with __func__. Converts "ddebug:" prefix to "dynamic_debug:". Most likely the if (verbose) outputs could also be converted from pr_info to pr_debug. Signed-off-by: Joe Perches Signed-off-by: Jason Baron Signed-off-by: Greg Kroah-Hartman --- lib/dynamic_debug.c | 59 +++++++++++++++++++++++------------------------------ 1 file changed, 26 insertions(+), 33 deletions(-) diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c index a3eb6ab074a6..4fc03ddb05f2 100644 --- a/lib/dynamic_debug.c +++ b/lib/dynamic_debug.c @@ -10,6 +10,8 @@ * Copyright (C) 2011 Bart Van Assche. All Rights Reserved. */ +#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__ + #include #include #include @@ -160,8 +162,7 @@ static void ddebug_change(const struct ddebug_query *query, else dp->enabled = 0; if (verbose) - printk(KERN_INFO - "ddebug: changed %s:%d [%s]%s %s\n", + pr_info("changed %s:%d [%s]%s %s\n", dp->filename, dp->lineno, dt->mod_name, dp->function, ddebug_describe_flags(dp, flagbuf, @@ -171,7 +172,7 @@ static void ddebug_change(const struct ddebug_query *query, mutex_unlock(&ddebug_lock); if (!nfound && verbose) - printk(KERN_INFO "ddebug: no matches for query\n"); + pr_info("no matches for query\n"); } /* @@ -216,10 +217,10 @@ static int ddebug_tokenize(char *buf, char *words[], int maxwords) if (verbose) { int i; - printk(KERN_INFO "%s: split into words:", __func__); + pr_info("split into words:"); for (i = 0 ; i < nwords ; i++) - printk(" \"%s\"", words[i]); - printk("\n"); + pr_cont(" \"%s\"", words[i]); + pr_cont("\n"); } return nwords; @@ -331,16 +332,15 @@ static int ddebug_parse_query(char *words[], int nwords, } } else { if (verbose) - printk(KERN_ERR "%s: unknown keyword \"%s\"\n", - __func__, words[i]); + pr_err("unknown keyword \"%s\"\n", words[i]); return -EINVAL; } } if (verbose) - printk(KERN_INFO "%s: q->function=\"%s\" q->filename=\"%s\" " - "q->module=\"%s\" q->format=\"%s\" q->lineno=%u-%u\n", - __func__, query->function, query->filename, + pr_info("q->function=\"%s\" q->filename=\"%s\" " + "q->module=\"%s\" q->format=\"%s\" q->lineno=%u-%u\n", + query->function, query->filename, query->module, query->format, query->first_lineno, query->last_lineno); @@ -369,7 +369,7 @@ static int ddebug_parse_flags(const char *str, unsigned int *flagsp, return -EINVAL; } if (verbose) - printk(KERN_INFO "%s: op='%c'\n", __func__, op); + pr_info("op='%c'\n", op); for ( ; *str ; ++str) { for (i = ARRAY_SIZE(opt_array) - 1; i >= 0; i--) { @@ -384,7 +384,7 @@ static int ddebug_parse_flags(const char *str, unsigned int *flagsp, if (flags == 0) return -EINVAL; if (verbose) - printk(KERN_INFO "%s: flags=0x%x\n", __func__, flags); + pr_info("flags=0x%x\n", flags); /* calculate final *flagsp, *maskp according to mask and op */ switch (op) { @@ -402,8 +402,7 @@ static int ddebug_parse_flags(const char *str, unsigned int *flagsp, break; } if (verbose) - printk(KERN_INFO "%s: *flagsp=0x%x *maskp=0x%x\n", - __func__, *flagsp, *maskp); + pr_info("*flagsp=0x%x *maskp=0x%x\n", *flagsp, *maskp); return 0; } @@ -508,7 +507,7 @@ static __initdata char ddebug_setup_string[1024]; static __init int ddebug_setup_query(char *str) { if (strlen(str) >= 1024) { - pr_warning("ddebug boot param string too large\n"); + pr_warn("ddebug boot param string too large\n"); return 0; } strcpy(ddebug_setup_string, str); @@ -536,8 +535,7 @@ static ssize_t ddebug_proc_write(struct file *file, const char __user *ubuf, return -EFAULT; tmpbuf[len] = '\0'; if (verbose) - printk(KERN_INFO "%s: read %d bytes from userspace\n", - __func__, (int)len); + pr_info("read %d bytes from userspace\n", (int)len); ret = ddebug_exec_query(tmpbuf); if (ret) @@ -600,8 +598,7 @@ static void *ddebug_proc_start(struct seq_file *m, loff_t *pos) int n = *pos; if (verbose) - printk(KERN_INFO "%s: called m=%p *pos=%lld\n", - __func__, m, (unsigned long long)*pos); + pr_info("called m=%p *pos=%lld\n", m, (unsigned long long)*pos); mutex_lock(&ddebug_lock); @@ -626,8 +623,8 @@ static void *ddebug_proc_next(struct seq_file *m, void *p, loff_t *pos) struct _ddebug *dp; if (verbose) - printk(KERN_INFO "%s: called m=%p p=%p *pos=%lld\n", - __func__, m, p, (unsigned long long)*pos); + pr_info("called m=%p p=%p *pos=%lld\n", + m, p, (unsigned long long)*pos); if (p == SEQ_START_TOKEN) dp = ddebug_iter_first(iter); @@ -650,8 +647,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p) char flagsbuf[8]; if (verbose) - printk(KERN_INFO "%s: called m=%p p=%p\n", - __func__, m, p); + pr_info("called m=%p p=%p\n", m, p); if (p == SEQ_START_TOKEN) { seq_puts(m, @@ -676,8 +672,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p) static void ddebug_proc_stop(struct seq_file *m, void *p) { if (verbose) - printk(KERN_INFO "%s: called m=%p p=%p\n", - __func__, m, p); + pr_info("called m=%p p=%p\n", m, p); mutex_unlock(&ddebug_lock); } @@ -700,7 +695,7 @@ static int ddebug_proc_open(struct inode *inode, struct file *file) int err; if (verbose) - printk(KERN_INFO "%s: called\n", __func__); + pr_info("called\n"); iter = kzalloc(sizeof(*iter), GFP_KERNEL); if (iter == NULL) @@ -752,8 +747,7 @@ int ddebug_add_module(struct _ddebug *tab, unsigned int n, mutex_unlock(&ddebug_lock); if (verbose) - printk(KERN_INFO "%u debug prints in module %s\n", - n, dt->mod_name); + pr_info("%u debug prints in module %s\n", n, dt->mod_name); return 0; } EXPORT_SYMBOL_GPL(ddebug_add_module); @@ -775,8 +769,7 @@ int ddebug_remove_module(const char *mod_name) int ret = -ENOENT; if (verbose) - printk(KERN_INFO "%s: removing module \"%s\"\n", - __func__, mod_name); + pr_info("removing module \"%s\"\n", mod_name); mutex_lock(&ddebug_lock); list_for_each_entry_safe(dt, nextdt, &ddebug_tables, link) { @@ -852,8 +845,8 @@ static int __init dynamic_debug_init(void) if (ddebug_setup_string[0] != '\0') { ret = ddebug_exec_query(ddebug_setup_string); if (ret) - pr_warning("Invalid ddebug boot param %s", - ddebug_setup_string); + pr_warn("Invalid ddebug boot param %s", + ddebug_setup_string); else pr_info("ddebug initialized with string %s", ddebug_setup_string); -- cgit v1.2.3 From fae8d206a188080d3d23b621fc2652f15f3457b6 Mon Sep 17 00:00:00 2001 From: Jason Baron Date: Thu, 11 Aug 2011 14:36:38 -0400 Subject: dynamic_debug: remove unused control variables Remove no longer used dynamic debug control variables. The definitions were removed a while ago, but we forgot to clean up the extern references. Signed-off-by: Jason Baron Signed-off-by: Greg Kroah-Hartman --- include/linux/dynamic_debug.h | 7 ------- 1 file changed, 7 deletions(-) diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h index bdf15319944e..843cb9eb4226 100644 --- a/include/linux/dynamic_debug.h +++ b/include/linux/dynamic_debug.h @@ -1,13 +1,6 @@ #ifndef _DYNAMIC_DEBUG_H #define _DYNAMIC_DEBUG_H -/* dynamic_printk_enabled, and dynamic_printk_enabled2 are bitmasks in which - * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They - * use independent hash functions, to reduce the chance of false positives. - */ -extern long long dynamic_debug_enabled; -extern long long dynamic_debug_enabled2; - /* * An instance of this structure is created in a special * ELF section at every dynamic debug callsite. At runtime, -- cgit v1.2.3 From ac0ac38f68be73b92dc390ceace50a0d143d76ae Mon Sep 17 00:00:00 2001 From: Jason Baron Date: Thu, 11 Aug 2011 14:36:43 -0400 Subject: dynamic_debug: add Jason Baron as maintainer Add a maintainers entry for dynamic debug. Hopefully nobody will object to me as maintainer... Signed-off-by: Jason Baron Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 069ee3b5c651..476209c40395 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2297,6 +2297,12 @@ L: netdev@vger.kernel.org S: Maintained F: drivers/net/wan/dscc4.c +DYNAMIC DEBUG +M: Jason Baron +S: Maintained +F: lib/dynamic_debug.c +F: include/linux/dynamic_debug.h + DZ DECSTATION DZ11 SERIAL DRIVER M: "Maciej W. Rozycki" S: Maintained -- cgit v1.2.3 From ffa10cb47a94c9b456c83301c8047e2a898dd409 Mon Sep 17 00:00:00 2001 From: Jason Baron Date: Thu, 11 Aug 2011 14:36:48 -0400 Subject: dynamic_debug: make netdev_dbg() call __netdev_printk() Previously, if dynamic debug was enabled netdev_dbg() was using dynamic_dev_dbg() to print out the underlying msg. Fix this by making sure netdev_dbg() uses __netdev_printk(). Cc: David S. Miller Signed-off-by: Jason Baron Signed-off-by: Greg Kroah-Hartman --- include/linux/dynamic_debug.h | 17 +++++++++++++++++ include/linux/netdevice.h | 6 ++++-- lib/dynamic_debug.c | 25 +++++++++++++++++++++++++ net/core/dev.c | 3 ++- 4 files changed, 48 insertions(+), 3 deletions(-) diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h index 843cb9eb4226..feaac1ee3001 100644 --- a/include/linux/dynamic_debug.h +++ b/include/linux/dynamic_debug.h @@ -47,6 +47,13 @@ extern int __dynamic_dev_dbg(struct _ddebug *descriptor, const char *fmt, ...) __attribute__ ((format (printf, 3, 4))); +struct net_device; + +extern int __dynamic_netdev_dbg(struct _ddebug *descriptor, + const struct net_device *dev, + const char *fmt, ...) + __attribute__ ((format (printf, 3, 4))); + #define dynamic_pr_debug(fmt, ...) do { \ static struct _ddebug descriptor \ __used \ @@ -67,6 +74,16 @@ extern int __dynamic_dev_dbg(struct _ddebug *descriptor, __dynamic_dev_dbg(&descriptor, dev, fmt, ##__VA_ARGS__); \ } while (0) +#define dynamic_netdev_dbg(dev, fmt, ...) do { \ + static struct _ddebug descriptor \ + __used \ + __attribute__((section("__verbose"), aligned(8))) = \ + { KBUILD_MODNAME, __func__, __FILE__, fmt, __LINE__, \ + _DPRINTK_FLAGS_DEFAULT }; \ + if (unlikely(descriptor.enabled)) \ + __dynamic_netdev_dbg(&descriptor, dev, fmt, ##__VA_ARGS__);\ + } while (0) + #else static inline int ddebug_remove_module(const char *mod) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index ddee79bb8f15..9333a0300c5e 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2617,6 +2617,9 @@ static inline const char *netdev_name(const struct net_device *dev) return dev->name; } +extern int __netdev_printk(const char *level, const struct net_device *dev, + struct va_format *vaf); + extern int netdev_printk(const char *level, const struct net_device *dev, const char *format, ...) __attribute__ ((format (printf, 3, 4))); @@ -2644,8 +2647,7 @@ extern int netdev_info(const struct net_device *dev, const char *format, ...) #elif defined(CONFIG_DYNAMIC_DEBUG) #define netdev_dbg(__dev, format, args...) \ do { \ - dynamic_dev_dbg((__dev)->dev.parent, "%s: " format, \ - netdev_name(__dev), ##args); \ + dynamic_netdev_dbg(__dev, format, ##args); \ } while (0) #else #define netdev_dbg(__dev, format, args...) \ diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c index 4fc03ddb05f2..ee3b9ba625c5 100644 --- a/lib/dynamic_debug.c +++ b/lib/dynamic_debug.c @@ -33,6 +33,7 @@ #include #include #include +#include extern struct _ddebug __start___verbose[]; extern struct _ddebug __stop___verbose[]; @@ -503,6 +504,30 @@ int __dynamic_dev_dbg(struct _ddebug *descriptor, } EXPORT_SYMBOL(__dynamic_dev_dbg); +int __dynamic_netdev_dbg(struct _ddebug *descriptor, + const struct net_device *dev, const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + int res; + + BUG_ON(!descriptor); + BUG_ON(!fmt); + + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + res = dynamic_emit_prefix(descriptor); + res += __netdev_printk(KERN_CONT, dev, &vaf); + + va_end(args); + + return res; +} +EXPORT_SYMBOL(__dynamic_netdev_dbg); + static __initdata char ddebug_setup_string[1024]; static __init int ddebug_setup_query(char *str) { diff --git a/net/core/dev.c b/net/core/dev.c index 17d67b579beb..c47a7bcf3c64 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -6290,7 +6290,7 @@ const char *netdev_drivername(const struct net_device *dev) return empty; } -static int __netdev_printk(const char *level, const struct net_device *dev, +int __netdev_printk(const char *level, const struct net_device *dev, struct va_format *vaf) { int r; @@ -6305,6 +6305,7 @@ static int __netdev_printk(const char *level, const struct net_device *dev, return r; } +EXPORT_SYMBOL(__netdev_printk); int netdev_printk(const char *level, const struct net_device *dev, const char *format, ...) -- cgit v1.2.3 From b5fb0a03214dfd02bc34bda659d5b89ef12741b2 Mon Sep 17 00:00:00 2001 From: Jason Baron Date: Thu, 11 Aug 2011 14:36:53 -0400 Subject: dynamic_debug: make netif_dbg() call __netdev_printk() Previously, netif_dbg() was using dynamic_dev_dbg() to perform the underlying printk. Fix it to use __netdev_printk(), instead. Cc: David S. Miller Signed-off-by: Jason Baron Signed-off-by: Greg Kroah-Hartman --- include/linux/netdevice.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 9333a0300c5e..279726039f00 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2714,9 +2714,7 @@ do { \ #define netif_dbg(priv, type, netdev, format, args...) \ do { \ if (netif_msg_##type(priv)) \ - dynamic_dev_dbg((netdev)->dev.parent, \ - "%s: " format, \ - netdev_name(netdev), ##args); \ + dynamic_netdev_dbg(netdev, format, ##args); \ } while (0) #else #define netif_dbg(priv, type, dev, format, args...) \ -- cgit v1.2.3 From ebf4127cd677e9781b450e44dfaaa1cc595efcaa Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Mon, 22 Aug 2011 15:51:34 +0200 Subject: kobj_uevent: Ignore if some listeners cannot handle message kobject_uevent() uses a multicast socket and should ignore if one of listeners cannot handle messages or nobody is listening at all. Easily reproducible when a process in system is cloned with CLONE_NEWNET flag. (See also http://article.gmane.org/gmane.linux.kernel.device-mapper.dm-crypt/5256) Signed-off-by: Milan Broz Acked-by: Kay Sievers Cc: stable Signed-off-by: Greg Kroah-Hartman --- lib/kobject_uevent.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c index 70af0a7f97c0..ad72a03ce5e9 100644 --- a/lib/kobject_uevent.c +++ b/lib/kobject_uevent.c @@ -282,7 +282,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, kobj_bcast_filter, kobj); /* ENOBUFS should be handled in userspace */ - if (retval == -ENOBUFS) + if (retval == -ENOBUFS || retval == -ESRCH) retval = 0; } else retval = -ENOMEM; -- cgit v1.2.3 From d58cb9cc8a46c9e539cbf8007cd5ede3c09c3524 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 23 Aug 2011 19:27:27 +0200 Subject: docs/driver-model: Document device.groups Several drivers use device_create_file() where device.groups should be used instead. This patch documents that and also removes the comments about device classes since these should not be used in new code in the way documented until now in Documentation/driver-model/device.txt. Signed-off-by: Bart Van Assche Cc: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- Documentation/driver-model/device.txt | 65 +++++++++++++++++------------------ 1 file changed, 32 insertions(+), 33 deletions(-) diff --git a/Documentation/driver-model/device.txt b/Documentation/driver-model/device.txt index bdefe728a737..1e70220d20f4 100644 --- a/Documentation/driver-model/device.txt +++ b/Documentation/driver-model/device.txt @@ -45,33 +45,52 @@ struct device_attribute { const char *buf, size_t count); }; -Attributes of devices can be exported via drivers using a simple -procfs-like interface. +Attributes of devices can be exported by a device driver through sysfs. Please see Documentation/filesystems/sysfs.txt for more information on how sysfs works. +As explained in Documentation/kobject.txt, device attributes must be be +created before the KOBJ_ADD uevent is generated. The only way to realize +that is by defining an attribute group. + Attributes are declared using a macro called DEVICE_ATTR: #define DEVICE_ATTR(name,mode,show,store) Example: -DEVICE_ATTR(power,0644,show_power,store_power); +static DEVICE_ATTR(type, 0444, show_type, NULL); +static DEVICE_ATTR(power, 0644, show_power, store_power); -This declares a structure of type struct device_attribute named -'dev_attr_power'. This can then be added and removed to the device's -directory using: +This declares two structures of type struct device_attribute with respective +names 'dev_attr_type' and 'dev_attr_power'. These two attributes can be +organized as follows into a group: -int device_create_file(struct device *device, struct device_attribute * entry); -void device_remove_file(struct device * dev, struct device_attribute * attr); +static struct attribute *dev_attrs[] = { + &dev_attr_type.attr, + &dev_attr_power.attr, + NULL, +}; -Example: +static struct attribute_group dev_attr_group = { + .attrs = dev_attrs, +}; + +static const struct attribute_group *dev_attr_groups[] = { + &dev_attr_group, + NULL, +}; + +This array of groups can then be associated with a device by setting the +group pointer in struct device before device_register() is invoked: -device_create_file(dev,&dev_attr_power); -device_remove_file(dev,&dev_attr_power); + dev->groups = dev_attr_groups; + device_register(dev); -The file name will be 'power' with a mode of 0644 (-rw-r--r--). +The device_register() function will use the 'groups' pointer to create the +device attributes and the device_unregister() function will use this pointer +to remove the device attributes. Word of warning: While the kernel allows device_create_file() and device_remove_file() to be called on a device at any time, userspace has @@ -84,24 +103,4 @@ not know about the new attributes. This is important for device driver that need to publish additional attributes for a device at driver probe time. If the device driver simply calls device_create_file() on the device structure passed to it, then -userspace will never be notified of the new attributes. Instead, it should -probably use class_create() and class->dev_attrs to set up a list of -desired attributes in the modules_init function, and then in the .probe() -hook, and then use device_create() to create a new device as a child -of the probed device. The new device will generate a new uevent and -properly advertise the new attributes to userspace. - -For example, if a driver wanted to add the following attributes: -struct device_attribute mydriver_attribs[] = { - __ATTR(port_count, 0444, port_count_show), - __ATTR(serial_number, 0444, serial_number_show), - NULL -}; - -Then in the module init function is would do: - mydriver_class = class_create(THIS_MODULE, "my_attrs"); - mydriver_class.dev_attr = mydriver_attribs; - -And assuming 'dev' is the struct device passed into the probe hook, the driver -probe function would do something like: - device_create(&mydriver_class, dev, chrdev, &private_data, "my_name"); +userspace will never be notified of the new attributes. -- cgit v1.2.3 From b7565fa3a4b84460ce1765cc468700a6bfd82746 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Tue, 23 Aug 2011 19:28:43 +0200 Subject: docs/driver-model: Update device class docs The driver model documentation was added to the kernel tree before struct class was added to . Hence this patch that updates the paragraph about struct class in Documentation/driver-model/binding.txt. Signed-off-by: Bart Van Assche Cc: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- Documentation/driver-model/binding.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Documentation/driver-model/binding.txt b/Documentation/driver-model/binding.txt index f7ec9d625bfc..abfc8e290d53 100644 --- a/Documentation/driver-model/binding.txt +++ b/Documentation/driver-model/binding.txt @@ -48,10 +48,6 @@ devclass_add_device is called to enumerate the device within the class and actually register it with the class, which happens with the class's register_dev callback. -NOTE: The device class structures and core routines to manipulate them -are not in the mainline kernel, so the discussion is still a bit -speculative. - Driver ~~~~~~ -- cgit v1.2.3 From 01dcc60a7cb8cd5193676554b94a90d349bdfd15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 25 Aug 2011 11:16:00 +0200 Subject: new helper to create platform devices with dma mask MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit compared to the most powerful and already existing helper (namely platform_device_register_resndata) this allows to specify a dma_mask. To make eventual extensions later more easy, a struct holding the used information is created instead of passing the information by function parameters. Signed-off-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 52 +++++++++++++++++++++++++---------------- include/linux/platform_device.h | 48 +++++++++++++++++++++++++++++++++++-- 2 files changed, 78 insertions(+), 22 deletions(-) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index cd7157575e58..4573f5ec9367 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -375,52 +375,64 @@ void platform_device_unregister(struct platform_device *pdev) EXPORT_SYMBOL_GPL(platform_device_unregister); /** - * platform_device_register_resndata - add a platform-level device with + * platform_device_register_full - add a platform-level device with * resources and platform-specific data * - * @parent: parent device for the device we're adding - * @name: base name of the device we're adding - * @id: instance id - * @res: set of resources that needs to be allocated for the device - * @num: number of resources - * @data: platform specific data for this platform device - * @size: size of platform specific data + * @pdevinfo: data used to create device * * Returns &struct platform_device pointer on success, or ERR_PTR() on error. */ -struct platform_device *platform_device_register_resndata( - struct device *parent, - const char *name, int id, - const struct resource *res, unsigned int num, - const void *data, size_t size) +struct platform_device *platform_device_register_full( + struct platform_device_info *pdevinfo) { int ret = -ENOMEM; struct platform_device *pdev; - pdev = platform_device_alloc(name, id); + pdev = platform_device_alloc(pdevinfo->name, pdevinfo->id); if (!pdev) - goto err; - - pdev->dev.parent = parent; + goto err_alloc; + + pdev->dev.parent = pdevinfo->parent; + + if (pdevinfo->dma_mask) { + /* + * This memory isn't freed when the device is put, + * I don't have a nice idea for that though. Conceptually + * dma_mask in struct device should not be a pointer. + * See http://thread.gmane.org/gmane.linux.kernel.pci/9081 + */ + pdev->dev.dma_mask = + kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL); + if (!pdev->dev.dma_mask) + goto err; + + *pdev->dev.dma_mask = pdevinfo->dma_mask; + pdev->dev.coherent_dma_mask = pdevinfo->dma_mask; + } - ret = platform_device_add_resources(pdev, res, num); + ret = platform_device_add_resources(pdev, + pdevinfo->res, pdevinfo->num_res); if (ret) goto err; - ret = platform_device_add_data(pdev, data, size); + ret = platform_device_add_data(pdev, + pdevinfo->data, pdevinfo->size_data); if (ret) goto err; ret = platform_device_add(pdev); if (ret) { err: + kfree(pdev->dev.dma_mask); + +err_alloc: platform_device_put(pdev); return ERR_PTR(ret); } return pdev; } -EXPORT_SYMBOL_GPL(platform_device_register_resndata); +EXPORT_SYMBOL_GPL(platform_device_register_full); static int platform_drv_probe(struct device *_dev) { diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 27bb05aae70d..651a066686ac 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -49,10 +49,54 @@ extern struct resource *platform_get_resource_byname(struct platform_device *, u extern int platform_get_irq_byname(struct platform_device *, const char *); extern int platform_add_devices(struct platform_device **, int); -extern struct platform_device *platform_device_register_resndata( +struct platform_device_info { + struct device *parent; + + const char *name; + int id; + + const struct resource *res; + unsigned int num_res; + + const void *data; + size_t size_data; + u64 dma_mask; +}; +extern struct platform_device *platform_device_register_full( + struct platform_device_info *pdevinfo); + +/** + * platform_device_register_resndata - add a platform-level device with + * resources and platform-specific data + * + * @parent: parent device for the device we're adding + * @name: base name of the device we're adding + * @id: instance id + * @res: set of resources that needs to be allocated for the device + * @num: number of resources + * @data: platform specific data for this platform device + * @size: size of platform specific data + * + * Returns &struct platform_device pointer on success, or ERR_PTR() on error. + */ +static inline struct platform_device *platform_device_register_resndata( struct device *parent, const char *name, int id, const struct resource *res, unsigned int num, - const void *data, size_t size); + const void *data, size_t size) { + + struct platform_device_info pdevinfo = { + .parent = parent, + .name = name, + .id = id, + .res = res, + .num_res = num, + .data = data, + .size_data = size, + .dma_mask = 0, + }; + + return platform_device_register_full(&pdevinfo); +} /** * platform_device_register_simple - add a platform-level device and its resources -- cgit v1.2.3 From 0e392412f334c80baedb30a29796a256b0d5e629 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 25 Aug 2011 11:16:01 +0200 Subject: ARM: mxc: convert device creation to use platform_device_reg