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() ...
This commit is contained in:
commit
2d03423b23
|
@ -529,7 +529,7 @@ memory (e.g. allocated with <function>kmalloc()</function>). There's also
|
|||
</para></listitem>
|
||||
|
||||
<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
|
||||
appears in sysfs.
|
||||
</para></listitem>
|
||||
|
|
|
@ -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
|
||||
~~~~~~
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
device_create_file(dev,&dev_attr_power);
|
||||
device_remove_file(dev,&dev_attr_power);
|
||||
static const struct attribute_group *dev_attr_groups[] = {
|
||||
&dev_attr_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
The file name will be 'power' with a mode of 0644 (-rw-r--r--).
|
||||
This array of groups can then be associated with a device by setting the
|
||||
group pointer in struct device before device_register() is invoked:
|
||||
|
||||
dev->groups = dev_attr_groups;
|
||||
device_register(dev);
|
||||
|
||||
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.
|
||||
|
|
|
@ -4,7 +4,7 @@ sysfs - _The_ filesystem for exporting kernel objects.
|
|||
Patrick Mochel <mochel@osdl.org>
|
||||
Mike Murphy <mamurph@cs.clemson.edu>
|
||||
|
||||
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.
|
||||
|
|
|
@ -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:
|
||||
|
||||
- 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
|
||||
of your submission.
|
||||
stable@vger.kernel.org. You must note the upstream commit ID in the
|
||||
changelog of your submission.
|
||||
- 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
|
||||
the stable tree without anything else needing to be done by the author
|
||||
or subsystem maintainer.
|
||||
|
@ -35,10 +35,10 @@ Procedure for submitting patches to the -stable tree:
|
|||
cherry-picked than this can be specified in the following format in
|
||||
the sign-off area:
|
||||
|
||||
Cc: <stable@kernel.org> # .32.x: a1f84a3: sched: Check for idle
|
||||
Cc: <stable@kernel.org> # .32.x: 1b9508f: sched: Rate-limit newidle
|
||||
Cc: <stable@kernel.org> # .32.x: fd21073: sched: Fix affinity logic
|
||||
Cc: <stable@kernel.org> # .32.x
|
||||
Cc: <stable@vger.kernel.org> # .32.x: a1f84a3: sched: Check for idle
|
||||
Cc: <stable@vger.kernel.org> # .32.x: 1b9508f: sched: Rate-limit newidle
|
||||
Cc: <stable@vger.kernel.org> # .32.x: fd21073: sched: Fix affinity logic
|
||||
Cc: <stable@vger.kernel.org> # .32.x
|
||||
Signed-off-by: Ingo Molnar <mingo@elte.hu>
|
||||
|
||||
The tag sequence has the meaning of:
|
||||
|
|
|
@ -1,109 +0,0 @@
|
|||
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
|
|||
S: Maintained
|
||||
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
|
||||
M: "Maciej W. Rozycki" <macro@linux-mips.org>
|
||||
S: Maintained
|
||||
|
|
|
@ -37,59 +37,6 @@ int __init mxc_register_device(struct platform_device *pdev, void *data)
|
|||
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 = {
|
||||
.init_name = "mxc_aips",
|
||||
.parent = &platform_bus,
|
||||
|
|
|
@ -14,10 +14,22 @@
|
|||
extern struct device mxc_aips_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 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(
|
||||
const char *name, int id,
|
||||
|
|
|
@ -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, ...)
|
||||
|
|
|
@ -147,6 +147,9 @@ probe_failed:
|
|||
printk(KERN_WARNING
|
||||
"%s: probe of %s failed with error %d\n",
|
||||
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
|
||||
|
|
|
@ -223,6 +223,42 @@ int memory_isolate_notify(unsigned long val, void *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
|
||||
* OK to have direct references to sparsemem variables in here.
|
||||
|
@ -230,7 +266,6 @@ int memory_isolate_notify(unsigned long val, void *v)
|
|||
static int
|
||||
memory_block_action(unsigned long phys_index, unsigned long action)
|
||||
{
|
||||
int i;
|
||||
unsigned long start_pfn, start_paddr;
|
||||
unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block;
|
||||
struct page *first_page;
|
||||
|
@ -238,26 +273,13 @@ memory_block_action(unsigned long phys_index, unsigned long action)
|
|||
|
||||
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) {
|
||||
case MEM_ONLINE:
|
||||
start_pfn = page_to_pfn(first_page);
|
||||
|
||||
if (!pages_correctly_reserved(start_pfn, nr_pages))
|
||||
return -EBUSY;
|
||||
|
||||
ret = online_pages(start_pfn, nr_pages);
|
||||
break;
|
||||
case MEM_OFFLINE:
|
||||
|
@ -380,9 +402,13 @@ memory_probe_store(struct class *class, struct class_attribute *attr,
|
|||
u64 phys_addr;
|
||||
int nid;
|
||||
int i, ret;
|
||||
unsigned long pages_per_block = PAGES_PER_SECTION * sections_per_block;
|
||||
|
||||
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++) {
|
||||
nid = memory_add_physaddr_to_nid(phys_addr);
|
||||
ret = add_memory(nid, phys_addr,
|
||||
|
|
|
@ -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;
|
||||
goto err_alloc;
|
||||
|
||||
pdev->dev.parent = parent;
|
||||
pdev->dev.parent = pdevinfo->parent;
|
||||
|
||||
ret = platform_device_add_resources(pdev, res, num);
|
||||
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,
|
||||
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)
|
||||
{
|
||||
|
@ -614,7 +626,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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
|
||||
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,
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
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)
|
||||
|
@ -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)
|
||||
{
|
||||
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 {
|
||||
|
@ -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)
|
||||
page = virt_to_page(idev->info->mem[mi].addr + offset);
|
||||
else
|
||||
page = vmalloc_to_page((void *)idev->info->mem[mi].addr
|
||||
+ offset);
|
||||
page = vmalloc_to_page((void *)(unsigned long)idev->info->mem[mi].addr + offset);
|
||||
get_page(page);
|
||||
vmf->page = page;
|
||||
return 0;
|
||||
|
@ -750,14 +749,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)
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/uio_driver.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#define DRIVER_VERSION "0.01.0"
|
||||
#define DRIVER_AUTHOR "Michael S. Tsirkin <mst@redhat.com>"
|
||||
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 <greg@kroah.com>
|
||||
* Copyright (C) 2004 IBM Inc.
|
||||
|
|
166
fs/sysfs/dir.c
166
fs/sysfs/dir.c
|
@ -43,20 +43,48 @@ 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;
|
||||
|
||||
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
|
||||
* 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;
|
||||
if (sysfs_type(sd) == SYSFS_DIR)
|
||||
parent_sd->s_dir.subdirs++;
|
||||
|
||||
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",
|
||||
(unsigned long) 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;
|
||||
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)
|
|||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -126,7 +149,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))
|
||||
|
@ -138,10 +160,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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -155,16 +176,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);
|
||||
|
||||
|
@ -173,8 +194,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_);
|
||||
}
|
||||
|
@ -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_sibling = acxt->removed;
|
||||
sd->u.removed_list = acxt->removed;
|
||||
acxt->removed = sd;
|
||||
}
|
||||
|
||||
|
@ -514,8 +533,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);
|
||||
|
@ -540,15 +558,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;
|
||||
|
||||
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;
|
||||
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
|
||||
}
|
||||
return NULL;
|
||||
|
||||
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 found;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -744,21 +783,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);
|
||||
|
||||
|
@ -881,12 +918,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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -11,14 +11,18 @@
|
|||
#include <linux/lockdep.h>
|
||||
#include <linux/kobject_ns.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/rbtree.h>
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
struct sysfs_elem_symlink {
|
||||
|
@ -56,9 +60,16 @@ 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 {
|
||||
struct completion *completion;
|
||||
struct sysfs_dirent *removed_list;
|
||||
} u;
|
||||
|
||||
const void *s_ns; /* namespace tag */
|
||||
union {
|
||||
struct sysfs_elem_dir s_dir;
|
||||
|
|
|
@ -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)));
|
||||
|
|
|
@ -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,
|
||||
|
@ -47,26 +40,55 @@ 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)));
|
||||
|
||||
#define dynamic_pr_debug(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_pr_debug(&descriptor, pr_fmt(fmt), ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
struct device;
|
||||
|
||||
extern int __dynamic_dev_dbg(struct _ddebug *descriptor,
|
||||
const struct device *dev,
|
||||
const char *fmt, ...)
|
||||
__attribute__ ((format (printf, 3, 4)));
|
||||
|
||||
#define dynamic_dev_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)) \
|
||||
dev_printk(KERN_DEBUG, dev, fmt, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
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 DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt) \
|
||||
static struct _ddebug __used __aligned(8) \
|
||||
__attribute__((section("__verbose"))) name = { \
|
||||
.modname = KBUILD_MODNAME, \
|
||||
.function = __func__, \
|
||||
.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
|
||||
|
||||
|
|
|
@ -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...) \
|
||||
|
@ -2712,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...) \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -23,7 +23,10 @@ struct uio_map;
|
|||
/**
|
||||
* struct uio_mem - description of a UIO memory region
|
||||
* @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
|
||||
* @memtype: type of memory addr points to
|
||||
* @internal_addr: ioremap-ped version of addr, for driver internal use
|
||||
|
@ -31,7 +34,7 @@ struct uio_map;
|
|||
*/
|
||||
struct uio_mem {
|
||||
const char *name;
|
||||
unsigned long addr;
|
||||
phys_addr_t addr;
|
||||
unsigned long size;
|
||||
int memtype;
|
||||
void __iomem *internal_addr;
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
* Copyright (C) 2011 Bart Van Assche. All Rights Reserved.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
|
@ -29,6 +31,8 @@
|
|||
#include <linux/jump_label.h>
|
||||
#include <linux/hardirq.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
extern struct _ddebug __start___verbose[];
|
||||
extern struct _ddebug __stop___verbose[];
|
||||
|
@ -37,7 +41,6 @@ struct ddebug_table {
|
|||
struct list_head link;
|
||||
char *mod_name;
|
||||
unsigned int num_ddebugs;
|
||||
unsigned int num_enabled;
|
||||
struct _ddebug *ddebugs;
|
||||
};
|
||||
|
||||
|
@ -147,19 +150,13 @@ static void ddebug_change(const struct ddebug_query *query,
|
|||
newflags = (dp->flags & mask) | flags;
|
||||
if (newflags == dp->flags)
|
||||
continue;
|
||||
|
||||
if (!newflags)
|
||||
dt->num_enabled--;
|
||||
else if (!dp->flags)
|
||||
dt->num_enabled++;
|
||||
dp->flags = newflags;
|
||||
if (newflags)
|
||||
dp->enabled = 1;
|
||||
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,
|
||||
|
@ -169,7 +166,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");
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -214,10 +211,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;
|
||||
|
@ -329,16 +326,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);
|
||||
|
||||
|
@ -367,7 +363,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--) {
|
||||
|
@ -382,7 +378,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) {
|
||||
|
@ -400,8 +396,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;
|
||||
}
|
||||
|
||||
|
@ -426,40 +421,117 @@ static int ddebug_exec_query(char *query_string)
|
|||
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, ...)
|
||||
{
|
||||
va_list args;
|
||||
int res;
|
||||
struct va_format vaf;
|
||||
char buf[PREFIX_SIZE];
|
||||
|
||||
BUG_ON(!descriptor);
|
||||
BUG_ON(!fmt);
|
||||
|
||||
va_start(args, fmt);
|
||||
res = printk(KERN_DEBUG);
|
||||
if (descriptor->flags & _DPRINTK_FLAGS_INCL_TID) {
|
||||
if (in_interrupt())
|
||||
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);
|
||||
vaf.fmt = fmt;
|
||||
vaf.va = &args;
|
||||
res = printk("%s%pV", dynamic_emit_prefix(descriptor, buf), &vaf);
|
||||
va_end(args);
|
||||
|
||||
return res;
|
||||
}
|
||||
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 __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);
|
||||
|
@ -487,8 +559,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)
|
||||
|
@ -551,8 +622,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);
|
||||
|
||||
|
@ -577,8 +647,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);
|
||||
|
@ -601,8 +671,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,
|
||||
|
@ -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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -651,7 +719,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)
|
||||
|
@ -695,7 +763,6 @@ int ddebug_add_module(struct _ddebug *tab, unsigned int n,
|
|||
}
|
||||
dt->mod_name = new_name;
|
||||
dt->num_ddebugs = n;
|
||||
dt->num_enabled = 0;
|
||||
dt->ddebugs = tab;
|
||||
|
||||
mutex_lock(&ddebug_lock);
|
||||
|
@ -703,8 +770,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);
|
||||
|
@ -726,8 +792,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) {
|
||||
|
@ -803,8 +868,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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -6298,7 +6298,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;
|
||||
|
@ -6313,6 +6313,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, ...)
|
||||
|
|
Loading…
Reference in New Issue