From ec748fa9ed3fec44aeebbf86ae050b0cc7a978d9 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 21 Jul 2008 22:33:36 +0300 Subject: driver core: make struct platform_pm_ops static This patch makes the needlessly global struct platform_pm_ops static. Signed-off-by: Adrian Bunk Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/base') diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 3f940393d6c7..e621dade7eaa 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -862,7 +862,7 @@ static int platform_pm_restore_noirq(struct device *dev) #endif /* !CONFIG_HIBERNATION */ -struct pm_ext_ops platform_pm_ops = { +static struct pm_ext_ops platform_pm_ops = { .base = { .prepare = platform_pm_prepare, .complete = platform_pm_complete, -- cgit v1.2.3 From 5739411acbaa63a6c22c91e340fdcdbcc7d82a51 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Wed, 3 Sep 2008 18:26:40 +0200 Subject: Driver core: Clarify device cleanup. Make the comments on how to use device_initialize(), device_add() and device_register() a bit clearer - in particular, explicitly note that put_device() must be used once we tried to add the device to the hierarchy. Signed-off-by: Cornelia Huck Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/core.c b/drivers/base/core.c index b98cb1416a2d..aac91e89d6af 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -523,11 +523,16 @@ static void klist_children_put(struct klist_node *n) * device_initialize - init device structure. * @dev: device. * - * This prepares the device for use by other layers, - * including adding it to the device hierarchy. + * This prepares the device for use by other layers by initializing + * its fields. * It is the first half of device_register(), if called by - * that, though it can also be called separately, so one - * may use @dev's fields (e.g. the refcount). + * that function, though it can also be called separately, so one + * may use @dev's fields. In particular, get_device()/put_device() + * may be used for reference counting of @dev after calling this + * function. + * + * NOTE: Use put_device() to give up your reference instead of freeing + * @dev directly once you have called this function. */ void device_initialize(struct device *dev) { @@ -835,9 +840,13 @@ static void device_remove_sys_dev_entry(struct device *dev) * This is part 2 of device_register(), though may be called * separately _iff_ device_initialize() has been called separately. * - * This adds it to the kobject hierarchy via kobject_add(), adds it + * This adds @dev to the kobject hierarchy via kobject_add(), adds it * to the global and sibling lists for the device, then * adds it to the other relevant subsystems of the driver model. + * + * NOTE: _Never_ directly free @dev after calling this function, even + * if it returned an error! Always use put_device() to give up your + * reference instead. */ int device_add(struct device *dev) { @@ -965,6 +974,10 @@ done: * I.e. you should only call the two helpers separately if * have a clearly defined need to use and refcount the device * before it is added to the hierarchy. + * + * NOTE: _Never_ directly free @dev after calling this function, even + * if it returned an error! Always use put_device() to give up the + * reference initialized in this function instead. */ int device_register(struct device *dev) { -- cgit v1.2.3 From 286661b3777897220ecfcd774bccc68a34667f39 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Wed, 3 Sep 2008 18:26:41 +0200 Subject: Driver core: Fix cleanup in device_create_vargs(). If device_register() in device_create_vargs() fails, the device must be cleaned up with put_device() (which is also fine on NULL) instead of kfree(). Signed-off-by: Cornelia Huck Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/base') diff --git a/drivers/base/core.c b/drivers/base/core.c index aac91e89d6af..9649d1c422a4 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1256,7 +1256,7 @@ struct device *device_create_vargs(struct class *class, struct device *parent, return dev; error: - kfree(dev); + put_device(dev); return ERR_PTR(retval); } EXPORT_SYMBOL_GPL(device_create_vargs); -- cgit v1.2.3 From 6cd49586090187a2a145bb6570fb2392f121aa22 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Sun, 14 Sep 2008 08:32:06 -0700 Subject: device model: Do a quickcheck for driver binding before doing an expensive check This patch adds a quick check for the driver<->device match before taking the locks and doin gthe expensive checks. Taking the lock hurts in asynchronous boot context where the device lock gets hit; one of the init functions takes the lock and goes to do an expensive hardware init; the other init functions walk the same PCI list and get stuck on the lock as a result. For the common case, we can know there's no chance whatsoever of a match if the device isn't in the drivers ID table... so this patch does that check as a best-effort-avoid-the-lock approach. Bootcharts for before and after can be seen at http://www.fenrus.org/before.svg http://www.fenrus.org/after.svg Note the long time "agp_ali_init" takes in the first graph; my laptop doesn't even have an ALI chip in it! (the bootgraphs look a bit dissimilar, but that's the point, the first one has a bunch of arbitrary delays in it that cause it to look very different) This reduces my kernel boot time by about 20% Signed-off-by: Arjan van de Ven Cc: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/base/dd.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/base') diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 3ac443b2ac08..20febc00a525 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -257,6 +257,9 @@ static int __driver_attach(struct device *dev, void *data) * is an error. */ + if (drv->bus->match && !drv->bus->match(dev, drv)) + return 0; + if (dev->parent) /* Needed for USB */ down(&dev->parent->sem); down(&dev->sem); -- cgit v1.2.3 From 728f08934b087b96aacb00467f5551e0a5593fca Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Sat, 20 Sep 2008 19:09:00 -0700 Subject: debug: use dev_WARN() rather than WARN_ON() in device_pm_add() device_pm_add() has a WARN_ON that is showing relatively high on kerneloops.org, but unfortunately the WARN_ON is less than useful in that it doesn't print any information about what device is causing the issue. This patch fixes this by turning the WARN_ON() into the newly introduces dev_WARN() which will print information about the device in question. Signed-off-by: Arjan van de Ven Signed-off-by: Greg Kroah-Hartman --- drivers/base/power/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/base') diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 273a944d4040..b0eb6afdd861 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -83,7 +83,7 @@ void device_pm_add(struct device *dev) * transition is in progress in order to avoid leaving them * unhandled down the road */ - WARN_ON(true); + dev_WARN(dev, "Parentless device registered during a PM transaction\n"); } list_add_tail(&dev->power.entry, &dpm_list); -- cgit v1.2.3 From 3ce24d8d93f8f9617841d0c8416174da7ee1b042 Mon Sep 17 00:00:00 2001 From: Peter Korsgaard Date: Tue, 23 Sep 2008 22:01:27 +0200 Subject: Driver core: make bus_find_device_by_name() more robust Use sysfs_streq() in bus_find_device_by_name() so trailing newlines are ignored (E.G. in bind/unbind). Signed-off-by: Peter Korsgaard Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/bus.c b/drivers/base/bus.c index ef522ae55480..39b9b58c6974 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -333,9 +333,7 @@ static int match_name(struct device *dev, void *data) { const char *name = data; - if (strcmp(name, dev->bus_id) == 0) - return 1; - return 0; + return sysfs_streq(name, dev->bus_id); } /** -- cgit v1.2.3 From d8bf254089a6c31d7d01a4d1d2f1861662900855 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 22 Sep 2008 14:41:40 -0700 Subject: platform: add new device registration helper Add a helper that registers simple platform_device w/o resources but with parent and device data. This is usefull to cleanup platform code from code that registers such simple devices as leds-gpio, generic-bl, etc. Signed-off-by: Dmitry Baryshkov Cc: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) (limited to 'drivers/base') diff --git a/drivers/base/platform.c b/drivers/base/platform.c index e621dade7eaa..9e60f7c739c6 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -391,6 +391,53 @@ error: } EXPORT_SYMBOL_GPL(platform_device_register_simple); +/** + * platform_device_register_data + * @parent: parent device for the device we're adding + * @name: base name of the device we're adding + * @id: instance id + * @data: platform specific data for this platform device + * @size: size of platform specific data + * + * This function creates a simple platform device that requires minimal + * resource and memory management. Canned release function freeing memory + * allocated for the device allows drivers using such devices to be + * unloaded without waiting for the last reference to the device to be + * dropped. + */ +struct platform_device *platform_device_register_data( + struct device *parent, + const char *name, int id, + const void *data, size_t size) +{ + struct platform_device *pdev; + int retval; + + pdev = platform_device_alloc(name, id); + if (!pdev) { + retval = -ENOMEM; + goto error; + } + + pdev->dev.parent = parent; + + if (size) { + retval = platform_device_add_data(pdev, data, size); + if (retval) + goto error; + } + + retval = platform_device_add(pdev); + if (retval) + goto error; + + return pdev; + +error: + platform_device_put(pdev); + return ERR_PTR(retval); +} + static int platform_drv_probe(struct device *_dev) { struct platform_driver *drv = to_platform_driver(_dev->driver); -- cgit v1.2.3 From 030c1d2bfcc2187650fb975456ca0b61a5bb77f4 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 8 May 2008 14:41:00 -0700 Subject: kobject: Fix kobject_rename and !CONFIG_SYSFS When looking at kobject_rename I found two bugs with that exist when sysfs support is disabled in the kernel. kobject_rename does not change the name on the kobject when sysfs support is not compiled in. kobject_rename without locking attempts to check the validity of a rename operation, which the kobject layer simply does not have the infrastructure to do. This patch documents the previously unstated requirement of kobject_rename that is the responsibility of the caller to provide mutual exclusion and to be certain that the new_name for the kobject is valid. This patch modifies sysfs_rename_dir in !CONFIG_SYSFS case to call kobject_set_name to actually change the kobject_name. This patch removes the bogus and misleading check in kobject_rename that attempts to see if a rename is valid. The check is bogus because we do not have the proper locking. The check is misleading because it looks like we can and do perform checking at the kobject level that we don't. Signed-off-by: Eric W. Biederman Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/base') diff --git a/drivers/base/core.c b/drivers/base/core.c index 9649d1c422a4..8c2cc2648f5a 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1327,6 +1327,11 @@ EXPORT_SYMBOL_GPL(device_destroy); * device_rename - renames a device * @dev: the pointer to the struct device to be renamed * @new_name: the new name of the device + * + * It is the responsibility of the caller to provide mutual + * exclusion between two different calls of device_rename + * on the same device to ensure that new_name is valid and + * won't conflict with other devices. */ int device_rename(struct device *dev, char *new_name) { -- cgit v1.2.3 From 99178b036c97293a65004ff5ec5cff9f833aaecd Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 26 Aug 2008 11:00:57 -0500 Subject: Driver core: add bus_sort_breadthfirst() function The PCI core wants to reorder the devices in the bus list. So move this functionality out of the pci core and into the driver core so that anyone else can also do this if needed. This also lets us change how struct device is attached to drivers in the future without messing with the PCI core. Acked-by: Jesse Barnes Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'drivers/base') diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 39b9b58c6974..5aee1c0169ea 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -980,6 +980,56 @@ struct klist *bus_get_device_klist(struct bus_type *bus) } EXPORT_SYMBOL_GPL(bus_get_device_klist); +/* + * Yes, this forcably breaks the klist abstraction temporarily. It + * just wants to sort the klist, not change reference counts and + * take/drop locks rapidly in the process. It does all this while + * holding the lock for the list, so objects can't otherwise be + * added/removed while we're swizzling. + */ +static void device_insertion_sort_klist(struct device *a, struct list_head *list, + int (*compare)(const struct device *a, + const struct device *b)) +{ + struct list_head *pos; + struct klist_node *n; + struct device *b; + + list_for_each(pos, list) { + n = container_of(pos, struct klist_node, n_node); + b = container_of(n, struct device, knode_bus); + if (compare(a, b) <= 0) { + list_move_tail(&a->knode_bus.n_node, + &b->knode_bus.n_node); + return; + } + } + list_move_tail(&a->knode_bus.n_node, list); +} + +void bus_sort_breadthfirst(struct bus_type *bus, + int (*compare)(const struct device *a, + const struct device *b)) +{ + LIST_HEAD(sorted_devices); + struct list_head *pos, *tmp; + struct klist_node *n; + struct device *dev; + struct klist *device_klist; + + device_klist = bus_get_device_klist(bus); + + spin_lock(&device_klist->k_lock); + list_for_each_safe(pos, tmp, &device_klist->k_list) { + n = container_of(pos, struct klist_node, n_node); + dev = container_of(n, struct device, knode_bus); + device_insertion_sort_klist(dev, &sorted_devices, compare); + } + list_splice(&sorted_devices, &device_klist->k_list); + spin_unlock(&device_klist->k_lock); +} +EXPORT_SYMBOL_GPL(bus_sort_breadthfirst); + int __init buses_init(void) { bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL); -- cgit v1.2.3 From c80cfb0406c01bb5da91bfe30f5cb1fd96831138 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 15 Oct 2008 22:01:35 -0700 Subject: vsprintf: use new vsprintf symbolic function pointer format Use the '%pF' format to get rid of an "#ifdef DEBUG" and make some printks atomic. This removes the last in-tree uses of print_fn_descriptor_symbol(). I marked print_fn_descriptor_symbol() deprecated and scheduled it for removal next year to give time for out-of-tree modules to be updated. parisc's print_fn_descriptor_symbol() is currently broken there (it needs to dereference the function pointer similar to ia64 and power). This patch shouldn't make anything worse, but it means we need to fix dereference_function_descriptor() instead of print_fn_descriptor_symbol() to get meaningful initcall_debug output. Signed-off-by: Bjorn Helgaas Cc: Jesse Barnes Cc: Kyle McMartin Cc: "Rafael J. Wysocki" Cc: Kay Sievers Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/base/power/main.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 273a944d4040..03bde7524bc3 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -778,10 +778,7 @@ EXPORT_SYMBOL_GPL(device_suspend); void __suspend_report_result(const char *function, void *fn, int ret) { - if (ret) { - printk(KERN_ERR "%s(): ", function); - print_fn_descriptor_symbol("%s returns ", fn); - printk("%d\n", ret); - } + if (ret) + printk(KERN_ERR "%s(): %pF returns %d\n", function, fn, ret); } EXPORT_SYMBOL_GPL(__suspend_report_result); -- cgit v1.2.3 From d133181d873255cb071f8b19c4b2c1f326c2de95 Mon Sep 17 00:00:00 2001 From: Alberto Bertogli Date: Wed, 15 Oct 2008 22:01:53 -0700 Subject: Fix typo in the FIRMWARE_IN_KERNEL help Signed-off-by: Alberto Bertogli Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/base/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/base') diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index 6318f6b57360..d8e8c49c0cbd 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig @@ -54,7 +54,7 @@ config FIRMWARE_IN_KERNEL such firmware, and do not wish to use an initrd. This single option controls the inclusion of firmware for - every driver which usees request_firmare() and ships its + every driver which uses request_firmare() and ships its firmware in the kernel source tree, to avoid a proliferation of 'Include firmware for xxx device' options. -- cgit v1.2.3 From 266a813c083d67886d89f1066ea6355857b51f83 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 15 Oct 2008 22:04:20 -0700 Subject: firmware: use dev_printk when possible Convert printks to use dev_printk(). Signed-off-by: Bjorn Helgaas Cc: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/base/firmware_class.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index c9c92b00fd55..b7e571031ecd 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -164,8 +164,7 @@ static ssize_t firmware_loading_store(struct device *dev, } /* fallthrough */ default: - printk(KERN_ERR "%s: unexpected value (%d)\n", __func__, - loading); + dev_err(dev, "%s: unexpected value (%d)\n", __func__, loading); /* fallthrough */ case -1: fw_load_abort(fw_priv); @@ -309,7 +308,7 @@ static int fw_register_device(struct device **dev_p, const char *fw_name, *dev_p = NULL; if (!fw_priv || !f_dev) { - printk(KERN_ERR "%s: kmalloc failed\n", __func__); + dev_err(device, "%s: kmalloc failed\n", __func__); retval = -ENOMEM; goto error_kfree; } @@ -329,8 +328,7 @@ static int fw_register_device(struct device **dev_p, const char *fw_name, f_dev->uevent_suppress = 1; retval = device_register(f_dev); if (retval) { - printk(KERN_ERR "%s: device_register failed\n", - __func__); + dev_err(device, "%s: device_register failed\n", __func__); goto error_kfree; } *dev_p = f_dev; @@ -363,15 +361,13 @@ static int fw_setup_device(struct firmware *fw, struct device **dev_p, fw_priv->fw = fw; retval = sysfs_create_bin_file(&f_dev->kobj, &fw_priv->attr_data); if (retval) { - printk(KERN_ERR "%s: sysfs_create_bin_file failed\n", - __func__); + dev_err(device, "%s: sysfs_create_bin_file failed\n", __func__); goto error_unreg; } retval = device_create_file(f_dev, &dev_attr_loading); if (retval) { - printk(KERN_ERR "%s: device_create_file failed\n", - __func__); + dev_err(device, "%s: device_create_file failed\n", __func__); goto error_unreg; } @@ -401,8 +397,8 @@ _request_firmware(const struct firmware **firmware_p, const char *name, *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL); if (!firmware) { - printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n", - __func__); + dev_err(device, "%s: kmalloc(struct firmware) failed\n", + __func__); retval = -ENOMEM; goto out; } @@ -411,15 +407,15 @@ _request_firmware(const struct firmware **firmware_p, const char *name, builtin++) { if (strcmp(name, builtin->name)) continue; - printk(KERN_INFO "firmware: using built-in firmware %s\n", - name); + dev_info(device, "firmware: using built-in firmware %s\n", + name); firmware->size = builtin->size; firmware->data = builtin->data; return 0; } if (uevent) - printk(KERN_INFO "firmware: requesting %s\n", name); + dev_info(device, "firmware: requesting %s\n", name); retval = fw_setup_device(firmware, &f_dev, name, device, uevent); if (retval) -- cgit v1.2.3 From c9f66169f1c696f9489503d7de92daff135c1efd Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 15 Oct 2008 22:05:15 -0700 Subject: resource: add resource_type() and IORESOURCE_TYPE_BITS Add resource_type() and IORESOURCE_TYPE_BITS. They make it easier to add more resource types without having to rewrite tons of code. Signed-off-by: Magnus Damm Cc: Ben Dooks Cc: Jean Delvare Cc: Paul Mundt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/base/platform.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 3f940393d6c7..66b710c28812 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -42,10 +42,8 @@ struct resource *platform_get_resource(struct platform_device *dev, for (i = 0; i < dev->num_resources; i++) { struct resource *r = &dev->resource[i]; - if ((r->flags & (IORESOURCE_IO|IORESOURCE_MEM| - IORESOURCE_IRQ|IORESOURCE_DMA)) == type) - if (num-- == 0) - return r; + if (type == resource_type(r) && num-- == 0) + return r; } return NULL; } @@ -78,10 +76,8 @@ struct resource *platform_get_resource_byname(struct platform_device *dev, for (i = 0; i < dev->num_resources; i++) { struct resource *r = &dev->resource[i]; - if ((r->flags & (IORESOURCE_IO|IORESOURCE_MEM| - IORESOURCE_IRQ|IORESOURCE_DMA)) == type) - if (!strcmp(r->name, name)) - return r; + if (type == resource_type(r) && !strcmp(r->name, name)) + return r; } return NULL; } @@ -259,9 +255,9 @@ int platform_device_add(struct platform_device *pdev) p = r->parent; if (!p) { - if (r->flags & IORESOURCE_MEM) + if (resource_type(r) == IORESOURCE_MEM) p = &iomem_resource; - else if (r->flags & IORESOURCE_IO) + else if (resource_type(r) == IORESOURCE_IO) p = &ioport_resource; } @@ -282,9 +278,14 @@ int platform_device_add(struct platform_device *pdev) return ret; failed: - while (--i >= 0) - if (pdev->resource[i].flags & (IORESOURCE_MEM|IORESOURCE_IO)) - release_resource(&pdev->resource[i]); + while (--i >= 0) { + struct resource *r = &pdev->resource[i]; + unsigned long type = resource_type(r); + + if (type == IORESOURCE_MEM || type == IORESOURCE_IO) + release_resource(r); + } + return ret; } EXPORT_SYMBOL_GPL(platform_device_add); @@ -306,7 +307,9 @@ void platform_device_del(struct platform_device *pdev) for (i = 0; i < pdev->num_resources; i++) { struct resource *r = &pdev->resource[i]; - if (r->flags & (IORESOURCE_MEM|IORESOURCE_IO)) + unsigned long type = resource_type(r); + + if (type == IORESOURCE_MEM || type == IORESOURCE_IO) release_resource(r); } } -- cgit v1.2.3 From 4f98a2fee8acdb4ac84545df98cccecfd130f8db Mon Sep 17 00:00:00 2001 From: Rik van Riel Date: Sat, 18 Oct 2008 20:26:32 -0700 Subject: vmscan: split LRU lists into anon & file sets Split the LRU lists in two, one set for pages that are backed by real file systems ("file") and one for pages that are backed by memory and swap ("anon"). The latter includes tmpfs. The advantage of doing this is that the VM will not have to scan over lots of anonymous pages (which we generally do not want to swap out), just to find the page cache pages that it should evict. This patch has the infrastructure and a basic policy to balance how much we scan the anon lists and how much we scan the file lists. The big policy changes are in separate patches. [lee.schermerhorn@hp.com: collect lru meminfo statistics from correct offset] [kosaki.motohiro@jp.fujitsu.com: prevent incorrect oom under split_lru] [kosaki.motohiro@jp.fujitsu.com: fix pagevec_move_tail() doesn't treat unevictable page] [hugh@veritas.com: memcg swapbacked pages active] [hugh@veritas.com: splitlru: BDI_CAP_SWAP_BACKED] [akpm@linux-foundation.org: fix /proc/vmstat units] [nishimura@mxp.nes.nec.co.jp: memcg: fix handling of shmem migration] [kosaki.motohiro@jp.fujitsu.com: adjust Quicklists field of /proc/meminfo] [kosaki.motohiro@jp.fujitsu.com: fix style issue of get_scan_ratio()] Signed-off-by: Rik van Riel Signed-off-by: Lee Schermerhorn Signed-off-by: KOSAKI Motohiro Signed-off-by: Hugh Dickins Signed-off-by: Daisuke Nishimura Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/base/node.c | 56 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 23 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/node.c b/drivers/base/node.c index 5116b78c6325..fc7e9bf0cdbc 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -61,34 +61,44 @@ static ssize_t node_read_meminfo(struct sys_device * dev, si_meminfo_node(&i, nid); n = sprintf(buf, "\n" - "Node %d MemTotal: %8lu kB\n" - "Node %d MemFree: %8lu kB\n" - "Node %d MemUsed: %8lu kB\n" - "Node %d Active: %8lu kB\n" - "Node %d Inactive: %8lu kB\n" + "Node %d MemTotal: %8lu kB\n" + "Node %d MemFree: %8lu kB\n" + "Node %d MemUsed: %8lu kB\n" + "Node %d Active: %8lu kB\n" + "Node %d Inactive: %8lu kB\n" + "Node %d Active(anon): %8lu kB\n" + "Node %d Inactive(anon): %8lu kB\n" + "Node %d Active(file): %8lu kB\n" + "Node %d Inactive(file): %8lu kB\n" #ifdef CONFIG_HIGHMEM - "Node %d HighTotal: %8lu kB\n" - "Node %d HighFree: %8lu kB\n" - "Node %d LowTotal: %8lu kB\n" - "Node %d LowFree: %8lu kB\n" + "Node %d HighTotal: %8lu kB\n" + "Node %d HighFree: %8lu kB\n" + "Node %d LowTotal: %8lu kB\n" + "Node %d LowFree: %8lu kB\n" #endif - "Node %d Dirty: %8lu kB\n" - "Node %d Writeback: %8lu kB\n" - "Node %d FilePages: %8lu kB\n" - "Node %d Mapped: %8lu kB\n" - "Node %d AnonPages: %8lu kB\n" - "Node %d PageTables: %8lu kB\n" - "Node %d NFS_Unstable: %8lu kB\n" - "Node %d Bounce: %8lu kB\n" - "Node %d WritebackTmp: %8lu kB\n" - "Node %d Slab: %8lu kB\n" - "Node %d SReclaimable: %8lu kB\n" - "Node %d SUnreclaim: %8lu kB\n", + "Node %d Dirty: %8lu kB\n" + "Node %d Writeback: %8lu kB\n" + "Node %d FilePages: %8lu kB\n" + "Node %d Mapped: %8lu kB\n" + "Node %d AnonPages: %8lu kB\n" + "Node %d PageTables: %8lu kB\n" + "Node %d NFS_Unstable: %8lu kB\n" + "Node %d Bounce: %8lu kB\n" + "Node %d WritebackTmp: %8lu kB\n" + "Node %d Slab: %8lu kB\n" + "Node %d SReclaimable: %8lu kB\n" + "Node %d SUnreclaim: %8lu kB\n", nid, K(i.totalram), nid, K(i.freeram), nid, K(i.totalram - i.freeram), - nid, K(node_page_state(nid, NR_ACTIVE)), - nid, K(node_page_state(nid, NR_INACTIVE)), + nid, K(node_page_state(nid, NR_ACTIVE_ANON) + + node_page_state(nid, NR_ACTIVE_FILE)), + nid, K(node_page_state(nid, NR_INACTIVE_ANON) + + node_page_state(nid, NR_INACTIVE_FILE)), + nid, K(node_page_state(nid, NR_ACTIVE_ANON)), + nid, K(node_page_state(nid, NR_INACTIVE_ANON)), + nid, K(node_page_state(nid, NR_ACTIVE_FILE)), + nid, K(node_page_state(nid, NR_INACTIVE_FILE)), #ifdef CONFIG_HIGHMEM nid, K(i.totalhigh), nid, K(i.freehigh), -- cgit v1.2.3 From 7b854121eb3e5ba0241882ff939e2c485228c9c5 Mon Sep 17 00:00:00 2001 From: Lee Schermerhorn Date: Sat, 18 Oct 2008 20:26:40 -0700 Subject: Unevictable LRU Page Statistics Report unevictable pages per zone and system wide. Kosaki Motohiro added support for memory controller unevictable statistics. [riel@redhat.com: fix printk in show_free_areas()] [akpm@linux-foundation.org: fix units in /proc/vmstats] Signed-off-by: Lee Schermerhorn Signed-off-by: Rik van Riel Signed-off-by: KOSAKI Motohiro Debugged-by: Hiroshi Shimamoto Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/base/node.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/base') diff --git a/drivers/base/node.c b/drivers/base/node.c index fc7e9bf0cdbc..11a9a05cf554 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -70,6 +70,9 @@ static ssize_t node_read_meminfo(struct sys_device * dev, "Node %d Inactive(anon): %8lu kB\n" "Node %d Active(file): %8lu kB\n" "Node %d Inactive(file): %8lu kB\n" +#ifdef CONFIG_UNEVICTABLE_LRU + "Node %d Noreclaim: %8lu kB\n" +#endif #ifdef CONFIG_HIGHMEM "Node %d HighTotal: %8lu kB\n" "Node %d HighFree: %8lu kB\n" @@ -99,6 +102,9 @@ static ssize_t node_read_meminfo(struct sys_device * dev, nid, K(node_page_state(nid, NR_INACTIVE_ANON)), nid, K(node_page_state(nid, NR_ACTIVE_FILE)), nid, K(node_page_state(nid, NR_INACTIVE_FILE)), +#ifdef CONFIG_UNEVICTABLE_LRU + nid, K(node_page_state(nid, NR_UNEVICTABLE)), +#endif #ifdef CONFIG_HIGHMEM nid, K(i.totalhigh), nid, K(i.freehigh), -- cgit v1.2.3 From 5344b7e648980cc2ca613ec03a56a8222ff48820 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Sat, 18 Oct 2008 20:26:51 -0700 Subject: vmstat: mlocked pages statistics Add NR_MLOCK zone page state, which provides a (conservative) count of mlocked pages (actually, the number of mlocked pages moved off the LRU). Reworked by lts to fit in with the modified mlock page support in the Reclaim Scalability series. [kosaki.motohiro@jp.fujitsu.com: fix incorrect Mlocked field of /proc/meminfo] [lee.schermerhorn@hp.com: mlocked-pages: add event counting with statistics] Signed-off-by: Nick Piggin Signed-off-by: Lee Schermerhorn Signed-off-by: Rik van Riel Signed-off-by: KOSAKI Motohiro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/base/node.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/base') diff --git a/drivers/base/node.c b/drivers/base/node.c index 11a9a05cf554..fb45d88a2446 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -71,7 +71,8 @@ static ssize_t node_read_meminfo(struct sys_device * dev, "Node %d Active(file): %8lu kB\n" "Node %d Inactive(file): %8lu kB\n" #ifdef CONFIG_UNEVICTABLE_LRU - "Node %d Noreclaim: %8lu kB\n" + "Node %d Unevictable: %8lu kB\n" + "Node %d Mlocked: %8lu kB\n" #endif #ifdef CONFIG_HIGHMEM "Node %d HighTotal: %8lu kB\n" @@ -104,6 +105,7 @@ static ssize_t node_read_meminfo(struct sys_device * dev, nid, K(node_page_state(nid, NR_INACTIVE_FILE)), #ifdef CONFIG_UNEVICTABLE_LRU nid, K(node_page_state(nid, NR_UNEVICTABLE)), + nid, K(node_page_state(nid, NR_MLOCK)), #endif #ifdef CONFIG_HIGHMEM nid, K(i.totalhigh), -- cgit v1.2.3 From af936a1606246a10c145feac3770f6287f483f02 Mon Sep 17 00:00:00 2001 From: Lee Schermerhorn Date: Sat, 18 Oct 2008 20:26:53 -0700 Subject: vmscan: unevictable LRU scan sysctl This patch adds a function to scan individual or all zones' unevictable lists and move any pages that have become evictable onto the respective zone's inactive list, where shrink_inactive_list() will deal with them. Adds sysctl to scan all nodes, and per node attributes to individual nodes' zones. Kosaki: If evictable page found in unevictable lru when write /proc/sys/vm/scan_unevictable_pages, print filename and file offset of these pages. [akpm@linux-foundation.org: fix one CONFIG_MMU=n build error] [kosaki.motohiro@jp.fujitsu.com: adapt vmscan-unevictable-lru-scan-sysctl.patch to new sysfs API] Signed-off-by: Lee Schermerhorn Signed-off-by: Rik van Riel Signed-off-by: KOSAKI Motohiro Signed-off-by: KOSAKI Motohiro Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/base/node.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/base') diff --git a/drivers/base/node.c b/drivers/base/node.c index fb45d88a2446..f5207090885a 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -13,6 +13,7 @@ #include #include #include +#include static struct sysdev_class node_class = { .name = "node", @@ -191,6 +192,8 @@ int register_node(struct node *node, int num, struct node *parent) sysdev_create_file(&node->sysdev, &attr_meminfo); sysdev_create_file(&node->sysdev, &attr_numastat); sysdev_create_file(&node->sysdev, &attr_distance); + + scan_unevictable_register_node(node); } return error; } @@ -210,6 +213,8 @@ void unregister_node(struct node *node) sysdev_remove_file(&node->sysdev, &attr_numastat); sysdev_remove_file(&node->sysdev, &attr_distance); + scan_unevictable_unregister_node(node); + sysdev_unregister(&node->sysdev); } -- cgit v1.2.3 From 9f1b16a51ea7180eca8a0d76a6bd587385a30757 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Sat, 18 Oct 2008 20:27:12 -0700 Subject: memory_probe: fix wrong sysfs file attribute This attribute just has a write operation. [akpm@linux-foundation.org: use S_IWUSR as suggested by Randy] Signed-off-by: Shaohua Li Cc: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/base/memory.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/base') diff --git a/drivers/base/memory.c b/drivers/base/memory.c index af0d175c025d..5260e9e0df48 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -21,6 +21,8 @@ #include #include #include +#include + #include #include @@ -325,7 +327,7 @@ memory_probe_store(struct class *class, const char *buf, size_t count) return count; } -static CLASS_ATTR(probe, 0700, NULL, memory_probe_store); +static CLASS_ATTR(probe, S_IWUSR, NULL, memory_probe_store); static int memory_probe_init(void) { -- cgit v1.2.3 From 65151365ad59af00e229d0fe33b4f1f9350c685f Mon Sep 17 00:00:00 2001 From: Qinghuang Feng Date: Mon, 13 Oct 2008 18:05:04 +0800 Subject: driver core: drivers/base/sys.c: update comments There are no functions named sys_device_shutdown or sys_device_suspend in the kernel. They should be fixed to sysdev_shutdown and sysdev_suspend respectively. Signed-off-by: Qinghuang Feng Signed-off-by: Greg Kroah-Hartman --- drivers/base/sys.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/sys.c b/drivers/base/sys.c index 75dd6e22faff..3ca9c5e8d765 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c @@ -355,7 +355,7 @@ static void __sysdev_resume(struct sys_device *dev) * sysdev_suspend - Suspend all system devices. * @state: Power state to enter. * - * We perform an almost identical operation as sys_device_shutdown() + * We perform an almost identical operation as sysdev_shutdown() * above, though calling ->suspend() instead. Interrupts are disabled * when this called. Devices are responsible for both saving state and * quiescing or powering down the device. @@ -437,7 +437,7 @@ aux_driver: /** * sysdev_resume - Bring system devices back to life. * - * Similar to sys_device_suspend(), but we iterate the list forwards + * Similar to sysdev_suspend(), but we iterate the list forwards * to guarantee that parent devices are resumed before their children. * * Note: Interrupts are disabled when called. -- cgit v1.2.3 From 4e318d7c6c9dd5cdae48bcf61558bbc0c09b12ac Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 13 Oct 2008 12:03:03 +0200 Subject: sysfs: Fix return values for sysdev_store_{ulong,int} SYSFS: Fix return values for sysdev_store_{ulong,int} Always return the full size instead of the consumed length of the string in sysdev_store_{ulong,int} This avoids EINVAL errors in some echo versions. Signed-off-by: Andi Kleen Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/base/sys.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/sys.c b/drivers/base/sys.c index 3ca9c5e8d765..c98c31ec2f75 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c @@ -488,7 +488,8 @@ ssize_t sysdev_store_ulong(struct sys_device *sysdev, if (end == buf) return -EINVAL; *(unsigned long *)(ea->var) = new; - return end - buf; + /* Always return full write size even if we didn't consume all */ + return size; } EXPORT_SYMBOL_GPL(sysdev_store_ulong); @@ -511,7 +512,8 @@ ssize_t sysdev_store_int(struct sys_device *sysdev, if (end == buf || new > INT_MAX || new < INT_MIN) return -EINVAL; *(int *)(ea->var) = new; - return end - buf; + /* Always return full write size even if we didn't consume all */ + return size; } EXPORT_SYMBOL_GPL(sysdev_store_int); -- cgit v1.2.3