From 6e03a201bbe8137487f340d26aa662110e324b20 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 9 Apr 2009 22:04:07 -0700 Subject: firmware: speed up request_firmware(), v3 Rather than calling vmalloc() repeatedly to grow the firmware image as we receive data from userspace, just allocate and fill individual pages. Then vmap() the whole lot in one go when we're done. A quick test with a 337KiB iwlagn firmware shows the time taken for request_firmware() going from ~32ms to ~5ms after I apply this patch. [v2: define PAGE_KERNEL_RO as PAGE_KERNEL where necessary, use min_t()] [v3: kunmap() takes the struct page *, not the virtual address] Signed-off-by: David Woodhouse Tested-by: Sachin Sant --- drivers/base/firmware_class.c | 129 +++++++++++++++++++++++++++++++++--------- 1 file changed, 103 insertions(+), 26 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index d3a59c688fe..8a267c42762 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -17,7 +17,7 @@ #include #include #include - +#include #include #include "base.h" @@ -45,7 +45,10 @@ struct firmware_priv { struct bin_attribute attr_data; struct firmware *fw; unsigned long status; - int alloc_size; + struct page **pages; + int nr_pages; + int page_array_size; + const char *vdata; struct timer_list timeout; }; @@ -122,6 +125,10 @@ static ssize_t firmware_loading_show(struct device *dev, return sprintf(buf, "%d\n", loading); } +/* Some architectures don't have PAGE_KERNEL_RO */ +#ifndef PAGE_KERNEL_RO +#define PAGE_KERNEL_RO PAGE_KERNEL +#endif /** * firmware_loading_store - set value in the 'loading' control file * @dev: device pointer @@ -141,6 +148,7 @@ static ssize_t firmware_loading_store(struct device *dev, { struct firmware_priv *fw_priv = dev_get_drvdata(dev); int loading = simple_strtol(buf, NULL, 10); + int i; switch (loading) { case 1: @@ -151,13 +159,30 @@ static ssize_t firmware_loading_store(struct device *dev, } vfree(fw_priv->fw->data); fw_priv->fw->data = NULL; + for (i = 0; i < fw_priv->nr_pages; i++) + __free_page(fw_priv->pages[i]); + kfree(fw_priv->pages); + fw_priv->pages = NULL; + fw_priv->page_array_size = 0; + fw_priv->nr_pages = 0; fw_priv->fw->size = 0; - fw_priv->alloc_size = 0; set_bit(FW_STATUS_LOADING, &fw_priv->status); mutex_unlock(&fw_lock); break; case 0: if (test_bit(FW_STATUS_LOADING, &fw_priv->status)) { + vfree(fw_priv->fw->data); + fw_priv->fw->data = vmap(fw_priv->pages, + fw_priv->nr_pages, + 0, PAGE_KERNEL_RO); + if (!fw_priv->fw->data) { + dev_err(dev, "%s: vmap() failed\n", __func__); + goto err; + } + /* Pages will be freed by vfree() */ + fw_priv->pages = NULL; + fw_priv->page_array_size = 0; + fw_priv->nr_pages = 0; complete(&fw_priv->completion); clear_bit(FW_STATUS_LOADING, &fw_priv->status); break; @@ -167,6 +192,7 @@ static ssize_t firmware_loading_store(struct device *dev, dev_err(dev, "%s: unexpected value (%d)\n", __func__, loading); /* fallthrough */ case -1: + err: fw_load_abort(fw_priv); break; } @@ -191,8 +217,28 @@ firmware_data_read(struct kobject *kobj, struct bin_attribute *bin_attr, ret_count = -ENODEV; goto out; } - ret_count = memory_read_from_buffer(buffer, count, &offset, - fw->data, fw->size); + if (offset > fw->size) + return 0; + if (count > fw->size - offset) + count = fw->size - offset; + + ret_count = count; + + while (count) { + void *page_data; + int page_nr = offset >> PAGE_SHIFT; + int page_ofs = offset & (PAGE_SIZE-1); + int page_cnt = min_t(size_t, PAGE_SIZE - page_ofs, count); + + page_data = kmap(fw_priv->pages[page_nr]); + + memcpy(buffer, page_data + page_ofs, page_cnt); + + kunmap(fw_priv->pages[page_nr]); + buffer += page_cnt; + offset += page_cnt; + count -= page_cnt; + } out: mutex_unlock(&fw_lock); return ret_count; @@ -201,27 +247,39 @@ out: static int fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size) { - u8 *new_data; - int new_size = fw_priv->alloc_size; + int pages_needed = ALIGN(min_size, PAGE_SIZE) >> PAGE_SHIFT; + + /* If the array of pages is too small, grow it... */ + if (fw_priv->page_array_size < pages_needed) { + int new_array_size = max(pages_needed, + fw_priv->page_array_size * 2); + struct page **new_pages; + + new_pages = kmalloc(new_array_size * sizeof(void *), + GFP_KERNEL); + if (!new_pages) { + fw_load_abort(fw_priv); + return -ENOMEM; + } + memcpy(new_pages, fw_priv->pages, + fw_priv->page_array_size * sizeof(void *)); + memset(&new_pages[fw_priv->page_array_size], 0, sizeof(void *) * + (new_array_size - fw_priv->page_array_size)); + kfree(fw_priv->pages); + fw_priv->pages = new_pages; + fw_priv->page_array_size = new_array_size; + } - if (min_size <= fw_priv->alloc_size) - return 0; + while (fw_priv->nr_pages < pages_needed) { + fw_priv->pages[fw_priv->nr_pages] = + alloc_page(GFP_KERNEL | __GFP_HIGHMEM); - new_size = ALIGN(min_size, PAGE_SIZE); - new_data = vmalloc(new_size); - if (!new_data) { - printk(KERN_ERR "%s: unable to alloc buffer\n", __func__); - /* Make sure that we don't keep incomplete data */ - fw_load_abort(fw_priv); - return -ENOMEM; - } - fw_priv->alloc_size = new_size; - if (fw_priv->fw->data) { - memcpy(new_data, fw_priv->fw->data, fw_priv->fw->size); - vfree(fw_priv->fw->data); + if (!fw_priv->pages[fw_priv->nr_pages]) { + fw_load_abort(fw_priv); + return -ENOMEM; + } + fw_priv->nr_pages++; } - fw_priv->fw->data = new_data; - BUG_ON(min_size > fw_priv->alloc_size); return 0; } @@ -258,10 +316,25 @@ firmware_data_write(struct kobject *kobj, struct bin_attribute *bin_attr, if (retval) goto out; - memcpy((u8 *)fw->data + offset, buffer, count); - - fw->size = max_t(size_t, offset + count, fw->size); retval = count; + + while (count) { + void *page_data; + int page_nr = offset >> PAGE_SHIFT; + int page_ofs = offset & (PAGE_SIZE - 1); + int page_cnt = min_t(size_t, PAGE_SIZE - page_ofs, count); + + page_data = kmap(fw_priv->pages[page_nr]); + + memcpy(page_data + page_ofs, buffer, page_cnt); + + kunmap(fw_priv->pages[page_nr]); + buffer += page_cnt; + offset += page_cnt; + count -= page_cnt; + } + + fw->size = max_t(size_t, offset, fw->size); out: mutex_unlock(&fw_lock); return retval; @@ -277,7 +350,11 @@ static struct bin_attribute firmware_attr_data_tmpl = { static void fw_dev_release(struct device *dev) { struct firmware_priv *fw_priv = dev_get_drvdata(dev); + int i; + for (i = 0; i < fw_priv->nr_pages; i++) + __free_page(fw_priv->pages[i]); + kfree(fw_priv->pages); kfree(fw_priv); kfree(dev); -- cgit v1.2.3 From 0fa1b0a144ee3e57f63ae25a7c5402f57232853d Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Thu, 14 May 2009 23:15:22 +0200 Subject: trivial: fix grammo in bus_for_each_dev() kerneldoc Signed-off-by: Alex Chiang Acked-by: Randy Dunlap Signed-off-by: Jiri Kosina --- drivers/base/bus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/base') diff --git a/drivers/base/bus.c b/drivers/base/bus.c index c6599618523..4b04a15146d 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -279,7 +279,7 @@ static struct device *next_device(struct klist_iter *i) * * NOTE: The device that returns a non-zero value is not retained * in any way, nor is its refcount incremented. If the caller needs - * to retain this data, it should do, and increment the reference + * to retain this data, it should do so, and increment the reference * count in the supplied callback. */ int bus_for_each_dev(struct bus_type *bus, struct device *start, -- cgit v1.2.3 From 62b0124761b9c2e304ee07dcf4db46c4a3dfec11 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 18 Apr 2009 13:45:13 +0200 Subject: PM: Warn if interrupts are enabled during suspend-resume of sysdevs Sysdevs have to be suspended and resumed with interrupts disabled and things usually break in a way that's difficult to debug if one of sysdev drivers enables interrupts by mistake during suspend or resume. Add extra checks that will generate warnings in such cases. Signed-off-by: Rafael J. Wysocki --- drivers/base/sys.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers/base') diff --git a/drivers/base/sys.c b/drivers/base/sys.c index 3236b434b96..9742a78c9fe 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c @@ -343,11 +343,15 @@ static void __sysdev_resume(struct sys_device *dev) /* First, call the class-specific one */ if (cls->resume) cls->resume(dev); + WARN_ONCE(!irqs_disabled(), + "Interrupts enabled after %pF\n", cls->resume); /* Call auxillary drivers next. */ list_for_each_entry(drv, &cls->drivers, entry) { if (drv->resume) drv->resume(dev); + WARN_ONCE(!irqs_disabled(), + "Interrupts enabled after %pF\n", drv->resume); } } @@ -377,6 +381,9 @@ int sysdev_suspend(pm_message_t state) if (ret) return ret; + WARN_ONCE(!irqs_disabled(), + "Interrupts enabled while suspending system devices\n"); + pr_debug("Suspending System Devices\n"); list_for_each_entry_reverse(cls, &system_kset->list, kset.kobj.entry) { @@ -393,6 +400,9 @@ int sysdev_suspend(pm_message_t state) if (ret) goto aux_driver; } + WARN_ONCE(!irqs_disabled(), + "Interrupts enabled after %pF\n", + drv->suspend); } /* Now call the generic one */ @@ -400,6 +410,9 @@ int sysdev_suspend(pm_message_t state) ret = cls->suspend(sysdev, state); if (ret) goto cls_driver; + WARN_ONCE(!irqs_disabled(), + "Interrupts enabled after %pF\n", + cls->suspend); } } } @@ -452,6 +465,9 @@ int sysdev_resume(void) { struct sysdev_class *cls; + WARN_ONCE(!irqs_disabled(), + "Interrupts enabled while resuming system devices\n"); + pr_debug("Resuming System Devices\n"); list_for_each_entry(cls, &system_kset->list, kset.kobj.entry) { -- cgit v1.2.3 From e39a71ef80877f4e30d808af9acceec80f4d2f7c Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 15 May 2009 00:53:26 +0200 Subject: PM: Rename device_power_down/up() Rename the functions performing "_noirq" dev_pm_ops operations from device_power_down() and device_power_up() to device_suspend_noirq() and device_resume_noirq(). The new function names are chosen to show that the functions are responsible for calling the _noirq() versions to finalize the suspend/resume operation. The current function names do not perform power down/up anymore so the names may be misleading. Global function renames: - device_power_down() -> device_suspend_noirq() - device_power_up() -> device_resume_noirq() Static function renames: - suspend_device_noirq() -> __device_suspend_noirq() - resume_device_noirq() -> __device_resume_noirq() Signed-off-by: Magnus Damm Acked-by: Greg Kroah-Hartman Acked-by: Len Brown Signed-off-by: Rafael J. Wysocki --- drivers/base/power/main.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 3e4bc699bc0..c5a35bc9d63 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -315,13 +315,13 @@ static void pm_dev_err(struct device *dev, pm_message_t state, char *info, /*------------------------- Resume routines -------------------------*/ /** - * resume_device_noirq - Power on one device (early resume). + * __device_resume_noirq - Power on one device (early resume). * @dev: Device. * @state: PM transition of the system being carried out. * * Must be called with interrupts disabled. */ -static int resume_device_noirq(struct device *dev, pm_message_t state) +static int __device_resume_noirq(struct device *dev, pm_message_t state) { int error = 0; @@ -363,7 +363,7 @@ static void dpm_power_up(pm_message_t state) int error; dev->power.status = DPM_OFF; - error = resume_device_noirq(dev, state); + error = __device_resume_noirq(dev, state); if (error) pm_dev_err(dev, state, " early", error); } @@ -371,18 +371,18 @@ static void dpm_power_up(pm_message_t state) } /** - * device_power_up - Turn on all devices that need special attention. + * device_resume_noirq - Turn on all devices that need special attention. * @state: PM transition of the system being carried out. * * Call the "early" resume handlers and enable device drivers to receive * interrupts. */ -void device_power_up(pm_message_t state) +void device_resume_noirq(pm_message_t state) { dpm_power_up(state); resume_device_irqs(); } -EXPORT_SYMBOL_GPL(device_power_up); +EXPORT_SYMBOL_GPL(device_resume_noirq); /** * resume_device - Restore state for one device. @@ -577,13 +577,13 @@ static pm_message_t resume_event(pm_message_t sleep_state) } /** - * suspend_device_noirq - Shut down one device (late suspend). + * __device_suspend_noirq - Shut down one device (late suspend). * @dev: Device. * @state: PM transition of the system being carried out. * * This is called with interrupts off and only a single CPU running. */ -static int suspend_device_noirq(struct device *dev, pm_message_t state) +static int __device_suspend_noirq(struct device *dev, pm_message_t state) { int error = 0; @@ -602,7 +602,7 @@ static int suspend_device_noirq(struct device *dev, pm_message_t state) } /** - * device_power_down - Shut down special devices. + * device_suspend_noirq - Shut down special devices. * @state: PM transition of the system being carried out. * * Prevent device drivers from receiving interrupts and call the "late" @@ -610,7 +610,7 @@ static int suspend_device_noirq(struct device *dev, pm_message_t state) * * Must be called under dpm_list_mtx. */ -int device_power_down(pm_message_t state) +int device_suspend_noirq(pm_message_t state) { struct device *dev; int error = 0; @@ -618,7 +618,7 @@ int device_power_down(pm_message_t state) suspend_device_irqs(); mutex_lock(&dpm_list_mtx); list_for_each_entry_reverse(dev, &dpm_list, power.entry) { - error = suspend_device_noirq(dev, state); + error = __device_suspend_noirq(dev, state); if (error) { pm_dev_err(dev, state, " late", error); break; @@ -627,10 +627,10 @@ int device_power_down(pm_message_t state) } mutex_unlock(&dpm_list_mtx); if (error) - device_power_up(resume_event(state)); + device_resume_noirq(resume_event(state)); return error; } -EXPORT_SYMBOL_GPL(device_power_down); +EXPORT_SYMBOL_GPL(device_suspend_noirq); /** * suspend_device - Save state of one device. -- cgit v1.2.3 From d161630297a20802d01c55847bfcba85d2118a9f Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Sun, 24 May 2009 22:05:42 +0200 Subject: PM core: rename suspend and resume functions This patch (as1241) renames a bunch of functions in the PM core. Rather than go through a boring list of name changes, suffice it to say that in the end we have a bunch of pairs of functions: device_resume_noirq dpm_resume_noirq device_resume dpm_resume device_complete dpm_complete device_suspend_noirq dpm_suspend_noirq device_suspend dpm_suspend device_prepare dpm_prepare in which device_X does the X operation on a single device and dpm_X invokes device_X for all devices in the dpm_list. In addition, the old dpm_power_up and device_resume_noirq have been combined into a single function (dpm_resume_noirq). Lastly, dpm_suspend_start and dpm_resume_end are the renamed versions of the former top-level device_suspend and device_resume routines. Signed-off-by: Alan Stern Acked-by: Magnus Damm Signed-off-by: Rafael J. Wysocki --- drivers/base/power/main.c | 80 ++++++++++++++++++++--------------------------- 1 file changed, 34 insertions(+), 46 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index c5a35bc9d63..1f3d82260db 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -315,13 +315,13 @@ static void pm_dev_err(struct device *dev, pm_message_t state, char *info, /*------------------------- Resume routines -------------------------*/ /** - * __device_resume_noirq - Power on one device (early resume). + * device_resume_noirq - Power on one device (early resume). * @dev: Device. * @state: PM transition of the system being carried out. * * Must be called with interrupts disabled. */ -static int __device_resume_noirq(struct device *dev, pm_message_t state) +static int device_resume_noirq(struct device *dev, pm_message_t state) { int error = 0; @@ -344,16 +344,16 @@ static int __device_resume_noirq(struct device *dev, pm_message_t state) } /** - * dpm_power_up - Power on all regular (non-sysdev) devices. + * dpm_resume_noirq - Power on all regular (non-sysdev) devices. * @state: PM transition of the system being carried out. * - * Execute the appropriate "noirq resume" callback for all devices marked - * as DPM_OFF_IRQ. + * Call the "noirq" resume handlers for all devices marked as + * DPM_OFF_IRQ and enable device drivers to receive interrupts. * * Must be called under dpm_list_mtx. Device drivers should not receive * interrupts while it's being executed. */ -static void dpm_power_up(pm_message_t state) +void dpm_resume_noirq(pm_message_t state) { struct device *dev; @@ -363,33 +363,21 @@ static void dpm_power_up(pm_message_t state) int error; dev->power.status = DPM_OFF; - error = __device_resume_noirq(dev, state); + error = device_resume_noirq(dev, state); if (error) pm_dev_err(dev, state, " early", error); } mutex_unlock(&dpm_list_mtx); -} - -/** - * device_resume_noirq - Turn on all devices that need special attention. - * @state: PM transition of the system being carried out. - * - * Call the "early" resume handlers and enable device drivers to receive - * interrupts. - */ -void device_resume_noirq(pm_message_t state) -{ - dpm_power_up(state); resume_device_irqs(); } -EXPORT_SYMBOL_GPL(device_resume_noirq); +EXPORT_SYMBOL_GPL(dpm_resume_noirq); /** - * resume_device - Restore state for one device. + * device_resume - Restore state for one device. * @dev: Device. * @state: PM transition of the system being carried out. */ -static int resume_device(struct device *dev, pm_message_t state) +static int device_resume(struct device *dev, pm_message_t state) { int error = 0; @@ -462,7 +450,7 @@ static void dpm_resume(pm_message_t state) dev->power.status = DPM_RESUMING; mutex_unlock(&dpm_list_mtx); - error = resume_device(dev, state); + error = device_resume(dev, state); mutex_lock(&dpm_list_mtx); if (error) @@ -480,11 +468,11 @@ static void dpm_resume(pm_message_t state) } /** - * complete_device - Complete a PM transition for given device + * device_complete - Complete a PM transition for given device * @dev: Device. * @state: PM transition of the system being carried out. */ -static void complete_device(struct device *dev, pm_message_t state) +static void device_complete(struct device *dev, pm_message_t state) { down(&dev->sem); @@ -527,7 +515,7 @@ static void dpm_complete(pm_message_t state) dev->power.status = DPM_ON; mutex_unlock(&dpm_list_mtx); - complete_device(dev, state); + device_complete(dev, state); mutex_lock(&dpm_list_mtx); } @@ -540,19 +528,19 @@ static void dpm_complete(pm_message_t state) } /** - * device_resume - Restore state of each device in system. + * dpm_resume_end - Restore state of each device in system. * @state: PM transition of the system being carried out. * * Resume all the devices, unlock them all, and allow new * devices to be registered once again. */ -void device_resume(pm_message_t state) +void dpm_resume_end(pm_message_t state) { might_sleep(); dpm_resume(state); dpm_complete(state); } -EXPORT_SYMBOL_GPL(device_resume); +EXPORT_SYMBOL_GPL(dpm_resume_end); /*------------------------- Suspend routines -------------------------*/ @@ -577,13 +565,13 @@ static pm_message_t resume_event(pm_message_t sleep_state) } /** - * __device_suspend_noirq - Shut down one device (late suspend). + * device_suspend_noirq - Shut down one device (late suspend). * @dev: Device. * @state: PM transition of the system being carried out. * * This is called with interrupts off and only a single CPU running. */ -static int __device_suspend_noirq(struct device *dev, pm_message_t state) +static int device_suspend_noirq(struct device *dev, pm_message_t state) { int error = 0; @@ -602,15 +590,15 @@ static int __device_suspend_noirq(struct device *dev, pm_message_t state) } /** - * device_suspend_noirq - Shut down special devices. + * dpm_suspend_noirq - Power down all regular (non-sysdev) devices. * @state: PM transition of the system being carried out. * - * Prevent device drivers from receiving interrupts and call the "late" + * Prevent device drivers from receiving interrupts and call the "noirq" * suspend handlers. * * Must be called under dpm_list_mtx. */ -int device_suspend_noirq(pm_message_t state) +int dpm_suspend_noirq(pm_message_t state) { struct device *dev; int error = 0; @@ -618,7 +606,7 @@ int device_suspend_noirq(pm_message_t state) suspend_device_irqs(); mutex_lock(&dpm_list_mtx); list_for_each_entry_reverse(dev, &dpm_list, power.entry) { - error = __device_suspend_noirq(dev, state); + error = device_suspend_noirq(dev, state); if (error) { pm_dev_err(dev, state, " late", error); break; @@ -627,17 +615,17 @@ int device_suspend_noirq(pm_message_t state) } mutex_unlock(&dpm_list_mtx); if (error) - device_resume_noirq(resume_event(state)); + dpm_resume_noirq(resume_event(state)); return error; } -EXPORT_SYMBOL_GPL(device_suspend_noirq); +EXPORT_SYMBOL_GPL(dpm_suspend_noirq); /** - * suspend_device - Save state of one device. + * device_suspend - Save state of one device. * @dev: Device. * @state: PM transition of the system being carried out. */ -static int suspend_device(struct device *dev, pm_message_t state) +static int device_suspend(struct device *dev, pm_message_t state) { int error = 0; @@ -704,7 +692,7 @@ static int dpm_suspend(pm_message_t state) get_device(dev); mutex_unlock(&dpm_list_mtx); - error = suspend_device(dev, state); + error = device_suspend(dev, state); mutex_lock(&dpm_list_mtx); if (error) { @@ -723,11 +711,11 @@ static int dpm_suspend(pm_message_t state) } /** - * prepare_device - Execute the ->prepare() callback(s) for given device. + * device_prepare - Execute the ->prepare() callback(s) for given device. * @dev: Device. * @state: PM transition of the system being carried out. */ -static int prepare_device(struct device *dev, pm_message_t state) +static int device_prepare(struct device *dev, pm_message_t state) { int error = 0; @@ -781,7 +769,7 @@ static int dpm_prepare(pm_message_t state) dev->power.status = DPM_PREPARING; mutex_unlock(&dpm_list_mtx); - error = prepare_device(dev, state); + error = device_prepare(dev, state); mutex_lock(&dpm_list_mtx); if (error) { @@ -807,12 +795,12 @@ static int dpm_prepare(pm_message_t state) } /** - * device_suspend - Save state and stop all devices in system. + * dpm_suspend_start - Save state and stop all devices in system. * @state: PM transition of the system being carried out. * * Prepare and suspend all devices. */ -int device_suspend(pm_message_t state) +int dpm_suspend_start(pm_message_t state) { int error; @@ -822,7 +810,7 @@ int device_suspend(pm_message_t state) error = dpm_suspend(state); return error; } -EXPORT_SYMBOL_GPL(device_suspend); +EXPORT_SYMBOL_GPL(dpm_suspend_start); void __suspend_report_result(const char *function, void *fn, int ret) { -- cgit v1.2.3 From e240b58c79144708530138e05f17c6d0d8d744a8 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Sun, 24 May 2009 22:05:54 +0200 Subject: PM: Remove bus_type suspend_late()/resume_early() V2 Remove the ->suspend_late() and ->resume_early() callbacks from struct bus_type V2. These callbacks are legacy stuff at this point and since there seem to be no in-tree users we may as well remove them. New users should use dev_pm_ops. Signed-off-by: Magnus Damm Acked-by: Pavel Machek Acked-by: Greg Kroah-Hartman Signed-off-by: Rafael J. Wysocki --- drivers/base/power/main.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 1f3d82260db..68f9f3cecf7 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -334,9 +334,6 @@ static int device_resume_noirq(struct device *dev, pm_message_t state) if (dev->bus->pm) { pm_dev_dbg(dev, state, "EARLY "); error = pm_noirq_op(dev, dev->bus->pm, state); - } else if (dev->bus->resume_early) { - pm_dev_dbg(dev, state, "legacy EARLY "); - error = dev->bus->resume_early(dev); } End: TRACE_RESUME(error); @@ -581,10 +578,6 @@ static int device_suspend_noirq(struct device *dev, pm_message_t state) if (dev->bus->pm) { pm_dev_dbg(dev, state, "LATE "); error = pm_noirq_op(dev, dev->bus->pm, state); - } else if (dev->bus->suspend_late) { - pm_dev_dbg(dev, state, "legacy LATE "); - error = dev->bus->suspend_late(dev, state); - suspend_report_result(dev->bus->suspend_late, error); } return error; } -- cgit v1.2.3 From 00725787511e20dbd1fdc1fb233606120ae5c8cf Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 4 Jun 2009 22:13:25 +0200 Subject: PM: Remove device_type suspend()/resume() This patch removes the legacy callbacks ->suspend() and ->resume() from struct device_type. These callbacks seem unused, and new code should instead make use of struct dev_pm_ops. Signed-off-by: Magnus Damm Acked-by: Greg Kroah-Hartman Signed-off-by: Rafael J. Wysocki --- drivers/base/power/main.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 68f9f3cecf7..fae72545898 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -399,9 +399,6 @@ static int device_resume(struct device *dev, pm_message_t state) if (dev->type->pm) { pm_dev_dbg(dev, state, "type "); error = pm_op(dev, dev->type->pm, state); - } else if (dev->type->resume) { - pm_dev_dbg(dev, state, "legacy type "); - error = dev->type->resume(dev); } if (error) goto End; @@ -641,10 +638,6 @@ static int device_suspend(struct device *dev, pm_message_t state) if (dev->type->pm) { pm_dev_dbg(dev, state, "type "); error = pm_op(dev, dev->type->pm, state); - } else if (dev->type->suspend) { - pm_dev_dbg(dev, state, "legacy type "); - error = dev->type->suspend(dev, state); - suspend_report_result(dev->type->suspend, error); } if (error) goto End; -- cgit v1.2.3 From 783ea7d4eeefe895f2731fe73ac951e94418927b Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 4 Jun 2009 22:13:33 +0200 Subject: Driver Core: Rework platform suspend/resume, print warning This patch reworks the platform driver code for legacy suspend and resume to avoid installing callbacks in struct device_driver. A warning is also added telling users to update the platform driver to use dev_pm_ops. The functions platform_legacy_suspend()/resume() directly call suspend and resume callbacks in struct platform_driver instead of wrapping things in platform_drv_suspend()/resume(). Signed-off-by: Magnus Damm Acked-by: Greg Kroah-Hartman Signed-off-by: Rafael J. Wysocki --- drivers/base/platform.c | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 8b4708e0624..ead3f64c41d 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -469,22 +469,6 @@ static void platform_drv_shutdown(struct device *_dev) drv->shutdown(dev); } -static int platform_drv_suspend(struct device *_dev, pm_message_t state) -{ - struct platform_driver *drv = to_platform_driver(_dev->driver); - struct platform_device *dev = to_platform_device(_dev); - - return drv->suspend(dev, state); -} - -static int platform_drv_resume(struct device *_dev) -{ - struct platform_driver *drv = to_platform_driver(_dev->driver); - struct platform_device *dev = to_platform_device(_dev); - - return drv->resume(dev); -} - /** * platform_driver_register * @drv: platform driver structure @@ -498,10 +482,10 @@ int platform_driver_register(struct platform_driver *drv) drv->driver.remove = platform_drv_remove; if (drv->shutdown) drv->driver.shutdown = platform_drv_shutdown; - if (drv->suspend) - drv->driver.suspend = platform_drv_suspend; - if (drv->resume) - drv->driver.resume = platform_drv_resume; + if (drv->suspend || drv->resume) + pr_warning("Platform driver '%s' needs updating - please use " + "dev_pm_ops\n", drv->driver.name); + return driver_register(&drv->driver); } EXPORT_SYMBOL_GPL(platform_driver_register); @@ -633,10 +617,12 @@ static int platform_match(struct device *dev, struct device_driver *drv) static int platform_legacy_suspend(struct device *dev, pm_message_t mesg) { + struct platform_driver *pdrv = to_platform_driver(dev->driver); + struct platform_device *pdev = to_platform_device(dev); int ret = 0; - if (dev->driver && dev->driver->suspend) - ret = dev->driver->suspend(dev, mesg); + if (dev->driver && pdrv->suspend) + ret = pdrv->suspend(pdev, mesg); return ret; } @@ -667,10 +653,12 @@ static int platform_legacy_resume_early(struct device *dev) static int platform_legacy_resume(struct device *dev) { + struct platform_driver *pdrv = to_platform_driver(dev->driver); + struct platform_device *pdev = to_platform_device(dev); int ret = 0; - if (dev->driver && dev->driver->resume) - ret = dev->driver->resume(dev); + if (dev->driver && pdrv->resume) + ret = pdrv->resume(pdev); return ret; } -- cgit v1.2.3 From 6acf70f078ca42a63397b8b84bf6383b01303009 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Thu, 23 Apr 2009 22:31:52 +0800 Subject: driver core: firmware_class: replace kfree(dev) with put_device(dev) against v2.6.30-rc3-next tree. Signed-off-by: Ming Lei Signed-off-by: Greg Kroah-Hartman --- drivers/base/firmware_class.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 8a267c42762..2d296b7f703 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -356,7 +356,7 @@ static void fw_dev_release(struct device *dev) __free_page(fw_priv->pages[i]); kfree(fw_priv->pages); kfree(fw_priv); - kfree(dev); + put_device(dev); module_put(THIS_MODULE); } @@ -400,14 +400,16 @@ static int fw_register_device(struct device **dev_p, const char *fw_name, retval = device_register(f_dev); if (retval) { dev_err(device, "%s: device_register failed\n", __func__); - goto error_kfree; + put_device(f_dev); + goto error_kfree1; } *dev_p = f_dev; return 0; error_kfree: - kfree(fw_priv); kfree(f_dev); +error_kfree1: + kfree(fw_priv); return retval; } -- cgit v1.2.3 From 309b7d60a345f402bec3cf9caadb53de4028e2aa Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Fri, 24 Apr 2009 14:57:00 +0200 Subject: driver core: add BUS_NOTIFY_UNBOUND_DRIVER event This patch adds a new bus notifier event which is emitted _after_ a device is removed from its driver. This event will be used by the dma-api debug code to check if a driver has released all dma allocations for that device. Signed-off-by: Joerg Roedel Signed-off-by: Greg Kroah-Hartman --- drivers/base/dd.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/base') diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 742cbe6b042..efd00de183b 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -320,6 +320,10 @@ static void __device_release_driver(struct device *dev) devres_release_all(dev); dev->driver = NULL; klist_remove(&dev->p->knode_driver); + if (dev->bus) + blocking_notifier_call_chain(&dev->bus->p->bus_notifier, + BUS_NOTIFY_UNBOUND_DRIVER, + dev); } } -- cgit v1.2.3 From c0afe7ba5e71d8ab66bc42f90b3e237581d3c509 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 27 Apr 2009 02:38:16 +0200 Subject: driver core: Const-correct platform getbyname functions This converts resource and IRQ getbyname functions for the platform bus to use const char *, I ran into compiler moanings when I tried using a const char * for looking up a certain resource. Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/platform.c b/drivers/base/platform.c index ead3f64c41d..59df6290951 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -69,7 +69,8 @@ EXPORT_SYMBOL_GPL(platform_get_irq); * @name: resource name */ struct resource *platform_get_resource_byname(struct platform_device *dev, - unsigned int type, char *name) + unsigned int type, + const char *name) { int i; @@ -88,7 +89,7 @@ EXPORT_SYMBOL_GPL(platform_get_resource_byname); * @dev: platform device * @name: IRQ name */ -int platform_get_irq_byname(struct platform_device *dev, char *name) +int platform_get_irq_byname(struct platform_device *dev, const char *name) { struct resource *r = platform_get_resource_byname(dev, IORESOURCE_IRQ, name); -- cgit v1.2.3 From 59a3cd7f9da60ac4ba8ae5a4cddc48fe4a450129 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 5 May 2009 20:38:28 -0700 Subject: Driver core: fix comment for device_attach() We are looking for matching drivers, not devices. Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/base/dd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/base') diff --git a/drivers/base/dd.c b/drivers/base/dd.c index efd00de183b..f0106875f01 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -226,7 +226,7 @@ static int __device_attach(struct device_driver *drv, void *data) * pair is found, break out and return. * * Returns 1 if the device was bound to a driver; - * 0 if no matching device was found; + * 0 if no matching driver was found; * -ENODEV if the device is not registered. * * When called for a USB interface, @dev->parent->sem must be held. -- cgit v1.2.3 From 9227c47bbdd87f276e08ed17877cc1649f5ed10a Mon Sep 17 00:00:00 2001 From: Dave Young Date: Mon, 11 May 2009 14:18:55 +0800 Subject: driver-core: make sysdev_class_register check kobject_set_name return value sysdev_class_register should check the kobject_set_name return value. Add the return value checking code. Signed-off-by: Dave Young Signed-off-by: Greg Kroah-Hartman --- drivers/base/sys.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/base') diff --git a/drivers/base/sys.c b/drivers/base/sys.c index 9742a78c9fe..162355cd745 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c @@ -131,6 +131,8 @@ static struct kset *system_kset; int sysdev_class_register(struct sysdev_class *cls) { + int retval; + pr_debug("Registering sysdev class '%s'\n", cls->name); INIT_LIST_HEAD(&cls->drivers); @@ -138,7 +140,11 @@ int sysdev_class_register(struct sysdev_class *cls) cls->kset.kobj.parent = &system_kset->kobj; cls->kset.kobj.ktype = &ktype_sysdev_class; cls->kset.kobj.kset = system_kset; - kobject_set_name(&cls->kset.kobj, cls->name); + + retval = kobject_set_name(&cls->kset.kobj, cls->name); + if (retval) + return retval; + return kset_register(&cls->kset); } -- cgit v1.2.3 From 401097ea4b89846d66ac78f7f108d49c2e922d9c Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Tue, 12 May 2009 13:37:57 -0700 Subject: driver core: synchronize device shutdown A patch series to make .shutdown execute asynchronously. Some drivers's shutdown can take a lot of time. The patches can help save some shutdown time. The patches use Arjan's async API. This patch: synchronize all tasks submitted by .shutdown Signed-off-by: Shaohua Li Cc: Arjan van de Ven Cc: Dmitry Torokhov Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/base') diff --git a/drivers/base/core.c b/drivers/base/core.c index 1977d4beb89..7e8576d7822 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "base.h" #include "power/power.h" @@ -1665,4 +1666,5 @@ void device_shutdown(void) kobject_put(sysfs_dev_char_kobj); kobject_put(sysfs_dev_block_kobj); kobject_put(dev_kobj); + async_synchronize_full(); } -- cgit v1.2.3 From 7fcab099795812a8a08eb3b8c8ddb35c3685045f Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Fri, 29 May 2009 11:33:19 +0800 Subject: driver core: fix documentation of request_firmware_nowait request_firmware_nowait declares it can be called in non-sleep contexts, but kthead_run called by request_firmware_nowait may sleep. So fix its documentation and comment to make callers clear about it. Signed-off-by: Ming Lei Signed-off-by: Greg Kroah-Hartman --- drivers/base/firmware_class.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 2d296b7f703..24277025058 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -617,8 +617,9 @@ request_firmware_work_func(void *arg) * @cont: function will be called asynchronously when the firmware * request is over. * - * Asynchronous variant of request_firmware() for contexts where - * it is not possible to sleep. + * Asynchronous variant of request_firmware() for user contexts where + * it is not possible to sleep for long time. It can't be called + * in atomic contexts. **/ int request_firmware_nowait( -- cgit v1.2.3 From 976821d756c53b421d7c58a9ed60125016d330aa Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Wed, 27 May 2009 00:49:31 +0200 Subject: firmware: allocate firmware id dynamically The firmware loader has a statically allocated 30 bytes long string for the firmware id (a.k.a. the firmware file name). There is no reason why we couldnt allocate it dynamically, and avoid having restrictions on the firmware names lengths. Signed-off-by: Samuel Ortiz Cc: Marcel Holtmann Cc: Zhu Yi , Cc: John Linville Signed-off-by: Greg Kroah-Hartman --- drivers/base/firmware_class.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 24277025058..3591ba7ff6f 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -40,7 +40,7 @@ static int loading_timeout = 60; /* In seconds */ static DEFINE_MUTEX(fw_lock); struct firmware_priv { - char fw_id[FIRMWARE_NAME_MAX]; + char *fw_id; struct completion completion; struct bin_attribute attr_data; struct firmware *fw; @@ -355,6 +355,7 @@ static void fw_dev_release(struct device *dev) for (i = 0; i < fw_priv->nr_pages; i++) __free_page(fw_priv->pages[i]); kfree(fw_priv->pages); + kfree(fw_priv->fw_id); kfree(fw_priv); put_device(dev); @@ -386,7 +387,13 @@ static int fw_register_device(struct device **dev_p, const char *fw_name, init_completion(&fw_priv->completion); fw_priv->attr_data = firmware_attr_data_tmpl; - strlcpy(fw_priv->fw_id, fw_name, FIRMWARE_NAME_MAX); + fw_priv->fw_id = kstrdup(fw_name, GFP_KERNEL); + if (!fw_priv->fw_id) { + dev_err(device, "%s: Firmware name allocation failed\n", + __func__); + retval = -ENOMEM; + goto error_kfree; + } fw_priv->timeout.function = firmware_class_timeout; fw_priv->timeout.data = (u_long) fw_priv; @@ -401,14 +408,15 @@ static int fw_register_device(struct device **dev_p, const char *fw_name, if (retval) { dev_err(device, "%s: device_register failed\n", __func__); put_device(f_dev); - goto error_kfree1; + goto error_kfree_fw_id; } *dev_p = f_dev; return 0; +error_kfree_fw_id: + kfree(fw_priv->fw_id); error_kfree: kfree(f_dev); -error_kfree1: kfree(fw_priv); return retval; } -- cgit v1.2.3 From acc0e90fbccbc6e4d48184cba0983ea044e131af Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 2 Jun 2009 15:39:55 -0700 Subject: driver core: fix gcc 4.3.3 warnings about string literals This removes the warning: format not a string literal and no format arguments warnings in the driver core that gcc 4.3.3 complains about. Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 4 ++-- drivers/base/firmware_class.c | 2 +- drivers/base/platform.c | 2 +- drivers/base/sys.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/core.c b/drivers/base/core.c index 7e8576d7822..4d59975c24a 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -875,7 +875,7 @@ int device_add(struct device *dev) * the name, and force the use of dev_name() */ if (dev->init_name) { - dev_set_name(dev, dev->init_name); + dev_set_name(dev, "%s", dev->init_name); dev->init_name = NULL; } @@ -1272,7 +1272,7 @@ struct device *__root_device_register(const char *name, struct module *owner) if (!root) return ERR_PTR(err); - err = dev_set_name(&root->dev, name); + err = dev_set_name(&root->dev, "%s", name); if (err) { kfree(root); return ERR_PTR(err); diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 3591ba7ff6f..ddeb819c8f8 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -399,7 +399,7 @@ static int fw_register_device(struct device **dev_p, const char *fw_name, fw_priv->timeout.data = (u_long) fw_priv; init_timer(&fw_priv->timeout); - dev_set_name(f_dev, dev_name(device)); + dev_set_name(f_dev, "%s", dev_name(device)); f_dev->parent = device; f_dev->class = &firmware_class; dev_set_drvdata(f_dev, fw_priv); diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 59df6290951..81cb01bfc35 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -245,7 +245,7 @@ int platform_device_add(struct platform_device *pdev) if (pdev->id != -1) dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id); else - dev_set_name(&pdev->dev, pdev->name); + dev_set_name(&pdev->dev, "%s", pdev->name); for (i = 0; i < pdev->num_resources; i++) { struct resource *p, *r = &pdev->resource[i]; diff --git a/drivers/base/sys.c b/drivers/base/sys.c index 162355cd745..79a9ae5238a 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c @@ -141,7 +141,7 @@ int sysdev_class_register(struct sysdev_class *cls) cls->kset.kobj.ktype = &ktype_sysdev_class; cls->kset.kobj.kset = system_kset; - retval = kobject_set_name(&cls->kset.kobj, cls->name); + retval = kobject_set_name(&cls->kset.kobj, "%s", cls->name); if (retval) return retval; -- cgit v1.2.3 From 6fcf53acccf85b4b0d0260e66c692a341760f464 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Thu, 30 Apr 2009 15:23:42 +0200 Subject: Driver Core: add nodename callbacks This adds the nodename callback for struct class, struct device_type and struct device, to allow drivers to send userspace hints on the device name and subdirectory that should be used for it. Signed-off-by: Kay Sievers Signed-off-by: Jan Blunck Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) (limited to 'drivers/base') diff --git a/drivers/base/core.c b/drivers/base/core.c index 4d59975c24a..7ecb1938e59 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -162,10 +162,18 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, struct device *dev = to_dev(kobj); int retval = 0; - /* add the major/minor if present */ + /* add device node properties if present */ if (MAJOR(dev->devt)) { + const char *tmp; + const char *name; + add_uevent_var(env, "MAJOR=%u", MAJOR(dev->devt)); add_uevent_var(env, "MINOR=%u", MINOR(dev->devt)); + name = device_get_nodename(dev, &tmp); + if (name) { + add_uevent_var(env, "DEVNAME=%s", name); + kfree(tmp); + } } if (dev->type && dev->type->name) @@ -1128,6 +1136,47 @@ static struct device *next_device(struct klist_iter *i) return dev; } +/** + * device_get_nodename - path of device node file + * @dev: device + * @tmp: possibly allocated string + * + * Return the relative path of a possible device node. + * Non-default names may need to allocate a memory to compose + * a name. This memory is returned in tmp and needs to be + * freed by the caller. + */ +const char *device_get_nodename(struct device *dev, const char **tmp) +{ + char *s; + + *tmp = NULL; + + /* the device type may provide a specific name */ + if (dev->type && dev->type->nodename) + *tmp = dev->type->nodename(dev); + if (*tmp) + return *tmp; + + /* the class may provide a specific name */ + if (dev->class && dev->class->nodename) + *tmp = dev->class->nodename(dev); + if (*tmp) + return *tmp; + + /* return name without allocation, tmp == NULL */ + if (strchr(dev_name(dev), '!') == NULL) + return dev_name(dev); + + /* replace '!' in the name with '/' */ + *tmp = kstrdup(dev_name(dev), GFP_KERNEL); + if (!*tmp) + return NULL; + while ((s = strchr(*tmp, '!'))) + s[0] = '/'; + return *tmp; +} + /** * device_for_each_child - device child iterator. * @parent: parent struct device. -- cgit v1.2.3 From 6837765963f1723e80ca97b1fae660f3a60d77df Mon Sep 17 00:00:00 2001 From: KOSAKI Motohiro Date: Tue, 16 Jun 2009 15:32:51 -0700 Subject: mm: remove CONFIG_UNEVICTABLE_LRU config option Currently, nobody wants to turn UNEVICTABLE_LRU off. Thus this configurability is unnecessary. Signed-off-by: KOSAKI Motohiro Cc: Johannes Weiner Cc: Andi Kleen Acked-by: Minchan Kim Cc: David Woodhouse Cc: Matt Mackall Cc: Rik van Riel Cc: Lee Schermerhorn Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/base/node.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/node.c b/drivers/base/node.c index 40b809742a1..91d4087b403 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -72,10 +72,8 @@ 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 Unevictable: %8lu kB\n" "Node %d Mlocked: %8lu kB\n" -#endif #ifdef CONFIG_HIGHMEM "Node %d HighTotal: %8lu kB\n" "Node %d HighFree: %8lu kB\n" @@ -105,10 +103,8 @@ 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)), nid, K(node_page_state(nid, NR_MLOCK)), -#endif #ifdef CONFIG_HIGHMEM nid, K(i.totalhigh), nid, K(i.freehigh), -- cgit v1.2.3