[PATCH] change memoryX->phys_device from number to symlink [1/2] generic func

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch is from memory hotplug tree in lhms.
This patch changes memory_device's phys_device member from just a number
to symbolic link to the device. AFAIK, phys_device is not used now.

example)
$readlink /sys/devices/system/memory/memory10/phys_device
../../../../firmware/acpi/namespace/ACPI/_SB/LSB1/MEM3

This will help memory hotplug shell script.

-- Kame

struct memory_block is a struct for memory hotplug and creates sysfs
entry like this.
/sys/device/system/memory/memory10/
This struct has a member phys_device and this is just a number.
A user can read this member like this.
%cat /sys/devices/system/memory/memory10/state
0

AFAIK, there is no table to match this number and a real device.
And this is always 0 now.

This patch changes memory_block->phys_device from a number
to symbolic link to the device to which the memory block 
belongs to.
ex)
% readlink /sys/devices/system/memory/memory10/phys_device
../../../../firmware/acpi/namespace/ACPI/_SB/LSB1/MEM3

This is usefull for memory hotplug shell script and we don't
have to maintain a table phys_device_number <-> device.

A patch making acpi-memory-hotplug use this will follow this patch.

Signed-Off-By: KAMEZAWA Hiroyuki <[email protected]>

Index: testtree/drivers/base/memory.c
===================================================================
--- testtree.orig/drivers/base/memory.c	2006-02-17 15:07:56.000000000 +0900
+++ testtree/drivers/base/memory.c	2006-02-17 15:08:16.000000000 +0900
@@ -252,31 +252,30 @@
 	return count;
 }
 
-/*
- * phys_device is a bad name for this.  What I really want
- * is a way to differentiate between memory ranges that
- * are part of physical devices that constitute
- * a complete removable unit or fru.
- * i.e. do these ranges belong to the same physical device,
- * s.t. if I offline all of these sections I can then
- * remove the physical device?
- */
-static ssize_t show_phys_device(struct sys_device *dev, char *buf)
-{
-	struct memory_block *mem =
-		container_of(dev, struct memory_block, sysdev);
-	return sprintf(buf, "%d\n", mem->phys_device);
-}
 
 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);
 
 #define mem_create_simple_file(mem, attr_name)	\
 	sysdev_create_file(&mem->sysdev, &attr_##attr_name)
 #define mem_remove_simple_file(mem, attr_name)	\
 	sysdev_remove_file(&mem->sysdev, &attr_##attr_name)
 
+static int attach_phys_device(struct memory_block *mem, struct kobject *kobj)
+{
+	int ret;
+	ret = sysfs_create_link(&mem->sysdev.kobj, kobj, "phys_device");
+	if (ret)
+		return ret;
+	mem->phys_device = kobj;
+	return 0;
+}
+
+static void remove_phys_device(struct memory_block *mem)
+{
+	sysfs_remove_link(&mem->sysdev.kobj, "phys_device");
+	mem->phys_device = NULL;
+}
 /*
  * Block size attribute stuff
  */
@@ -330,13 +329,14 @@
 #endif
 
 /*
- * Note that phys_device is optional.  It is here to allow for
- * differentiation between which *physical* devices each
+ * kobj is a kobject of physical memory device which includes the specified range
+ * It is here to allow for differentiation between which *physical* devices each
  * section belongs to...
+ * If kobj != NULL, symbolic link to device from mem_section is created.
  */
 
 static int add_memory_block(unsigned long node_id, struct mem_section *section,
-		     unsigned long state, int phys_device)
+		     unsigned long state, struct kobject *kobj)
 {
 	struct memory_block *mem = kzalloc(sizeof(*mem), GFP_KERNEL);
 	int ret = 0;
@@ -346,16 +346,16 @@
 
 	mem->phys_index = __section_nr(section);
 	mem->state = state;
+	mem->phys_device = 0;
 	init_MUTEX(&mem->state_sem);
-	mem->phys_device = phys_device;
 
 	ret = register_memory(mem, section, NULL);
 	if (!ret)
 		ret = mem_create_simple_file(mem, phys_index);
 	if (!ret)
 		ret = mem_create_simple_file(mem, state);
-	if (!ret)
-		ret = mem_create_simple_file(mem, phys_device);
+	if (!ret && kobj)
+		ret = attach_phys_device(mem, kobj);
 
 	return ret;
 }
@@ -391,27 +391,58 @@
 	return mem;
 }
 
-int remove_memory_block(unsigned long node_id, struct mem_section *section,
-		int phys_device)
+static struct memory_block *pfn_to_memory_block(unsigned long pfn)
+{
+	struct mem_section *section;
+	section = __nr_to_section(pfn_to_section_nr(pfn));
+	return find_memory_block(section);
+}
+
+
+int remove_memory_block(unsigned long node_id, struct mem_section *section)
 {
 	struct memory_block *mem;
 
 	mem = find_memory_block(section);
 	mem_remove_simple_file(mem, phys_index);
 	mem_remove_simple_file(mem, state);
-	mem_remove_simple_file(mem, phys_device);
+	if (mem->phys_device)
+		remove_phys_device(mem);
 	unregister_memory(mem, section, NULL);
 
 	return 0;
 }
 
 /*
+ * creating symbolic link from mem_section[] in specified address range
+ * to specified device. This device here is expected to be physical memory device.
+ * This symbolic link will be used to show relationship between mem_section and device.
+ */
+int attach_device_to_memsection(u64 start_addr, u64 end_addr, struct kobject *kobj)
+{
+	unsigned long pfn = start_addr >> PAGE_SHIFT;
+	unsigned long end_pfn = end_addr >> PAGE_SHIFT;
+	struct memory_block *mem;
+	int ret = 0;
+	for (; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
+		mem = pfn_to_memory_block(pfn);
+		if (mem) {
+			ret = attach_phys_device(mem, kobj);
+			if (ret)
+				break;
+		}
+	}
+	return ret;
+}
+
+
+/*
  * need an interface for the VM to add new memory regions,
  * but without onlining it.
  */
 int register_new_memory(struct mem_section *section)
 {
-	return add_memory_block(0, section, MEM_OFFLINE, 0);
+	return add_memory_block(0, section, MEM_OFFLINE, NULL);
 }
 
 int unregister_memory_section(struct mem_section *section)
@@ -419,7 +450,7 @@
 	if (!valid_section(section))
 		return -EINVAL;
 
-	return remove_memory_block(0, section, 0);
+	return remove_memory_block(0, section);
 }
 
 /*
Index: testtree/include/linux/memory.h
===================================================================
--- testtree.orig/include/linux/memory.h	2006-02-17 15:07:56.000000000 +0900
+++ testtree/include/linux/memory.h	2006-02-17 15:08:16.000000000 +0900
@@ -31,7 +31,9 @@
 	 * initialization.
 	 */
 	struct semaphore state_sem;
-	int phys_device;		/* to which fru does this belong? */
+
+	/* information related to hardware */
+	struct kobject *phys_device;	/* a device includes this memory. */
 	void *hw;			/* optional pointer to fw/hw data */
 	int (*phys_callback)(struct memory_block *);
 	struct sys_device sysdev;
@@ -73,7 +75,10 @@
 extern int register_new_memory(struct mem_section *);
 extern int unregister_memory_section(struct mem_section *);
 extern int memory_dev_init(void);
-extern int remove_memory_block(unsigned long, struct mem_section *, int);
+extern int remove_memory_block(unsigned long, struct mem_section *);
+/* creating symbolic link between memory device and memory section */
+extern int attach_device_to_memsection(u64 start_addr, u64 end_addr, struct kobject *kobj);
+
 
 #define CONFIG_MEM_BLOCK_SIZE	(PAGES_PER_SECTION<<PAGE_SHIFT)
 

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux