From 5c755e9fd813810680abd56ec09a5f90143e815b Mon Sep 17 00:00:00 2001 From: Badari Pulavarty Date: Wed, 23 Jul 2008 21:28:19 -0700 Subject: memory-hotplug: add sysfs removable attribute for hotplug memory remove Memory may be hot-removed on a per-memory-block basis, particularly on POWER where the SPARSEMEM section size often matches the memory-block size. A user-level agent must be able to identify which sections of memory are likely to be removable before attempting the potentially expensive operation. This patch adds a file called "removable" to the memory directory in sysfs to help such an agent. In this patch, a memory block is considered removable if; o It contains only MOVABLE pageblocks o It contains only pageblocks with free pages regardless of pageblock type On the other hand, a memory block starting with a PageReserved() page will never be considered removable. Without this patch, the user-agent is forced to choose a memory block to remove randomly. Sample output of the sysfs files: ./memory/memory0/removable: 0 ./memory/memory1/removable: 0 ./memory/memory2/removable: 0 ./memory/memory3/removable: 0 ./memory/memory4/removable: 0 ./memory/memory5/removable: 0 ./memory/memory6/removable: 0 ./memory/memory7/removable: 1 ./memory/memory8/removable: 0 ./memory/memory9/removable: 0 ./memory/memory10/removable: 0 ./memory/memory11/removable: 0 ./memory/memory12/removable: 0 ./memory/memory13/removable: 0 ./memory/memory14/removable: 0 ./memory/memory15/removable: 0 ./memory/memory16/removable: 0 ./memory/memory17/removable: 1 ./memory/memory18/removable: 1 ./memory/memory19/removable: 1 ./memory/memory20/removable: 1 ./memory/memory21/removable: 1 ./memory/memory22/removable: 1 Signed-off-by: Badari Pulavarty Signed-off-by: Mel Gorman Acked-by: KAMEZAWA Hiroyuki Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/base/memory.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers/base') diff --git a/drivers/base/memory.c b/drivers/base/memory.c index 4d4e0e7b6e92..855ed1a9f97b 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -100,6 +100,21 @@ static ssize_t show_mem_phys_index(struct sys_device *dev, return sprintf(buf, "%08lx\n", mem->phys_index); } +/* + * Show whether the section of memory is likely to be hot-removable + */ +static ssize_t show_mem_removable(struct sys_device *dev, char *buf) +{ + unsigned long start_pfn; + int ret; + struct memory_block *mem = + container_of(dev, struct memory_block, sysdev); + + start_pfn = section_nr_to_pfn(mem->phys_index); + ret = is_mem_section_removable(start_pfn, PAGES_PER_SECTION); + return sprintf(buf, "%d\n", ret); +} + /* * online, offline, going offline, etc. */ @@ -262,6 +277,7 @@ static ssize_t show_phys_device(struct sys_device *dev, static SYSDEV_ATTR(phys_index, 0444, show_mem_phys_index, NULL); static SYSDEV_ATTR(state, 0644, show_mem_state, store_mem_state); static SYSDEV_ATTR(phys_device, 0444, show_phys_device, NULL); +static SYSDEV_ATTR(removable, 0444, show_mem_removable, NULL); #define mem_create_simple_file(mem, attr_name) \ sysdev_create_file(&mem->sysdev, &attr_##attr_name) @@ -350,6 +366,8 @@ static int add_memory_block(unsigned long node_id, struct mem_section *section, ret = mem_create_simple_file(mem, state); if (!ret) ret = mem_create_simple_file(mem, phys_device); + if (!ret) + ret = mem_create_simple_file(mem, removable); return ret; } @@ -394,6 +412,7 @@ int remove_memory_block(unsigned long node_id, struct mem_section *section, mem_remove_simple_file(mem, phys_index); mem_remove_simple_file(mem, state); mem_remove_simple_file(mem, phys_device); + mem_remove_simple_file(mem, removable); unregister_memory(mem, section); return 0; -- cgit v1.2.3 From f37e66173e0cc09b4e5a89eb0294abbefc15f435 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Fri, 25 Jul 2008 01:48:23 -0700 Subject: firmware: use memory_read_from_buffer() Signed-off-by: Akinobu Mita Cc: Greg Kroah-Hartman Cc: Markus Rechberger Cc: Kay Sievers Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/base/firmware_class.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index b0be1d18fee2..c9c92b00fd55 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -184,7 +184,7 @@ firmware_data_read(struct kobject *kobj, struct bin_attribute *bin_attr, struct device *dev = to_dev(kobj); struct firmware_priv *fw_priv = dev_get_drvdata(dev); struct firmware *fw; - ssize_t ret_count = count; + ssize_t ret_count; mutex_lock(&fw_lock); fw = fw_priv->fw; @@ -192,14 +192,8 @@ firmware_data_read(struct kobject *kobj, struct bin_attribute *bin_attr, ret_count = -ENODEV; goto out; } - if (offset > fw->size) { - ret_count = 0; - goto out; - } - if (offset + ret_count > fw->size) - ret_count = fw->size - offset; - - memcpy(buffer, fw->data + offset, ret_count); + ret_count = memory_read_from_buffer(buffer, count, &offset, + fw->data, fw->size); out: mutex_unlock(&fw_lock); return ret_count; -- cgit v1.2.3 From 00412be1d7bdf451653c7dafeb09f4f83398d756 Mon Sep 17 00:00:00 2001 From: Rene Herman Date: Fri, 25 Jul 2008 19:44:45 -0700 Subject: isa: set 24-bit dma_mask for ISA devices dma_alloc_coherent() on x86 currently takes a passed in NULL device pointer to mean that it should allocate an ISA compatible (24-bit) buffer which is a bit of a hack. The ALSA ISA drivers are the main consumers of this but have a struct device in fact readily available. For the legacy drivers, this sets the device dma_mask in preparation for using the actual device with the DMA API so as to eventually not need the NULL hack in dma_alloc_coherent(). This does not fix a current bug -- 2.6.26-rc1 stumbled over the NULL hack in dma_alloc_coherent() but this has already been fixed in commit 4a367f3a9dbf2e7ffcee4702203479809236ee6e by Takashi Iwai. Signed-off-by: Rene Herman Cc: Bjorn Helgaas Acked-by: Takashi Iwai Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/base/isa.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/base') diff --git a/drivers/base/isa.c b/drivers/base/isa.c index d2222397a401..efd577574948 100644 --- a/drivers/base/isa.c +++ b/drivers/base/isa.c @@ -7,6 +7,7 @@ #include #include #include +#include #include static struct device isa_bus = { @@ -141,6 +142,9 @@ int isa_register_driver(struct isa_driver *isa_driver, unsigned int ndev) isa_dev->dev.release = isa_dev_release; isa_dev->id = id; + isa_dev->dev.coherent_dma_mask = DMA_24BIT_MASK; + isa_dev->dev.dma_mask = &isa_dev->dev.coherent_dma_mask; + error = device_register(&isa_dev->dev); if (error) { put_device(&isa_dev->dev); -- cgit v1.2.3 From f810a5cf28a818db96333cd23646f0227ec015b4 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Fri, 25 Jul 2008 19:45:39 -0700 Subject: Use WARN() in drivers/base/ Use WARN() instead of a printk+WARN_ON() pair; this way the message becomes part of the warning section for better reporting/collection. Signed-off-by: Arjan van de Ven Cc: Greg KH Cc: Kay Sievers Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/base/core.c | 6 ++---- drivers/base/memory.c | 3 +-- drivers/base/sys.c | 12 ++++-------- 3 files changed, 7 insertions(+), 14 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/core.c b/drivers/base/core.c index 7d5c63c81a59..068aa1c9538c 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -116,12 +116,10 @@ static void device_release(struct kobject *kobj) dev->type->release(dev); else if (dev->class && dev->class->dev_release) dev->class->dev_release(dev); - else { - printk(KERN_ERR "Device '%s' does not have a release() " + else + WARN(1, KERN_ERR "Device '%s' does not have a release() " "function, it is broken and must be fixed.\n", dev->bus_id); - WARN_ON(1); - } } static struct kobj_type device_ktype = { diff --git a/drivers/base/memory.c b/drivers/base/memory.c index 855ed1a9f97b..3ad49a00029f 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -204,9 +204,8 @@ memory_block_action(struct memory_block *mem, unsigned long action) } break; default: - printk(KERN_WARNING "%s(%p, %ld) unknown action: %ld\n", + WARN(1, KERN_WARNING "%s(%p, %ld) unknown action: %ld\n", __func__, mem, action, action); - WARN_ON(1); ret = -EINVAL; } diff --git a/drivers/base/sys.c b/drivers/base/sys.c index 40fc14f03540..75dd6e22faff 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c @@ -168,19 +168,16 @@ int sysdev_driver_register(struct sysdev_class *cls, struct sysdev_driver *drv) int err = 0; if (!cls) { - printk(KERN_WARNING "sysdev: invalid class passed to " + WARN(1, KERN_WARNING "sysdev: invalid class passed to " "sysdev_driver_register!\n"); - WARN_ON(1); return -EINVAL; } /* Check whether this driver has already been added to a class. */ - if (drv->entry.next && !list_empty(&drv->entry)) { - printk(KERN_WARNING "sysdev: class %s: driver (%p) has already" + if (drv->entry.next && !list_empty(&drv->entry)) + WARN(1, KERN_WARNING "sysdev: class %s: driver (%p) has already" " been registered to a class, something is wrong, but " "will forge on!\n", cls->name, drv); - WARN_ON(1); - } mutex_lock(&sysdev_drivers_lock); if (cls && kset_get(&cls->kset)) { @@ -194,8 +191,7 @@ int sysdev_driver_register(struct sysdev_class *cls, struct sysdev_driver *drv) } } else { err = -EINVAL; - printk(KERN_ERR "%s: invalid device class\n", __func__); - WARN_ON(1); + WARN(1, KERN_ERR "%s: invalid device class\n", __func__); } mutex_unlock(&sysdev_drivers_lock); return err; -- cgit v1.2.3