diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-25 12:13:59 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-25 12:13:59 +0200 |
commit | 2d03423b2319cc854adeb28a03f65de5b5e0ab63 (patch) | |
tree | 20d9ddb661f3247f5dfaa6da8212123ed14a24c4 | |
parent | 59e52534172d845ebffb0d7e85fc56fb7b857051 (diff) | |
parent | 2bbcb8788311a40714b585fc11b51da6ffa2ab92 (diff) | |
download | op-kernel-dev-2d03423b2319cc854adeb28a03f65de5b5e0ab63.zip op-kernel-dev-2d03423b2319cc854adeb28a03f65de5b5e0ab63.tar.gz |
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()
...
29 files changed, 527 insertions, 432 deletions
diff --git a/Documentation/DocBook/uio-howto.tmpl b/Documentation/DocBook/uio-howto.tmpl index 7c4b514d..54883de 100644 --- a/Documentation/DocBook/uio-howto.tmpl +++ b/Documentation/DocBook/uio-howto.tmpl @@ -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> diff --git a/Documentation/driver-model/binding.txt b/Documentation/driver-model/binding.txt index f7ec9d6..abfc8e2 100644 --- a/Documentation/driver-model/binding.txt +++ b/Documentation/driver-model/binding.txt @@ -48,10 +48,6 @@ devclass_add_device is called to enumerate the device within the class and actually register it with the class, which happens with the class's register_dev callback. -NOTE: The device class structures and core routines to manipulate them -are not in the mainline kernel, so the discussion is still a bit -speculative. - Driver ~~~~~~ diff --git a/Documentation/driver-model/device.txt b/Documentation/driver-model/device.txt index bdefe72..1e70220 100644 --- a/Documentation/driver-model/device.txt +++ b/Documentation/driver-model/device.txt @@ -45,33 +45,52 @@ struct device_attribute { const char *buf, size_t count); }; -Attributes of devices can be exported via drivers using a simple -procfs-like interface. +Attributes of devices can be exported by a device driver through sysfs. Please see Documentation/filesystems/sysfs.txt for more information on how sysfs works. +As explained in Documentation/kobject.txt, device attributes must be be +created before the KOBJ_ADD uevent is generated. The only way to realize +that is by defining an attribute group. + Attributes are declared using a macro called DEVICE_ATTR: #define DEVICE_ATTR(name,mode,show,store) Example: -DEVICE_ATTR(power,0644,show_power,store_power); +static DEVICE_ATTR(type, 0444, show_type, NULL); +static DEVICE_ATTR(power, 0644, show_power, store_power); -This declares a structure of type struct device_attribute named -'dev_attr_power'. This can then be added and removed to the device's -directory using: +This declares two structures of type struct device_attribute with respective +names 'dev_attr_type' and 'dev_attr_power'. These two attributes can be +organized as follows into a group: -int device_create_file(struct device *device, struct device_attribute * entry); -void device_remove_file(struct device * dev, struct device_attribute * attr); +static struct attribute *dev_attrs[] = { + &dev_attr_type.attr, + &dev_attr_power.attr, + NULL, +}; -Example: +static struct attribute_group dev_attr_group = { + .attrs = dev_attrs, +}; + +static const struct attribute_group *dev_attr_groups[] = { + &dev_attr_group, + NULL, +}; + +This array of groups can then be associated with a device by setting the +group pointer in struct device before device_register() is invoked: -device_create_file(dev,&dev_attr_power); -device_remove_file(dev,&dev_attr_power); + dev->groups = dev_attr_groups; + device_register(dev); -The file name will be 'power' with a mode of 0644 (-rw-r--r--). +The device_register() function will use the 'groups' pointer to create the +device attributes and the device_unregister() function will use this pointer +to remove the device attributes. Word of warning: While the kernel allows device_create_file() and device_remove_file() to be called on a device at any time, userspace has @@ -84,24 +103,4 @@ not know about the new attributes. This is important for device driver that need to publish additional attributes for a device at driver probe time. If the device driver simply calls device_create_file() on the device structure passed to it, then -userspace will never be notified of the new attributes. Instead, it should -probably use class_create() and class->dev_attrs to set up a list of -desired attributes in the modules_init function, and then in the .probe() -hook, and then use device_create() to create a new device as a child -of the probed device. The new device will generate a new uevent and -properly advertise the new attributes to userspace. - -For example, if a driver wanted to add the following attributes: -struct device_attribute mydriver_attribs[] = { - __ATTR(port_count, 0444, port_count_show), - __ATTR(serial_number, 0444, serial_number_show), - NULL -}; - -Then in the module init function is would do: - mydriver_class = class_create(THIS_MODULE, "my_attrs"); - mydriver_class.dev_attr = mydriver_attribs; - -And assuming 'dev' is the struct device passed into the probe hook, the driver -probe function would do something like: - device_create(&mydriver_class, dev, chrdev, &private_data, "my_name"); +userspace will never be notified of the new attributes. diff --git a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt index 597f728..07235ca 100644 --- a/Documentation/filesystems/sysfs.txt +++ b/Documentation/filesystems/sysfs.txt @@ -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. diff --git a/Documentation/stable_kernel_rules.txt b/Documentation/stable_kernel_rules.txt index e213f45..21fd05c 100644 --- a/Documentation/stable_kernel_rules.txt +++ b/Documentation/stable_kernel_rules.txt @@ -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: diff --git a/Documentation/zh_CN/SubmitChecklist b/Documentation/zh_CN/SubmitChecklist deleted file mode 100644 index 4c741d6..0000000 --- a/Documentation/zh_CN/SubmitChecklist +++ /dev/null @@ -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) diff --git a/MAINTAINERS b/MAINTAINERS index 5ccf370..e1b0c92 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -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 diff --git a/arch/arm/plat-mxc/devices.c b/arch/arm/plat-mxc/devices.c index 0d6ed31b..a34b2ae 100644 --- a/arch/arm/plat-mxc/devices.c +++ b/arch/arm/plat-mxc/devices.c @@ -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, diff --git a/arch/arm/plat-mxc/include/mach/devices-common.h b/arch/arm/plat-mxc/include/mach/devices-common.h index 524538a..543525d 100644 --- a/arch/arm/plat-mxc/include/mach/devices-common.h +++ b/arch/arm/plat-mxc/include/mach/devices-common.h @@ -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, diff --git a/drivers/base/core.c b/drivers/base/core.c index bc8729d..82c86545 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1764,8 +1764,8 @@ void device_shutdown(void) #ifdef CONFIG_PRINTK -static int __dev_printk(const char *level, const struct device *dev, - struct va_format *vaf) +int __dev_printk(const char *level, const struct device *dev, + struct va_format *vaf) { if (!dev) return printk("%s(NULL device *): %pV", level, vaf); @@ -1773,6 +1773,7 @@ static int __dev_printk(const char *level, const struct device *dev, return printk("%s%s %s: %pV", level, dev_driver_string(dev), dev_name(dev), vaf); } +EXPORT_SYMBOL(__dev_printk); int dev_printk(const char *level, const struct device *dev, const char *fmt, ...) diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 6658da7..142e3d600 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -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 diff --git a/drivers/base/memory.c b/drivers/base/memory.c index 2840ed4..8272d92 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -224,13 +224,48 @@ int memory_isolate_notify(unsigned long val, void *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. */ 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, diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 99a5272..7a24895 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -375,52 +375,64 @@ void platform_device_unregister(struct platform_device *pdev) EXPORT_SYMBOL_GPL(platform_device_unregister); /** - * platform_device_register_resndata - add a platform-level device with + * platform_device_register_full - add a platform-level device with * resources and platform-specific data * - * @parent: parent device for the device we're adding - * @name: base name of the device we're adding - * @id: instance id - * @res: set of resources that needs to be allocated for the device - * @num: number of resources - * @data: platform specific data for this platform device - * @size: size of platform specific data + * @pdevinfo: data used to create device * * Returns &struct platform_device pointer on success, or ERR_PTR() on error. */ -struct platform_device *platform_device_register_resndata( - struct device *parent, - const char *name, int id, - const struct resource *res, unsigned int num, - const void *data, size_t size) +struct platform_device *platform_device_register_full( + struct platform_device_info *pdevinfo) { int ret = -ENOMEM; struct platform_device *pdev; - pdev = platform_device_alloc(name, id); + pdev = platform_device_alloc(pdevinfo->name, pdevinfo->id); if (!pdev) - goto err; - - pdev->dev.parent = parent; + goto err_alloc; + + pdev->dev.parent = pdevinfo->parent; + + if (pdevinfo->dma_mask) { + /* + * This memory isn't freed when the device is put, + * I don't have a nice idea for that though. Conceptually + * dma_mask in struct device should not be a pointer. + * See http://thread.gmane.org/gmane.linux.kernel.pci/9081 + */ + pdev->dev.dma_mask = + kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL); + if (!pdev->dev.dma_mask) + goto err; + + *pdev->dev.dma_mask = pdevinfo->dma_mask; + pdev->dev.coherent_dma_mask = pdevinfo->dma_mask; + } - ret = platform_device_add_resources(pdev, res, num); + ret = platform_device_add_resources(pdev, + pdevinfo->res, pdevinfo->num_res); if (ret) goto err; - ret = platform_device_add_data(pdev, data, size); + ret = platform_device_add_data(pdev, + pdevinfo->data, pdevinfo->size_data); if (ret) goto err; ret = platform_device_add(pdev); if (ret) { err: + kfree(pdev->dev.dma_mask); + +err_alloc: platform_device_put(pdev); return ERR_PTR(ret); } return pdev; } -EXPORT_SYMBOL_GPL(platform_device_register_resndata); +EXPORT_SYMBOL_GPL(platform_device_register_full); static int platform_drv_probe(struct device *_dev) { @@ -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; } diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c index 0fd7e77..dee33ad 100644 --- a/drivers/misc/pch_phub.c +++ b/drivers/misc/pch_phub.c @@ -90,6 +90,7 @@ #define PCH_PHUB_INTPIN_REG_WPERMIT_REG3 0x002C #define PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE 0x0040 #define CLKCFG_REG_OFFSET 0x500 +#define FUNCSEL_REG_OFFSET 0x508 #define PCH_PHUB_OROM_SIZE 15360 @@ -108,6 +109,7 @@ * @intpin_reg_wpermit_reg3: INTPIN_REG_WPERMIT register 3 val * @int_reduce_control_reg: INT_REDUCE_CONTROL registers val * @clkcfg_reg: CLK CFG register val + * @funcsel_reg: Function select register value * @pch_phub_base_address: Register base address * @pch_phub_extrom_base_address: external rom base address * @pch_mac_start_address: MAC address area start address @@ -128,6 +130,7 @@ struct pch_phub_reg { u32 intpin_reg_wpermit_reg3; u32 int_reduce_control_reg[MAX_NUM_INT_REDUCE_CONTROL_REG]; u32 clkcfg_reg; + u32 funcsel_reg; void __iomem *pch_phub_base_address; void __iomem *pch_phub_extrom_base_address; u32 pch_mac_start_address; @@ -211,6 +214,8 @@ static void pch_phub_save_reg_conf(struct pci_dev *pdev) __func__, i, chip->int_reduce_control_reg[i]); } chip->clkcfg_reg = ioread32(p + CLKCFG_REG_OFFSET); + if ((chip->ioh_type == 2) || (chip->ioh_type == 4)) + chip->funcsel_reg = ioread32(p + FUNCSEL_REG_OFFSET); } /* pch_phub_restore_reg_conf - restore register configuration */ @@ -271,6 +276,8 @@ static void pch_phub_restore_reg_conf(struct pci_dev *pdev) } iowrite32(chip->clkcfg_reg, p + CLKCFG_REG_OFFSET); + if ((chip->ioh_type == 2) || (chip->ioh_type == 4)) + iowrite32(chip->funcsel_reg, p + FUNCSEL_REG_OFFSET); } /** @@ -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, diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c index d2efe82..a783d53 100644 --- a/drivers/uio/uio.c +++ b/drivers/uio/uio.c @@ -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) diff --git a/drivers/uio/uio_pci_generic.c b/drivers/uio/uio_pci_generic.c index fc22e1e..02bd47b 100644 --- a/drivers/uio/uio_pci_generic.c +++ b/drivers/uio/uio_pci_generic.c @@ -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; diff --git a/drivers/uio/uio_pdrv_genirq.c b/drivers/uio/uio_pdrv_genirq.c index bae96d2..0b2ed71 100644 --- a/drivers/uio/uio_pdrv_genirq.c +++ b/drivers/uio/uio_pdrv_genirq.c @@ -253,7 +253,7 @@ static const struct dev_pm_ops uio_pdrv_genirq_dev_pm_ops = { }; #ifdef CONFIG_OF -static const struct of_device_id __devinitconst uio_of_genirq_match[] = { +static const struct of_device_id uio_of_genirq_match[] = { { /* empty for now */ }, }; MODULE_DEVICE_TABLE(of, uio_of_genirq_match); diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index e7a7a2f..f3a257d 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -1,5 +1,5 @@ /* - * file.c - part of debugfs, a tiny little debug file system + * inode.c - part of debugfs, a tiny little debug file system * * Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com> * Copyright (C) 2004 IBM Inc. diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index ea9120a..83bb9d1 100644 --- a/fs/sysfs/dir.c +++ b/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); - - /* 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; + struct rb_node **p; + struct rb_node *parent; + + 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; + + while (p) { + int c; +#define node rb_entry(p, struct sysfs_dirent, name_node) + c = strcmp(name, node->s_name); + if (c < 0) { + p = node->name_node.rb_left; + } else if (c > 0) { + p = node->name_node.rb_right; + } else { + found = node; + p = node->name_node.rb_left; + } +#undef node + } - for (sd = parent_sd->s_dir.children; sd; sd = sd->s_sibling) { - if (ns && sd->s_ns && (sd->s_ns != ns)) - continue; - if (!strcmp(sd->s_name, name)) - return sd; + if (found && ns) { + while (found->s_ns && found->s_ns != ns) { + p = rb_next(&found->name_node); + if (!p) + return NULL; + found = rb_entry(p, struct sysfs_dirent, name_node); + if (strcmp(name, found->s_name)) + return NULL; + } } - return NULL; + + return found; } /** @@ -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; } diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index e3f091a..1ee18c8 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -202,18 +202,6 @@ static inline void set_inode_attr(struct inode * inode, struct iattr * iattr) inode->i_ctime = iattr->ia_ctime; } -static int sysfs_count_nlink(struct sysfs_dirent *sd) -{ - struct sysfs_dirent *child; - int nr = 0; - - for (child = sd->s_dir.children; child; child = child->s_sibling) - if (sysfs_type(child) == SYSFS_DIR) - nr++; - - return nr + 2; -} - static void sysfs_refresh_inode(struct sysfs_dirent *sd, struct inode *inode) { struct sysfs_inode_attrs *iattrs = sd->s_iattr; @@ -230,7 +218,7 @@ static void sysfs_refresh_inode(struct sysfs_dirent *sd, struct inode *inode) } if (sysfs_type(sd) == SYSFS_DIR) - inode->i_nlink = sysfs_count_nlink(sd); + inode->i_nlink = sd->s_dir.subdirs + 2; } int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 845ab3a..ce29e28 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -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; diff --git a/include/linux/device.h b/include/linux/device.h index c20dfbf..4639419 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -785,6 +785,8 @@ extern const char *dev_driver_string(const struct device *dev); #ifdef CONFIG_PRINTK +extern int __dev_printk(const char *level, const struct device *dev, + struct va_format *vaf); extern int dev_printk(const char *level, const struct device *dev, const char *fmt, ...) __attribute__ ((format (printf, 3, 4))); @@ -805,6 +807,9 @@ extern int _dev_info(const struct device *dev, const char *fmt, ...) #else +static inline int __dev_printk(const char *level, const struct device *dev, + struct va_format *vaf) + { return 0; } static inline int dev_printk(const char *level, const struct device *dev, const char *fmt, ...) __attribute__ ((format (printf, 3, 4))); diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h index e747ecd..13aae80 100644 --- a/include/linux/dynamic_debug.h +++ b/include/linux/dynamic_debug.h @@ -1,13 +1,6 @@ #ifndef _DYNAMIC_DEBUG_H #define _DYNAMIC_DEBUG_H -/* dynamic_printk_enabled, and dynamic_printk_enabled2 are bitmasks in which - * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They - * use independent hash functions, to reduce the chance of false positives. - */ -extern long long dynamic_debug_enabled; -extern long long dynamic_debug_enabled2; - /* * An instance of this structure is created in a special * ELF section at every dynamic debug callsite. At runtime, @@ -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) - - -#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 device; + +extern int __dynamic_dev_dbg(struct _ddebug *descriptor, + const struct device *dev, + const char *fmt, ...) + __attribute__ ((format (printf, 3, 4))); + +struct net_device; + +extern int __dynamic_netdev_dbg(struct _ddebug *descriptor, + const struct net_device *dev, + const char *fmt, ...) + __attribute__ ((format (printf, 3, 4))); + +#define 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 diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index ddee79b..2797260 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -2617,6 +2617,9 @@ static inline const char *netdev_name(const struct net_device *dev) return dev->name; } +extern int __netdev_printk(const char *level, const struct net_device *dev, + struct va_format *vaf); + extern int netdev_printk(const char *level, const struct net_device *dev, const char *format, ...) __attribute__ ((format (printf, 3, 4))); @@ -2644,8 +2647,7 @@ extern int netdev_info(const struct net_device *dev, const char *format, ...) #elif defined(CONFIG_DYNAMIC_DEBUG) #define netdev_dbg(__dev, format, args...) \ do { \ - dynamic_dev_dbg((__dev)->dev.parent, "%s: " format, \ - netdev_name(__dev), ##args); \ + dynamic_netdev_dbg(__dev, format, ##args); \ } while (0) #else #define netdev_dbg(__dev, format, args...) \ @@ -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...) \ diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 27bb05a..651a066 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -49,10 +49,54 @@ extern struct resource *platform_get_resource_byname(struct platform_device *, u extern int platform_get_irq_byname(struct platform_device *, const char *); extern int platform_add_devices(struct platform_device **, int); -extern struct platform_device *platform_device_register_resndata( +struct platform_device_info { + struct device *parent; + + const char *name; + int id; + + const struct resource *res; + unsigned int num_res; + + const void *data; + size_t size_data; + u64 dma_mask; +}; +extern struct platform_device *platform_device_register_full( + struct platform_device_info *pdevinfo); + +/** + * platform_device_register_resndata - add a platform-level device with + * resources and platform-specific data + * + * @parent: parent device for the device we're adding + * @name: base name of the device we're adding + * @id: instance id + * @res: set of resources that needs to be allocated for the device + * @num: number of resources + * @data: platform specific data for this platform device + * @size: size of platform specific data + * + * Returns &struct platform_device pointer on success, or ERR_PTR() on error. + */ +static inline struct platform_device *platform_device_register_resndata( struct device *parent, const char *name, int id, const struct resource *res, unsigned int num, - const void *data, size_t size); + const void *data, size_t size) { + + struct platform_device_info pdevinfo = { + .parent = parent, + .name = name, + .id = id, + .res = res, + .num_res = num, + .data = data, + .size_data = size, + .dma_mask = 0, + }; + + return platform_device_register_full(&pdevinfo); +} /** * platform_device_register_simple - add a platform-level device and its resources diff --git a/include/linux/uio_driver.h b/include/linux/uio_driver.h index 665517c..fd99ff9 100644 --- a/include/linux/uio_driver.h +++ b/include/linux/uio_driver.h @@ -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; diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c index 79fc20b..dcdade3 100644 --- a/lib/dynamic_debug.c +++ b/lib/dynamic_debug.c @@ -10,6 +10,8 @@ * Copyright (C) 2011 Bart Van Assche. All Rights Reserved. */ +#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__ + #include <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); diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c index 70af0a7..ad72a03 100644 --- a/lib/kobject_uevent.c +++ b/lib/kobject_uevent.c @@ -282,7 +282,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, kobj_bcast_filter, kobj); /* ENOBUFS should be handled in userspace */ - if (retval == -ENOBUFS) + if (retval == -ENOBUFS || retval == -ESRCH) retval = 0; } else retval = -ENOMEM; diff --git a/net/core/dev.c b/net/core/dev.c index b10ff0a..231d312 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -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, ...) |