Commit 2d03423b authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'driver-core-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core

* 'driver-core-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (38 commits)
  mm: memory hotplug: Check if pages are correctly reserved on a per-section basis
  Revert "memory hotplug: Correct page reservation checking"
  Update email address for stable patch submission
  dynamic_debug: fix undefined reference to `__netdev_printk'
  dynamic_debug: use a single printk() to emit messages
  dynamic_debug: remove num_enabled accounting
  dynamic_debug: consolidate repetitive struct _ddebug descriptor definitions
  uio: Support physical addresses >32 bits on 32-bit systems
  sysfs: add unsigned long cast to prevent compile warning
  drivers: base: print rejected matches with DEBUG_DRIVER
  memory hotplug: Correct page reservation checking
  memory hotplug: Refuse to add unaligned memory regions
  remove the messy code file Documentation/zh_CN/SubmitChecklist
  ARM: mxc: convert device creation to use platform_device_register_full
  new helper to create platform devices with dma mask
  docs/driver-model: Update device class docs
  docs/driver-model: Document device.groups
  kobj_uevent: Ignore if some listeners cannot handle message
  dynamic_debug: make netif_dbg() call __netdev_printk()
  dynamic_debug: make netdev_dbg() call __netdev_printk()
  ...
parents 59e52534 2bbcb878
...@@ -529,7 +529,7 @@ memory (e.g. allocated with <function>kmalloc()</function>). There's also ...@@ -529,7 +529,7 @@ memory (e.g. allocated with <function>kmalloc()</function>). There's also
</para></listitem> </para></listitem>
<listitem><para> <listitem><para>
<varname>unsigned long addr</varname>: Required if the mapping is used. <varname>phys_addr_t addr</varname>: Required if the mapping is used.
Fill in the address of your memory block. This address is the one that Fill in the address of your memory block. This address is the one that
appears in sysfs. appears in sysfs.
</para></listitem> </para></listitem>
......
...@@ -48,10 +48,6 @@ devclass_add_device is called to enumerate the device within the class ...@@ -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 and actually register it with the class, which happens with the
class's register_dev callback. 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 Driver
~~~~~~ ~~~~~~
......
...@@ -45,33 +45,52 @@ struct device_attribute { ...@@ -45,33 +45,52 @@ struct device_attribute {
const char *buf, size_t count); const char *buf, size_t count);
}; };
Attributes of devices can be exported via drivers using a simple Attributes of devices can be exported by a device driver through sysfs.
procfs-like interface.
Please see Documentation/filesystems/sysfs.txt for more information Please see Documentation/filesystems/sysfs.txt for more information
on how sysfs works. 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: Attributes are declared using a macro called DEVICE_ATTR:
#define DEVICE_ATTR(name,mode,show,store) #define DEVICE_ATTR(name,mode,show,store)
Example: 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 This declares two structures of type struct device_attribute with respective
'dev_attr_power'. This can then be added and removed to the device's names 'dev_attr_type' and 'dev_attr_power'. These two attributes can be
directory using: organized as follows into a group:
int device_create_file(struct device *device, struct device_attribute * entry); static struct attribute *dev_attrs[] = {
void device_remove_file(struct device * dev, struct device_attribute * attr); &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); dev->groups = dev_attr_groups;
device_remove_file(dev,&dev_attr_power); 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 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 device_remove_file() to be called on a device at any time, userspace has
...@@ -84,24 +103,4 @@ not know about the new attributes. ...@@ -84,24 +103,4 @@ not know about the new attributes.
This is important for device driver that need to publish additional This is important for device driver that need to publish additional
attributes for a device at driver probe time. If the device driver simply 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 calls device_create_file() on the device structure passed to it, then
userspace will never be notified of the new attributes. Instead, it should userspace will never be notified of the new attributes.
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");
...@@ -4,7 +4,7 @@ sysfs - _The_ filesystem for exporting kernel objects. ...@@ -4,7 +4,7 @@ sysfs - _The_ filesystem for exporting kernel objects.
Patrick Mochel <mochel@osdl.org> Patrick Mochel <mochel@osdl.org>
Mike Murphy <mamurph@cs.clemson.edu> Mike Murphy <mamurph@cs.clemson.edu>
Revised: 15 July 2010 Revised: 16 August 2011
Original: 10 January 2003 Original: 10 January 2003
...@@ -370,3 +370,11 @@ int driver_create_file(struct device_driver *, const struct driver_attribute *); ...@@ -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 *); 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.
...@@ -24,10 +24,10 @@ Rules on what kind of patches are accepted, and which ones are not, into the ...@@ -24,10 +24,10 @@ Rules on what kind of patches are accepted, and which ones are not, into the
Procedure for submitting patches to the -stable tree: Procedure for submitting patches to the -stable tree:
- Send the patch, after verifying that it follows the above rules, to - Send the patch, after verifying that it follows the above rules, to
stable@kernel.org. You must note the upstream commit ID in the changelog stable@vger.kernel.org. You must note the upstream commit ID in the
of your submission. changelog of your submission.
- To have the patch automatically included in the stable tree, add the tag - To have the patch automatically included in the stable tree, add the tag
Cc: stable@kernel.org Cc: stable@vger.kernel.org
in the sign-off area. Once the patch is merged it will be applied to in the sign-off area. Once the patch is merged it will be applied to
the stable tree without anything else needing to be done by the author the stable tree without anything else needing to be done by the author
or subsystem maintainer. or subsystem maintainer.
...@@ -35,10 +35,10 @@ Procedure for submitting patches to the -stable tree: ...@@ -35,10 +35,10 @@ Procedure for submitting patches to the -stable tree:
cherry-picked than this can be specified in the following format in cherry-picked than this can be specified in the following format in
the sign-off area: the sign-off area:
Cc: <stable@kernel.org> # .32.x: a1f84a3: sched: Check for idle Cc: <stable@vger.kernel.org> # .32.x: a1f84a3: sched: Check for idle
Cc: <stable@kernel.org> # .32.x: 1b9508f: sched: Rate-limit newidle Cc: <stable@vger.kernel.org> # .32.x: 1b9508f: sched: Rate-limit newidle
Cc: <stable@kernel.org> # .32.x: fd21073: sched: Fix affinity logic Cc: <stable@vger.kernel.org> # .32.x: fd21073: sched: Fix affinity logic
Cc: <stable@kernel.org> # .32.x Cc: <stable@vger.kernel.org> # .32.x
Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Ingo Molnar <mingo@elte.hu>
The tag sequence has the meaning of: The tag sequence has the meaning of:
......
Chinese translated version of Documentation/SubmitChecklist
If you have any comment or update to the content, please contact the
original document maintainer directly. However, if you have a problem
communicating in English you can also ask the Chinese maintainer for
help. Contact the Chinese maintainer if this translation is outdated
or if there is a problem with the translation.
Chinese maintainer: Harry Wei <harryxiyou@gmail.com>
---------------------------------------------------------------------
Documentation/SubmitChecklist 的中文翻译
如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文
交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻
译存在问题,请联系中文版维护者。
中文版维护者: 贾威威 Harry Wei <harryxiyou@gmail.com>
中文版翻译者: 贾威威 Harry Wei <harryxiyou@gmail.com>
中文版校译者: 贾威威 Harry Wei <harryxiyou@gmail.com>
以下为正文
---------------------------------------------------------------------
Linux内核提交清单
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
这里有一些内核开发者应该做的基本事情,如果他们想看到自己的内核补丁提交
被接受的更快。
这些都是超出Documentation/SubmittingPatches文档里所提供的以及其他
关于提交Linux内核补丁的说明。
1:如果你使用了一个功能那么就#include定义/声明那个功能的那个文件。
不要依靠其他间接引入定义/声明那个功能的头文件。
2:构建简洁适用或者更改CONFIG选项 =y,=m,或者=n。
不要有编译警告/错误, 不要有链接警告/错误。
2b:通过 allnoconfig, allmodconfig
2c:当使用 0=builddir 成功地构建
3:通过使用本地交叉编译工具或者其他一些构建产所,在多CPU框架上构建。
4:ppc64 是一个很好的检查交叉编译的框架,因为它往往把‘unsigned long’
当64位值来使用。
5:按照Documentation/CodingStyle文件里的详细描述,检查你补丁的整体风格。
使用补丁风格检查琐碎的违规(scripts/checkpatch.pl),审核员优先提交。
你应该调整遗留在你补丁中的所有违规。
6:任何更新或者改动CONFIG选项都不能打乱配置菜单。
7:所有的Kconfig选项更新都要有说明文字。
8:已经认真地总结了相关的Kconfig组合。这是很难通过测试做好的--脑力在这里下降。
9:检查具有简洁性。
10:使用'make checkstack'和'make namespacecheck'检查,然后修改所找到的问题。
注意:堆栈检查不会明确地出现问题,但是任何的一个函数在堆栈上使用多于512字节
都要准备修改。
11:包含kernel-doc到全局内核APIs文件。(不要求静态的函数,但是包含也无所谓。)
使用'make htmldocs'或者'make mandocs'来检查kernel-doc,然后修改任何
发现的问题。
12:已经通过CONFIG_PREEMPT, CONFIG_DEBUG_PREEMPT,
CONFIG_DEBUG_SLAB, CONFIG_DEBUG_PAGEALLOC, CONFIG_DEBUG_MUTEXES,
CONFIG_DEBUG_SPINLOCK, CONFIG_DEBUG_ATOMIC_SLEEP测试,并且同时都
使能。
13:已经都构建并且使用或者不使用 CONFIG_SMP 和 CONFIG_PREEMPT测试执行时间。
14:如果补丁影响IO/Disk,等等:已经通过使用或者不使用 CONFIG_LBDAF 测试。
15:所有的codepaths已经行使所有lockdep启用功能。
16:所有的/proc记录更新都要作成文件放在Documentation/目录下。
17:所有的内核启动参数更新都被记录到Documentation/kernel-parameters.txt文件中。
18:所有的模块参数更新都用MODULE_PARM_DESC()记录。
19:所有的用户空间接口更新都被记录到Documentation/ABI/。查看Documentation/ABI/README
可以获得更多的信息。改变用户空间接口的补丁应该被邮件抄送给linux-api@vger.kernel.org。
20:检查它是不是都通过`make headers_check'。
21:已经通过至少引入slab和page-allocation失败检查。查看Documentation/fault-injection/。
22:新加入的源码已经通过`gcc -W'(使用"make EXTRA_CFLAGS=-W")编译。这样将产生很多烦恼,
但是对于寻找漏洞很有益处,例如:"warning: comparison between signed and unsigned"。
23:当它被合并到-mm补丁集后再测试,用来确定它是否还和补丁队列中的其他补丁一起工作以及在VM,VFS
和其他子系统中各个变化。
24:所有的内存屏障{e.g., barrier(), rmb(), wmb()}需要在源代码中的一个注释来解释他们都是干什么的
以及原因。
25:如果有任何输入输出控制的补丁被添加,也要更新Documentation/ioctl/ioctl-number.txt。
26:如果你的更改代码依靠或者使用任何的内核APIs或者与下面的kconfig符号有关系的功能,你就要
使用相关的kconfig符号关闭, and/or =m(如果选项提供)[在同一时间不是所用的都启用,仅仅各个或者自由
组合他们]:
CONFIG_SMP, CONFIG_SYSFS, CONFIG_PROC_FS, CONFIG_INPUT, CONFIG_PCI,
CONFIG_BLOCK, CONFIG_PM, CONFIG_HOTPLUG, CONFIG_MAGIC_SYSRQ,
CONFIG_NET, CONFIG_INET=n (后一个使用 CONFIG_NET=y)
...@@ -2294,6 +2294,12 @@ L: netdev@vger.kernel.org ...@@ -2294,6 +2294,12 @@ L: netdev@vger.kernel.org
S: Maintained S: Maintained
F: drivers/net/wan/dscc4.c F: drivers/net/wan/dscc4.c
DYNAMIC DEBUG
M: Jason Baron <jbaron@redhat.com>
S: Maintained
F: lib/dynamic_debug.c
F: include/linux/dynamic_debug.h
DZ DECSTATION DZ11 SERIAL DRIVER DZ DECSTATION DZ11 SERIAL DRIVER
M: "Maciej W. Rozycki" <macro@linux-mips.org> M: "Maciej W. Rozycki" <macro@linux-mips.org>
S: Maintained S: Maintained
......
...@@ -37,59 +37,6 @@ int __init mxc_register_device(struct platform_device *pdev, void *data) ...@@ -37,59 +37,6 @@ int __init mxc_register_device(struct platform_device *pdev, void *data)
return ret; return ret;
} }
struct platform_device *__init imx_add_platform_device_dmamask(
const char *name, int id,
const struct resource *res, unsigned int num_resources,
const void *data, size_t size_data, u64 dmamask)
{
int ret = -ENOMEM;
struct platform_device *pdev;
pdev = platform_device_alloc(name, id);
if (!pdev)
goto err;
if (dmamask) {
/*
* 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)
/* ret is still -ENOMEM; */
goto err;
*pdev->dev.dma_mask = dmamask;
pdev->dev.coherent_dma_mask = dmamask;
}
if (res) {
ret = platform_device_add_resources(pdev, res, num_resources);
if (ret)
goto err;
}
if (data) {
ret = platform_device_add_data(pdev, data, size_data);
if (ret)
goto err;
}
ret = platform_device_add(pdev);
if (ret) {
err:
if (dmamask)
kfree(pdev->dev.dma_mask);
platform_device_put(pdev);
return ERR_PTR(ret);
}
return pdev;
}
struct device mxc_aips_bus = { struct device mxc_aips_bus = {
.init_name = "mxc_aips", .init_name = "mxc_aips",
.parent = &platform_bus, .parent = &platform_bus,
......
...@@ -14,10 +14,22 @@ ...@@ -14,10 +14,22 @@
extern struct device mxc_aips_bus; extern struct device mxc_aips_bus;
extern struct device mxc_ahb_bus; extern struct device mxc_ahb_bus;
struct platform_device *imx_add_platform_device_dmamask( static inline struct platform_device *imx_add_platform_device_dmamask(
const char *name, int id, const char *name, int id,
const struct resource *res, unsigned int num_resources, const struct resource *res, unsigned int num_resources,
const void *data, size_t size_data, u64 dmamask); const void *data, size_t size_data, u64 dmamask)
{
struct platform_device_info pdevinfo = {
.name = name,
.id = id,
.res = res,
.num_res = num_resources,
.data = data,
.size_data = size_data,
.dma_mask = dmamask,
};
return platform_device_register_full(&pdevinfo);
}
static inline struct platform_device *imx_add_platform_device( static inline struct platform_device *imx_add_platform_device(
const char *name, int id, const char *name, int id,
......
...@@ -1764,8 +1764,8 @@ void device_shutdown(void) ...@@ -1764,8 +1764,8 @@ void device_shutdown(void)
#ifdef CONFIG_PRINTK #ifdef CONFIG_PRINTK
static int __dev_printk(const char *level, const struct device *dev, int __dev_printk(const char *level, const struct device *dev,
struct va_format *vaf) struct va_format *vaf)
{ {
if (!dev) if (!dev)
return printk("%s(NULL device *): %pV", level, vaf); return printk("%s(NULL device *): %pV", level, vaf);
...@@ -1773,6 +1773,7 @@ static int __dev_printk(const char *level, const struct device *dev, ...@@ -1773,6 +1773,7 @@ static int __dev_printk(const char *level, const struct device *dev,
return printk("%s%s %s: %pV", return printk("%s%s %s: %pV",
level, dev_driver_string(dev), dev_name(dev), vaf); level, dev_driver_string(dev), dev_name(dev), vaf);
} }
EXPORT_SYMBOL(__dev_printk);
int dev_printk(const char *level, const struct device *dev, int dev_printk(const char *level, const struct device *dev,
const char *fmt, ...) const char *fmt, ...)
......
...@@ -147,6 +147,9 @@ static int really_probe(struct device *dev, struct device_driver *drv) ...@@ -147,6 +147,9 @@ static int really_probe(struct device *dev, struct device_driver *drv)
printk(KERN_WARNING printk(KERN_WARNING
"%s: probe of %s failed with error %d\n", "%s: probe of %s failed with error %d\n",
drv->name, dev_name(dev), ret); drv->name, dev_name(dev), ret);
} else {
pr_debug("%s: probe of %s rejects match %d\n",
drv->name, dev_name(dev), ret);
} }
/* /*
* Ignore errors returned by ->probe so that the next driver can try * Ignore errors returned by ->probe so that the next driver can try
......
...@@ -223,6 +223,42 @@ int memory_isolate_notify(unsigned long val, void *v) ...@@ -223,6 +223,42 @@ int memory_isolate_notify(unsigned long val, void *v)
return atomic_notifier_call_chain(&memory_isolate_chain, val, v); return atomic_notifier_call_chain(&memory_isolate_chain, val, v);
} }
/*
* The probe routines leave the pages reserved, just as the bootmem code does.
* Make sure they're still that way.
*/
static bool pages_correctly_reserved(unsigned long start_pfn,
unsigned long nr_pages)
{
int i, j;
struct page *page;
unsigned long pfn = start_pfn;
/*
* memmap between sections is not contiguous except with
* SPARSEMEM_VMEMMAP. We lookup the page once per section
* and assume memmap is contiguous within each section
*/
for (i = 0; i < sections_per_block; i++, pfn += PAGES_PER_SECTION) {
if (WARN_ON_ONCE(!pfn_valid(pfn)))
return false;
page = pfn_to_page(pfn);
for (j = 0; j < PAGES_PER_SECTION; j++) {
if (PageReserved(page + j))
continue;
printk(KERN_WARNING "section number %ld page number %d "
"not reserved, was it already online?\n",
pfn_to_section_nr(pfn), j);
return false;
}
}
return true;
}
/* /*
* MEMORY_HOTPLUG depends on SPARSEMEM in mm/Kconfig, so it is * MEMORY_HOTPLUG depends on SPARSEMEM in mm/Kconfig, so it is
* OK to have direct references to sparsemem variables in here. * OK to have direct references to sparsemem variables in here.
...@@ -230,7 +266,6 @@ int memory_isolate_notify(unsigned long val, void *v) ...@@ -230,7 +266,6 @@ int memory_isolate_notify(unsigned long val, void *v)
static int static int
memory_block_action(unsigned long phys_index, unsigned long action) memory_block_action(unsigned long phys_index, unsigned long action)
{ {
int i;
unsigned long start_pfn, start_paddr; unsigned long start_pfn, start_paddr;
unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block; unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block;
struct page *first_page; struct page *first_page;
...@@ -238,26 +273,13 @@ memory_block_action(unsigned long phys_index, unsigned long action) ...@@ -238,26 +273,13 @@ memory_block_action(unsigned long phys_index, unsigned long action)
first_page = pfn_to_page(phys_index << PFN_SECTION_SHIFT); first_page = pfn_to_page(phys_index << PFN_SECTION_SHIFT);
/*
* The probe routines leave the pages reserved, just
* as the bootmem code does. Make sure they're still
* that way.
*/
if (action == MEM_ONLINE) {
for (i = 0; i < nr_pages; i++) {
if (PageReserved(first_page+i))
continue;
printk(KERN_WARNING "section number %ld page number %d "
"not reserved, was it already online?\n",
phys_index, i);
return -EBUSY;
}
}
switch (action) { switch (action) {
case MEM_ONLINE: case MEM_ONLINE:
start_pfn = page_to_pfn(first_page); start_pfn = page_to_pfn(first_page);
if (!pages_correctly_reserved(start_pfn, nr_pages))
return -EBUSY;
ret = online_pages(start_pfn, nr_pages); ret = online_pages(start_pfn, nr_pages);
break; break;
case MEM_OFFLINE: case MEM_OFFLINE:
...@@ -380,9 +402,13 @@ memory_probe_store(struct class *class, struct class_attribute *attr, ...@@ -380,9 +402,13 @@ memory_probe_store(struct class *class, struct class_attribute *attr,
u64 phys_addr; u64 phys_addr;
int nid; int nid;
int i, ret; int i, ret;
unsigned long pages_per_block = PAGES_PER_SECTION * sections_per_block;
phys_addr = simple_strtoull(buf, NULL, 0); phys_addr = simple_strtoull(buf, NULL, 0);
if (phys_addr & ((pages_per_block << PAGE_SHIFT) - 1))
return -EINVAL;
for (i = 0; i < sections_per_block; i++) { for (i = 0; i < sections_per_block; i++) {
nid = memory_add_physaddr_to_nid(phys_addr); nid = memory_add_physaddr_to_nid(phys_addr);
ret = add_memory(nid, phys_addr, ret = add_memory(nid, phys_addr,
......
...@@ -375,52 +375,64 @@ void platform_device_unregister(struct platform_device *pdev) ...@@ -375,52 +375,64 @@ void platform_device_unregister(struct platform_device *pdev)
EXPORT_SYMBOL_GPL(platform_device_unregister); 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 * resources and platform-specific data
* *
* @parent: parent device for the device we're adding * @pdevinfo: data used to create device
* @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. * Returns &struct platform_device pointer on success, or ERR_PTR() on error.
*/ */
struct platform_device *platform_device_register_resndata( struct platform_device *platform_device_register_full(
struct device *parent, struct platform_device_info *pdevinfo)
const char *name, int id,
const struct resource *res, unsigned int num,
const void *data, size_t size)
{ {
int ret = -ENOMEM; int ret = -ENOMEM;
struct platform_device *pdev; struct platform_device *pdev;
pdev = platform_device_alloc(name, id); pdev = platform_device_alloc(pdevinfo->name, pdevinfo->id);
if (!pdev) if (!pdev)
goto err; goto err_alloc;
pdev->dev.parent = parent; 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) if (ret)
goto err; goto err;
ret = platform_device_add_data(pdev, data, size); ret = platform_device_add_data(pdev,
pdevinfo->data, pdevinfo->size_data);
if (ret) if (ret)
goto err; goto err;
ret = platform_device_add(pdev); ret = platform_device_add(pdev);
if (ret) { if (ret) {
err: err:
kfree(pdev->dev.dma_mask);
err_alloc:
platform_device_put(pdev); platform_device_put(pdev);
return ERR_PTR(ret); return ERR_PTR(ret);
} }
return pdev; return pdev;
} }
EXPORT_SYMBOL_GPL(platform_device_register_resndata); EXPORT_SYMBOL_GPL(platform_device_register_full);
static int platform_drv_probe(struct device *_dev) static int platform_drv_probe(struct device *_dev)
{ {
...@@ -614,7 +626,7 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env) ...@@ -614,7 +626,7 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env)
return rc; return rc;
add_uevent_var(env, "MODALIAS=%s%s", PLATFORM_MODULE_PREFIX, add_uevent_var(env, "MODALIAS=%s%s", PLATFORM_MODULE_PREFIX,
(pdev->id_entry) ? pdev->id_entry->name : pdev->name); pdev->name);
return 0; return 0;
} }
......
...@@ -90,6 +90,7 @@ ...@@ -90,6 +90,7 @@
#define PCH_PHUB_INTPIN_REG_WPERMIT_REG3 0x002C #define PCH_PHUB_INTPIN_REG_WPERMIT_REG3 0x002C
#define PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE 0x0040 #define PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE 0x0040
#define CLKCFG_REG_OFFSET 0x500 #define CLKCFG_REG_OFFSET 0x500
#define FUNCSEL_REG_OFFSET 0x508
#define PCH_PHUB_OROM_SIZE 15360 #define PCH_PHUB_OROM_SIZE 15360
...@@ -108,6 +109,7 @@ ...@@ -108,6 +109,7 @@
* @intpin_reg_wpermit_reg3: INTPIN_REG_WPERMIT register 3 val * @intpin_reg_wpermit_reg3: INTPIN_REG_WPERMIT register 3 val
* @int_reduce_control_reg: INT_REDUCE_CONTROL registers val * @int_reduce_control_reg: INT_REDUCE_CONTROL registers val
* @clkcfg_reg: CLK CFG register val * @clkcfg_reg: CLK CFG register val
* @funcsel_reg: Function select register value
* @pch_phub_base_address: Register base address * @pch_phub_base_address: Register base address
* @pch_phub_extrom_base_address: external rom base address * @pch_phub_extrom_base_address: external rom base address
* @pch_mac_start_address: MAC address area start address * @pch_mac_start_address: MAC address area start address
...@@ -128,6 +130,7 @@ struct pch_phub_reg { ...@@ -128,6 +130,7 @@ struct pch_phub_reg {
u32 intpin_reg_wpermit_reg3; u32 intpin_reg_wpermit_reg3;
u32 int_reduce_control_reg[MAX_NUM_INT_REDUCE_CONTROL_REG]; u32 int_reduce_control_reg[MAX_NUM_INT_REDUCE_CONTROL_REG];
u32 clkcfg_reg; u32 clkcfg_reg;
u32 funcsel_reg;
void __iomem *pch_phub_base_address; void __iomem *pch_phub_base_address;
void __iomem *pch_phub_extrom_base_address; void __iomem *pch_phub_extrom_base_address;
u32 pch_mac_start_address; u32 pch_mac_start_address;
...@@ -211,6 +214,8 @@ static void pch_phub_save_reg_conf(struct pci_dev *pdev) ...@@ -211,6 +214,8 @@ static void pch_phub_save_reg_conf(struct pci_dev *pdev)
__func__, i, chip->int_reduce_control_reg[i]); __func__, i, chip->int_reduce_control_reg[i]);
} }
chip->clkcfg_reg = ioread32(p + CLKCFG_REG_OFFSET); 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 */ /* pch_phub_restore_reg_conf - restore register configuration */
...@@ -271,6 +276,8 @@ static void pch_phub_restore_reg_conf(struct pci_dev *pdev) ...@@ -271,6 +276,8 @@ static void pch_phub_restore_reg_conf(struct pci_dev *pdev)
} }
iowrite32(chip->clkcfg_reg, p + CLKCFG_REG_OFFSET); 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);
} }
/** /**
...@@ -594,8 +601,7 @@ static ssize_t show_pch_mac(struct device *dev, struct device_attribute *attr, ...@@ -594,8 +601,7 @@ static ssize_t show_pch_mac(struct device *dev, struct device_attribute *attr,
pch_phub_read_gbe_mac_addr(chip, mac); pch_phub_read_gbe_mac_addr(chip, mac);
return sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n", return sprintf(buf, "%pM\n", mac);
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
} }
static ssize_t store_pch_mac(struct device *dev, struct device_attribute *attr, static ssize_t store_pch_mac(struct device *dev, struct device_attribute *attr,
......
...@@ -69,7 +69,7 @@ static ssize_t map_name_show(struct uio_mem *mem, char *buf) ...@@ -69,7 +69,7 @@ static ssize_t map_name_show(struct uio_mem *mem, char *buf)
static ssize_t map_addr_show(struct uio_mem *mem, char *buf) static ssize_t map_addr_show(struct uio_mem *mem, char *buf)
{ {
return sprintf(buf, "0x%lx\n", mem->addr); return sprintf(buf, "0x%llx\n", (unsigned long long)mem->addr);
} }
static ssize_t map_size_show(struct uio_mem *mem, char *buf) static ssize_t map_size_show(struct uio_mem *mem, char *buf)
...@@ -79,7 +79,7 @@ static ssize_t map_size_show(struct uio_mem *mem, char *buf) ...@@ -79,7 +79,7 @@ static ssize_t map_size_show(struct uio_mem *mem, char *buf)
static ssize_t map_offset_show(struct uio_mem *mem, char *buf) static ssize_t map_offset_show(struct uio_mem *mem, char *buf)
{ {
return sprintf(buf, "0x%lx\n", mem->addr & ~PAGE_MASK); return sprintf(buf, "0x%llx\n", (unsigned long long)mem->addr & ~PAGE_MASK);
} }
struct map_sysfs_entry { struct map_sysfs_entry {
...@@ -634,8 +634,7 @@ static int uio_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) ...@@ -634,8 +634,7 @@ static int uio_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
if (idev->info->mem[mi].memtype == UIO_MEM_LOGICAL) if (idev->info->mem[mi].memtype == UIO_MEM_LOGICAL)
page = virt_to_page(idev->info->mem[mi].addr + offset); page = virt_to_page(idev->info->mem[mi].addr + offset);
else else
page = vmalloc_to_page((void *)idev->info->mem[mi].addr page = vmalloc_to_page((void *)(unsigned long)idev->info->mem[mi].addr + offset);
+ offset);
get_page(page); get_page(page);
vmf->page = page; vmf->page = page;
return 0; return 0;
...@@ -750,14 +749,13 @@ static int uio_major_init(void) ...@@ -750,14 +749,13 @@ static int uio_major_init(void)
uio_major = MAJOR(uio_dev); uio_major = MAJOR(uio_dev);
uio_cdev = cdev; uio_cdev = cdev;
result = 0; return 0;
out:
return result;
out_put: out_put:
kobject_put(&cdev->kobj); kobject_put(&cdev->kobj);
out_unregister: out_unregister:
unregister_chrdev_region(uio_dev, UIO_MAX_DEVICES); unregister_chrdev_region(uio_dev, UIO_MAX_DEVICES);
goto out; out:
return result;
} }
static void uio_major_cleanup(void) static void uio_major_cleanup(void)
......
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/uio_driver.h> #include <linux/uio_driver.h>
#include <linux/spinlock.h>
#define DRIVER_VERSION "0.01.0" #define DRIVER_VERSION "0.01.0"
#define DRIVER_AUTHOR "Michael S. Tsirkin <mst@redhat.com>" #define DRIVER_AUTHOR "Michael S. Tsirkin <mst@redhat.com>"
...@@ -33,7 +32,6 @@ ...@@ -33,7 +32,6 @@
struct uio_pci_generic_dev { struct uio_pci_generic_dev {
struct uio_info info; struct uio_info info;
struct pci_dev *pdev; struct pci_dev *pdev;
spinlock_t lock; /* guards command register accesses */
}; };
static inline struct uio_pci_generic_dev * static inline struct uio_pci_generic_dev *
...@@ -57,7 +55,6 @@ static irqreturn_t irqhandler(int irq, struct uio_info *info) ...@@ -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 % 4);
BUILD_BUG_ON(PCI_COMMAND + 2 != PCI_STATUS); BUILD_BUG_ON(PCI_COMMAND + 2 != PCI_STATUS);
spin_lock_irq(&gdev->lock);
pci_block_user_cfg_access(pdev); pci_block_user_cfg_access(pdev);
/* Read both command and status registers in a single 32-bit operation. /* 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) ...@@ -83,7 +80,6 @@ static irqreturn_t irqhandler(int irq, struct uio_info *info)
done: done:
pci_unblock_user_cfg_access(pdev); pci_unblock_user_cfg_access(pdev);
spin_unlock_irq(&gdev->lock);
return ret; return ret;
} }
...@@ -158,7 +154,6 @@ static int __devinit probe(struct pci_dev *pdev, ...@@ -158,7 +154,6 @@ static int __devinit probe(struct pci_dev *pdev,
gdev->info.irq_flags = IRQF_SHARED; gdev->info.irq_flags = IRQF_SHARED;
gdev->info.handler = irqhandler; gdev->info.handler = irqhandler;
gdev->pdev = pdev; gdev->pdev = pdev;
spin_lock_init(&gdev->lock);
if (uio_register_device(&pdev->dev, &gdev->info)) if (uio_register_device(&pdev->dev, &gdev->info))
goto err_register; goto err_register;
......
...@@ -253,7 +253,7 @@ static const struct dev_pm_ops uio_pdrv_genirq_dev_pm_ops = { ...@@ -253,7 +253,7 @@ static const struct dev_pm_ops uio_pdrv_genirq_dev_pm_ops = {
}; };
#ifdef CONFIG_OF #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 */ }, { /* empty for now */ },
}; };
MODULE_DEVICE_TABLE(of, uio_of_genirq_match); MODULE_DEVICE_TABLE(of, uio_of_genirq_match);
......
/* /*
* 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 <greg@kroah.com> * Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com>
* Copyright (C) 2004 IBM Inc. * Copyright (C) 2004 IBM Inc.
......
...@@ -43,20 +43,48 @@ static DEFINE_IDA(sysfs_ino_ida); ...@@ -43,20 +43,48 @@ static DEFINE_IDA(sysfs_ino_ida);
static void sysfs_link_sibling(struct sysfs_dirent *sd) static void sysfs_link_sibling(struct sysfs_dirent *sd)
{ {
struct sysfs_dirent *parent_sd = sd->s_parent; struct sysfs_dirent *parent_sd = sd->s_parent;
struct sysfs_dirent **pos;
BUG_ON(sd->s_sibling); struct rb_node **p;
struct rb_node *parent;
/* Store directory entries in order by ino. This allows
* readdir to properly restart without having to add a if (sysfs_type(sd) == SYSFS_DIR)
* cursor into the s_dir.children list. parent_sd->s_dir.subdirs++;
*/
for (pos = &parent_sd->s_dir.children; *pos; pos = &(*pos)->s_sibling) { p = &parent_sd->s_dir.inode_tree.rb_node;
if (sd->s_ino < (*pos)->s_ino) parent = NULL;
break; 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",
(unsigned long) sd->s_ino);
BUG();
}
#undef node
} }
sd->s_sibling = *pos; rb_link_node(&sd->inode_node, parent, p);
*pos = sd; rb_insert_color(&sd->inode_node, &parent_sd->s_dir.inode_tree);
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);
} }
/** /**
...@@ -71,16 +99,11 @@ static void sysfs_link_sibling(struct sysfs_dirent *sd) ...@@ -71,16 +99,11 @@ static void sysfs_link_sibling(struct sysfs_dirent *sd)
*/ */
static void sysfs_unlink_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; rb_erase(&sd->inode_node, &sd->s_parent->s_dir.inode_tree);
pos = &(*pos)->s_sibling) { rb_erase(&sd->name_node, &sd->s_parent->s_dir.name_tree);
if (*pos == sd) {
*pos = sd->s_sibling;
sd->s_sibling = NULL;
break;
}
}
} }
/** /**
...@@ -126,7 +149,6 @@ struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd) ...@@ -126,7 +149,6 @@ struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd)
*/ */
void sysfs_put_active(struct sysfs_dirent *sd) void sysfs_put_active(struct sysfs_dirent *sd)
{ {
struct completion *cmpl;
int v; int v;
if (unlikely(!sd)) if (unlikely(!sd))
...@@ -138,10 +160,9 @@ void sysfs_put_active(struct sysfs_dirent *sd) ...@@ -138,10 +160,9 @@ void sysfs_put_active(struct sysfs_dirent *sd)
return; return;
/* atomic_dec_return() is a mb(), we'll always see the updated /* atomic_dec_return() is a mb(), we'll always see the updated
* sd->s_sibling. * sd->u.completion.
*/ */
cmpl = (void *)sd->s_sibling; complete(sd->u.completion);
complete(cmpl);
} }
/** /**
...@@ -155,16 +176,16 @@ static void sysfs_deactivate(struct sysfs_dirent *sd) ...@@ -155,16 +176,16 @@ static void sysfs_deactivate(struct sysfs_dirent *sd)
DECLARE_COMPLETION_ONSTACK(wait); DECLARE_COMPLETION_ONSTACK(wait);
int v; 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)) if (!(sysfs_type(sd) & SYSFS_ACTIVE_REF))
return; return;
sd->s_sibling = (void *)&wait; sd->u.completion = (void *)&wait;
rwsem_acquire(&sd->dep_map, 0, 0, _RET_IP_); rwsem_acquire(&sd->dep_map, 0, 0, _RET_IP_);
/* atomic_add_return() is a mb(), put_active() will always see /* 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); v = atomic_add_return(SD_DEACTIVATED_BIAS, &sd->s_active);
...@@ -173,8 +194,6 @@ static void sysfs_deactivate(struct sysfs_dirent *sd) ...@@ -173,8 +194,6 @@ static void sysfs_deactivate(struct sysfs_dirent *sd)
wait_for_completion(&wait); wait_for_completion(&wait);
} }
sd->s_sibling = NULL;
lock_acquired(&sd->dep_map, _RET_IP_); lock_acquired(&sd->dep_map, _RET_IP_);
rwsem_release(&sd->dep_map, 1, _RET_IP_); rwsem_release(&sd->dep_map, 1, _RET_IP_);
} }
...@@ -490,7 +509,7 @@ void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) ...@@ -490,7 +509,7 @@ void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
} }
sd->s_flags |= SYSFS_FLAG_REMOVED; sd->s_flags |= SYSFS_FLAG_REMOVED;
sd->s_sibling = acxt->removed; sd->u.removed_list = acxt->removed;
acxt->removed = sd; acxt->removed = sd;
} }
...@@ -514,8 +533,7 @@ void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt) ...@@ -514,8 +533,7 @@ void sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt)
while (acxt->removed) { while (acxt->removed) {
struct sysfs_dirent *sd = acxt->removed; struct sysfs_dirent *sd = acxt->removed;
acxt->removed = sd->s_sibling; acxt->removed = sd->u.removed_list;
sd->s_sibling = NULL;
sysfs_deactivate(sd); sysfs_deactivate(sd);
unmap_bin_file(sd); unmap_bin_file(sd);
...@@ -540,15 +558,36 @@ struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, ...@@ -540,15 +558,36 @@ struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd,
const void *ns, const void *ns,
const unsigned char *name) 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 (found && ns) {
if (ns && sd->s_ns && (sd->s_ns != ns)) while (found->s_ns && found->s_ns != ns) {
continue; p = rb_next(&found->name_node);
if (!strcmp(sd->s_name, name)) if (!p)
return sd; return NULL;
found = rb_entry(p, struct sysfs_dirent, name_node);
if (strcmp(name, found->s_name))
return NULL;
}
} }
return NULL;
return found;
} }
/** /**
...@@ -744,21 +783,19 @@ void sysfs_remove_subdir(struct sysfs_dirent *sd) ...@@ -744,21 +783,19 @@ void sysfs_remove_subdir(struct sysfs_dirent *sd)
static void __sysfs_remove_dir(struct sysfs_dirent *dir_sd) static void __sysfs_remove_dir(struct sysfs_dirent *dir_sd)
{ {
struct sysfs_addrm_cxt acxt; struct sysfs_addrm_cxt acxt;
struct sysfs_dirent **pos; struct rb_node *pos;
if (!dir_sd) if (!dir_sd)
return; return;
pr_debug("sysfs %s: removing dir\n", dir_sd->s_name); pr_debug("sysfs %s: removing dir\n", dir_sd->s_name);
sysfs_addrm_start(&acxt, dir_sd); sysfs_addrm_start(&acxt, dir_sd);
pos = &dir_sd->s_dir.children; pos = rb_first(&dir_sd->s_dir.inode_tree);
while (*pos) { while (pos) {
struct sysfs_dirent *sd = *pos; struct sysfs_dirent *sd = rb_entry(pos, struct sysfs_dirent, inode_node);
pos = rb_next(pos);
if (sysfs_type(sd) != SYSFS_DIR) if (sysfs_type(sd) != SYSFS_DIR)
sysfs_remove_one(&acxt, sd); sysfs_remove_one(&acxt, sd);
else
pos = &(*pos)->s_sibling;
} }
sysfs_addrm_finish(&acxt); sysfs_addrm_finish(&acxt);
...@@ -881,12 +918,28 @@ static struct sysfs_dirent *sysfs_dir_pos(const void *ns, ...@@ -881,12 +918,28 @@ static struct sysfs_dirent *sysfs_dir_pos(const void *ns,
pos = NULL; pos = NULL;
} }
if (!pos && (ino > 1) && (ino < INT_MAX)) { if (!pos && (ino > 1) && (ino < INT_MAX)) {
pos = parent_sd->s_dir.children; struct rb_node *p = parent_sd->s_dir.inode_tree.rb_node;
while (pos && (ino > pos->s_ino)) while (p) {
pos = pos->s_sibling; #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; return pos;
} }
...@@ -894,10 +947,13 @@ static struct sysfs_dirent *sysfs_dir_next_pos(const void *ns, ...@@ -894,10 +947,13 @@ static struct sysfs_dirent *sysfs_dir_next_pos(const void *ns,
struct sysfs_dirent *parent_sd, ino_t ino, struct sysfs_dirent *pos) struct sysfs_dirent *parent_sd, ino_t ino, struct sysfs_dirent *pos)
{ {
pos = sysfs_dir_pos(ns, parent_sd, ino, pos); pos = sysfs_dir_pos(ns, parent_sd, ino, pos);
if (pos) if (pos) do {
pos = pos->s_sibling; struct rb_node *p = rb_next(&pos->inode_node);
while (pos && pos->s_ns && pos->s_ns != ns) if (!p)
pos = pos->s_sibling; pos = NULL;
else
pos = rb_entry(p, struct sysfs_dirent, inode_node);
} while (pos && pos->s_ns && pos->s_ns != ns);
return pos; return pos;
} }
......
...@@ -202,18 +202,6 @@ static inline void set_inode_attr(struct inode * inode, struct iattr * iattr) ...@@ -202,18 +202,6 @@ static inline void set_inode_attr(struct inode * inode, struct iattr * iattr)
inode->i_ctime = iattr->ia_ctime; 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) static void sysfs_refresh_inode(struct sysfs_dirent *sd, struct inode *inode)
{ {
struct sysfs_inode_attrs *iattrs = sd->s_iattr; struct sysfs_inode_attrs *iattrs = sd->s_iattr;
...@@ -230,7 +218,7 @@ static void sysfs_refresh_inode(struct sysfs_dirent *sd, struct inode *inode) ...@@ -230,7 +218,7 @@ static void sysfs_refresh_inode(struct sysfs_dirent *sd, struct inode *inode)
} }
if (sysfs_type(sd) == SYSFS_DIR) 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) int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
......
...@@ -11,14 +11,18 @@ ...@@ -11,14 +11,18 @@
#include <linux/lockdep.h> #include <linux/lockdep.h>
#include <linux/kobject_ns.h> #include <linux/kobject_ns.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/rbtree.h>
struct sysfs_open_dirent; struct sysfs_open_dirent;
/* type-specific structures for sysfs_dirent->s_* union members */ /* type-specific structures for sysfs_dirent->s_* union members */
struct sysfs_elem_dir { struct sysfs_elem_dir {
struct kobject *kobj; 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;
}; };
struct sysfs_elem_symlink { struct sysfs_elem_symlink {
...@@ -56,9 +60,16 @@ struct sysfs_dirent { ...@@ -56,9 +60,16 @@ struct sysfs_dirent {
struct lockdep_map dep_map; struct lockdep_map dep_map;
#endif #endif
struct sysfs_dirent *s_parent; struct sysfs_dirent *s_parent;
struct sysfs_dirent *s_sibling;
const char *s_name; const char *s_name;
struct rb_node inode_node;
struct rb_node name_node;
union {
struct completion *completion;
struct sysfs_dirent *removed_list;
} u;
const void *s_ns; /* namespace tag */ const void *s_ns; /* namespace tag */
union { union {
struct sysfs_elem_dir s_dir; struct sysfs_elem_dir s_dir;
......
...@@ -785,6 +785,8 @@ extern const char *dev_driver_string(const struct device *dev); ...@@ -785,6 +785,8 @@ extern const char *dev_driver_string(const struct device *dev);
#ifdef CONFIG_PRINTK #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, extern int dev_printk(const char *level, const struct device *dev,
const char *fmt, ...) const char *fmt, ...)
__attribute__ ((format (printf, 3, 4))); __attribute__ ((format (printf, 3, 4)));
...@@ -805,6 +807,9 @@ extern int _dev_info(const struct device *dev, const char *fmt, ...) ...@@ -805,6 +807,9 @@ extern int _dev_info(const struct device *dev, const char *fmt, ...)
#else #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, static inline int dev_printk(const char *level, const struct device *dev,
const char *fmt, ...) const char *fmt, ...)
__attribute__ ((format (printf, 3, 4))); __attribute__ ((format (printf, 3, 4)));
......
#ifndef _DYNAMIC_DEBUG_H #ifndef _DYNAMIC_DEBUG_H
#define _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 * An instance of this structure is created in a special
* ELF section at every dynamic debug callsite. At runtime, * ELF section at every dynamic debug callsite. At runtime,
...@@ -47,26 +40,55 @@ extern int ddebug_remove_module(const char *mod_name); ...@@ -47,26 +40,55 @@ extern int ddebug_remove_module(const char *mod_name);
extern int __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...) extern int __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...)
__attribute__ ((format (printf, 2, 3))); __attribute__ ((format (printf, 2, 3)));
#define dynamic_pr_debug(fmt, ...) do { \ struct device;
static struct _ddebug descriptor \
__used \ extern int __dynamic_dev_dbg(struct _ddebug *descriptor,
__attribute__((section("__verbose"), aligned(8))) = \ const struct device *dev,
{ KBUILD_MODNAME, __func__, __FILE__, fmt, __LINE__, \ const char *fmt, ...)
_DPRINTK_FLAGS_DEFAULT }; \ __attribute__ ((format (printf, 3, 4)));
if (unlikely(descriptor.enabled)) \
__dynamic_pr_debug(&descriptor, pr_fmt(fmt), ##__VA_ARGS__); \ struct net_device;
} while (0)
extern int __dynamic_netdev_dbg(struct _ddebug *descriptor,
const struct net_device *dev,
#define dynamic_dev_dbg(dev, fmt, ...) do { \ const char *fmt, ...)
static struct _ddebug descriptor \ __attribute__ ((format (printf, 3, 4)));
__used \
__attribute__((section("__verbose"), aligned(8))) = \ #define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt) \
{ KBUILD_MODNAME, __func__, __FILE__, fmt, __LINE__, \ static struct _ddebug __used __aligned(8) \
_DPRINTK_FLAGS_DEFAULT }; \ __attribute__((section("__verbose"))) name = { \
if (unlikely(descriptor.enabled)) \ .modname = KBUILD_MODNAME, \
dev_printk(KERN_DEBUG, dev, fmt, ##__VA_ARGS__); \ .function = __func__, \
} while (0) .filename = __FILE__, \
.format = (fmt), \
.lineno = __LINE__, \
.flags = _DPRINTK_FLAGS_DEFAULT, \
.enabled = false, \
}
#define dynamic_pr_debug(fmt, ...) \
do { \
DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \
if (unlikely(descriptor.enabled)) \
__dynamic_pr_debug(&descriptor, pr_fmt(fmt), \
##__VA_ARGS__); \
} while (0)
#define dynamic_dev_dbg(dev, fmt, ...) \
do { \
DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \
if (unlikely(descriptor.enabled)) \
__dynamic_dev_dbg(&descriptor, dev, fmt, \
##__VA_ARGS__); \
} while (0)
#define dynamic_netdev_dbg(dev, fmt, ...) \
do { \
DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \
if (unlikely(descriptor.enabled)) \
__dynamic_netdev_dbg(&descriptor, dev, fmt, \
##__VA_ARGS__); \
} while (0)
#else #else
......
...@@ -2617,6 +2617,9 @@ static inline const char *netdev_name(const struct net_device *dev) ...@@ -2617,6 +2617,9 @@ static inline const char *netdev_name(const struct net_device *dev)
return dev->name; 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, extern int netdev_printk(const char *level, const struct net_device *dev,
const char *format, ...) const char *format, ...)
__attribute__ ((format (printf, 3, 4))); __attribute__ ((format (printf, 3, 4)));
...@@ -2644,8 +2647,7 @@ extern int netdev_info(const struct net_device *dev, const char *format, ...) ...@@ -2644,8 +2647,7 @@ extern int netdev_info(const struct net_device *dev, const char *format, ...)
#elif defined(CONFIG_DYNAMIC_DEBUG) #elif defined(CONFIG_DYNAMIC_DEBUG)
#define netdev_dbg(__dev, format, args...) \ #define netdev_dbg(__dev, format, args...) \
do { \ do { \
dynamic_dev_dbg((__dev)->dev.parent, "%s: " format, \ dynamic_netdev_dbg(__dev, format, ##args); \
netdev_name(__dev), ##args); \
} while (0) } while (0)
#else #else
#define netdev_dbg(__dev, format, args...) \ #define netdev_dbg(__dev, format, args...) \
...@@ -2712,9 +2714,7 @@ do { \ ...@@ -2712,9 +2714,7 @@ do { \
#define netif_dbg(priv, type, netdev, format, args...) \ #define netif_dbg(priv, type, netdev, format, args...) \
do { \ do { \
if (netif_msg_##type(priv)) \ if (netif_msg_##type(priv)) \
dynamic_dev_dbg((netdev)->dev.parent, \ dynamic_netdev_dbg(netdev, format, ##args); \
"%s: " format, \
netdev_name(netdev), ##args); \
} while (0) } while (0)
#else #else
#define netif_dbg(priv, type, dev, format, args...) \ #define netif_dbg(priv, type, dev, format, args...) \
......
...@@ -49,10 +49,54 @@ extern struct resource *platform_get_resource_byname(struct platform_device *, u ...@@ -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_get_irq_byname(struct platform_device *, const char *);
extern int platform_add_devices(struct platform_device **, int); 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, struct device *parent, const char *name, int id,
const struct resource *res, unsigned int num, 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 * platform_device_register_simple - add a platform-level device and its resources
......
...@@ -23,7 +23,10 @@ struct uio_map; ...@@ -23,7 +23,10 @@ struct uio_map;
/** /**
* struct uio_mem - description of a UIO memory region * struct uio_mem - description of a UIO memory region
* @name: name of the memory region for identification * @name: name of the memory region for identification
* @addr: address of the device's memory * @addr: address of the device's memory (phys_addr is used since
* addr can be logical, virtual, or physical & phys_addr_t
* should always be large enough to handle any of the
* address types)
* @size: size of IO * @size: size of IO
* @memtype: type of memory addr points to * @memtype: type of memory addr points to
* @internal_addr: ioremap-ped version of addr, for driver internal use * @internal_addr: ioremap-ped version of addr, for driver internal use
...@@ -31,7 +34,7 @@ struct uio_map; ...@@ -31,7 +34,7 @@ struct uio_map;
*/ */
struct uio_mem { struct uio_mem {
const char *name; const char *name;
unsigned long addr; phys_addr_t addr;
unsigned long size; unsigned long size;
int memtype; int memtype;
void __iomem *internal_addr; void __iomem *internal_addr;
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
* Copyright (C) 2011 Bart Van Assche. All Rights Reserved. * Copyright (C) 2011 Bart Van Assche. All Rights Reserved.
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
...@@ -29,6 +31,8 @@ ...@@ -29,6 +31,8 @@
#include <linux/jump_label.h> #include <linux/jump_label.h>
#include <linux/hardirq.h> #include <linux/hardirq.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/device.h>
#include <linux/netdevice.h>
extern struct _ddebug __start___verbose[]; extern struct _ddebug __start___verbose[];
extern struct _ddebug __stop___verbose[]; extern struct _ddebug __stop___verbose[];
...@@ -37,7 +41,6 @@ struct ddebug_table { ...@@ -37,7 +41,6 @@ struct ddebug_table {
struct list_head link; struct list_head link;
char *mod_name; char *mod_name;
unsigned int num_ddebugs; unsigned int num_ddebugs;
unsigned int num_enabled;
struct _ddebug *ddebugs; struct _ddebug *ddebugs;
}; };
...@@ -147,19 +150,13 @@ static void ddebug_change(const struct ddebug_query *query, ...@@ -147,19 +150,13 @@ static void ddebug_change(const struct ddebug_query *query,
newflags = (dp->flags & mask) | flags; newflags = (dp->flags & mask) | flags;
if (newflags == dp->flags) if (newflags == dp->flags)
continue; continue;
if (!newflags)
dt->num_enabled--;
else if (!dp->flags)
dt->num_enabled++;
dp->flags = newflags; dp->flags = newflags;
if (newflags) if (newflags)
dp->enabled = 1; dp->enabled = 1;
else else
dp->enabled = 0; dp->enabled = 0;
if (verbose) if (verbose)
printk(KERN_INFO pr_info("changed %s:%d [%s]%s %s\n",
"ddebug: changed %s:%d [%s]%s %s\n",
dp->filename, dp->lineno, dp->filename, dp->lineno,
dt->mod_name, dp->function, dt->mod_name, dp->function,
ddebug_describe_flags(dp, flagbuf, ddebug_describe_flags(dp, flagbuf,
...@@ -169,7 +166,7 @@ static void ddebug_change(const struct ddebug_query *query, ...@@ -169,7 +166,7 @@ static void ddebug_change(const struct ddebug_query *query,
mutex_unlock(&ddebug_lock); mutex_unlock(&ddebug_lock);
if (!nfound && verbose) if (!nfound && verbose)
printk(KERN_INFO "ddebug: no matches for query\n"); pr_info("no matches for query\n");
} }
/* /*
...@@ -214,10 +211,10 @@ static int ddebug_tokenize(char *buf, char *words[], int maxwords) ...@@ -214,10 +211,10 @@ static int ddebug_tokenize(char *buf, char *words[], int maxwords)
if (verbose) { if (verbose) {
int i; int i;
printk(KERN_INFO "%s: split into words:", __func__); pr_info("split into words:");
for (i = 0 ; i < nwords ; i++) for (i = 0 ; i < nwords ; i++)
printk(" \"%s\"", words[i]); pr_cont(" \"%s\"", words[i]);
printk("\n"); pr_cont("\n");
} }
return nwords; return nwords;
...@@ -329,16 +326,15 @@ static int ddebug_parse_query(char *words[], int nwords, ...@@ -329,16 +326,15 @@ static int ddebug_parse_query(char *words[], int nwords,
} }
} else { } else {
if (verbose) if (verbose)
printk(KERN_ERR "%s: unknown keyword \"%s\"\n", pr_err("unknown keyword \"%s\"\n", words[i]);
__func__, words[i]);
return -EINVAL; return -EINVAL;
} }
} }
if (verbose) if (verbose)
printk(KERN_INFO "%s: q->function=\"%s\" q->filename=\"%s\" " pr_info("q->function=\"%s\" q->filename=\"%s\" "
"q->module=\"%s\" q->format=\"%s\" q->lineno=%u-%u\n", "q->module=\"%s\" q->format=\"%s\" q->lineno=%u-%u\n",
__func__, query->function, query->filename, query->function, query->filename,
query->module, query->format, query->first_lineno, query->module, query->format, query->first_lineno,
query->last_lineno); query->last_lineno);
...@@ -367,7 +363,7 @@ static int ddebug_parse_flags(const char *str, unsigned int *flagsp, ...@@ -367,7 +363,7 @@ static int ddebug_parse_flags(const char *str, unsigned int *flagsp,
return -EINVAL; return -EINVAL;
} }
if (verbose) if (verbose)
printk(KERN_INFO "%s: op='%c'\n", __func__, op); pr_info("op='%c'\n", op);
for ( ; *str ; ++str) { for ( ; *str ; ++str) {
for (i = ARRAY_SIZE(opt_array) - 1; i >= 0; i--) { for (i = ARRAY_SIZE(opt_array) - 1; i >= 0; i--) {
...@@ -382,7 +378,7 @@ static int ddebug_parse_flags(const char *str, unsigned int *flagsp, ...@@ -382,7 +378,7 @@ static int ddebug_parse_flags(const char *str, unsigned int *flagsp,
if (flags == 0) if (flags == 0)
return -EINVAL; return -EINVAL;
if (verbose) 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 */ /* calculate final *flagsp, *maskp according to mask and op */
switch (op) { switch (op) {
...@@ -400,8 +396,7 @@ static int ddebug_parse_flags(const char *str, unsigned int *flagsp, ...@@ -400,8 +396,7 @@ static int ddebug_parse_flags(const char *str, unsigned int *flagsp,
break; break;
} }
if (verbose) if (verbose)
printk(KERN_INFO "%s: *flagsp=0x%x *maskp=0x%x\n", pr_info("*flagsp=0x%x *maskp=0x%x\n", *flagsp, *maskp);
__func__, *flagsp, *maskp);
return 0; return 0;
} }
...@@ -426,40 +421,117 @@ static int ddebug_exec_query(char *query_string) ...@@ -426,40 +421,117 @@ static int ddebug_exec_query(char *query_string)
return 0; return 0;
} }
#define PREFIX_SIZE 64
static int remaining(int wrote)
{
if (PREFIX_SIZE - wrote > 0)
return PREFIX_SIZE - wrote;
return 0;
}
static char *dynamic_emit_prefix(const struct _ddebug *desc, char *buf)
{
int pos_after_tid;
int pos = 0;
pos += snprintf(buf + pos, remaining(pos), "%s", KERN_DEBUG);
if (desc->flags & _DPRINTK_FLAGS_INCL_TID) {
if (in_interrupt())
pos += snprintf(buf + pos, remaining(pos), "%s ",
"<intr>");
else
pos += snprintf(buf + pos, remaining(pos), "[%d] ",
task_pid_vnr(current));
}
pos_after_tid = pos;
if (desc->flags & _DPRINTK_FLAGS_INCL_MODNAME)
pos += snprintf(buf + pos, remaining(pos), "%s:",
desc->modname);
if (desc->flags & _DPRINTK_FLAGS_INCL_FUNCNAME)
pos += snprintf(buf + pos, remaining(pos), "%s:",
desc->function);
if (desc->flags & _DPRINTK_FLAGS_INCL_LINENO)
pos += snprintf(buf + pos, remaining(pos), "%d:", desc->lineno);
if (pos - pos_after_tid)
pos += snprintf(buf + pos, remaining(pos), " ");
if (pos >= PREFIX_SIZE)
buf[PREFIX_SIZE - 1] = '\0';
return buf;
}
int __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...) int __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...)
{ {
va_list args; va_list args;
int res; int res;
struct va_format vaf;
char buf[PREFIX_SIZE];
BUG_ON(!descriptor); BUG_ON(!descriptor);
BUG_ON(!fmt); BUG_ON(!fmt);
va_start(args, fmt); va_start(args, fmt);
res = printk(KERN_DEBUG); vaf.fmt = fmt;
if (descriptor->flags & _DPRINTK_FLAGS_INCL_TID) { vaf.va = &args;
if (in_interrupt()) res = printk("%s%pV", dynamic_emit_prefix(descriptor, buf), &vaf);
res += printk(KERN_CONT "<intr> ");
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 += vprintk(fmt, args);
va_end(args); va_end(args);
return res; return res;
} }
EXPORT_SYMBOL(__dynamic_pr_debug); 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;
char buf[PREFIX_SIZE];
BUG_ON(!descriptor);
BUG_ON(!fmt);
va_start(args, fmt);
vaf.fmt = fmt;
vaf.va = &args;
res = __dev_printk(dynamic_emit_prefix(descriptor, buf), dev, &vaf);
va_end(args);
return res;
}
EXPORT_SYMBOL(__dynamic_dev_dbg);
#ifdef CONFIG_NET
int __dynamic_netdev_dbg(struct _ddebug *descriptor,
const struct net_device *dev, const char *fmt, ...)
{
struct va_format vaf;
va_list args;
int res;
char buf[PREFIX_SIZE];
BUG_ON(!descriptor);
BUG_ON(!fmt);
va_start(args, fmt);
vaf.fmt = fmt;
vaf.va = &args;
res = __netdev_printk(dynamic_emit_prefix(descriptor, buf), dev, &vaf);
va_end(args);
return res;
}
EXPORT_SYMBOL(__dynamic_netdev_dbg);
#endif
static __initdata char ddebug_setup_string[1024]; static __initdata char ddebug_setup_string[1024];
static __init int ddebug_setup_query(char *str) static __init int ddebug_setup_query(char *str)
{ {
if (strlen(str) >= 1024) { if (strlen(str) >= 1024) {
pr_warning("ddebug boot param string too large\n"); pr_warn("ddebug boot param string too large\n");
return 0; return 0;
} }
strcpy(ddebug_setup_string, str); strcpy(ddebug_setup_string, str);
...@@ -487,8 +559,7 @@ static ssize_t ddebug_proc_write(struct file *file, const char __user *ubuf, ...@@ -487,8 +559,7 @@ static ssize_t ddebug_proc_write(struct file *file, const char __user *ubuf,
return -EFAULT; return -EFAULT;
tmpbuf[len] = '\0'; tmpbuf[len] = '\0';
if (verbose) if (verbose)
printk(KERN_INFO "%s: read %d bytes from userspace\n", pr_info("read %d bytes from userspace\n", (int)len);
__func__, (int)len);
ret = ddebug_exec_query(tmpbuf); ret = ddebug_exec_query(tmpbuf);
if (ret) if (ret)
...@@ -551,8 +622,7 @@ static void *ddebug_proc_start(struct seq_file *m, loff_t *pos) ...@@ -551,8 +622,7 @@ static void *ddebug_proc_start(struct seq_file *m, loff_t *pos)
int n = *pos; int n = *pos;
if (verbose) if (verbose)
printk(KERN_INFO "%s: called m=%p *pos=%lld\n", pr_info("called m=%p *pos=%lld\n", m, (unsigned long long)*pos);
__func__, m, (unsigned long long)*pos);
mutex_lock(&ddebug_lock); mutex_lock(&ddebug_lock);
...@@ -577,8 +647,8 @@ static void *ddebug_proc_next(struct seq_file *m, void *p, loff_t *pos) ...@@ -577,8 +647,8 @@ static void *ddebug_proc_next(struct seq_file *m, void *p, loff_t *pos)
struct _ddebug *dp; struct _ddebug *dp;
if (verbose) if (verbose)
printk(KERN_INFO "%s: called m=%p p=%p *pos=%lld\n", pr_info("called m=%p p=%p *pos=%lld\n",
__func__, m, p, (unsigned long long)*pos); m, p, (unsigned long long)*pos);
if (p == SEQ_START_TOKEN) if (p == SEQ_START_TOKEN)
dp = ddebug_iter_first(iter); dp = ddebug_iter_first(iter);
...@@ -601,8 +671,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p) ...@@ -601,8 +671,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
char flagsbuf[8]; char flagsbuf[8];
if (verbose) if (verbose)
printk(KERN_INFO "%s: called m=%p p=%p\n", pr_info("called m=%p p=%p\n", m, p);
__func__, m, p);
if (p == SEQ_START_TOKEN) { if (p == SEQ_START_TOKEN) {
seq_puts(m, seq_puts(m,
...@@ -627,8 +696,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p) ...@@ -627,8 +696,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
static void ddebug_proc_stop(struct seq_file *m, void *p) static void ddebug_proc_stop(struct seq_file *m, void *p)
{ {
if (verbose) if (verbose)
printk(KERN_INFO "%s: called m=%p p=%p\n", pr_info("called m=%p p=%p\n", m, p);
__func__, m, p);
mutex_unlock(&ddebug_lock); mutex_unlock(&ddebug_lock);
} }
...@@ -651,7 +719,7 @@ static int ddebug_proc_open(struct inode *inode, struct file *file) ...@@ -651,7 +719,7 @@ static int ddebug_proc_open(struct inode *inode, struct file *file)
int err; int err;
if (verbose) if (verbose)
printk(KERN_INFO "%s: called\n", __func__); pr_info("called\n");
iter = kzalloc(sizeof(*iter), GFP_KERNEL); iter = kzalloc(sizeof(*iter), GFP_KERNEL);
if (iter == NULL) if (iter == NULL)
...@@ -695,7 +763,6 @@ int ddebug_add_module(struct _ddebug *tab, unsigned int n, ...@@ -695,7 +763,6 @@ int ddebug_add_module(struct _ddebug *tab, unsigned int n,
} }
dt->mod_name = new_name; dt->mod_name = new_name;
dt->num_ddebugs = n; dt->num_ddebugs = n;
dt->num_enabled = 0;
dt->ddebugs = tab; dt->ddebugs = tab;
mutex_lock(&ddebug_lock); mutex_lock(&ddebug_lock);
...@@ -703,8 +770,7 @@ int ddebug_add_module(struct _ddebug *tab, unsigned int n, ...@@ -703,8 +770,7 @@ int ddebug_add_module(struct _ddebug *tab, unsigned int n,
mutex_unlock(&ddebug_lock); mutex_unlock(&ddebug_lock);
if (verbose) if (verbose)
printk(KERN_INFO "%u debug prints in module %s\n", pr_info("%u debug prints in module %s\n", n, dt->mod_name);
n, dt->mod_name);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(ddebug_add_module); EXPORT_SYMBOL_GPL(ddebug_add_module);
...@@ -726,8 +792,7 @@ int ddebug_remove_module(const char *mod_name) ...@@ -726,8 +792,7 @@ int ddebug_remove_module(const char *mod_name)
int ret = -ENOENT; int ret = -ENOENT;
if (verbose) if (verbose)
printk(KERN_INFO "%s: removing module \"%s\"\n", pr_info("removing module \"%s\"\n", mod_name);
__func__, mod_name);
mutex_lock(&ddebug_lock); mutex_lock(&ddebug_lock);
list_for_each_entry_safe(dt, nextdt, &ddebug_tables, link) { list_for_each_entry_safe(dt, nextdt, &ddebug_tables, link) {
...@@ -803,8 +868,8 @@ static int __init dynamic_debug_init(void) ...@@ -803,8 +868,8 @@ static int __init dynamic_debug_init(void)
if (ddebug_setup_string[0] != '\0') { if (ddebug_setup_string[0] != '\0') {
ret = ddebug_exec_query(ddebug_setup_string); ret = ddebug_exec_query(ddebug_setup_string);
if (ret) if (ret)
pr_warning("Invalid ddebug boot param %s", pr_warn("Invalid ddebug boot param %s",
ddebug_setup_string); ddebug_setup_string);
else else
pr_info("ddebug initialized with string %s", pr_info("ddebug initialized with string %s",
ddebug_setup_string); ddebug_setup_string);
......
...@@ -282,7 +282,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, ...@@ -282,7 +282,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
kobj_bcast_filter, kobj_bcast_filter,
kobj); kobj);
/* ENOBUFS should be handled in userspace */ /* ENOBUFS should be handled in userspace */
if (retval == -ENOBUFS) if (retval == -ENOBUFS || retval == -ESRCH)
retval = 0; retval = 0;
} else } else
retval = -ENOMEM; retval = -ENOMEM;
......
...@@ -6298,7 +6298,7 @@ const char *netdev_drivername(const struct net_device *dev) ...@@ -6298,7 +6298,7 @@ const char *netdev_drivername(const struct net_device *dev)
return empty; 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) struct va_format *vaf)
{ {
int r; int r;
...@@ -6313,6 +6313,7 @@ static int __netdev_printk(const char *level, const struct net_device *dev, ...@@ -6313,6 +6313,7 @@ static int __netdev_printk(const char *level, const struct net_device *dev,
return r; return r;
} }
EXPORT_SYMBOL(__netdev_printk);
int netdev_printk(const char *level, const struct net_device *dev, int netdev_printk(const char *level, const struct net_device *dev,
const char *format, ...) const char *format, ...)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment